Поиск по сайту:

Как использовать 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()