IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

Copie char *argv[] dans char *tab[]


Sujet :

C

  1. #1
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2010
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2010
    Messages : 26
    Par défaut Copie char *argv[] dans char *tab[]
    Bonsoir à tous !

    Voila, je rencontre un petit problème.
    Je souhaite copié le tableau (char *argv[]) dans un autre tableau.
    J'ai fait donc comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    int i = 0;
    char *tab = NULL;
    tab = malloc(argc * sizeof(char*)); /* On alloue le tableau */
    if(tab == NULL) /* On vérifie s'il n'est pas NULL */
        exit(1);
    /* On copie dans le tableau */
    for(i = 0; i < argc; i++) 
        tab[i] = argv[i];
    printf("%s\n", tab[0]); /* Le programme plante à cette endroit */
     
    /* Libération de la mémoire */
    free(tab);
    tab = NULL; /* On met le pointeur à NULL */
    Par contre, je ne souhaite pas utiliser la fonction memcpy() pour copier mon tableau.

    Et, lorsque j'affiche une case du tableau (tab[0]), mon programme plante.
    J'avoue ne pas comprendre pourquoi.
    J'ai fait un autre code pour copier un autre tableau.
    Voila ce code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    int i = 0;
    char *tab[] = NULL;
    char *tab2[] = NULL;
    /* Allocation dynamique des tableaux */
    tab = malloc(argc * sizeof(char*));
    tab2 = malloc(argc *sizeof(char *));
    if(tab == NULL || tab2 == NULL) /* Vérification */
        exit(1);
     
    /* On ajoute dans le tableau les valeur Hello */
    for(i = 0; i < argc; i++)
        tab[i] = "Hello";
     
    /* On affiche les valeurs du tab[] */
    for(i = 0; i < argc; i++)
        printf("Tab : %s\n", tab[i]); /* Mon programme plante */
     
    /* On copie le tab[] dans tab2[] */
    for(i = 0; i < argc; i++) 
        tab2[i] = tab[i];
     
    /* On affiche les valeurs de tab2[] */
    for(i = 0; i < argc; i++)
        printf("Tab2 : %c\n", tab2[i]);
     
    /* Libération de la mémoire */
    free(tab);
    free(tab2);
     
    /* On met les pointeurs à NULL */
    tab = NULL;
    tab2 = NULL;
    Est-ce possible de copier un tableau de chaine de caractère ? Je me suis poser la question, s'il fallait copier aussi chaque caractère dans la case du tableau correspondant ?

    Je vous remercie d'avance de votre aide

    Cordialement,
    vegnagun

  2. #2
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    char *tab = NULL;
    tab = malloc(argc * sizeof(char*));
    Ceci doit alerter : Si dans le malloc() on a sizeof(type), alors la valeur de retour doit être du type type * .
    On devrait donc avoir char ** tab; Alors tab[0] sera un char * (au lieu d'un char !) ce qui est conforme avec le format "%s".

    Moyennant quoi, seuls les pointeurs sont copiés, pas les chaines de caractères. Il faut donc s'assurer de la pérennité de ces chaines pendant l'utilisation de ces adresses (si cela vient des arguments de main(), pas de problème)

    Sur le deuxième code, je suis surpris que cela compile sans erreurs:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    char *tab[] = NULL;  
    char *tab2[] = NULL;
    /* Allocation dynamique des tableaux */
    tab = ....
    tab2 = ...

  3. #3
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2010
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2010
    Messages : 26
    Par défaut
    Tout d'abord, merci de t'a réponse.

    Je ne pense pas que j'ai compris votre explication sur le malloc(). Vous voulez dire que lorsqu'on appelle un malloc(sizeof(char)), la variable sera un pointeur ?

    Ah oui... J'y avais pas penser. Mais je voit pas trop comment faire pour copier les chaines de caractère et non pas les pointeurs.

  4. #4
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    Vous voulez dire que lorsqu'on appelle un malloc(sizeof(char)), la variable sera un pointeur ?
    La valeur renvoyée par malloc() est une adresse, donc elle doit être stockée dans un objet pointeur
    Mais je voit pas trop comment faire pour copier les chaines de caractère et non pas les pointeurs
    . Pour mettre des chaines de caractères, il faut des tableaux et copier dans les tableaux en utilisant, par exemple, strcpy(). La question est alors de choisir comment créer ces tableaux : par allocation statique, automatique ou dynamique suivant le problème à résoudre

  5. #5
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2010
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2010
    Messages : 26
    Par défaut
    Merci pour ton explication sur le malloc().

    Mais lorsque je fait comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    strcpy(tab[0], argv[0]); /* Il plante */
    J'avoue ne pas trop comprendre.

  6. #6
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    je crois que tu ne comprends pas trop ce que signifient les symboles..

    char *argv[] est équivalent char **argv

    Quand tu références argv[0], tu pointes donc sur une chaîne.

    Vu que tu n'as pas alloué tab[0] avec la longueur de la chaîne, ça plante..

    Pour dupliquer argv, le plus simple serait :

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    int i ;
    char **tab;
     
    tab = malloc ( argc * sizeof(char*) );
     
    if ( tab != NULL )
      for i = 0 ; i < argc ; i++ )
         tab[i] = strdup(argv[i]) ;

  7. #7
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    argv est un tableau de chaines de caractères (un tableau de tableaux), alors argv[0] est l'adresse de début d'une chaine de caractères (voir plus bas) c'est à dire l'adresse de début d'un TABLEAU de char.

    Par contre, tab est un tableau de pointeurs et tab[0] est un pointeur. Pour qu'on puisse écrire strcpy(tab[0], argv[0]) , il faut que tab[0] contienne l'adresse de début d'un tableau de char (suffisamment grand).

    Il faut absolument faire la différence entre un pointeur et un tableau.
    Il n'y a aucune connection entre objet pointeur et tableau. Par contre, il y en a une entre adresse et tableau.
    La difficulté vient d'une mauvaise terminologie : il y a confusion entre objet pointeur (que j'appelle simplement pointeur) et constante pointeur (que j'appelle adresse) sous un seul vocable "pointeur" alors que les deux choses sont différentes. Pourtant, le principe est simple. Pour résumer :

    1- Un pointeur est un objet qui ne peut être utilisé que pour stocker une adresse (on voit que la différence entre pointeur et adresse est celle qui existe entre le conteneur et le contenu).

    2- L'identificateur A associé à un tableau ne représente l'objet tableau que dans 3 types d'expressions : sizeof A , &A et (A). Dans tous les autres cas, c'est une adresse (celle du premier élément du tableau identifié par A). Ce n'est pas, dans ces cas, un objet (donc a fortiori un objet pointeur).

  8. #8
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    @souviron34
    char *argv[] est équivalent char **argv
    Non, c'est faux et si on considère que c'est un énoncé approximatif et simplificateur pour faire vite, cette simplification abusive est la source des difficultés que je signale dans mon post précédent.

    char *argv[] : argv est un tableau (de pointeurs sur char)

    char **argv : argv est un pointeur (sur un pointeur sur char)

  9. #9
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2010
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2010
    Messages : 26
    Par défaut
    @souviron34 -> merci, ton code fonctionne

    Citation Envoyé par diogene Voir le message
    Par contre, tab est un tableau de pointeurs et tab[0] est un pointeur. Pour qu'on puisse écrire strcpy(tab[0], argv[0]) , il faut que tab[0] contienne l'adresse de début d'un tableau de char (suffisamment grand).
    Vous voulez dire qu'il faut que je donne l'adresse argv[0] dans le tab[0] ?

    Par contre, je suis d'accord avec vous qu'un pointeur est une "variable" contenant l'adresse d'une autre variable.

  10. #10
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut @diogene :
    Citation Envoyé par diogene Voir le message
    Non, c'est faux et si on considère que c'est un énoncé approximatif et simplificateur pour faire vite, cette simplification abusive est la source des difficultés que je signale dans mon post précédent.
    j'admet ta considération, néanmoins les avis sont plus que partagés sur ce point ;

    http://bytes.com/topic/c/answers/619...gv-implemented

    http://stackoverflow.com/questions/5...argc-char-argv

    http://bytes.com/topic/c/answers/215...argc-char-argv

    http://cboard.cprogramming.com/c-pro...ar-**argv.html

    http://www.dreamincode.net/forums/to...rgc-char-argv/

    Même la doc de MPI (même en ayant le pré-C89 C) :

    http://www.mpi-forum.org/docs/mpi-11-html/node151.html


    Je n'en ferai pas un plat, je comprend ta position, mais visiblement ce n'est qu'une interprétation (pédagogique, certes).

  11. #11
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    @souviron34

    Sur un sujet aussi sensible, il faut être précis ou on peut semer dans les esprits des généralisations abusives.
    Ce que je reproche à ta phrase, c'est d'avoir été sans nuances. Si tu avais dit
    Lorsque argv est déclaré comme un paramètre d'une fonction, alors char *argv[] est équivalent à char **argv
    je n'aurais rien trouvé à redire (et toutes les références que tu cites se placent dans ce cas).

    Accessoirement, le contexte de la discussion, même si c'est une supposition vraisemblable, n'implique pas obligatoirement que argv est un des paramètres de main().

  12. #12
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    @vegnagun
    Vous voulez dire qu'il faut que je donne l'adresse argv[0] dans le tab[0] ?
    Non, il faut y mettre l'adresse du premier élément du tableau de destination (et donc il faut avoir un tableau de destination suffisamment grand). argv[0] est l'adresse du premier élément du tableau source (celui qui doit être copié).

  13. #13
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2010
    Messages
    26
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2010
    Messages : 26
    Par défaut
    Citation Envoyé par diogene Voir le message
    Non, il faut y mettre l'adresse du premier élément du tableau de destination (et donc il faut avoir un tableau de destination suffisamment grand). argv[0] est l'adresse du premier élément du tableau source (celui qui doit être copié).
    D'accord. Merci, je essayer de trouver la solution.

    Je vais trouver quelques cours sur les pointeurs ainsi que les tableaux, faut que je progresse dans ce domaine là

    Je vous remercie à tous de votre aide

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. différence entre char **argv et char *argv[]
    Par BoxOfTheNight dans le forum C
    Réponses: 3
    Dernier message: 23/08/2014, 08h54
  2. copier tous les argv dans un seul char*
    Par coyotemk dans le forum Débuter
    Réponses: 3
    Dernier message: 06/12/2008, 17h14
  3. Convertir un (char *) en (const char *) dans C++
    Par anas.eh dans le forum C++
    Réponses: 10
    Dernier message: 03/09/2007, 13h59
  4. Tableau de char[] passé dans une fonction
    Par Joratois dans le forum C
    Réponses: 26
    Dernier message: 07/06/2007, 15h06
  5. char** argv incompris
    Par sanatou dans le forum C++
    Réponses: 2
    Dernier message: 07/12/2006, 11h51

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo