使用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而不是fscanf
! fscanf
会读取它直到它\ n(新行)字符,而你可以使用fgets读取所有使用完全相同代码的行! 希望有帮助:)
您应该在说明符“%[^ \ n]”之后放置一个空格或使用“%[^ \ n] \ n”。 两者都允许您跳过换行符。
fscanf(database, "%[\n] ", buffer);
要么
fscanf(database, "%[\n]\n", buffer);