Как использовать std::getline() в С++?
В этой статье мы рассмотрим использование функции std::getline() в C++. Это очень удобная функция, если вы хотите прочитать символы из входного потока.
Давайте выясним, как мы можем использовать это правильно, используя несколько наглядных примеров.
Базовый синтаксис std::getline() в C++
Эта функция считывает символы из входного потока и помещает их в строку.
Нам нужно импортировать заголовочный файл <string>
, так как getline()
является частью этого файла.
Хотя для этого требуются аргументы шаблона, мы сосредоточимся на строковых входных данных (символах), так как выходные данные записываются в строку.
istream& getline(istream& input_stream, string& output, char delim);
Это говорит о том, что getline()
принимает входной поток и записывает его в output
. Разделители можно дополнительно указать с помощью delim
.
Это также возвращает ссылку на тот же входной поток, но в большинстве случаев нам не нужен этот дескриптор.
Использование std::getline() для чтения из входных потоков
Теперь, когда мы знаем базовый синтаксис, давайте получим ввод из std::cin
(стандартный поток ввода) в строку.
#include <iostream>
#include <string>
int main() {
// Define a name (String)
std::string name;
std::cout << "Enter the name: ";
// Get the input from std::cin and store into name
std::getline(std::cin, name);
std::cout << "Hello " << name << "!\n";
return 0;
}
Выход
Enter the name: JournalDev
Hello JournalDev!
Действительно, мы смогли без проблем получить ввод из std::cin
!
Давайте теперь возьмем другой пример, где у нас есть файл input.txt
, содержащий следующее содержимое:
$ cat input.txt
Hello from JournalDev
Second Line of file
Last line
Давайте теперь прочитаем файл построчно и сохраним их в виде вектора строк!
Основная логика будет заключаться в том, чтобы продолжать чтение с помощью std::getline(file)
, пока входной поток не достигнет EOF.
Мы можем легко написать это, используя этот формат:
std::ifstream infile("input.txt");
// Temporary buffer
std::string temp;
// Get the input from the input file until EOF
while (std::getline(infile, temp)) {
// Add to the list of output strings
outputs.push_back(temp);
}
Полный код показан ниже:
#include <iostream>
#include <string>
#include <vector> // For std::vector
#include <fstream> // For std::ifstream and std::ofstream
int main() {
// Store the contents into a vector of strings
std::vector<std::string> outputs;
std::cout << "Reading from input.txt....\n";
// Create the file object (input)
std::ifstream infile("input.txt");
// Temporary buffer
std::string temp;
// Get the input from the input file until EOF
while (std::getline(infile, temp)) {
// Add to the list of output strings
outputs.push_back(temp);
}
// Use a range-based for loop to iterate through the output vector
for (const auto& i : outputs)
std::cout << i << std::endl;
return 0;
}
Выход
Reading from input.txt....
Hello from JournalDev
Second Line of file
Last line
Использование std::getline() в C++ для разделения ввода с помощью разделителей
Мы также можем использовать аргумент delim
, чтобы заставить функцию getline разделить ввод с точки зрения символа-разделителя.
По умолчанию разделителем является \n
(новая строка). Мы можем изменить это, чтобы getline()
разделял ввод на основе других символов!
Давайте установим символ разделителя на символ пробела в приведенном выше примере и посмотрим, что произойдет!
#include <iostream>
#include <string>
#include <vector> // For std::vector
#include <fstream> // For std::ifstream and std::ofstream
int main() {
// Store the contents into a vector of strings
std::vector<std::string> outputs;
std::cout << "Reading from input.txt....\n";
// Create the file object (input)
std::ifstream infile("input.txt");
// Temporary buffer
std::string temp;
// Get the input from the input file until EOF
while (std::getline(infile, temp, ' ')) {
// Add to the list of output strings
outputs.push_back(temp);
}
// Use a range-based for loop to iterate through the output vector
for (const auto& i : outputs)
std::cout << i << std::endl;
return 0;
}
Выход
Reading from input.txt....
Hello
from
JournalDev
Second
Line
of
file
Last
line
Действительно, теперь у нас есть строка, разделенная пробелами!
Возможные проблемы с использованием std::getline()
Хотя std::getline()
— очень полезная функция, могут возникнуть некоторые проблемы, с которыми вы можете столкнуться при ее использовании вместе с некоторыми входными потоками, такими как std::cin
. .
std::getline()
не игнорирует начальные пробелы и символы новой строки.
Из-за этого, если вы вызовете std::cin >> var;
непосредственно перед getline()
, во входном потоке останется символ новой строки после чтения входная переменная.
Таким образом, если вы вызовете getline()
сразу после cin
, вместо этого вы получите новую строку, так как это первый символ во входном потоке!
Чтобы избежать этого, просто добавьте фиктивный std::getline()
для использования этого символа новой строки!
В приведенной ниже программе показана проблема с использованием cin
непосредственно перед getline()
.
#include <iostream>
#include <string>
int main() {
// Define a name (String)
std::string name;
int id;
std::cout << "Enter the id: ";
std::cin >> id;
std::cout << "Enter the Name: ";
// Notice std::cin was the last input call!
std::getline(std::cin, name);
std::cout << "Id: " << id << std::endl;
std::cout << "Name: " << name << "\n";
return 0;
}
Выход
Enter the id: 10
Enter the Name: Id: 10
Name:
Заметьте, я вообще не смог ввести имя! Поскольку во входном потоке была конечная новая строка, она просто взяла ее, а так как это разделитель, чтение прекратилось!
Теперь давайте добавим фиктивный вызов std::getline()
непосредственно перед нашим фактическим вызовом std::getline()
.
#include <iostream>
#include <string>
int main() {
// Define a name (String)
std::string name;
int id;
std::cout << "Enter the id: ";
std::cin >> id;
std::cout << "Enter the Name: ";
// Add a dummy getline() call
std::getline(std::cin, name);
// Notice std::cin was the last input call!
std::getline(std::cin, name);
std::cout << "Id: " << id << std::endl;
std::cout << "Name: " << name << "\n";
return 0;
}
Выход
Enter the id: 10
Enter the Name: JournalDev
Id: 10
Name: JournalDev
Наконец-то мы исправили нашу ошибку! Надеюсь, это заставит вас немного подумать, прежде чем слепо использовать std::getline()
.
К сожалению, в C++ нет элегантных методов для ввода данных, поэтому приходится обходиться тем, что есть!
Заключение
В этой статье мы узнали об использовании std::getline() в C++. Мы также рассмотрим несколько примеров, иллюстрирующих возможности и недостатки этой функции.
Рекомендации
- страница cppreference.com std::getline()
- Вопрос StackOverflow по использованию std::getline()