将csv文件读取到C中的结构

时间:2018-01-27 21:20:20

标签: c string csv struct

csv文件都具有以下格式:

Number of Spaces,10,,,,,,,,
,,,,,,,,,
,,,,,,,,,
Type,Set Id,Intraset Id,Name,Property Cost,House Cost,Hotel Cost,Rent,Rent with House,Rent With Hotel
Go,400,MU,,,,,,,
Property,0,0,0A,500,50,50,5,50,2000
Property,0,1,0B,1000,50,50,10,75,2500
Property,1,0,1A,2000,200,200,20,100,3000
Property,1,1,1B,2500,200,200,25,150,3000
Property,1,2,1C,3000,200,200,30,200,3500
Property,2,0,2A,4000,400,400,40,300,4000
Property,2,1,2B,4500,400,400,45,400,4000
Property,2,2,2C,5000,400,400,50,500,4000
Property,2,3,2D,5500,400,400,55,600,4500

第四行描述了它下面每行中的每个字段,即第5行,type是property,set id是0,name是0A等。我有一个包含所有变量的结构Space此信息。第5行是特殊的:它有Go类型,传递Go获得400美元,名称是MU,其他任何字段都不适用。 (这是Monopoly的一个版本)。

我在努力的方法是如何获得我需要的价值观。到目前为止,我只是设法获得空格数值(这决定了板上的行数):

void openSpecs(char *fileName) {
  FILE* file = fopen(fileName, "r");

  if (file == NULL) {
    printf("Could not open %s\n", fileName);
  }

  char c;

  do {
    fscanf(file, "%c", &c);
    //printf("%c", c);
  } while (!feof(file) && c != ',');


  //printf("\n\n");
  int numSpaces;
  fscanf(file, "%d", &numSpaces);
  //printf("there are %d spaces\n", numSpaces);
// note: the printf statements are there to help me see where I'm at in the file

  fclose(file);
}

我对如何处理文件的其余部分感到矛盾。我正在考虑使用while循环来跳过剩下的逗号,然后只是阅读第4行,因为我不需要保存其中任何一个。从那里,我不知道该怎么做。如果我使用strtok,我需要从文件中有一行作为C字符串,对吗?我无法静态分配C字符串,然后使用fscanf(不允许静态分配),那么如何为长度未知的字符串动态分配?

编辑:

char str[4096];
  fgets(str, 4096, file);
  printf("%s\n", str);

  int goCash = 0;
  char* name = NULL;

  char delim[2] = ",";
  char* token;
  token = strtok(str, delim); // this is Go


  token = strtok(str, delim);
  goCash = (int) token;


  token = strtok(str, delim);
  strcpy(name, token);


  printf("you get %d for going past %s\n", goCash, name);

1 个答案:

答案 0 :(得分:0)

小心,因为strtok可能会遇到问题。

例如,请考虑以下几行:

Property,0,0,0A,500,50,50,5,50,2000
Property,,0,0A,500,50,50,5,50,2000

请注意,在第二行中,缺少第二个字段,并且您有两个连续的分隔符:",,"strtok并未向您显示缺少字段的任何迹象,只是跳到下一个可用字段。

您可以通过将,,替换为, ,

来解决此问题

另一个问题是fgets包含行尾字符,您想删除它。

enum { Type, SetId, IntrasetId, Name, PropertyCost, HouseCost, HotelCost,
    Rent, RentwithHouse, RentWithHotel, total };

FILE *fp = fopen("test.txt", "r");
char buf[1000], temp[1000];
while(fgets(temp, sizeof(temp), fp))
{
    //remove end of line
    temp[strcspn(temp, "\r\n")] = 0;

    //replace ",," with ", ,"
    int j = 0;
    for(int i = 0, len = strlen(temp); i < len; i++) 
    {
        buf[j++] = temp[i];
        if (temp[i]==',' && temp[i+1]==',')
            buf[j++] = '0';
    }
    buf[j] = 0;

    //read all the fields
    char field[total][100];
    for(int i = 0; i < total; i++) *field[i] = 0;
    int i = 0;
    char *ptr = strtok(buf, ",");
    while(ptr)
    {
        strcpy(field[i++], ptr);
        ptr = strtok(NULL, ",");
    }
    for(int i = 0; i < total; i++)
        printf("%s, ", field[i]);
    printf(" rent(%d)\n", atoi(field[RentWithHotel]));
}
fclose(fp);