Schleife mit ESC-abbruch geht das?

Gast #637629
Lesenswert?

Hi!

Ich habe auch erst mit VC++ angefangen, und nachdem ich jetzt mal ein 
paar Tutorials durchgearbeitet habe, wollte ich mal ein eigenes Programm 
schreiben. Aber jetzt hänge ich an einer Stele fest.

Ich habe in einer case-Anweisung eine do-while-Schleife. Ich will es so 
haben, dass der compiler so lange die Schleifenanweisungen macht, bis 
der jemand die ESC-Taste gedrückt hat. Leider klappt das bei mir nicht.

Ich habe geschrieben:

int abbruch;
...

#define   ESC      27

...

case 2:
  {
    cin.get();
    do
    {
         printf("Hallo");
    }
    while (abbruch != ESC);
  }
break;

...

Das Programm zeigt mir aber immer nur das Wort "Hallo" aus.
Was kann ich da jetzt tun?

Danke & gruß
Moony
Gast #637647
Lesenswert?

ja, das hatte ich auch schon. Das hat zwar funktioniert, aber ich wollte 
unbedingt abbruch auf ESC haben, da ich noch etliches in die Shcleife 
reinmachen werde, und dann auch sicher mal zwischendurch cin.get() 
verwenden werde. Wenn es dann so weit ist, beendet er mitten in der 
Schleife, und das wäre nicht so schön. :-)

Hat jemand noch eine Idee wie man das machen könnte?

ich habe vergessen dazuzusagen, dass die do-while Schleife nicht 
zwingent nötig ist. Einfach nur eine Schleife, die zuende sein sollte, 
wenn man ESC drückt.

Dank & Gruß

moony
Persönliche Seite #637656
Lesenswert?

> ja, das hatte ich auch schon. Das hat zwar funktioniert, aber ich wollte
> unbedingt abbruch auf ESC haben, da ich noch etliches in die Shcleife
> reinmachen werde, und dann auch sicher mal zwischendurch cin.get()
> verwenden werde. Wenn es dann so weit ist, beendet er mitten in der
> Schleife, und das wäre nicht so schön. :-)

Lies Dir das bitte nochmal durch. Verstehst Du das, was Du da 
geschrieben hast?

Ich nicht.
Gast #637657
Lesenswert?

ja, ich verstehe das.

Ich meinte:

Wenn ich die Schleife abbrechen lasse, wenn man ENTER drückt, und dann 
noch in die Schleife schreibe, dass er weitermachen soll wenn man ENTER 
drückt, dann bricht er an der Stelle ab, wo es eigentlich weitergehen 
soll wenn man ENTER drückt. und das wäre nicht so schön.

Jetzt verstanden?

Moony
Gast #637670
Lesenswert?

Dann liegt das Problem aber in der Programmlogik. Du musst dir also 
erstmal selbst darüber klar werden, was das Programm mit welchem 
Tastendruck zu welchem Zeitpunkt anfangen soll.

Ein Kommandozeilen-Tool bricht man übrigens üblicherweise nicht mit 
Escape ab, sondern mit Signalen wie SIGINT, das durch den Tastendruck 
Strg-C erzeugt wird.
#637865
Lesenswert?

Chris wrote:
> Ein Kommandozeilen-Tool bricht man übrigens üblicherweise nicht mit
> Escape ab, sondern mit Signalen wie SIGINT, das durch den Tastendruck
> Strg-C erzeugt wird.

Das stimmt so nicht. Strg-C killt das Programm, d.h., es wird dort 
beendet, wo es sich gerade befindet. Ein reguläres Beenden ist so nicht 
möglich.

Die Idee, ESC zu verwenden, um die Schleife zu beenden und dann evtl. 
regulär zu terminieren, oder auch irgendwas anderes zu machen, ist weder 
exotisch, noch falsch, sondern durchaus naheliegend.

@moony
Versuchs mal mit cin.getc(abbruch); -- abbruch muß dann allerdings als 
char definiert sein.
Gast #637872
Lesenswert?

>Das stimmt so nicht. Strg-C killt das Programm, d.h., es wird dort
>beendet, wo es sich gerade befindet. Ein reguläres Beenden ist so nicht
>möglich.
Das stimmt so aber auch nicht. Ich weiss nicht, wie das C-Aequivalent 
ist, aber mit PERL geht ein sauberers Beenden bei Strg-C so:

SIG{INT} = sub { do_this_and_that(); exit 0};
Persönliche Seite #637875
Lesenswert?

> Das stimmt so nicht. Strg-C killt das Programm, d.h., es wird dort
> beendet, wo es sich gerade befindet. Ein reguläres Beenden ist so nicht
> möglich.

Das ist doch auch Quatsch. Ein vernüftiges Programm wird einen 
Signalhandler für SIGINT und Konsorten implementieren und dann die 
Signale mit vernünftigem Beenden verarbeiten.
Gast #638241
Lesenswert?

Hi all!

Ich habe jetzt alle eure tipps mal ausprobiert aber es funktioniert 
immer noch nicht. :-/

Das programm beendet immer noch nicht, wenn man ESC drückt. Gibt es in 
VC++ nicht so etwas wie in Pascal...

repeat

<das und das>

until keypessed = ESC;

???

Danke an alle & Gruß

moony
#638290
Lesenswert?

Ich hab nochmal etwas nachgedacht... Mit cin.get() oder cin.getc() kann 
es aus einem ganz einfachen Grund nicht gehen: Diese Funktionen warten, 
bis eine Eingabe anliegt, d.h. deine Schleife stoppt so lange, bis eine 
Eingabe kam.

Die Lösung: Du must in der Schleife feststellen, ob überhaupt ein 
Zeichen im Puffer steht. Erst wenn das der Fall ist, holst du es mit 
cin.getc() ab und wertest es aus.

Die Abfrage, ob ein Zeichen vorhanden ist, ist über den an cin istream 
streambuf möglich. An diesen streambuf kann man folgendermaßen kommen:

   streambuf *pCon = cin.rdbuf();

rdbuf ist eine Memberfunktion der Basisklasse ios.

Aus dem streambuf erhält man die Anzahl der unverarbeiteten Zeichen mit

   streamsize sSize = pCon->in_avail();

Wenn man nun die ganze Schose zusammensetzt, erhält man folgenden 
Ausdruck, um die Anzahl der in cin bereitstehenden Zeichen abzufragen:

   if (cin.rdbuf()->in_avl() > 0)
      <hole und verarbeite das Zeichen>

Eventuell könnte man es auch kürzer machen, aber ich mir nicht sicher, 
ob das funktioniert: Man ruft cin.peek(). Die sieht nur im Puffer nach, 
was das nächste Zeichen ist. Wenn cin.peek() auch dann zurückkehrt, wenn 
kein Zeichen anliegt, geht es damit, wenn sie wartet, hast du Pech 
gehabt... Wie sie sich verhält, wenn der Puffer leer ist, habe ich auf 
die Schnelle leider nicht gefunden.
#638319
Lesenswert?

Uhu Uhuhu wrote:

> Die Abfrage, ob ein Zeichen vorhanden ist, ist über den an cin istream
> streambuf möglich. An diesen streambuf kann man folgendermaßen kommen:
>
>    streambuf *pCon = cin.rdbuf();
>
> rdbuf ist eine Memberfunktion der Basisklasse ios.
>
> Aus dem streambuf erhält man die Anzahl der unverarbeiteten Zeichen mit
>
>    streamsize sSize = pCon->in_avail();
>
> Wenn man nun die ganze Schose zusammensetzt, erhält man folgenden
> Ausdruck, um die Anzahl der in cin bereitstehenden Zeichen abzufragen:
>
>    if (cin.rdbuf()->in_avl() > 0)
>       <hole und verarbeite das Zeichen>

Das kann das Problem lösen, muss es aber nicht. Denn: Wie kommen
denn die Zeichen in den stream Buffer hinein? Niemand sagt, dass
bei einem Aufruf von rdbuf oder in_avail auch alle Zeichen, die
vom BS gepuffert wurden, auch übernommen werden.

In C++ gibt es grundsätzlich kein dezidiertes 'keyboard' und damit
auch keine Möglichkeit festzustellen ob eine Taste gedrückt wurde
oder nicht.

Alle 100% Lösungen zu diesem Thema sind immer Platformabhängig.


Oft gibt es eine Funktion namens kbhit(), die genau das macht:
Beim Betriebssystem nachfragen, ob ein Tastendruck vorliegt.
Gast #638335
Lesenswert?

Nachdem ich jetzt die ganze Schose in eine for(;;)-Schleife gemacht 
habe, und versucht habe die Zeichen mit cin.getc() abzuholen, zeigte er 
mir die Fehlermeldungen an:

error C2039: 'getc': Ist kein Element von 
'std::basic_istream<_Elem,_Traits>'

Was kann ich da jetzt tun? Habe ich irgentetwas falsch gemacht oder 
vergessen?

Gruß

moony
Gast #638380
Lesenswert?

Ich habe jetzt mal in der Doku und auch auf 
msdn2.microsoft.com/en-us/library/ nachgesehen. Er findet nicht einmal 
cin.getc()!

Welchen Referenzparameter meinst du denn?

Auch wenn die Frage dumm ist, beantworte sie mir bitte trotzdem.
moony
#638438
Lesenswert?

Da stehts: Beitrag "Re: Schleife mit ESC-abbruch geht das?"

Ansonsten: Googel einfach mal nach cin.getc - aber wenn es gelingt, die 
Anzahl der vorhandenen Zeichen abzufragen, kannst du evtl. auch get 
verwenden, wenn dein Compiler getc nicht kennt.

getc steht auf 
http://search.msdn.microsoft.com/search/Default.aspx?query=getc&brand=msdn&locale=en-us&refinement=00&lang=en-us
gelistet. Ich hatte einfach auf 
http://msdn2.microsoft.com/en-us/library/ nach getc - ohne Objekt und 
Klammern - gesucht.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren