mikrocontroller.net

Forum: PC-Programmierung Schleife mit ESC-abbruch geht das?


Autor: moony (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du solltest den Rückgabewert von cin.get() auch auswerten ... Du weist 
ihn aber keiner Variablen zu.
Versuche mal folgendes

  abbruch = cin.get();

Autor: moony (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: moony (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: déjà vu (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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};

Autor: Thomas B. (yahp) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Bobby (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Leute helft mir mal:

Das mit den Signals kenn ich bisher nur
von Linux. Gibt es das auch bei Windows ?

Autor: t.danielzik (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo moony,

du must die Zeile cin.get() auch innerhalb der do Schleife einfügen.

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

dann sollte es gehen.

Autor: moony (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: moony (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Guck mal in die Doku - cin.getc hat einen Referenzparameter...

Die Parameter bei Funktionen in verbalen Beschreibungen wegzulassen, ist 
bequem und üblich, wird aber vom Compiler nicht toleriert.

Autor: moony (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht 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.as...
gelistet. Ich hatte einfach auf 
http://msdn2.microsoft.com/en-us/library/ nach getc - ohne Objekt und 
Klammern - gesucht.

Autor: moony (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok. Jetzt klappt alles.
Vielen Dank an alle und Bis zum nächstem Problem.

Gruß

moony

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist dir eigentlich klar, warum der Compiler

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

schimpft, wenn du ihm cin.getc(); zu fressen gibst? Es gibt doch 
istream::getc...

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.