Читайте также:
|
|
Самое длинное слово 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.outThe winter of our discontentThewinterofourdiscontentФункции setw() вместо размера массива передается размер указателя, длина которого на нашей машине равна четырем байтам, поэтому вывод разбит на строки по три символа.
Попытка исправить ошибку приводит к еще более серьезной проблеме:
Мы хотели передать 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(); ++cnt; // новое самое длинное слово? сохраним его if (curLen > max) { max = curLen; largest = buf; } } cout < "Число прочитанных слов " << cnt << endl; cout << "Длина самого длинного слова " << max << endl; cout << "Самое длинное слово " << largest << endl;}Однако запятая и кавычка по-прежнему считаются частью слова. Напишем функцию для удаления этих символов из слова:
#include <string>void filter_string(string &str){ // элементы, подлежащие фильтрации string filt_elems("\",?."); string::size_type pos = 0; while ((pos = str.find_first_of(filt_elems, pos))!= string::npos) str.erase(pos, 1);}Эта функция работает правильно, но множество символов, которые мы собираемся отбрасывать, "зашито" в код. Лучше дать пользователю возможность самому передать строку, содержащую такие символы. Если он согласен на множество по умолчанию, то может передать пустую строку.
#include <string>void filter_string(string &str, string filt_elems = string("\",.")){ string::size_type pos = 0; while ((pos = str.find_first_of(filt_elems, pos))!= string::npos) str.erase(pos, 1);}Более общая версия filter_string() принимает пару итераторов, обозначающих диапазон, где производится фильтрация:
template <class InputIterator>void filter_string(InputIterator first, InputIterator last, string filt_elems = string("\",.")){ for (; first!= last; first++) { string::size_type pos = 0; while ((pos = (*first).find_first_of(filt_elems, pos))!= string::npos) (*first).erase(pos, 1); }}С использованием этой функции программа будет выглядеть так:
#include string>#include <algorithm>#include <iterator>#include <vector>#include <iostream> bool length_less(string s1, string s2) { return s1.size() < s2.size(); } int main(){ istream_iterator< string > input(cin), eos; vector< string > text; // copy - это обобщенный алгоритм copy(input, eos, back_inserter(text)); string filt_elems("\",.;:"); filter_string(text.begin(), text.end(), filt_elems); int cnt = text.size(); // max_element - это обобщенный алгоритм string *max = max_element(text.begin(), text.end(), length_less); int len = max->size(); cout << "Число прочитанных слов " << cnt << endl; cout << "Длина самого длинного слова " << len << endl; cout << "Самое длинное слово " << *max << endl;}Когда мы применили в алгоритме max_element() стандартный оператор "меньше", определенный в классе string, то были удивлены полученным результатом:
Дата добавления: 2015-09-03; просмотров: 116 | Нарушение авторских прав
<== предыдущая страница | | | следующая страница ==> |
Полиморфизм и виртуальные функции. Применение динамического полиморфизма. Виртуальные деструкторы. Абстрактные классы и чисто виртуальные функции. | | | Самое длинное слово beautiful |