Программирование. Принципы и практика использования C++ Исправленное издание, стр. 162
theguestsarrived;then,Это слова невозможно найти в словаре: “planned,” и “arrived;” — это вообще не слова. Это набор букв, состоящий из слов, к которым присоединены лишние и не относящиеся к делу знаки пунктуации. В большинстве случаев мы должны рассматривать знаки пунктуации как разделители. Как же избавиться от этих знаков пунктуации? Мы могли бы считать символы, удалить знаки пунктуации или преобразовать их в пробелы, а затем ввести “очищенные” данные снова.
string line;getline(cin,line); // вводим строку linefor (int i=0; i<line.size(); ++i) // заменяем знаки пунктуации // пробелами switch(line[i]) { case ';': case '.': case ',': case '?': case '!': line[i] = ' '; }stringstream ss(line); // создаем поток istream ss, вводя в него // строку linevector<string> vs;string word;while (ss>>word) // считываем слова без знаков пунктуации vs.push_back(word);Применив такой способ, получаем желаемый результат.
AsplannedtheguestsarrivedthenК сожалению, этот код слишком сложен и излишне специализирован. А что делать, если знаки пунктуации определены иначе? Опишем более общий и полезный способ удаления нежелательных символов из потока ввода. Как должен выглядеть этот поток? Как должен выглядеть наш код? Может быть, так?
ps.whitespace(";:,."); // точка с запятой, двоеточие, запятая и точка // считаются разделителямиstring word;while (ps>>word) vs.push_back(word);Как определить поток, работающий так, как поток
psas.notСлова
asnotasnotДля того чтобы сделать это, можно определить класс. Он должен принимать символы из потока
istream>>istreamPunct_streamclass 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; } // добавляет символ // в набор разделителей bool is_whitespace(char c); // является ли c набором // разделителей? void case_sensitive(bool b) { sensitive = b; } bool is_case_sensitive() { return sensitive; } Punct_stream& operator>>(string& s); operator bool();private: istream& source; // источник символов istringstream buffer; // буфер для форматирования string white; // символы–разделители bool sensitive; // является ли поток чувствительным // к регистру?};Как и в предыдущем примере, основная идея — ввести строку из потока
istreamistringstreamPunct_streamcase_sensitive()Например, можно приказать объекту класса
Punct_streamMan bites dog!
как
manbitesdogКонструктор класса
Punct_streamistreamsourcePunct_streamcin