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?
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
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 cout
s si stdin
n'est pas connecté à un terminal, et dans le second cas, vous souhaitez supprimer les deux premiers cout
s, 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
Donc, il y a quelques choses que vous pouvez faire:
cout << "Enter...
de votre code afin que le seul résultat du programme soit ce qui est stocké dans le fichier.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 > .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.