Понимание ungetc использовать в простом getword

Я сталкивался с таким примером getword. Я понимаю все проверки и т. Д., Но у меня есть проблема с ungetc.

Когда c удовлетворяет if ((!isalpha(c)) || c == EOF)а также не удовлетворяет while (isalnum(c)) -> это не буква и не число - ungetc отвергает это char,

Давайте предположим, что это '\n',

Тогда дело доходит до return word однако он не может быть возвращен, так как он не сохранен ни в одном массиве. Что происходит потом?

    while (isalnum(c)) {
        if (cur >= size) {
            size += buf;
            word = realloc(word, sizeof(char) * size);

        }
        word[cur] = c;
        cur++;
        c = fgetc(fp);
    }
    if ((!isalpha(c)) || c == EOF) {
        ungetc(c, fp);          
    }
    return word;

РЕДАКТИРОВАТЬ@Mark Byers - спасибо, но что c был отклонен с какой-то целью, и не будет выполнять условие снова и снова в бесконечном цикле?

3 ответа

Решение

Состояние терминала прямо перед линией, которую вы не понимаете, не очень хорошее. Вероятно, должно быть:

int c;

...

if (!isalpha(c) && c != EOF)
    ungetc(c, fp);

Это означает, что если последний прочитанный символ был реальным символом (не EOF) и не был буквенным символом, отодвиньте его обратно для повторной обработки любым последующим использованием входного потока fp, То есть предположим, что вы читаете пустое место; пробел завершит цикл, и пробел будет сдвинут назад так, чтобы следующий getc(fp) будет читать бланк снова (как бы fscanf() или же fread() или любая другая операция чтения в файловом потоке fp). Если вместо пустого вы получили EOF, то в моем пересмотренном коде нет попытки отодвинуть EOF; в исходном коде EOF будет отброшен назад.

Обратите внимание, что c должен быть int а не char,

ungetc помещает символы в поток, чтобы при следующем чтении этот символ снова возвращался.

ungetc(c, fp);  /* Push the character c onto the stream. */
/* ...etc... */
c = fgetc(fp);  /* Reads the same value again. */

Иногда это может быть удобно, если вы читаете символы, чтобы узнать, когда текущий токен завершен, но еще не готовы прочитать следующий токен.

ХОРОШО. Теперь я понимаю, почему это, например, с. '\n' беспокоил меня. Я просто тупой и забыл про раздел в main() ссылаясь на getword. Конечно, перед вызовом getword есть пара тестов (еще один ungetc там) и это fputs что персонажи не удовлетворяют isalnum Из этого вытекает, что while зациклиться getword всегда начинается хотя бы с одного isalnum положительный, и проверка в конце означает только следующие символы.

Другие вопросы по тегам