Вход/Регистрация
Программирование. Принципы и практика использования C++ Исправленное издание
вернуться

Страуструп Бьерн

Шрифт:

Token tt = t; // копирование при инициализации

if (tt.kind != t.kind) error("невозможно!");

t = t2; // присваивание

cout << t.value; // вывод числа 3.14

Имея класс

Token
, можно выразить выражение
(1.5+4)*11
с помощью семи лексем.

Обратите внимание на то, что для простых лексем значение не требуется, поэтому мы не используем член

value
. Нам нужен символ для обозначения чисел. Мы выбрали символ
'8'
просто потому, что он явно не оператор и не знак пунктуации. Использование символа
'8'
для обозначения чисел немного загадочно, но это лишь на первых порах.

Класс

Token
представляет пример типа, определенного пользователем. Тип, определенный пользователем, может иметь функции-члены (операции), а также данные члены. Существует много причин для определения функций-членов. В данном примере мы описали две функции-члена для того, чтобы инициализация объекта класса
Token
стала проще.

class Token {

public:

char kind; // вид лексемы

double value; // для чисел: значение

Token(char ch) // создает объект класса Token

// из переменной типа char

:kind(ch), value(0) { }

Token(char ch, double val) // создает объект класса Token

:kind(ch), value(val) { } // из переменных типа

// char и double

};

Эти две функции-члена называют конструкторами (constructors). Их имя совпадает с именем типа, и они используются для инициализации (конструирования) объектов класса

Token
. Рассмотрим пример.

Token t1('+'); // инициализируем t1, так что t1.kind = '+'

Token t2('8',11.5); // инициализируем t2,

// так что t2.kind = '8' и t2.value = 11.5

В первом конструкторе фрагмент

:kind(ch)
,
value(0)
означает “инициализировать член kind значением переменной
ch
и установить член
value
равным нулю”. Во втором конструкторе фрагмент
:kind(ch)
,
value(val)
означает “инициализировать член
kind
значением переменной
ch
и установить член
value
равным переменной val”. В обоих вариантах нам требуется лишь создать объект класса
Token
, поэтому тело функции ничего не содержит:
{ }
. Специальный синтаксис инициализации (список инициализации членов класса) начинается с двоеточия и используется только в конструкторах.

Обратите внимание на то, что конструктор не возвращает никаких значений, потому что в конструкторе это не предусмотрено. (Подробности изложены в разделах 9.4.2 и 9.7.)

6.3.4. Использование лексем

Итак, похоже, что мы можем завершить нашу программу, имитирующую калькулятор! Однако следует уделить немного времени для планирования. Как использовать класс

Token
в калькуляторе?

Можно считать входную информацию в вектор объектов

Token
.

Token get_token; // считывает объекты класса Token из потока cin

vector<Token> tok; // здесь храним объекты класса Token

int main

{

while (cin) {

Token t = get_token;

tok.push_back(t);

}

// ...

}

Теперь можно сначала считать выражение, а вычислить его позднее. Например, для выражения

11*12
получим следующие лексемы:

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

11
и
12
хранятся как числовые значения, а не как строки.

Рассмотрим теперь более сложные выражения. Выражение

1+2*3
состоит из пяти объектов класса
Token
.

Теперь операцию умножения можно выполнить с помощью простого цикла.

for (int i = 0; i<tok.size; ++i) {

if (tok[i].kind=='*') { // мы нашли умножение!

double d = tok[i–1].value*tok[i+1].value;

// и что теперь?

}

}

Да, и что теперь? Что делать с произведением

d
? Как определить порядок выполнения частичных выражений? Хорошо, символ
+
предшествует символу
*
, поэтому мы не можем выполнить операции просто слева направо. Можно попытаться выполнить их справа налево! Этот подход сработает для выражения
1+2*3
, но не для выражения
1*2+3
. Рассмотрим выражение
1+2*3+4
. Это пример “внутренних вычислений”:
1+(2*3)+4
. А как обработать скобки? Похоже, мы зашли в тупик. Теперь необходимо вернуться назад, прекратить на время программировать и подумать о том, как считывается и интерпретируется входная строка и как вычисляется арифметическое выражение.

  • Читать дальше
  • 1
  • ...
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: