2012-07-12 2 views
9

Ho il seguente codice:Problema con cin quando gli spazi sono immessi, utilizzando classe string

main.cpp

#include <iostream> 
#include <string> 

using namespace std; 

string name; 
string age; 

int main() { 
    cout <<"Name: "; 
    cin >> name; 
    cout << endl; 
    cout <<"Age: "; 
    cin >> age; 
    cout << endl; 
    cout << "Your name is " << name << ", and you are " << age << " years old." << endl; 
    cout << "Press enter to close this application" << endl; 
    getchar(); 
    return 0; 
} 

ho notato che se metto uno spazio nel mio input per nome che ha vinto Mi dà la possibilità di inserire il nome, e vedrà la voce dopo lo spazio come età. Mi scuso se questo è un errore da principiante, che probabilmente è. In precedenza ho programmato Java e ho deciso che volevo passare a C++ perché si adattava meglio alle mie esigenze. Probabilmente ho anche formato il mio codice in modo strano ai tuoi standard, correggilo se lo desideri.

Screenshot of console

Ho anche notato un altro errore, qualcosa che non ho mai avuto problemi con in Java. Non riesco a capire come impedirgli di chiudersi all'istante quando termina l'elaborazione. Ho sentito che puoi usare "system. (" Pause "), ma mi è stato anche detto di non usarlo. Sono davvero confuso su cosa usare.Ho sentito usare getchar() ;, ma non sembra di fare nulla.

Qualsiasi aiuto sarebbe molto apprezzato, come io sono un principiante assoluto quando si tratta di C++.

+0

@chris Vorrei scegliere il tuo commento come risposta, ma non penso davvero che mi lascerebbe. Grazie per l'aiuto. Ti dispiacerebbe ripubblicare quello o qualcosa come una risposta in modo da poterlo selezionare? –

+0

Ho deciso prima del tuo commento di dare una risposta più dettagliata. È lì (e si spera non abbia errori impercettibili) se vuoi leggerlo. – chris

+0

Oh, e il motivo per cui il 'getchar' non funziona è la stessa ragione per cui il mio primo esempio per la sostituzione di' system ("pause") 'non funziona. È spiegato nella risposta. – chris

risposta

13

Ecco cosa sta accadendo con il buffer di ingresso quando si esegue il programma:

std::cin >> name; 

Stai aspettando l'input. Quando si entra "Ryan Cleary", e premere invio, il buffer di input contiene:

Ryan Cleary\n 

Ora il vostro cin legge l'input come normale, fermandosi a spazi bianchi, lasciando il buffer in questo modo:

Cleary\n 

Nota lo spazio iniziale, poiché si ferma dopo aver letto Ryan. La tua prima variabile ora contiene Ryan. Se, tuttavia, si desidera il nome completo, utilizzare std::getline. Leggerà fino a una nuova riga, non solo uno spazio bianco. Ad ogni modo, continuando su:

std::cin >> age; 

Ora stai ricevendo un altro input. C'è già qualcosa lì, però. Si salta gli spazi fino a quando si può iniziare la lettura, lasciando il buffer con solo:

\n 

tua seconda variabile ottiene il testo Cleary. Nota la nuova riga ancora nel buffer, che mi porta alla seconda parte. Sostituire system ("pause"); in un modo che funziona sempre è complicato.La cosa migliore è di solito a vivere con una soluzione meno-che-perfetto, o come mi piace fare, uno che non è garantito per fare esattamente quello che dice:

std::cin.get(); //this consumes the left over newline and exits without waiting 

Okay, quindi cin.get() no lavoro. Che ne dite di questo:

std::cin.get(); //consume left over newline 
std::cin.get(); //wait 

che funziona perfettamente, ma cosa succede se si copia-incolla da qualche parte dove il ritorno a capo non è rimasto? Dovrai premere invio due volte!

La soluzione è cancellare la newline (e qualsiasi altra cosa), quindi attendere. Questo è lo scopo di cin.sync(). Comunque, come visto nella sezione note, non è garantito che cancelli il buffer come dice, quindi se il compilatore non sceglie, non può essere usato. Per me, invece, lo fa esattamente questo, lasciando una soluzione di:

std::cin.sync(); //clear buffer 
std::cin.get(); //wait 

La principale cosa brutta di system("pause"); è che non avete idea di quale programma verrà eseguito sul computer di qualcun altro. Potrebbero aver cambiato pause.exe o metterne uno che è stato trovato per primo, e non hai modo di saperlo. Questo potrebbe potenzialmente rovinare il loro computer a causa del fatto che potrebbe essere qualsiasi programma.

+1

Grazie, un'ottima risposta. Ha spiegato molto per me. Ho molta più comprensione di prima con il modo in cui l'input di pars di C++. –

+0

Mi sono imbattuto in questo mentre su Google. Una spiegazione eccellente. Grazie v. Molto. – PingPing

7

si dovrebbe provare cin.getline, in questo modo, il flusso sarà di leggere fino al primo carattere di nuova riga.

Ok, cattivi consigli come alcune persone hanno sottolineato. è possibile utilizzare std::getline per leggere un'intera linea. Anche in questo caso, il delimitatore è il ritorno a capo, a meno che informato. per leggere da cin, puoi passarlo come primo parametro (e la stringa come seconda).

std::string str; 
std::getline(cin, str); // to read until the end of line 

std::getline(cin, str, ' '); // to read until a space character, for instance 

(ovviamente, è possibile omettere la parte std:: dalle linee, dal momento che già informato il compilatore che si sta utilizzando il std namespace)

+0

-1 cattivo consiglio. 'std :: getline' è sicuro e facile,' cin.getline' non lo è. –

+0

Ho perso la parte in cui l'OP diceva che stava usando la classe di stringhe. –

+0

corretto. Ma in ogni caso, non mi merito gli uptotes poiché ho appena preso in prestito la risposta dai commenti ... –