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
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
> 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.
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
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.
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.
>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};
> 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.
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.
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
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.
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.
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
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.
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
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...