Vous faites des IO de manière incorrecte, le manuel POSIX et toutes les autres documentations associées indiquent explicitement de ne jamais mélanger les IO effectuées sur FILE *
s et descripteurs de fichiers. Vous avez très clairement enfreint cette règle. Cette règle est en place car FILE *
s utiliser la mise en mémoire tampon an cela signifie qu'après un appel au fgets
il ne restera plus rien pour read
obtenir parce que fgets
déjà lu toutes les données en attente dans un tampon qui est conservé dans le FILE *
structure.
Donc, comme il n'y a aucun moyen de vérifier si une méthode ISO C IO bloquera, nous devons utiliser uniquement des descripteurs de fichiers.
Puisque nous savons que STDIN_FILENO
est juste le nombre 0, nous pouvons utiliser
fcntl (0, F_SETFL, O_NONBLOCK);
cela transformera tous les read
s sur le descripteur de fichier 0 en mode non bloquant, si vous souhaitez utiliser un descripteur de fichier différent afin de pouvoir laisser 0 seul, utilisez simplement dup
pour le dupliquer.
De cette façon, vous pouvez rester à l'écart du poll
complètement et implémentez ngetc
comme
ssize_t
ngetc (char *c)
{
return read (0, c, 1);
}
ou mieux encore, une macro
#define ngetc(c) (read (0, (c), 1))
Ainsi, vous obtenez une implémentation simple pour ce que vous recherchez.
Modifier : Si vous craignez toujours que le terminal ne mette en mémoire tampon l'entrée, vous pouvez toujours modifier les paramètres du terminal, voir Comment désactiver la mise en mémoire tampon de ligne de l'entrée dans xterm à partir du programme ? pour plus d'informations sur la façon de procéder.
Modifier : La raison pour laquelle on ne pouvait pas utiliser fgetc
au lieu de read
est pour la même raison que l'utilisation de fgets
ne fonctionnera pas. Lorsque l'un des FILE *
Les fonctions d'E/S sont exécutées, elles lisent toutes les données du descripteur de fichier associé. Mais une fois que cela se produit, poll
ne reviendra jamais car il attend un descripteur de fichier toujours vide, et la même chose se produira avec read
. Ainsi, je vous suggère de suivre les conseils de la documentation et jamais mélanger les flux (IO utilisant fgets
, fgetc
, etc.) et descripteurs de fichiers (IO utilisant read
, write
, etc.)