Бесконечный цикл while при чтении файла

Я получаю бесконечный цикл (в цикле while) с этой функцией. Я новичок в работе с файлами, поэтому мне кажется, что я что-то упускаю... Я не вижу, что не так.

void cipher(FILE* password_ptr,int n)
{    
        if (password_ptr == NULL)
        {
                printf("Error:password_ptr points to null");
                return;
        }
        while(!feof(password_ptr))
        {
                fseek(password_ptr, 0, SEEK_CUR); // don't move
                int en=fgetc(password_ptr)+n;

                fseek(password_ptr, -1, SEEK_CUR); // move backwards one character
                if(fputc(en,password_ptr)!=en)
                {
                printf("Error:fputc didn't work");
                }
                fseek(password_ptr, 0, SEEK_CUR);
        }
        fclose(password_ptr);
};

Спасибо!


person spatara    schedule 04.03.2012    source источник
comment
Почему ты вообще fseek пытаешься не двигаться?   -  person Ry-♦    schedule 04.03.2012
comment
ваши собственные комментарии к коду говорят вам, почему - примените 1-й к последнему fseek, если вы действительно его не видите   -  person Aaron Gage    schedule 04.03.2012


Ответы (1)


Побочным эффектом вызова fseek() является то, что индикация EOF в файле очищается:

C99 7.19.9.2/5 Функция fseek:

После определения новой позиции успешный вызов функции fseek отменяет любые эффекты функции ungetc в потоке, очищает индикатор конца файла для потока, а затем устанавливает новое положение.

Обратите внимание, что ваш код также использует общий анти-шаблон цикла, управляемого функцией feof(). Эта функция не вернет EOF до тех пор, пока после операция ввода-вывода не приведет вас к этой точке (установит индикатор конца файла). Другими словами, даже когда вы входите в цикл, fgetc() может выйти из строя из-за того, что он находится в конце файла (именно это установит индикатор конца файла). Но затем последующий поиск очистит этот индикатор. Тем временем вы будете работать с EOF так, как если бы это было обычное успешное чтение.

Видеть:

Вместо этого вы можете попробовать следующий цикл:

int c;
while((c = fgetc(password_ptr)) != EOF)
{
    int en= c+n;

    fseek(password_ptr, -1, SEEK_CUR); // move backwards one character
    if(fputc(en,password_ptr)!=en)
    {
        printf("Error:fputc didn't work");
        break;
    }
}

Вам также нужно подумать о том, как вы хотите, чтобы этот фрагмент кода обрабатывал ситуацию, когда en выходит за пределы диапазона unsigned char. Поскольку fputc() преобразует записываемый символ в unsigned char перед записью в поток, если en выходит за пределы этого диапазона, будет отображаться ошибка «fputc не работает». Это может произойти, например, если добавление n к символу, прочитанному fgetc(), больше 255.

person Michael Burr    schedule 04.03.2012
comment
@spatara: Примечание: в моем первоначальном предложенном исправлении c было объявлено как int, что может привести к тому, что EOF не будет обнаружен (еще одна распространенная ошибка с обработкой EOF) - c должен быть типа int, чтобы убедиться, что EOF правильно обнаружен. - person Michael Burr; 12.03.2012