there is no such creature," she tells him, at the same time

wanting him to tell her more. Shyly, she asks, " I mean,

Daddy, is there?"

Поместим этот текст в файл alice_emma, а затем перенаправим на него стандартный вход программы. Позже, когда мы познакомимся с файловым вводом, мы откроем и прочтем этот файл непосредственно. Следующая программа помещает прочитанные со стандартного ввода слова в C-строку и находит самое длинное слово:

#include iostream.h

#include string.h

int main()

{

const int bufSize = 24;

char buf[ bufSize ], largest[ bufSize ];

// для хранения статистики

int curLen, max = -1, cnt = 0;

while ( cin buf )

{

curLen = strlen( buf );

++cnt;

// новое самое длинное слово? сохраним его

if ( curLen max ) {

max = curLen;

strcpy( largest, buf );

}

}

cout " Число прочитанных слов "

cnt endl;

cout " Длина самого длинного слова "

max endl;

cout " Самое длинное слово"

largest endl;

}

После компиляции и запуска программа выводит следующие сведения:

Число прочитанных слов 65

Длина самого длинного слова 10

Самое длинное слово creature,"

На самом деле этот результат неправилен: самое длинное слово beautiful, в нем девять букв. Однако выбрано creature, потому что программа сочла его частью запятую и кавычку. Следовательно, необходимо отфильтровать небуквенные символы.

Но прежде чем заняться этим, рассмотрим программу внимательнее. В ней каждое слово помещается в массив buf, длина которого равна 24. Если бы в тексте попалось слово длиной 24 символа (или более), то буфер переполнился бы и программа, вероятно, закончилась бы крахом. Чтобы предотвратить переполнение входного массива, можно воспользоваться манипулятором setw(). Модифицируем предыдущую программу:

while ( cin setw( bufSize ) buf )

Здесь bufSize – размер массива символов buf. setw() разбивает строку длиной bufSize или больше на несколько строк, каждая из которых не длиннее, чем bufSize - 1.

Завершается такая частичная строка двоичным нулем. Для использования setw() в программу необходимо включить заголовочный файл iomanip:

#include iomanip

Если в объявлении массива buf размер явно не указан:

char buf[] = "Нереалистичный пример";

то программист может применить оператор sizeof, но при условии, что идентификатор является именем массива и находится в области видимости выражения:

while ( cin setw(sizeof( buf )) buf )

Применение оператора sizeof в следующем примере дает неожиданный результат:

#include iostream

#include iomanip

int main()

{

const int bufSize = 24;

char buf[ bufSize ];

char *pbuf = buf;

// если строка длиннее, чем sizeof(char*),

// она разбивается на несколько строк

while ( cin setw( sizeof( pbuf )) pbuf )

cout pbuf endl;

}

Программа печатает:

$ a.out

The winter of our discontent

The

win

ter

of

our

dis

con

ten

t

Функции setw() вместо размера массива передается размер указателя, длина которого на нашей машине равна четырем байтам, поэтому вывод разбит на строки по три символа.

Попытка исправить ошибку приводит к еще более серьезной проблеме:

while ( cin setw(sizeof( *pbuf )) pbuf )

Мы хотели передать setw() размер массива, адресуемого pbuf. Но выражение

*pbuf

дает только один символ, т.е. объект типа char. Поэтому setw() передается значение 1. На каждой итерации цикла while в массив, на который указывает pbuf, помещается только нулевой символ. До чтения из стандартного ввода дело так и не доходит, программа зацикливается.

При использовании класса string все проблемы управления памятью исчезают, об этом заботится сам string. Вот как выглядит наша программа в данном случае:

#include iostream.h

#include string

int main()

{

string buf, largest;

// для хранения статистики

int curLen, // длина текущего слова

max = -1, // максимальная длина слова

cnt = 0; // счетчик прочитанных слов

while ( cin buf )

{

curLen = buf.size();

Перейти на страницу:

Похожие книги