Torna indietro   Hardware Upgrade Forum > Software > Programmazione

Samsung Galaxy S25 Edge: il top di gamma ultrasottile e leggerissimo. La recensione
Samsung Galaxy S25 Edge: il top di gamma ultrasottile e leggerissimo. La recensione
Abbiamo provato il nuovo Galaxy S25 Edge, uno smartphone unico per il suo spessore di soli 5,8 mm e un peso super piuma. Parliamo di un device che ha pro e contro, ma sicuramente si differenzia dalla massa per la sua portabilità, ma non senza qualche compromesso. Ecco la nostra prova completa.
HP Elitebook Ultra G1i 14 è il notebook compatto, potente e robusto
HP Elitebook Ultra G1i 14 è il notebook compatto, potente e robusto
Pensato per il professionista sempre in movimento, HP Elitebook Ultra G1i 14 abbina una piattaforma Intel Core Ultra 7 ad una costruzione robusta, riuscendo a mantenere un peso contenuto e una facile trasportabilità. Ottime prestazioni per gli ambiti di produttività personale con un'autonomia lontano dalla presa di corrente che permette di lavorare per tutta la giornata
Microsoft Surface Pro 12 è il 2 in 1 più compatto e silenzioso
Microsoft Surface Pro 12 è il 2 in 1 più compatto e silenzioso
Basato su piattaforma Qualcomm Snapdragon X Plus a 8 core, il nuovo Microsoft Surface Pro 12 è un notebook 2 in 1 molto compatto che punta sulla facilità di trasporto, sulla flessibilità d'uso nelle differenti configurazioni, sul funzionamento senza ventola e sull'ampia autonomia lontano dalla presa di corrente
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 03-06-2007, 10:23   #1
uomoserio
Senior Member
 
L'Avatar di uomoserio
 
Iscritto dal: Aug 2000
Messaggi: 608
Controllo input in C/C++: alcune domande.

Ciao a tutti, avrei bisogno di qualche delucidazione sulla gestione dell'input da tastiera in C/C++.
Di seguito è il classico giochino "indovina il numero", sulla base del quale avrei alcune domande da farvi per gestire le immissioni da tastiera da parte dell'utente:

Codice:
#include <cstdlib>
#include <iostream>
#include <ctime>
using namespace std;

unsigned int insNumero();
void gioco();

int main()
{
    char again;
    do {            
        gioco();
        do{    
               printf("\n\nVuoi giocare ancora? [s/n] ");
               again=getchar();
               fflush(stdin);
               if (again!='s' && again!='n') printf("\nScelta non consentita. Premi 's' o 'n'");
        } while (again!='s' && again!='n');
    } while (again=='s');
    
    return 0;
}

unsigned int insNumero()
{
         int numInserito;
         do{
             printf("\nInserisci il numero: ");
             scanf("%u", &numInserito);
             if (numInserito==0 || numInserito > 100) printf("\nDevi inserire un numero da 1 a 100!!!\n");
             fflush(stdin);
         } while(numInserito==0 || numInserito > 100);
         return numInserito;
}

void gioco()
{
     unsigned int numMagico;
     unsigned int numIndovina;
     srand(time(NULL));
     numMagico=(rand()%100)+1;
     printf("\n\nIndovina il numero magico da 1 a 100\n");
     do {
         numIndovina=insNumero();
         if (numIndovina < numMagico) printf("\nHai inserito un numero troppo basso.\n");
         else if (numIndovina > numMagico) printf("\nHai inserito un numero troppo alto.\n");
              else {
                   printf("COMPLIMENTI!!!\n");
                   printf("Il numero magico era proprio: %u", numMagico);
              }
     } while (numIndovina != numMagico);
     return;
}
Domanda 1: nella funzione insNumero(), ho usato un metodo spicciolo per controllare che il valore immesso sia compreso fra 1 e 100, così se l'utente immette dei caratteri invece di numeri il controllo comunque lo blocca (altrimenti il programma si impalla di brutto!). Ma se io avessi voluto verificare a priori il tipo immesso dall'utente (caratteri o numeri) come dovevo fare?

Domanda 2: per evitare i soliti problemi con i caratteri rimanenti nel buffer di immissione, dopo ogni inserimento da parte dell'utente ho usato fflush(stdin) per svuotare il buffer ed evitare che all'immisione successiva venissero presi eventuali caratteri residui. Questo è un sistema corretto? Oppure esiste un sistema migliore per controllare l'eccedenza del buffer di stdin? Inoltre la funzione fflush(stdin) l'ho trovata cercando nei forum....ma possibile che nessun manuale di C/C++, fra le decine che possiedo, si degni di spiegare queste cose? Eppure il problema della ingestibilità del buffer di input è un problema molto diffuso, a quanto leggo in giro....

Domanda 3: per ora il programma è scritto in C, usando le funzioni standard printf e scanf. Ma se io avessi voluto rimanere sul C++ e usare cin per le immissioni dell'utente, in che modo si utilizza esattamente? So che la forma generale con l'operatore estrattore è "cin >> variabile", ma in che modo posso formattare l'input (come ad esempio"%u" in scanf) per essere sicuro che mi restituisca un valore e non un carattere?

Grazie per la pazienza.
__________________
Intel Core2Quad Q6600 2,4GHz @ 3,0 GHz
2 Gb RAM 667 MHz
ATI HD2900XT
uomoserio è offline   Rispondi citando il messaggio o parte di esso
Old 03-06-2007, 11:05   #2
andbin
Senior Member
 
L'Avatar di andbin
 
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
Quote:
Originariamente inviato da uomoserio Guarda i messaggi
Domanda 1: nella funzione insNumero(), ho usato un metodo spicciolo per controllare che il valore immesso sia compreso fra 1 e 100, così se l'utente immette dei caratteri invece di numeri il controllo comunque lo blocca (altrimenti il programma si impalla di brutto!). Ma se io avessi voluto verificare a priori il tipo immesso dall'utente (caratteri o numeri) come dovevo fare?
Avresti dovuto usare funzioni a più basso livello e non standard, es. getch() o le API Win32 se stai lavorando su Windows.

Quote:
Originariamente inviato da uomoserio Guarda i messaggi
Domanda 2: per evitare i soliti problemi con i caratteri rimanenti nel buffer di immissione, dopo ogni inserimento da parte dell'utente ho usato fflush(stdin) per svuotare il buffer ed evitare che all'immisione successiva venissero presi eventuali caratteri residui. Questo è un sistema corretto? Oppure esiste un sistema migliore per controllare l'eccedenza del buffer di stdin? Inoltre la funzione fflush(stdin) l'ho trovata cercando nei forum....ma possibile che nessun manuale di C/C++, fra le decine che possiedo, si degni di spiegare queste cose? Eppure il problema della ingestibilità del buffer di input è un problema molto diffuso, a quanto leggo in giro....
fflush(stdin) non va molto bene. Secondo le specifiche, fflush va usato solo con stream di output, perché con stream di input il comportamento è indefinito (sebbene in alcuni ambienti fa proprio quello che vuoi, cioè pulire il buffer di input).
Ci sono altri modi per eliminare i caratteri in più:
- Fare un ciclo while(getchar() != '\n');
- Evitare scanf e usare fgets/sscanf

Quote:
Originariamente inviato da uomoserio Guarda i messaggi
Domanda 3: per ora il programma è scritto in C, usando le funzioni standard printf e scanf. Ma se io avessi voluto rimanere sul C++ e usare cin per le immissioni dell'utente, in che modo si utilizza esattamente? So che la forma generale con l'operatore estrattore è "cin >> variabile", ma in che modo posso formattare l'input (come ad esempio"%u" in scanf) per essere sicuro che mi restituisca un valore e non un carattere?
In effetti hai fatto un po' un mix ... hai usato roba del "C" (scanf, printf) ma poi hai incluso roba del C++. Evita questi mix.
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%)
andbin è offline   Rispondi citando il messaggio o parte di esso
Old 03-06-2007, 11:15   #3
ndakota
Senior Member
 
L'Avatar di ndakota
 
Iscritto dal: Oct 2006
Città: milano
Messaggi: 1439
in effetti iostream e namespace std li potrebbe anche togliere no?
ndakota è offline   Rispondi citando il messaggio o parte di esso
Old 03-06-2007, 13:41   #4
uomoserio
Senior Member
 
L'Avatar di uomoserio
 
Iscritto dal: Aug 2000
Messaggi: 608
Quote:
Originariamente inviato da andbin Guarda i messaggi
Avresti dovuto usare funzioni a più basso livello e non standard, es. getch() o le API Win32 se stai lavorando su Windows.
Per ora faccio cose in console, sto appena imparando, niente API Win32.
Ma getch() e sua sorella getche() servono per leggere caratteri da stdin senza buffer, giusto? Come posso usarlo per verificare se l'utente digita dei caratteri invece che dei numeri? E poi mi sembra che getch() restituisca un tipo char, come lo uso per inserire valori in variabili int?

Quote:
Originariamente inviato da andbin Guarda i messaggi
fflush(stdin) non va molto bene. Secondo le specifiche, fflush va usato solo con stream di output, perché con stream di input il comportamento è indefinito (sebbene in alcuni ambienti fa proprio quello che vuoi, cioè pulire il buffer di input).
Ci sono altri modi per eliminare i caratteri in più:
- Fare un ciclo while(getchar() != '\n');
- Evitare scanf e usare fgets/sscanf
Hai ragione, in effetti non avevo pensato al ciclo while per svuotare il buffer. Semplice e veloce, grazie
Da quello che ho letto fgets e sscanf servono per le stringhe....dovrei usare quelli per ricevere numeri dal stdin? Ma poi hanno comunque il problema del buffer, giusto? Quindi dovrei in ogni caso svuotarlo, vero?

Quote:
Originariamente inviato da andbin Guarda i messaggi
In effetti hai fatto un po' un mix ... hai usato roba del "C" (scanf, printf) ma poi hai incluso roba del C++. Evita questi mix.
Per il mix col C++ ti riferisci all'uso di <iostream> con "using namespace std"? In effetti originariamente avevo scritto il programma usando cin e cout, ma poi li ho sostituiti perchè non riuscivo a capire come gestirli.
__________________
Intel Core2Quad Q6600 2,4GHz @ 3,0 GHz
2 Gb RAM 667 MHz
ATI HD2900XT
uomoserio è offline   Rispondi citando il messaggio o parte di esso
Old 03-06-2007, 15:05   #5
marco.r
Senior Member
 
Iscritto dal: Dec 2005
Città: Istanbul
Messaggi: 1817
Quote:
Originariamente inviato da uomoserio Guarda i messaggi
Ciao a tutti, avrei bisogno di qualche
Domanda 1: nella funzione insNumero(), ho usato un metodo spicciolo per controllare che il valore immesso sia compreso fra 1 e 100, così se l'utente immette dei caratteri invece di numeri il controllo comunque lo blocca (altrimenti il programma si impalla di brutto!). Ma se io avessi voluto verificare a priori il tipo immesso dall'utente (caratteri o numeri) come dovevo fare?
Se vuoi usare gli stream del C++, puoi fare qualcosa di simile al seguente:
Codice:
#include <iostream>
using namespace std;

/* ... */
int n;
cin >> n
if ( cin.fail() ) // ho inserito dei caratteri
{
  cin.clear();
  while( !isdigit( cin.peek() ) ) cin.ignore();
}
Questo fa si' che in caso di errore vengano ignorati tutti i caratteri fino alla prima cifra.
Se preferisci che venga ignorata tutta la riga, allora puoi fare nel modo seguente
Codice:
#include <iostream>
using namespace std;

/* ... */
int n;
cin >> n
if ( cin.fail() ) // ho inserito dei caratteri
{
  cin.clear();
  while( cin.peek() != '\n' ) cin.ignore();
}
Vedi tu quale sia piu' adatto al tuo caso

Quote:
Domanda 2: per evitare i soliti problemi con i caratteri rimanenti nel buffer di immissione, dopo ogni inserimento da parte dell'utente ho usato fflush(stdin) per svuotare il buffer ed evitare che all'immisione successiva venissero presi eventuali caratteri residui. Questo è un sistema corretto? Oppure esiste un sistema migliore per controllare l'eccedenza del buffer di stdin? Inoltre la funzione fflush(stdin) l'ho trovata cercando nei forum....ma possibile che nessun manuale di C/C++, fra le decine che possiedo, si degni di spiegare queste cose? Eppure il problema della ingestibilità del buffer di input è un problema molto diffuso, a quanto leggo in giro....
No, flush va bene solo con l'output. Se anche funzionasse (ovvero svuotando il buffer di input) non puoi avere la certezza che questo contenga una sola linea di testo

Quote:
Domanda 3: per ora il programma è scritto in C, usando le funzioni standard printf e scanf. Ma se io avessi voluto rimanere sul C++ e usare cin per le immissioni dell'utente, in che modo si utilizza esattamente? So che la forma generale con l'operatore estrattore è "cin >> variabile", ma in che modo posso formattare l'input (come ad esempio"%u" in scanf) per essere sicuro che mi restituisca un valore e non un carattere?
Nel tuo caso, vedi la prima riga: basta usare una variabile del tipo opportuno, ven,tuali input non previsti settano lo stato del canale su "fail". In generale non puoi formattare l'input allo stesso modo in cui usi una scanf, ci si puo' arrivare vicino leggendo l'input in variabili del tipo opportuno, ed ignorando i caratteri che non ti interessano.
__________________
One of the conclusions that we reached was that the "object" need not be a primitive notion in a programming language; one can build objects and their behaviour from little more than assignable value cells and good old lambda expressions. —Guy Steele

Ultima modifica di marco.r : 03-06-2007 alle 15:06. Motivo: tag sbagliati...
marco.r è offline   Rispondi citando il messaggio o parte di esso
Old 03-06-2007, 15:26   #6
uomoserio
Senior Member
 
L'Avatar di uomoserio
 
Iscritto dal: Aug 2000
Messaggi: 608
Quote:
Originariamente inviato da marco.r Guarda i messaggi
Se vuoi usare gli stream del C++, puoi fare qualcosa di simile al seguente:
Codice:
#include <iostream>
using namespace std;

/* ... */
int n;
cin >> n
if ( cin.fail() ) // ho inserito dei caratteri
{
  cin.clear();
  while( !isdigit( cin.peek() ) ) cin.ignore();
}
Questo fa si' che in caso di errore vengano ignorati tutti i caratteri fino alla prima cifra.
Se preferisci che venga ignorata tutta la riga, allora puoi fare nel modo seguente
Codice:
#include <iostream>
using namespace std;

/* ... */
int n;
cin >> n
if ( cin.fail() ) // ho inserito dei caratteri
{
  cin.clear();
  while( cin.peek() != '\n' ) cin.ignore();
}
Vedi tu quale sia piu' adatto al tuo caso
Grazie!
E' esattamente quello che cercavo. Sapevo che cin adatta l'input alla variabile che lo deve contenere, ma non conoscevo tutte le sottofunzioni peek, fail, clear e ignore.
A dire il vero avevo visto queste cose qui:
http://www.cplusplus.com/reference/iostream/istream/
ma non ci ho capito un gran ché, forse perchè sono agli inizi!

Quote:
Originariamente inviato da marco.r Guarda i messaggi
No, flush va bene solo con l'output. Se anche funzionasse (ovvero svuotando il buffer di input) non puoi avere la certezza che questo contenga una sola linea di testo
In effetti me lo avete già detto in tanti, però a me funziona. Poi l'ho trovato scritto in molti forum, come soluzione di svuotamento del buffer.
Comunque ora che mi hai dato la soluzione migliore la sostituisco senza dubbio.

Grazie di tutto.
__________________
Intel Core2Quad Q6600 2,4GHz @ 3,0 GHz
2 Gb RAM 667 MHz
ATI HD2900XT
uomoserio è offline   Rispondi citando il messaggio o parte di esso
Old 04-06-2007, 14:18   #7
uomoserio
Senior Member
 
L'Avatar di uomoserio
 
Iscritto dal: Aug 2000
Messaggi: 608
Quote:
Originariamente inviato da marco.r Guarda i messaggi
No, flush va bene solo con l'output. Se anche funzionasse (ovvero svuotando il buffer di input) non puoi avere la certezza che questo contenga una sola linea di testo
Ok, come suggerito da andbin, per svuotare il buffer posso usare:
Codice:
while (getchar()!='\n')
che va benissimo, in effetti. Ma per usare esclusivamente le funzioni di I/O del C++, ho sostituito getchar() con cin.get() nel ciclo while, però in caso di errore non funziona. Perchè?
Prendi questo codice:
Codice:
#include <iostream>
using namespace std;

int main()
{
    int x;
    cout << "Inserisci un numero: ";
    cin >> x;
    if (cin.fail()) cout << "\nErrore";
       else cout << "\nHai digitato: " << x;
    while (cin.get()!='\n');
    cin.get();
    return 0;
}
Se io immetto un numero, procede tutto bene.
Ma se io, invece, inserisco uno o più caratteri, il programma stampa correttamente il messaggio "Errore" (sfruttando la funzione cin.fail() ), però poi si pianta nel ciclo while di svuotamento.
Da quello che ho capito dal comportamento, in caso di errore nello stream di input non esiste più '\n' e il ciclo while diventa infinito!

Quindi come risolvo? Cosa devo cercare invece di '\n'?
__________________
Intel Core2Quad Q6600 2,4GHz @ 3,0 GHz
2 Gb RAM 667 MHz
ATI HD2900XT
uomoserio è offline   Rispondi citando il messaggio o parte di esso
Old 04-06-2007, 17:27   #8
marco.r
Senior Member
 
Iscritto dal: Dec 2005
Città: Istanbul
Messaggi: 1817
Quote:
Originariamente inviato da uomoserio Guarda i messaggi
Codice:
#include <iostream>
using namespace std;

int main()
{
    int x;
    cout << "Inserisci un numero: ";
    cin >> x;
    if (cin.fail()) cout << "\nErrore";
       else cout << "\nHai digitato: " << x;
    while (cin.get()!='\n');
    cin.get();
    return 0;
}
Quindi come risolvo? Cosa devo cercare invece di '\n'?
A naso direi che ti sei dimenticato di impostare su "pulito" lo stato del canale con cin.clear() prima del ciclo while, per cui le chiamate successive a cin.get() falliscono tutte.
__________________
One of the conclusions that we reached was that the "object" need not be a primitive notion in a programming language; one can build objects and their behaviour from little more than assignable value cells and good old lambda expressions. —Guy Steele
marco.r è offline   Rispondi citando il messaggio o parte di esso
Old 04-06-2007, 17:43   #9
uomoserio
Senior Member
 
L'Avatar di uomoserio
 
Iscritto dal: Aug 2000
Messaggi: 608
Quote:
Originariamente inviato da marco.r Guarda i messaggi
A naso direi che ti sei dimenticato di impostare su "pulito" lo stato del canale con cin.clear() prima del ciclo while, per cui le chiamate successive a cin.get() falliscono tutte.
Cavolo, hai ragione!!
Infatti adesso funziona, e in questo modo sono riuscito anche a trasformare il giochino del numero in modo da usare soltanto istruzioni C++ e abbandonare quelle standard del C.
Grazie infinite!
__________________
Intel Core2Quad Q6600 2,4GHz @ 3,0 GHz
2 Gb RAM 667 MHz
ATI HD2900XT
uomoserio è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


Samsung Galaxy S25 Edge: il top di gamma ultrasottile e leggerissimo. La recensione Samsung Galaxy S25 Edge: il top di gamma ultraso...
HP Elitebook Ultra G1i 14 è il notebook compatto, potente e robusto HP Elitebook Ultra G1i 14 è il notebook c...
Microsoft Surface Pro 12 è il 2 in 1 più compatto e silenzioso Microsoft Surface Pro 12 è il 2 in 1 pi&u...
Recensione REDMAGIC Astra Gaming Tablet: che spettacolo di tablet! Recensione REDMAGIC Astra Gaming Tablet: che spe...
Dopo un mese, e 50 foto, cosa abbiamo capito della nuova Nintendo Switch 2 Dopo un mese, e 50 foto, cosa abbiamo capito del...
Samsung Galaxy S26 Edge: più auto...
Escobar Inc.: una frode che porta il mar...
Apple e la smart home in arrivo? Nuovo H...
Anche Alfa Romeo lancia il suo incentivo...
Un braccialetto che ascolta e registra o...
OPPO Find X8 Ultra: il RE dei cameraphon...
DeepL sempre più potente: arrivan...
Addio a Shunsaku Tamiya, il papà ...
Il volontariato non può essere gr...
Baxi presenta le nuove pompe di calore a...
Solo 104€ per questo robot Lefant da 500...
AppleCare One è unico! 3 disposit...
La HP DeskJet 4220e a soli 39€: un po' c...
Muore il traffico dei siti web per colpa...
Auto giapponesi, aria di festa a Tokyo: ...
Chromium
GPU-Z
OCCT
LibreOffice Portable
Opera One Portable
Opera One 106
CCleaner Portable
CCleaner Standard
Cpu-Z
Driver NVIDIA GeForce 546.65 WHQL
SmartFTP
Trillian
Google Chrome Portable
Google Chrome 120
VirtualBox
Tutti gli articoli Tutte le news Tutti i download

Strumenti

Regole
Non Puoi aprire nuove discussioni
Non Puoi rispondere ai messaggi
Non Puoi allegare file
Non Puoi modificare i tuoi messaggi

Il codice vB è On
Le Faccine sono On
Il codice [IMG] è On
Il codice HTML è Off
Vai al Forum


Tutti gli orari sono GMT +1. Ora sono le: 16:53.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Served by www3v