Различный выходной файл содержимого копии в C - PullRequest
2 голосов
/ 14 января 2012

Здравствуйте, у меня была простая программа для копирования файлов на C, но я не могу объяснить, почему я получаю разные выходные данные в конечном файле, когда я использую 2-й метод.Правильный вывод для цикла for:

I am the worst programmer in the world!
:D
 And this is bla bla bla bla
 more bla bla bla...

НО с циклом while в EOF генерируется случайный символ:

I am the worst programmer in the world!
:D
 And this is bla bla bla bla
 more bla bla bla...


Код:

int main()
{
int i;
char ch;
create_files();
FILE *src = fopen("best.txt", "r");
FILE *dst = fopen("copied.txt", "w");
for(i=getc(src); i!=EOF; i=getc(src))  //correct copy
    {
        putc(i, dst);
    }

/* while(!feof(src))                  //woot?
    {
        ch=fgetc(src);
        fputc(ch,dst);
    }*/

fclose(dst);
fclose(src);
return 0;
}

void create_files()
{
    FILE *fp;
    fp = fopen("best.txt","w");
    fprintf(fp,"I am the worst programmer in the world!\n:D\n And this is bla bla bla bla\n more bla bla bla...\n");
    fclose(fp);
}

iмы использовали и fputc или putc и fgetc или getc и все то же самое.Я что-то забыл?

Ответы [ 5 ]

2 голосов
/ 14 января 2012

Что

while (!feof(src)) {
    ch=fgetc(src);
    fputc(ch,dst);
}

делает, есть:

  1. проверка на EOF
  2. читать символ, возможно вызывая EOF
  3. выводит только что прочитанный символ без проверки EOF.

Когда происходит EOF, (3) все еще выполняется перед проверкой в ​​(1) на следующей итерации. Специальное значение EOF преобразуется в char и выводится.

Правильный цикл

while ((ch = fgetc(src)) != EOF)
    fputc(ch, dst);

при условии вы даете ch тип int, потому что char не может представлять EOF. Запишите назначение в чеке; некоторые программисты скажут вам, что это безобразно, но многие используют его, так что вы можете с этим привыкнуть. Ваш вариант for цикл также является правильным.

(За исключением 1: fputc эквивалентно putc и fgetc - getc, если вы не пытаетесь использовать их в контексте указателя на функцию.)

(Кроме 2: ваш цикл while также не проверяет поток ошибки , а проверка на EOF также возвращает перехватчики.)

1 голос
/ 14 января 2012

Цикл while дает вам случайный символ, потому что EOF фактически не помечается, пока чтение не завершится неудачей. Итак, что происходит в вашем цикле while, вы читаете, fgetc не удается, устанавливает EOF и возвращает вам значение duff, которое вы затем печатаете.

Лучший способ структурировать цикл while:

ch=fgetc(src);
while (!feof(src)) {
   fputc(ch,dst);
   ch=fgetc(src);
}
1 голос
/ 14 января 2012

В вашем цикле while есть ошибка выключения. Он читает / записывает дополнительный символ, из которого исходит бонус - вы записали значение EOF, возвращаемое fgetc(), в выходной файл!

1 голос
/ 14 января 2012

Первый цикл извлекает символ (возможно, обнаруживает EOF), а затем проверяет, что значение не обнаружило EOF, и, возможно, выполняет блок, записывающий символ (пока все символы не будут прочитаны).

Второй цикл проверяет, был ли обнаружен EOF, извлекает символ (возможно, обнаруживает EOF), записывает символ (безотносительно к тому, что он может быть) и, возможно, продолжается на следующий символ (если EOF не был не обнаружено).

Во втором цикле вы пишете символ перед проверкой, является ли он EOF.

0 голосов
/ 14 января 2012

Редактировать

Похоже, это не настоящая проблема, но я буду держать ответ в качестве совета.


Единственное, что я заметил, это:

char ch;

В зависимости от вашей системы, char может быть подписанным или неподписанным, достаточным для удержания EOF или недостаточным.Ваш цикл while, вероятно, демонстрирует, что ваша ОС подходит в последнем случае.

Вместо этого используйте int и попробуйте.

...