2014-11-25 3 views
1

Я пытаюсь понять, почему использование функции C strtok не работает должным образом для меня. Вот проблема: У меня есть файл, который содержит два типа информации: заголовки и текстовые описания. Каждая строка в файле является заголовком или частью текстового описания. Заголовок начинается с '>'. Текст описания следует за заголовком и может охватывать несколько строк. В конце текста есть пустая строка, которая отделяет описание от следующего заголовка. Моя цель - написать два отдельных файла: один содержит заголовки на каждой строке, а другой содержит соответствующее описание на отдельной строке. Чтобы реализовать коды на C, я использовал fgets для чтения файла по одной строке за раз в динамически распределенную память. Чтобы написать текст описания в одной строке, я использовал `strtok, чтобы избавиться от любых новых символов строки в тексте.Последний символ не печатается в файл

Мой код работает правильно для файлов заголовков. Однако для файла описаний я заметил, что последний символ текста не распечатывается в файл, даже если он печатается на стандартный вывод.

FILE *headerFile = fopen("Headers", "w"); //to write headers 
FILE *desFile = fopen("Descriptions", "w"); //to write descriptions 

FILE *pfile = fopen("Data","r"); 

if (pfile != NULL) 
{ 

    int numOfHeaders =0; 

    char **data1 = NULL; //an array to hold a header line 
    char **data2 = NULL; //an array to hold a description line 
    char line[700] ; //maximum size for the line 

    while (fgets(line, sizeof line, pfile)) 
    { 

     if(line[0] =='>') //It is a header 
     { 
      data1 = realloc(data1,(numOfHeaders +1)* sizeof(*data1)); 
      data1[numOfHeaders]= malloc(strlen(line)+1); 
      strcpy(data1[numOfHeaders],line); 

      fprintf(headerFile, "%s",line);//writes the header 

      if(numOfHeaders >0) 
      fprintf(desFile, "\n");//writes a new line in the desc file 

      numOfHeaders++;    
     } 

     //it is not a header and not an empty line 
     if(line[0] != '>' && strlen(line)>2) 
     { 
      data2 = realloc(data2,(numOfHeaders +1)* sizeof(*data2)); 
      data2[numOfHeaders]= malloc(strlen(line)+1); 

      char *s = strtok(line, "\n ");    
      strcpy(data2[numOfHeaders],s); 

      fprintf(desFile, "%s",data2[numOfHeaders]);    
      printf(desFile, "%s",data2[numOfHeaders]); 
     } 

    } //end-while 
    fclose(desFile); 
    fclose(headerFile); 
    fclose(pfile); 

    printf("There are %d headers in the file.\n",numOfHeaders); 

} 
+2

'printf (desFile,"% s ", data2 [numOfHeaders]);' - первый параметр кажется неправильным. Должно быть: 'printf ("% s ", data2 [numOfHeaders]);' Typo? –

+0

Возможно, вы захотите рассмотреть возможность использования свободной памяти() в том, что вы malloc() – Mawg

+0

'char * s = strtok (строка," \ n ");' Почему есть пробел после '\ n'? –

ответ

0

Как уже упоминалось в комментариях:

fprintf(desFile, "%s",data2[numOfHeaders]); //okay    
    printf(desFile, "%s",data2[numOfHeaders]); //wrong 

Вторая линия должна быть:

printf("%s",data2[numOfHeaders]); //okay 

Или вы могли бы сделать это:

sprintf(buffer, "%s",data2[numOfHeaders]); 
    fprintf(desFile, buffer); 
    printf(buffer);  

Другой возможныйвопросы:
без входного файла это не возможно, чтобы знать наверняка, что strtok() делает, но здесь является предположение основано на том, что вы описали:

В этих двух строках:

data2[numOfHeaders]= malloc(strlen(line)+1); 

    char *s = strtok(line, "\n ");   

, если строка, содержащаяся в data2 имеет какие-либо пробелы, с будет содержать только сегмент, возникающую до того, что ев темп. И потому, что вы только назвав его однажды линии получает обновилась:

while (fgets(line, sizeof line, pfile)) 

только один маркер (самый первый сегмент) будет прочитан.

Не всегда, но Обычно, strtok() вызывается в цикле:

char *s = {0}; 
s= strtok(stringToParse, "\n ");//make initial call before entering loop 
while(s)//ALWAYS test to see if s contains new content, else NULL 
{ 
    //do something with s 
    strcpy(data2[numOfHeaders],s); 
    //get next token from string 
    s = strtok(NULL, "\n ");//continue to tokenize string until s is null 
} 

Но, как я уже говорил выше, вы вызываете его только один раз на эту строку перед содержимым строки изменяется. Возможно, что сегмент, не распечатываемый, еще не был маркирован strtok().

Смежные вопросы