Leggere una riga intera
cin >> text legge una sola parola: si ferma al primo spazio. Per leggere tutto ciò che l'utente ha digitato fino al tasto Invio, spazi compresi, usa std::getline dall'header <string>:
#include <iostream>
#include <string>
int main() {
std::string name;
std::cout << "Full name: ";
std::getline(std::cin, name);
std::cout << "Hello, " << name << "!\n";
}
Digitando Ada Lovelace viene stampato Hello, Ada Lovelace!. Con std::cin >> name verrebbe stampato Hello, Ada! e Lovelace resterebbe in attesa nell'input.
La firma è:
std::istream& std::getline(std::istream& input, std::string& text);
std::istream& std::getline(std::istream& input, std::string& text, char delim);
inputè qualsiasi stream di input:std::cin, un file aperto constd::ifstreamo unastd::istringstreamcostruita da una stringa.textviene sostituito (non esteso) con i caratteri letti.delimè il carattere che termina la lettura. Il valore predefinito è'\n'. Il delimitatore viene rimosso dallo stream e non viene memorizzato intext.- Il valore restituito è lo stream stesso, ed è questo che ti permette di usarlo in una condizione.
Dato che getline funziona allo stesso modo su qualsiasi stream di input, gli esempi eseguibili di questa pagina leggono da una std::istringstream che contiene un testo fisso. Così l'output è prevedibile senza dover digitare nulla. Per leggere invece dalla tastiera, sostituisci la variabile dello stream con std::cin.
Output:
[Ada Lovelace]
[Alan Turing]
Le parentesi quadre mostrano che l'a capo non fa parte di nessuna delle due stringhe.
getline dopo cin >> restituisce una stringa vuota
È il problema più comune con getline. Leggi un numero con >>, poi una riga con getline, e il getline sembra venire saltato:
Output:
age: 30
city: []
input >> age legge i caratteri 30 e si ferma al primo carattere che non può far parte di un numero, l'a capo. Quell'a capo resta nello stream. getline legge poi fino all'a capo successivo, ne trova uno subito e restituisce una stringa vuota. Con std::cin l'effetto è che il programma non si ferma mai ad aspettare la seconda risposta.
Ci sono due soluzioni standard. Entrambe vanno tra il >> e il getline.
Soluzione 1: scarta il resto della riga con ignore.
Output:
age: 30
city: [Paris]
ignore(n, '\n') butta via caratteri finché non ha rimosso un a capo oppure n caratteri, a seconda di cosa arriva prima. Passare il più grande std::streamsize possibile significa "fino all'a capo, per quanto lontano sia". Rimuove anche tutto ciò che l'utente ha digitato dopo il numero sulla stessa riga, come spazi finali. Con la tastiera la riga è std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');, e richiede #include <limits>.
Un semplice std::cin.ignore() scarta esattamente un carattere. Funziona quando l'a capo segue direttamente il numero, e fallisce non appena c'è uno spazio prima.
Soluzione 2: salta gli spazi iniziali con std::ws.
Output:
age: 30
city: [Paris]
std::ws è un manipolatore che consuma tutti gli spazi bianchi (spazi, tabulazioni, a capo) nella posizione corrente. input >> std::ws restituisce lo stream, quindi può essere passato direttamente a getline. Salta anche le righe vuote e gli spazi iniziali, il che è comodo per nomi e città ma sbagliato quando gli spazi iniziali o una riga vuota sono input significativi. In quel caso usa ignore.
Leggere fino alla fine dell'input
getline restituisce lo stream, e uno stream diventa false quando una lettura fallisce. Quando non ci sono più righe, getline fallisce, quindi un ciclo while attorno a esso legge ogni riga e si ferma alla fine:
Output:
1: [apples 3]
2: [bread 1]
3: []
4: [milk 2]
read 4 lines
Due dettagli di quell'output:
- Una riga vuota è comunque una lettura riuscita. Produce una stringa vuota e il ciclo continua. Solo il raggiungimento della fine dell'input lo ferma.
- L'ultima riga non ha bisogno di un a capo finale. Se il testo terminasse con
milk 2senza\n,getlinela restituirebbe comunque, e la chiamata successiva fallirebbe.
Con std::cin, lo stesso ciclo legge finché l'input non termina. Questo succede quando l'input viene passato da un file (./program < data.txt), oppure quando l'utente preme Ctrl+D su macOS e Linux, o Ctrl+Z e poi Invio su Windows.
Evita lo schema while (!input.eof()) { std::getline(input, line); ... }. eof() diventa vero solo dopo che una lettura ha già raggiunto la fine, quindi il corpo viene eseguito una volta in più con una lettura fallita e una line vecchia. Metti invece la chiamata a getline nella condizione.
Leggere un file riga per riga
I file usano lo stesso ciclo. Apri il file con std::ifstream da <fstream>, controlla che si sia aperto e leggi:
Output:
1. Ada 92
2. Grace 88
3. Alan 95
if (!file) intercetta un file mancante o un percorso sbagliato prima del ciclo. Senza, il ciclo legge semplicemente zero righe, il che sembra un file vuoto invece di un errore. Il file si chiude automaticamente quando file esce dallo scope alla fine di main.
I file salvati su Windows terminano ogni riga con \r\n. Quando un file del genere viene letto su Linux o macOS, getline rimuove il \n ma lascia il \r, quindi ogni riga termina con un ritorno a capo invisibile che rompe i confronti come line == "done". Rimuovilo dopo la lettura:
if (!line.empty() && line.back() == '\r') {
line.pop_back();
}
Usare un delimitatore personalizzato
Il terzo argomento cambia il carattere che termina ogni lettura. Un uso comune è dividere una riga sulle virgole. Leggi prima la riga, poi dividila tramite una std::istringstream:
Output:
fields: 3
[Ada Lovelace]
[36]
[London]
La virgola viene rimossa dallo stream e non memorizzata, come succede all'a capo nella forma predefinita. Nota che con un delimitatore personalizzato l'a capo è un carattere qualsiasi. Se chiami std::getline(file, field, ',') direttamente su un file di più righe, l'ultimo campo di una riga e il primo della successiva ti arrivano uniti, come in "London\nGrace Hopper". Leggere una riga alla volta e dividere ogni riga separatamente evita il problema. La pagina sugli string stream tratta std::istringstream più nel dettaglio, compresa la conversione di campi come "36" in numeri.
std::getline e cin.getline
Esiste anche una funzione membro con un nome simile:
char buffer[20];
std::cin.getline(buffer, 20); // funzione membro, array di char a dimensione fissa
std::string text;
std::getline(std::cin, text); // funzione libera, std::string
cin.getline scrive in un array di char e memorizza al massimo size - 1 caratteri più il terminatore '\0'. Una riga più lunga mette lo stream in uno stato di errore, e ogni lettura successiva viene saltata finché non chiami std::cin.clear(). std::getline con una std::string non ha limiti di lunghezza da gestire. Usalo, a meno che tu non stia lavorando con un'API che richiede un array di char.
Errori comuni
- Mescolare
>>egetlinesenza eliminare l'a capo. Aggiungiignore(...)oppure usastd::wstra i due. La pagina su input e output mostra lo stesso problema constd::cine come riprendersi quando una lettura numerica fallisce. - Chiamare
getline(std::cin, number)con unint.getlinelegge solo in unastd::string. Leggi la riga, poi convertila constd::stoio con unastd::istringstream. - Ciclare su
eof(). Verifica direttamente la chiamata agetline:while (std::getline(input, line)). - Dimenticare
#include <string>.std::getlineper le stringhe è dichiarato in<string>. Alcuni compilatori lo lasciano passare tramite<iostream>, e il codice poi fallisce con un altro compilatore. - Non controllare che un file si sia aperto. Un percorso sbagliato fa fallire
std::ifstreamin silenzio e il ciclo di lettura viene eseguito zero volte.
Domande frequenti
Cosa fa getline in C++?
std::getline(stream, text) legge caratteri da stream nella std::string text finché non incontra un a capo, poi rimuove quell'a capo dallo stream senza memorizzarlo. A differenza di cin >> text, conserva gli spazi, quindi legge una riga intera come un nome completo o una frase.
Perché getline viene saltato dopo cin >> in C++?
cin >> number smette di leggere all'a capo che hai digitato dopo il numero e lascia quell'a capo nel buffer di input. Il getline successivo lo trova subito e restituisce una stringa vuota. Scartalo prima con std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');, oppure chiama std::getline(std::cin >> std::ws, text) per saltare gli spazi iniziali.
Come si usa getline con un delimitatore diverso dall'a capo?
Passa il delimitatore come terzo argomento: std::getline(stream, field, ','). Legge fino alla virgola successiva, memorizza il testo che la precede e scarta la virgola. Gli a capo vengono allora trattati come caratteri normali, quindi di solito si combina con una std::stringstream costruita da una singola riga.
Come si legge un file riga per riga in C++?
Aprilo con std::ifstream file("data.txt"); e cicla con while (std::getline(file, line)) { ... }. getline restituisce lo stream, che diventa false quando non ci sono più righe, quindi il ciclo si ferma alla fine del file.
Qual è la differenza tra cin.getline e getline?
std::getline(std::cin, text) è una funzione libera che legge in una std::string, che cresce per contenere qualsiasi riga. std::cin.getline(buffer, size) è una funzione membro che legge in un array di char di dimensione fissa e fallisce se la riga è più lunga di size - 1 caratteri. Usa std::getline con std::string, a meno che tu non abbia un motivo per usare array grezzi.