Форум программистов, компьютерный форум CyberForum.ru

Калькулятор в книге Страуструпа - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 17, средняя оценка - 4.65
tramp_1-3
 Аватар для tramp_1-3
14 / 14 / 1
Регистрация: 13.10.2012
Сообщений: 428
28.07.2013, 14:48     Калькулятор в книге Страуструпа #1
Я знал, что это довольно тяжелая книга, поэтому начал читать ее после другой о С++, но пример "элементарного" калькулятора поставил меня в тупик с первых же строк. В этой теме я буду задавать вопросы относительно него по частям. Вот с самого начала: это всё вообще что? Даже не псевдокод, почему END в начале? Что за выражения? Что за термы? Первичное? Выражения? Прочитал весь пример, и так вопросов куча.
(стр. 70)
Грамматика языка калькулятора определяется следующими правилами:
программа:
END // END - это конец ввода
список-выраженийEND
список-выражений:
выражение PRINT // PRINT - это'\n' или';'
выражение PRINT список-выражений
выражение:
выражение+ терм
выражение - терм
терм
терм:
терм/ первичное
терм* первичное
первичное
первичное:
NUMBER // число с плавающей запятой в С++
NAME // имя в языке С++ за исключением'_'
NAME = выражение
- первичное
( выражение)
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Dani
1263 / 621 / 50
Регистрация: 11.08.2011
Сообщений: 2,236
Записей в блоге: 2
Завершенные тесты: 1
29.07.2013, 13:32     Калькулятор в книге Страуструпа #21
Она не сложная - просто вызывается expression, для каждого слагаемого вызывается term, и для каждого множителя(или делимого) в Терме вызывается primary.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
tramp_1-3
 Аватар для tramp_1-3
14 / 14 / 1
Регистрация: 13.10.2012
Сообщений: 428
29.07.2013, 13:58  [ТС]     Калькулятор в книге Страуструпа #22
Dani, в expr () после вызова get_token() функция term () возвращает уже следующий после left терм?
C++
1
2
3
4
5
6
7
8
double left = term(); 
for(;;) // ``вечно'' 
switch(curr_tok) { 
case PLUS: 
get_token(); // случай'+' 
left += term(); 
break;
...
Dani
1263 / 621 / 50
Регистрация: 11.08.2011
Сообщений: 2,236
Записей в блоге: 2
Завершенные тесты: 1
29.07.2013, 14:03     Калькулятор в книге Страуструпа #23
tramp_1-3, ты напутал. Вызов get_token должен быть сразу после for(;;). Т.е. что делает ф-ция (expression (term() ей аналогична практически):
1) Каждое выражение начинается со слагаемого. Считываем его при помощи ф-ции term;
2) Считываем токен в цикле for(;;)
3) Если то токен + или - , то, по правилам математики, дальше должно идти еще одно слагаемое. Вызываем ф-цию term(), чтобы найти следующее слагаемое.
4) Если этот токен не + и не -, это значит, что мы достигли конца выражения.

У тебя же токен считывается и выкидывается. По-моему, ты смотришь нерабочую версию калькулятора (в главе 6, там по-моему только третья функция expression правильная)
tramp_1-3
 Аватар для tramp_1-3
14 / 14 / 1
Регистрация: 13.10.2012
Сообщений: 428
29.07.2013, 14:11  [ТС]     Калькулятор в книге Страуструпа #24
Цитата Сообщение от Dani Посмотреть сообщение
У тебя же токен считывается и выкидывается. По-моему, ты смотришь нерабочую версию калькулятора (в главе 6, там по-моему только третья функция expression правильная)
Попробую возразить: get_token () пишет в глобальную curr_tok, так что вроде ничего не выкидывается. Возможно, у нас издания разные..
Миниатюры
Калькулятор в книге Страуструпа  
Dani
1263 / 621 / 50
Регистрация: 11.08.2011
Сообщений: 2,236
Записей в блоге: 2
Завершенные тесты: 1
29.07.2013, 14:18     Калькулятор в книге Страуструпа #25
tramp_1-3, да, издания разные. Но смысл тот же, просто в моем издании он описывал поток лексем, со всем наворотами, а тут - все хитрее и непонятнее. Смысл в том, что то, как я написал - в default надо возвращать токен обратно в поток, а тут - токены все хитро используются, потому ничего возвращать не нужно, т.к. в curr_tok уже будет нужная лексема. Об этом не думай пока, сконцентрируйся на вызовах. Потом поймешь.

В моем издании еще было не for(;;), a while(true)
tramp_1-3
 Аватар для tramp_1-3
14 / 14 / 1
Регистрация: 13.10.2012
Сообщений: 428
29.07.2013, 14:28  [ТС]     Калькулятор в книге Страуструпа #26
Dani, константа с плавающей точкой - просто число, которое ввел в программу пользователь?
NAME - имя чего? В чем вообще смысл блока case NAME: ?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
double number_value; 
char name_string[256]; 
double prim() // обрабатывает первичное
{ 
switch (curr_tok) { 
case NUMBER: // константа с плавающей точкой
get_token(); 
return number_value; 
case NAME: 
if (get_token() == ASSIGN) { 
name* n = insert(name_string); 
get_token(); 
n->value = expr(); 
return n->value; 
} 
return look(name_string)->value;
...
Dani
1263 / 621 / 50
Регистрация: 11.08.2011
Сообщений: 2,236
Записей в блоге: 2
Завершенные тесты: 1
29.07.2013, 15:16     Калькулятор в книге Страуструпа #27
Цитата Сообщение от tramp_1-3 Посмотреть сообщение
константа с плавающей точкой - просто число, которое ввел в программу пользователь?
да, это так.
Цитата Сообщение от tramp_1-3 Посмотреть сообщение
NAME - имя чего?
Это точно должно быть описано в книге. Скорее всего, это константа для обозначения имени. Т.е. для каждой лексемы есть свой тип и свое обозначение. NAME - для обозначения имен переменных.
tramp_1-3
 Аватар для tramp_1-3
14 / 14 / 1
Регистрация: 13.10.2012
Сообщений: 428
29.07.2013, 15:48  [ТС]     Калькулятор в книге Страуструпа #28
Цитата Сообщение от Dani Посмотреть сообщение
Это точно должно быть описано в книге. Скорее всего, это константа для обозначения имени. Т.е. для каждой лексемы есть свой тип и свое обозначение. NAME - для обозначения имен переменных.
В вашей реализации такого нет? Везде это просто "имя", это что, переменные в калькуляторе вводить можно?
"Если последнее значениеNUMBER хранится в глобальной переменнойnumber_value, то строковое
представление последнего значенияNAME хранится вname_string. Перед тем, как что-либо делать с
именем, калькулятор должен заглянуть вперед, чтобы выяснить, будет ли ему присваиваться значение,
или же будет только использоваться существующее его значение. В обоих случаях надо обратиться к
таблице имен. Эта таблица рассматривается в$$3.1.3; а здесь достаточно только знать, что она
состоит из записей, имеющих вид:
C++
1
2
3
4
5
struct name { 
char* string; 
name* next; 
double value; 
};
Бьерн Страуструп. Язык программирования С++
74
Членnext используется только служебными функциями, работающими с таблицей:
C++
1
2
name* look(const char*); 
name* insert(const char*);
Обе функции возвращают указатель на ту записьname, которая соответствует их параметру-строке.
Функцияlook() "ругается", если имя не было занесено в таблицу. Это означает, что в калькуляторе
можно использовать имя без предварительного описания, но в первый раз оно может появиться только
в левой части присваивания."
Dani
1263 / 621 / 50
Регистрация: 11.08.2011
Сообщений: 2,236
Записей в блоге: 2
Завершенные тесты: 1
29.07.2013, 15:54     Калькулятор в книге Страуструпа #29
tramp_1-3, да, т.к. здесь указывается реализация списка структур name, которая хранит: string - имя, value - значение и указатель на следующий объект переменной.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
30.07.2013, 13:43     Калькулятор в книге Страуструпа
Еще ссылки по теме:

Калькулятор страуструпа C++
C++ Задание из Страуструпа
C++ Обучение по книге Страуструпа "принципы и практика C++". Не выводится "Hello, World"

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
tramp_1-3
 Аватар для tramp_1-3
14 / 14 / 1
Регистрация: 13.10.2012
Сообщений: 428
30.07.2013, 13:43  [ТС]     Калькулятор в книге Страуструпа #30
Dani, настало время функции ввода (а т.к. в плюсах ввод буферизуется, это делает её самой сложной)
Ввод всего всего выражения целиком (например,2 + 4 * 8 происходит в if(!cin.get(ch)) return curr_tok = END;?
Если да, то ведь в плюсах буферизованное выражения после прочтения (while (ch!='\n' && isspace(ch))) выкидывается и нигде не хранится, тогда как происходит дальнейшее обращение к ch?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
token_value get_token() 
{ 
char ch; 
do { // пропускает обобщенные пробелы за исключением'\n' 
if(!cin.get(ch)) return curr_tok = END; 
} while (ch!='\n' && isspace(ch)); 
switch (ch) { 
case ';': 
case '\n': 
cin >> ws;  // пропуск обобщенного пробела
return curr_tok=PRINT; 
case '*': 
case '/': 
case '+': 
case '-': 
case '(': 
case ')': 
case '=': 
return curr_tok=token_value(ch); 
case '0': case '1': case '2': case '3': case '4': 
case '5': case '6': case '7': case '8': case '9': 
case '.': 
cin.putback(ch); 
cin >> number_value; 
return curr_tok=NUMBER; 
default: // NAME, NAME= или ошибка
if (isalpha(ch)) { 
char* p = name_string; 
*p++ = ch; 
while (cin.get(ch) && isalnum(ch)) *p++ = ch; 
cin.putback(ch); 
*p = 0; 
return curr_tok=NAME; 
} 
error("недопустимая лексема");
return curr_tok=PRINT; 
} 
}
Yandex
Объявления
30.07.2013, 13:43     Калькулятор в книге Страуструпа
Ответ Создать тему
Опции темы

Текущее время: 00:21. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru