cout "Строка #" lcnt
"\tПрочитано символов: " readin endl;
cout.write( inBuf, readin).put('\n').put('\n');
}
cout "Всего прочитано строк: " lcnt endl;
cout "Самая длинная строка: " max endl;
}
Когда на вход было подано несколько фраз из романа Германа Мелвилла "Моби Дик", программа напечатала следующее:
Строка #1 Прочитано символов: 45
Call me Ishmael. Some years ago, never mind
Строка #2 Прочитано символов: 46
how long precisely, having little or no money
Строка #3 Прочитано символов: 48
in my purse, and nothing particular to interest
Строка #4 Прочитано символов: 51
me on shore, I thought I would sail about a little
Строка #5 Прочитано символов: 47
and see the watery part of the world. It is a
Строка #6 Прочитано символов: 43
way I have of driving off the spleen, and
Строка #7 Прочитано символов: 28
regulating the circulation.
Всего прочитано строк: 7
Самая длинная строка: 51
Функция-член getline() класса istream поддерживает только ввод в массив символов. Однако в стандартной библиотеке есть обычная функция getline(), которая помещает символы в объект класса string:
getline( istream &is, string str, char delimiter );
Эта функция читает не более str::max_size()-1 символов. Если входная последовательность длиннее, то операция завершается неудачно и объект переводится в ошибочное состояние. В противном случае ввод прекращается, когда прочитан ограничитель (он удаляется из потока, но в строку не помещается) либо достигнут конец файла.
Вот еще три необходимые нам функции-члена класса istream:
// возвращает символ в поток
putback( char class );
// устанавливает "указатель на следующий символ потока istream на один символ назад
unget();
// возвращает следующий символ (или EOF),
// но не извлекает его из потока
peek();
Следующий фрагмент иллюстрирует использование некоторых из них:
char ch, next, lookahead;
while ( cin.get( ch ))
{
switch (ch) {
case '/':
// это комментарий? посмотрим с помощью peek()
// если да, пропустить остаток строки
next = cin.peek();
if ( next == '/' )
cin.ignore( lineSize, '\n' );
break;
case '':
// проверка на лексему =
next = cin.peek();
if ( next == '' ) {
lookahead = cin.get();
next = cin.peek();
if ( next != '=' )
cin.putback( lookahead );
}
// ...
}
Упражнение 20.4
Прочитайте из стандартного ввода следующую последовательность символов, включая все пустые, и скопируйте каждый символ на стандартный вывод (эхо-копирование):
a b c
d e
f
Упражнение 20.5
Прочитайте фразу "riverrun, from bend of bay to swerve of shore" сначала как последовательность из девяти строк, а затем как одну строку.
Упражнение 20.6
С помощью функций getline() и gcount() прочитайте последовательность строк из стандартного ввода и найдите самую длинную (не забудьте, что строку, прочитанную за несколько обращений к getline(), нужно считать одной).
20.4. Перегрузка оператора вывода
Если мы хотим, чтобы наш тип класса поддерживал операции ввода/вывода, то необходимо перегрузить оба соответствующих оператора. В этом разделе мы рассмотрим, как перегружается оператор вывода. (Перегрузка оператора ввода – тема следующего раздела.) Например, для класса WordCount он выглядит так:
class WordCount {
friend ostream&
operator( ostream&, const WordCount& );
public:
WordCount( string word, int cnt=1 );
// ...
private:
string word;
int occurs;
};
ostream&
operator ( ostream& os, const WordCount& wd )
{ // формат: счетчик слово
os " " " " "
wd.word;
return os;
}