fscanf 读取 7 行中的 1 行错误
fscanf reads one line out of 7 wrong
我有一个压缩文本文件,其中包含 7 行很长的文本,其中包含用于解码 JPEG 编码文件的信息。
当我尝试用我的 C 程序逐行读取解压缩的文件时,fscanf
,我正确地读取了前 3 行和后 3 行,只有第 4 行没有被读取为符合预期的字符串。
第4行的输出是一个很长的字符串,里面填满了1
和0
。
如果我用记事本或十六进制编辑器查看输入文件,一切看起来都很好。
如果我手动创建一个具有相同结构(但行较短)的文本文件,fscanf
工作正常。
使用我的程序解压缩文件或手动解压缩文件没有区别。
FILE *tmpdata;
char enc_path[256];
int arrsize;
// Building the absolute Path
sprintf(enc_path, "%s%stmp.txt", dest, src_name);
arrsize = unzip(); // gives back size of the file
// not the best way to create the output strings,
// but I don't know the size of the lines.
char masse[10];
char ytabelle[arrsize / 3];
char cbtabelle[arrsize / 3];
char crtabelle[arrsize / 2];
char ywerte[arrsize /3];
char cbwerte[arrsize / 3];
char crwerte[arrsize / 3];
if ((tmpdata = fopen(enc_path, "r")) == NULL) {
printf("Error: can´t read input file\n");
return EXIT_FAILURE;
}
fscanf(tmpdata, "%s %s %s %s %s %s %s", masse, ytabelle, cbtabelle, crtabelle, ywerte, cbwerte, crwerte);
输入文件如下所示:
512x512
Y{42:110000;13:111000;...;0:0;}
CB{42:110000;13:111000;...;0:0;}
CR{42:110000;13:111000;...;0:0;}
000111010010111001110000111100011...
100011011101110001101000011100110...
100011101110110111011001100111011...
如果我打印单独的字符串:
512x512
Y{42:110000;13:111000;...;0:0;}
CB{42:110000;13:111000;...;0:0;}
111001111111111000110000111111000...
000111010010111001110000111100011...
100011011101110001101000011100110...
100011101110110111011001100111011...
也许可以避免堆栈分配??
char masse[10];
char *ytabelle = malloc(arrsize/3); if (!ytabelle) exit(EXIT_FAILURE);
char *cbtabelle = malloc(arrsize/3); if (!cbtabelle) exit(EXIT_FAILURE);
char *crtabelle = malloc(arrsize/2); if (!crtabelle) exit(EXIT_FAILURE);
char *ywerte = malloc(arrsize/3); if (!ywerte) exit(EXIT_FAILURE);
char *cbwerte = malloc(arrsize/3); if (!cbwerte) exit(EXIT_FAILURE);
char *crwerte = malloc(arrsize/3); if (!crwerte) exit(EXIT_FAILURE);
/* use as before */
free(ytabelle);
free(cbtabelle);
free(crtabelle);
free(ywerte);
free(cbwerte);
free(crwerte);
您的程序无法正常运行的原因有多种:
您可能会为自动存储分配太多数据(又名在堆栈上),导致不稳定的行为。
文件中的字符串可能包含嵌入的 spaces,导致 fscanf()
读取单词而不是行。
您没有告诉 fscanf()
目标数组的大小。 fscanf()
可能会将数据存储到目标数组的末尾之外,溢出到下一个数组(这可以解释观察到的行为)或导致其他一些未定义的行为。
当目标数组不是简单常量时,传递目标数组的大小非常麻烦。我建议你使用 fgets()
而不是 fscanf()
来读取文件内容并将 malloc()
的数组分配到更大的大小以避免问题:
FILE *tmpdata;
char enc_path[256];
size_t arrsize;
// Building the absolute path
snprintf(enc_path, sizeof enc_path, "%s%stmp.txt", dest, src_name);
arrsize = unzip(); // gives back size of the file
// not the best way to create the output strings,
// but I don't know the size of the lines.
char masse[16];
size_t ytabelle_size = arrsize + 2;
size_t cbtabelle_size = arrsize + 2;
size_t crtabelle_size = arrsize + 2;
char *ytabelle = malloc(ytabelle_size);
char *cbtabelle = malloc(cbtabelle_size);
char *crtabelle = malloc(crtabelle_size);
size_t ywerte_size = arrsize + 2;
size_t cbwerte_size = arrsize + 2;
size_t crwerte_size = arrsize + 2;
char *ywerte = malloc(ywerte_size);
char *cbwerte = malloc(cbwerte_size);
char *crwerte = malloc(crwerte_size);
if (!ytabelle ||!cbtabelle ||!crtabelle ||!ywerte ||!cbwerte ||!crwerte) {
printf("Error: cannot allocate memory\n");
return EXIT_FAILURE;
}
if ((tmpdata = fopen(enc_path, "r")) == NULL) {
printf("Error: cannot open input file\n");
return EXIT_FAILURE;
}
if (!fgets(masse, sizeof masse, tmpdata)
|| !fgets(ytabelle, ytabelle_size, tmpdata)
|| !fgets(cbtabelle, cbtabelle_size, tmpdata)
|| !fgets(crtabelle, crtabelle_size, tmpdata)
|| !fgets(ywerte, ywerte_size, tmpdata)
|| !fgets(cbwerte, cbwerte_size, tmpdata)
|| !fgets(crwerte, crwerte_size, tmpdata)) {
printf("Error: cannot read input file\n");
return EXIT_FAILURE;
}
// file contents were read, arrays should have a trailing newline, which
// you should strip or handle in the decoding phase.
...
如果您使用的是 GNUlibc 或一些现代 Posix 系统,您可以在 fscanf()
中使用 m
前缀来为从中读取的单词分配 space文件。使用这个允许更简单但不可移植的解决方案:
FILE *tmpdata;
char enc_path[256];
size_t arrsize;
// Building the absolute path
snprintf(enc_path, sizeof enc_path, "%s%stmp.txt", dest, src_name);
arrsize = unzip(); // gives back size of the file
// not the best way to create the output strings,
// but I don't know the size of the lines.
char masse[16];
char *ytabelle = NULL;
char *cbtabelle = NULL;
char *crtabelle = NULL;
char *ywerte = NULL;
char *cbwerte = NULL;
char *crwerte = NULL;
if ((tmpdata = fopen(enc_path, "r")) == NULL) {
printf("Error: cannot open input file\n");
return EXIT_FAILURE;
}
if (fscanf(tmpdata, "%ms %ms %ms %ms %ms %ms %ms", &masse,
&ytabelle, &cbtabelle, &crtabelle,
&ywerte, &cbwerte, &crwerte) != 7) {
printf("Error: cannot read input file\n");
return EXIT_FAILURE;
}
...
PS: 与德语不同,英语名词首字母不大写,语言、人名、地名等例外
我有一个压缩文本文件,其中包含 7 行很长的文本,其中包含用于解码 JPEG 编码文件的信息。
当我尝试用我的 C 程序逐行读取解压缩的文件时,fscanf
,我正确地读取了前 3 行和后 3 行,只有第 4 行没有被读取为符合预期的字符串。
第4行的输出是一个很长的字符串,里面填满了1
和0
。
如果我用记事本或十六进制编辑器查看输入文件,一切看起来都很好。
如果我手动创建一个具有相同结构(但行较短)的文本文件,fscanf
工作正常。
使用我的程序解压缩文件或手动解压缩文件没有区别。
FILE *tmpdata;
char enc_path[256];
int arrsize;
// Building the absolute Path
sprintf(enc_path, "%s%stmp.txt", dest, src_name);
arrsize = unzip(); // gives back size of the file
// not the best way to create the output strings,
// but I don't know the size of the lines.
char masse[10];
char ytabelle[arrsize / 3];
char cbtabelle[arrsize / 3];
char crtabelle[arrsize / 2];
char ywerte[arrsize /3];
char cbwerte[arrsize / 3];
char crwerte[arrsize / 3];
if ((tmpdata = fopen(enc_path, "r")) == NULL) {
printf("Error: can´t read input file\n");
return EXIT_FAILURE;
}
fscanf(tmpdata, "%s %s %s %s %s %s %s", masse, ytabelle, cbtabelle, crtabelle, ywerte, cbwerte, crwerte);
输入文件如下所示:
512x512 Y{42:110000;13:111000;...;0:0;} CB{42:110000;13:111000;...;0:0;} CR{42:110000;13:111000;...;0:0;} 000111010010111001110000111100011... 100011011101110001101000011100110... 100011101110110111011001100111011...
如果我打印单独的字符串:
512x512 Y{42:110000;13:111000;...;0:0;} CB{42:110000;13:111000;...;0:0;} 111001111111111000110000111111000... 000111010010111001110000111100011... 100011011101110001101000011100110... 100011101110110111011001100111011...
也许可以避免堆栈分配??
char masse[10];
char *ytabelle = malloc(arrsize/3); if (!ytabelle) exit(EXIT_FAILURE);
char *cbtabelle = malloc(arrsize/3); if (!cbtabelle) exit(EXIT_FAILURE);
char *crtabelle = malloc(arrsize/2); if (!crtabelle) exit(EXIT_FAILURE);
char *ywerte = malloc(arrsize/3); if (!ywerte) exit(EXIT_FAILURE);
char *cbwerte = malloc(arrsize/3); if (!cbwerte) exit(EXIT_FAILURE);
char *crwerte = malloc(arrsize/3); if (!crwerte) exit(EXIT_FAILURE);
/* use as before */
free(ytabelle);
free(cbtabelle);
free(crtabelle);
free(ywerte);
free(cbwerte);
free(crwerte);
您的程序无法正常运行的原因有多种:
您可能会为自动存储分配太多数据(又名在堆栈上),导致不稳定的行为。
文件中的字符串可能包含嵌入的 spaces,导致
fscanf()
读取单词而不是行。您没有告诉
fscanf()
目标数组的大小。fscanf()
可能会将数据存储到目标数组的末尾之外,溢出到下一个数组(这可以解释观察到的行为)或导致其他一些未定义的行为。
当目标数组不是简单常量时,传递目标数组的大小非常麻烦。我建议你使用 fgets()
而不是 fscanf()
来读取文件内容并将 malloc()
的数组分配到更大的大小以避免问题:
FILE *tmpdata;
char enc_path[256];
size_t arrsize;
// Building the absolute path
snprintf(enc_path, sizeof enc_path, "%s%stmp.txt", dest, src_name);
arrsize = unzip(); // gives back size of the file
// not the best way to create the output strings,
// but I don't know the size of the lines.
char masse[16];
size_t ytabelle_size = arrsize + 2;
size_t cbtabelle_size = arrsize + 2;
size_t crtabelle_size = arrsize + 2;
char *ytabelle = malloc(ytabelle_size);
char *cbtabelle = malloc(cbtabelle_size);
char *crtabelle = malloc(crtabelle_size);
size_t ywerte_size = arrsize + 2;
size_t cbwerte_size = arrsize + 2;
size_t crwerte_size = arrsize + 2;
char *ywerte = malloc(ywerte_size);
char *cbwerte = malloc(cbwerte_size);
char *crwerte = malloc(crwerte_size);
if (!ytabelle ||!cbtabelle ||!crtabelle ||!ywerte ||!cbwerte ||!crwerte) {
printf("Error: cannot allocate memory\n");
return EXIT_FAILURE;
}
if ((tmpdata = fopen(enc_path, "r")) == NULL) {
printf("Error: cannot open input file\n");
return EXIT_FAILURE;
}
if (!fgets(masse, sizeof masse, tmpdata)
|| !fgets(ytabelle, ytabelle_size, tmpdata)
|| !fgets(cbtabelle, cbtabelle_size, tmpdata)
|| !fgets(crtabelle, crtabelle_size, tmpdata)
|| !fgets(ywerte, ywerte_size, tmpdata)
|| !fgets(cbwerte, cbwerte_size, tmpdata)
|| !fgets(crwerte, crwerte_size, tmpdata)) {
printf("Error: cannot read input file\n");
return EXIT_FAILURE;
}
// file contents were read, arrays should have a trailing newline, which
// you should strip or handle in the decoding phase.
...
如果您使用的是 GNUlibc 或一些现代 Posix 系统,您可以在 fscanf()
中使用 m
前缀来为从中读取的单词分配 space文件。使用这个允许更简单但不可移植的解决方案:
FILE *tmpdata;
char enc_path[256];
size_t arrsize;
// Building the absolute path
snprintf(enc_path, sizeof enc_path, "%s%stmp.txt", dest, src_name);
arrsize = unzip(); // gives back size of the file
// not the best way to create the output strings,
// but I don't know the size of the lines.
char masse[16];
char *ytabelle = NULL;
char *cbtabelle = NULL;
char *crtabelle = NULL;
char *ywerte = NULL;
char *cbwerte = NULL;
char *crwerte = NULL;
if ((tmpdata = fopen(enc_path, "r")) == NULL) {
printf("Error: cannot open input file\n");
return EXIT_FAILURE;
}
if (fscanf(tmpdata, "%ms %ms %ms %ms %ms %ms %ms", &masse,
&ytabelle, &cbtabelle, &crtabelle,
&ywerte, &cbwerte, &crwerte) != 7) {
printf("Error: cannot read input file\n");
return EXIT_FAILURE;
}
...
PS: 与德语不同,英语名词首字母不大写,语言、人名、地名等例外