[英]fgets() not working after fscanf()
我正在使用fscanf读取日期,然后使用fgets读取便笺。 但是,在第一次迭代之后,fscanf返回值-1。
我使用GDB逐步调试程序。 在首次使用fgets之前,它可以正常工作。 当我尝试打印出fgets在第一次迭代中读取的行时,它给了我这个:
(gdb) print line
$6 = "\rtest\r18/04/2010\rtest2\r03/05/2010\rtest3\r05/08/2009\rtest4\r\n\000\000\000\000q\352\261\a\370\366\377\267.N=\366\000\000\000\000\003\000\000\000\370xC\000\000\000\000\000\000\000\000\000\001\000\000\000\227\b\000\000\070\367\377\267H\364\377\267\362\202\004\bdoD\000\354\201\004\b\001\000\000\000\304oC\000p\363\377\277\260zC\000D\363\377\277\n!B\000\064\363\377\277\354\201\004\b(\363\377\277TzC\000\000\000\000\000\070\367\377\267\001\000\000\000\000\000\000\000\001\000\000\000\370xC\000\001\000\000\000\000\000\312\000\000\000\000\000\377\260\360\000\001\000\000\000\277\000\000\000\364\317\000\000\344\261\\\000\000\000\000\000p\363\377\277|\233\004\b\350\362\377\277 \204\004\b\005\000\000\000|\233\004\b\030\363\377\277"
看起来fgets读取剩余的条目,然后将它们全部存储在单个字符串中。
我不确定为什么要这样做。
这是主要代码:
int main(int argc, char* argv[]) {
FILE* file;
int numEntries, i = 0;
int index = atoi(argv[1]);
char line[SIZE];
JournalEntry *entry;
/*argument provided is the entry user wants to be displayed*/
if (argc > 2) {
perror("Error: Too many arguments provided");
}
file = fopen("journalentries.txt", "r");
if (file == NULL) {
perror("Error in opening file");
}
if (fscanf(file, "%d", &numEntries) != 1) {
perror("Unable to read number of entries");
}
entry = (JournalEntry*)malloc(numEntries * sizeof(JournalEntry));
if (entry == NULL) {
perror("Malloc failed");
}
for (i = 0; i < numEntries; i++) {
if (fscanf(file, "%d/%d/%d", &entry[i].day, &entry[i].month, &entry[i].year) != 3) {
perror("Unable to read date of entry");
}
if (fgets(line, sizeof(line), file) == NULL) {
perror("Unable to read text of entry");
}
}
printf("%d-%02d-%02d %s: ", entry[index].year, entry[index].month, entry[index].day, entry[index].text);
if(ferror(file)) {
perror("Error with file");
}
fclose(file);
free(entry);
return 0;
}
我必须读取的文件:第一行包含要读取的条目数
4
12/04/2010
test
18/04/2010
test2
03/05/2010
test3
05/08/2009
test4
头文件中的struct JournalEntry结构:
typedef struct {
int day;
int month;
int year;
char text[250];
} JournalEntry;
看起来fgets读取剩余的条目,然后将它们全部存储在单个字符串中。
是的, '\\r'
不是行终止符。 因此,当fscanf
在第一个无效字符处停止解析并将它们留在缓冲区中时, fgets
会读取它们直到行尾。 并且由于文件中没有有效的行终止符,所以直到文件结束。
您可能应该修复文件,使其具有有效的(Unix?)行尾,例如使用合适的文本编辑器即可。 但这是另一个问题,之前已经有人问过(如此处 ),具体取决于您的问题中未包含的细节。
此外,您需要仔细检查fscanf
返回值。 仅当返回值为-1时才使用perror
,否则错误消息将与该错误完全无关。 如果返回值>=0
但与所需值不同,则打印自定义错误消息“无效的输入语法”或其他内容(并可能使用fgets
从缓冲区中读取其余行)。
另外,为了可靠地混合scanf
和fgets
,我需要在fscanf
格式字符串中添加空格,以便它会读取行尾的所有空格(也包括下一行的开头和任何空行),因此请小心如果重要的话),就像这样:
int items_read = scanf("%d ", &intvalue);
如另一个答案所述,最好只读取带有fgets
行,然后逐行用sscanf
解析它们。
不要混合使用fscanf()
和fgets()
,因为前者可能会将内容留在流的缓冲区中。
对于面向行的格式,请使用fgets()
读取整行,然后使用例如sscanf()
解析已阅读的内容。
运行GDB时看到的字符串实际上以第一个空字符结尾:
"\rtest\r18/04/2010\rtest2\r03/05/2010\rtest3\r05/08/2009\rtest4\r\n\000"
之后的其他数据将被忽略(使用普通str函数时);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.