Дополнительный EOF персонаж
У меня есть программа, которая читает файл в структуру буфера. У меня проблема в том, что когда я смотрю на вывод файла, в конце появляется дополнительный символ EOF. Я опубликую связанные функции:(ПРИМЕЧАНИЕ: я удалил проверки параметров и только разместил код в функции, связанной с проблемой)
b_load
int b_load(FILE * const fi, Buffer * const pBD){
unsigned char character; /*Variable to hold read character from file*/
Buffer * tempBuffer; /*Temparary Bufer * to prevent descruction of main Buffer*/
short num_chars = 0; /*Counter of the amount of characters read into the buffer*/
/*Assigns main Buffer to tempBuffer*/
tempBuffer = pBD;
/*Infinite loop that breaks after EOF is read*/
while(1){
/*calls fgetc() and returns the char into the character variable*/
character = (unsigned char)fgetc(fi);
if(!feof(fi)){
tempBuffer = b_addc(pBD,character);
if(tempBuffer == NULL)
return LOAD_FAIL;
++num_chars;
}else{
break;
}
}
return num_chars;
}
b_print
int b_print(Buffer * const pBD){
int num_chars = 0;
if(pBD->addc_offset == 0)
printf("The buffer is empty\n");
/*Sets getc_offset to 0*/
b_set_getc_offset(pBD, 0);
pBD->eob=0;
/*b_eob returns the structures eob field*/
while (!b_eob(pBD)){
printf("%c",b_getc(pBD));
++num_chars;
}
printf("\n");
return num_chars;
}
b_getc
char b_getc(Buffer * const pBD){
if(pBD->getc_offset == pBD->addc_offset){
pBD->eob = 1;
return R_FAIL_1;
}
pBD->eob = 0;
return pBD->ca_head[(pBD->getc_offset)++];
}
в конце я получаю:
"кот" (у - это символ EOF)
Он печатает символ EOF, но никогда не добавляется в буфер. Когда код драйвера добавляет символ EOF в конец буфера, появляются 2. Есть идеи, что вызывает это? Я мог бы использовать feof()
не так, что может быть, но это требуется в коде
2 ответа
Там нет "EOF персонаж". EOF
это значение, возвращаемое getchar()
и связанные функции, чтобы указать, что у них больше нет ввода для чтения. Это макрос, который расширяется до отрицательного целочисленного константного выражения, обычно (-1)
,
(Для текстовых файлов Windows условие конца файла может быть вызвано символом Control-Z в файле. Если вы прочитаете такой файл в текстовом режиме, вы не увидите этот символ; он просто будет действовать как он достиг конца файла в тот момент.)
Не используйте feof()
функция, чтобы обнаружить, что больше нет ввода для чтения. Вместо этого посмотрите на значение, возвращаемое любой входной функцией, которую вы используете. Различные функции ввода по-разному указывают на то, что они ничего не могут прочитать; Прочтите документацию, которую вы используете. Например, fgets()
возвращает нулевой указатель, getchar()
возвращается EOF
, а также scanf()
возвращает количество элементов, которые он смог прочитать.
getchar()
например, возвращает либо только что прочитанный символ (рассматривается как unsigned char
и преобразован в int
) или значение EOF
чтобы указать, что он не мог ничего читать. Отрицательное значение EOF
выбран специально, чтобы избежать столкновения с любым допустимым значением типа unsigned char
, Это означает, что вам нужно сохранить значение, возвращаемое getchar()
в int
объект; если вы храните его в char
или же unsigned char
вместо этого вы можете потерять информацию и фактический символ со значением 0xff
может быть ошибочно принят за EOF
,
feof()
Функция возвращает значение индикатора конца файла для файла, из которого вы читаете. Этот индикатор становится истинным после того, как вы попытались и не смогли прочитать из файла. И если вы исчерпали ввод из-за ошибки, а не из-за условия конца файла, feof()
никогда не станет правдой.
Ты можешь использовать feof()
и / или ferror()
чтобы определить, почему не было больше входных данных для чтения, но только после того, как вы обнаружили это другими способами.
Рекомендуемое чтение: раздел 12 часто задаваемых вопросов о comp.lang.c, который охватывает stdio. (И все остальное.)
ОБНОВИТЬ:
Я не видел достаточно вашего кода, чтобы понять, что вы делаете с Buffer
объекты. Ваш внешний вид на самом деле выглядит (почти) правильным, хотя он написан неуклюже.
Обычная идиома для чтения символов из файла:
int c; /* `int`, NOT `char` or `unsigned char` */
while ((c = fgetc(fi)) != EOF) {
/* process character in `c` */
}
Но ваш подход, который я мог бы изменить так:
while (1) {
c = fgetc(fi);
if (feof(fi) || ferror(fi)) {
/* no more input */
break;
}
/* process character in c */
}
должно на самом деле работать. Обратите внимание, что я добавил проверку для ferror(f1)
, Может быть, у вас есть ошибка на входе (которую вы не обнаруживаете)? Это вызвало бы c
содержать EOF
или значение EOF
преобразован в тип c
, Это сомнительно, хотя, так как это, вероятно, даст вам бесконечный цикл.
Предлагаемый подход: использование интерактивного отладчика или добавление printf
звонки, показать значение character
каждый раз через цикл. Если ваш входной цикл работает правильно, то создайте урезанную версию вашей программы с жесткой последовательностью вызовов b_addc()
и посмотрите, сможете ли вы воспроизвести проблему таким образом.
Там вы идете...
int b_load(FILE * const fi, Buffer * const pBD){
int character; /*Variable to hold read character from file*/
Buffer * tempBuffer; /*Temparary Bufer * to prevent descruction of main Buffer*/
short num_chars ; /*Counter of the amount of characters read into the buffer*/
/*Infinite loop that breaks WHEN EOF is read*/
while(num_chars = 0; 1; num_chars++ ) {
character = fgetc(fi);
if (character == EOF || feof(fi)) break; // since you insist on the silly feof() ...
tempBuffer = b_addc(pBD, (unsigned char) character);
if(tempBuffer == NULL) return LOAD_FAIL;
}
}
return num_chars;
}