Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 5.00/14: Рейтинг темы: голосов - 14, средняя оценка - 5.00
0 / 0 / 0
Регистрация: 17.05.2011
Сообщений: 27
1

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

12.07.2012, 16:46. Просмотров 2899. Ответов 10
Метки нет (Все метки)

Здравствуйте. Читаю книжку Бьярне Страуструпа в ней разбирается работа калькулатора. Возникает много вопросов, так как некоторые вещи, к сожалению, там не описаны.
Функция для рассмотрения первичных выражений в калькуляторе:
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

Заранее огромное спасибо!
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
12.07.2012, 16:46
Ответы с готовыми решениями:

Нужен пример функции для работы со строками
Какие функции для работы со строками есть. Если не сложно можете привести пример

Почему не работает программа-пример для демонстрации работы функции strcmp (из книги Шилдта)?
Здравствуйте, помогите пожалуйста разобраться, почему программа не выполняется как надо....

простой пример работы с БД
добрый вечер. хотел сделать простенький пример... но увы :( последний шаг не получается сделать....

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

10
Каратель
Эксперт С++
6593 / 4014 / 401
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
12.07.2012, 18:59 2
Цитата Сообщение от arfaa Посмотреть сообщение
Опять же как это осуществляется без цикла?
Цитата Сообщение от arfaa Посмотреть сообщение
опять же если нет цикла?
читайте про рекурсивный спуск
0
0 / 0 / 0
Регистрация: 17.05.2011
Сообщений: 27
12.07.2012, 22:56  [ТС] 3
Рекурсия-это вызов функции самой себя,в данном коде она себя не вызывает вообще, то есть может быть такой вариант через expression(), она может вернуться к самой себе,если будут использоваться двойные скобки,но в какой-то момент данному куску надо будет возвратить именно какое-то значение, иначе программа будет зациклена.
0
1450 / 787 / 257
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2
13.07.2012, 00:15 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();  //если все будет хорошо - вернет число
}
}
0
0 / 0 / 0
Регистрация: 17.05.2011
Сообщений: 27
13.07.2012, 03:14  [ТС] 6
yuron_477, к сожалению из всех ответивших только вы меня поняли. Я понимаю, про то, что expression -> term->primary->expresion и так далее... Прочитал все. Но,во-первых,я не понимаю как происходит чтение из строки,пытаюсь найти с примером работу функции get_token() чтобы понять, что я ввожу и что получаю, то есть что получает компьютер после работы функции get_token(). Написано в общих чертах для получения лексем,тут не поспоришь, но как она выделяет их, выделяет один символ и прогоняет через всю программу этот символ определяя его принадлежность к той или иной функции или всю строку сразу делит на лексемы и прогоняет их все сразу? Зашел на официальный сайт страйструпа http://www.stroustrup.com/Prog... ator00.cpp хотел хоть посмотреть принцип работы, ввожу в строчку 2+2*3 пишет ошибку, вожу построчно:
2
+
2
*
3
тоже безуспешно, в интернете не могу найти принцип работы синтаксического анализатора get_token() мне бы именно на примере принцип его работы, а не сухо его код! Может объясните чуть поподробнее,буду очень признателен!
0
0 / 0 / 0
Регистрация: 28.08.2011
Сообщений: 9
13.07.2012, 07:14 7
arfaa, внимательно смотри. Есть у Страуструпа в калькуляторе цикл. Он находится в функции main(). Выглядит примерно следующим образом:

C++
1
2
3
4
5
6
7
8
int main(){
       while(cin){
              get_token();
              ...
              ...
              cout<<expr(false);
       }
}
Цикл работает, пока в потоке ввода что-то есть.
0
1450 / 787 / 257
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2
13.07.2012, 11:00 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");  // иначе плохая лексема
    }
}
0
0 / 0 / 0
Регистрация: 17.05.2011
Сообщений: 27
13.07.2012, 14:16  [ТС] 9
yuron_477, 1) а каким образом происходит преобразования ch после возврата в поток с помощью putback?return Token('8',val)-эта строчка понятна,но как из char происходит преобразование в double,если параметры объекта до этого char=символу, а double отсутствовало напрочь.
2)То есть считывание выражение происходит сразу всего?
3)Читал про калькулятор не только у Страуструпа,и везде пишется,что программа как бы заголядывает на одну лексему(на один знак) вперед,где механизм реализации "заглядывания" вперед?
0
1450 / 787 / 257
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2
13.07.2012, 14:38 10
Считывание в char нужно для правильной обработки в операторе switc(ch). Если ch равно (, ), +, -, *, /, то возвращается объект Token(ch). Если ch в виде цифры, то она закидывается назад в поток ввода, словно мы ее не видели ("заглядывания" вперед), далее все последующие лексемы, которые будут цифрами (включительно с той первой цифрой, которую мы закинули в поток) считываются в переменную val типа double с помощью cin>>val и после етого возвращается объект Token('8',val).
0
0 / 0 / 0
Регистрация: 17.05.2011
Сообщений: 27
13.07.2012, 14:54  [ТС] 11
т.е. этот механизм :
cin.putback(ch); // если была цифра - закидывает цифру назад в поток ввода
double val;
cin >> val; // считывает введенное число в double (в данном случае 12,67)
return Token('8',val);
преобразует символ ch в арифметическое число?

И еще вопрос,когда по функции прошло первое число,в данном случае 12,67 , оно записалось в объект Token,а функция возвращает это значение. Куда сохраняются возвращенные значения, ведь нужно пройти по строке, и вернуть остальные символы и цифры?
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
13.07.2012, 14:54

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь.

Пример работы с сетью
Кто-нибуть напишите пожалуйста самый простейщий пример работы с сетью. Например: клиент отправляет...

Пример работы кафе
Доброго времени суток, форумчане! Помогите пожалуйста начинающему, как лучше описать работу кафе...

Пример работы с JobObject
Как правильно я должен использовать этот пример для работы с JobObject , в своем проекте? ...

Пример онлайн работы
Здравствуйте, не оставьте пожалуйста новичка форума без внимания. Мне интересен принцип работы...


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

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2020, vBulletin Solutions, Inc.