使用fgets()和strtok()使用逗号分隔符读取文件

时间:2010-12-02 13:44:48

标签: c fgets strtok

我有一个文本文件,其中三个字段用逗号分隔。 我的文本文件的内容示例:12345,真正的编程新手,BS ME 要将文件加载到程序中,我使用下面的代码....我的问题是,有时代码工作,有时它不会(没有错误消息出现程序只关闭自己,不会继续)。我还观察到文本文件是空白的(没有写入任何内容)它会自动关闭并且不会继续。非常感谢您的帮助。谢谢!

int read(){
     FILE *stream = NULL;
     int ctr;
     char linebuffer[45];
     char delims[]=", ";
     char *number[3];
     char *token = NULL;
     stream = fopen("student.txt", "rt");
     if (stream == NULL) stream = fopen("student.txt", "wt");
     else {
          printf("\nReading the student list directory. Wait a moment please...");
          while(!feof(stream)){            
                ctr=0;
                fgets(linebuffer, 46, stream);
                token = strtok(linebuffer, delims);
                while(token != NULL){
                  number[ctr] = linebuffer;
                  token = strtok(NULL, delims); 
                  ctr++;
                }
          recordCtr++;                      
          }                     
     recordCtr--;
     }
     fclose(stream);
}    

3 个答案:

答案 0 :(得分:2)

一旦找到,就永远不会复制token。您无法复制linebuffer,因为当下一行被加载时,其中的数据将被覆盖。

这一行:

number[ctr] = linebuffer;

应该引用token来保存最近找到的令牌,但事实并非如此。它应该读起来像 1

strcpy(number[ctr], token);

但是你必须改变声明以确保空间:

char number[3][32];

显然,这会引入缓冲区溢出风险,如果有一个非常长的令牌则不适合。如何最好地处理这是一个练习。 :)

1 为什么临时矢量在用于存储两个数字时被称为“数字”,一个字符串(名称)超出我的范围。

答案 1 :(得分:1)

您的fgets()调用需要指定45作为大小,或者当fgets写入NULL终止符时,您会缓冲缓冲区。这会将“delims”字符串设置为空字符串。

即使函数声明声明它返回一个int,你也不会返回任何值。

我不知道你的“struct student”的定义是什么,但是在使用strcpy()时你可能会溢出缓冲区。你也减少了“recordCtr”。为什么?如果您无法打开文字,为什么要打开文件进行书写?为什么?如果失败,则在NULL指针上调用fclose。我怀疑这有多大帮助。

我刚注意到你没有初始化“数字”。如果第一行没有得到三个数字,那么从未初始化的指针开始strcpy()。它可能具有NULL值,因此程序将会出现段错误。

你也有一个大小为3的数组,但是如果你读的行有超过3个以逗号分隔的字段,你将会溢出数组。

也可能有很多其他错误。

很多程序员都不会费心去做所有好的编码实践,例如检查返回值,初始化变量等等。他们经常会得到像这样的代码。如果你想成为一名优秀的程序员,那就试着养成做所有这些事情的习惯,或者至少一直考虑你是否需要。

此代码中存在许多潜在错误。如果一行超过45个字符,会发生什么?您不会删除换行符。你没有将字符串转换为数字(虽然数字[1]似乎是一个字符串数据,所以为什么要将它存储在一个名为“数字”的数组?)或检查fgets实际返回任何数据或检查你有多少数据得到。

答案 2 :(得分:1)

让买家小心。

strtok 可能会有一些边缘情况需要担心。

“一,二,三”将产生3个代币。

“one ,, three”将产生2个令牌。