Kyrol
Kyrol

Reputation: 3617

Strange behaviour using fgets and strtok_r

This is my code:

#define LEN 40
#define STUDLIST "./students.txt"

int main()
{
 FILE * studd;
 char del[] = "" " '\n'";
 char name[LEN], surname[LEN], str[LEN];
 char *ret;
 char *tokens[2] = {NULL};
 char *pToken = str;
 unsigned int i = 0;

 /* open file */
 if ( (studd = fopen(STUDLIST,"r") ) == NULL ) 
 {
   fprintf(stderr, "fopen\n");
   exit(EXIT_FAILURE);
 }

 while((ret = fgets(str, LEN, studd)))
    {
     if(ret)
        {
         for( tokens[i] = strtok_r( str, del, &pToken ); ++i < 2; 
              tokens[i] = strtok_r( NULL, del, &pToken ) );

           strcpy(name, tokens[0]);
           strcpy(surname, tokens[1]);

           printf( "name = %s\n", name );
           printf( "surname = %s\n", surname );
         }
      fflush(studd);
    }
   fclose(studd);

 return 0;
}

Here there is the file students.txt: http://pastebin.com/wNpmXYis

I don't understand why the output isn't correct as I expected. I use a loop to read each line with fgets, then I have a sting composed by [Name Surname], and I want to divide it in two different strings ([name] and [surname]) using strtok_r. I tried with a static string and it works well, but If I read many strings from FILE the output is not correct as you can see here:

http://pastebin.com/70uPMzPh

Where is my fault?

Upvotes: 1

Views: 301

Answers (2)

skywall
skywall

Reputation: 4005

Why are you using forloop? ...

while((ret = fgets(str, LEN, studd)))
{
  if(ret)
  {
    tokens[0] = strtok_r( str, del, &pToken );
    tokens[1] = strtok_r( NULL, del, &pToken );

    strcpy(name, tokens[0]);
    strcpy(surname, tokens[1]);

    printf( "name = %s\n", name );
    printf( "surname = %s\n", surname );
  }
}

Upvotes: 4

abelenky
abelenky

Reputation: 64730

You start i at zero:

unsigned int i = 0;

And later you increment it:

++i < 2; 

You never set i back to zero, and in fact, continue incrementing i again for every new line in your file. With 14 names in your input file, I expect i to get to about 14.
(or maybe 13 or 15, depending on the exact logic).

So this line:

tokens[i] = strtok_r(...);

ends up putting strtok results into tokens[2..15]. But only tokens[0] and tokens[1] are valid. Everything else is undefined behavior.

Answer: Be sure you reset i to zero when you read a new line of your file.

Upvotes: 2

Related Questions