|
| Problemer med std::cin Fra : Henrik Koksby Hansen |
Dato : 07-06-02 21:49 |
|
void klasse::funktion() {
int nummer=0;
cout << "Tast nummer: "; cin >> nummer;
if( (nummer > 999) && (nummer < 10000) ) {
if (arkivklasse.tilfoej(nummer) == true) {
cout << "Nummer " << nummer << " oprettet." <<
endl;
else
cout << "Nummeret findes allerede." << endl;
}
else cout << "Ugyldigt dataformat." << endl;
system ("pause");
}
Hvis man ved inputtet taster et bogstav f.eks., vil funktionen
efterfølgende springe cin-inputtet over, konsekvent, og give fejlen
'Ugyldigt dataformat' ...
Jeg forstår det ikke. Er der nogen, der har en forklaring?
Funktionen bliver kaldt fra en primær funktion (menu) i samme klasse,
som, efter den kaldte funktion er udført, kalder sig selv igen (efter
en udført switch-case).
Jeg ved godt at menuen kan gøres mere elegant - evt. med en
while-løkke, så man slipper for den rekursive effekt. Men det burde da
ikke have indflydelse på dette problem?
MVH
Henrik
| |
Mogens Hansen (07-06-2002)
| Kommentar Fra : Mogens Hansen |
Dato : 07-06-02 22:12 |
|
"Henrik Koksby Hansen" <koksby@elektronik.dk> wrote in message
news:uo62gu0nqvmlfne1bqh3g2m9ffk43asnpo@4ax.com...
[snip]
> int nummer=0;
>
> cout << "Tast nummer: "; cin >> nummer;
>
[snip]
> if (arkivklasse.tilfoej(nummer) == true) {
>
Mon ikke der er en { for meget ?
[snip]
> cout << "Nummeret findes allerede." << endl;
> }
>
Og en } for meget ?
[snip]
> Jeg forstår det ikke. Er der nogen, der har en forklaring?
>
Du prøver på at læse en integer fra cin.
Hvis du taster et bogstav, kan det ikke tolkes som værende del af en
integer.
Derfor fejler kaldet og nummer få ikke tildelt nogen værdi, og vil derfor
have sin oprindelige værdi - 0.
Venlig hilsen
Mogens Hansen
| |
Henrik Koksby Hansen (07-06-2002)
| Kommentar Fra : Henrik Koksby Hansen |
Dato : 07-06-02 22:32 |
|
>Du prøver på at læse en integer fra cin.
>Hvis du taster et bogstav, kan det ikke tolkes som værende del af en
>integer.
>Derfor fejler kaldet og nummer få ikke tildelt nogen værdi, og vil derfor
>have sin oprindelige værdi - 0.
[...]
Men burde funktionen ikke have glemt det, når den afsluttes - og så
vente på input næste gang den kaldes? Det er jo en lokal variabel, som
slettes fra hukommelsen, når funktionen er udført?
Hvis nej, må løsningen vel være at lave et input til char, som sendes
videre, evt. med atoi? (metode ligegyldig, jeg snakker om princippet:)
Og jo, undskyld - der er kommet et par klammer for meget ind i forhold
til den 'rigtige' (læs: oprindelige) kode.
MVH
Henrik
| |
Morten Brix Pedersen (08-06-2002)
| Kommentar Fra : Morten Brix Pedersen |
Dato : 08-06-02 01:31 |
|
Henrik Koksby Hansen wrote:
>>Du prøver på at læse en integer fra cin.
>>Hvis du taster et bogstav, kan det ikke tolkes som værende del af en
>>integer.
>>Derfor fejler kaldet og nummer få ikke tildelt nogen værdi, og vil derfor
>>have sin oprindelige værdi - 0.
>
> [...]
>
> Men burde funktionen ikke have glemt det, når den afsluttes - og så
> vente på input næste gang den kaldes? Det er jo en lokal variabel, som
> slettes fra hukommelsen, når funktionen er udført?
Nej - streamen kommer i en "bad state" hvor den ikke kan gøre noget
medmindre du selv clearer den bad state vha. cin.clear();.
Løsningen er at checke om cin får det rigtige input:
int i;
if (cin >> i) {
cout << "vi fik en integer" << endl;
} else {
cout << "du indtastede ikke en integer" << endl;
}
Det står bedre beskrevet i C++ FAQ LITE (som faktisk er ret god):
http://www.parashift.com/c++-faq-lite/input-output.html#faq-15.2
- Morten.
| |
Mogens Hansen (08-06-2002)
| Kommentar Fra : Mogens Hansen |
Dato : 08-06-02 06:55 |
|
"Henrik Koksby Hansen" <koksby@elektronik.dk> wrote
> >Du prøver på at læse en integer fra cin.
> >Hvis du taster et bogstav, kan det ikke tolkes som værende del af en
> >integer.
> >Derfor fejler kaldet og nummer få ikke tildelt nogen værdi, og vil derfor
> >have sin oprindelige værdi - 0.
> [...]
>
> Men burde funktionen ikke have glemt det, når den afsluttes - og så
> vente på input næste gang den kaldes? Det er jo en lokal variabel, som
> slettes fra hukommelsen, når funktionen er udført?
>
Den lokale variabel (nummer) spiller ingen rolle.
Det er streamens state, der er afgørende.
Når du prøver at læse en integer,og det ikke kan lade sig gøre, så fil
"ios_base::failbit" blive sat, og forblive sat indtil den slettes.
> Hvis nej, må løsningen vel være at lave et input til char, som sendes
> videre, evt. med atoi? (metode ligegyldig, jeg snakker om princippet:)
>
Det er ikke nødvendigt.
Man skal blot komme ud af fejlsituationen, og så fortsætte:
#include <limits>
#include <iostream>
int main(void)
{
using namespace std;
for(;;) {
int i;
if(cin >> i) {
cout << "Integer read: " << i << endl;
}
else {
cout << "Not an integer" << endl;
// recover from error state
cin.clear();
// and ignore current content of
// input buffer, to proceed
cin.ignore(cin.rdbuf()->in_avail());
}
}
}
Venlig hilsen
Mogens Hansen
| |
Henrik Koksby Hansen (08-06-2002)
| Kommentar Fra : Henrik Koksby Hansen |
Dato : 08-06-02 09:08 |
|
>Den lokale variabel (nummer) spiller ingen rolle.
>Det er streamens state, der er afgørende.
>
>Når du prøver at læse en integer,og det ikke kan lade sig gøre, så fil
>"ios_base::failbit" blive sat, og forblive sat indtil den slettes.
[...]
Mange tak for de gode svar, Mogens og Morten.
Det var alt jeg ville vide - nu giver det pludselig mening.
Jeg havde hørt min programmeringslærer, som ikke kunne give en
forklaring - og jeg har da også bladret bogen tynd, for at finde
svaret.
MVH
Henrik
| |
Mogens Hansen (08-06-2002)
| Kommentar Fra : Mogens Hansen |
Dato : 08-06-02 09:53 |
|
"Henrik Koksby Hansen" <koksby@elektronik.dk> wrote
> Jeg havde hørt min programmeringslærer, som ikke kunne give en
> forklaring - og jeg har da også bladret bogen tynd, for at finde
> svaret.
>
Den formodentlig mest dækkende bog om streams er
Standard C++ IOStreams and Locales
Angelika Langer & Klaus Kreft
ISBN 0-201-18395-1
Venlig hilsen
Mogens Hansen
| |
|
|