//
struct PersonInfo {
string name;
vector
};
Один член класса PersonInfo будет представлять имя человека, а вектор будет содержать переменное количество его номеров телефонов.
Наша программа будет читать файл данных и создавать вектор объекта класса PersonInfo. Каждый элемент вектора будет соответствовать одной записи в файле. Ввод обрабатывается в цикле, который читает запись, а затем извлекает имя и номера телефона каждого человека:
string line, word; //
vector
//
//
while (getline(cin, line)) {
PersonInfo info; //
istringstream record(line); //
record >> info.name; //
while (record >> word) //
info.phones.push_back(word); //
people.push_back(info); //
}
Здесь для чтения всей записи со стандартного устройства ввода используется функция getline(). Если вызов функции getline() успешен, то переменная line будет содержать запись из входного файла. В цикле while определяется локальный объект PersonInfo для содержания данных из текущей записи.
Затем с только что прочитанной строкой связывается поток istringstream. Теперь для чтения каждого элемента в текущей записи можно использовать оператор ввода класса istringstream. Сначала читается имя, затем следует цикл while, читающий номера телефонов данного человека.
Внутренний цикл while завершается, когда все данные в строке прочитаны. Этот цикл работает аналогично другим, написанным для чтения из объекта cin. Различие только в том, что этот цикл читает данные из строки, а не со стандартного устройства ввода. Когда строка прочитана полностью, встретившийся "конец файла" свидетельствует о том, что следующая операция ввода в объект record потерпит неудачу.
Внешний цикл while завершается добавлением в вектор только что обработанного объекта класса PersonInfo. Внешний цикл while продолжается, пока объект cin не встретит конец файла.
Упражнение 8.9. Используйте функцию, написанную для первого упражнения 8.1.2, для вывода содержимого объекта класса istringstream.
Упражнение 8.10. Напишите программу для сохранения каждой строки из файла в векторе vector. Затем используйте объект класса istringstream для чтения каждого элемента из вектора по одному слову за раз.
Упражнение 8.11. Программа этого раздела определила свой объект класса istringstream во внешнем цикле while. Какие изменения необходимо внести, чтобы определить объект record вне этого цикла? Перепишите программу, перенеся определение объекта record во вне цикла while, и убедитесь, все ли необходимые изменения внесены.
Упражнение 8.12. Почему в классе PersonInfo не использованы внутриклассовые инициализаторы?
8.3.2. Использование класса ostringstream
Класс ostringstream полезен тогда, когда необходимо организовать вывод небольшими частями за раз, не откладывая его на более позднее время. Например, могла бы возникнуть необходимость проверять и переформатировать номера телефонов, которые были прочитаны в коде предыдущего примера. Если все номера допустимы, необходимо переформатировать номера и вывести их в новый файл. Если у кого-нибудь будут недопустимые номера, то помещать их в новый файл не нужно. Вместо этого следует вывести сообщение об ошибке, содержащее имя человека и список его недопустимых номеров.
Поскольку нельзя включать для человека данные с недопустимыми номерами, мы не можем произвести вывод, пока не просмотрим и не проверим все их номера. Но можно "записать" вывод в оперативную память объекта класса ostringstream:
for (const auto &entry : people) { //
ostringstream formatted, badNums; //
//