Torna indietro   Hardware Upgrade Forum > Software > Programmazione

Le soluzioni FSP per il 2026: potenza e IA al centro
Le soluzioni FSP per il 2026: potenza e IA al centro
In occasione del Tech Tour 2025 della European Hardware Association abbiamo incontrato a Taiwan FSP, azienda impegnata nella produzione di alimentatori, chassis e soluzioni di raffreddamento tanto per clienti OEM come a proprio marchio. Potenze sempre più elevate negli alimentatori per far fronte alle necessità delle elaborazioni di intelligenza artificiale.
AWS annuncia European Sovereign Cloud, il cloud sovrano per convincere l'Europa
AWS annuncia European Sovereign Cloud, il cloud sovrano per convincere l'Europa
AWS è il principale operatore di servizi cloud al mondo e da tempo parla delle misure che mette in atto per garantire una maggiore sovranità alle organizzazioni europee. L'azienda ha ora lanciato AWS European Sovereign Cloud, una soluzione specificamente progettata per essere separata e distinta dal cloud "normale" e offrire maggiori tutele e garanzie di sovranità
Redmi Note 15 Pro+ 5G: autonomia monstre e display luminoso, ma il prezzo è alto
Redmi Note 15 Pro+ 5G: autonomia monstre e display luminoso, ma il prezzo è alto
Xiaomi ha portato sul mercato internazionale la nuova serie Redmi Note, che rappresenta spesso una delle migliori scelte per chi non vuole spendere molto. Il modello 15 Pro+ punta tutto su una batteria capiente e su un ampio display luminoso, sacrificando qualcosa in termini di potenza bruta e velocità di ricarica
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 03-06-2007, 11: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, 12: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, 12: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, 14: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, 16: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 16:06. Motivo: tag sbagliati...
marco.r è offline   Rispondi citando il messaggio o parte di esso
Old 03-06-2007, 16: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, 15: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, 18: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, 18: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


Le soluzioni FSP per il 2026: potenza e IA al centro Le soluzioni FSP per il 2026: potenza e IA al ce...
AWS annuncia European Sovereign Cloud, il cloud sovrano per convincere l'Europa AWS annuncia European Sovereign Cloud, il cloud ...
Redmi Note 15 Pro+ 5G: autonomia monstre e display luminoso, ma il prezzo è alto Redmi Note 15 Pro+ 5G: autonomia monstre e displ...
HONOR Magic 8 Pro: ecco il primo TOP del 2026! La recensione HONOR Magic 8 Pro: ecco il primo TOP del 2026! L...
Insta360 Link 2 Pro e 2C Pro: le webcam 4K che ti seguono, anche con gimbal integrata Insta360 Link 2 Pro e 2C Pro: le webcam 4K che t...
Realme: la trasformazione in sub-brand d...
PlayStation 6 si farà attendere: ...
BWT Alpine chiude la prima tornata di pr...
Beyond Good & Evil 2 non è st...
Qualcomm: il CEO ha guadagnato quasi 30 ...
AMD: 'Non importa cosa dice Intel, i mig...
Non è solo colpa del mercato: il ...
3 smartphone ai prezzi più bassi ...
Pwn2Own Automotive 2026 da record: 76 ze...
Più watt, più bassi e subwoofer incluso:...
Xiaomi POCO F8 Pro, un top di gamma a 54...
Tassa di 2 euro sui piccoli pacchi: un a...
Robot super automatico con lavaggio a 75...
Ecco perché dovremmo tutti avere ...
È un robot completo con molte del...
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: 18:29.


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