Дополнительный 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;
}    
Другие вопросы по тегам