Странное поведение с использованием fgets и strtok_r - PullRequest
1 голос
/ 02 марта 2012

Это мой код:

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

Здесь находится файл Students.txt: http://pastebin.com/wNpmXYis

Я не понимаю, почему вывод не так, как я ожидал. Я использую цикл для чтения каждой строки с помощью fgets , затем у меня есть строка, составленная из [Имя Фамилия] , и я хочу разделить ее на две разные строки ( [ имя] и [фамилия ) с использованием strtok_r . Я пробовал со статической строкой, и она работает хорошо, но если я читаю много строк из FILE, вывод будет неправильным, как вы можете видеть здесь:

http://pastebin.com/70uPMzPh

Где моя вина?

Ответы [ 2 ]

4 голосов
/ 02 марта 2012

Почему вы используете for цикл? ...

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 );
  }
}
2 голосов
/ 02 марта 2012

Вы начинаете i с нуля:

unsigned int i = 0;

А потом вы увеличиваете его:

++i < 2; 

Вы никогда не устанавливаете i обратно на ноль, и фактически продолжаете увеличивать i снова для каждой новой строки в вашем файле. С 14 именами во входном файле, я ожидаю, что i достигнет приблизительно 14.
(или, может быть, 13 или 15, в зависимости от точной логики) .

Итак, эта строка:

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

приводит к выводу strtok результатов в tokens[2..15]. Но только tokens[0] и tokens[1] действительны. Все остальное неопределенное поведение .

Ответ: Обязательно сбросьте i на ноль при чтении новой строки вашего файла.

...