2

I am trying to read two numbers from a text file. I used strtok, and the delimiter is " ". The text file (named data.txt) file has only two numbers, the line is "3 5". But the program crashes... any help is appreciated.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
    
int main(){
    
    FILE *data;
    data = fopen("data.txt", "r");
    
    int m, n;
    char *line, *number;
    while(!feof(data))
    {
        fscanf(data, "%s", line);
        number = strtok(line, " ");     
        m = atoi(number);       
        number = strtok(NULL, " ");     
        n = atoi(number);
    }       
}
anastaciu
  • 23,467
  • 7
  • 28
  • 53
smiili
  • 53
  • 5
  • 3
    `line` is a pointer. What variable or memory space does it point to? – user253751 Apr 21 '21 at 16:59
  • See also https://stackoverflow.com/q/5431941/10622916. In general you should check all return values to be sure that no error occurred. – Bodo Apr 21 '21 at 17:01
  • 1
    `while(!feof(data))` before any read has an undefined behavior, check the value returned by *fscanf*. – bruno Apr 21 '21 at 17:08
  • If you're just going to `strtok`, you might as well use `"%d%d"` in the scanf. But if you are going to use `%s`, you must add a maximum field width which is one less than the size of the buffer. eg `char line[32]; ... scanf("%31s", line);`. Since you have allocated zero for the buffer, there's clearly an issue. – William Pursell Apr 21 '21 at 17:34
  • @bruno [while(!feof(data)) before any read has an undefined behavior](https://stackoverflow.com/questions/67200294/trying-to-read-a-two-numbers-from-a-text-file#comment118782200_67200294) is not supported by the C spec. `fopen()` --> "The error and end-of-file indicators for the stream are cleared." and `feof()` "function tests the end-of-file indicator for the stream pointed to by stream." It is well defined, even if it is not what OP should be doing. – chux - Reinstate Monica Apr 21 '21 at 17:37
  • smiili, For robust code, consider other issues: 1) What should happen if the line has 3 numbers? 2) What should happen if the value is outside the `int` range? – chux - Reinstate Monica Apr 21 '21 at 17:52
  • @bruno Nope, it's not UB. It's just bad. – klutt Apr 21 '21 at 18:27

1 Answers1

2

line is a uninitialized pointer, it doesn't point to any valid memory location so you can't use it to store data, use an array instead.

while(!feof(data)) is not what you'd want to use to control your read cycle.

Use fgets/sscanf to parse the values, simple and easy way to do it:

FILE *data;
data = fopen("data.txt", "r");
int m, n;
char line[32];

if (data != NULL)
{
    while (fgets(line, sizeof line, data)) // assuming that you want to have more lines
    {
        if(sscanf(line, "%d%d", &m, &n) != 2){
            // values not parsed correctly
            //handle parsing error
        }
    }
}

Or as @chux pointed out, to detect extra junk on the line:

 char end;  
 if(sscanf(line, "%d%d %c", &m, &n, &end) != 2) {
     // if more characters exist on the line
     // the return value of sscanf will be 3
 }

If the values in the file can be outside the range of an int consider using strtol instead of sscanf.

anastaciu
  • 23,467
  • 7
  • 28
  • 53