我有一个压缩的文本文件,有7行非常长的文本,其中包含JPEG编码文件的解码信息。
当我试图用我的C程序逐行读取解压文件时,我得到了正确的前3行和后3行,只是第4行没有像预期的那样作为字符串读取。
第四行的输出是一个很长的字符串,其中包含fscanf
和1
。
如果我用记事本或十六进制编辑器查看输入文件,一切看起来都很好。
如果我手动创建一个结构相同(但行较短)的文本文件,0
可以正常工作。
如果我用我的程序解压文件,或者手动解压,没有区别。
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;}
铬{42:110000;13:111000;…;0:0;}
0001110101011100111000111100011。。。
10001101110111000010100011100110。。。
1000111011011111011001011011011011011011。。。
如果我打印单独的字符串:
512x512个
Y{42:110000;13:111000;…;0:0;}
CB{42:110000;13:111000;…;0:0;}
111001111111000110001111111000。。。
0001110101011100111000111100011。。。
10001101110111000010100011100110。。。
1000111011011111011001011011011011011011。。。
最佳答案
程序不能正常运行的原因有很多:
使用自动存储(即堆栈上的存储)可能会分配过多的数据,从而导致不稳定的行为。
文件中的字符串可能包含嵌入的空格,导致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系统,那么可以使用
m
中的fscanf()
前缀为从文件中读取的单词分配空间。使用此功能可以实现更简单但不可移植的解决方案: 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;
}
...
附言:与德语不同,英语中名词的首字母不大写,但语言、人名和地名等例外情况除外。