unix: main () interactive, ligne de commande, tuyauterie et redirection dans C?

Bien qu’il y ait un moyen facile d’utiliser à la fois la redirection de fichiers et la diffusion , ainsi que la lecture interactive des entrées utilisateur, avec main () , comme le montre cet extrait de code C …

#define SIZ 1024 #include  extern void do_something_with_the_array(float *a[], int *n); int main(int argc, const char * argv[]) { float f[SIZ]; int k = 0; while ((scanf("%f", &f[k]) == 1)&&(k < SIZ)) { k++; } do_something_with_the_array(f, k); return 0; } 

… Je ne suis pas sûr qu’il existe un moyen compatible avec les sources UNIX modernes et faciles pour atteindre par programmation une des trois possibilités dans un main() en C , selon le contexte?

  • lecture interactive d’une chaîne de chiffres en tant que saisie utilisateur
  • lecture de la même chaîne de chiffres que les arguments de la ligne de commande
  • redirection de fichier et tuyauterie

Je comprends que la tuyauterie et la redirection “appartiennent” au shell qui intercepte le programme avant même qu’il ne commence à s’exécuter, alors que les arguments de ligne de commande et la lecture interactive “appartiennent” à main () .

Je vois l’utilisation de l’ entrée stdin ou file ou de l’ entrée de tuyau assez explicite. Cependant, la lecture des arguments en ligne de commande est une autre histoire. Voici une démo sur la façon dont je le code habituellement, mais ça me semble un peu lourd et piraté. De plus, dans des scénarios plus compliqués avec des options, cela pourrait devenir un morceau de code plutôt désordonné. Je ne sais pas non plus à quel point c’est sûr ou infaillible que c’est …

 #define SIZ 1024 #include  #include  extern void do_something_with_the_array(float *, int); int main(int argc, const char * argv[]) { float f[SIZ]; int k = 0; if(argc > 2){ for(k = 0; k < argc - 1; k++) f[k] = (float)atof(argv[k+1]); } else while ((scanf("%f", &f[k]) == 1)&&(k < SIZ)) k++; do_something_with_the_array(f, k); return 0; } 

Merci d’avance!

Je ne connais pas une bibliothèque C qui fera en sorte que les trois cas spécifiques que vous avez mentionnés se ressemblent (bien que quelqu’un le fasse, s’il vous plaît, répondez parce que j’aimerais aussi savoir!). Je pense que vous recherchez quelque chose qui ne ressemble pas à l’opérateur diamant <> en Perl , mais pour des arguments individuels plutôt que des fichiers contenant des arguments.

Je pense que @David Hoelzer a la bonne idée: gérer les trois cas séparément. Par exemple, lors du traitement des arguments de ligne de commande ou de fichier, ne générez pas les invites “Entrez une valeur” que vous pouvez imprimer pour une saisie interactive. Pour le traitement en ligne de commande, getopt est un bon sharepoint départ.

Maintenant, un défi pour vous: enveloppez ces trois opérations dans une bibliothèque et rendez-la open-source pour que le rest d’entre nous puisse en bénéficier! 🙂

Un certain nombre de programmes se soucient de savoir s’ils sont invoqués avec une entrée clavier ou une entrée de fichier, y compris le shell lui-même.

Prenons / bin / sh comme premier exemple. Si vous l’appelez directement, il lance un shell interactif, mais si vous y insérez quelque chose, il démarre comme un shell de lecture non interactif. La principale différence entre les deux est que, s’il n’est pas interactif, il n’affiche pas l’invite $. Cependant, au cas où il serait vraiment interactif, il peut être lancé avec l’option -i pour le rendre interactif alors qu’il en déciderait normalement autrement.

La magie impliquée ici est isatty() ; voir l’ man 3 isatty .

De plus, certains programmes aiment recevoir des entrées au clavier lors du traitement des entrées standard redirigées. Il y a deux manières généralement privilégiées de le faire; soit ouvrir et lire à partir de /dev/tty ou lire l’erreur standard, selon le contexte. La plupart des éléments d’un pipeline démarré de manière interactive ne sont pas redirigés par erreur standard. Par conséquent, cela a tendance à fonctionner correctement (la lecture d’une erreur standard redirigée génère immédiatement une erreur car le handle n’est pas ouvert en lecture). Si vous voulez le rendre potentiellement entièrement automatisable, vous lisez l’erreur standard, sinon vous lisez /dev/tty .