C语言 使用 fscanf 逐行遍历 FILE
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20108334/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Traverse FILE line by line using fscanf
提问by Brandon Amir
Ok so i have a text file database.txt.
好的,所以我有一个文本文件 database.txt。
Each line is a user with the format below
每一行都是一个用户,格式如下
"John Smith"| 4| 80.00| "123 Lollipop Lane"| "New Jersey"| "08080"
When I try do the following:
当我尝试执行以下操作时:
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);
}
It runs fine for the first line, sending in the ENTIRE line to the create_Customer(char * buffer) function. For some reason I do not understand, after this first line it continually tries to send "John Smith" instead of moving on to the next line. I believe my format is incorrect but I can't figure out how to accomplish what I am trying to accomplish which is read this file line by line and pass each line into the create_Customer function.
它在第一行运行良好,将整个行发送到 create_Customer(char * buffer) 函数。出于某种原因,我不明白,在第一行之后,它不断尝试发送“John Smith”而不是移动到下一行。我相信我的格式不正确,但我无法弄清楚如何完成我想要完成的工作,即逐行读取此文件并将每一行传递给 create_Customer 函数。
回答by rkyser
I think you need a closing \nin your pattern. I saw the a bunch of scrolling text with the same first line with %[^\n], but with %[^\n]\nI saw the expected output.
我认为你需要\n在你的模式中结束。我看到一堆滚动文本与第一行相同%[^\n],但是%[^\n]\n我看到了预期的输出。
However, if the line in the file exceeds that of the buffer, you may run into a problem where your buffer doesn't have enough space. The results
但是,如果文件中的行超过缓冲区的行数,您可能会遇到缓冲区没有足够空间的问题。结果
Test v1:
测试 v1:
Code
代码
#include <stdio.h>
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);
}
Results
结果
> 12343456567856789
> zbasdflkjasdfkjklsdafjklas
> zxcvjkleryjkldhfg
> 1234567890123456789012341234
> 12345678901234567890123123asdfjklzxcv;jkl;eqwrtjklkzlcxvjkleqrt41234
*** stack smashing detected ***: ./fscanf terminated
Segmentation fault (core dumped)
Test v2:
测试 v2:
Let's fix the code so that we don't overrun our buffer. We do this by changing %[^\n]\nto %30[^\n]\n. This tells fscanf that it can only use upto the size of the buffer -- 30.
让我们修复代码,以免溢出缓冲区。我们通过更改%[^\n]\n为 来做到这一点%30[^\n]\n。这告诉 fscanf 它最多只能使用缓冲区的大小——30。
Code
代码
#include <stdio.h>
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);
}
Results
结果
It looks like it worked!
看起来它奏效了!
> 12343456567856789
> zbasdflkjasdfkjklsdafjklas
> zxcvjkleryjkldhfg
> 1234567890123456789012341234
> 12345678901234567890123123asdf
> jklzxcv;jkl;eqwrtjklkzlcxvjkle
> qrt41234
test.txt
测试.txt
This is what the test file looks like that I was using.
这就是我使用的测试文件的样子。
12343456567856789
zbasdflkjasdfkjklsdafjklas
zxcvjkleryjkldhfg
1234567890123456789012341234
12345678901234567890123123asdfjklzxcv;jkl;eqwrtjklkzlcxvjkleqrt41234
Any reason you are using fscanfand not fgets?
您使用fscanf而不是使用的任何原因fgets?
One thing to note if you use fgets, you may want to strip the \ncharacter because it will be included as part of the string.
如果您使用fgets,需要注意的一件事是,您可能想要删除该\n字符,因为它将作为字符串的一部分包含在内。
From cplusplus.comfgets:
来自cplusplus.comfgets:
Reads characters from stream and stores them as a C string into str until (num-1) characters have been read or either a newline or the end-of-file is reached, whichever happens first.
从流中读取字符并将它们作为 C 字符串存储到 str 中,直到读取 (num-1) 个字符或到达换行符或文件结尾,以先发生者为准。
Example:
例子:
/* fgets example */
#include <stdio.h>
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);
}
回答by Chris Dodd
The problem is that your fscanfwill never read the newline at the end of the first line. So when it is called the second time, it will fail (returning 0, not EOF) and read nothing, leaving bufferunchanged.
问题是你fscanf永远不会读到第一行末尾的换行符。所以当它第二次被调用时,它会失败(返回 0,而不是 EOF)并且不读取任何内容,保持buffer不变。
You could add a call to fscanf("%*[\n]");at the end of your while loop to skip the newline (and any blank lines that might occur). Or you could just use fgetsinstead, which also makes it easier to avoid the potential buffer overflow problem.
您可以fscanf("%*[\n]");在 while 循环的末尾添加一个调用以跳过换行符(以及可能出现的任何空行)。或者您可以直接使用fgets,这也可以更轻松地避免潜在的缓冲区溢出问题。
回答by Themis Beris
You have to use fgets, instead of fscanf!The fscanfreads until it meats \n (new line) character ,whereas you can use fgets to read all lines with the exact same code you used!
Hope that helped :)
您必须使用fgets,而不是fscanf!The fscanfreads 直到它变成 \n (new line) character ,而您可以使用 fgets 读取与您使用的代码完全相同的所有行!希望有所帮助:)
回答by Ali Eren ?elik
You should put a blank after specifier "%[^\n] " or use "%[^\n]\n". Both will allow you to skip the newline character.
您应该在说明符 "%[^\n] " 后放置一个空格或使用 "%[^\n]\n"。两者都允许您跳过换行符。
fscanf(database, "%[\n] ", buffer);
or
或者
fscanf(database, "%[\n]\n", buffer);

