Come C++ comunica con la console
C++ gestisce l'I/O da console tramite gli stream dell'header <iostream>. Scrivi verso l'esterno con cout (output di caratteri) e leggi dall'utente con cin (input di caratteri). Usano due operatori che hai già visto come shift di bit, qui riutilizzati:
<<è l'operatore di inserimento: manda i dati dentrocout.>>è l'operatore di estrazione: tira fuori i dati dacine li mette in una variabile.
Un modo comodo per ricordare la direzione: le frecce puntano nel verso in cui scorrono i dati. Ora che sai tenere del testo nelle stringhe, vediamo come far entrare e uscire quel testo dal tuo programma.
Stampare con cout
cout manda sull'output standard tutto ciò che vi inserisci. Puoi concatenare più << in una sola istruzione, mescolando liberamente testo, numeri e variabili.
Ogni << aggiunge alla stessa riga finché non inserisci un ritorno a capo. Hai due modi per farlo: '\n' inserisce un carattere di nuova riga, mentre endl inserisce un ritorno a capo e svuota il buffer sullo schermo. Lo svuotamento ha un costo reale, quindi dentro un ciclo che stampa migliaia di righe preferisci '\n': lo stream si svuota da solo quando serve (e sempre all'uscita del programma).
// Va bene per un messaggio occasionale:
cout << "Done" << endl;
// In un ciclo critico preferisci questo, senza flush forzato a ogni iterazione:
for (int i = 0; i < 1000000; ++i)
cout << i << '\n';
Leggere con cin e >>
cin >> variable legge un token delimitato da spazi e lo converte nel tipo della variabile. Salta eventuali spazi o ritorni a capo iniziali, poi si ferma allo spazio successivo.
Poiché >> si ferma agli spazi, è ottimo per numeri singoli e parole singole ma inutile per una frase intera: cin >> word sull'input hello world legge solo hello e lascia world nel buffer per la lettura successiva.
Leggere una riga intera con getline
Per catturare una riga intera, spazi compresi, usa getline(cin, line), che legge tutto fino al tasto Invio in una std::string.
È lo strumento giusto ogni volta che l'input può contenere spazi: nomi, indirizzi, frasi. C'è solo una trappola che ti aspetta non appena mescoli getline con >>.
La pagina su getline tratta la funzione nel dettaglio: delimitatori personalizzati, lettura fino alla fine dell'input e lettura di un file riga per riga con std::ifstream.
La trappola del ritorno a capo tra cin e getline
È il bug di I/O più comune in C++. Quando fai cin >> n, l'estrazione legge il numero ma lascia il ritorno a capo (il tasto Invio che hai premuto) nel buffer di input. Il getline successivo vede subito quel ritorno a capo rimasto, considera la riga già finita e ti restituisce una stringa vuota, senza mai fermarsi ad aspettare l'input.
int age;
string city;
cin >> age; // scrivi 30 e premi Invio; '\n' resta nel buffer
getline(cin, city); // legge il '\n' rimasto -> city è "" (vuota!)
La soluzione è scartare quel ritorno a capo rimasto con cin.ignore dopo il >> e prima del getline:
cin.ignore(numeric_limits<streamsize>::max(), '\n') salta caratteri finché non ha consumato un ritorno a capo (o raggiunto la fine dell'input). È la versione robusta: la forma più breve cin.ignore() scarta un solo carattere, e non funziona più se l'utente ha scritto spazi in più dopo il numero. Prendi l'abitudine di usare la forma completa.
Quando l'input fallisce
Se l'utente scrive lettere dove ti aspettavi un numero, l'estrazione fallisce: cin entra in uno stato di errore e la variabile di destinazione resta invariata (viene impostata a 0 da C++11). Peggio ancora, una volta che cin è in stato di errore, ogni lettura successiva viene saltata in silenzio, e puoi finire in un ciclo infinito.
Il recupero richiede sempre due passaggi: cin.clear() azzera i flag di errore così lo stream torna utilizzabile, e cin.ignore(...) butta via i caratteri incriminati ancora bloccati nel buffer. Se salti l'ignore, l'input errato resta lì e il >> successivo fallisce di nuovo: il classico ciclo infinito. Controllare cin >> n direttamente nella condizione funziona perché lo stream si converte in false quando è in stato di errore.
Errori comuni da evitare
- Usare
cin >> sper una frase. Si ferma al primo spazio. Usagetlineper tutto ciò che contiene spazi. - Dimenticare
cin.ignoretra>>egetline. Il ritorno a capo rimasto ti dà una riga vuota. Svuota prima il buffer. - Usare
endlovunque. Ognuno forza uno svuotamento. Usa'\n'di default e riservaendla quando l'output deve davvero comparire subito. - Ignorare un
cinfallito. Delle lettere in una lettura numerica lascianocinbloccato; prima di leggere di nuovo fai sempreclear()e poiignore().
Domande frequenti
Perché getline salta l'input subito dopo aver usato cin in C++?
cin >> x legge il numero ma lascia nel buffer il ritorno a capo che hai premuto. Il getline successivo legge fino a quel ritorno a capo rimasto e restituisce subito una stringa vuota. Eliminalo prima con cin.ignore(numeric_limits<streamsize>::max(), '\n'); dopo il >> e prima del getline.
Qual è la differenza tra endl e \n in C++?
Entrambi terminano la riga, ma endl in più svuota il buffer di output sullo schermo, mentre '\n' inserisce solo un ritorno a capo. Lo svuotamento ha un costo: in un ciclo stretto preferisci '\n' e lascia che lo stream si svuoti da solo. Usa endl solo quando ti serve davvero che l'output compaia subito.
Come leggo un'intera riga di testo, spazi compresi, in C++?
Usa getline(cin, line), non cin >> line. L'operatore >> si ferma al primo spazio, quindi prende una sola parola. getline legge tutto fino al tasto Invio in una std::string, spazi compresi.