» » » » Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп

Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп

На нашем литературном портале можно бесплатно читать книгу Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп, Бьёрн Страуструп . Жанр: Программирование. Онлайн библиотека дает возможность прочитать весь текст и даже без регистрации и СМС подтверждения на нашем литературном портале litmir.org.
Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп
Название: Программирование. Принципы и практика использования C++ Исправленное издание
Дата добавления: 22 август 2024
Количество просмотров: 99
Читать онлайн

Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних просмотр данного контента СТРОГО ЗАПРЕЩЕН! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту readbookfedya@gmail.com для удаления материала

Программирование. Принципы и практика использования C++ Исправленное издание читать книгу онлайн

Программирование. Принципы и практика использования C++ Исправленное издание - читать бесплатно онлайн , автор Бьёрн Страуструп

Специальное издание самой читаемой и содержащей наиболее достоверные сведения книги по C++. Книга написана Бьярне Страуструпом — автором языка программирования C++ — и является каноническим изложением возможностей этого языка.
Помимо подробного описания собственно языка, на страницах книги вы найдете доказавшие свою эффективность подходы к решению разнообразных задач проектирования и программирования. Многочисленные примеры демонстрируют как хороший стиль программирования на С-совместимом ядре C++, так и современный -ориентированный подход к созданию программных продуктов. Третье издание бестселлера было существенно переработано автором. Результатом этой переработки стала большая доступность книги для новичков. В то же время, текст обогатился сведениями и методиками программирования, которые могут оказаться полезными даже для многоопытных специалистов по C++. Не обойдены вниманием и нововведения языка: стандартная библиотека шаблонов (STL), пространства имен (namespaces), механизм идентификации типов во время выполнения (RTTI), явные приведения типов (cast-операторы) и другие.
Настоящее специальное издание отличается от третьего добавлением двух новых приложений (посвященных локализации и безопасной обработке исключений средствами стандартной библиотеки), довольно многочисленными уточнениями в остальном тексте, а также исправлением множества опечаток.
Книга адресована программистам, использующим в своей повседневной работе C++. Она также будет полезна преподавателям, студентам и всем, кто хочет ознакомиться с описанием языка «из первых рук».

Перейти на страницу:
class="code">  else {

                     // обрабатываем операторы

  }

}

Функция istream::get() считывает отдельный символ в свой аргумент. Разделители при этом не игнорируются. Как и оператор >>, функция get() возвращает ссылку на свой поток istream, так что можно проверить его состояние.

При вводе отдельных символов мы обычно хотим классифицировать их: это символ или цифра? В верхнем регистре или в нижнем? И так далее. Для этого существует набор стандартных библиотечных функций.

 Обратите внимание на то, что категории классификации можно объединять с помощью оператора ИЛИ (||). Например, выражение isalnum(c) означает isalpha(c)||isdigit(c); иначе говоря, “является ли символ c буквой или цифрой?”

Кроме того, в стандартной библиотеке есть две полезные функции для уничтожения различий между символами, набранными в разных регистрах.

Это удобно, когда мы хотим устранить различия между символами, набранными в разных регистрах. Например, если пользователь ввел слова Right, right и rigHT, то, скорее всего, он имел в виду одно и то же (например, слово rigHT чаще всего является результатом нечаянного нажатия клавиши <Caps Lock>). Применив функцию tolower() к каждому символу в каждой из строк, мы можем получить одно и то же значение: right. Эту операцию можно выполнить с любым объектом класса string.

void tolower(string& s) // вводит строку s в нижнем регистре

{

  for (int i=0; i<s.length(); ++i) s[i] = tolower(s[i]);

}

 

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

11.7. Использование нестандартных разделителей

В этом разделе мы рассмотрим гипотетические примеры использования потоков 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<line.size(); ++i) // заменяем знаки пунктуации

                                  // пробелами

  switch(line[i]) {

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

    line[i] = ' ';

  }

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

                       // строку line

vector<string> 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; } // добавляет символ

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

  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;       // является ли поток чувствительным

                        // к регистру?

};

Как и в предыдущем примере, основная идея — ввести строку из потока istream как

Перейти на страницу:
Комментариев (0)