C读取以逗号分隔的数字文件

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C读取以逗号分隔的数字文件相关的知识,希望对你有一定的参考价值。

我试图读取包含逗号操作的数字的文件,并将它们存储在没有逗号的数组中。

例如:processes.txt包含

0,1,3
1,0,5
2,9,8
3,10,6

一个名为数字的数组应如下所示:

0 1 3 1 0 5 2 9 8 3 10 6

我到目前为止的代码是:

FILE *fp1;
char c; //declaration of characters

fp1=fopen(argv[1],"r"); //opening the file



int list[300];


c=fgetc(fp1); //taking character from fp1 pointer or file
int i=0,number,num=0;

while(c!=EOF) //iterate until end of file
    if (isdigit(c)) //if it is digit
        sscanf(&c,"%d",&number); //changing character to number (c)
        num=(num*10)+number;

    
    else if (c==',' || c=='\n')  //if it is new line or ,then it will store the number in list
        list[i]=num;
        num=0;
        i++;

    

    c=fgetc(fp1);


但如果是两位数则会出现问题。有没有人有更好的解决方案?谢谢!

答案

对于逗号前没有空格的数据,您可以简单地使用:

while (fscanf(fp1, "%d,", &num) == 1 && i < 300)
    list[i++] = num;

如果有数字,这将在数字后面读取逗号,在没有数字时默默忽略。如果数据中的逗号之前可能有空格,请在格式字符串中的逗号前添加空格。对i的测试可以防止你在list数组的边界外写字。 ++运营商在这里独树一帜。

另一答案

首先,fgetc返回int,所以c需要是int

除此之外,我会采用略有不同的方法。我承认它有点过于复杂。但是,如果您有几种不同类型的字段需要不同的操作(如解析器),则此方法可能可用。针对您的具体问题,我推荐Johathan Leffler的回答。

int c=fgetc(f);

while(c!=EOF && i<300) 
    if(isdigit(c)) 
        fseek(f, -1, SEEK_CUR);
        if(fscanf(f, "%d", &list[i++]) != 1) 
            // Handle error
        
    
    c=fgetc(f);

在这里,我不关心逗号和换行符。除了数字作为分隔符之外,我还有其他任何东西。我做的基本上是这样的:

read next byte
if byte is digit:
     back one byte in the file
     read number, irregardless of length
else continue

增加的条件i<300是出于安全原因。如果你真的想要检查除逗号和换行之外的其他内容(我没有得到你发现那么重要的印象)你可以很容易地添加一个else if (c == ...来处理错误。

请注意,您应该始终检查sscanffscanfscanf等函数的返回值。实际上,您也应该为fseek执行此操作。在这种情况下它并不重要,因为这个代码不太可能因为这个原因而失败,所以为了便于阅读,我把它留了下来。但是在生产代码中你应该检查它。

另一答案

我的解决方案是首先读取整行,然后用逗号作为分隔符用strtok_r解析它。如果你想要可移植的代码,你应该使用strtok

readline的天真实现将是这样的:

static char *readline(FILE *file)

    char *line = malloc(sizeof(char));
    int index = 0;
    int c = fgetc(file);
    if (c == EOF) 
        free(line);
        return NULL;
    
    while (c != EOF && c != '\n') 
        line[index++] = c;
        char *l = realloc(line, (index + 1) * sizeof(char));
        if (l == NULL) 
            free(line);
            return NULL;
        
        line = l;
        c = fgetc(file);
    
    line[index] = '\0';
    return line;

然后你只需要用strtok_r解析整行,所以你会以这样的结尾:

int main(int argc, char **argv)

    FILE *file = fopen(argv[1], "re");
    int list[300];
    if (file == NULL) 
        return 1;
    
    char *line;
    int numc = 0;
    while((line = readline(file)) != NULL) 
        char *saveptr;
        // Get the first token
        char *tok = strtok_r(line, ",", &saveptr);
        // Now start parsing the whole line
        while (tok != NULL) 
            // Convert the token to a long if possible
            long num = strtol(tok, NULL, 0);
            if (errno != 0) 
                // Handle no value conversion
                // ...
                // ...
            
            list[numc++] = (int) num;
            // Get next token
            tok = strtok_r(NULL, ",", &saveptr);
        
        free(line);
    
    fclose(file);
    return 0;

要打印整个列表,只需使用for循环:

for (int i = 0; i < numc; i++) 
    printf("%d ", list[i]);

printf("\n");

以上是关于C读取以逗号分隔的数字文件的主要内容,如果未能解决你的问题,请参考以下文章

以逗号作为小数分隔符的数据框

Matlab 读取dat文件(包含几行多余文本,数据带有数字和字符串,且以逗号分隔)

当某些数字包含逗号作为千位分隔符时如何读取数据?

php fgetcsv() 行以逗号分隔符结尾

c++读取以逗号为分隔符的一串数字

Python - 从文本文件中读取逗号分隔值,然后将结果输出到文本文件[关闭]