23.4 – Классы потоков для работы со строками
До сих пор все примеры ввода/вывода, которые вы видели, касались записи в cout
или чтения из cin
. Однако есть еще один набор классов, называемых классами потоков для строк, которые позволяют использовать знакомые операторы вставки (<<
) и извлечения (>>
) для работы со строками. Подобно istream
и ostream
, строковые потоки предоставляют буфер для хранения данных. Однако, в отличие от cin
и cout
, эти потоки не подключены к каналу ввода/вывода (например, к клавиатуре, монитору и т.д.). Одно из основных применений строковых потоков – это буферизация вывода для последующего отображения или построчная обработка ввода.
Для строк существует шесть классов потоков: istringstream
(производный от istream
), ostringstream
(производный от ostream
) и stringstream
(производный от iostream
), которые используются для чтения и записи строк символов с нормальной шириной. wistringstream
, wostringstream
и wstringstream
используются для чтения и записи строк широких символов. Чтобы использовать строковые потоки, вам необходимо включить заголовок sstream
.
Есть два способа передать данные в строковый поток:
1. Использовать оператор вставки (<<
):
std::stringstream os;
os << "en garde!" << '\n'; // вставить "en garde!" в строковый поток
2. Использовать функцию str(string)
, чтобы установить значение буфера:
std::stringstream os;
os.str("en garde!"); // установить буфер stringstream в значение "en garde!"
Есть два аналогичных способа получить данные из строкового потока:
1. Использовать функцию str()
для получения результатов буфера:
std::stringstream os;
os << "12345 67.89" << '\n';
cout << os.str();
Этот код печатает:
12345 67.89
2. Использовать оператор извлечения (>>
):
std::stringstream os;
os << "12345 67.89"; // вставляем строку чисел в поток
std::string strValue;
os >> strValue;
std::string strValue2;
os >> strValue2;
// выводим числа, разделяя их через тире
std::cout << strValue << " - " << strValue2 << '\n';
Эта программа печатает:
12345 - 67.89
Обратите внимание, что оператор >>
выполняет итерацию по строке – каждое последующее использование >>
возвращает следующее извлекаемое значение в потоке. str()
, напротив, возвращает всё значение потока, даже если для потока уже использовался оператор >>
.
Преобразование между строками и числами
Поскольку операторы вставки и извлечения знают, как работать со всеми базовыми типами данных, мы можем использовать их для преобразования строк в числа и наоборот.
Во-первых, давайте посмотрим, как преобразовать числа в строку:
std::stringstream os;
int nValue{ 12345 };
double dValue{ 67.89 };
os << nValue << ' ' << dValue;
std::string strValue1, strValue2;
os >> strValue1 >> strValue2;
std::cout << strValue1 << ' ' << strValue2 << '\n';
Этот код печатает:
12345 67.89
Теперь давайте, преобразуем строку цифр в число:
std::stringstream os;
os << "12345 67.89"; // вставляем строку цифр в поток
int nValue;
double dValue;
os >> nValue >> dValue;
cout << nValue << ' ' << dValue << '\n';
Эта программа печатает:
12345 67.89
Очистка строкового потока для повторного использования
Есть несколько способов очистить буфер строкового потока.
1. Установить его в значение пустой строки с помощью str()
с пустой строкой в стиле C.
std::stringstream os;
os << "Hello ";
os.str(""); // стереть буфер
os << "World!";
std::cout << os.str();
2. Установить его в значение пустой строки с помощью str()
с пустым объектом std::string
:
std::stringstream os;
os << "Hello ";
os.str(std::string{}); // стереть буфер
os << "World!";
cout << os.str();
Обе эти программы дают следующий результат:
World!
При очистке строкового потока также обычно рекомендуется вызвать функцию clear()
:
std::stringstream os;
os << "Hello ";
os.str(""); // стереть буфер
os.clear(); // сбросить флаги ошибок
os << "World!";
std::cout << os.str();
clear()
сбрасывает все флаги ошибок, которые могли быть установлены, и возвращает поток обратно в состояние нормы. Подробнее о состоянии потоков и флагах ошибок мы поговорим в следующем уроке.