Toon posts:

[C++] Blijf hangen in een while loop

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ik heb het volgende stukje geprogrammeerd, maar zodra ik bij naam een te lange string invoer blijft hij hangen in de while loop omdat hij die string in het geheugen houd, is er iemand die weet hoe ik hem weer leeg kan gooien??

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
#include <iostream.h>

void Invoer()
{
    char Invoer_Naam[41] = "", Invoer_Adres[41] = "", Invoer_Postcode[7], Invoer_Plaats[20], Invoer_Telefoon[20];
    while( strlen( Invoer_Naam ) < 1 || strlen( Invoer_Naam ) > 40 )
    {
        cout << "Naam: ";
        cin.getline( Invoer_Naam, 41 );
    }
    cout << "Adres: ";
    cin.getline( Invoer_Adres, 41 );
    while( strlen( Invoer_Postcode ) != 6 )
    {
        cout << "Postcode: ";
        cin.getline( Invoer_Postcode, 7 );
    }
    cout << "Plaats: ";
    cin.getline( Invoer_Plaats, 20 );
    cout << "Telefoon: ";
    cin.getline( Invoer_Telefoon, 20 );
}

int main()
{
    Invoer();
    return 0;
}

[ Voor 10% gewijzigd door Verwijderd op 18-12-2002 20:57 ]


  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Verwijderd schreef op 18 december 2002 @ 20:45:
Ik heb het volgende stukje geprogrammeerd, maar zodra ik bij naam een te lange string invoer blijft hij hangen in de while loop omdat hij die string in het geheugen houd, is er iemand die weet hoe ik hem weer leeg kan gooien??

code:
1
2
3
4
5
6
7
8
void Invoer()
{
    char Invoer_Naam[41] = "", Invoer_Adres[41] = "", Invoer_Postcode[7], Invoer_Plaats[20], Invoer_Telefoon[20];
    while( strlen( Invoer_Naam ) > 40 )
    {
        cout << "Naam: ";
        cin.getline( Invoer_Naam, 41 );
    }
Invoer_Naam[0] = '\0';

maaruh, weet je zeker dat je van die vreemde while loopjes wil? Zolang ie groter als 40 is? dat gebeurt bijna nooit. Ik zou ook cin.getline( Invoer_Naam, 40 ); gebruiken anders heb je een buffer overflow met 41 tekens + \0. En dan slaat je while loop zeker nergens meer op

[ Voor 36% gewijzigd door LordLarry op 18-12-2002 20:56 ]

We adore chaos because we like to restore order - M.C. Escher


Verwijderd

Topicstarter
Ik wil dus dat je maximaal 40 tekens in kunt voeren. Word gewoon een beveiliging dat je der geen dikke braggelrommel in krijgt :)

  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Ook je != 6 is een beetje vreemd allemaal....en waarom geen do while ipv een while? waarom zou je vooraf controleren als dat toch nooit onwaar is? En waarom controleren of ie uberhaupt langer is dan 40? waneer gebeurt dat dan?

We adore chaos because we like to restore order - M.C. Escher


  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Verwijderd schreef op 18 december 2002 @ 21:00:
Ik wil dus dat je maximaal 40 tekens in kunt voeren. Word gewoon een beveiliging dat je der geen dikke braggelrommel in krijgt :)
Ik ben geen C++ kenner, maar daar zorgt getline toch voor? (als je er tenminste maar 40 van maak ipv 41

We adore chaos because we like to restore order - M.C. Escher


Verwijderd

Topicstarter
het probleem is dat het gewoon moet willen, en ik het er graag in wil hebben.
waar moet je deze plaatsen?

Invoer_Naam[0] = '\0';

aangezien hij blijft hangen in de loop.

Verwijderd

Topicstarter
LordLarry schreef op 18 December 2002 @ 21:03:
[...]


Ik ben geen C++ kenner, maar daar zorgt getline toch voor? (als je er tenminste maar 40 van maak ipv 41
euh, ja maar dan vraagt hij niet opnieuw, hij pakt gewoon de eerste 40 chars. en de rest slaat hij op in de volgende string

  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Ah! nu snap ik je :) de getline blijft in je toetsenbord buffer hangen. Geen idee nog wat je daar aan kan doen, ik kijk nog wel even...

Ik heb het even nagezocht, die getline(.., 41) is wel goed idd. Getline rekend de null char ook mee. Dat betekend wel dat je nooit meer als 40 chars (+ null char) in je string kan hebben en dat > 40 nooit waar zal zijn.

We adore chaos because we like to restore order - M.C. Escher


Verwijderd

Topicstarter
jup, ik zit alleen ff vast hoe ik die string weer leeg kan krijgen als hij hem gecontroleerd heeft en hij klopt niet.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17:57

.oisyn

Moderator Devschuur®

Demotivational Speaker

Even kijken hoor, je wilt dus niet dat ie de string zomaar afkapt, en je wilt ook dat ie de naam opnieuw vraagt als de invoer te lang is?

Ik zou std::string gebruiken, daarmee kan getline () oneindig lange regels lezen. Vervolgens controleer je gewoon of ie te lang is, zodat je de vraag opnieuw kunt stellen als dat zo is.
Overigens, iostream.h is deprecated, gebruik iostream (die overigens ook alle standaard classes en functies enzo in de std namespace declareert)

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
#include <string>

void invoer ()
{
    using namespace std;
    string naam;

    do
    {
        cout << "Je naam: ";
        getline (cin, naam);
    }
    while (naam.length () > 40);

    // ...
}


hier zit overigens nog geen foutafhandeling in (wat bijvoorbeeld als cin een EOF tegenkomt?)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Topicstarter
nou, dat gedoe met namespaces ed wil ik eigenlijk voorkomen, dat werkt namelijk niet bij ons op school.
Denk dat de compiler te oud is

  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

Ok, ik heb het even uitgezocht voor je:

C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int main(int argc, char* argv[])
{
    char Invoer_Naam[12] = "";
    bool fail;

    do{
      fail = false;

      cout << "Naam: ";
      cin.getline( Invoer_Naam, 12 );
      if (cin.fail()){
        fail = true;
        cin.clear();
        cin.ignore(INT_MAX, '\n');
      }
    }while(fail || (Invoer_Naam[0] == '\0'));

    cout << strlen( Invoer_Naam );

    return 0;
}

We adore chaos because we like to restore order - M.C. Escher


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 13-08 16:46

curry684

left part of the evil twins

C++:
1
2
3
4
char  l_Input[40];
printf("Naam: ");
scanf("%39s", l_Input);
printf("U heet %s\n", l_Input);

(niks mis met standard C-libs als het 10 keer kortere code levert)

Professionele website nodig?


Verwijderd

curry684 schreef op 19 december 2002 @ 02:04:
C++:
1
2
3
4
char  l_Input[40];
printf("Naam: ");
scanf("%39s", l_Input);
printf("U heet %s\n", l_Input);
C++:
1
2
3
4
cout << "Naam: ";
string input;
getline(cin, input);
cout << "U heet " << input << "\n";
(niks mis met standard C-libs als het 10 keer kortere code levert)
Mijn C++ versie is niet langer, wél type-safe, flexibeler (geen vaste bufferlengte), en duidelijker (door string ipv char[], << ipv printf, getline ipv scanf, en geen %s of %39s codes).

[ Voor 12% gewijzigd door Verwijderd op 19-12-2002 02:50 ]


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 13-08 16:46

curry684

left part of the evil twins

Verwijderd schreef op 19 December 2002 @ 02:47:
Mijn C++ versie is niet langer, wél type-safe, flexibeler (geen vaste bufferlengte), en duidelijker (door string ipv char[], << ipv printf, getline ipv scanf, en geen %s of %39s codes).
Daarentegen is mijn versie ook perfecte C++ (het compileert tenslotte zonder errors) en voldoet wel aan de opdracht:
Verwijderd schreef op 18 December 2002 @ 21:00:
Ik wil dus dat je maximaal 40 tekens in kunt voeren. Word gewoon een beveiliging dat je der geen dikke braggelrommel in krijgt :)
* curry684 wist vantevoren stiekem wel dat hier weer een dikke ruzie over zou ontstaan maar had er wel weer zin in :P

Professionele website nodig?


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 24-08 22:38
curry684 schreef op 19 December 2002 @ 10:20:
Daarentegen is mijn versie ook perfecte C++ (het compileert tenslotte zonder errors) en voldoet wel aan de opdracht:
* curry684 wist vantevoren stiekem wel dat hier weer een dikke ruzie over zou ontstaan maar had er wel weer zin in :P
Met als opvallend verschil dat de meneer van jouw versie geen spaties in zijn naam mag hebben. >:)

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Verwijderd

curry684 schreef op 19 december 2002 @ 10:20:
[...]
Daarentegen is mijn versie ook perfecte C++ (het compileert tenslotte zonder errors) en voldoet wel aan de opdracht:
[...]
Als je per sé niet achteraf de lengte met string::length wil checken, kun je zo'n char array in combinatie met basic_istream::getline gebruiken. Er blijven genoeg voordelen (die ik al eerder noemde) over om deze oplossing boven de ouderwetse C-style oplossing te verkiezen.
* curry684 wist vantevoren stiekem wel dat hier weer een dikke ruzie over zou ontstaan maar had er wel weer zin in :P
Ik ben niet geinteresseerd in ruzie, ik ben vooral oprecht benieuwd naar je andere argumenten, want ik kan simpelweg niet bevatten dat een C++ programmeur met verstand van zaken terug zou willen vallen op een zo overduidelijk inferieure C oplossing..

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 13-08 16:46

curry684

left part of the evil twins

Verwijderd schreef op 19 december 2002 @ 11:01:
Ik ben niet geinteresseerd in ruzie, ik ben vooral oprecht benieuwd naar je andere argumenten, want ik kan simpelweg niet bevatten dat een C++ programmeur met verstand van zaken terug zou willen vallen op een zo overduidelijk inferieure C oplossing..
Sja ik gebruik zelf altijd ReadConsole(...), weggeencapsuleerd in een class met een functie ReadLine die een string-class teruggeeft.
C++:
1
2
3
4
l_Result = l_Console->Text(L"Naam: ")->ReadLine();
if(l_Result.Length() > 40)
  throw EInvalidInputLength(l_Result.Length());
l_Console->Text("U heet ")->String(l_Result)->NewLine(2);
farlane schreef op 19 december 2002 @ 10:58:
Met als opvallend verschil dat de meneer van jouw versie geen spaties in zijn naam mag hebben. >:)
Whoopsie ;)

* curry684 heeft al 3 jaar niet meer scanf gebruikt of zo, maar 't blijft leuk om even de knuppel in het hoenderhok te slingeren 8)

Professionele website nodig?


Verwijderd

curry684 schreef op 19 december 2002 @ 12:31:
[...]

Sja ik gebruik zelf altijd ReadConsole(...), weggeencapsuleerd in een class met een functie ReadLine die een string-class teruggeeft.

[...]

* curry684 heeft al 3 jaar niet meer scanf gebruikt of zo, maar 't blijft leuk om even de knuppel in het hoenderhok te slingeren 8)
Maar het feit dat je de topicstarter die C-style code aanbood terwijl hij al met cin/cout/getline in de weer was, geeft aan dat je die benadering beter vindt. Waarom? Ik heb een aantal argumenten aangedragen waarom ik die benadering juist slechter vind, vind je die argumenten ongeldig of misschien irrelevant? Of zijn er misschien voordelen van scanf/printf die ik over het hoofd zie?

Ik wacht in spanning :).

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 24-08 22:38
Verwijderd schreef op 19 December 2002 @ 13:48:
[...]

Maar het feit dat je de topicstarter die C-style code aanbood terwijl hij al met cin/cout/getline in de weer was, geeft aan dat je die benadering beter vindt. Waarom? Ik heb een aantal argumenten aangedragen waarom ik die benadering juist slechter vind, vind je die argumenten ongeldig of misschien irrelevant? Of zijn er misschien voordelen van scanf/printf die ik over het hoofd zie?

Ik wacht in spanning :).
Je hebt toch wel dat gedeelte van dat hoederhok enzo gelezen ? ;)

( Ik vind printf een hele handige functie, ook al is tie niet typesafe. Maar misschien is het beter om de topicstarter daar niet mee lastig te vallen. )

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Verwijderd

farlane schreef op 19 december 2002 @ 14:29:
[...]
Je hebt toch wel dat gedeelte van dat hoederhok enzo gelezen ? ;)
Sorry, maar een regelrechte troll (want dat is het, als het hem puur alleen maar om de negatieve reacties ging en hij niet achter z'n post staat) had ik van hem niet verwacht.

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 13-08 16:46

curry684

left part of the evil twins

Verwijderd schreef op 19 December 2002 @ 14:36:
[...]

Sorry, maar een regelrechte troll (want dat is het, als het hem puur alleen maar om de negatieve reacties ging en hij niet achter z'n post staat) had ik van hem niet verwacht.
Lol, nee het was niet als troll bedoeld. Het was bedoeld als simpele, werkende oplossing in 3 regels nadat er 12 posts was geruzied over de 'correcte' oplossing (lullig dat ik die whitespace was vergeten). Ik had gisteravond express nog niet gepost omdat ik geen zin had in de 'maar dat is geen C++'-discussie, maar vanochtend verveelde ik me wat meer, eindejaar dus weinig te doen op het werk :P

Ennuh:
Waarom? Ik heb een aantal argumenten aangedragen waarom ik die benadering juist slechter vind, vind je die argumenten ongeldig of misschien irrelevant? Of zijn er misschien voordelen van scanf/printf die ik over het hoofd zie?
Zoals farlane al zegt is (s)printf indien goed gebruikt een fantastische functie, en van (s)scanf ben ik zelf eerlijk gezegd ook nooit zo'n fan geweest: fgets was ook veel beter, zo lang is het al geleden voor mij ;)

Ik neem een voorbeeld uit een profile report dumper die ik heb geschreven:
C++:
1
printf("%-40s | %3d | %5.2f", l_MethodName, l_TimesCalled, l_AvgTimePerCall);

• Ik weet wat ik erin stop dus ik ben typesafe
• Ik krijg automatische formatting
• Een methodname > 40 chars wordt geclipped.
• Automatische formatting van die float op 2 cijfers achter de komma

Voordelen genoeg, indien met verstand gebruikt :) Ik zeg allesbehalve dat printf altijd een fantastische oplossing is, maar voor formatted output onverslaanbaar.

Professionele website nodig?


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17:57

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ik vindt de formatting van printf ook lekkerder werken, hoewel het overloaden van de << operator voor je eigen types ook rete-handig is. Ik gebruik meestal ook gewoon std::ostream, maar als ik echt goede formatting nodig heb gebruik ik toch echt v?(f|s)?printf, aangezien ik het gewoonweg lomp vind om allerlei methoden aan te roepen of manipulators in de stream te shiften, en ook nog eens de vorige status bij te houden zodat je die weer terug kan zetten, zodat je anderen niet opscheept met jouw specifieke formatting.

[ Voor 3% gewijzigd door .oisyn op 19-12-2002 15:30 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21-08 17:14
Tips:
http://www.boost.org/libs/format/index.htm (typesafe formatter in printf stijl)
code:
1
cout << format("writing %s,  x=%s : %d-th step \n") % "toto" % 40.23 % 50;


http://www.boost.org/libs/io/doc/ios_state.html ( IO state savers)
code:
1
boost::io::ios_flags_saver  ifs( std::cout );

Als je je afvraagt hoe ifs werkt , de dtor reset de std::cout state. Dus bij elke scope exit wordt std::cout naar de originele toestand teruggezet - het zgn RAII idioom.

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