使用fscanf跳转到下一行()

时间:2015-03-03 22:26:15

标签: c file csv scanf

我有两个文件 .csv ,我需要阅读整个文件,但必须按字段提交。我的意思是, csv 文件是用逗号分隔数据的文件,所以我不能使用 fgets
我需要读取所有数据,但我不知道如何跳转到下一行。

这是我到目前为止所做的:

int main()
{
   FILE *arq_file;
   arq_file = fopen("file.csv", "r");

   if(arq_file == NULL){
      printf("Not possible to read the file.");
      exit(0);
   }

   while( !feof(arq_file) ){
   fscanf(arq_file, "%i %lf", &myStruct[i+1].Field1, &myStruct[i+1].Field2);  
   }

   fclose(arq_file);
   return 0;
}  

它将进入无限循环,因为它永远不会到达下一行 我怎么能到达我刚看到的那条线下面的线?

更新:文件01示例

1,Alan,123,
2,Alan Harper,321
3,Jose Rendeks,32132
4,Maria da graça,822282
5,Charlie Harper,9999999999  

文件02示例

1,320,123
2,444,321
3,250,123,321
3,3,250,373,451
2,126,621
1,120,320
2,453,1230
3,12345,0432,1830

2 个答案:

答案 0 :(得分:2)

我认为一个示例比提供提示更好,这是fgets() + strtok()的组合,还有其他功能可以用于示例strchr(),尽管这更容易因为我只是想指出你正确的方向,所以我就这样做了

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int
main(void)
{
    FILE  *file;
    char   buffer[256];
    char  *pointer;
    size_t line;

    file = fopen("data.dat", "r");
    if (file == NULL)
     {
        perror("fopen()");
        return -1;
     }

    line = 0;
    while ((pointer = fgets(buffer, sizeof(buffer), file)) != NULL)
     {
        size_t field;
        char  *token;

        field = 0;
        while ((token = strtok(pointer, ",")) != NULL)
         {
            printf("line %zu, field %zu -> %s\n", line, field, token);

            field  += 1;
            pointer = NULL;
         }
        line += 1;
     }
    return 0;
}

我认为代码的工作原理非常清楚,我希望你能理解。

答案 1 :(得分:2)

如果相同的代码必须同时处理两个数据文件,那么您就会将字段读入字符串,然后将字符串转换为数字。

从您的描述中不清楚您是否需要在行尾处做一些特殊操作 - 但由于只有一个数据行以逗号结尾,因此您必须允许将字段分隔为逗号或换行符。

坦率地说,你可能在使用getchar()或同等版本时做得很好;这很简单。

char buffer[4096];
char *bufend = buffer + sizeof(buffer) - 1;
char *curfld = buffer;
int c;

while ((c = getc(arq_file)) != EOF)
{
    if (curfld == bufend)
        …process overlong field…
    else if (c == ',' || c == '\n')
    {
        *curfld = '\0';
        process(buffer);
        curfld = buffer;
    }
    else
        *curfld++ = c;
}
if (c == EOF && curfld != buffer)
{
    *curfld = '\0';
    process(buffer);
}

但是,如果你想使用更高级别的函数,那么你确实想使用fgets()来读取行(除非你需要担心不正常的行结尾,例如DOS vs Unix vs old-style Mac (仅限CR)行结尾)。或者使用POSIX getline()读取任意长行。然后使用strtok_r()或等效的分割线。

char *buffer = 0;
size_t buflen = 0;

while (getline(&buffer, &buflen, arq_file) != -1)
{
     char *posn = buffer;
     char *epos;
     char *token;
     while ((token = strtok_r(posn, ",\n", &epos)) != 0)
     {
         process(token);
         posn = 0;
     }
     /* Do anything special for end of line */
}
free(buffer);

如果您认为必须使用scanf(),则需要使用以下内容:

char buffer[4096];
char c;

while (fscanf(arq_file, "%4095[^,\n]%c", buffer, &c) == 2)
    process(buffer);

%4095[^,\n]扫描集最多可读取4095个字符,既不是逗号也不是换行符buffer,然后读取下一个字符(因此必须是逗号或换行符 - 或者可以想象为EOF ,但这导致问题)进入c。如果文件中的最后一个字符既不是逗号也不是换行符,那么您将跳过最后一个字段。