Чтение онлайн

ЖАНРЫ

Программирование. Принципы и практика использования C++ Исправленное издание
Шрифт:

void set_value(string s, double d)

// присваивает объекту класса Variable с именем s значение d

{

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

if (var_table[i].name == s) {

var_table[i].value = d;

return;

}

error("set: неопределенная переменная", s);

}

Теперь можем считать и записывать переменные, представленные в виде объектов

класса
Variable
в векторе
var_table
. Как поместить новый объект класса
Variable
в вектор
var_table
? Как пользователь калькулятора должен сначала записать переменную, а затем присвоить ей значения? Можно сослаться на обозначения, принятые в языке С++.

double var = 7.2;

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

double
, поэтому явно указывать этот тип совершенно не обязательно. Можно было бы написать проще.

var = 7.2;

Что ж, возможно, но теперь мы не можем отличить определение новой переменной от синтаксической ошибки.

var1 = 7.2; // определение новой переменной с именем var1

var1 = 3.2; // определение новой переменной с именем var2

Ой! Очевидно, что мы имели в виду

var2 = 3.2;
но не сказали об этом явно (за исключением комментария). Это не катастрофа, но будем следовать традициям языков программирования, в частности языка С++, в которых объявления переменных с их инициализацией отличаются от присваивания. Мы можем использовать ключевое слово
double
, но для калькулятора нужно что-нибудь покороче, поэтому — следуя другой старой традиции — выбрали ключевое слово
let
.

let var = 7.2;

Грамматика принимает следующий вид:

Вычисление:

Инструкция

Печать

Выход

Инструкция вычисления

Инструкция:

Объявление

Выражение

Объявление:

"let" Имя "=" Выражение

Вычисление — это новое правило вывода в грамматике. Оно выражает цикл (в функции

calculate
), который позволяет выполнять несколько вычислений в ходе одного сеанса работы программы. При обработке выражений и объявлений это правило опирается на правило Инструкция. Например, инструкцию можно обработать следующим образом:

double statement

{

Token t = ts.get;

switch (t.kind) {

case let:

return declaration;

default:

ts.putback(t);

return expression;

}

}

Вместо функции

expression
в функции
calculate
можем использовать функцию
statement
.

void calculate

{

while (cin)

try {

cout << prompt;

Token t = ts.get;

while (t.kind == print) t=ts.get; //
игнорируем
"печать"

if (t.kind == quit) return; // выход

ts.putback(t);

cout << result << statement << endl;

}

catch (exception& e) {

cerr << e.what << endl; // выводим сообщение об ошибке

clean_up_mess;

}

}

Теперь необходимо написать функцию

declaration
. Что следует сделать? Нужно убедиться, что после ключевого слова
let
следует Имя, а за ним — символ = и Выражение. Именно это утверждает грамматика. Что делать с членом
name
? Мы должны добавить в вектор
var_table
типа
vector<Variable>
объект класса
Variable
c заданными строкой name и значением выражения. После этого мы сможем извлекать значения с помощью функции
get_value
и изменять их с помощью функции
set_value
. Однако сначала надо решить, что случится, если мы определим переменную дважды. Рассмотрим пример.

let v1 = 7;

let v1 = 8;

Мы решили, что повторное определение является ошибкой. Обычно это просто синтаксическая ошибка. Вероятно, мы имели в виду не то, что написали, а следующие инструкции:

let v1 = 7;

let v2 = 8;

Определение объекта класса

Variable
с именем
var
и значением
val
состоит из двух логических частей.

1. Проверяем, существует ли в векторе

var_table
объект класса
Variable
с именем
var
.

2. Добавляем пару (

var
,
val
) в вектор
var_table
.

Мы не должны использовать неинициализированные переменные, поэтому определили функции

is_declared
и
define_name
, представляющие эти две операции.

bool is_declared(string var)

// есть ли переменная var в векторе var_table?

{

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

if (var_table[i].name == var) return true;

return false;

}

double define_name(string var, double val)

// добавляем пару (var,val) в вектор var_table

{

if (is_declared(var)) error(var,"declared twice");

var_table.push_back(Variable(var,val));

Поделиться с друзьями: