Урок №208. Функционал класса istream

  Юрий  | 

  Обновл. 2 Июл 2019  | 

 5618

Библиотека iostream по своей сути довольно сложная, поэтому мы не сможем охватить её полностью в рамках этих уроках. Тем не менее, мы можем рассмотреть основной её функционал. В этом уроке мы разберёмся с классом istream.

Примечание: Весь функционал объектов, которые работают с потоками ввода/вывода, находится в пространстве имён std. Это означает, что вам нужно либо добавлять префикс std:: ко всем объектам/функциям ввода/вывода, либо использовать строчку using namespace std;.

Оператор извлечения

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

Что произойдёт, если пользователь введёт 20 символов? Правильно, переполнение. Одним из способов решения этой проблемы является использование манипуляторов. Манипулятор — это объект, который используется для изменения потока данных с использованием операторов извлечения (>>) или вставки (<<).

Мы уже работали с одним из манипуляторов: endl, который одновременно выводит символ новой строки и удаляет текущие данные из буфера. C++ предоставляет ещё один манипулятор — setw() (из заголовочного файла iomanip), который используется для ограничения количества символов, считываемых из потока. Для использования setw() вам нужно просто передать в качестве параметра максимальное количество символов для извлечения и вставить вызов этого манипулятора следующим образом:

Эта программа теперь прочитает только первые 11 символов из входного потока (+ один символ для нуль-терминатора). Все остальные символы останутся в потоке до следующего извлечения.

Извлечение и пробелы


Важный момент: оператор извлечения работает с «отформатированными» данными, т.е. он игнорирует все пробелы, символы табуляции и символ новой строки. Например:

Если пользователь введёт следующее:

Hello! My name is Anton

То оператор извлечения пропустит все пробелы и символы новой строки. Следовательно, результат выполнения программы выше:

Hello!MynameisAnton

Часто пользовательский ввод всё же нужен со всеми его пробелами. Для этого класс istream предоставляет множество функций. Одной из наиболее полезных является фунция get(), которая извлекает символ из входного потока. Вот та же программа, что выше, но уже с использованием get():

Теперь, если мы введём следующее:

Hello! My name is Anton

То получим:

Hello! My name is Anton

get() также имеет строковую версию, в которой можно указать максимальное количество символов для извлечения. Например:

Если мы введём следующее:

Hello! My name is Anton

То получим:

Hello! My n

Обратите внимание, программа считывает только первые 11 символов (+ нуль-терминатор). Остальные символы остаются во входном потоке.

Один важный нюанс: get() не считывает символ новой строки! Например:

Если пользователь введёт следующее:

Hello!

То получит:

Hello!

И программа сразу же завершит своё выполнение! Почему так? Почему не срабатывает второй ввод данных? Дело в том, что первый get() считывает символы до символа новой строки, а затем останавливается. Второй get() видит, что во входном потоке всё ещё есть данные и пытается их извлечь. Но первый символ, на который он натыкается — символ новой строки, поэтому происходит второй «Стоп!».

Для решения этой проблемы класс istream предоставляет функцию getline(), которая работает точно так же, как get(), но при этом может считывать символы новой строки:

Этот код работает точно так, как ожидается, даже если пользователь введёт строку с символом новой строки.

Если вам нужно узнать количество символов, извлечённых последним getline() — используйте gcount():

Результат:

Hello! My name is Anton
24 characters were read

Специальная версия getline() для std::string

Есть специальная версия getline(), которая находится вне класса istream и используется для считывания переменных типа std::string. Эта специальная версия getline(), которая не является членом ни ostream, ни istream, а подключается заголовочным файлом string. Например:

Ещё несколько полезных функций класса istream


Есть ещё несколько полезных функций класса istream, которые вы можете использовать:

   ignore() — игнорирует первый символ из потока.

   ignore(int nCount) — игнорирует первые nCount (количество) символов из потока.

   peek() — считывает символ из потока, при этом не удаляя его из потока.

   unget() — возвращает последний считанный символ обратно в поток, чтобы его можно было извлечь в следующий раз.

   putback(char ch) — помещает выбранный вами символ обратно в поток, чтобы его можно было извлечь в следующий раз.

istream содержит ещё множество других полезный функций и их вариаций, но это уже тема для отдельного туториала.

Оценить статью:

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (31 оценок, среднее: 4,84 из 5)
Загрузка...

Добавить комментарий

Ваш E-mail не будет опубликован. Обязательные поля помечены *