Читаем Программирование полностью

  buffer.clear();

  // заполняем объект buffer

}

Если объект buffer находится в состоянии bad() или существуют проблемы с источником данных, работа прекращается; в противном случае объект buffer очищается и выполняется новая попытка. Мы должны очистить объект buffer, потому что попадем в “цикл заполнения”, только если попытка ввода закончится неудачей. Обычно это происходит, если вызывается функция eof() для объекта buffer; иначе говоря, когда в объекте buffer не остается больше символов для чтения. Обработка состояний потока всегда запутанна и часто является причиной очень тонких ошибок, требующих утомительной отладки. К счастью, остаток цикла заполнения вполне очевиден.

string line;

getline(source,line); // вводим строку line из потока source

                      // при необходимости выполняем замену символов

for (int i =0; i

  if (is_whitespace(line[i]))

    line[i]= ' ';               // в пробел

  else if (!sensitive)

    line[i] = tolower(line[i]); // в нижний регистр

  buffer.str(line);             // вводим строку в поток

Считываем строку в объект buffer, затем просматриваем каждый символ строки в поисках кандидатов на замену. Функция is_whitespace() является членом класса Punct_stream, который мы определим позднее. Функция tolower() — это стандартная библиотечная функция, выполняющая очевидное задание, например превращает символ A в символ a (см. раздел 11.6).

После правильной обработки строки line ее необходимо записать в поток istringstream. Эту задачу выполняет функция buffer.str(line); эту команду можно прочитать так: “Поместить строку из объекта buffer класса istringstream в объект line”.

Обратите внимание на то, что мы “забыли” проверить состояние объекта source после чтения данных с помощью функции getline(). Это не обязательно, поскольку в начале цикла выполняется проверка условия !source.good().

Как всегда, оператор >> возвращает ссылку на поток *this (раздел 17.10).

Проверка разделителей проста; мы сравниваем символ с каждым символом из строки, в которой записаны разделители.

bool Punct_stream::is_whitespace(char c)

{

  for (int i = 0; i

    if (c==white[i]) return true;

  return false;

}

Напомним, что поток istringstream обрабатывает обычные разделители (например, символы перехода на новую строку или пробел) по-прежнему, поэтому никаких особых действий предпринимать не надо.

Осталась одна загадочная функция.

Punct_stream::operator bool()

{

  return !(source.fail() || source.bad()) && source.good();

}

Обычное использование потока istream сводится к проверке результата оператора >>. Рассмотрим пример.

while (ps>>s) { /* ... */ }

Это значит, что нам нужен способ для проверки результата выполнения инструкции ps>>s, представленного в виде булевого значения. Результатом инструкции ps>>s является объект класса Punct_stream, поэтому нам нужен способ неявного преобразования класса Punct_stream в тип bool. Эту задачу решает функция operator bool() в классе Punct_stream.

Функция-член operator bool() определяет преобразование класса Punct_stream в тип bool. В частности, она возвращает значение true, если эта операция над классом Punct_stream прошла успешно.

Теперь можем написать программу.

int main()

 // вводит текст и создает упорядоченный список всех слов

 // из заданного текста, игнорируя знаки пунктуации и регистры,

 // а также удаляя дубликаты из полученного результата

{

  Punct_stream ps(cin);

  ps.whitespace(";:,.?!()\"{}<>/&$@#%^*|~"); // \" в строке

                                             // означает "

  ps.case_sensitive(false);

  cout << "Пожалуйста, введите слова \n";

  vector vs;

  string word;

  while (ps>>word) vs.push_back(word); // ввод слов

  sort(vs.begin(),vs.end());           // сортировка в лексикографическом

                                       // порядке

  for (int i=0; i

    if (i==0 || vs[i]!=vs[i–1]) cout << vs[i] << endl;

}

Перейти на страницу:
Нет соединения с сервером, попробуйте зайти чуть позже