Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 11, средняя оценка - 4.82
arfaa
0 / 0 / 0
Регистрация: 17.05.2011
Сообщений: 27
#1

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

12.07.2012, 16:46. Просмотров 1634. Ответов 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
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
12.07.2012, 16:46
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Пример работы функции get_toke() (C++):

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

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

Нужен пример работы со структурами - C++
Здравствуйте, не могли ли вы мне привести пример простой программы, в которой происходят простые действия, в которой присутствует структура...

Нужен пример работы с матрицами - C++
Как сделать матрицы в C++? Привидите хоть небольшой пример.

Нужен пример работы с последовательным портом - C++
Всем здравствуйте. Поделитесь пожалуйста примером роаботы с последовательным портом. Желательно через API, можно и через "SerialPort": ...

&,|, ^, приведите пример на каждую операцию бе компелятора а в ручную , для объяснения работы этих операций - C++
#include <iostream> int main() { char op = 0; std::cin >> op; int a = 220; int b =...

10
Jupiter
Каратель
Эксперт С++
6559 / 3980 / 227
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
12.07.2012, 18:59 #2
Цитата Сообщение от arfaa Посмотреть сообщение
Опять же как это осуществляется без цикла?
Цитата Сообщение от arfaa Посмотреть сообщение
опять же если нет цикла?
читайте про рекурсивный спуск
0
arfaa
0 / 0 / 0
Регистрация: 17.05.2011
Сообщений: 27
12.07.2012, 22:56  [ТС] #3
Рекурсия-это вызов функции самой себя,в данном коде она себя не вызывает вообще, то есть может быть такой вариант через expression(), она может вернуться к самой себе,если будут использоваться двойные скобки,но в какой-то момент данному куску надо будет возвратить именно какое-то значение, иначе программа будет зациклена.
0
-=ЮрА=-
Заблокирован
Автор FAQ
12.07.2012, 23:07 #4
arfaa, посмотри сюда
Распознавание ручного ввода задания аналитических зависимостей
0
DiffEreD
1431 / 768 / 95
Регистрация: 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
arfaa
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/Programming/calculator00.cpp хотел хоть посмотреть принцип работы, ввожу в строчку 2+2*3 пишет ошибку, вожу построчно:
2
+
2
*
3
тоже безуспешно, в интернете не могу найти принцип работы синтаксического анализатора get_token() мне бы именно на примере принцип его работы, а не сухо его код! Может объясните чуть поподробнее,буду очень признателен!
0
movsesiv
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
DiffEreD
1431 / 768 / 95
Регистрация: 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
arfaa
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
DiffEreD
1431 / 768 / 95
Регистрация: 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
arfaa
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
13.07.2012, 14:54
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
13.07.2012, 14:54
Привет! Вот еще темы с ответами:

Определить типы и функции; в функции main() реализовать демонстрацию работы - C++
Определите структуру TreeNode – узел дерева: struct TreeNode { char name; //имя узла TreeNode * nodes; //список дочерних узлов ...

Пример использования функции extern - C++
Доброго времени суток форумчане! Пытаюсь закрыть долг по программированию, но препод очень жесткий и просто так ставить ставить зачет мне...

Пример коллизии хэш функции - C++
Видел пример в вики по поводу коллизии хэш функции, но не понял его. То есть, коллизия случается, когда на входе разные данные, а на выходе...

Виртуальные функции в классах - нужен пример - C++
Добрый день. Хочу сразу извиниться за столь простые вопросы (виртуальные функции считаются азами ООП). Однако я никак не могу вникнуть в...


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

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

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