Programmieren - alles kontrollieren 4.941 Themen, 20.715 Beiträge

Tastatureingaben abfangen mit C

Synthetic_codes / 3 Antworten / Baumansicht Nickles

Hi, ich schreibe gerade an einem Programm, das als eine art KonsolenNetzwerkServer arbeitet. ich suche nun eine Methode mit der ich spezielle tasten abfangen kann, um das Programm zu beenden. (zb wenn man esc drückt, beendet das programm sich). leider funktioniert das nicht mit getchar/getc(stdin). gibt es nun eine C-Funktion aus der libc, mit der ich tastatureingaben überwachen kann, das mir den ASCII Code der gedrückten taste zurückgibt? momentan ist das programm für windows programmiert, es soll aber wenn es fertig ist auf linux portiert werden können, deshalb sollen keine WIN32 API funktionen verwendet werden(über das nachrichten system wäre das ja auch kein problem(mit WM_KEYDOWN)).

PS: hat einer vielleicht die opcodes folgender assembler befehle parat/weiss wo ich die finde:

mov eax, irgendwas
mor ebx, irgendwas
mov ecx, irgendwas
mov edx, irgendwas
mov irgendwas, eax
mov irgendwas, ebx
mov irgendwas, ebx
mov irgendwas, ebx

Thanx schonmal

'); DROP TABLE users;--
bei Antwort benachrichtigen
vergisses Synthetic_codes „Tastatureingaben abfangen mit C“
Optionen

Hallo,

Assembler kannst Du nicht nehmen, wie willst Du das denn portieren ?

Es gibt mehrere Lösungen unterschiedlicher Qualität:

DOS:
getchar() bzw. fgetc(stdin) funktionieren nicht so wie gewollt,
da hier die Tastatureingaben erst nach Drücken der Return Taste
an das Programm übergeben werden.
Alternative:
Du kannst die Tastatur Eingaben mit _getch() (siehe conio.h) lesen.
Der eingegebene Buchstabe wird nicht geechoet.
Wenn Du ein Echo brauchst, nehme _getche().

Problem:
Leider funktioniert das nur unter DOS, es gibt kein Pendant unter
Unix/Linux.


Unix/Linux:
Eine ähnliche Funktionalität wie mit _getch() erreichst Du unter Unix,
indem Du Dein Terminal(fenster) in den Raw (char Device) Modus setzt.
(Default ist Cooked (Block Device))
Dazu musst Du entweder vor dem Start Deines Programmes
z. B. unter Linux ein "stty raw" absetzen oder im Programm
mit ioctl() das Terminal in den Raw Modus setzen.
Dann liefert getchar() bzw fgetc(stdin) das gewünschte Ergebnis.
Zum Ende des Programms bzw. nach dem Verlassen des Programms
muss das Terminal mit "stty cooked" oder ioctl()
wieder in den cooked Modus gesetzt werden, sonst
kannst Du nicht mehr vernuenftig damit arbeiten ;-)
(Wenn CR nicht mehr funktionierst, kannst Du ctrl-j nehmen )


Besser und portabel:
Am Besten verwendest Du die Curses Bibliothek.
Unter Linux im Standard Lieferumfang der mir bekannten Distris,
unter DOS als PC-Curses verfügbar. (einfach mal Googeln)

Der Umgang mit Curses ist nicht leicht, aber gut dokumentiert.
Vorteile:
Portabel
Laeuft mit allen bekannten Terminal Emulationen (VT100, ANSI, VT52......)
gesteuert über die Environment Variable TERM
Ist ein alter Unix Standard.
Bietet viele Features zur Bildschirm Ansteuerung incl. Fenstertechnik.
Ist sehr performant.

Die Tastaturabfrage selber muesstest Du natürlich
in die Hauptschleife des Programms mit einbauen.
Hier stellt sich das Problem, eine nicht blockierende Tastaturabfrage
zu implementieren, damit die Hauptschleife nicht angehalten wird.
Hier würde ich entweder 2 Prozesse (s. fork()) oder Threads nehmen.
Die Lösung mit Prozessen würde mir besser gefallen.
Kommunizieren können sie entweder mit Signalen (man signal)
oder besser mit Messages (man ipc, man msgget).

Meine Ideallösung wäre ein Daemon Prozess für den Server
und ein separates Programm, was über Messages mit dem Daemon
kommuniziert und das Front End bildet.

Gruss, vergisses

bei Antwort benachrichtigen
Synthetic_codes Nachtrag zu: „Tastatureingaben abfangen mit C“
Optionen

re, danke schonmal, mit _getch() läuft das schon ganz gut. wegen dem assembler, das war für ein anderes projekt.
aber eine frage... es muss doch noch einen weg geben(im übrigen fällt mir grad ein dass man mit asembler zb die BIOS Tastatur interrupts ansprechen könnte oder?)

auf jeden fall mal danke, hat mich ein grosses stück weiter gebracht. curses benutze ich unter linux bereits, allerdings ist die sache die dass bei meinem compiler ( DevC++ -> www.bloodshed.net) der ignoriert den kompilerbefehl zum statischen linken einfach, sodass ich die ganze curses lib mit meinem programm liefern müsste. wenn du weisst wie ich mit dem guten alten (und freien) DevC++ statisch linken kann dann wäre curses allerdings perfekt.

'); DROP TABLE users;--
bei Antwort benachrichtigen
vergisses Synthetic_codes „re, danke schonmal, mit _getch läuft das schon ganz gut. wegen dem assembler,...“
Optionen

Hi,

nach meinen Erfahrungen wird Curses unter Unix immer
dynamisch gelinkt; es gibt gar keine statisch linkbare Lib.
Grund:
Für die Verwendung von Curses müssen diverse Voraussetzungen
erfüllt sein.
So muß z. B. terminfo installiert sein, da Curses auf die
terminfo Datenbank zugreift.

Unter DOS braucht man das Ansi.sys.

Man kann unter Unix bzw. Linux Systemen im Grunde davon ausgehen,
dass diese Voraussetzungen erfüllt sind und die Curses Lib da ist,
wenn der vi installiert ist. (was meistens der Fall ist)

Geschichtliches ;-)
Curses war in der Urversion die Screen IO des vi.
Bei der Entwicklung des vi hat man bereits die Wiederverwendbarkeit
der IO Funktionen geplant und diese als eigenständige Lib (Curses)
implementiert. (damals hat man eben noch gründlich gearbeit)

Unter DOS kannst Du DOS Interrupts abfangen.
Der Aufwand lohnt sich aber nicht, da _getch() genau das macht ...

Wenn Du planst, unter DOS zu entwickeln und später auf
Unix/Linux zu portieren, solltest Du ohnehin auf Interrupt Handling
und Assembler verzichten, da ansonsten die Portierung sehr
aufwändig wird.

Gruss, vergisses

bei Antwort benachrichtigen