Kniga-Online.club
» » » » Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп

Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп

Читать бесплатно Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп. Жанр: Программирование год 2004. Так же читаем полные версии (весь текст) онлайн без регистрации и SMS на сайте kniga-online.club или прочесть краткое содержание, предисловие (аннотацию), описание и ознакомиться с отзывами (комментариями) о произведении.
Перейти на страницу:
class="code">c; в противном случае необходимо считывать символы из потока cin, пока не встретится символ c. Теперь функцию clean_up_mess() можно написать следующим образом:

void clean_up_mess()

{

  ts.ignore(print);

}

Обработка ошибок всегда является сложной. Она требует постоянного экспериментирования и тестирования, поскольку крайне трудно представить заранее, какая ошибка может возникнуть в ходе выполнения программы. Защита программы от неправильного использования всегда представляет собой очень сложную задачу. Дилетанты об этом никогда не беспокоятся. Качественная обработка ошибок — один из признаков профессионализма.

7.8. Переменные

Поработав над стилем и обработкой ошибок, можем вернуться к попыткам улучшить функциональные возможности калькулятора. Мы получили вполне работоспособную программу; как же ее улучшить? Во-первых, необходимо ввести переменные. Использование переменных позволяет лучше выражать более длинные вычисления.

Аналогично для научных вычислений хотелось бы иметь встроенные имена, такие как pi и e, как в научных калькуляторах. Переменные и константы — основные новшества, которые мы внесем в калькулятор. Это коснется многих частей кода. Такие действия не следует предпринимать без весомых причин и без достаточного времени на работу. В данном случае мы вносим переменные и константы, поскольку это дает возможность еще раз проанализировать код и освоить новые методы программирования.

7.8.1. Переменные и определения

 Очевидно, что для работы с переменными и константами программа-калькулятор должна хранить пары (имя, значение) так, чтобы мы имели доступ к значению по имени. Класс Variable можно определить следующим образом:

class Variable {

public:

  string name;

  double value;

  Variable (string n, double v) :name(n), value(v) { }

};

Член класса name используется для идентификации объекта класса Variable, а член value — для хранения значения, соответствующего члену name. Конструктор добавлен просто для удобства.

Как хранить объекты класса Variable так, чтобы их значение можно было найти или изменить по строке name? Оглядываясь назад, видим, что на этот вопрос есть только один правильный ответ: в виде вектора объектов класса Variable.

vector<Variable> var_table;

В вектор var_table можно записать сколько угодно объектов класса Variable, а найти их можно, просматривая элементы вектора один за другим. Теперь можно написать функцию get_value(), которая ищет заданную строку name и возвращает соответствующее ей значение value.

double get_value(string s)

  // возвращает значение переменной с именем s

{

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

  if (var_table[i].name == s) return var_table[i].value;

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

}

Этот код действительно прост: он перебирает объекты класса Variable в векторе var_table (начиная с первого элемента и продолжая до последнего включительно) и проверяет, совпадает ли их член name c аргументом s. Если строки name и s совпадают, функция возвращает член value соответствующего объекта. Аналогично можно определить функцию set_value(), присваивающую новое значение члену value объекта класса Variable.

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 следует Имя, а за ним — символ = и Выражение. Именно это утверждает грамматика. Что делать с

Перейти на страницу:

Бьёрн Страуструп читать все книги автора по порядку

Бьёрн Страуструп - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки kniga-online.club.


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

Отзывы читателей о книге Программирование. Принципы и практика использования C++ Исправленное издание, автор: Бьёрн Страуструп. Читайте комментарии и мнения людей о произведении.


Уважаемые читатели и просто посетители нашей библиотеки! Просим Вас придерживаться определенных правил при комментировании литературных произведений.

  • 1. Просьба отказаться от дискриминационных высказываний. Мы защищаем право наших читателей свободно выражать свою точку зрения. Вместе с тем мы не терпим агрессии. На сайте запрещено оставлять комментарий, который содержит унизительные высказывания или призывы к насилию по отношению к отдельным лицам или группам людей на основании их расы, этнического происхождения, вероисповедания, недееспособности, пола, возраста, статуса ветерана, касты или сексуальной ориентации.
  • 2. Просьба отказаться от оскорблений, угроз и запугиваний.
  • 3. Просьба отказаться от нецензурной лексики.
  • 4. Просьба вести себя максимально корректно как по отношению к авторам, так и по отношению к другим читателям и их комментариям.

Надеемся на Ваше понимание и благоразумие. С уважением, администратор kniga-online.


Прокомментировать
Подтвердите что вы не робот:*
Подтвердите что вы не робот:*