PDA

View Full Version : [C++] Metodo d'acquisizione CIN. Restringere il tipo variabile possibile


Albitexm
25-04-2011, 21:07
Ho scritto un codice che acquisisce un numero con il metodo cin:
cin>>int x;
Il problema è che quando per sbaglio, digito sulla tastira una lettera invece che un numero, il programma impazzisce o genera n.cicli non uguali a int x;
Come posso fare ignorare al programma input in ingresso che non siano interi?
Ho provato a creare un ciclo do-while con la condizione di x compreso in un intervallo d'interi. Ma in questo modo non impazzisce, ma m'interpreta x "traducendo" la lettera pigiata per sbaglio sulla scacchiera.

WarDuck
25-04-2011, 21:44
Quelli da tastiera sono caratteri, acquisisci l'input come carattere o stringa, ti assicuri che rappresenti un intero valido e poi procedi alla conversione.

tuccio`
25-04-2011, 23:10
se sbagli e non inserisci un intero dove se ne aspetta uno, il fail bit del cin viene messo a true (credo :asd:)... quindi se prima di leggere chiami il metodo clear e poi controlli se il failbit è a true, almeno ti puoi accorgere dell'errore

eventualmente puoi anche cambiare l'exception mask per farti lanciare un'eccezione in questo caso

Albitexm
26-04-2011, 00:55
se sbagli e non inserisci un intero dove se ne aspetta uno, il fail bit del cin viene messo a true (credo :asd:)... quindi se prima di leggere chiami il metodo clear e poi controlli se il failbit è a true, almeno ti puoi accorgere dell'errore

eventualmente puoi anche cambiare l'exception mask per farti lanciare un'eccezione in questo caso

Grazie.

Albitexm
26-04-2011, 08:39
Quelli da tastiera sono caratteri, acquisisci l'input come carattere o stringa, ti assicuri che rappresenti un intero valido e poi procedi alla conversione.

Seguendo il tuo consiglio ho scritto un codice, che mi acquisisce un numero come stringa e me lo trasforma in intero. Nel caso inserisca un carattere diverso da "0/9" mi richiede d'inserire nuovamente la stringa:

#include <iostream>
#include <string>
using namespace std;

int el10,key,nl,x,elv,nul;
int nint=0;
char wf;
const int maxl=9;//massima dimensione numero=999.999.999
char vn[maxl];
string n;//numero partite input stringa


// funzione per elevare a potenza di 10

int esp (int elv,int k)
{
int ì=1;
for (ì;ì<elv;ì++)
{
k=k*10;
}
return el10=k;
}


// funzione trasformazione input char estratti da stringa
//in ingresso, in interi

int tcti(char In)
{

if (In=='0')
key=0;
else if (In=='1')
key=1;
else if (In=='2')
key=2;
else if (In=='3')
key=3;
else if (In=='4')
key=4;
else if (In=='5')
key=5;
else if (In=='6')
key=6;
else if (In=='7')
key=7;
else if (In=='8')
key=8;
else if (In=='9')
key=9;
else
key=10;
return key;
}



int main()
{
char dec; //deep copy numero partite n
int i=0;
do
{
nint=0;
cout<<endl<<endl<<" Quante partite vuoi fare? ";
cin>>n;
nl=n.length();

//costruzione vettore caratteri della stringa
// numero partite "n"

i=0;
for (i;i<nl;i++)
{
basic_string <char>::reference refn1 = n [i];
dec=refn1;
vn[i]=dec;
}

i=0;
for (i;i<nl;i++)
{

dec=vn[i];
tcti(dec);
if (key==10)
break;
else if (key>-1&&key<10)
{
switch (i)
{
case 0: esp(nl-i,key);nint+=el10;break;
case 1: esp(nl-i,key);nint+=el10;break;
case 2: esp(nl-i,key);nint+=el10;break;
case 3: esp(nl-i,key);nint+=el10;break;
case 4: esp(nl-i,key);nint+=el10;break;
case 5: esp(nl-i,key);nint+=el10;break;
case 6: esp(nl-i,key);nint+=el10;break;
case 7: esp(nl-i,key);nint+=el10;break;
case 8: esp(nl-i,key);nint+=el10;break;
default :nint=0;break;
}
}
else
{
cout<<endl<<endl<<"error case input";
break;
}
}
if (key==10)
{
nul=1;
continue;
}
else
{
cout<<endl<<" Vuoi fare n. partite="<<nint<<"?"<<endl;
cout<<" sei sicuro?";cin>>wf;
}

}
while(wf!='s');

cout<<endl<<" numero partite="<<nint<<endl<<endl;
system("pause");
return 0;

}

WarDuck
26-04-2011, 10:10
Mi sembra un po' troppo lunghetto (non sono sceso nei dettagli) :D.

C'è la funzione atoi() che può fare al caso tuo, anche se è pessima per i controlli (restituisce 0 in caso di errore e parsa anche stringhe non complete come numeri, ad esempio "576asd" lo converte in 576).

Comunque tieni conto che lavorando sulla codifica ASCII puoi ricavarti il numero intero dalla sua rappresentazione.

Albitexm
26-04-2011, 18:33
Mi sembra un po' troppo lunghetto (non sono sceso nei dettagli) :D..

Ho acquisito l'input non come intero ma come stringa. Ho estratto i singoli caratteri della stringa. Poi ho scritto una funzione che mi ritorna un intero corrispondente al carattere se questo è compreso tra 0 e 9, altrimenti mi ritorna un numero che interpreto come errore. Se la funzione mi restituisce errore, invio un continue, e quindi viene ripetuto il ciclo do while, e richiesto nuovamente l'input dalla tastira. Altrimenti l'intero , viene passato a una funzione, che somma le unità,decine,centinai ecc , per ottenere l'intero finale. LA cosa funziona, ma sinceramente mi sembra un po' laboriosa, per risolvere un compito relativamente semplice come questo.


C'è la funzione atoi() che può fare al caso tuo, anche se è pessima per i controlli (restituisce 0 in caso di errore e parsa anche stringhe non complete come numeri, ad esempio "576asd" lo converte in 576).:D..

Mi sembra strano che il C++ di oggi, non abbia delle funzioni al riguardo.

Albitexm
26-04-2011, 18:37
se sbagli e non inserisci un intero dove se ne aspetta uno, il fail bit del cin viene messo a true (credo :asd:)... quindi se prima di leggere chiami il metodo clear e poi controlli se il failbit è a true, almeno ti puoi accorgere dell'errore

eventualmente puoi anche cambiare l'exception mask per farti lanciare un'eccezione in questo caso

In rete mi hanno proposto un codice che segue la tua idea. Lo posto perchè potrebbe essre utile a qualche altro principiante come me:

#include "stdafx.h"
#include <iostream>
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
int x;

do{
cout << "Inserisci:";

cin.clear();
while(cin.get() != '\n');

cin >> x;
} while(cin.fail());

cout << x;

return 0;
}