Toon posts:

[C++] Voorkomen dat een programma in een while loop blijft

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

Verwijderd

Topicstarter
Ik heb dit stukje code:

C++:
1
2
3
4
5
while (c != ']')
{
   c =  com->getChar();
   sData = sData + c;
}


Wanneer ik op een button druk voert hij dit stukje code uit. De microcontroller stuurt *als het goed is* zo'n soort code: "[|Dit is een woord|en dit ook !|]"
Nu wil het nog wel eens voorkomen dat het "]" byte niet overkomt. Gevolg: programma blijft hangen omdat hij eeuwig in de while loop blijft, de COM poort wordt niet gesloten -> dus rebooten om weer te kunnen gebruiken.

Hoe zou ik er voor kunnen zorgen dat als ik op Cancel druk deze routine wordt overgeslagen?

[ Voor 27% gewijzigd door Verwijderd op 13-12-2002 17:39 ]


  • mulder
  • Registratie: Augustus 2001
  • Laatst online: 00:27

mulder

ik spuug op het trottoir

Je moet dan checken in de loop of er op een toets gedrukt is. Nu is mijn C++ kennis heel erg summier, moet er zal wel zoiets zijn als een ('keyboard')buffer waar toetsaanslagen worden gequed.

oogjes open, snaveltjes dicht


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21-08 17:14
Uit m'n hoofd: cin.rdbuf()->in_avail() geeft aan of er keybord input beschikbaar is.
ESC zal alleen niet gedetecteerd worden, omdat dat geen karakter is. Daarvoor moet je naar OS-specifieke methoden toe, dus welk OS gebruik je?

[ Voor 50% gewijzigd door MSalters op 13-12-2002 18:00 . Reden: Esc is geen karakter ]

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


  • mulder
  • Registratie: Augustus 2001
  • Laatst online: 00:27

mulder

ik spuug op het trottoir

ik lees net kbhit of _kbhit. Misschien dat iemand de verschillen kan toelichten

btw, hierzo:
http://www.digitalmars.com/rtl/conio.html

[ Voor 28% gewijzigd door mulder op 13-12-2002 17:59 ]

oogjes open, snaveltjes dicht


  • Chieliot
  • Registratie: September 2001
  • Laatst online: 04-12-2025
Ben niet zo met C++ bezig maar ken je niet zeggen:

code:
1
while (c != ']' && c != NULL) {


Ofzo iets?

[ Voor 18% gewijzigd door Chieliot op 13-12-2002 18:21 ]

AMD XP1800+, 512MB Intern, Maxtor 160Gig, Matrox G550 32 DDR Dual Head in een Chieftec DX-01-SLD


  • Orphix
  • Registratie: Februari 2000
  • Niet online
Ik geloof dat Toverstaf met een grafische interface werkt dus gaan voorgaande oplossingen niet op.
Welke omgeving gebruik je?

Trouwens ... is het niet misschien verstandiger om erachter proberen te komen waarom de ] soms niet aankomt?! Het probleem bij de wortel aanpakken is natuurlijk beter dan een soort workaround.

[ Voor 46% gewijzigd door Orphix op 13-12-2002 18:31 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:18

.oisyn

Moderator Devschuur®

Demotivational Speaker

MSalters schreef op 13 december 2002 @ 17:58:
Uit m'n hoofd: cin.rdbuf()->in_avail() geeft aan of er keybord input beschikbaar is.
ESC zal alleen niet gedetecteerd worden, omdat dat geen karakter is. Daarvoor moet je naar OS-specifieke methoden toe, dus welk OS gebruik je?


werkt dat?
Probeerde ik laatst in MSVC 7.1, en toen wilde het niet

Is op zich ook logisch als je erover nadenkt: in de streambuf staan een paar gebufferde chars. Die worden gebufferd tijdens een inleesactie. Als jij echter niets inleest, maar je drukt tijdens de loop van je programma op een toets, dan zal die toetsaanslag niet zomaar 'op miraculeuze wijze' in je streambuf buffer terecht komen
(ok, streambuf::showmanyc () zou natuurlijk op een OS specifieke manier geimplementeerd kunnen worden, maar is er een garantie dat dat ook daadwerkelijk zo is bij de keyboardbuffer waar cin gebruik van maakt?)

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
Ik werk in C++ Builder 5; en het MOET "Windows versie" onafhankelijk zijn... dat is echt noodzakelijk ('t was al een heel gedoe om de compoort zowel onder NT als onder 9x werkend te krijgen)

Op zich werkt de communicatie tussen microcontroller en computer voor de rest perfect, maar het product is bedoelt voor 65+ 'ers. En die mensen willen nog wel eens een kabel eruit trekken / controller uitzetten... op zo'n moment komt het ']' teken dus nooit aan.

Maar het is dus niet zo simpel om een while loop te "verbreken"? Ik had zelf dit in gedachten:

C++:
1
2
3
4
5
while !(c = ']' || btnCancel->Execute()) 
{ 
   c =  com->getChar(); 
   sData = sData + c; 
}


Maar dat werkt dus niet :(
De compiler zegt dan namelijk dat je geen functie als voorwaarde mag gebruiken.

[ Voor 12% gewijzigd door Verwijderd op 13-12-2002 19:20 ]


  • mulder
  • Registratie: Augustus 2001
  • Laatst online: 00:27

mulder

ik spuug op het trottoir

Maar komt er toch geen data meer door? Of begint weer met een '['? Stel dat eerst eens vast...

[ Voor 8% gewijzigd door mulder op 13-12-2002 19:24 ]

oogjes open, snaveltjes dicht


Verwijderd

Topicstarter
Don Facundo schreef op 13 december 2002 @ 19:23:
Maar komt er toch geen data meer door? Of begint weer met een '['? Stel dat eerst eens vast...
explain please :)

  • mulder
  • Registratie: Augustus 2001
  • Laatst online: 00:27

mulder

ik spuug op het trottoir

Ik bedoel, je zegt de stekker gaat er uit. Er komt dan geen data meer door: conditie voor een check. Anders, er komt geen ']'.. wat dan wel? De volgende message? Dus een '['?. Conditie.

oogjes open, snaveltjes dicht


Verwijderd

Topicstarter
Don Facundo schreef op 13 december 2002 @ 19:32:
Ik bedoel, je zegt de stekker gaat er uit. Er komt dan geen data meer door: conditie voor een check. Anders, er komt geen ']'.. wat dan wel? De volgende message? Dus een '['?. Conditie.
Nee; er worden geen acknowledgement bits gebruikt.
Dus een rotte verbinding zorgt voor rotte informatie om het maar kort te zeggen :)

Het is puur en alleen als er bijvoorbeeld op "Receive" wordt gedrukt je deze routine ook weer kunt stoppen... bijvoorbeeld omdat degene de kabel eruit heeft getrokken, of misschien wel omdat hij / zij erachter komt dat de stok nog in de auto ligt.... etc etc

De verbinding ansich is gewoon goed; maar ik wil het proces gewoon op ieder moment kunnen onderbreken.

  • mulder
  • Registratie: Augustus 2001
  • Laatst online: 00:27

mulder

ik spuug op het trottoir

Dan moet het met een simpele boolean toch kunnen werken. Voor dat de loop begint zet je deze op false. Een cancel button zet deze op true. Deze boolean kun je dus in je while-loop conditie plaatsen. Nu kan het zijn dat de klik er niet door komt.. je zit nl in een loop. Zover ik weet heeft Delphi Application.ProccessMessages, en ik meen dat je BCB gebruikt en dus zal hier een dergelijk functie, zo niet gelijk, beschikbaar voor zijn.

[ Voor 10% gewijzigd door mulder op 13-12-2002 19:41 ]

oogjes open, snaveltjes dicht


  • Shadowman
  • Registratie: Januari 2002
  • Niet online
Even zomaar.
Het kan zijn dat een string pas wordt gelezen na een enter. zet er is in de while-loop:
cout << c;
en kijk of het dan werkt. dan weet je ook zeker dat die in de loop komt

Verwijderd

Topicstarter
Shadowman schreef op 13 December 2002 @ 19:45:
Even zomaar.
Het kan zijn dat een string pas wordt gelezen na een enter. zet er is in de while-loop:
cout << c;
en kijk of het dan werkt. dan weet je ook zeker dat die in de loop komt
Hij komt gewoon in de loop. Er is niets mis met de code :)
Werk trouwens met Builder.... geen command progsels.

  • Shadowman
  • Registratie: Januari 2002
  • Niet online
Ik werk meer met QT (onder linux) maar kan je die code niet in een aparte thread zetten die je cancelled als je op de cancel-button klikt.
(is geloof ik wel mogelijk in QT, misschien ook in Builder)

  • TRON
  • Registratie: September 2001
  • Laatst online: 16-08 07:26
misschien is het dom hoor... maar ehh... kan dit niet?

C++:
1
2
3
4
5
6
7
while !(c = ']' || btnCancel->Execute())  
{  
   i =+ i + 1;                  // verkorte notatie dan he ;)
   c =  com->getChar();  
   sData = sData + c;  
   if (i > 10) {EXIT THIS F-ING LOOP;}
}


Het is wel omslachtig...

[ Voor 24% gewijzigd door TRON op 13-12-2002 19:54 ]

Leren door te strijden? Dat doe je op CTFSpel.nl. Vraag een gratis proefpakket aan t.w.v. EUR 50 (excl. BTW)


  • CyberSnooP
  • Registratie: Augustus 2000
  • Laatst online: 31-03 16:47

CyberSnooP

^^^^ schrijft --->

Wanneer eindigt de aanroep com->getChar();?
Wacht die net zolang totdat er nieuw karakter in de invoerbuffer van de seriële-poort beschikbaar is? Dan heb je een klein beetje een probleem, aangezien je code gewoon op dat punt blijft hangen.

Of zit er een time-out op? (dat kan in het geval van Windows), dan kun je die time-out detecteren. Zorg dat er op dat moment in je com-object een boolean (bijv. timed_out) op true komt te staan. Die boolean zet je vervolgens in je while-condititie.

BTW.. wat TRON hierboven probeert te bereiken is me totaal onduidelijk? De loop altijd na 10 ontvangen karakters beëindigen?

[ Voor 12% gewijzigd door CyberSnooP op 13-12-2002 19:59 ]

|_____vakje______|


  • Shadowman
  • Registratie: Januari 2002
  • Niet online
TRON schreef op 13 december 2002 @ 19:53:
misschien is het dom hoor... maar ehh... kan dit niet?

C++:
1
2
while !(c = ']' || btnCancel->Execute())  
...


Het is wel omslachtig...
nee dit kan niet want er werd al eerder opgemerkt dat btnCancel->Execute() niet als argument mag worden meegegeven.

  • TRON
  • Registratie: September 2001
  • Laatst online: 16-08 07:26
Sorry... die btnCancel->Execute() hoort daar natuurlijk niet te staan |:( |:( |:(

Leren door te strijden? Dat doe je op CTFSpel.nl. Vraag een gratis proefpakket aan t.w.v. EUR 50 (excl. BTW)


  • EfBe
  • Registratie: Januari 2000
  • Niet online
Blijft hij niet gewoon in die c = com->getChar(); routine hangen? Indien het mogelijk is is het wellicht verstandig juist die routine robuster te maken, dus dat die getChar() routine altijd eindigt, bv met een timeout, welke getriggerd wordt door een timertje / eventhandler

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


Verwijderd

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
bool buttonClicked = false;

void __fastcall TForm1::Button1Click(TObject *Sender)
{
    buttonClicked = true;
}

void blabla()
{
    while (c != ']' && !buttonClicked) 
    { 
        c =  com->getChar(); 
        sData = sData + c; 
    }
}

zoiets :?

[ Voor 6% gewijzigd door Verwijderd op 13-12-2002 20:36 . Reden: mooier :P ]


  • EfBe
  • Registratie: Januari 2000
  • Niet online
Verwijderd schreef op 13 December 2002 @ 20:35:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
bool buttonClicked = false;

void __fastcall TForm1::Button1Click(TObject *Sender)
{
    buttonClicked = true;
}

void blabla()
{
    while (c != ']' && !buttonClicked) 
    { 
        c =  com->getChar(); 
        sData = sData + c; 
    }
}
zoiets :?
In een single thread werkt dit niet, volgens mij. Hij giert als een gek in die while-loop rond en als hij in die whileloop zit moet je via een andere thread die buttonClicked op true kunnen krijgen. Maar ik heb het vermoeden dat c = com->getChar(); nooit returned. Indien wel, dan kan er ook gewoon een timertje worden gestart die de volatile declared quitLoop bool dan bv op true zet, middels een andere thread.

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


Verwijderd

Topicstarter
Mmm, bedankt voor het meedenken iedereen :)
Wanneer eindigt de aanroep com->getChar();?
Wacht die net zolang totdat er nieuw karakter in de invoerbuffer van de seriële-poort beschikbaar is? Dan heb je een klein beetje een probleem, aangezien je code gewoon op dat punt blijft hangen.
Yupz, hij wacht net zo lang totdat het "]" karakter voorbij is gekomen. Ik kan dus nu op "Start" drukken en morgen vroeg wacht hij nog steeds; er komt dus geen time-out.

Ik vind het een beetje overkill om een thread te gaan gebruiken... ik zal eens kijken naar een timertje.
Ik maak dan een genestelde while loop; als de timer bijvoorbeeld 10 seconden heeft geteld (een overdracht duurt rond de 0.5 seconden) stopt hij de while loop.

Is alleen nog de vraag of hij dan weer niet in die genestelde while loop blijft hangen, ik hoop het niet :)
k ga even knutselen :)

  • EfBe
  • Registratie: Januari 2000
  • Niet online
Ik denk dat je niet aan een aparte thread ontkomt, je timertje moet bij het aflopen iets doen. Als hij een event genereert zie jij die nooit voorbijkomen :) Kan je timertje een routine aanroepen bij afvuren en doet hij dat ook (system roept dan jouw callback aan), dan kun je daar een volatile var zetten. :)

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


Verwijderd

Verwijderd schreef op 13 december 2002 @ 21:20:
Mmm, bedankt voor het meedenken iedereen :)


[...]

Yupz, hij wacht net zo lang totdat het "]" karakter voorbij is gekomen. Ik kan dus nu op "Start" drukken en morgen vroeg wacht hij nog steeds; er komt dus geen time-out.

Ik vind het een beetje overkill om een thread te gaan gebruiken... ik zal eens kijken naar een timertje.
Ik maak dan een genestelde while loop; als de timer bijvoorbeeld 10 seconden heeft geteld (een overdracht duurt rond de 0.5 seconden) stopt hij de while loop.

Is alleen nog de vraag of hij dan weer niet in die genestelde while loop blijft hangen, ik hoop het niet :)
k ga even knutselen :)
Wat denk je wat die timer is dan? Ook een extra thread :P Alleen is die oplossing niet zo mooi imho.

  • Lone Gunman
  • Registratie: Juni 1999
  • Niet online
k weet niet hoe je je serieele communicatie precies afhandelt, maar als je de standaard voorzieningen van windows gebruikt kan je netjes afvangen wanneer de receive buffer leeg is. Als je dan ook nog zorgt dat je een receive buffer hebt, kan je gewoon de hele stream ineens controleren ipv per character.

Experience has taught me that interest begets expectation, and expectation begets disappointment, so the key to avoiding disappointment is to avoid interest.


Verwijderd

even in een soort pseudo code (geen C++ programmeur)

code:
1
2
3
4
5
repeat
  c = com->getChar();  
  k = LeesToetsenbordbuffer
  sData = sData + c;
until c=']' or k='ESC'


nou ja, het ziet er niet uit, maar het idee is duidelijk denk ik..

[ Voor 11% gewijzigd door Verwijderd op 14-12-2002 00:04 ]


  • mulder
  • Registratie: Augustus 2001
  • Laatst online: 00:27

mulder

ik spuug op het trottoir

Application->ProcessMessages bestaat volgens Google, dus je kunt gewoon die methode gebruiken die ik eerder heb gepost.

oogjes open, snaveltjes dicht


Verwijderd

Je mag op een com-port toch gewoon een ReadFile doen?
Die kan je namelijk overlapped (=nonblocking) doen, zodat je op zeer eenvoudige wijze een timeout of een user-abort kan toepassen...

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21-08 17:14
Akhorahil heeft de elegantste oplossing tot nu toe. Je kunt overigens ook SetCommTimeouts( ) gebruiken om te detecteren dat je vast zit in je ReadFile call.

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