2009-11-10 5 views
3

J'ai stdin dans un select() ensemble et je veux prendre une chaîne de stdin chaque fois que l'utilisateur tape et frappe Entrez.ncurses et le blocage stdin

Mais sélectionnez déclenche stdin comme prêt à lire avant Entrez est touché, et, dans de rares cas, avant tout est tapé du tout. Cela bloque mon programme sur getstr() jusqu'à ce que je frappe Entrez.

J'ai essayé le réglage nocbreak() et c'est parfait vraiment, sauf que rien ne se répercute à l'écran, donc je ne peux pas voir ce que je tape. Et le réglage echo() ne change pas cela.

J'ai également essayé d'utiliser timeout(0), mais les résultats étaient encore plus fous et ne fonctionnaient pas.

+0

bien au fond, je me demande si je dois utiliser des fils maintenant à cause de ncurses, parce que je peux faire ça, mais ce n'est pas aussi élégant que d'utiliser select. La seule autre option à laquelle je peux penser est de lire chaque caractère et d'en faire un traitement radical. Cela semble être encore plus désordonné. – graw

Répondre

1

Ce que vous devez faire est de vérifier si un caractère est disponible avec la fonction getch(). Si vous l'utilisez en mode sans délai, la méthode ne bloquera pas. Ensuite, vous devez manger les caractères jusqu'à ce que vous rencontriez un '\ n', en ajoutant chaque caractère à la chaîne résultante au fur et à mesure.

Alternativement - et la méthode que j'utilise - est d'utiliser la bibliothèque GNL readline. Il a un support pour non-blocking behavior, mais la documentation sur cette section n'est pas si excellente.

Inclus ici est un petit exemple que vous pouvez utiliser. Il a une boucle select, et utilise la bibliothèque GNU readline:

#include <stdio.h> 
#include <readline/readline.h> 
#include <readline/history.h> 
#include <stdlib.h> 
#include <stdbool.h> 

int quit = false; 

void rl_cb(char* line) 
{ 
    if (NULL==line) { 
     quit = true; 
     return; 
    } 

    if(strlen(line) > 0) add_history(line); 

    printf("You typed:\n%s\n", line); 
    free(line); 
} 

int main() 
{ 
    struct timeval to; 
    const char *prompt = "# "; 

    rl_callback_handler_install(prompt, (rl_vcpfunc_t*) &rl_cb); 

    to.tv_sec = 0; 
    to.tv_usec = 10000; 

    while(1){ 
     if (quit) break; 
     select(1, NULL, NULL, NULL, &to); 
     rl_callback_read_char(); 
    }; 
    rl_callback_handler_remove(); 

    return 0; 
} 

Compile avec:

gcc -Wall rl.c -lreadline 
+0

Merci. J'ai essayé d'utiliser la solution readline, elle a l'air sympa, mais elle ne résonne pas correctement quand on utilise des curses en même temps. Ils ne sont probablement pas méchants à utiliser ensemble. J'ai décidé d'utiliser simplement getch() et de maintenir un tampon interne de la ligne. C'est étonnamment facile. – graw