Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп
Книгу Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп читаем онлайн бесплатно полную версию! Чтобы начать читать не надо регистрации. Напомним, что читать онлайн вы можете не только на компьютере, но и на андроид (Android), iPhone и iPad. Приятного чтения!
Шрифт:
Интервал:
Закладка:
В качестве альтернативы можно было бы сделать так, чтобы функция 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, подобные следующей:
if (s=="jan")
m = 1;
else if (s=="feb")
m = 2;
...
Это не просто утомительно; таким образом мы встраиваем названия месяцев в код. Было бы лучше занести их в таблицу, чтобы основная программа оставалась неизменной, даже если мы изменим символьное представление месяцев. Мы решили представить входную информацию в виде класса vector<string>, добавив к нему функцию инициализации и просмотра.
vector<string> month_input_tbl; // month_input_tbl[0]=="jan"
void init_input_tbl(vector<string>& tbl)
// инициализирует вектор входных представлений
{
tbl.push_back("jan");
tbl.push_back("feb");
tbl.push_back("mar");
tbl.push_back("apr");
tbl.push_back("may");
tbl.push_back("jun");
tbl.push_back("jul");
tbl.push_back("aug");
tbl.push_back("sep");
tbl.push_back("oct");
tbl.push_back("nov");
tbl.push_back("dec");
}
int month_to_int(string s)
// Является ли строка s названием месяца? Если да, то возвращаем ее
// индекс из диапазона [0:11], в противном случае возвращаем –1
{
for (int i=0; i<12; ++i) if (month_input_tbl[i]==s) return i;
return –1;
}
На всякий случай заметим, что стандартная библиотека С++ предусматривает более простой способ решения этой задачи. См. тип map<string,int> в разделе 21.6.1.
Если мы хотим вывести данные, то должны решить обратную задачу. У нас есть представление месяца с помощью чисел int, и мы хотели бы представить их в символьном виде. Наше решение очень простое, но вместо использования таблицы перехода от типа string к типу int мы теперь используем таблицу перехода от типа int к типу string.
vector<string> month_print_tbl; // month_print_tbl[0]=="January"
void init_print_tbl(vector<string>& tbl)
// инициализируем вектор представления для вывода
{
tbl.push_back("January");
tbl.push_back("February");
tbl.push_back("March");
tbl.push_back("April");
tbl.push_back("May");
tbl.push_back("June");
tbl.push_back("July");
tbl.push_back("August");
tbl.push_back("September");
tbl.push_back("October");
tbl.push_back("November");
tbl.push_back("December");
}
string int_to_month(int i)
// месяцы [0:11]
{
if (i<0 || 12<=i) error("Неправильный индекс месяца.");
return month_print_tbl[i];
}
Для того чтобы этот подход работал, необходимо где-то вызвать функции инициализации, такие как указаны в начале функции main().
// первая инициализация таблиц представлений:
init_print_tbl(month_print_tbl);
init_input_tbl(month_input_tbl);
Итак, действительно ли вы прочитали все фрагменты кода и пояснения к ним? Или ваши глаза устали, и вы перешли сразу в конец главы? Помните, что самый простой способ научиться писать хорошие программы — читать много чужих программ. Хотите — верьте, хотите — нет, но методы, использованные в описанном примере, просты, хотя и не тривиальны, и требуют объяснений. Ввод данных — фундаментальная задача. Правильная разработка циклов ввода (с корректной инициализацией каждой использованной переменной) также очень важна. Не меньшее значение имеет задача преобразования одного представления в другое. Иначе говоря, вы должны знать такие методы. Остается лишь выяснить, насколько хорошо вы усвоили эти методы и не упустили ли из виду важные факты.
Задание
1. Разработайте программу, работающую с точками (см. раздел 10.4). Начните с определения типа данных Point, имеющего два члена — координаты x и y.
2. Используя код и обсуждение из раздела 10.4, предложите пользователю ввести семь пар (x,y). После ввода данных запишите их в вектор объектов класса Point с именем original_points.
3. Выведите на печать данные из объекта original_points, чтобы увидеть, как они выглядят.
4. Откройте поток ofstream и выведите все точки в файл mydata.txt. В системе Windows для облегчения просмотра данных с помощью простого текстового редактора (например, WordPad) лучше использовать расширение файла .txt.
5. Закройте поток ofstream, а затем откройте поток ifstream для файла mydata.txt. Введите данные из файла mydata.txt и запишите их в новый вектор с именем processed_points.
6. Выведите на печать данные из обоих векторов.
7. Сравните эти два вектора и выведите на печать сообщение Что-то не так !, если количество элементов или значений элементов в векторах не совпадает.
Контрольные вопросы
1. Насколько разнообразными являются средства ввода и вывода у современных компьютеров?
2. Что делает поток istream?
3. Что делает поток ostream?
4. Что такое файл?
5. Что такое формат файла?
6. Назовите четыре разных типа устройств для ввода и вывода данных из программ.
7. Перечислите четыре этапа чтения файла.
8. Перечислите четыре этапа записи файлов.
9. Назовите и определите четыре состояния потоков.
10. Обсудите возможные способы решения следующих задач ввода.
10.1. Пользователь набрал значение, выходящее за пределы допустимого
Прочитали книгу? Предлагаем вам поделится своим отзывом от прочитанного(прослушанного)! Ваш отзыв будет полезен читателям, которые еще только собираются познакомиться с произведением.
Уважаемые читатели, слушатели и просто посетители нашей библиотеки! Просим Вас придерживаться определенных правил при комментировании литературных произведений.
- 1. Просьба отказаться от дискриминационных высказываний. Мы защищаем право наших читателей свободно выражать свою точку зрения. Вместе с тем мы не терпим агрессии. На сайте запрещено оставлять комментарий, который содержит унизительные высказывания или призывы к насилию по отношению к отдельным лицам или группам людей на основании их расы, этнического происхождения, вероисповедания, недееспособности, пола, возраста, статуса ветерана, касты или сексуальной ориентации.
- 2. Просьба отказаться от оскорблений, угроз и запугиваний.
- 3. Просьба отказаться от нецензурной лексики.
- 4. Просьба вести себя максимально корректно как по отношению к авторам, так и по отношению к другим читателям и их комментариям.
Надеемся на Ваше понимание и благоразумие. С уважением, администратор knigkindom.ru.
Оставить комментарий
-
Гость Юлия11 ноябрь 09:30
О, роман что надо! ...
Не отпускай моей руки - Люси Эллис
-
Гость Юлия10 ноябрь 17:15
Вот роман то, что надо!)...
Продлить наше счастье - Мелани Милберн
-
машаМ10 ноябрь 14:55
Замечательный роман!...
Плач в ночи - Мэри Хиггинс Кларк
