« std::getline() mi nie działa!, pytanie/odpowiedź »
Odpowiedź na częste pytanie, dlaczego mieszanie >> i std::getline() nie działa zgodnie z oczekiwaniami. (pytanie/odpowiedź)
Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?
Zarejestruj się!
Autor: pekfos
FAQ

std::getline() mi nie działa!

[pytanie/odpowiedź] Odpowiedź na częste pytanie, dlaczego mieszanie >> i std::getline() nie działa zgodnie z oczekiwaniami.

Działa, tylko nie robi tego, czego oczekujesz

To jest typowy kod, który sprawia problemy:
C/C++
#include <iostream>
#include <string>

int main()
{
    int liczba;
    std::string tekst;
   
    std::cout << "Podaj liczbe: ";
    std::cin >> liczba;
   
    std::cout << "Podaj tekst: ";
    std::getline( std::cin, tekst );
   
    std::cout << "liczba = " << liczba << "; tekst = \"" << tekst << "\"\n";
}
Program pyta o liczbę, podajemy przykładowo 5
Podaj liczbe: 5
Podaj tekst: liczba = 5; tekst = ""
I wczytało 5, ale std::getline() 'nie zadziałało' i wczytało pusty łańcuch, bez zatrzymania programu w oczekiwaniu na dane. A to dlatego, że std::getline() miało już dane do odczytania. Podajmy dane wejściowe inaczej:
Podaj liczbe: 5ala ma kota
Podaj tekst: liczba = 5; tekst = "ala ma kota"
Wciąż się program nie zatrzymał na podawaniu tekstu przez użytkownika, ale jak widać tekst został wczytany poprawnie. Problem jest w tym, jak te dwie metody są użyte razem. Wczytywanie operatorem >> wczytuje do białego znaku (lub błędnego znaku), w tym przypadku do znaku nowej linii, ale zostawia ten znak w strumieniu. Następne użycia tego operatora ignorują białe znaki poprzedzające dane. std::getline() wczytuje jak leci, aż dojdzie do końca pliku, lub ustawionego znaku kończącego - domyślnie znaku nowej linii. Nie dołącza znaku kończącego do wczytanych danych, ale usuwa go ze strumienia.
Dlatego jeśli std::getline() jest użyte po >>, funkcja może się zakończyć natychmiastowo, poprzez zostawiony znak nowej linii. Rozwiązanie to usunąć resztę linii, wraz ze znakiem nowej linii, ze strumienia.
C/C++
#include <iostream>
#include <string>
#include <limits>

int main()
{
    int liczba;
    std::string tekst;
   
    std::cout << "Podaj liczbe: ";
    std::cin >> liczba;
   
    std::cin.ignore( std::numeric_limits < std::streamsize >::max(), '\n' );
   
    std::cout << "Podaj tekst: ";
    std::getline( std::cin, tekst );
   
    std::cout << "liczba = " << liczba << "; tekst = \"" << tekst << "\"\n";
}
Podaj liczbe: 5
Podaj tekst: ala ma kota
liczba = 5; tekst = "ala ma kota"
Podaj liczbe: 123 wszystko dalej zostanie pominiete
Podaj tekst: zostanie wczytane tylko to
liczba = 123; tekst = "zostanie wczytane tylko to"