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

Пример работы функции get_toke() - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 11, средняя оценка - 4.82
arfaa
0 / 0 / 0
Регистрация: 17.05.2011
Сообщений: 27
12.07.2012, 16:46     Пример работы функции get_toke() #1
Здравствуйте. Читаю книжку Бьярне Страуструпа в ней разбирается работа калькулатора. Возникает много вопросов, так как некоторые вещи, к сожалению, там не описаны.
Функция для рассмотрения первичных выражений в калькуляторе:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
double primary()
 {
   Token t=get_token();
   switch(t.kind) {
     case '(' :
        {
           double d=expression(); // функция выражений
           t=get_token();
           if(t.kind!=')' ) error(" ')' expected");
           return d;
        }
      case '8':
           return t.value;
      default:
           error("ожидается первичное выражение");
     }
 }
1.Работа функции get_token() она считывает лексемы в объект t по одной?Но почему тогда нет цикла, ведь считалась только одна? Если считываются все лексемы сразу, то каким образом они считываются дальше по одной, опять же если нет цикла?
2.Допусти выражение 2+2*3. Здесь пять лексем 2;+;2;*;3; и нету не одной скобки, то есть выбор ключа по скобка не осуществляется.'8'-это символ того,что та лексема число.У нас есть ключ как раз по этому символу.Но получается,что после обнаружения вернется только значение для одного числа?Опять же как это осуществляется без цикла?
3.Что возвращает эта функция в итоге для выражения 2+2*3

Заранее огромное спасибо!
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Jupiter
Каратель
Эксперт C++
6543 / 3963 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
12.07.2012, 18:59     Пример работы функции get_toke() #2
Цитата Сообщение от arfaa Посмотреть сообщение
Опять же как это осуществляется без цикла?
Цитата Сообщение от arfaa Посмотреть сообщение
опять же если нет цикла?
читайте про рекурсивный спуск
arfaa
0 / 0 / 0
Регистрация: 17.05.2011
Сообщений: 27
12.07.2012, 22:56  [ТС]     Пример работы функции get_toke() #3
Рекурсия-это вызов функции самой себя,в данном коде она себя не вызывает вообще, то есть может быть такой вариант через expression(), она может вернуться к самой себе,если будут использоваться двойные скобки,но в какой-то момент данному куску надо будет возвратить именно какое-то значение, иначе программа будет зациклена.
-=ЮрА=-
Заблокирован
Автор FAQ
12.07.2012, 23:07     Пример работы функции get_toke() #4
arfaa, посмотри сюда
Распознавание ручного ввода задания аналитических зависимостей
DiffEreD
 Аватар для DiffEreD
1420 / 757 / 95
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2
13.07.2012, 00:15     Пример работы функции get_toke() #5
Цитата Сообщение от arfaa Посмотреть сообщение
в какой-то момент данному куску надо будет возвратить какое-то значение иначе программа будет зациклена.
Если вы на той главе о которой я думаю, то там сначала вызывается ф-ция expression(), она вызывает ф-цию term() и еще получает лексему с помощью get_token() для подальшой обработки. Ф-ция term() в свою очередь вызывает ф-цию primary() + получает лексему для обработки. Ф-ция primary() в свою очередь вызывает й-цию expression(). Если ничего не вызовет прерывания, то етот цикл будет продолжаться.
Читайте далее, там более подробно должно быть описано. Я сам по началу запутался.

Добавлено через 52 минуты
Вот немного прокоментировал
программу
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
double primary()
{
    Token t = ts.get(); //считывает лексему
    switch (t.kind) {   //проверяет тип лексемы
    case '(':    // если  лексема "(", то вызывется снова expression()
        {    
            double d = expression();
            t = ts.get();
            if (t.kind != ')') error("')' expected)");
            return d;
        }
    case '8':            // если лексема цыфра, то primary() возвращает цыфру
        return t.value;  
    default:
        error("primary expected");  
    }
}
 
//------------------------------------------------------------------------------
 
// deal with *, /, and %
double term()
{
    double left = primary(); // принимает то что возвращает primary()
    Token t = ts.get();        // получает следующую лексему
 
    while(true) {
        switch (t.kind) {
        case '*': 
            left *= primary();
            t = ts.get();
        case '/':
            {    
                double d = primary();
                if (d == 0) error("divide by zero");
                left /= d; 
                t = ts.get();
                break;
            }
        default: //если лексема не * и не /, то возвращает число
            ts.putback(t);     // 
            return left;
        }
    }
}
 
//------------------------------------------------------------------------------
 
// deal with + and -
double expression()
{
    double left = term();      // принимает то что возвращает Term()
    Token t = ts.get();        // ну и далее по аналогии
 
    while(true) {    
        switch(t.kind) {
        case '+':
            left += term();    
            t = ts.get();
            break;
        case '-':
            left += term();   
            t = ts.get();
            break;
        default: 
            ts.putback(t);     
            return left;      
        }
    }
}
 
int main()
{
     while (cin) {
     Token t = ts.get();
     double val;
     if (t.kind == 'q') break; // 'q' for quit
     if (t.kind == ';')        // ';' for "print now"
           cout << "=" << val << '\n';
     else
          ts.putback(t);
     val = expression();  //если все будет хорошо - вернет число
}
}
arfaa
0 / 0 / 0
Регистрация: 17.05.2011
Сообщений: 27
13.07.2012, 03:14  [ТС]     Пример работы функции get_toke() #6
yuron_477, к сожалению из всех ответивших только вы меня поняли. Я понимаю, про то, что expression -> term->primary->expresion и так далее... Прочитал все. Но,во-первых,я не понимаю как происходит чтение из строки,пытаюсь найти с примером работу функции get_token() чтобы понять, что я ввожу и что получаю, то есть что получает компьютер после работы функции get_token(). Написано в общих чертах для получения лексем,тут не поспоришь, но как она выделяет их, выделяет один символ и прогоняет через всю программу этот символ определяя его принадлежность к той или иной функции или всю строку сразу делит на лексемы и прогоняет их все сразу? Зашел на официальный сайт страйструпа http://www.stroustrup.com/Programming/calculator00.cpp хотел хоть посмотреть принцип работы, ввожу в строчку 2+2*3 пишет ошибку, вожу построчно:
2
+
2
*
3
тоже безуспешно, в интернете не могу найти принцип работы синтаксического анализатора get_token() мне бы именно на примере принцип его работы, а не сухо его код! Может объясните чуть поподробнее,буду очень признателен!
movsesiv
 Аватар для movsesiv
0 / 0 / 0
Регистрация: 28.08.2011
Сообщений: 9
13.07.2012, 07:14     Пример работы функции get_toke() #7
arfaa, внимательно смотри. Есть у Страуструпа в калькуляторе цикл. Он находится в функции main(). Выглядит примерно следующим образом:

C++
1
2
3
4
5
6
7
8
int main(){
       while(cin){
              get_token();
              ...
              ...
              cout<<expr(false);
       }
}
Цикл работает, пока в потоке ввода что-то есть.
DiffEreD
 Аватар для DiffEreD
1420 / 757 / 95
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2
13.07.2012, 11:00     Пример работы функции get_toke() #8
Цитата Сообщение от arfaa Посмотреть сообщение
хотел хоть посмотреть принцип работы
Эта версия его программы еще недоработана, там далее в книге описывается новая версия калькулятора. По вашей ссылке на сайте Страуструпа есть же пример ф-ции (в новой версии она заменяется на ф-цию get()):
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Token get_token()    // read a token from cin
{
    char ch;
    cin >> ch;    // считываем выражение (например вводим 12,67+6*7(2+7);
 
    switch (ch) {
 //еще не реализовано   case ';':    // for "print"
 //еще не реализовано  case 'q':    // for "quit"
    case '(': case ')': case '+': case '-': case '*': case '/': 
        return Token(ch); // смотрит на первую лексему и если она (, ), +, -, *, / - возвращает Token(ch)
    case '.':
    case '0': case '1': case '2': case '3': case '4':
    case '5': case '6': case '7': case '8': case '9':  //иначе: 
        {    
            cin.putback(ch);         // если была цифра - закидывает цифру назад в поток ввода
            double val;
            cin >> val;              // считывает введенное число в double (в данном случае 12,67)
            return Token('8',val);   // возвращает объект Token('8',val)
        }
    default:
        error("Bad token");  // иначе плохая лексема
    }
}
arfaa
0 / 0 / 0
Регистрация: 17.05.2011
Сообщений: 27
13.07.2012, 14:16  [ТС]     Пример работы функции get_toke() #9
yuron_477, 1) а каким образом происходит преобразования ch после возврата в поток с помощью putback?return Token('8',val)-эта строчка понятна,но как из char происходит преобразование в double,если параметры объекта до этого char=символу, а double отсутствовало напрочь.
2)То есть считывание выражение происходит сразу всего?
3)Читал про калькулятор не только у Страуструпа,и везде пишется,что программа как бы заголядывает на одну лексему(на один знак) вперед,где механизм реализации "заглядывания" вперед?
DiffEreD
 Аватар для DiffEreD
1420 / 757 / 95
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2
13.07.2012, 14:38     Пример работы функции get_toke() #10
Считывание в char нужно для правильной обработки в операторе switc(ch). Если ch равно (, ), +, -, *, /, то возвращается объект Token(ch). Если ch в виде цифры, то она закидывается назад в поток ввода, словно мы ее не видели ("заглядывания" вперед), далее все последующие лексемы, которые будут цифрами (включительно с той первой цифрой, которую мы закинули в поток) считываются в переменную val типа double с помощью cin>>val и после етого возвращается объект Token('8',val).
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
13.07.2012, 14:54     Пример работы функции get_toke()
Еще ссылки по теме:

C++ Подскажите пример функции с переменным числом параметров, в том числе 0
C++ Нужен пример рекурсивной функции для понимания ее назначения и практической пользы
Нужен пример работы со структурами C++

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

Или воспользуйтесь поиском по форуму:
arfaa
0 / 0 / 0
Регистрация: 17.05.2011
Сообщений: 27
13.07.2012, 14:54  [ТС]     Пример работы функции get_toke() #11
т.е. этот механизм :
cin.putback(ch); // если была цифра - закидывает цифру назад в поток ввода
double val;
cin >> val; // считывает введенное число в double (в данном случае 12,67)
return Token('8',val);
преобразует символ ch в арифметическое число?

И еще вопрос,когда по функции прошло первое число,в данном случае 12,67 , оно записалось в объект Token,а функция возвращает это значение. Куда сохраняются возвращенные значения, ведь нужно пройти по строке, и вернуть остальные символы и цифры?
Yandex
Объявления
13.07.2012, 14:54     Пример работы функции get_toke()
Ответ Создать тему
Опции темы

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