使用fscanf逐行遍历FILE

好的,我有一个文本文件database.txt。

每行都是具有以下格式的用户

"John Smith"| 4| 80.00| "123 Lollipop Lane"| "New Jersey"| "08080" 

当我尝试执行以下操作时:

 database = fopen(fileName,"r"); while(fscanf(database,"%[^\n]", buffer) != EOF){ printf("ATTEMPT TO: Insert user %s\n\n", buffer); if (insert_Customer(clients, create_Customer(buffer)) < 0){ printf("\nERROR: Failed to insert and create customer %s\n", buffer); } else printf("\nSUCCESS: Inserted Customer %s\n\n", buffer); } 

它在第一行运行正常,将ENTIRE行发送到create_Customer(char * buffer)函数。 出于某种原因,我不明白,在第一行后,它不断尝试发送“John Smith”,而不是继续前进到下一行。 我相信我的格式不正确,但我无法弄清楚如何完成我想要完成的工作,这是逐行读取此文件并将每行传递到create_Customer函数。

我认为你需要在你的模式中关闭\n 。 我看到一堆滚动文本与%[^\n]相同的第一行,但是%[^\n]\n我看到了预期的输出。

但是,如果文件中的行超过缓冲区的行,则可能会遇到缓冲区空间不足的问题。 结果

测试v1:

 #include  int main(int argc, char * argv[]) { FILE * database; char buffer[30]; database = fopen("test.txt", "r"); if (NULL == database) { perror("opening database"); return (-1); } while (EOF != fscanf(database, "%[^\n]\n", buffer)) { printf("> %s\n", buffer); } fclose(database); return (0); } 

结果

 > 12343456567856789 > zbasdflkjasdfkjklsdafjklas > zxcvjkleryjkldhfg > 1234567890123456789012341234 > 12345678901234567890123123asdfjklzxcv;jkl;eqwrtjklkzlcxvjkleqrt41234 *** stack smashing detected ***: ./fscanf terminated Segmentation fault (core dumped) 

测试v2:

让我们修复代码,这样我们就不会超出缓冲区。 我们通过将%[^\n]\n更改为%30[^\n]\n 。 这告诉fscanf它只能使用最大缓冲区大小 – 30。

 #include  int main(int argc, char * argv[]) { FILE * database; char buffer[30]; database = fopen("test.txt", "r"); if (NULL == database) { perror("opening database"); return (-1); } while (EOF != fscanf(database, "%30[^\n]\n", buffer)) { printf("> %s\n", buffer); } fclose(database); return (0); } 

结果

它看起来像是有效的!

 > 12343456567856789 > zbasdflkjasdfkjklsdafjklas > zxcvjkleryjkldhfg > 1234567890123456789012341234 > 12345678901234567890123123asdf > jklzxcv;jkl;eqwrtjklkzlcxvjkle > qrt41234 

的test.txt

这就是我正在使用的测试文件的样子。

 12343456567856789 zbasdflkjasdfkjklsdafjklas zxcvjkleryjkldhfg 1234567890123456789012341234 12345678901234567890123123asdfjklzxcv;jkl;eqwrtjklkzlcxvjkleqrt41234 

你使用fscanf而不是fgets任何原因?

有一点需要注意,如果你使用fgets ,你可能想要fgets \n字符,因为它将作为字符串的一部分包含在内。

来自cplusplus.com fgets

从流中读取字符并将它们作为C字符串存储到str中,直到读取(num-1)个字符或者到达换行符或文件结尾,以先发生者为准。

例:

 /* fgets example */ #include  int main() { FILE * database; int res; char buffer [100]; database = fopen(fileName,"r"); if (NULL == database) { perror("opening database file"); return (-1); } /* while not end-of-file */ while (!feof(database)) { /* we expect buffer pointer back if all is well, get out if we don't get it */ if (buffer != fgets(buffer, 100, database)) break; /* strip /n */ int len = strlen(buffer); if (buffer[len - 1] == '\n') buffer[len - 1] = 0; printf("ATTEMPT TO: Insert user %s\n\n", buffer); if (insert_Customer(clients, create_Customer(buffer)) < 0) printf("\nERROR: Failed to insert and create customer %s\n", buffer); else printf("\nSUCCESS: Inserted Customer %s\n\n", buffer); } /* a little clean-up */ fclose(database); return (0); } 

问题是你的fscanf永远不会在第一行的末尾读取换行符。 因此,当它第二次被调用时,它将失败(返回0,而不是EOF)并且什么都不读,保持buffer不变。

您可以添加对fscanf("%*[\n]");的调用fscanf("%*[\n]"); 在while循环结束时跳过换行符(以及可能出现的任何空行)。 或者您可以只使用fgets ,这也可以更容易地避免潜在的缓冲区溢出问题。

你必须使用fgets而不是fscanffscanf会读取它直到它\ n(新行)字符,而你可以使用fgets读取所有使用完全相同代码的行! 希望有帮助:)

您应该在说明符“%[^ \ n]”之后放置一个空格或使用“%[^ \ n] \ n”。 两者都允许您跳过换行符。

 fscanf(database, "%[\n] ", buffer); 

要么

 fscanf(database, "%[\n]\n", buffer);