Void newline();
Int main()
{
using namespace std;
string first_name, last_name, record_name;
string motto = "Your records are our records.";
cout << "Enter your first and last name:\n";
cin >> first_name >> last_name;
newline();
record_name = last_name + ", " + first_name;
cout << "Your name in our records is: ";
cout << record_name << endl;
cout << "Our motto is\n" << motto << endl;
cout << "Please suggest a better (one line) motto:\n";
getline(cin,motto);
cout << "Our new motto will be:\n";
cout << motto << endl;
return 0; }
// Используем библиотеку классов iostream.
Void newline()
{
using namespace std;
char next_char;
do
{
сin.get(next_char);
} while (next_char != '\n'); }
Пример диалога
Enter your first and last name:
Anna Torres
Your name in our records is: Torres, Anna
Our motto is
Your records are our records.
Please suggest a better (one-line) motto:
Our records go where no records dared to go before.
Our new motto will be:
Our records go where no records dared to go before.
Совет программисту: дополнительные версии функции getline
До сих пор в данной главе описывался такой способ вызова функции getline:
string line;
cout << "Enter a line of input:\n";
getline(cin,line):
Эта версия функции прекращает чтение, встретив символ конца строки '\n'. Еще одна версия названной функции позволяет задать другой сигнальный символ, отмечающий конец входных данных. Например, вызов функции getline в приведенном фрагменте кода:
string line;
cout << "Enter some input:\n";
getline(cin.Line, '?');
указывает, что чтение данных будет прекращено, когда во входном потоке встретится знак вопроса.
Функцию getline можно использовать как функцию типа void, но на самом деле она возвращает ссылку на свой первый аргумент, которым в приведенном фрагменте кода является cin. Поэтому при выполнении кода
string s1, s2;
getline(cin,s1) >> s2;
в переменную si будет прочитана строка текста, а в переменную s2 — следующее
за этой строкой слово (строка символов без пробелов).
Вызов getline(cin.s1) возвращает ссылку на cin, так что после него выполняется
оператор cin >> s2;
Этот способ использования функции getline скорее необычен, нежели полезен, но все же иногда и он может пригодиться.
Ловушка: комбинирование ввода с помощью потока cin и функции getline
Применение программного кода, в котором одновременно используются поток cin с оператором >> для ввода значений переменных и функция getline, требует особой аккуратности. В качестве примера рассмотрим фрагмент кода:
int n;
string line;
cin >> n;
getline(cin.line);
Когда при его выполнении считываются такие входные данные:
42
Hello hitchhiker.
можно предположить, что переменной n присваивается значение 42, а переменной line — значение, представляющее строку "Hello hitchhiker.".
Но на самом деле переменной n действительно присваивается значение 42, а вот переменной line — пустая строка. В чем же дело?
Оператор cin >> n; пропускает ведущие пробелы во входном потоке, но сохраняет для следующего оператора ввода остаток строки, в данном случае символ '\n'. Он всегда оставляет следующему вызову функции getline остаток строки (хотя бы только названный символ). В данном случае эта функция первым видит символ '\n' и тут же прекращает чтение, так что в результате считывается пустая строка. Если вам покажется, что программа непонятным образом игнорирует входные данные, посмотрите, не вызывается ли функция getline вслед за оператором >>. Во избежание такой накладки можно пользоваться функцией new_line, приведенной в листинге 15.2, или функцией ignore из библиотеки iostream. Например:
cin.ignore(1000, '\n');
При таких аргументах функция-член ignore удалит из входного потока весь остаток строки, включая символ ' \n' (или 1000 символов, если среди них не окажется символа '\n').
Использование функции getline с объектами типа string
У функции getline есть две версии для работы с объектами типа string:
istream& getline(istream& ins, string& str_var, char delimiter);
и
istream& getline(istream& ins, string& str_var);
Первая из них считывает символы из объекта istream, переданного в качестве первого аргумента (например объекта cin), и помещает эти символы в переменную str_var типа string до тех пор, пока не встретит символ delimiter. Данный символ удаляется из входного потока, но в переменную не помещается. Во второй версии в качестве значения delimiter по умолчанию используется символ '\п'. В остальном обе версии работают одинаково.
Функция getline возвращает свой первый аргумент (во всех примерах этой лекции — объект cin), но обычно применяется как функция типа void.
Одновременное использование оператора >> и функции getline может вызвать также другие проблемы. Особенно часто они встречаются при переходе от одного компилятора к другому. В подобных случаях, в частности когда от программы требуется высокая степень переносимости, можно попробовать выполнять посимвольный ввод с помощью функции cin.get.
Обработка строк с помощью класса string
Класс string позволяет выполнять над строковыми значениями все те операции, о которых рассказывалось в лекции 14, посвященном строкам С, и даже больше.
Данный класс поддерживает доступ к символам как к элементам массива, так что объекты этого класса обладают всеми преимуществами массивов символов плюс дополнительными преимуществами, которых нет у массивов, например возможностью автоматического увеличения их вместимости.
Если объект типа string назван last_name, то доступ к i-му символу представляемой им строки выполняется с помощью обращения last_name[i]. Использование такого синтаксиса доступа показано в программе из листинга 15.3.
Здесь же демонстрируется применение функции-члена length, имеющейся у каждого объекта типа string, — она возвращает длину представляемой им строки. Таким образом, объект типа string может использоваться не только как обычный массив, но и как частично заполненный массив с автоматическим отслеживанием количества заполненных элементов.
Листинг 15.3. Доступ к объекту типа string как к массиву
// Демонстрирует использование объекта типа string как массива.
#include <iostream>
#include <string>
using namespace std: