webForumDet fria alternativet

Kolla så det inte är integer

12 svar · 373 visningar · startad av Mc Fetto

Mc FettoMedlem sedan nov. 20022 355 inlägg
#1

Jag gör ett program där man kan mata in olika värden och vill om man råkar mata in fel, t ex om man matar in text i stället för ett nummer så ska en exception komma.. hur kan jag kolla så det är en integer?

aasahMedlem sedan mars 20034 471 inlägg
#2

Om du har

int i;
cin << i;

och du skriver in en int så är allt frid och fröjd. Om du däremot skriver in "tre" så kommer ett exception att kastas. Så om du fångar exceptions som slängs så borde du få tag i alla saker som ej är heltal.

I C har jag inte en aning om hur det funkar.

Mc FettoMedlem sedan nov. 20022 355 inlägg
#3

Det jag frågar är hur jag ska fånga exception för just det!

PeWMedlem sedan juni 200010 432 inlägg
#4

Re: Kolla så det är integer

Mc Fetto skrev:

Jag gör ett program där man kan mata in olika värden och vill om man råkar mata in fel, t ex om man matar in text i stället för ett nummer så ska en exception komma.. hur kan jag kolla så det är en integer?

if(!cin>>_var_)
            cout  << "NaN";
        else {
                ....
                ....
               }

Visserligen ingen riktig "exception" - hantering, men om du bara ska kolla att det är ett numeriskt värde (int el. double) och inte "a-z" fungerar det.

Sang-draxMedlem sedan juli 2002581 inlägg
#5

aasah skrev:

Om du har
int i;
cin << i;

och du skriver in en int så är allt frid och fröjd. Om du däremot skriver in "tre" så kommer ett exception att kastas. Så om du fångar exceptions som slängs så borde du få tag i alla saker som ej är heltal.

I C har jag inte en aning om hur det funkar.

cin kastar inga exceptions!

Det är för övrigt mycket bättre att läsa in hela raden med getline() och sedan läsa från den strängen med stringstream.

string s;
getline(cin,s);
stringstream sin(s);
sin >> i;
if (!sin)
  //error
aasahMedlem sedan mars 20034 471 inlägg
#6

Sang-drax skrev:

aasah skrev:

Om du har
int i;
cin << i;

och du skriver in en int så är allt frid och fröjd. Om du däremot skriver in "tre" så kommer ett exception att kastas. Så om du fångar exceptions som slängs så borde du få tag i alla saker som ej är heltal.

I C har jag inte en aning om hur det funkar.

cin kastar inga exceptions!...

Korrekt, jag kom ihåg fel! :r Testade idag. Däremot noterade jag något annat.

void main() {
   int i;
   cout << "siffra" << endl;
   cin >> i;
   cout << "klar" << i << endl;
}

När koden körs och jag skriver in ett heltal så får jag snyggt ut det talet.
Om jag skriver in 3.1415 ==> 3, trunkerar - eller läser bara 3:an(?)
Om jag skriver in godtycklig bokstav eller sträng - verkar det som - skriver programmet ut ett mycket stort negativt tal. Alltid SAMMA tal. Vad beror det på? Nån som vet?

PeWMedlem sedan juni 200010 432 inlägg
#7

asaah skrev:

När koden körs och jag skriver in ett heltal så får jag snyggt ut det talet.
Om jag skriver in 3.1415 ==> 3, trunkerar - eller läser bara 3:an(?)
Om jag skriver in godtycklig bokstav eller sträng - verkar det som - skriver programmet ut ett mycket stort negativt tal. Alltid SAMMA tal. Vad beror det på? Nån som vet?

Det där med samma tal är en definitionsfråga, ty anledning till att det är ett stort negativt tal är samma anledning till att icke initierade variabler har ett stort negativt värde. En trolig anledning kan vara att den minnesplats som variablen pekar på innehåller gammal data och att den mest signifikanta biten (för den nya variablen) är satt och talet är då negativt ur 2-komplements perspektiv.

Vet dock inte hur minneskretsarna ser ut när minnet startas upp, men man kan tänka sig att de initialt består av ettor i alla celler. Isf blir alla tal negativa från början.. men nu är jag på för mig okänd mark (hur minneskrestarna initialt fungerar, jag ville bara dela med mig en tänkbar förklaring till varför oinitierat minne ofta ger negativa värden även direkt efter start). Vilken del av minnet (user space) har nog inget med detta att göra (?)

Hursomhelst så ger en operation med cin på en integer att det förutsätts att strängen (ja det är alltid en sträng med teckenkoder som läses in från tangentbordet) består av tecken mellan 0x30 och 0x39. En inledning med kod 0x2D är dock tillåtet då det är "-" och symboliserar negativt tal. Är tecknets kod utanför intervall så ignoreras tecknet och den inre funktionen i cin terminerar. Har då inte integeren tilldelats något i den inre funktionen har den samma värde som innan. Men i ditt fall med 3.14 så hinner 3:an placeras i integeren innan funktionen terminerar vid 0x2E (punkt) så det är 3 du får kvar.

Mao kan man mycket väl initiera integern med valfritt värde och se om en förändring skett. Om inte så var inmatat tal icke ett numeriskt (10-bas) sådant. I min rekommendation med

if(!cin>>_var_)
            cout  << "NaN";
        else {
                ....
                ....
               }

..bör således _var_ initieras till något värde <0 för att säkerställa att satsen agerar på rätt sätt. (Om den icke initierade variablen _var_ råkar ha ett skräpvärde >0). Här kan man då tillse att initiera och testa med värden som inte är tillåtna... då det kan hända att man visst vill ha värden som är <0.

Ingen snygg exceptionlösning, men ändock fungerande och enkel.

r-> +t

aasahMedlem sedan mars 20034 471 inlägg
#8

Tackar, PEW, för den långa och intressanta förklaringen! :) Uppskattas!

PeWMedlem sedan juni 200010 432 inlägg
#9

Varsågod :)

Mc FettoMedlem sedan nov. 20022 355 inlägg
#10

Hm har suttit ett bra tag med detta problem nu!
Om användaren skriver in en bokstv istället för en int så flippar programmet loss och börjar loopa i casesatsen.

jag har:

							cout<<"Ange ObjektId (sex siffror): ";
							cin>>oid;
							cin.get(c);

Nu undrar jag hur jag får användaren att få en ny chans att skriva in rätt?

PeWMedlem sedan juni 200010 432 inlägg
#11

Men har du inte testat det jag föreslog?

Mc FettoMedlem sedan nov. 20022 355 inlägg
#12

Jag har provat ett par olika varianter, men jag har inte riktigt koll på hur det fungerar. Min kod ser ut så här nu och det händer samma som tidigare!

							cout<<"Ange ObjektId (sex siffror): ";
							cin>>oid;
							cin.get(c);
		
							if(!cin>>oid)
							{
								while (!cin>>oid)
								{
									cout<<"fel"; cout<<"Ange ObjektId (sex siffror): "<<endl; 
									cin>>oid;
									cin.get(c);
								}
							}

Tacksam för svar :)

PeWMedlem sedan juni 200010 432 inlägg
#13

Tja... en annan lösning är att läsa in som sträng och göra om det till ett tal genom atoi(char *); Då slipper du problemet med de skräp i teckenbufferten som blir kvar. Lite 'C', kanske... men det funkar.

135 ms totalt · 3 externa anrop · v20260731065814-full.beb2e261
0 ms — hämta forumlista (cache)
0 ms — hämta statistik (cache)
132 ms — hämta tråd, inlägg och bilagor (db)