使用fscanf逐行遍历FILE

时间:2013-11-20 22:23:19

标签: c file printf traversal scanf

好的,我有一个文本文件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函数。

4 个答案:

答案 0 :(得分:7)

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

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

测试v1:

代码

#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);
}

结果

> 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 <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);
}

结果

看起来很有效!

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

的test.txt

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

12343456567856789
zbasdflkjasdfkjklsdafjklas
zxcvjkleryjkldhfg
1234567890123456789012341234
12345678901234567890123123asdfjklzxcv;jkl;eqwrtjklkzlcxvjkleqrt41234

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

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

来自cplusplus.com fgets

  

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

示例:

/* 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);
}

答案 1 :(得分:2)

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

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

答案 2 :(得分:1)

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

答案 3 :(得分:0)

你应该在说明符&#34;%[^ \ n]&#34;之后放空格。或使用&#34;%[^ \ n] \ n&#34;。两者都允许您跳过换行符。

{'c': 3, 'v': 2}

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