Looking for Computer Science & Information Technology online
courses ?
Check my new web site: https://www.yesik.it !
A partir de votre shell, vous avez sans doute déjà utilisé des commandes de la forme:
sh$ ls /etc sh$ javac Demo.java sh$ g++ -Wall -Werror -o hello hello.cc sh$ firefox http://www.chicoree.fr etc...
Dans chacun de ces exemples, la commande sert à lancer un programme (ls, javac, g++ ou firefox). Mais l'exécution de ce programme dépend des autres informations qui vous avez données sur la ligne de commande. Ces informations sont des arguments du programme. Dans la terminologie de l'informatique, on dit que vous avez invoqué un programme en lui passant des arguments sur la ligne de commande.
Nous allons voir ici comment récupérer ces arguments dans un programme.
Java
En Java, le programme principal prend en paramètre un tableau de chaînes de caractères traditionnellement appelé args:
static public void main(String[] args) {
...
Ce tableau sert à récupérer les arguments de la ligne de commande lorsque le programme est exécuté.

Note:
Les arguments récupérés sont ceux de la ligne de commande lorsque le programme est exécuté, pas ceux passés lorsqu'il a été compilé!
public class Arguments { public static void main(String[] args) { System.out.println("Nombre d'arguments: " + args.length); for(int i = 0; i < args.length; ++i) { System.out.println("Argument " + i + ": " + args[i]); } } }
Le programme ci-dessus affiche le nombre et les arguments reçus. Pour le compiler et l'exécuter, vous pouvez utiliser les commandes suivantes:
sh$ javac Arguments.java
sh$ java Arguments Nombre d'arguments: 0
sh$ java Arguments hello Java Nombre d'arguments: 2 Argument 0: hello Argument 1: Java
Un exemple utile en Java
Vous connaissez la commande shell echo? Celle-ci permet d'afficher un message sur la sortie standard, par exemple lors de l'exécution d'un script:
sh$ echo Salut! Salut!
Nous allons réaliser un programme similaire à la commande echo, mais qui affiche le message en MAJUSCULES.
Le principe est simple: nous allons parcourir le tableau des arguments, et afficher chacun d'eux après l'avoir converti en majuscule. Il nous faut donc:
- une boucle: for .. in fera l'affaire
- une méthode pour afficher: System.out.println
- une méthode pour convertir en majuscules: une recherche dans la documentation de Java nous mène à la méthode toUpperCase.
Muni de ces informations, le programme suivant ne doit receler aucune complexité:
public class Upper { static public void main(String[] args) { for(String arg : args) { // pour chaque argument String enMajuscule = arg.toUpperCase(); System.out.print(enMajuscule); // affiche la chaîne en majuscule System.out.print(" "); // ajoute un blanc de séparation } System.out.println(); // fini par un retour à la ligne } }
La compilation et l'exécution se fait de manière classique:
sh$ javac Upper.java
sh$ java Upper Hello world! HELLO WORLD!
Pour vous convaincre du fonctionnement de ce programme, n'hésitez pas à expérimenter un peu. Par exemple en l'appelant sans argument. Ou en séparant les arguments par plusieurs espaces au lieu d'un seul...
Groovy
Tout ce que nous avons dit plus haut est tout aussi valide pour Groovy. En fait, les deux programmes Java ci-dessus sont également des programmes Groovy valides – et qui font bien sûr la même chose:
sh$ cp Arguments.java Arguments.groovy sh$ groovy Arguments.groovy Nombre d'arguments: 0 sh$ groovy Arguments.groovy abc def ghi Nombre d'arguments: 3 Argument 0: abc Argument 1: def Argument 2: ghi
sh$ cp Upper.java Upper.groovy sh$ groovy Upper.groovy Hello world! HELLO WORLD!
Néanmoins, on peut faire un tout petit peu mieux en Groovy:
- en se souvenant que le programme principal Groovy peut simplement être défini en dehors de toute classe – à la manière du programme principal PHP;
- En utilisant la méthode each et une fermeture pour parcourir le tableau;
- en utilisant la possibilité en Groovy d'inclure dynamiquement le contenu d'une variable dans une chaîne (print("$enMajuscule ")):
args.each() { def enMajuscule = it.toUpperCase(); print("$enMajuscule "); } println();

Remarque:
Pourquoi print("$enMajuscule "); plutôt que simplement print(enMajuscule);?
En fait, si vous regardez attentivement, vous verrez qu'il y a un espace à la fin de la chaîne:
print("$enMajuscule "); /* ^ il y a un blanc ici ! */
Cela me permet d'ajouter un blanc de séparation après chaque argument. Et m'épargne la concaténation suivante:
print(enMajuscule + " ");
C++
C++ tout comme Java permet de récupérer les arguments passés par le shell dans un tableau. Par contre, ce tableau est un peu différent. Sans rentrer dans les détails, il contient non pas une chaîne de caractère contenant chaque argument, mais l'adresse en mémoire où se trouve le premier caractère de l'argument. La fin de chaque argument pouvant être déterminée par la présence du caractère spécial 0 (zéro).
Vous savez également qu'il n'est pas facile de connaître, en C++, la taille d'un tableau. Pour cette raison, celle-ci est communiquée au programme en même temps que le tableau des arguments.
Sachant qu'en C++, l'adresse d'un caractère est du type char*, cela nous donne la déclaration suivante pour le programme principal:
int main(int argc, char * argv[])
{
/* ... */
return 0;
}
Pour visualiser les arguments reçus par le programme nous pouvons utiliser le programme suivant:
#include <iostream> int main(int argc, char * argv []) { std::cout << "Nombre d'arguments: " << argc << std::endl; for(int i = 0; i < argc; i = i+1) { std::cout << "Argument " << i << ": " << argv[i] << std::endl; } return 0; }
Nous pouvons compiler et exécuter le programme ainsi:
sh$ g++ arguments.cc -Wall -Werror -o arguments
sh$ ./arguments Nombre d'arguments: 1 Argument 0: ./arguments
sh$ ./arguments Hello c++ Nombre d'arguments: 3 Argument 0: ./arguments Argument 1: Hello Argument 2: c++

Piège:
Si vous avez déjà testé le programme Java équivalent, vous remarquerez qu'en C++, le programme reçoit un argument supplémentaire: En effet, en C++ le programme reçoit systématiquement son nom en premier argument.
sh$ ./arguments Nombre d'arguments: 1 Argument 0: ./arguments
Remarquez aussi que le nom du programme est reçu comme il a été tapé dans le shell. Y compris avec le chemin:
sh$ pwd
/home/sylvain/Developpement/args/cc/arguments
sh$ /home/sylvain/Developpement/args/cc/arguments
Nombre d'arguments: 1
Argument 0: /home/sylvain/Developpement/args/cc/arguments
Un exemple utile en C++
Tout comme avec Java, nous allons écrire un programme utilitaire pour afficher un message en majuscules. Résumons les informations à notre disposition:
- argc nous permet de savoir combien d'arguments nous avons reçus. Sachant qu'il faut ignorer le premier, puisque c'est le nom du programme;
- Le tableau argv permet de savoir où se trouve en mémoire le premier caractère de chaque argument;
- Le dernier caractère de chaque argument est identifié par la valeur spéciale 0;
- Enfin – et ça, c'est une rapide recherche dans la documentation qui nous l'indique – il existe une fonction toupper pour convertir un caractère en majuscule.
Comme c'est peut être un peu compliqué, nous allons y aller progressivement. Tout d'abord, commençons par le programme principal et une boucle pour parcourir le tableau des arguments.
int main(int argc, char * argv []) { /* Commence à 1 pour ''sauter'' le nom du programme */ for(int i = 1; i < argc; i = i+1) /* pour chaque argument */ { /* ... */ } return 0; }
Maintenant, pour chaque argument, il nous faut le parcourir caractère par caractère. En effet: le fonction toupper travaille au niveau des caractères individuels:
#include <iostream> int main(int argc, char * argv []) { /* Commence à 1 pour ''sauter'' le nom du programme */ for(int i = 1; i < argc; i = i+1) /* pour chaque argument */ { /* pour chaque caractère de l'argument */ for(char *argument = argv[i]; *argument != 0; argument = argument+1) { /* ... */ } } return 0; }
Remarquez l'utilisation de la boucle for. Celle-ci sert à parcourir caractère par caractère un argument. Ce qui est notable ici, c'est que nous utilisons pour variable de boucle une adresse mémoire (en C++, on utilise le terme de pointeur). Celle-ci peut être incrémentée comme n'importe quelle autre variable de boucle. Enfin, denier point notable, pour savoir ce qui se trouve à l'adresse désignée par un pointeur, on utilise une étoile (*).
Tout cela pour dire que dans la boucle la plus interne, *argument désigne bien un caractère d'un argument. Pour vous en convaincre, vous pouvez l'afficher:
for(char *argument = argv[i]; *argument != 0; argument = argument+1)
{
std::cout << *argument << std::endl;
}
Bien, maintenant que nous parcourons nos arguments caractère par caractère, reste à utiliser la fonction toupper. C'est ce que fait le programme ci-dessous. Pour enjoliver l'affichage, il ajoute également un espace pour séparer les arguments et d'un retour à la ligne après le dernier:
#include <ctype.h> #include <iostream> int main(int argc, char * argv []) { /* Commence à 1 pour ''sauter'' le nom du programme */ for(int i = 1; i < argc; i = i+1) /* pour chaque argument */ { /* pour chaque caractère de l'argument */ for(char *argument = argv[i]; *argument != 0; argument = argument+1) { char majuscule = toupper(*argument); std::cout << majuscule; } std::cout << " "; /* espace de séparation */ } std::cout << std::endl; /* retour à la ligne */ return 0; }
Comme toujours, vous pouvez compiler et tester ainsi:
sh$ g++ -Wall -Werror upper.cc -o upper
sh$ ./upper Hello world! HELLO WORLD!
Un dernier mot: le programme C++ est définitivement plus complexe que sa contrepartie Java. En particulier parce qu'il travaille au niveau du "caractère en mémoire". Alors que le programme Java manipule une "chaîne de caractère", ce qui est un concept de plus haut niveau. C++ confirme donc son statut de langage "système". Il permet la manipulation directe de la mémoire – mais au prix d'une plus grande complexité des programmes.
A vous de jouer
On souhaite un programme C++ capable d'afficher les arguments reçus sur la ligne de commande en ne capitalisant que l'initiale, conformément aux exemples suivants:
sh$ ./capitalise david copperfield David Copperfield sh$ ./capitalise Oliver TWIST Oliver Twist
- Ecrivez ce programme en utilisant les fonctions C toupper pour capitaliser l'initiale et tolower pour passer en minuscule les autres caractères.
-
(plus difficile) Assurez-vous que votre programme réagit correctement aux noms composés:
sh$ ./capitalise jean-claude Jean-Claude
Vous aurez sans doute besoin de la fonction C isalpha.