C从文件中读取:只读取行的第一个字符

时间:2016-05-08 19:13:26

标签: c

我必须从DIMES ASNodes.csv(http://netdimes.org/new/?q=node/65)文件中获取节点ID。 文件看起来像这样:

6067,UNKNOWN,2007-02-03 10:03:53.0,2007-01-02 02:54:13.0,12,6,0
29287,UNKNOWN,2007-02-03 21:11:07.0,2007-01-02 07:33:35.0,1,0,0
...

到目前为止,我想出了这段代码,但它不能正常工作。虽然它打印出我需要的所有数字,但它也打印出两次节点id,有时会在两者之间打印零。感谢您的任何想法

void loadNodes(const char* filename)
{
    FILE* nodes = fopen(filename, "r");

    unsigned int id = 0;
    char line[64];

    while (fgets(line, sizeof(line), nodes) != NULL) {
        sscanf(line, "%u%*[^\n]", &id);
        printf("id = %u\n", id);
    }
    fclose(nodes);
}

output

2 个答案:

答案 0 :(得分:1)

我认为麻烦的是你的行有63个字符加上换行符,这意味着fgets()读取但不包括换行符(并且你处理它并得到正确的数字),然后下一个fgets()读取在前一个输入上留下的换行符(并且你处理它 - 令人惊讶的是你得到零而不是重复前一个数字。)

这是您的代码转换为MCVE(How to create a Minimal, Complete, and Verifiable Example?main()程序,该程序从标准输入读取(这使我无需验证,打开和关闭文件):

#include <stdio.h>

int main(void)
{
    unsigned id = 0;
    char line[64];

    while (fgets(line, sizeof(line), stdin) != NULL)
    {
        printf("Line: [%s]\n", line);
        sscanf(line,"%u", &id);
        printf("id = %u\n", id);
    }

    return 0;
}

请注意刚读取的行的诊断打印。代码应该真正检查sscanf()的返回值。 (跳过尾随碎片没有任何优点,所以我从格式字符串中删除了它。)

给定数据文件(data):

6067,UNKNOWN,2007-02-03 10:03:53.0,2007-01-02 02:54:13.0,12,6,0
29287,UNKNOWN,2007-02-03 21:11:07.0,2007-01-02 07:33:35.0,1,0,0

我从so.37103830 < data获得的输出是:

Line: [6067,UNKNOWN,2007-02-03 10:03:53.0,2007-01-02 02:54:13.0,12,6,0]
id = 6067
Line: [
]
id = 6067
Line: [29287,UNKNOWN,2007-02-03 21:11:07.0,2007-01-02 07:33:35.0,1,0,0]
id = 29287
Line: [
]
id = 29287

避免问题

最简单的解决方法是使用更长的缓冲区长度;我通常使用4096,如果我不关心如果读取了很长的行会发生什么,但你可能会认为128或256就足够了。

否则,我使用POSIX getline(),它将读取任意长行(不会耗尽内存)。

如果线路长度较长,我会得到输出:

Line: [6067,UNKNOWN,2007-02-03 10:03:53.0,2007-01-02 02:54:13.0,12,6,0
]
id = 6067
Line: [29287,UNKNOWN,2007-02-03 21:11:07.0,2007-01-02 07:33:35.0,1,0,0
]
id = 29287

答案 1 :(得分:0)

假设您只需要文件中的第一列(因为您提到了节点ID),您可以使用:

unsigned int node_id;
char str[100];
while(scanf("%u,%[^\n]",&node_id, str) == 2) {
    printf("%u\n",node_id);
}

Demo