web-dev-qa-db-fra.com

Passage du contenu du fichier sur la ligne de commande du programme c ++

J'ai le programme suivant (appelons-le programme.cc):

int main() {
  int x, y, sum;
  std::cout << "A program which adds two integers\n";
  std::cout << "Enter 1st integer: ";
  std::cin >> x;
  std::cout << "Enter 2nd integer: ";
  std::cin >> y;
  sum = x + y;
  std::cout << "Sum is " << sum << std::endl;
  return 0;
}

J'écris actuellement un script bash qui prend un fichier et le passe à travers la ligne de commande en tant qu'arguments transmis à ce programme cpp. Comme vous pouvez le constater, le programme ci-dessus demande deux entrées.

Je sais comment vous pouvez transmettre le contenu d'un fichier pour l'utiliser comme entrée sur stdin. Mais comment feriez-vous cela si vous voulez transmettre le contenu d'un fichier sous forme d'arguments via la ligne de commande?

Pour élaborer, disons que fichier.txt est le fichier qui m'intéresse, qui contient simplement deux entiers sur des lignes séparées.

EDIT: J'ai essayé la commande xargs:

       xargs program.cc < file.txt > outputresult.txt

Mais cela finit par imprimer ce que j'ai dans cout, par exemple:

     A program which adds two integers
     Enter 1st integer: Enter 2nd integer: Sum is 2

Je ne veux que ce qui est compté APRÈS que tous mes arguments aient été acceptés. Comment puis-je faire cela?

1
E 4 6

Comme vous l'avez écrit, vous devez transmettre le contenu du fichier à votre programme, pas le fichier lui-même (et xargs, au fait). Une façon de le faire est d'utiliser redirection d'entrée :

a.out < file

Par exemple:

$ cat file
4 
7
$ ./a.out < file
A program which adds two integers
Enter 1st integer: Enter 2nd integer: Sum is 11

Une autre façon de faire la même chose est d’imprimer le contenu du fichier et de le transmettre à votre programme avec un tuyau:

$ cat file | ./a.out 
A program which adds two integers
Enter 1st integer: Enter 2nd integer: Sum is 11

Une approche beaucoup plus propre, bien sûr, consisterait à écrire votre programme de manière à ce qu'il puisse prendre des arguments au lieu de lire les entrées standard:

./a.out 4 7

Ou bien, écrivez-le pour qu'il puisse ouvrir les fichiers en interne et les analyser pour ses données d'entrée:

./a.out file

Quoi qu'il en soit, pour obtenir uniquement la dernière ligne de la sortie, affichez le reste avec l'erreur standard:

#include <iostream>

int main() {
  int x, y, sum;
  std::cerr << "A program which adds two integers\n";
  std::cerr << "Enter 1st integer: ";
  std::cin >> x;
  std::cerr << "Enter 2nd integer: ";
  std::cin >> y;
  std::cerr << "\n";
  sum = x + y;
  std::cout << "Sum is " << sum << std::endl;
  return 0;
}

Maintenant, lancez:

$ ./a.out < file > output.txt
A program which adds two integers
Enter 1st integer: Enter 2nd integer: 
$ cat output.txt
Sum is 11

Ou, pour donner les valeurs manuellement:

$ ./a.out > output.txt 
A program which adds two integers
Enter 1st integer: 4
Enter 2nd integer: 7

$ cat output.txt 
Sum is 11
2
terdon

Comme terdon l’a déjà souligné, vous devez soit rediriger stdin à partir d’un fichier (et appeler le programme à l’aide de program <inputfile.txt par exemple), soit modifier votre programme afin qu’il analyse les arguments passés à partir de la ligne de commande ( et appelez le programme en utilisant par exemple program 1 2);

Dans le premier cas, vous souhaitez supprimer les deux premiers couts si stdin n'est pas connecté à un terminal, et dans le second cas, vous souhaitez supprimer les deux premiers couts, par exemple, si disons que pas assez d'arguments ont été passés depuis la ligne de commande;

En parlant de la première méthode, vous pouvez vérifier si un descripteur de fichier est connecté à un terminal à l’aide de la fonction isatty() (fonction POSIX définie dans unistd.h):

int isatty(int fd);

Si fd est un descripteur de fichier ouvert connecté à un terminal, la fonction renvoie 1; Si fd n'est pas un descripteur de fichier ouvert ou n'est pas connecté à un terminal, la fonction renvoie 0:

#include <iostream>
#include <unistd.h>

int main() {
    int x, y, sum;
    std::cout << "A program which adds two integers\n";
    if(isatty(0)) {
        std::cout << "Enter 1st integer: ";
    }
    std::cin >> x;
    if(isatty(0)) {
        std::cout << "Enter 2nd integer: ";
    }
    std::cin >> y;
    sum = x + y;
    std::cout << "Sum is " << sum << std::endl;
    return 0;
}

De cette façon, l'utilisateur ne sera invité à insérer les numéros que si stdin n'a pas été redirigé:

user@user-X550CL ~/tmp % ./a.out               
A program which adds two integers
Enter 1st integer: 1
Enter 2nd integer: 2
Sum is 3
user@user-X550CL ~/tmp % cat inputfile.txt 
3
4
user@user-X550CL ~/tmp % ./a.out <inputfile.txt 
A program which adds two integers
Sum is 7

En parlant de la deuxième méthode, voici un exemple très approximatif sur la façon d’analyser les arguments passés depuis la ligne de commande (les arguments passés depuis la ligne de commande sont stockés dans argv, qui est un tableau de pointeurs vers un caractère. Vous devrez convertir chaque argument en un entier, mais n'utilisez pas atoi()! Utilisez quelque chose qui vous permette de vérifier si les arguments sont numériques ou non. J'ai utilisé atoi() juste par souci de simplicité. :

#include <iostream>
#include <cstdlib>

int main(int argc, char *argv[]) {
    int x, y, sum;
    std::cout << "A program which adds two integers\n";
    if(argc == 3) {
        x = atoi(argv[1]);
        y = atoi(argv[2]);
    }
    else {
        std::cout << "Enter 1st integer: ";
        std::cin >> x;
        std::cout << "Enter 2nd integer: ";
        std::cin >> y;
    }
    sum = x + y;
    std::cout << "Sum is " << sum << std::endl;
    return 0;
}

De cette façon, l'utilisateur ne sera invité à insérer les nombres que si un nombre suffisant d'arguments n'a pas été passé depuis la ligne de commande:

user@user-X550CL ~/tmp % ./a.out
A program which adds two integers      
Enter 1st integer: 1
Enter 2nd integer: 2
Sum is 3
user@user-X550CL ~/tmp % ./a.out 3
A program which adds two integers
Enter 1st integer: ^C
user@user-X550CL ~/tmp % ./a.out 3 4
A program which adds two integers
Sum is 7
1
kos

Donc, il y a quelques choses que vous pouvez faire:

  1. Vous pouvez exporter dans un fichier au sein de C++ en utilisant quelque chose comme this .
  2. Vous pouvez supprimer les lignes cout << "Enter... de votre code afin que le seul résultat du programme soit ce qui est stocké dans le fichier.
  3. Vous pouvez contourner le problème en utilisant le flux de sortie d'erreur (cerr au lieu de cout) et manipuler les sorties en conséquence. Si vous voulez que cout soit visible et cerr dans le fichier, faites xargs program.cc < file.txt 2> outputresult.txt (avec 2> au lieu de>). Si vous voulez que cerr soit visible et couté dans le fichier, faites-le comme ci-dessus avec just > .
  4. Conservez la sortie telle quelle, mais exécutez 2 autres exécutions qui suppriment les lignes indésirables de votre code:

cat outputresult.txt | grep Sum > tempfile && mv tempfile outputresult.txt

Vous pouvez implémenter ceci avec votre code comme ceci:

./program.cc < file.txt | grep Sum > outputresult.txt

Cependant, cette méthode nécessite l’écriture de nouvelles lignes. Vous devez donc vous assurer que la sortie est affichée dans chaque nouvelle ligne.

Personnellement, je suggérerais d'utiliser soit la gestion de fichiers au sein de C++, soit le cout et le piratage, en fonction de l'utilisation du programme.

0
Zzzach...