Чтение текста в буфер в c.(пропускает последнюю строку данных, когда в текстовом файле нет новой строки) - PullRequest
2 голосов
/ 26 мая 2011

Я пытаюсь прочитать строки в текстовом файле в буфер, указав функции номер строки в качестве параметра. Затем эта функция копирует текст, содержащийся в этой конкретной строке файла, в переменную retreiveString для использования. У меня проблема в том, что если в самом конце текстового файла нет «пустой строки», программа не копирует последнюю запись в буфер. Что я делаю не так?

пример текстового файла, который читается правильно

строка 0

строка 1


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

строка 0

строка 1

//test2
    #include <stdio.h> 
    #include <string.h>
    #define BUFFER_SIZE 80

    char read_in_buffer[BUFFER_SIZE];
    char retreivedString[BUFFER_SIZE];
    void getString(int lineNum);
    int maxDataNum = 0;
    bool endOfFileReached =  false;

    int main(void){
        printf("-Main-\n");


        getString(1);
        printf("retrieved:%s\n",retreivedString);
        printf("maxdata: %d\n",maxDataNum);
        printf("strlen: %d",strlen(retreivedString));
        /*
        getString(2);
        printf("retrieved: %s\n",retreivedString);
        printf("maxdata: %d\n",maxDataNum);
        getString(4);
        printf("retrieved: %s\n",retreivedString);
        printf("maxdata: %d\n",maxDataNum);
       */

       return 0;
    }

    void getString(int lineNum){
        FILE *fin=fopen("file1_Windows.txt","r");
        int line_number = 0;
        char *temp;


       if(fin==NULL){
           printf("cannot open file1_Windows.txt\n");
       }
       while (1){

            memset(read_in_buffer,0,sizeof(read_in_buffer));
            fgets(read_in_buffer,sizeof(read_in_buffer),fin); //change to segment size?

            if (!feof(fin)) {
                if (lineNum == line_number){
                    memset(retreivedString,0,sizeof(retreivedString));
                    strcpy(retreivedString,read_in_buffer);
                }
                //printf("current line %d:     ",line_number);
                //printf("%s",read_in_buffer);
                line_number++;

            }else {
                fclose(fin);
                printf("End-of-File reached. \n");
                maxDataNum = line_number;   
                printf("maxdata: %d\n",maxDataNum);

                if (lineNum == maxDataNum){
                    endOfFileReached =  true;
                }else if (lineNum > maxDataNum){
                    printf("file read error, you're reading further that data on file\n");
                }

                break;
            }

       }

    }

Ответы [ 4 ]

3 голосов
/ 26 мая 2011

Сделай это. Возвращается, если вызов fopen не удался, и помещает вызов fgets в цикл while:

void getString(int lineNum){
        FILE *fin=fopen("file1_Windows.txt","r");
        int line_number = 0;
        char *temp;


       if(fin==NULL){
           printf("cannot open file1_Windows.txt\n");
           return;
       }
       memset(read_in_buffer,0,sizeof(read_in_buffer));
       while (fgets(read_in_buffer,sizeof(read_in_buffer),fin) != NULL){
            if (lineNum == line_number){
                memset(retreivedString,0,sizeof(retreivedString));
                strcpy(retreivedString,read_in_buffer);
            }
            //printf("current line %d:     ",line_number);
            //printf("%s",read_in_buffer);
            line_number++;
        memset(read_in_buffer,0,sizeof(read_in_buffer));
       }
       fclose(fin);
       printf("End-of-File reached. \n");
       maxDataNum = line_number;   
       printf("maxdata: %d\n",maxDataNum);
       if (lineNum == maxDataNum){
            endOfFileReached =  true;
       }else if (lineNum > maxDataNum){
            printf("file read error, you're reading further that data on file\n");
       }
    }
2 голосов
/ 26 мая 2011

Вот что стандарт говорит о fgets:

Сводка

char *fgets(char * restrict s, int n, FILE * restrict stream);

Описание

Функция fgets считывает самое большее на единицу меньше, чем число символов, указанное в n, из потока, на который указывает поток, в массив, на который указывает s.Никакие дополнительные символы не читаются после символа новой строки (который сохраняется) или после конца файла.Нулевой символ записывается сразу после последнего прочитанного в массив символа.

Возвращает

Функция fgets возвращает s в случае успеха.Если обнаружен конец файла и в массив не были прочитаны символы, содержимое массива остается неизменным и возвращается нулевой указатель.Если во время операции возникает ошибка чтения, содержимое массива неопределенное и возвращается нулевой указатель.

Итак, вот что происходит:

  1. При чтении последнегострока, fgets возвращает read_in_buffer ( не нулевой указатель ), поскольку читаются символы и не возникает ошибка чтения.
  2. Затем проверка feof (fin) возвращает true (поскольку EOF уже достигнуто), что делает этот код никогда не выполняющимся: strcpy (retreivedString, read_in_buffer) .

Вывод:

  • retreivedString никогда не изменяется и, поскольку это глобальная переменная, она была инициализирована 0 битами (эквивалентно пустой строке).

Так что если вы напечатаете retreivedString, вывод будет пустой строкой.

2 голосов
/ 26 мая 2011

Вместо того, чтобы тестировать feof (см. этот поток по причинам, не требующим этого) в цикле while, проверьте, имеет ли значение read_in_buffer ноль, как только у вас закончились строки для чтенияэтот указатель становится нулевым.Вы могли бы даже поместить свои fgets в качестве тела оператора if:

if (fgets(read_in_buffer,sizeof(read_in_buffer),fin))
{

}
0 голосов
/ 26 мая 2011

поместите строку fgets () внутрь условия if (). В конце концов, вы хотите прочитать что-то из файла, только если EOF не был установлен.

if (!feof(fin)) {
    line_number++;
    fgets(read_in_buffer,sizeof(read_in_buffer),fin);  
    ...
}
...