简体   繁体   English

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

[英]Reading the file with comma delimiter using fgets() and strtok()

I have a text file with three fields separated by comma. 我有一个文本文件,其中三个字段用逗号分隔。 Example of the content of my text file: 12345, true programming newbie, BS ME To load the file into the program, i used the below code.... my problem is that sometimes the code works and sometimes it doesn't (no error message appears the program just closes itself and doesn't continue). 我的文本文件的内容示例:12345,真正的编程新手,BS ME要将文件加载到程序中,我使用下面的代码....我的问题是,有时代码工作,有时它没有(不出现错误消息,程序只是自行关闭,不会继续)。 i also observed the text file is blank (nothing is written) it automatically closes itself and doesn't continue. 我还观察到文本文件是空白的(没有写入任何内容)它会自动关闭并且不会继续。 Your help would be highly appreciated. 非常感谢您的帮助。 Thanks! 谢谢!

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);
}    

You never copy the token once you've found it. 一旦找到token就永远不会复制token You can't copy linebuffer , as the data in there will be overwritten as the next line is loaded. 你不能复制linebuffer ,因为当下一行被加载时,那里的数据将被覆盖。

This line: 这一行:

number[ctr] = linebuffer;

should reference token to save the most recently found token, but it doesn't. 应该引用token来保存最近找到的令牌,但事实并非如此。 It should probably read something like 1 : 它可能应该读为1

strcpy(number[ctr], token);

but then you'd have to change the declaration to make sure there's space: 但是你必须改变声明以确保空间:

char number[3][32];

Obviously, this introduces a buffer overrun risk, if there's a very long token it won't fit. 显然,这会引入缓冲区溢出风险,如果有一个很长的令牌,它就不适合。 How to best handle that is left as an exercise. 如何最好地处理这是一个练习。 :) :)

1 Why the temporary vector is called "number" when it is used to store two numbers and one string (the name) is beyond me. 1当临时向量用于存储两个数字和一个字符串(名称)超出我时,为什么将临时向量称为“数字”。

Your fgets() call needs to specify 45 as the size or you oveflow the buffer when fgets writes the NULL terminator. 你的fgets()调用需要指定45作为大小,或者当fgets写入NULL终止符时你会缓冲缓冲区。 That will set the "delims" string to be an empty string. 这会将“delims”字符串设置为空字符串。

Also you are not returning any value even though the function declaration states it returns an int. 即使函数声明声明它返回一个int,你也不会返回任何值。

I don't know what the definition of your "struct student" is, but you may be overflowing buffers when using strcpy() . 我不知道你的“struct student”的定义是什么,但是在使用strcpy()时你可能会溢出缓冲区。 Also you decrement "recordCtr". 你也减少了“recordCtr”。 Why? 为什么? Why do you open the file for writing if you can't open it for writing? 如果您无法打开文字,为什么要打开文件进行书写? Why? 为什么? If that fails too, you call fclose on a NULL pointer. 如果失败,则在NULL指针上调用fclose。 I doubt that helps much. 我怀疑这有多大帮助。

I just noticed that you do not initialise "number". 我刚注意到你没有初始化“数字”。 If you don't get three numbers on the first line, you then strcpy() from an uninitialised pointer. 如果你没有在第一行得到三个数字,那么你从未初始化的指针strcpy() It probably has a NULL value so the program will segfault. 它可能具有NULL值,因此程序将是段错误的。

Also you have an array of size 3, but if the line you read has more than 3 comma separated fields you will overflow the array. 你也有一个大小为3的数组,但如果你读的行有超过3个逗号分隔的字段,你将溢出数组。

There are probably many other errors as well. 可能还有许多其他错误。

A lot of programmers just can't be bothered to do all the good coding practices like checking return values, initialising variables, and so on. 很多程序员都不会费心去做所有好的编码实践,例如检查返回值,初始化变量等等。 They often end up with code like this. 他们经常会得到像这样的代码。 If you want to be a really good programmer, try and get in the habit of doing all these things, or at least always thinking about whether you need to or not. 如果你想成为一名优秀的程序员,那就试着养成做所有这些事情的习惯,或者至少总是考虑你是否需要。

There are so many potential bugs in this code. 这段代码中有很多潜在的错误。 What happens if a line is more than 45 characters long? 如果一行超过45个字符,会发生什么? You don't strip newlines. 您不会删除换行符。 You don't convert the strings to numbers (although number[1] appears to be a string data so why store it in an array called "numbers"?) or check that fgets actually returned any data or check how many pieces of data you get. 你没有将字符串转换为数字(虽然数字[1]似乎是一个字符串数据,所以为什么要将它存储在一个名为“数字”的数组?)或检查fgets实际返回任何数据或检查你有多少数据得到。

Let the buyer beware. 让买家小心。

strtok may have some edge cases to worry about. strtok可能会有一些边缘情况需要担心。

"one,two,three" will yield 3 tokens. “一,二,三”将产生3个代币。

"one,,three" will yield 2 tokens. “一,三”将产生2个代币。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM