De ce getline citește o linie goală după cin în C++
Repară citirea unei linii după un număr în C++. Înțelege ce rămâne în flux, când folosești ignore și de ce ws poate șterge date importante.
În acest material
Dacă getline pare să sară peste text imediat după cin >> n, verifică separatorul rămas în flux. Citirea numărului se oprește înaintea caracterelor care nu mai fac parte din el. Un sfârșit de linie poate rămâne disponibil pentru următoarea citire, iar getline îl întâlnește imediat.
Reproduce problema cu două linii
Presupune că intrarea este numărul 3 pe prima linie și Ana are mere pe a doua. După citirea lui 3, sfârșitul primei linii este încă în flux. getline citește până la acel delimitator și obține textul gol. Nu este o problemă a tastaturii și nici o dovadă că string nu poate păstra spații.
Soluția depinde de formatul intrării. Dacă numărul ocupă prima linie, iar textul începe pe următoarea, poți elimina restul primei linii, inclusiv delimitatorul. Dacă textul este pe aceeași linie cu numărul, aceeași operație l-ar arunca. Citește cerința înainte să adaugi ignore.
După cin care citește 3, separatorul de linie rămâne în flux; getline îl întâlnește imediat și produce un text gol.Mărește schema ↗
Variantă completă cu char[]
Următorul program presupune un număr pe prima linie și un text în codificarea ASCII, cu litere latine fără diacritice, cifre și semne obișnuite, de cel mult 100 de caractere pe a doua. Textul poate fi gol și poate începe cu spații. Capacitatea 101 include locul pentru terminator.
#include <iostream>
#include <limits>
using namespace std;
int main() {
int n; char text[101];
cin >> n;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cin.getline(text,101);
cout << n << ':' << text << '\n';
}
Aceeași intrare, cu std::string
std::string gestionează memoria textului, dar nu schimbă poziția din flux. De aceea operația de eliminare a restului primei linii rămâne necesară.
#include <iostream>
#include <limits>
#include <string>
using namespace std;
int main() {
int n; string text;
cin >> n;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
getline(cin,text);
cout << n << ':' << text << '\n';
}
De ce nu ajunge întotdeauna ignore() fără argumente
Apelul fără argumente elimină un singur caracter. Dacă după număr sunt spații înaintea sfârșitului de linie, elimină doar primul spațiu. Forma cu numeric_limits<streamsize>::max() și delimitatorul de linie consumă tot restul acelei linii.
O altă soluție întâlnită este getline(cin >> ws, text). Ea elimină toate caracterele albe inițiale, inclusiv linii goale și spații semnificative. Este potrivită numai dacă formatul permite ignorarea lor. Nu este echivalentă cu păstrarea exactă a următoarei linii.
Trei teste care fac diferența
- Numărul 3, apoi
Ana are mere: ieșirea este3:Ana are mere. - Numărul 3 urmat de spații pe prima linie, apoi
Ana: cele două spații dinaintea numelui trebuie păstrate după două puncte. - Numărul 3, apoi o linie goală: ieșirea este
3:. O soluție cuwspoate continua să aștepte alt text în loc să păstreze linia goală.
Dacă citirea numărului eșuează, problema este diferită: fluxul intră într-o stare de eroare. Nu masca o intrare invalidă prin apeluri repetate la ignore. Programele de mai sus presupun date conforme cu formatul declarat.
Pentru baza necesară, citește citirea datelor și char[], string și getline. Pentru intrări pe mai multe linii din fișiere, continuă cu citirea fișierelor text. Comportamentul delimitatorului și al lui ignore este descris în specificația C++ pentru citirea neformatată.
Întrebări frecvente
De ce citește getline o linie goală după cin?
După cin >> n, separatorul de sfârșit de linie poate rămâne în flux. Următorul getline îl întâlnește imediat și produce un text gol, fără să ajungă la linia următoare.
Când folosesc cin.ignore înainte de getline?
Când formatul spune că numărul este pe o linie, iar textul pe următoarea, elimină restul primei linii până la separator. Dacă textul este pe aceeași linie cu numărul, această operație l-ar elimina și pe el.
Este getline cu ws potrivit pentru linii goale?
Nu dacă trebuie să păstrezi liniile goale sau spațiile inițiale. ws consumă caracterele albe de la început; alegerea lui trebuie făcută după formatul intrării, nu ca remediu universal pentru citire.