ファイルのオープン、ファイルの読み取り、ファイルの書き込み、およびファイルのクローズにエラーが発生した場合の検出を防止する検証には、多くの問題があります。そこに行く前に、定数が必要な場合は#define
、enum
を使用して定数を定義します。
enum { NAMSZ = 15, MAXC = 512 };
(あなたのコード点在マジックナンバーを持っていないような方法は、注:scanf
フィールド幅修飾子は例外です - 彼らは、指定しなければならず、変数や定数のラベルを使用することはできません。
:)
typedef struct a {...
を宣言する必要はありません、あなただけの構造体のtypedef
を使用し、a
を使用しません0
typedef struct {
char name[NAMSZ];
char surname[NAMSZ];
int age;
} sid;
私はあなたにWhy is while (!feof (file)) always wrong?へのリンクを与えました。代わりに、各行を保持するのに十分なバッファを宣言し、各行をfgets
で読み込み、必要な値をsscanf
(または単にポインタとループ)を使用して行から解析します。
int binarycopy (char *s1, char *s2)
{
sid id = { .name = "" };
FILE *f, *g;
char buf[MAXC] = "";
f = fopen (s1, "r");
g = fopen (s2, "wb");
if (f == NULL || g == NULL) {
fprintf (stderr, "binarycopy: file open failed.\n");
exit (EXIT_FAILURE);
}
while (fgets (buf, MAXC, f)) {
if (sscanf (buf, "%14s %14s %d", id.name, id.surname, &id.age) == 3) {
if (fwrite (&id, sizeof id, 1, g) != 1) {
fprintf (stderr, "error: fwrite error.\n");
exit (EXIT_FAILURE);
}
}
else {
fprintf (stderr, "binarycopy error: invalid line format.\n");
exit (EXIT_FAILURE);
}
}
fclose (f);
if (fclose (g) == -1) {
fprintf (stderr, "error: on stream close.\n");
exit (EXIT_FAILURE);
}
return 1;
}
:あなたがに書き込まれたデータをシリアル化する必要がある一方で
(ノート。。fclose
の検証書き込み後ストリームエラーがそれ以外の場合は報告されていないことが発生することができ、常に書き込み後fclose
を検証)上記のバイナリファイル(例えば、各名前のstrlen
をチェックし、長さを書き、次に文字数を入力し、年齢を入力すると、struct-at-a-timeを書くことができますが、注:のデータファイルはアノトで動作することは保証されていませんパッディングの違いにより、アーキテクチャやコンパイラに影響を与えます。構造体を記述して同じコンパイラで読み戻すこともできますが、データのシリアライズは適切な方法です。
お読みになりたい場合は、逆の操作を行います。 fread
struct
相当のデータを入力し、テキストファイルにその行を書き込みます。 main()
で
int textcopy (char *s1, char *s2)
{
sid id;
FILE *f;
FILE *g;
f = fopen (s1, "rb");
g = fopen (s2, "w");
if (f == NULL || g == NULL) {
fprintf (stderr, "textcopy: file open failed.\n");
exit (EXIT_FAILURE);
}
while (fread (&id, sizeof id, 1, f) == 1)
fprintf (g, "%s %s %d\n", id.name, id.surname, id.age);
fclose (f);
if (fclose (g) == -1) {
fprintf (stderr, "error: on stream close.\n");
exit (EXIT_FAILURE);
}
return 1;
}
あなたのオプションを検証します。 -b
または-t
が表示されない場合は、エラーを処理してください。またstrcmp
を使用する必要はありません。argv[1]
(たとえばargv[1][1]
)の2番目の文字が'b'
または't'
であるかどうかを確認してください。
#include <stdio.h>
#include <stdlib.h>
enum { NAMSZ = 15, MAXC = 512 };
typedef struct {
char name[NAMSZ];
char surname[NAMSZ];
int age;
} sid;
int binarycopy (char *s1, char *s2)
{
sid id = { .name = "" };
FILE *f, *g;
char buf[MAXC] = "";
f = fopen (s1, "r");
g = fopen (s2, "wb");
if (f == NULL || g == NULL) {
fprintf (stderr, "binarycopy: file open failed.\n");
exit (EXIT_FAILURE);
}
while (fgets (buf, MAXC, f)) {
if (sscanf (buf, "%14s %14s %d", id.name, id.surname, &id.age) == 3) {
if (fwrite (&id, sizeof id, 1, g) != 1) {
fprintf (stderr, "error: fwrite error.\n");
exit (EXIT_FAILURE);
}
}
else {
fprintf (stderr, "binarycopy error: invalid line format.\n");
exit (EXIT_FAILURE);
}
}
fclose (f);
if (fclose (g) == -1) {
fprintf (stderr, "error: on stream close.\n");
exit (EXIT_FAILURE);
}
return 1;
}
int textcopy (char *s1, char *s2)
{
sid id;
FILE *f;
FILE *g;
f = fopen (s1, "rb");
g = fopen (s2, "w");
if (f == NULL || g == NULL) {
fprintf (stderr, "textcopy: file open failed.\n");
exit (EXIT_FAILURE);
}
while (fread (&id, sizeof id, 1, f) == 1)
fprintf (g, "%s %s %d\n", id.name, id.surname, id.age);
fclose (f);
if (fclose (g) == -1) {
fprintf (stderr, "error: on stream close.\n");
exit (EXIT_FAILURE);
}
return 1;
}
int main (int argc, char *argv[])
{
if (argc < 4) {
printf ("Not enough arguments");
return 1;
}
if (argv[1][1] == 'b')
binarycopy (argv[2], argv[3]);
else if (argv[1][1] == 't')
textcopy (argv[2], argv[3]);
else
fprintf (stderr, "error: unrecognized option.\n");
return 0;
}
例入力ファイル
$ cat dat/nameage.txt
John Smith 30
Mary Jane 35
Dan Kane 55
Annie Adams 40
使用例/出力
コピーバイナリへ:
int main (int argc, char *argv[])
{
if (argc < 4) {
printf ("Not enough arguments");
return 1;
}
if (argv[1][1] == 'b')
binarycopy (argv[2], argv[3]);
else if (argv[1][1] == 't')
textcopy (argv[2], argv[3]);
else
fprintf (stderr, "error: unrecognized option.\n");
return 0;
}
は完全にそれを置く、あなたのような何かを行うことができます:
$ ./bin/filecopytb -b dat/nameage.txt dat/nameagecpy.bin
コピーをテキストに:
$ ./bin/filecopytb -t dat/nameagecpy.bin dat/nameagecpy.txt
は比較:バイナリの
$ diff dat/nameage.txt dat/nameagecpy.txt
hexdumpに対して:テキストの
$ hexdump -Cv dat/nameagecpy.bin
00000000 4a 6f 68 6e 00 00 00 00 00 00 00 00 00 00 00 53 |John...........S|
00000010 6d 69 74 68 00 00 00 00 00 00 00 00 00 00 00 00 |mith............|
00000020 1e 00 00 00 4d 61 72 79 00 00 00 00 00 00 00 00 |....Mary........|
00000030 00 00 00 4a 61 6e 65 00 00 00 00 00 00 00 00 00 |...Jane.........|
00000040 00 00 00 00 23 00 00 00 44 61 6e 00 00 00 00 00 |....#...Dan.....|
00000050 00 00 00 00 00 00 00 4b 61 6e 65 00 00 00 00 00 |.......Kane.....|
00000060 00 00 00 00 00 00 00 00 37 00 00 00 41 6e 6e 69 |........7...Anni|
00000070 65 00 00 00 00 00 00 00 00 00 00 41 64 61 6d 73 |e..........Adams|
00000080 00 00 00 00 00 00 00 00 00 00 00 00 28 00 00 00 |............(...|
猫:
$ cat dat/nameagecpy.txt
John Smith 30
Mary Jane 35
Dan Kane 55
Annie Adams 40
ご質問がある場合は、私に連絡してください。
あなたの読み込みまたは書き込みの妥当性は確認されていません。 (f、 "%s%s%d"、名前、名字、年齢)== 3){...} 'while(!feof(f)){...よりもはるかに良いでしょう} [**] while(!feof(file))はいつも間違っているのですか?**](http://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong) '* /}の後にストリームエラーを処理する' '(fclose(g)== -1) 'を確認する必要があります。 –
' char surname {char}'を持つときに 'Binarycopy'で' char surnames [20];を宣言するのはなぜですか? [15]; '' struct a'の中で? –
それはタイプミスでした、私はあなたに編集していただきますありがとうございます –