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

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

Шрифт:

char ch2 = 0;

char ch3 = 0;

Distribution dd;

if (is >> ch1 >> dd.year

>> ch2 >> dd.young >> dd.middle >> dd.old

>> ch3) {

if (ch1!= '(' || ch2!=':' || ch3!=')') {

is.clear(ios_base::failbit);

return is;

}

}

else

return is;

d = dd;

return is;

}

Этот код является результатом непосредственного воплощения идей, изложенных в главе 10. Если какие-то места этого кода вам не ясны, пожалуйста, перечитайте эту главу. Мы не обязаны определять тип

Distribution
и оператор
>>
. Однако он упрощает код по сравнению с методом грубой силы, основанным на принципе “просто прочитать данные и построить график”. Наше использование класса
Distribution
разделяет код на логические части, что облегчает его анализ и отладку. Не бойтесь вводить типы просто для того, чтобы упростить код. Мы определяем классы, чтобы программа точнее соответствовала нашему представлению об основных понятиях предметной области. В этом случае даже “небольшие” понятия, использованные локально, например линия, представляющая распределение возрастов по годам, могут оказаться полезными. Имея тип
Distribution
, можем записать цикл чтения данных следующим образом.

string file_name = "japanese-age-data.txt";

ifstream ifs(file_name.c_str);

if (!ifs) error("Невозможно открыть файл ",file_name);

// ...

Distribution d;

while (ifs>>d) {

if (d.year<base_year || end_year<d.year)

error("год не попадает в диапазон");

if (d.young+d.middle+d.old != 100)

error("Проценты не согласованы");

// ...

}

Иначе говоря, мы пытаемся открыть файл

japanese-age-data.txt
и выйти из программы, если его нет. Идея не указывать явно имя файла в программе часто оказывается удачной, но в данном случае мы пишем простой пример и не хотим прилагать лишние усилия. С другой стороны, мы присваиваем имя файла
japanese-age-data.txt
именованной переменной типа
string
, поэтому при необходимости его легко изменить.

Цикл чтения проверяет диапазон чисел и согласованность данных. Это основные правила проверки таких данных. Поскольку оператор

>>
сам проверяет формат каждого элемента данных, в цикле чтения больше нет никаких проверок.

15.6.2. Общая схема

Что мы хотим увидеть на экране? Этот ответ можно найти в начале раздела 15.6. На первый взгляд, для изображения данных нужны три объекта класса

Open_polyline
— по одному на каждую возрастную группу. Каждый график должен быть помечен. Для этого мы решили в левой части окна записать “название” каждой линии. Этот выбор кажется удачнее, чем обычная альтернатива
clearer
, — поместить метку где-то на самой линии. Кроме того, для того чтобы отличать графики друг от друга, мы используем разные цвета и связываем их с метками.

Мы хотим пометить ось x, указав годы. Вертикальная линия, проходящая через отметку 2008, означает год, после которого данные являются результатом экстраполяции.

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

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

const int xmax = 600; // размер окна

const int ymax = 400;

const int xoffset = 100;// расстояние от левого края окна до оси y

const int yoffset = 60; // расстояние от нижнего края окна до оси х

const int xspace = 40; // пространство между осями

const int yspace = 40;

const int xlength = xmax–xoffset–xspace; // длина осей

const int ylength = ymax–yoffset–yspace;

В принципе эти инструкции определяют прямоугольную область (окно) и вложенный в него прямоугольник (определенный осями).

Без такого схематического представления о размещении элементов экрана в нашем окне с помощью символических констант код был бы безнадежно запутанным.

15.6.3. Масштабирование данных

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

  • Читать дальше
  • 1
  • ...
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • ...

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

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

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

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