c - 使用 fscanf 逐行遍历 FILE

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

第一行运行良好,将整行发送到 create_Customer(char * buffer) 函数。出于某种原因我不明白,在第一行之后它不断尝试发送“John Smith”而不是继续下一行。我认为我的格式不正确,但我不知道如何完成我正在尝试完成的工作,即逐行读取此文件并将每一行传递给 create_Customer 函数。

最佳答案

我认为您的模式中需要一个结束符 \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

测试.txt

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

12343456567856789
zbasdflkjasdfkjklsdafjklas
zxcvjkleryjkldhfg
1234567890123456789012341234
12345678901234567890123123asdfjklzxcv;jkl;eqwrtjklkzlcxvjkleqrt41234

您使用 fscanf 而不是 fgets 的原因是什么?

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

来自 cplusplus.com fgets:

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.

示例:

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

关于c - 使用 fscanf 逐行遍历 FILE,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20108334/

相关文章:

c - 删除尾随空白

c - 从 execvp 将 stdout 写入文件

visual-studio-2008 - Visual Studio 2008 项目引用

java - 检查 Java 中所有文件句柄何时被释放

java - 如何将声音(WAV)写入文件

c - 数组反射基本任务

php - mt_srand() 和 srand() - 是否有必要将种子重置为随机数?

c++ - printf 数据类型说明符复杂问题

perl - 在sprintf中截断(不舍入)小数位?

C printf() 不返回值