|
|
|
![]() |
|
Strumenti |
![]() |
#1 |
Senior Member
Iscritto dal: Apr 2004
Città: La regione del Triplete
Messaggi: 5744
|
[C/C++] Controllo input tastiera
Salve,
Sono alle prese con una funzione per la creazione di un semplice menu. Il programma esegue determinate azioni in base alla voce di menu che inserisco. Gestisco il tutto con uno switch. Codice:
void scelta() { int scelta; while ( ( scelta = getchar() ) != EOF ) { switch ( scelta ) { case 'S': case 's': cout<<"messaggio1"<<endl; break; case 'D': case 'd': cout<<"messaggio2"<<endl; break; case 'M': case 'm': cout<<"messaggio3"<<endl; break; default: cout<<"Scelta non corretta. Ridigitare."<<endl; break; } /* fine switch */ } /* fine while */ } /* fine funzione */ Se invece digito SS, cioè 2 volte S mi stampa 2 volte il messaggio. Se digito SD mi stampa i 2 messaggi corrispondenti. Vorrei, nel modo più semplice possibile (con una funzione che posso richiamare) fare il controllo in modo che se digito 2 caratteri invece di uno mi segnala l'errore. Qualche idea?
__________________
Trattative felicemente concluse con domienico120, xbax88 ed engiel, ottimi e seri utenti. |
![]() |
![]() |
![]() |
#2 |
Senior Member
Iscritto dal: Apr 2004
Città: La regione del Triplete
Messaggi: 5744
|
Ho modificato la funzione eliminando le lettere, sostituendole con dei comodi numeri
![]() Adesso risolve correttamente lo switch, mentre non esce dal while. Codice:
using namespace std; void scelta(); int main(int argc, char *argv[]) { scelta(); system("PAUSE"); return EXIT_SUCCESS; } void scelta() { int scelta; cout<< "Digitare 1 ...."<<endl; cout<< "Digitare 2 ....."<<endl; cout<< "Digitare 3 ......."<<endl; cout<< "Digitare 0 per uscire"<<endl; cin>>scelta; /* ripete finchè non si immette 0*/ while ( scelta !=0 ) { /* azione in base all'input */ switch ( scelta ) { case 1: cout<<"mess1"<<endl; break; /*esce dallo switch */ case 2: cout<<"mess2"<<endl; break; /* esce dallo switch */ case 3: cout<<"mess3"<<endl; break; /* esce dallo switch */ case '\n': /* ignora gli a capo, */ case '\t': /* tabs, */ case ' ': /* spazi in input */ break; /* esce dallo switch */ default: /* tutti gli altri caratteri */ cout<<"Scelta non corretta. Ridigitare."<<endl; break; } /* fine switch */ } /* fine while */ } /* fine funzione */ Se invece è 0 il valore, esce direttamente. Se il valore non è uno di quelli previsti al momento va in loop. Pensavo quindi: se oltre alla variabile io ne aggiungessi una di status (rendendo quindi la funzione int e non void) che mi viene restituita al main, il quale mi opera un controllo, se status è 0 vuol dire che la funzione è andata bene e ha preso il valore che gli occorreva, se invece è -1 per esempio vuol dire che la funzione ha preso un valore che non andava e deve ricominciare. Che ne dite come soluzione? Non ci sarebbe alternativamente un modo per evitare di ripartire con la funzione? Per esempio: inserisco il valore che non va bene, lo switch viene risolto, ma il valore è sempre diverso da 0, esce dal while e lo reinizia?
__________________
Trattative felicemente concluse con domienico120, xbax88 ed engiel, ottimi e seri utenti. |
![]() |
![]() |
![]() |
#3 |
Senior Member
Iscritto dal: Nov 2003
Città: Il Poli
Messaggi: 992
|
personalmente avrei tenuto la prima soluzione per il menù. semplicemente inserisci questa riga dopo lo switch
while(getchar()!="\n"); con questa però mangi tutto l'input che non è stato consumato sia esso corretto o meno. Per segnalare l'errore a quel punto devi aggiustarti con un flag. |
![]() |
![]() |
![]() |
#4 |
Senior Member
Iscritto dal: Apr 2004
Città: La regione del Triplete
Messaggi: 5744
|
Ho rimodificato il programma tornando alla versione iniziale. Ho aggiunto un getchar() che mi evita i loops e ho trasformato ogni digitazione in maiuscolo.
Codice:
void scelta() { int scelta; while ( ( scelta = getchar() ) != EOF ) { getchar(); scelta=toupper(scelta); switch ( scelta ) { case 'S': cout<<"messaggio1"<<endl; break; case 'D': cout<<"messaggio2"<<endl; break; case 'M': cout<<"messaggio3"<<endl; break; default: cout<<"Scelta non corretta. Ridigitare."<<endl; break; } /* fine switch */ } /* fine while */ } /* fine funzione */ SS -> messaggio1 messaggio1 SD -> messaggio1 messaggio2 MM -> messaggio3 messaggio3 SG -> messaggio1 e va a capo in attesa di digitazione (non stampa il messaggio del default ma presenta subito il cursore per una ridigitazione). Qualche idea?
__________________
Trattative felicemente concluse con domienico120, xbax88 ed engiel, ottimi e seri utenti. |
![]() |
![]() |
![]() |
#5 |
Senior Member
Iscritto dal: Nov 2005
Città: Cavallino (LE)
Messaggi: 335
|
Pe la variabile scelta dichiara cosi: char scelta = [1];Non so prova e fammi sapere
__________________
Notebook: HP DV6-6159sl -- PC CPU Intel i7 3770k, MB MSI Z77a-g45, RAM Corsair XMS 3 low profile 1600, SV Gigabyte HD6950, SSD Corsair GT60, HD WD 500Gb CG, WD750Gb CB, DVD-ROM LG lightscribe, ALI 750TX550W, CASE CM Advanced II, MONITOR Asus VW224T x 3, TASTIERA Thermaltake Challenger Pro, MOUSE Corsair M60, CUFFIE Roccat kave 5.1, SISTEMA AUDIO JBL ESC.XITE , MOUSEPAD Roccat Taito + CM Storm Ho concluso positivamente con: berna29,spl,Alex_Lupin,rb1205,katoble |
![]() |
![]() |
![]() |
#6 |
Senior Member
Iscritto dal: Apr 2004
Città: La regione del Triplete
Messaggi: 5744
|
Levando il secondo getchar() non ci sono problemi a quanto pare, non va in loop. Continua però a dare problemi.
Dichiarando la variabile come char scelta = [1]; ottengo errori.
__________________
Trattative felicemente concluse con domienico120, xbax88 ed engiel, ottimi e seri utenti. |
![]() |
![]() |
![]() |
#7 |
Senior Member
Iscritto dal: Nov 2005
Città: Cavallino (LE)
Messaggi: 335
|
Specifica gli errori per favore.
__________________
Notebook: HP DV6-6159sl -- PC CPU Intel i7 3770k, MB MSI Z77a-g45, RAM Corsair XMS 3 low profile 1600, SV Gigabyte HD6950, SSD Corsair GT60, HD WD 500Gb CG, WD750Gb CB, DVD-ROM LG lightscribe, ALI 750TX550W, CASE CM Advanced II, MONITOR Asus VW224T x 3, TASTIERA Thermaltake Challenger Pro, MOUSE Corsair M60, CUFFIE Roccat kave 5.1, SISTEMA AUDIO JBL ESC.XITE , MOUSEPAD Roccat Taito + CM Storm Ho concluso positivamente con: berna29,spl,Alex_Lupin,rb1205,katoble |
![]() |
![]() |
![]() |
#8 |
Senior Member
Iscritto dal: Apr 2004
Città: La regione del Triplete
Messaggi: 5744
|
Ero di fretta e non ho implementato correttamente
![]() Adesso, dichiarando come mi hai detto ottengo: initializer fails to determinate size of scelta. Se invece metto char scelta[1]; e lavoro sulla singola casella accedendo così Codice:
while ( ( scelta[0] = getchar() ) != EOF ) { scelta[0]=toupper(scelta[0]); /* rende maiuscolo il carattere inserito. Includere a inizio programma ctype.h */ /* azione in base all'input */ switch ( scelta[0] ) { ...... Adesso stavo pensando a sta cosa: e se usassi isalpha() della libreria ctype? Magari si semplifica un attimo. Devo capire prima cosa fa di preciso e cosa prende.
__________________
Trattative felicemente concluse con domienico120, xbax88 ed engiel, ottimi e seri utenti. |
![]() |
![]() |
![]() |
#9 | |
Senior Member
Iscritto dal: Nov 2005
Città: Cavallino (LE)
Messaggi: 335
|
Io sono niubbo totale e su questo
Quote:
Ma perche non usi dei semplici 'if'?Cosi risolvi tutto ![]() Ma studi su un Deitel?
__________________
Notebook: HP DV6-6159sl -- PC CPU Intel i7 3770k, MB MSI Z77a-g45, RAM Corsair XMS 3 low profile 1600, SV Gigabyte HD6950, SSD Corsair GT60, HD WD 500Gb CG, WD750Gb CB, DVD-ROM LG lightscribe, ALI 750TX550W, CASE CM Advanced II, MONITOR Asus VW224T x 3, TASTIERA Thermaltake Challenger Pro, MOUSE Corsair M60, CUFFIE Roccat kave 5.1, SISTEMA AUDIO JBL ESC.XITE , MOUSEPAD Roccat Taito + CM Storm Ho concluso positivamente con: berna29,spl,Alex_Lupin,rb1205,katoble |
|
![]() |
![]() |
![]() |
#10 | |
Senior Member
Iscritto dal: Apr 2004
Città: La regione del Triplete
Messaggi: 5744
|
Quote:
![]()
__________________
Trattative felicemente concluse con domienico120, xbax88 ed engiel, ottimi e seri utenti. |
|
![]() |
![]() |
![]() |
#11 |
Senior Member
Iscritto dal: Nov 2005
Città: Cavallino (LE)
Messaggi: 335
|
Che capitolo?
__________________
Notebook: HP DV6-6159sl -- PC CPU Intel i7 3770k, MB MSI Z77a-g45, RAM Corsair XMS 3 low profile 1600, SV Gigabyte HD6950, SSD Corsair GT60, HD WD 500Gb CG, WD750Gb CB, DVD-ROM LG lightscribe, ALI 750TX550W, CASE CM Advanced II, MONITOR Asus VW224T x 3, TASTIERA Thermaltake Challenger Pro, MOUSE Corsair M60, CUFFIE Roccat kave 5.1, SISTEMA AUDIO JBL ESC.XITE , MOUSEPAD Roccat Taito + CM Storm Ho concluso positivamente con: berna29,spl,Alex_Lupin,rb1205,katoble |
![]() |
![]() |
![]() |
#12 | |
Member
Iscritto dal: Jan 2007
Città: Asti
Messaggi: 256
|
Quote:
La variabile scelta è una variabile char, contiene UN solo carattere alla volta, se tu inserisci due lettere (poniamo S e G ) la getchar attribuirà a scelta prima la S, il tuo switch selezionerà l'operazione, poi il ciclo ricomincera' e la getchar consumerà ancora il buffer attribuendo a scelta la G e eseguendo l'operazione di G. E' ovvio proprio per struttura del programma, non puoi evitarlo. Volendo, potresti dichiarare scelta come vettore di caratteri, e printare errore nel caso in cui ci siano piu' di una lettera/operatore e il NULL nella stringa... Del tipo if ( strlen( scelta ) > 1 ) printf(" Errore nell'imput bla bla bla \n"); EDIT: Se proprio vuoi, puoi fare così. Poniamo che tu la prima lettera che inserisci è sempre la lettera che volevi inserire, e che se ne inserisci due vuoi segnalato l'errore, perchè inserita piu' di una lettera.. ok? Bene, in un esempio si potrebbe dire che con un imput come questo Snjknsvjhbsdgv noi volevamo intendere "Esegui l'istruzione 'S' " e che dopo la s ci siamo sbagliato e abbiamo digitato qualcosa in piu... Be, puoi dichiarare scelta come vettore di caratteri, leggere l'imput e usare lo switch infine su scelta[0], ossia sul primo elemento della stringa scelta. Se vuoi conservare il maiuscolo chiamala in questo modo : switch( toupper( scelta[0] ) ). Così facendo se la stringa fosse ghbhcd andrai a selezionare l'operazione G dello switch
__________________
![]() ![]() Ho concluso affari con: Samurri, kosimiro, mAiDeN75, Raziel1984, deidara, billy99. gertuzz Ultima modifica di Ibrahimovic : 06-10-2009 alle 23:09. |
|
![]() |
![]() |
![]() |
#13 |
Senior Member
Iscritto dal: Nov 2005
Messaggi: 2775
|
Ma hai provato la soluzione che ti ha proposto Jecko? Mi sembrava corretta...
|
![]() |
![]() |
![]() |
#14 |
Senior Member
Iscritto dal: Apr 2004
Città: La regione del Triplete
Messaggi: 5744
|
Dunque, ho notato che la mia funzione è lunghetta, fa più di una cosa ed è troppo specifica. Ho pertanto deciso di crearne una generale che posso chiamare quando mi fa comodo e che fa solo ed esclusivamente il controllo dell'input.
Ibra, secondo te cosa è più elegante? Segnalare subito l'errore o prendere per buono solo il primo carattere della stringa?
__________________
Trattative felicemente concluse con domienico120, xbax88 ed engiel, ottimi e seri utenti. |
![]() |
![]() |
![]() |
#15 |
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Mi è arrivata una erronea segnalazione da qualcuno, in ogni caso rispondo...
char scelta = [1]; non esiste in C o C++ La variabile char deve essere inizializzata o con un intero o con un carattere fra apici singoli. La risposta corretta era quella di Jecko, dopo la lettura del primo carattere all'interno della condizione del while, bisogna svuotare il buffer di input: while(getchar()!="\n"); Questo lo puoi mettere subito dopo l'apertura della parentisi del while. Una soluzione molto più C++ sarebbe stata questa: Codice:
while((scelta = cin.get()) != 0) { string temp; getline(cin, temp); |
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 19:24.