2015-12-14 18 views
22

Sono abbastanza nuovo per C++ e sto imparando cose come questa:Come si usa cin tra stringhe in C++?

cout << "My age is: "; 
cin >> age; 

Nei guai con cin, mi sono imbattuto in un posto di blocco.

Dire che volevo scrivere "I am x anni!".

"x" essere cin >> età;

Scrivo il codice in questo modo.

cout << "I am "; 
cin >> age; 
cout << "years old!"; 

Il roadblock è che produce un'interruzione di riga.

Non voglio interrompere la linea.

Come posso avere tutto questo rimanere su una linea?

+4

questo non ha molto senso per me. Non dovresti * prima * chiedere all'utente di inserire l'età e poi restituire 'std :: cout <<" I am "<< x <<" anni. \ N "' nel suo insieme? – 5gon12eder

+0

Quindi stai cercando di inventare qualcosa di simile a un vuoto in cui l'utente può inserire la loro età? Se è così, sfortunatamente, non è così che generalmente funzionano i sistemi basati su testo, ma sono sicuro che ciò potrebbe essere fatto con [ncurses] (https://en.wikipedia.org/wiki/Ncurses), anche se diventerebbe più complicato. – Numeri

+1

Il modo per immettere qualcosa senza una nuova riga è disattivare il buffering nel flusso. Ma ciò dipende dal sistema operativo in uso e non fa parte di C++. Ad esempio in Windows è possibile ottenere caratteri senza farli echeggiare sullo schermo e poi decidere in seguito quali mettere sullo schermo. –

risposta

8
unsigned int age; 
std::cin >> age; 

std::cout << "I am " << age << " years old!" << std::endl; 
+0

Questo è solo un modo per evitare questo problema, non una soluzione. – FalconUA

+3

Cosa? Questo non ha senso ... – erip

+0

Più uno per essere l'unico ad usare 'std :: endl' e non' \ n' – Mawg

11

cin legge l'input dopo un ritorno a capo viene inserito sulla console.

Pertanto, l'unico modo in cui è possibile farlo in modo continuo è richiedere all'utente la loro età e quindi procedere a scriverlo.

es:

std::cout << "Enter your age> "; 
std::cin >> age; 
std::cout << "I am " << age << " years old" << std::endl; 
+1

puoi fare riferimento alla cosa dopo la nuova linea? – dhein

22

Presumo si vuole realmente l'ingresso di essere in linea con con l'uscita eventuale. In caso contrario, la soluzione è banale: prima di leggere il valore e quindi stamparlo, es .:

std::cout << "how old are you? "; 
std::cin >> x; 
std::cout << "I am " << x << " years old\n"; 

trattati i di ingresso che è in linea con l'uscita è un pò più difficile. Il problema qui è che la gestione della console viene effettivamente eseguita dal sistema e non dal linguaggio. Di conseguenza, è necessario attendere una nuova riga quando si inseriscono i dati. La nuova riga sarà gestita dalla console e creerà un'interruzione di riga. Per disabilitare questo comportamento è necessario aggirare il problema facendo affidamento sul comportamento della console. Non esiste un modo standard in C++ per farlo.

Non so come gestire i controlli della console su Windows: sono principalmente un programmatore UNIX. Su un sistema UNIX si utilizza tcgetattr() e tcsetattr() per impostare la modalità di input come non canonica (ad esempio, per cancellare il bit ICANON). Il descrittore di file richiesto è semplicemente quello per l'input standard, ovvero 0.

Una volta che la console utilizza la modalità non canonica, tutti i tasti premuti vengono immediatamente inoltrati all'applicazione e l'eco dello schermo non viene eseguita. Di conseguenza, la funzione di lettura dovrà effettivamente eseguire l'eco di singoli caratteri e quindi inoltrare a una funzione di analisi. Il modo più semplice per fare è creare un buffer del flusso di filtraggio che faccia l'eco necessario per std::cin a std::cout durante l'inoltro del carattere. Tuttavia, mettere tutto insieme è un po 'di lavoro ...

Durante la cottura di una demo ho notato che avevo anche bisogno di occuparmi di echo (per evitare una nuova riga quando l'utente utilizza il tasto invio). È inoltre importante ripristinare i flag della console poiché alcuni di essi rimangono effettivamente modificati anche dopo la chiusura del programma.Un'implementazione mettendo insieme i pezzi, ma ancora manca la gestione degli errori potrebbe essere la seguente:

#include <iostream> 
#include <ctype.h> 
#include <termios.h> 

struct non_canon_buf 
    : std::streambuf { 
    char buffer; 
    non_canon_buf() { 
     termios flags = {}; 
     tcgetattr(0, &flags); 
     flags.c_lflag &= ~(ICANON | ECHO); 
     tcsetattr(0, TCSANOW, &flags); 
    } 
    ~non_canon_buf() { 
     termios flags = {}; 
     tcgetattr(0, &flags); 
     flags.c_lflag |= ICANON | ECHO; 
     tcsetattr(0, TCSANOW, &flags); 
    } 
    int underflow() { 
     if (std::cin.get(buffer)) { 
      this->setg(&buffer, &buffer, &buffer + 1); 
      if (!std::isspace(static_cast<unsigned char>(buffer))) { 
       std::cout << buffer << std::flush; 
      } 
      return std::char_traits<char>::to_int_type(buffer); 
     } 
     return std::char_traits<char>::eof(); 
    } 
}; 

int main() 
{ 
    non_canon_buf sbuf; 
    std::istream in(&sbuf); 
    std::cout << "I am "; 
    int age = 0; 
    in >> age; 
    std::cout << " years old\n"; 
    if (!in) { 
     std::cout << "ERROR: failed to enter a valid age!\n"; 
    } 
} 
+2

Solo per completezza, l'equivalente di Windows sarebbe ['SetConsoleMode'] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033.aspx) con' ENABLE_LINE_INPUT' e 'ENABLE_ECHO_INPUT' disabilitato. Quindi ['ReadConsole'] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms684958.aspx) (o' ReadFile' con stdin) può essere utilizzato. – Bob

+1

@Mawg Anche se questa potrebbe non essere una fonte autorevole, [cppreference.com] (http://en.cppreference.com/w/cpp/io/manip/endl) ha una nota su 'std :: endl' che dice "L'uso di std :: endl al posto di '\ n', incoraggiato da alcune fonti, può peggiorare significativamente le prestazioni di output." In modo che potrebbe essere ciò che è con il '\ n'. – Alex

+1

@Mawg: '\ n' è C++ perfettamente valido. Potresti preferire 'std :: endl', ma non devi inviare spam ai commenti di Overflow dello stack a nessuna risposta che usi una convenzione di codifica che non ti piace. Inoltre, notare che '\ n' e' std :: endl' tecnicamente non fanno nemmeno esattamente la stessa cosa, come spiegato nel link di Alex. – FrederikVds

6

Non puoi fare quello che vuoi in puro C++. Si può fare come gli altri hanno suggerito e ristampare la linea:

std::cout << "I am " << age << " years old!\n" 

In alternativa è possibile utilizzare una funzione specifica del sistema operativo per cancellare l'output della console. Read about this here.

Ad esempio, è possibile utilizzare system("cls"); per Windows per cancellare la console dopo aver chiesto all'utente la loro età.

#include <stdlib.h> 

int main(int argc, char* argv[]) { 
    unsigned int age; 
    std::cout << "My age is: " 
    std::cin >> age; 
    system("cls"); 
    std::cout << "I am " << age << " years old!\n" 
    ... 
} 

Resa:

C:>AgeProgram.exe I am 10 years old

+0

@Mawg 'std :: endl' svuota il buffer' cout'. In pochissimi casi lo vuoi davvero. '" \ n "' e 'endl' sono gli stessi sotto ogni altro aspetto. [Leggi questo.] (Http://stackoverflow.com/questions/213907/c-stdendl-vs-n) –

0

si può fare in questo modo

int user_age; 

std:cout<<"Enter Your Age:"   //Ask user for age 

std::cin >>user_age;    //Read user input 
std::cout<<"I am"<<user_age<<"years old!"<< std::endl; //finlly display the value