Пожалуйста, объясните этот пример кода C - PullRequest
5 голосов
/ 14 декабря 2011

Этот код взят из K & R.Я прочитал его несколько раз, но, похоже, это ускользает от моего понимания.

#define BUFSIZE 100

char buf[BUFSIZE];
int bufp = 0;

int getch(void)
{
      return(bufp>0)?buf[--bufp]:getchar();
}

int ungetch(int c)
{
      if(bufp>=BUFSIZE)
            printf("too many characters");
      else buf[bufp++]=c;
}

Цель этих двух функций, как говорит K & R, состоит в том, чтобы не дать программе читать слишком много ввода.т.е. без этого кода функция не сможет определить, что она прочитала достаточно данных, не прочитав сначала слишком много.Но я не понимаю, как это работает.

Например, рассмотрим getch ().Насколько я понимаю, это шаги, которые нужно выполнить:

  1. проверить, больше ли bufp, чем 0.
  2. , если так, то вернуть значение char buf [- bufp].
  3. else return getchar ().

Я хотел бы задать более конкретный вопрос, но я буквально не знаю, как этот код достигает того, для чего он предназначен, поэтому мойВопрос в том, какова (а) цель и (б) обоснование этого кода?

Заранее спасибо.

ПРИМЕЧАНИЕ. Для всех поклонников K & R этот код можно найти на странице.79 (в зависимости от вашего издания, я полагаю)

Ответы [ 5 ]

9 голосов
/ 14 декабря 2011

(a) Цель этого кода - иметь возможность прочитать символ и затем «не читать» его, если окажется, что вы случайно прочитали слишком много символов (с макс. 100 символов "непрочитанный"). Это полезно в парсерах с lookahead.

(b) getch считывает из buf, если в нем есть содержимое, обозначенное bufp>0. Если buf пусто, оно вызывает getchar. Обратите внимание, что он использует buf в качестве стека: он читает его справа налево.

ungetch помещает символ в стек buf после проверки, не заполнен ли стек.

1 голос
/ 14 декабря 2011

Этот блок кода предназначен для использования программами, которые принимают решения на основе того, что они читают из потока.Иногда такие программы должны смотреть на несколько символов из потока, фактически не потребляя ввод.Например, если ваш ввод выглядит как abcde12xy789, и вы должны разделить его на abcde, 12, xy, 789 (т.е. отдельные группы последовательных букв от групп последовательных цифр), вы не знаете, чтоВы достигли конца группы букв, пока не увидите цифру.Однако вы не хотите использовать эту цифру в тот момент, когда вы ее видите: все, что вам нужно, это знать, что группа букв заканчивается;вам нужен способ «вернуть» эту цифру.ungetch пригодится в этой ситуации: как только вы видите цифру после группы букв, вы возвращаете цифру обратно, вызывая ungetch.Ваша следующая итерация вернет эту цифру обратно по тому же механизму getch, избавляя вас от необходимости сохранять символ, который вы прочитали, но не использовали.

1 голос
/ 14 декабря 2011

Код на самом деле не предназначен для «чтения слишком большого количества ввода», вместо этого он позволяет вернуть уже прочитанные символы .

Например, вы читаете один символ с getch, смотрите, является ли это буквой, кладете его обратно с ungetch и читаете все буквы в цикле. Это способ предсказать, каким будет следующий персонаж.

0 голосов
/ 23 мая 2019

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

Это потому, что когда происходит последняя обработка (получение ввода), этот буфер (стек) будет давать дополнительный ввод в обратном порядке (означает последний дополнительный ввод, данный первым).

Из-за свойства стека LIFO (последний пришел первым вышел) буфер в этом коде должен быть quene, поскольку он будет работать лучше в случае более чем одного дополнительного ввода.

Эта ошибка в коде смутила меня, и, наконец, этот буфер должен быть изменен, как показано ниже.

#define BUFSIZE 100

char buf[BUFSIZE];
int bufr = 0;
int buff = 0;

int getch(void)
{
      if (bufr ==BUFSIZE)
             bufr=0;

      return(bufr>=0)?buf[bufr++]:getchar();
}

int ungetch(int c)
{
      if(buff>=BUFSIZE && bufr == 0)
            printf("too many characters");
      else if(buff ==BUFSIZE) 
            buff=0;  

       if(buff<=BUFSIZE)
            buf[buff++]=c;
}
0 голосов
/ 14 декабря 2011

Это решается с помощью приведенного выше фрагмента кода. Расширение этой концепции используется при обработке файлов, особенно при редактировании файлов. В этом случае вместо использования getchar (), который используется для получения ввода из стандартного ввода, файл используется в качестве источника ввода.

...