Почему ввод "abc!!!" но вывод не "abC+++"?

Я исследовал файл ввода / вывода. Ниже приведен код некоторых функций, таких как: fgetc(),fgets(),fputs(). Я не знаю, почему это не работает так, как я хочу. Большое спасибо! Ниже мой код:

#include <stdio.h>
int main()
{
   FILE *fp; //FILE type pointer
   int c; //using to get each character from file
   char buffer [256]; //array as buffer to archive string

    fp = fopen("file.txt", "r"); /*open a file with only read mode*/
   if( fp == NULL ) 
    {
      perror("Error in opening file");
       return(-1);
    }
     while(!feof(fp)) /*check if has not yet reached to end of file*/
     {
       c = getc (fp); //get a character from fp          
       if( c == '!' )
      {
         ungetc ('+', fp); //replace '!' by '+'

      }
      else
      {
         ungetc(c, fp); //no change
      }
       fgets(buffer,255,fp);//push string of fp to buffer
       fputs(buffer, stdout); //outputting string from buffer to stdout
    }
    return(0);
 }

4 ответа

Логика в цикле while имеет недостатки.

Вот что происходит:

Вы getc первый персонаж, a,

a это не ! так что вы ungetca обратно в поток.

Затем вы читаете всю строку. Конечно получаешь abc!!!,

Затем вы печатаете строку. Выход: abc!!!,

Если вы хотите манипулировать строкой, лучше манипулировать буфером, а не пытаться изменить поток:

   int i;
   int len = fgets(buffer,255,fp);//push string of fp to buffer
   for (i=0; i < len; i++) {
        if (buffer[i] == '!') {
             buffer[i] = '+';
        }
   }
   fputs(buffer, stdout); //outputting string from buffer to stdout

В качестве альтернативы, если вы действительно хотите использовать ungetc, вам нужно читать / печатать один символ за раз, потому что ungetc можно сделать безопасно только на одном персонаже. Держать if и ungetc и заменить fgets/fputs со следующим:

   fgets(buffer,1,fp);       // Read one character. 
   printf("%c", buffer[0]); // output one character from buffer to stdout

Ошибка возникает, как указано в другом ответе, потому что вы тестируете только первый символ в файле, а затем читаете из него 255 байт, вместо того, чтобы захватывать один байт за раз и тестировать его.

Также важно отметить, что ungetc влияет только на поток, а не на файл:

Однако обратите внимание, что это влияет только на дальнейшие операции ввода в этом потоке, а не на содержимое физического файла, связанного с ним, который не изменяется никакими вызовами этой функции. (Cplusplus.com)

Кроме того, функция гарантирована только для одного последовательного использования:

Задержанные символы будут возвращены в обратном порядке; гарантирован только один возврат. (руководство по Linux)

Вы просто контролируете первый символ файла и контролируете, что если он ! или нет, тогда вы читаете 255 байтов из этого потока и сбрасываете его в выходной поток.

Для входного файла (который abc!!! в вашем примере) после чтения 255 байт из этого файла make feof() возвращает True и прерывает ваш цикл, потому что читать нечего.

Возможно, потому что вы открываете файл только для чтения:

fp = fopen("file.txt", "r"); /*open a file with only read mode*/
Другие вопросы по тегам