Вниманию специалистов по C (Изъян в функции getop (K&R, 4.3 "Внешние переменные"))

Модератор: Модераторы разделов

promov
Сообщения: 384
Статус: Участник
ОС: Debian GNU/Linux

Вниманию специалистов по C

Сообщение promov »

В функции getop имеем

Код: Выделить всё

if (c!= EOF) {
     ungetch (c);
    }

Видим, что getop () вызывает ungetch (), но при том только условии, что (с!= EOF) Но в том-то и дело, что если нам необходимо будет выйти из программы (суть ввести во входной поток cимвол '\') тогда, грубо говоря, нам придётся делать это три раза. А могли бы обойтись двумя! Действительно, вводим в терминале набор символов. Для простоты наберём

Код: Выделить всё

4 5 + 6 3 * 7

А затем дадим команду на выполнение, но не традиционным путём, а <ctrl+d> (или у кого как). (Обратите внимание, набор символов должен оканчиваться на цифру, чтобы выполнение функции getop () "подошло" к вызову ungetch (). Если, допустим, набор символов будет оканчиваться не на цифру, тогда просто напросто из getop () выход будет осуществлён до "подхода" к вызову ungetch ())

Понятное дело, что преследуемая нами цель- считать этот входной поток, заполнить им некоторый массив и выйти из программы. Как видим, выполнение программы застопорилось. А застопорилось оно в функции getop (), вот в этом месте

while (isdigit (s [++ i]= c= getch ())) {
}

Я его переделал, чтобы было понятно

Код: Выделить всё

  do {
     //Вот перед этой строчкой функция getop застопорилась.
    c= getch ();
      s [++ i]= c;
     }
     while (isdigit (s [i]));


А застопорилась она, ибо ждё очередного симвла входного потока- а его нет. Чисто логически на этом месте должен был быть '\' Но такое уж у него свойство- исчезать из конца входного потока. Ладно, жмём ещё раз <сtrl+d>. Дальше функция getop () минует вызов ungetch (), возвращает значение в main, снова оттуда вызывается и перед очередным присвоением

Код: Выделить всё

c= getch ()
застопоривается ещё раз. Почему, недогадываетесь? Да потому, что буфер, к которому обращается getch () пуст. А пуст он по простой причине- его заполняет ungetch (), которая вызвана не была, о чём я написал несколькими строчками раньше! Значит, третий раз жмём <ctrl+d> и выходим из программы.

А если бы ungetch () была вызвана несмотря на то, что (с==EOF), тогда буфер, из которого (в первую очередь) getch () считывает значения был бы не пуст. И программа закончилась бы по второму нажатию <ctrl+d>. Пожалуйста, проверьте, кто сомневается.

К чему я это всё? Простоя не понимаю, зачем ungetch () вызывается только при определённом условии. Ну не могу же просто так я это спросить... Еcли кому есть что сказать- милости прошу к обсуждению.

Ну и сразу же здесь же. Как так? Функцией ungetch () буфер buf заполняется так: элемент N 0, 1, 2 А извлекается функцией getch N 2, 1, 0. Как так? Если buf- модель входного потока, в каком порядке он заполняется, в таком и должен опорожняться!
Зачем хорёк пошел в ларёк, зачем барсук полез на сук...
Мораль легко уразуметь: зачем на бал пришёл медведь?
Спасибо сказали:
promov
Сообщения: 384
Статус: Участник
ОС: Debian GNU/Linux

Re: Вниманию специалистов по C

Сообщение promov »

Ещё раз для заинтересовавшихся: однозначно: того, что я написал, мало. Для полного понимания необходимо обратиться к разделу 4.3 "Внешние переменные"(K&R)- я для того его и указал.

Дополнение: функция ungetch () заполняет массив buf элементов типа char (В книге ему дано название buf, потому я его буфером и назвал в сообщении N 1). К нему же обращается функция getch

Я все проверки осуществил, после убирания условия, о котором шла речь, чтобы выйти из программы, нужно сделать <ctrl+d> 2 раза. Если условие не убирать, то 3. Вопрос: зачем условие? Буду очень благодарен указавшеиу на моё непонимание. Я честно сделал анализ getop, getch и прочее, но видать всё-таки не разобрался.
Зачем хорёк пошел в ларёк, зачем барсук полез на сук...
Мораль легко уразуметь: зачем на бал пришёл медведь?
Спасибо сказали:
Аватара пользователя
diesel
Бывший модератор
Сообщения: 5989
ОС: OS X, openSuSE, ROSA, Debian

Re: Вниманию специалистов по C

Сообщение diesel »

Личные наезды убрал. Просьба удерживаться от обсуждения личностей участников форума, если есть какие-то замечания - разбираемся в личке, если не нравится стиль постящего - можно просто не читать.
Спасибо сказали: