getline в C++: чтение строки
Привет! В этой статье мы поговорим о функции std::getline
из стандартной библиотеки C++. Эта функция позволяет нам прочитать строку из любого потока ввода.
Начнем мы с рассмотрения разных вариантов использования этой функции. Потом посмотрим на ошибки, которые эта функция может вернуть, а закончим упражнениями, которые помогут закрепить изученный материал.
Чтение строки из потока при помощи getline
getline
является частью заголовочного файла <string>
. У этой функции есть два варианта:
istream& getline (istream& is, string& str);
istream& getline (istream& is, string& str, char delim);
Эта функция читает поток is
до тех пор, пока не встретит разделительный символ. По умолчанию, это символ переноса строки \n
, но мы можем указать любой другой передав delim
.
Сохраняет прочитанное getline
в аргумент str
типа std::string
, который мы передаем ей в качестве второго аргумента. Все, что хранилось в строке, будет перезаписано прочитанным из потока ввода is
.
Возвращает функция поток, из которого была прочитана строка: первый параметр is
.
Давайте посмотрим на пример использования функции getline
:
#include <iostream>
using namespace std;
int main() {
string input;
getline(cin, input);
cout << "input = \"" << input << "\"" << endl;
return 0;
}
Вывод программы:
чтение до конца строки
input = "чтение до конца строки"
В этом простом примере мы прочитали из стандартного ввода первую строку. В данном случае это "чтение до конца строки"
.
Мы также можем поменять символ, до которого мы хотим читать строку:
#include <iostream>
using namespace std;
int main() {
string input;
getline(cin, input, ';');
cout << "input = \"" << input << "\"" << endl;
return 0;
}
первая часть; вторая часть
input = "первая часть"
Тут мы добавили третий аргумент - ';'
. Поэтому мы получили только то, что было до точки с запятой.
Мы также можем прочитать несколько строк одним вызовом getline
:
первая
часть;
input = "первая
часть"
Тут getline
продолжил чтение, даже после того, как первая строка закончилась, и началась вторая.
В каком случае следующая программа выведет строку “Прочитано успешно”?
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main() {
string input;
ifstream file("text.txt");
getline(file, input, '*');
if(input == "test")
cout << "Прочитано успешно" << endl;
else
cout << "Ошибка чтения" << endl;
return 0;
}
Предполагаем, что файл text.txt
существует и может быть прочитан. Каким содержимым должен обладать text.txt
?
В примерах выше мы считывали строку из стандартного ввода. Однако getline
позволяет нам читать с любого потока. Давайте теперь попробуем считать строку из файла.
Чтение из файла при помощи getline
Поскольку getline
может читать из любого потока ввода, давайте воспользуемся классом ifstream
для чтения из файла:
#include <fstream>
#include <iostream>
using namespace std;
int main() {
ifstream shows_file("shows.txt");
string show;
getline(shows_file, show);
cout << "show = \"" << show << "\"" << endl;
return 0;
}
shows.txt:
Rick and Morty
Stranger Things
Game of Thrones
Вывод программы:
show = "Rick and Morty"
В программе выше мы поменяли первый аргумент функции getline
с cin
(поток стандартного ввода) на shows_file
(поток ввода из файла).
Использование цикла while с getline
Зачем нам останавливаться на первом шоу? Давайте прочитаем все строки, которые есть в файле shows.txt. Для этого можно воспользоваться циклом while
:
#include <fstream>
#include <iostream>
using namespace std;
int main() {
ifstream shows_file("shows.txt");
string show;
while (getline(shows_file, show)) {
cout << "show = \"" << show << "\"" << endl;
}
return 0;
}
shows.txt:
Rick and Morty
Stranger Things
Game of Thrones
show = "Rick and Morty"
show = "Stranger Things"
show = "Game of Thrones"
Как вы можете видеть, для чтения всего файла достаточно использовать возвращаемое значение getline
в условии цикла while
. Так можно сделать, потому что в ifstream
реализован оператор конвертации в bool
.
При конвертации в bool
, ifstream
возвращает true
если можно продолжить чтение, false
если нельзя:
cout << "can read: " << (bool)shows_file << endl;
while (getline(shows_file, show)) {
cout << "show = \"" << show << "\"" << endl;
}
cout << "can read: " << (bool)shows_file << endl;
Тут мы только добавили конвертацию в bool
до и после цикла. Вывод программы:
can read: 1
show = "Rick and Morty"
show = "Stranger Things"
show = "Game of Thrones"
can read: 0
Ожидаемо, мы не можем продолжить чтение после “Game of Thrones” (в файле после этого больше ничего нет).
Ошибки при работе с getline
При работе с потоками ввода всегда могут произойти ошибки. Для того, чтобы понять, что произошло, можно воспользоваться флагами на потоке ввода:
stream.good()
: возвращаетtrue
если все прошло без ошибок.stream.eof()
: поток ввода закончился.stream.fail()
: произошла ошибка или невозможно интерпретировать прочитанное как строку.stream.bad()
: произошла ошибка.
Давайте добавим проверку на ошибку в наш пример выше:
#include <fstream>
#include <iostream>
using namespace std;
int main() {
ifstream shows_file("shows.txt");
string show;
istream& x = getline(shows_file, show);
while (getline(shows_file, show)) {
cout << "show = \"" << show << "\"" << endl;
}
if (shows_file.bad()) {
cerr << "Что-то пошло не так. 😭" << endl;
}
return 0;
}
Теперь, если произойдет ошибка при чтении сериалов, мы увидим это в консоли:
show = "Rick and Morty"
show = "Stranger Things"
Что-то пошло не так. 😭
Пример программы с использованием getline
Представьте себе, что вы хотите создать программу для хранения списка задач. Пользователь может вводить свои задачи, и программа будет их отображать. Для этого мы будем использовать std::getline
для получения задач от пользователя:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main() {
vector<string> todo_list; // Хранение списка задач
string input; // Строка для временного хранения пользовательского ввода
cout << "Добро пожаловать в программу ToDo List!" << endl;
cout << "Введите ваши задачи. Для завершения ввода введите 'exit'." << endl;
// Бесконечный цикл для ввода задач до тех пор, пока пользователь не введет 'exit'
while (true) {
cout << "Новая задача: ";
getline(cin, input); // Получение строки от пользователя
if (input == "exit") {
break; // Завершаем цикл, если пользователь ввел 'exit'
}
todo_list.push_back(input); // Добавляем задачу в список
}
cout << "\nВаш список задач:" << endl;
for (int i = 0; i < todo_list.size(); i++) {
cout << i + 1 << ". " << todo_list[i] << endl; // Отображаем задачи пользователя
}
return 0;
}
Этот пример иллюстрирует, как можно использовать std::getline
для чтения строк из консоли. Вы также можете адаптировать этот код для чтения данных из файлов или других источников ввода.
Упражнения для getline
-
Простой ввод данных с использованием
getline
:
Напишите программу на C++, которая запрашивает у пользователя имя и фамилию. Используйте функциюgetline
для считывания данных. После этого программа должна выводить приветствие с именем и фамилией пользователя. Например, “Привет, [Имя Фамилия]!“. -
Использование
getline
с разделителем:
Модифицируйте программу из первого пункта так, чтобы пользователь вводил имя и фамилию через точку с запятой. Ваша задача - считать введенные данные и разделить их на имя и фамилию, используяgetline
с соответствующим разделителем. -
Чтение из файла с использованием
getline
:
Создайте текстовый файлstudents.txt
с именами студентов, каждое имя на новой строке. Напишите программу, которая считывает все имена из файла и выводит их на экран в формате: “Студент [номер]: [Имя]“.
Если хотите всегда быть в курсе последних новостей в мире программирования и IT, подписываетесь на мой Telegram-канал, где я делюсь свежими статьями, новостями и полезными советами. Буду рад видеть вас среди подписчиков!
Обсуждение