web-dev-qa-db-fra.com

Comment imprimer les arguments argv de la fonction principale en C?

Donc, je viens d'apprendre que nous pouvons donner deux arguments à la fonction principale, à savoir "argc" et "argv. Cependant, je ne suis pas en mesure de comprendre ce que argv contient: int main(int argc, char* argv[]); 

Argv est-il un tableau de caractères? ou est-ce un tableau de pointeurs pointant vers des caractères? De toute façon, je cherche un moyen d’imprimer les arguments que l’utilisateur passe à ce programme. C’est le code que j’ai écrit, mais il n’imprime pas pour ainsi dire l’argv. Qu'est-ce qui ne va pas? J'imagine que c'est ce que je comprends de l'argument qui rend ce code incorrect. 

#include<stdio.h>
int main(int argc, char *argv[])
{
    int i;
    printf("%d\n",argc);
    for(i=0;i<argc-1;i++)
    {
        printf("%s",*argv[i]);
    }
    return 0;
}

Après les suggestions que j'ai reçues des réponses, j'ai corrigé mon code comme suit.

#include<stdio.h>
int main(int argc, char *argv[])
{
    int i;
    printf("%d\n",argc);
    for(i=1;i<argc;i++)
    {
        printf("%s",argv[i]);
    }
    return 0;
}

Et j'utilise Ubuntu Linux sous VMWare sur mon ordinateur Windows 8.1. C'est la sortie que je reçois. C'est juste imprimer argc et après ça plus rien. Quel est le problème? Est-ce la façon dont je le compile ou quelque chose dans un terminal Linux?

 The snapshot of my terminal

Dans la figure ci-dessus, je souhaite que les numéros 2,4,5,3 soient à nouveau imprimés, mais ils ne sont pas imprimés. 

Merci.

9
user5987642

Expliquons les choses étape par étape. Tout d'abord, lorsque vous appelez votre programme en appelant quelque chose comme ...

./my-program arg0 arg1 arg2

Vous lui transmettez une série de trois arguments, non? Et chaque argument est une chaîne, non? Maintenant, la fonction main peut avoir l’un des deux prototypes spécifiés par le standard C ...

int main(); // Let's not worry about this for now
int main(int argc, char **argv);

L'idée est que main est capable de gérer les arguments que vous avez fournis. argc fournit le nombre d'arguments. Si vous avez remarqué, en passant trois arguments, argc vaut 4! Cela se produit car un premier argument est passé avant tous les autres, ./my-program, et permet à votre programme de se reconnaître.

Maintenant, que signifie char **argv? Quelque chose de la forme X* est un pointeur sur X, non? Donc, char * est un pointeur sur char et char ** est un pointeur sur pointeur à char. En C, une chaîne est simplement un tableau à zéro terminal de char, et un tableau peut être "dégradé" en un pointeur. Cela signifie que argv est un tableau de chaînes, dont la première, argv[0], est le nom du programme.

Maintenant, le standard C vous permet d’écrire tout prototype "compatible" pour main. Par exemple, vous pouvez écrire n'importe lequel de ces ...

int main(int argc, const char *const argv[]);
int main(int argc, const char *argv[])
int main(int argc, const char **argv);
int main(int argc, const char *const *const argv);

Vous n'avez pas besoin de comprendre ce qu'ils veulent dire maintenant, mais plutôt que argv est un tableau de chaînes et que vous devriez ne jamais modifier les chaînes car le prototype main d'origine semble vous faire confiance. Maintenant, sachant que les arguments commencent par argv[1], votre code ...

for(i=0;i<argc-1;i++)

Signifie: "Pour chaque i comprise entre 0 et argc - 1".

    printf("%s",*argv[i]);

Signifie: "Affiche le premier caractère de l'élément ith de argv". Pourquoi cela serait-il faux? Tout d'abord, vous imprimez une char et dites à printf qu'il s'agit d'une chaîne. Cela a un comportement indéfini. Ensuite, vous parcourez les premiers ith éléments de argv. Cela signifie que le premier élément "non-argument" sera inclus dans le mixage et que le dernier argument ne le sera pas. Pour le résoudre, écris quelque chose comme ...

for(i = 1; i < argc; i++)

Signifie: "Pour chaque i dans la plage allant de 1 à argc".

    printf("%s", argv[i]);

Signifie: "Affiche le ième élément de argv dans stdout.

9
3442

argv est-il un tableau de caractères? ou est-ce un tableau de pointeurs pointant vers des caractères? 

argv est un pointeur sur lequel pointer vers char. Lorsqu'une liste d'arguments est passée via la ligne de commande, un tableau de pointeurs char est créé et chacun de ces pointeurs pointe sur chacun de ces arguments, stockés sous la forme de chaînes, avec le nom du programme. argv pointe vers le premier pointeur de ce tableau char *. Par conséquent, argv[i] est un pointeur sur char

                           +--------------------------+
              +----+  +--> | argument 1 (program name)|
argv[0]+----> |    |  |    +--------------------------+
              |  +----+
              +----|       +--------------------------+
              |  +-------> |       argument 2         |
              |    |       +--------------------------+
              +----+
              |  +----+    +--------------------------+
              |    |  +--> |       argument 3         |
              +----+       +--------------------------+
           "char *" array

Vous devez changer 

printf("%s",*argv[i]);  

à 

printf("%s",argv[i]);  

*argv[i] est de type char. %s attend un type de char *.

5
haccks

Dans votre question modifiée, vous avez résolu votre principal problème. Maintenant, remarquez que votre invite ressemble à

./mygrep245YourName@ubuntu:~/test$

Ici ./mygrep245 correspond à votre sortie après avoir imprimé "5\n". Vous avez oublié d'imprimer des sauts de ligne. Ainsi, toute la sortie et la sortie suivante de Shell ont été concaténées telles quelles. Et le dernier argument 3 n'a pas été imprimé car vous avez mis i<argc-1 au lieu de i<argc ou i<=argc-1 dans votre condition de boucle.

2
Ruslan

char *argv[] est un pointeur sur char car les tableaux des arguments de fonction sont automatiquement convertis en pointeurs pointant sur des éléments du tableau.

Vous avez invoqué un comportement non défini en transmettant des données de type incorrect à printf(): %s s'attend à char*, mais vous avez passé char (converti en int pour les arguments avec numéro variable).

Supprimez le * supplémentaire o déréférenciez le pointeur.

#include<stdio.h>
int main(int argc, char *argv[])
{
    int i;
    printf("%d\n",argc);
    for(i=0;i<argc-1;i++)
    {
        printf("%s",argv[i]);
    }
    return 0;
}

Aussi, vous voudrez peut-être i<argc au lieu de i<argc-1. Pourquoi ne pas imprimer le dernier argument?

1
MikeCAT

Vous pouvez vous référer au document :

Comme vous pouvez le constater, main a maintenant des arguments. Le nom de la variable argc signifie "nombre d'arguments"; argc contient le nombre d'arguments passé au programme. Le nom de la variable argv signifie "vecteur d'argument". Un vecteur est un tableau unidimensionnel et argv est un tableau unidimensionnel de chaînes. Chaque chaîne est l'un des arguments cela a été transmis au programme.

Si vous avez besoin de l’imprimer, supprimez simplement le * et essayez ceci:

#include<stdio.h>
int main(int argc, char *argv[])
{
    int i;
    printf("%d\n",argc);
    for(i=0;i<argc-1;i++)
    {
        printf("%s",argv[i]);   //remove * from here
    }
    return 0;
}
0
Rahul Tripathi