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

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

Шрифт:

if (r.temperature<implausible_min ||
implausible_max<r.temperature)

return false;

return true;

}

В заключение можем прочитать объекты класса

Year
. Оператор
>>
в классе
Year
аналогичен оператору
>>
в классе
Month
.

istream& operator>>(istream& is, Year& y)

// считывает объект класса Year из потока is в объект y

// формат: { year 1972... }

{

char ch;

is >> ch;

if (ch!='{') {

is.unget;

is.clear(ios::failbit);

return is;

}

string year_marker;

int yy;

is >> year_marker >> yy;

if (!is || year_marker!="year")

error("Неправильное начало Year");

y.year = yy;

while(true) {

Month m; // каждый раз создаем новый объект m

if(!(is >> m)) break;

y.month[m.month] = m;

}

end_of_loop(is,'}',"Неправильный конец Year");

return is;

}

Можно было бы сказать, что этот оператор “удручающе аналогичен”, а не просто аналогичен, но здесь кроется важный нюанс. Посмотрите на цикл чтения. Ожидали ли вы чего-нибудь подобного следующему фрагменту?

Month m;

while (is >> m)

y.month[m.month] = m;

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

operator>>(istream& is, Month& m)
не присваивает объекту m совершенно новое значение; она просто добавляет в него данные из объектов класса
Reading
. Таким образом, повторяющаяся инструкция
is>>m
добавляла бы данные в один и тот же объект
m
. К сожалению, в этом случае каждый новый объект класса
Month
содержал бы все показания всех предшествующих месяцев текущего года. Для того чтобы считывать данные с помощью инструкции
is>>m
, нам нужен совершенно новый объект класса
Month
. Проще всего поместить определение объекта m в цикл так, чтобы он инициализировался на каждой итерации.

В качестве альтернативы можно было бы сделать так, чтобы функция

operator>>(istream& is, Month& m)
перед считыванием в цикле присваивала бы объекту
m
пустой объект.

Month m;

while (is >> m) {

y.month[m.month] = m;

m = Month; // "Повторная инициализация" объекта m

}

Попробуем применить это.

// открываем файл для ввода:

cout << "Пожалуйста, введите имя файла для ввода \n";

string name;

cin >> name;

ifstream ifs(name.c_str);

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

ifs.exceptions(ifs.exceptions|ios_base::badbit); // генерируем bad

// открываем файл для вывода:

cout << "Пожалуйста, введите имя файла для ввода \n";

cin >> name;

ofstream ofs(name.c_str);

if (!ofs) error(" невозможно открыть файл для ввода ",name);

// считываем произвольное количество объектов класса Year:

vector<Year> ys;

while(true) {

Year y; // объект класса Year каждый раз очищается

if (!(ifs>>y)) break;

ys.push_back(y);

}

cout << " считано " << ys.size << " записей по годам.\n";

for (int i = 0; i<ys.size; ++i) print_year(ofs,ys[i]);

Функцию

print_year
мы оставляем в качестве упражнения.

10.11.3. Изменение представления

Для того чтобы оператор

>>
класса
Month
работал, необходимо предусмотреть способ для ввода символьных представлений месяца. Для симметрии мы описываем способ сравнения с помощью символьного представления. Было бы слишком утомительно писать инструкции
if
, подобные следующей:

  • Читать дальше
  • 1
  • ...
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • ...

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

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

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

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