/ / C - stdin, pipeline unix et EOF - c, pipe, c99

C - stdin, pipeline unix et EOF - c, pipe, c99

J'écris une application qui reçoit d'aborddonnées provenant d’un pipeline Unix, puis invitant l’utilisateur à entrer. Ce que je n'arrive pas à comprendre, c'est pourquoi l'entrée du pipeline ne semble pas se fermer correctement avant d'inviter l'utilisateur à le faire. Il me semble que je manque quelque chose de très élémentaire ici.

J'ai essayé tous les exemples de rinçage stdin présenté ici sans succès. Ce Cela semble également potentiellement pertinent, mais je n’ai pas réussi à extraire de réponses pertinentes.

#include <stdio.h>
#include <stdlib.h>

#define BUFSZ 1024

int main(void) {

char *buf = calloc(BUFSZ, sizeof(char));

while(fgets(buf, BUFSZ, stdin)) { printf("Pipe input: %s", buf); }

printf("Enter input: ");
fgets(buf, BUFSZ, stdin);
printf("User input: %s", buf);

free(buf);
return 0;
}

Exemple d'utilisation et de sortie:

$ cat testdata2 | ./a.out
Pipe input: testdata testdata
Pipe input: testdata testdata2
Pipe input: testdata testdata3
Pipe input: testdata testdata4
Pipe input: testdata testdata5
Pipe input: testdata testdata6
Pipe input: testdata testdata7
Enter input: User input: testdata testdata7
$

Comment se peut-il que le second fgets () (destiné à la saisie au clavier) ne touche jamais le tampon?

Ce MCVE a été compilé testé sur OSX et Linux avec des résultats identiques.

Réponses:

5 pour la réponse № 1

Si stdin est une pipe, alors stdin n'est pas le terminal. Quand vous arrivez au bout du tuyau, c’est fini! C’est la fin du stdin. Vous vous attendez à une sorte de transformation magique où stdin cesse d'être le tuyau et commence à être quelque choseautre. Ne t'attends pas à ça. C'est toujours le tuyau. Et EOF a eu lieu. Pour les tuyaux, EOF est une condition permanente. Une fois que vous avez atteint EOF, vous ne recevrez jamais rien de plus.

Ne vérifiez la valeur de retour de fgets chaque temps. "Vous verrez que le dernier renvoie null, car il est à EOF.

Programmes qui veulent lire piped stdin et également obtenir une entrée au clavier doit ouvrir le terminal séparément, comme dans FILE *tty = fopen("/dev/tty", "r");