[C++] wel getallen, geen letters

Pagina: 1
Acties:
  • 305 views sinds 30-01-2008
  • Reageer

  • plukke
  • Registratie: Februari 2005
  • Laatst online: 19-09-2025
Hoi,

Na als C++ beginner een programmatje te hebben geschreven in C++ (ik gebruik MS visual studio .net pro) wat de wortel van een ingevoerd getal trekt heb ik een verificatie ingebouwd voor negatieve getallen dmv de volgende while loop.

While (getal<1) { cout<< "error"; cin>> getal; }

Getal is gedefineerd als een double en op 0 gezet boven deze while loop. De error werkt prima zodra je negatieve getallen invoert. probleem gefixed zou je zeggen. Nou, niet helemaal. Ik probeerde bij wijze van test een letter in te vullen maar dat vondt hij niet leuk, ik kreeg een oneindige "cout" aanroep met de errormelding.

Noch google noch GoT kon mij helpen aan een mogelijke oplossing voor dit "probleem". Aangezien de opdracht al voltooid is maar ik toch erg nieuwsgiering ben naar hoe je in vredesnaam de letters er uit kan vissen. Ik zit zelf te denken aan een "If" loop mar daarin alle letters gedefineerd. Dat moet toch makkelijker kunnen? Is er iemand zo gek om mij een beetje in de goede richting te willen sturen? ;)

[ Voor 27% gewijzigd door plukke op 09-09-2005 19:35 ]


  • apokalypse
  • Registratie: Augustus 2004
  • Laatst online: 28-04 22:54
waarom een while loop?
vulde je btw 1 of meerdere letter in?

dit lijkt me een goede oplossing:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>
#include <math.h>

using namespace std;

double wortel(double getal)
{
    return sqrt(getal);
}


void vraag()
{
    double getal;
    cout << "geef getal\n";
    cin >> getal;
    if (getal >= 0)
    {
        cout << wortel(getal) <<endl;
    }
    else
        cout << "error, opnieuw?\n";
    char antwoord;
    cout << "verder gaan (y/n)?\n";
    cin >> antwoord;
    if (antwoord == 'y' || antwoord == 'Y')//niet volledig
        vraag();
    else //deze hoeft noggeeneens
        exit(1);
}


void main()
{
    vraag();
}


zo kan je iig geen oneindelijk loop hebben, speciale functies is altijd wel aan te raden.
(de code is ff snel getypt)

edit: layout
edit: getest en werkend, ik had een double quote foutje, op deze manier geen problemen met letter. onnodige while loops moet je altijd vermijden. :)
edit: foei, nu heb ik het voorgekauwd :P ik was te enthousiast bezig

[ Voor 175% gewijzigd door apokalypse op 09-09-2005 20:21 ]


  • plukke
  • Registratie: Februari 2005
  • Laatst online: 19-09-2025
de while loop het ik gekozen omdat ik ook wil checken of het ingevoerde getal positief is. Eigenlijk wil ik hiervoor al checken of het eigenlijk wel een getal is in plaats van een letter, en dat hij na een letter een error geeft. Vandaar dus hier de keuze voor de while loop.

Moet alleen nog bekijken hoe ik mijn programma kan laten checken op letters zonder ze allemaal te benoemen in de if loop........

  • apokalypse
  • Registratie: Augustus 2004
  • Laatst online: 28-04 22:54
om te testen of een invoer een letter is, kan je de invoer opslaan als char en dan omzetten naar int (dat wordt dan de ascii code)
zie http://www.asciitable.com/

code:
1
2
3
4
5
bool is_number(char c)
{
    int ascii = c;
    return (ascii >= 48 && ascii <=57); // dit zijn in ascii-dec de characters 0-9
}


maar hoe het met doubles precies moet ben ik ff kwijt.

[ Voor 26% gewijzigd door apokalypse op 09-09-2005 20:10 ]


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 30-04 04:38
Als de eerstvolgende invoer een letter is, dan kún je geen getal inlezen. Als je dat toch probeert (met cin >> getal dus) dan gaat het mis en dat kun je controleren door cin.bad() aan te roepen. Je zou dus zulke code moeten gebruiken:
C++:
1
2
3
4
5
int getal;
do {
    std::cout << "Voer een getal in: " << std::flush;
    std::cin >> getal;
} while( cin.bad() || getal < 1 );

Helaas werkt dit nog niet zomaar, omdat invoer die niet ingelezen kan worden gewoon in de stream blijft staan. Daar komt de oneindige lus vandaan. Misschien is het dus handiger om regel voor regel in te lezen, en de regels afzonderlijk te parsen:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int getal = 0;
while(getal < 1)
{
    std::cout << "Voer een getal in: " << std::flush;

    // Regel inlezen
    std::string line;
    std::getline(std::cin, line);

    // Regel parsen
    std::istringstream parser(line);
    parser >> getal;

    if(!parser)
        cerr << "Ongeldige invoer!" << endl;
    else
    if(getal < 1)
        cerr << "Te klein getal!" << endl;

}

Merk op dat ik hierbij gebruik dat !parser equivalent is aan parser.bad() (een handig trucje wat bewerkstelligd is door een conversieoperator van de stream klasse te overloaden).

[ Voor 44% gewijzigd door Soultaker op 09-09-2005 21:11 ]


  • Robtimus
  • Registratie: November 2002
  • Laatst online: 30-04 19:28

Robtimus

me Robtimus no like you

apokalypse schreef op vrijdag 09 september 2005 @ 20:02:
om te testen of een invoer een letter is, kan je de invoer opslaan als char en dan omzetten naar int (dat wordt dan de ascii code)
zie http://www.asciitable.com/

code:
1
2
3
4
5
bool is_number(char c)
{
    int ascii = c;
    return (ascii >= 48 && ascii <=57); // dit zijn in ascii-dec de characters 0-9
}


maar hoe het met doubles precies moet ben ik ff kwijt.
Tip: gebruik (ascii >= '0' && ascii <= '9'). Is exact hetzelfde maar een stuk leesbaarder.

More than meets the eye
There is no I in TEAM... but there is ME
system specs


  • apokalypse
  • Registratie: Augustus 2004
  • Laatst online: 28-04 22:54
IceManX schreef op vrijdag 09 september 2005 @ 21:24:
[...]
Tip: gebruik (ascii >= '0' && ascii <= '9'). Is exact hetzelfde maar een stuk leesbaarder.
ja ik vraag me af waarom ik dat ook niet heb :)
waarschijnlijk omdat het uit een programma komt waarbij ik meer ascii codes gebruik.

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
In feite wil je twee dingen testen: Ten eerste, of er een getal ingelezen is, en ten tweede, of dat getal aan je eisen voldoet.
Het eerste test je standaard op de volgende manier
C++:
1
2
int getal;
while(  std::cin >> getal ) // zolang je van cin een getal leest

Het tweede kan via een
C++:
1
2
3
4
{ 
  if( getal<0 ) break;
  // ... rest van while
}

Overigens is '0' vaak, maar niet altijd ascii 48. Dat is niet erg, want '0' is overal '0'. en '1' is ook overal '0'+1

PS. als je het ooit zonder std::cin moet uitvissen: std::isdigit, std::isalpha, std::isalnum, std:isspace. Heleboel nuttige functietjes.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • plukke
  • Registratie: Februari 2005
  • Laatst online: 19-09-2025
Dat was de reply die ik zocht, muchos gracias, je hebt me weer op de goede weg gebracht. morgen eens even inbouwen :Y)

  • riezebosch
  • Registratie: Oktober 2001
  • Laatst online: 23-04 14:31
MSalters schreef op vrijdag 09 september 2005 @ 23:28:
In feite wil je twee dingen testen: Ten eerste, of er een getal ingelezen is, en ten tweede, of dat getal aan je eisen voldoet.
Het eerste test je standaard op de volgende manier
C++:
1
2
int getal;
while(  std::cin >> getal ) // zolang je van cin een getal leest

Het tweede kan via een
C++:
1
2
3
4
{ 
  if( getal<0 ) break;
  // ... rest van while
}

Overigens is '0' vaak, maar niet altijd ascii 48. Dat is niet erg, want '0' is overal '0'. en '1' is ook overal '0'+1

PS. als je het ooit zonder std::cin moet uitvissen: std::isdigit, std::isalpha, std::isalnum, std:isspace. Heleboel nuttige functietjes.
Met een break een while beëindigen? :o

Canon EOS 400D + 18-55mm F3.5-5.6 + 50mm F1.8 II + 24-105 F4L + 430EX Speedlite + Crumpler Pretty Boy Back Pack


  • Super_ik
  • Registratie: Maart 2001
  • Laatst online: 08:35

Super_ik

haklust!

apokalypse schreef op vrijdag 09 september 2005 @ 19:47:
waarom een while loop?
vulde je btw 1 of meerdere letter in?

dit lijkt me een goede oplossing:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>
#include <math.h>

using namespace std;

double wortel(double getal)
{
    return sqrt(getal);
}


void vraag()
{
    double getal;
    cout << "geef getal\n";
    cin >> getal;
    if (getal >= 0)
    {
        cout << wortel(getal) <<endl;
    }
    else
        cout << "error, opnieuw?\n";
    char antwoord;
    cout << "verder gaan (y/n)?\n";
    cin >> antwoord;
    if (antwoord == 'y' || antwoord == 'Y')//niet volledig
        vraag();
    else //deze hoeft noggeeneens
        exit(1);
}


void main()
{
    vraag();
}


zo kan je iig geen oneindelijk loop hebben, speciale functies is altijd wel aan te raden.
(de code is ff snel getypt)

edit: layout
edit: getest en werkend, ik had een double quote foutje, op deze manier geen problemen met letter. onnodige while loops moet je altijd vermijden. :)
edit: foei, nu heb ik het voorgekauwd :P ik was te enthousiast bezig
dude, hier is een goto nog netter :'( een functie die zigzelf aanroept en nooit meer terug gaat.
je kunt t beter als return value meegeven en die voor een while gebruiken:
code:
1
2
3
4
5
6
7
8
9
main
int x;
{
  do
  {
    vraag_getal_en_doe_check()
    print_getal(x)
 }while(!nog_een_keer())
}

[ Voor 11% gewijzigd door Super_ik op 10-09-2005 10:06 ]

8<------------------------------------------------------------------------------------
Als ik zo door ga haal ik m'n dood niet. | ik hou van goeie muziek


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 30-04 04:38
Het lijkt er op dat iedereen er aan voorbij gaat dat als er geen getal in de invoer zit, maar bijvoorbeeld een letter, die letter er nooit meer uitgaat. Als cin >> getal faalt dan kun je hoog en laag springen en herhalen zolang je wil maar dan ga je nooit een getal inlezen tot je de blokkerende invoer hebt verwijderd. Je krijgt dan de oneindige lus die in de topic start ook al genoemd werd.

Vandaar dat ik (voor gebruikersinteractie) aan zou raden om regel voor regel in te lezen (zoals ik in mijn eerdere reactie uitlegde).

  • apokalypse
  • Registratie: Augustus 2004
  • Laatst online: 28-04 22:54
riezebosch schreef op zaterdag 10 september 2005 @ 09:33:
[...]

Met een break een while beëindigen? :o
wat is daar zo raar aan?

  • riezebosch
  • Registratie: Oktober 2001
  • Laatst online: 23-04 14:31
Tja, aangezien MSalters het zegt zal het in een while-loop wel geoorloofd zijn. Maar normaalgesproken is het niet de meest nette manier om je program-flow te beïnvloeden. De leesbaarheid wordt er niet echt beter door, net als goto's ook not-done zijn.

Canon EOS 400D + 18-55mm F3.5-5.6 + 50mm F1.8 II + 24-105 F4L + 430EX Speedlite + Crumpler Pretty Boy Back Pack


  • Daos
  • Registratie: Oktober 2004
  • Niet online
In de informatica verspillen sommige mensen hun tijd aan het bewijzen dat hun code correct is. Als er een break in een loop staat dan kunnen ze het niet meer.

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 30-04 04:38
Daos schreef op zaterdag 10 september 2005 @ 23:13:
In de informatica verspillen sommige mensen hun tijd aan het bewijzen dat hun code correct is. Als er een break in een loop staat dan kunnen ze het niet meer.
Onzin, aangezien deze constructie:
C++:
1
2
3
4
5
while (a) {
   b;
   if(c) break;
   d;
}

equivalent is aan:
C++:
1
2
3
4
5
6
bool x = true;
while (a && x) {
   b;
   if(c) x = false;
   if(x) d;
}

(Iets soortgelijks kun je doen als het break statement ergens in een genest blok zit.) Dus de bewijsbaarheid neemt hierdoor niet af. Hetzelfde geldt everigens voor goto statements.

Het is dus veel zinniger om te denken aan zaken als leesbaarheid en onderhoudbaarheid en dan blijkt dat een break of goto op de juiste plaats helderder kan zijn dan een constructie met extra variabelen om te signaleren wanneer de lus onderbroken moet worden, wat de gebruikelijke alternatieve oplossing is.

[ Voor 29% gewijzigd door Soultaker op 10-09-2005 23:34 ]


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
Ik denk meer dat Daos bedoelt dat die mensen het niet meer kunnen omdat het voor hun dan te moeilijk wordt; uiteraard is het triviaal - al helemaal omdat de break helemaal als eerste staat. De equivalente code is (met short-circuit evaluation)
C++:
1
2
3
while( bool(cin>>getal) && getal >0 )
{
}

De bool cast is niet strict noodzakelijk, maar dan is het nog onduidelijker. De while( cin>>variable) vorm is kanoniek, vandaar dat ik die eerst gebruikte.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein

Pagina: 1