Erfassen Sie Zeichen aus der Standardeingabe, ohne auf das Drücken der Eingabetaste zu warten
Lesezeit: 8 Minuten
Adam
Ich kann mich nie erinnern, wie ich das mache, weil es so selten für mich vorkommt. Aber in C oder C++, was ist der beste Weg, um ein Zeichen von der Standardeingabe zu lesen, ohne auf einen Zeilenumbruch zu warten (drücken Sie die Eingabetaste).
Idealerweise würde es das eingegebene Zeichen auch nicht auf dem Bildschirm wiedergeben. Ich möchte nur Tastenanschläge erfassen, ohne den Konsolenbildschirm zu beeinflussen.
@adam – Können Sie klarstellen: Möchten Sie eine Funktion, die sofort zurückkehrt, wenn kein Zeichen verfügbar ist, oder eine, die immer auf einen einzelnen Tastendruck wartet?
– Roddy
8. Januar 2009 um 9:47 Uhr
@Roddy – Ich möchte eine Funktion, die immer auf einen einzelnen Tastendruck wartet.
– Adam
28. Mai 2009 um 4:52 Uhr
Johannes Schaub – litb
Das ist portabel in reinem C++ nicht möglich, da es zu sehr vom verwendeten Endgerät abhängt, mit dem man sich verbinden kann stdin (sie sind normalerweise zeilengepuffert). Sie können dafür jedoch eine Bibliothek verwenden:
conio verfügbar mit Windows-Compilern. Verwenden Sie die _getch() Funktion, um Ihnen ein Zeichen zu geben, ohne auf die Eingabetaste zu warten. Ich bin kein häufiger Windows-Entwickler, aber ich habe gesehen, dass meine Klassenkameraden einfach enthalten <conio.h> und benutze es. Sehen conio.h bei Wikipedia. Es listet auf getch()die in Visual C++ als veraltet deklariert ist.
Flüche für Linux verfügbar. Kompatible Curses-Implementierungen sind auch für Windows verfügbar. Es hat auch eine getch() Funktion. (Versuchen man getch um seine Manpage anzuzeigen). Sehen Flüche bei Wikipedia.
Ich würde Ihnen empfehlen, Flüche zu verwenden, wenn Sie plattformübergreifende Kompatibilität anstreben. Ich bin mir jedoch sicher, dass es Funktionen gibt, mit denen Sie die Zeilenpufferung ausschalten können (ich glaube, das heißt “Raw-Modus” im Gegensatz zum “Cooked-Modus” – schauen Sie sich das an man stty). Wenn ich mich nicht irre, würden Curses das auf tragbare Weise für Sie erledigen.
Beachten Sie, dass heutzutage ncurses ist die empfohlene Variante von curses.
– Nik
7. Mai 2016 um 3:04 Uhr
Wenn Sie eine Bibliothek brauchen, wie haben sie es dann gemacht? Um die Bibliothek zu erstellen, mussten Sie sie sicherlich programmieren, und das bedeutet, dass jeder sie programmieren könnte. Warum können wir also nicht einfach den Bibliothekscode programmieren, den wir selbst benötigen? das würde das auch machen Das ist in reinem C++ unmöglich portierbar falsch
– Benutzer6053405
3. Januar 2017 um 9:49 Uhr
@kid8 verstehe ich nicht
– Johannes Schaub – litb
3. Januar 2017 um 16:51 Uhr
@JohannesSchaub-litb er versucht wahrscheinlich zu sagen, wie der Bibliotheksimplementierer diese portable Methode in reinem c/c++ erstellt hat, wenn Sie sagen, dass dies nicht möglich ist.
– Abhinav Gauniyal
18. Januar 2017 um 2:30 Uhr
@AbhinavGauniyal ah, ich verstehe. Ich habe jedoch nicht gesagt, dass die Bibliotheks-Implementierer keine portablen Methoden erstellt haben (dh von einigermaßen portablen Programmen verwendet werden können). Ich habe angedeutet, dass sie kein portables C++ verwendet haben. Da dies offensichtlich nicht der Fall ist, verstehe ich nicht, warum sein Kommentar besagt, dass dieser Teil meiner Antwort falsch ist.
– Johannes Schaub – litb
18. Januar 2017 um 13:51 Uhr
Unter Linux (und anderen Unix-ähnlichen Systemen) kann dies auf folgende Weise erfolgen:
Grundsätzlich müssen Sie den kanonischen Modus (und den Echomodus zur Unterdrückung von Echos) ausschalten.
Ich habe versucht, diesen Code zu implementieren, aber ich habe einen Fehler beim Aufruf von erhalten read. Ich habe beide Header eingefügt.
– Michael Dorst
21. Juli 2012 um 1:59 Uhr
Möglicherweise, weil dieser Code falsch ist, da read() ein in unistd.h definierter POSIX-Systemaufruf ist. stdio.h könnte es zufällig enthalten, aber Sie brauchen stdio.h für diesen Code überhaupt nicht; Ersetzen Sie es durch unistd.h und es sollte gut sein.
– Falke Momot
22. Juli 2012 um 13:41 Uhr
Ich weiß nicht, wie ich hier gelandet bin, während ich nach Tastatureingaben am ROS-Terminal in Raspberry Pi gesucht habe. Dieser Codeschnipsel funktioniert bei mir.
– ja
23. März 2015 um 9:07 Uhr
@FalconMomot In meiner NetBeans IDE 8.1 (bei Kali Linux) heißt es: error: ‘perror’ was not declared in this scope beim Kompilieren, funktioniert aber gut, wenn es enthalten ist stdio.h zusammen mit unistd.h.
– Abhishek Kashyap
5. August 2016 um 22:37 Uhr
Gibt es eine einfache Möglichkeit, dies so zu erweitern, dass es nicht blockiert?
– Joe Strout
21. Juli 2017 um 14:21 Uhr
cwiii
Ich habe dies in einem anderen Forum gefunden, als ich nach der Lösung des gleichen Problems suchte. Ich habe es ein wenig von dem, was ich gefunden habe, modifiziert. Es funktioniert großartig. Ich verwende OS X. Wenn Sie also Microsoft ausführen, müssen Sie den richtigen system() -Befehl finden, um in den Raw- und den Cooked-Modus zu wechseln.
#include <iostream>
#include <stdio.h>
using namespace std;
int main() {
// Output prompt
cout << "Press any key to continue..." << endl;
// Set terminal to raw mode
system("stty raw");
// Wait for single character
char input = getchar();
// Echo input:
cout << "--" << input << "--";
// Reset terminal to normal "cooked" mode
system("stty cooked");
// And we're out of here
return 0;
}
Obwohl dies funktioniert, ist es meiner Meinung nach selten der “beste” Weg, das System zu berappen. Das stty-Programm ist in C geschrieben, sodass Sie oder einschließen und denselben Code aufrufen können, den stty verwendet, ohne von einem externen Programm/Fork/whatnot abhängig zu sein.
– Chris Lutz
26. Mai 2009 um 21:29 Uhr
Ich brauchte das für zufällige Proof-of-Concept-Sachen und Herumspielen. Genau das, was ich brauchte. Danke. Es sollte beachtet werden: Ich würde auf jeden Fall das stty cooked an das Ende des Programms stellen, sonst bleibt Ihre Shell im stty raw-Modus, was im Grunde genommen meine Shell kaputt gemacht hat, lol, nachdem das Programm gestoppt wurde.
– Benjamin
4. November 2014 um 5:32 Uhr
Ich glaube, du hast es vergessen #include <stdlib.h>
– NerdOfCode
9. Juni 2018 um 5:35 Uhr
Verwenden system ist eine sehr schlechte idee.
– Saphir_Ziegel
21. August 2020 um 16:40 Uhr
CONIO.H
Die Funktionen, die Sie benötigen, sind:
int getch();
Prototype
int _getch(void);
Description
_getch obtains a character from stdin. Input is unbuffered, and this
routine will return as soon as a character is available without
waiting for a carriage return. The character is not echoed to stdout.
_getch bypasses the normal buffering done by getchar and getc. ungetc
cannot be used with _getch.
Synonym
Function: getch
int kbhit();
Description
Checks if a keyboard key has been pressed but not yet read.
Return Value
Returns a non-zero value if a key was pressed. Otherwise, returns 0.
Dies nutzt kbhit() um zu überprüfen, ob die Tastatur gedrückt und verwendet wird getch() um das gedrückte Zeichen zu erhalten.
sinfod
Ich verwende kbhit(), um zu sehen, ob ein Zeichen vorhanden ist, und dann getchar(), um die Daten zu lesen. Unter Windows können Sie “conio.h” verwenden. Unter Linux müssen Sie Ihr eigenes kbhit() implementieren.
Siehe Code unten:
// kbhit
#include <stdio.h>
#include <sys/ioctl.h> // For FIONREAD
#include <termios.h>
#include <stdbool.h>
int kbhit(void) {
static bool initflag = false;
static const int STDIN = 0;
if (!initflag) {
// Use termios to turn off line buffering
struct termios term;
tcgetattr(STDIN, &term);
term.c_lflag &= ~ICANON;
tcsetattr(STDIN, TCSANOW, &term);
setbuf(stdin, NULL);
initflag = true;
}
int nbbytes;
ioctl(STDIN, FIONREAD, &nbbytes); // 0 is STDIN
return nbbytes;
}
// main
#include <unistd.h>
int main(int argc, char** argv) {
char c;
//setbuf(stdout, NULL); // Optional: No buffering.
//setbuf(stdin, NULL); // Optional: No buffering.
printf("Press key");
while (!kbhit()) {
printf(".");
fflush(stdout);
sleep(1);
}
c = getchar();
printf("\nChar received:%c\n", c);
printf("Done.\n");
return 0;
}
Habe hier eine Variante dieser Lösung gepostet: stackoverflow.com/a/67363091/1599699 Es funktioniert gut, danke.
– Andreas
3. Mai 2021 um 3:12 Uhr
10017400cookie-checkErfassen Sie Zeichen aus der Standardeingabe, ohne auf das Drücken der Eingabetaste zu wartenyes
@adam – Können Sie klarstellen: Möchten Sie eine Funktion, die sofort zurückkehrt, wenn kein Zeichen verfügbar ist, oder eine, die immer auf einen einzelnen Tastendruck wartet?
– Roddy
8. Januar 2009 um 9:47 Uhr
@Roddy – Ich möchte eine Funktion, die immer auf einen einzelnen Tastendruck wartet.
– Adam
28. Mai 2009 um 4:52 Uhr