Consoleneingabe während Programmlauf ermöglichen



  • Hallo c-community,

    ich habe folgendes Problem: Ich möchte wärend des Programmlaufs dem User die Möglichkeit geben die Console zu nutzen, um Befehle an das Programm zu schicken. Dazu habe ich mir folgendes Konzept überlegt:

    Es wird in einem Thread die Funktion kbHit und getCh in einer Schleife ausgeführt.

    int     		Console_getCh(void){
    	static int ch = -1, fd = 0;
    	struct termios neu, alt;
    	fd = fileno(stdin);
    	tcgetattr(fd, &alt);
    	neu = alt;
    	neu.c_lflag &= (unsigned)~(ICANON|ECHO);
    	tcsetattr(fd, TCSANOW, &neu);
    	ch = getchar();                    // <--Zeile blockiert
    	tcsetattr(fd,  TCSANOW, &alt);
    	return ch;
    }
    
    int				Console_kbHit(void){
        printf("kbhit begin\n");
    	struct termios term, oterm;
    	int fd = 0;
    	int c = 0;
    	tcgetattr(fd, &oterm);
    	memcpy(&term, &oterm, sizeof(term));
    	term.c_lflag = term.c_lflag & (!ICANON);
    	term.c_cc[VMIN] = 0;
    	term.c_cc[VTIME] = 1;
    	tcsetattr(fd, TCSANOW, &term);
    	c = getchar();
    	tcsetattr(fd, TCSANOW, &oterm);
    	if (c!= -1)
    	ungetc(c, stdin);
    	printf("kbhit end\n");
    	return ((c != -1) ? 1 : 0);
    }
    

    Diese beiden Funktionen habe ich schon mehrfach erfolgreich verwendet aber meist in meinem Hauptthread, damit ich per Tastendruck ein Programm beenden kann. Im Nebenthread habe ich jetzt das Phänomen, dass in der Funktion getCh die markierte Zeile (9) blockiert. Erst nach dem Drücken einer weiteren Taste, komme ich aus dieser Blockade heraus.

    Jetzt ist meine erste Frage, warum diese Funktion auf einmal blockiert. Mit dem ddd komme ich da irgendwie nicht weiter, da er sich beklagt, dass er die getch.c nicht findet. Deswegen kann ich diese nicht debuggen.

    Eine andere Frage wäre gibt es eine Alternative? Funktionen wie fgets möchte ich eigentlich nicht verwenden, da diese blockierend sind und ich die Erfahrung habe, dass dann das Programm nicht sauber beendet wird oder erst zwangsweise etwas eingegeben werden muss, damit das Programm endet.

    Vielen Dank
    mirrowwinger



  • Dieser Thread wurde von Moderator/in SeppJ aus dem Forum C (C89, C99 und C11) in das Forum Linux/Unix verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • Ich denke, diese Hacks sind ganz nett, wenn du Windows/DOS-Konsolenprogramme auf Linux laufen lassen willst.

    Aber wenn du selber was schreibst, dann nimm doch gleich die Linux-API ohne Umwege.
    ^(Deine Frage gehört auch in das Linux-Unterforum)^

    Du kannst auch ncurses benutzen.



  • Hast du wegen der Linux-Api eventuell nen manual parat?

    Sorry, dass ich das falsche Themengebiet gewählt hatte.



  • mirrowwinger schrieb:

    Hast du wegen der Linux-Api eventuell nen manual parat?

    Schau mal bei curses rein. Da gibt es auch eine getch -Funktion.
    Es gibt auch nodelay() und noecho() die man vorher Aufrufen kann.
    Das sollte schon reichen.

    Wenn du das nicht nutzen willst, dann schau bei
    struct termios
    tcgetattr
    tcsetattr
    nach.
    Da sind dann auch gleich die Attribute beschrieben.

    ^ncurses ist die freie Implementierung von curses^



  • @DirkB danke schonmal für die Tips.

    Der Fehler ist gefunden. Ich habe einfach zu oft getCh aufgerufen in der Schleife. Dadurch war der Charakter einfach schon weg und das Programm hat in der getch-Funktion gewartet, dass eine Taste gedrückt wird.
    Lösung ist also, als erstes:

    character = getCh();
    

    und dann weiter mit dem charackter arbeiten.

    Vielen Dank


Anmelden zum Antworten