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

  for (int i=0; i

}

  Для того чтобы действительно изменить объект класса string, используем передачу аргумента по ссылке (см. раздел 8.5.5). Если бы мы хотели сохранить старую строку без изменения, то могли бы написать функцию, создающую ее копию в нижнем регистре. Мы предпочитаем функцию tolower(), а не toupper(), поскольку она лучше работает с текстами на некоторых естественных языках, например немецком, в которых не каждый символ в нижнем регистре имеет эквивалент в верхнем регистре. 

<p id="AutBody_Root207"><strong>11.7. Использование нестандартных разделителей</strong></p>

В этом разделе мы рассмотрим гипотетические примеры использования потоков iostream для решения реальных задач. При вводе строк слова по умолчанию разделяются пробелами или другими специальными символами (whitespace). К сожалению, поток istream не имеет средств, позволяющих определять, какие символы должны играть роль разделителей, или непосредственно изменять способ, с помощью которого оператор >> считывает строки. Итак, что делать, если мы хотим дать другое определение разделителю? Рассмотрим пример из раздела 4.6.3, в котором мы считывали слова и сравнивали их друг с другом. Между этими словами стояли разделители, поэтому если мы вводили строку

As planned, the guests arrived; then

то получали слова

As

planned,

the

guests

arrived;

then,

Это слова невозможно найти в словаре: “planned,” и “arrived;” — это вообще не слова. Это набор букв, состоящий из слов, к которым присоединены лишние и не относящиеся к делу знаки пунктуации. В большинстве случаев мы должны рассматривать знаки пунктуации как разделители. Как же избавиться от этих знаков пунктуации? Мы могли бы считать символы, удалить знаки пунктуации или преобразовать их в пробелы, а затем ввести “очищенные” данные снова.

string line;

getline(cin,line);                // вводим строку line

for (int i=0; i

                                  // пробелами

  switch(line[i]) {

  case ';': case '.': case ',': case '?': case '!':

    line[i] = ' ';

  }

stringstream ss(line); // создаем поток istream ss, вводя в него

                       // строку line

vector vs;

string word;

while (ss>>word)       // считываем слова без знаков пунктуации

  vs.push_back(word);

Применив такой способ, получаем желаемый результат.

As

planned

the

guests

arrived

then

К сожалению, этот код слишком сложен и излишне специализирован. А что делать, если знаки пунктуации определены иначе? Опишем более общий и полезный способ удаления нежелательных символов из потока ввода. Как должен выглядеть этот поток? Как должен выглядеть наш код? Может быть, так?

ps.whitespace(";:,."); // точка с запятой, двоеточие, запятая и точка

                       // считаются разделителями

string word;

while (ps>>word) vs.push_back(word);

Как определить поток, работающий так, как поток ps? Основная идея заключается в том, чтобы считывать слова в обычный поток ввода, а затем обрабатывать символы-разделители, заданные пользователем, как настоящие разделители, т.е. не передавать разделители пользователю, а просто использовать их для отделения слов друг от друга. Рассмотрим пример.

as.not

Слова as и not должны быть двумя самостоятельными словами

as

not

Для того чтобы сделать это, можно определить класс. Он должен принимать символы из потока istream и содержать оператор >>, работающий так же, как оператор ввода потока istream, за исключением того, что мы сами можем указывать, какие символы являются разделителями. Для простоты будем считать существующие символы-разделители (пробел, символ перехода на новую строку и т.д.) обычными символами; мы просто позволим пользователю указать дополнительные разделители. Кроме того, мы не будем удалять указанные символы из потока; как и прежде, мы превратим их в разделители. Назовем наш класс Punct_stream.

class Punct_stream { // аналогичен потоку istream, но пользователь

                     // может самостоятельно задавать разделители

public:

  Punct_stream(istream& is)

      :source(is), sensitive(true) { }

  void whitespace(const string& s) // создает строку

                                   // разделителей s

  { white = s; }

  void add_white(char c) { white += c; } // добавляет символ

                                         // в набор разделителей

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