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 :

Exploiter tableaux dynamiques


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Juin 2012
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2012
    Messages : 12
    Par défaut Exploiter tableaux dynamiques
    Bonjour, suite au message que j'ai posé hier je tente de comprendre les tableaux dynamiques (bien qu'au final c'est un tableau de taille fixe que j'utilise, mais ne compliquons pas les choses plus qu'elles ne le sont!).

    L'objectif est simuler ce qui suit avec une boucle:
    Code c : 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
    int main(int argc, char **argv)
    {
        char str[6] = "abcde"; // 6 car \0 à la fin
        char copy[6];
     
        copy[0]=str[0];
        copy[1]=str[1];
        copy[2]=str[2];
        copy[3]=str[3];
        copy[4]=str[4];
        copy[5]=str[5];
     
       /*
        * Le code qui suit n'est pas autorisé (sauf en C99 je pense)
        int i;
        for(i=0; i<6; i++){
    	copy[i] = str[i];
        }   
        */
     
        printf("%s\n", copy); // affiche bien abcde
        return 0;
    }
    Je tente ma chance avec malloc():
    Code c : 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
    int main(int argc, char **argv)
    {
        char str[6] = "abcde"; // 6 car \0 à la fin
        char *copy;
     
        copy = malloc(6 * sizeof(int)); // On alloue de la mémoire pour le tableau copy
     
        int i;
        for(i=0; i<6; i++){
    	copy[i] = str[i];
        }
     
        printf("%s\n", copy);
        free(copy);
        return 0;
    }
    Est-ce la bonne méthode ( malloc() vs calloc() )? Existe-t-il quelque chose de plus simple?

    Merci pour le temps que vous me consacrerez.

  2. #2
    Membre chevronné

    Profil pro
    Inscrit en
    Août 2007
    Messages
    179
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 179
    Par défaut
    Ben c'est pas trop mal comme ça, c'est bien malloc() (puis c'est important d'apprendre à s'en servir), calloc() ne me semble pas très utile vu que tu définies tout de suite les valeurs (donc pas indispensable de les initialiser à 0)
    Une petite remarque tu utilises la taille la taille d'un "int" pour allouer des char. Fais plutôt
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    copy = (char*)malloc(6 * sizeof(char));
    (le (char*) ne sert à rien mais il augmente la lisibilité de ton code)

    enfin, on peut pas faire beaucoup plus simple si ce n'est en laissant "copy" sous forme de tableau (char copy[6];) comme dans le code que tu simules, du coup plus besoin de malloc (et de free) mais si tu ne l'as pas fait j'imagine qu'il y a une raison...

    edit : dernière petite remarque autant éviter les valeurs en dur par exemple dans ta boucle plutôt que d'aller jusqu'à 6, mieux vaux mettre strlen(str), ça fait plus sérieux et ça évite de devoir changer tout ton code si par exemple tu modifies la tailles des tableaux

  3. #3
    Membre habitué
    Profil pro
    Inscrit en
    Juin 2012
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2012
    Messages : 12
    Par défaut
    enfin, on peut pas faire beaucoup plus simple si ce n'est en laissant "copy" sous forme de tableau (char copy[6] comme dans le code que tu simules, du coup plus besoin de malloc (et de free) mais si tu ne l'as pas fait j'imagine qu'il y a une raison...
    oui, il y a une raison, comme écrit plus haut:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    /*
        * Le code qui suit n'est pas autorisé (sauf en C99 je pense)
        int i;
        for(i=0; i<6; i++){
    	copy[i] = str[i];
        }   
        */
    Ne vaut mieux-t-il pas coder en C89 pour une raison de portabilité?

  4. #4
    Membre chevronné

    Profil pro
    Inscrit en
    Août 2007
    Messages
    179
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 179
    Par défaut
    Citation Envoyé par programmeur.debutant Voir le message
    Ne vaut mieux-t-il pas coder en C89 pour une raison de portabilité?
    Mouais sans doute, encore qu'il y a moyen de tester que le compilateur est ou non compatible avec C99 et de coder en fonction (notament en testant si "__STDC_IEC_559__" est défini) mais là on rentre peut être dans des choses un peu compliquées.
    Par contre je ne vois pas ce qu'il y a de si incompatible avec C89 dans le code que tu présentes. Mets la déclaration de "i" avec les autres, les vieux compilateurs n'aiment pas trop que l'on déclare les variables n'importe où mais si tu arrives à avoir encore une erreur après ça, je suis curieux de la voir.

  5. #5
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 493
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 493
    Billets dans le blog
    1
    Par défaut
    Mettons certaines choses au clair

    Le terme de tableau dynamique est bizarre. En C, je pense qu'on peut dire qu'il y a d'un côté les tableaux, déclarées avec des [] et qui alloue une zone mémoire de taille fixe ou statique. ll y a de l'autre côté des pointeurs qui pointent sur une zone allouée dynamiquement avec malloc ou calloc et libérer par free. Dynamique car on peut faire des realloc, un free puis un nouveau malloc. Statique car on ne peut pas redimensionner. C'est bien l'allocation mémoire qui est statique ou dynamique, plus que le tableau (qui, à un instant donné est toujours de taille fixe).


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    /*
        * Le code qui suit n'est pas autorisé (sauf en C99 je pense)
        int i;
        for(i=0; i<6; i++){
    	copy[i] = str[i];
        }   
        */
    Pourquoi dis-tu cela ? Ca marche très bien en C89/90 et C99.


    Malloc vs calloc ? A part la mise à zéro et l'écriture, pas grand chose de différent.


    dernière petite remarque autant éviter les valeurs en dur par exemple dans ta boucle plutôt que d'aller jusqu'à 6, mieux vaux mettre strlen(str), ça fait plus sérieux et ça évite de devoir changer tout ton code si par exemple tu modifies la tailles des tableaux
    C'est vrai qu'il faut mieux ne pas écrire 6 partout, car le jour où tu souhaites que ce soit 8, il faut le changer partout. Mais la solution du strlen dans le for est une mauvaise idée pour le coup car la fonction sera appelée à chaque itération. Il faut mieux utiliser une variable pour stocker le résultat strlen et utiliser cette variable comme condition d'arrêt.

    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
    int main(int argc, char **argv)
    {
        char str[] = "une chaine. Je ne specifie pas la taille de "
        "'str' entre [] si je n'ai rien a rajouter a la fin.\n"
        "Si je veux une taille determinee du tableau, il faut le faire.\n";
     
        size_t longueur = strlen(str);
     
        char copy[longueur + 1]; /* Cette ecriture genere un warning en C89/90
                                    qui n'accepte pas les tableaux a taille variable
                                    (comprendre donnee par une variable).
                                    +1 pour '\0' final */
     
        size_t i;
     
        for(i=0; i<longueur; i++)
        {
            copy[i] = str[i];
        }
     
        printf("%s\n", copy);
        return longueur;
    }

    Quand à la question de la portabilité, j'ai envie de répondre : @#!?** $%#[!?@ on est au C11, stop le C89 ! Codons en C89 si pour mettre à jour une application en C89 ; pour une nouvelle application, codons en C99 (et C11 prochainement).

    Et comme dit par Pythéas, s'il y a besoin, il est possible de vérifier si le compilateur utilisé supporte le C99 ou seulement le C89/90. Donc s'il y a vraiment besoin de compatibilité (d'ailleurs, c'est plus de la compatibilité que de la portabilité), on peut faire ça

  6. #6
    Membre habitué
    Profil pro
    Inscrit en
    Juin 2012
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2012
    Messages : 12
    Par défaut
    Citation Envoyé par Bktero
    Pourquoi dis-tu cela ? Ca marche très bien en C89/90 et C99.
    Pas si j'en crois ceci :

    Le langage C existe en plusieurs versions.
    Une version récente, appelée le C99, autorise la création de tableaux à taille dynamique, c'est-à-dire de tableaux dont la taille est définie par une variable :
    ...

    ? Mais alors… il est interdit de créer un tableau dont la taille dépend d'une variable ?

    Non, rassurez-vous : c'est possible, même en C89. Mais pour faire cela, nous utiliserons une autre technique (plus sûre et qui marche partout) appelée l'allocation dynamique. Nous verrons cela bien plus loin dans ce cours.
    et ça se vérifie sur Wikipédia où on peut lire:
    Citation Envoyé par Wikipédia
    En 1999, une nouvelle évolution du langage est normalisée par l'ISO : C99 (formellement ISO/CEI 9899:1999). Parmi les ajouts, on notera les tableaux dynamiques, ainsi que des fonctionnalités (types complexes, mot-clef « restrict », directives agissant sur la simplification des instructions arithmétiques) souhaitables pour les calculs numériques intensifs, domaine habituel de FORTRAN.
    Et vu que vous me tendez la perche, faut-il spécifier quelque part dans le code source quelle version du C on utilise. Pour informer le compilateur (ça peut être bête comme question) ou tout simplement pour celui qui reprendra le code source par après moi.

    Ok, donc je ne me focalise pas sur le C89, je peux me laisser tenter par le c99.
    Vous avez quelques liens à me fournir pour me documenter sur les différences notables.

    Encore merci les gars.

  7. #7
    Membre Expert Avatar de Trademark
    Profil pro
    Inscrit en
    Février 2009
    Messages
    762
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 762
    Par défaut
    Bonjour,

    Vous mélangez un peu tout. On va préciser quelques trucs. Tout d'abord ceci :

    n'est pas un tableau dynamique (au sens alloué sur le tas) !
    Par conséquent c'est du code totalement valide en C89. Par contre faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    int taille;
    scanf("%d", &taille);
    char str[taille];
    n'est pas valide en C89 car la taille de str n'est pas connue à la compilation.

    Pour revenir à ton problème, pour faire ta copie, tu ne sauras généralement jamais la taille du tableau que tu vas copier, et c'est pour ça que tu utiliseras l'allocation dynamique (ce qui veut dire que tu ne connais pas la taille du tableau à la compilation). Par conséquent ce que tu cherches à faire c'est le code de la fonction strcpy :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    char* strcpy(char* dst, const char* src)
    {
      int i;
      for(i = 0; src[i] != '\0'; ++i)
        dst[i] = src[i];
      dst[i] = '\0';
      return dst;
    }
    Comme tu vois ce code n'alloue rien, il faut donc l'utiliser comme ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    int main()
    {
      char machaine[100];
      scanf("%99s", machaine); // on ne veut pas que l'utilisateur rentre plus de caractère que le buffer...
     
      char* macopie = malloc(strlen(machaine) + 1); // copie exacte du nombre de caractère entré.
      strcpy(macopie, machaine);
    }

Discussions similaires

  1. Tableaux dynamiques
    Par sebduth dans le forum Fortran
    Réponses: 5
    Dernier message: 05/07/2005, 15h36
  2. tableaux dynamiques
    Par Mynautor dans le forum C++
    Réponses: 23
    Dernier message: 12/02/2005, 02h45
  3. [D7] Tableaux dynamiques dans un record
    Par bobby-b dans le forum Langage
    Réponses: 2
    Dernier message: 30/06/2004, 23h23
  4. Article sur les tableaux dynamiques
    Par Eric Sigoillot dans le forum Langage
    Réponses: 2
    Dernier message: 16/04/2004, 22h00
  5. [Kylix] Tableaux dynamiques sour Kylix2
    Par Krän dans le forum EDI
    Réponses: 6
    Dernier message: 07/10/2003, 14h31

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