Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用strtok读取csv文件_C_Csv_Strtok - Fatal编程技术网

使用strtok读取csv文件

使用strtok读取csv文件,c,csv,strtok,C,Csv,Strtok,我正在尝试使用C中的strtok读取csv文件,并将内容存储到struct Game的数组中。 我的代码如下所示: FILE *fp; int i = 0; if((fp=fopen("Games.csv","r"))==NULL) { printf("Can't open file.\n"); exit(1); } rewind(fp); char buff[1024]; fgets(buff,1024,fp); char*

我正在尝试使用C中的strtok读取csv文件,并将内容存储到struct Game的数组中。 我的代码如下所示:

  FILE *fp;
  int i = 0;
  if((fp=fopen("Games.csv","r"))==NULL)
    {
      printf("Can't open file.\n");
      exit(1);
    }
  rewind(fp);
  char buff[1024]; 
  fgets(buff,1024,fp);
  char* delimiter = ",";

  while(fgets(buff, 1024, (FILE*)fp)!=NULL && i<5){

    Game[i].ProductID= strtok(buff, ",");   


    Game[i].ProductName = strtok(NULL, delimiter);

        Game[i].Publisher = strtok(NULL, delimiter);

    Game[i].Genre = strtok(NULL, delimiter);

    Game[i].Taxable = atoi(strtok(NULL, delimiter));

    Game[i].price = strtok(NULL, delimiter);

    Game[i].Quantity  = atoi(strtok(NULL, delimiter));


       printf("%s\n", Game[i].ProductID);

    i++;
   }


    i = 0;
    for(i = 0; i<5; i++){
       printf("%s", Game[i].ProductID);
    }
前五行(while循环中)是正确的。但是,最后五行(while循环之外)是错误的,它将打印整行内容


我对此很困惑。当数组被更改时,以及如何在while循环后仍然打印正确答案。

首先,介绍一下strok()的工作原理。该函数将返回一个指向原始字符串中某个位置的指针,该字符串已被修改,使其看起来像只有一个标记(a)

例如,
“A,B,C”
的第一个
strtok
会将其转换为
“A\0B,C”
,并返回
A
字符的地址。在这一点上使用它会给你一个
“A”

类似地,第二次调用会将其转换为
“A\0B\0C”
,并返回
B
字符的地址

它向您提供指向原始字符串的指针这一事实在这里至关重要,因为原始字符串位于
buff

而且,每次从文件中读取一行内容时,实际上都会覆盖
buff
。因此,对于所有这五行,
Game[i].ProductID
将只是
buff
的第一个字符的地址。处理完第五行后,该行:

while (fgets(buff, 1024, fp) != NULL && i < 5)
记住,您应该在某个时候
释放这些内存分配

在极不可能的情况下,您的环境没有
strdup
(它是POSIX而不是ISO),请参阅


另外,作为旁白,大多数CSV实现都允许嵌入逗号,例如将它们括在引号中或转义它们(后者很少见,但我见过):

这两个字段都可能是三个字段,
name
diablo,pax
awesome

使用strtok
简化处理将不允许出现这种复杂性,但是,假设您的字段不包含嵌入的逗号,这可能是可以的。如果您的输入更复杂,您最好使用第三方CSV库(当然有合适的许可证)


(a) 对于我们当中的语言律师,ISO C标准、
C117.24.5.8 strtok函数、/3和/4
(我的粗体)中包含了这一点:

3/序列中的第一个调用在
s1
指向的字符串中搜索
s2
指向的当前分隔符字符串中不包含的第一个字符。如果未找到此类字符,则
s1
指向的字符串中没有标记,
strtok
函数返回空指针。如果找到这样一个字符,它是第一个标记的开始

4/然后,
strtok
函数从中搜索包含在当前分隔符字符串中的字符。如果未找到此类字符,则当前标记将扩展到由
s1
指向的字符串的末尾,随后对标记的搜索将返回空指针。如果找到这样一个字符,它将被一个空字符覆盖,从而终止当前令牌。strok函数保存指向以下字符的指针,下一次搜索令牌将从该字符开始


首先,介绍
strtok()
的工作原理。该函数将返回一个指向原始字符串中某个位置的指针,该字符串已被修改,使其看起来像只有一个标记(a)

例如,
“A,B,C”
的第一个
strtok
会将其转换为
“A\0B,C”
,并返回
A
字符的地址。在这一点上使用它会给你一个
“A”

类似地,第二次调用会将其转换为
“A\0B\0C”
,并返回
B
字符的地址

它向您提供指向原始字符串的指针这一事实在这里至关重要,因为原始字符串位于
buff

而且,每次从文件中读取一行内容时,实际上都会覆盖
buff
。因此,对于所有这五行,
Game[i].ProductID
将只是
buff
的第一个字符的地址。处理完第五行后,该行:

while (fgets(buff, 1024, fp) != NULL && i < 5)
记住,您应该在某个时候
释放这些内存分配

在极不可能的情况下,您的环境没有
strdup
(它是POSIX而不是ISO),请参阅


另外,作为旁白,大多数CSV实现都允许嵌入逗号,例如将它们括在引号中或转义它们(后者很少见,但我见过):

这两个字段都可能是三个字段,
name
diablo,pax
awesome

使用strtok
简化处理将不允许出现这种复杂性,但是,假设您的字段不包含嵌入的逗号,这可能是可以的。如果您的输入更复杂,您最好使用第三方CSV库(当然有合适的许可证)


(a) 对于我们当中的语言律师,ISO C标准、
C117.24.5.8 strtok函数、/3和/4
(我的粗体)中包含了这一点:

3/序列中的第一个调用在
s1
指向的字符串中搜索
s2
指向的当前分隔符字符串中不包含的第一个字符。如果未找到此类字符,则
s1
指向的字符串中没有标记,
strtok
函数返回空指针。如果找到这样一个字符,它是第一个标记的开始

4/然后,
strtok
函数从那里搜索包含的字符
name,"diablo, pax",awesome
name,diablo\, pax,awesome