Fgets в C повторяет последнюю строку

#c #file #fgets

#c #файл #fgets

Вопрос:

У меня есть программа, подобная (из текста ссылки)

 FILE* soubor;
char buffer[100];
soubor = fopen("file","r");
string outp = "";
while (! feof(soubor))
{
        fgets(buffer,100,soubor);
        fputs (buffer , stdout);
}
fclose(soubor);
  

и файл, подобный

 A
B
C
D
E
  

и вывод программы является

 A
B
C
D
E
E
  

он повторяет последнюю строку файла дважды. У меня такая проблема и в других программах.

Ответ №1:

Использование feof() в качестве условия для цикла чтения из файла почти всегда приводит к проблемам. Стандартный способ выглядел бы следующим образом:

 while (fgets(buffer, 100, infile))
    fputs(buffer, stdout);
  

Ответ №2:

Проблема в том, что для последней строки fgets завершится ошибкой. Однако вы не проверяете feof до следующего цикла, поэтому вы все равно вызываете fputs, который распечатает содержимое буфера, то есть предыдущую строку.

Попробуйте это:

 FILE* soubor;
char buffer[100];
soubor = fopen("file","r");
string outp = "";
while (true)
{
  fgets(buffer,100,soubor);
  if (feof(soubor))
    break;
  fputs (buffer , stdout);
}
fclose(soubor);
  

Комментарии:

1. Стандартный шаблон (во всех порочных языках) заключается в том, чтобы поместить оператор get в качестве условия в цикл. Если это не удается, цикл никогда не вводится.

Ответ №3:

Мне нравится ответ Бена Рассела. Это моя версия, позволяющая избежать повторения последней строки в коде c. Это работает, но я не понимаю почему, потому что по условию if (fgets != NULL) это должно выполнять эту работу.

 int main ()
{
    FILE* pFile;
    char name[41] = "fileText04.txt";
    char text[81];
    int i;

    pFile = fopen("fileText04.txt", "wt");
    if (pFile == NULL)
    {
        printf("Error creating file n");
        exit(1);
    }
    else
    {
        for (i=0; i<5; i  )
        {
            printf("Write a text: n");
            fgets(text, 81, stdin);
            fputs(text, pFile);
        }
    }
    fclose (pFile);
    pFile = fopen(name, "rt");
    if (pFile == NULL)
    {
        printf("File not found. n");
        exit(2);
    }
    while (! feof(pFile))
    {
        fgets(text, 80, pFile);
        if (feof(pFile))   // This condition is needed to avoid repeating last line.
            break;         // This condition is needed to avoid repeating last line.
        if (fgets != NULL)
            fputs(text, stdout);
    }
    fclose (pFile);
    return 0;
}
  

Большое спасибо,
Хайме Дэвиу

Ответ №4:

Причина, по которой feof(inputfile_pointer) не является правильным способом проверки завершения при копировании файла, заключается в том, что он не работает в ОБЕИХ следующих ситуациях:

  1. Файл заканчивается без символа новой строки.
  2. Файл заканчивается символом новой строки.

Доказательство:

  • Предположим, что feof проверяется после fgets() , но до fputs() . Тогда это не сработает для случая 1. выше, поскольку любые символы, которые fgets() читаются перед EOF, не будут использоваться fputs() .
  • Предположим, что feof проверяется после fputs() , но до fgets() . Тогда это не сработает для случая 2. выше, поскольку, когда fgets() наконец встречается EOF, он не перезаписывает строку буфера ничем новым, и поскольку fputs() разрешено выполнить еще один раз, он поместит в выходной файл то же содержимое строки буфера, что и на предыдущей итерации; следовательно, в выходном файле повторяется последняя строка.