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 :

Tableau de N chaînes / Allocation dynamique


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé Avatar de acryline
    Profil pro
    Inscrit en
    Août 2006
    Messages
    200
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 200
    Par défaut Tableau de N chaînes / Allocation dynamique
    Bonjour,
    j'aimerais utiliser un tableau pour récupérer des chaînes de caractères de taille inférieure à 50 caractères. Donc seul le nombre de chaînes varie.

    En fait on a un tableau défini ainsi :

    Comment faire ?
    Merci pour votre aide.

  2. #2
    Membre éclairé Avatar de femtosa
    Inscrit en
    Juin 2002
    Messages
    253
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 253
    Par défaut
    FAQ, recherche et quand même, oui oui, un peu de réflexion ...

  3. #3
    Inactif  
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    1 958
    Détails du profil
    Informations personnelles :
    Âge : 60
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 1 958
    Par défaut
    Citation Envoyé par acryline
    Bonjour,
    j'aimerais utiliser un tableau pour récupérer des chaînes de caractères de taille inférieure à 50 caractères. Donc seul le nombre de chaînes varie.

    En fait on a un tableau défini ainsi :

    Comment faire ?
    Merci pour votre aide.
    Comment faire pour faire quoi ?
    Pour lire les chaînes de caractères ?

    Si tu n'en avais qu'une seule tu ferais probablement ça.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    char chaine[50];
    scanf("%s", chaine);
    N'est ce pas ?

    Donc tu fais pareil mais au lieu de mettre une variable chaine, tu mets une « cellule » de ton tableau qui pointe sur une chaîne... vois-tu ?

  4. #4
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Par défaut
    La valeur de N varie au cours de l'exécution du programme ? Car sinon il faut passer par un tableau dynamique donc par allocation ce qui change sensiblement ton tableau et sa création
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  5. #5
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Par défaut
    Citation Envoyé par Garulfo
    Comment faire pour faire quoi ?
    Pour lire les chaînes de caractères ?

    Si tu n'en avais qu'une seule tu ferais probablement ça.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    char chaine[50];
    scanf("%s", chaine);
    N'est ce pas ?

    Donc tu fais pareil mais au lieu de mettre une variable chaine, tu mets une « cellule » de ton tableau qui pointe sur une chaîne... vois-tu ?
    Si j'en avais qu'une seule je ferais:
    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
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    void fclean(char *s_buff, FILE *fp);
     
    int main(void)
    {
        char s_buff[50] = {0};
     
        printf("Entrz une chaine: ");
        fflush(stdout);
     
        if (fgets(s_buff, sizeof s_buff, stdin) != NULL)
        {
            fclean(s_buff, stdin);
            /* Suite du code */
        }
        else
        {
            fprintf(stderr, "Input error!\n");
        }
     
        return EXIT_SUCCESS;
    }
     
    void fclean(char *s_buff, FILE *fp)
    {
        char *pc = strchr(s_buff, '\n');
     
        if (pc != NULL)
        {
            *pc = 0;
        }
        else
        {
            int c;
            while ((c = fgetc(fp)) != '\n' && c != EOF)
            {
                continue;
            }
        }
    }
    voir, si vraiment il faut utiliser scanf():
    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
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    int main(void)
    {
        char s_buff[50] = {0};
        int c;
     
        printf("Entrz une chaine: ");
        fflush(stdout);
     
        if (scanf("%49[^\n]", s_buff) == 1)
        {
            if ((c = getchar()) != '\n')
            {
                /* saisie trop longue: on vide le tampon */
                scanf("%*[^\n]");
                getchar();
            }
     
            printf("%s\n", s_buff);
        }
     
        return EXIT_SUCCESS;
    }
    mais:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    char chaine[50];
    scanf("%s", chaine);
    n'est pas une idée très inspirée.

    Sinon, voici une exemple avec tableau dynamique:
    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
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    void fclean(char *s_buff, FILE *fp)
    {
        char *pc = strchr(s_buff, '\n');
     
        if (pc != NULL)
        {
            *pc = 0;
        }
        else
        {
            int c;
            while ((c = fgetc(fp)) != '\n' && c != EOF)
            {
                continue;
            }
        }
    }
     
    int main(void)
    {
        int err = EXIT_SUCCESS;
        int N = 3;
        int end = 0;
        char (*p_tab)[50] = NULL;
     
        p_tab = malloc(N * sizeof *p_tab);
        if (p_tab != NULL)
        {
            int i;
     
            /* Initialisation du tableau */
            memset(p_tab, 0, N * sizeof *p_tab);
     
            /* Saisie des chaines de caractère */
            for (i = 0; i < N && end == 0; ++i)
            {
                printf("Entrez une chaine: ");
                fflush(stdout);
     
                if (fgets(p_tab[i], sizeof p_tab[i], stdin) != NULL)
                {
                    fclean(p_tab[i], stdin);
                    if (strcmp(p_tab[i], "quit") == 0)
                    {
                        *p_tab[i] = 0;
                        end = 1;
                    }
                }
            }
     
            /* Affichage des chaines saisies */
            for (i = 0; i < N && *p_tab[i] != 0; ++i)
            {
                puts(p_tab[i]);
            }
     
            free(p_tab), p_tab = NULL;
        }
        else
        {
            fprintf(stderr, "Erreur d'allocation mémoire!\n");
            err = EXIT_FAILURE;
        }
        return err;
    }
    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  6. #6
    Membre confirmé Avatar de acryline
    Profil pro
    Inscrit en
    Août 2006
    Messages
    200
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 200
    Par défaut
    Jde l'avais mis en titre alors j'ai fait l'erreur de penser que ça suffisait.
    Je voulais savoir comment utiliser l'allocation dynamique avec un tableau de chaîne sachant que le nombre de chaînes peut changer.

    Pour un tableau normal on fait comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    //Tableau char chaine[N]
    char *chaine;
    chaine = malloc(N*sizeof(char));
    Pour un tableau de chaînes ça donne ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    //Tabeau char chaine [N][50];
    char  ????????; 
    chaine =???????;
    C'était tout ce que je voualais savoir Récupérer je sais faire...

    Merci !
    Edité : je crois que j'ai trouvé à la fin du code de mujigka, ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
       char (*p_tab)[50] = NULL;
        p_tab = malloc(N * sizeof *p_tab);
    J'avais fait un peu ça mais ça ne focntionnait pas, j'ai dû faire une petite erreur... je m'y remets . Merci

  7. #7
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Tu peux jouer avec realloc() (attention, pièges) ou créer une liste chaînée à la place (quitte à la reconvertir en tableau une fois la taille connue).
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  8. #8
    Membre éclairé
    Homme Profil pro
    Analyste/développeur Java EE
    Inscrit en
    Janvier 2005
    Messages
    376
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste/développeur Java EE

    Informations forums :
    Inscription : Janvier 2005
    Messages : 376
    Par défaut
    Je ferai quelque chose 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
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    char ** lignes = NULL;
    int i;
     
    //Allocation de la mémoire
    lignes = (char **)malloc(NB_LIGNES*sizeof(char *));  
    if (lignes == NULL) {
      perror("Erreur d'allocation de mémoire");
      return -1;
    }
    for (i= 0; i<NB_LIGNES; i ++){
      lignes[i] = NULL;
      lignes[i] = (char *)malloc(50*sizeof(char)); //50 lettres/ligne
      if (lignes[i] == NULL) {
        perror("Erreur d'allocation de mémoire");
        return -1;
      }
    }
     
    /*
     * Operations
     */
     
    //Libération de la mémoire
    for (i = 0; i<NB_LIGNES; i ++){
      free(lignes[i]);
    }
    free(lignes);

  9. #9
    Inactif  
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    1 958
    Détails du profil
    Informations personnelles :
    Âge : 60
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 1 958
    Par défaut
    Citation Envoyé par acryline
    Jde l'avais mis en titre alors j'ai fait l'erreur de penser que ça suffisait. [...]Merci
    Excuses moi... c'est moi qui ai mal lu le titre.
    Tout était là. Et je me suis trompé sur ton niveau... La remarque de Mujigka était donc pleinement justifiée -_-

    Donc ce que tu te demandes c'est comment allouer correctement la mémoire pour un tableau à deux dimensions en fait ?

    La réponse de Mujigka fonctionne mais n'est pas le meilleur choix.
    Cependant dans un premier temps ça te sera probablement bien suffisant.
    Quand tu voudras aller plus loin, tu as ça
    http://rperrot.developpez.com/articl...ationC/#L1.1.1
    Tu as une bonne explication des malloc, calloc et realloc.

    Mais cependant en faisant l'allocation telle que proposée par Mujigka tu alloues des espaces mémoires qui peuvent être disparates dans leurs localisations dans l'espace mémoire. De plus un tableau statique est alloué sur la pile d'appel (callstack) ce qui peut être génant (notamment si tu utilises beaucoup de fonctions récursives dans ton programme).
    Il vaut mieux allouer un bloc et le découper en morceaux.
    Je laisse tomber les vérifications sur les pointeurs:
    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
     
        int nb_lignes = 3;
        int nb_colonnes = 5; 
        int **matrice;          // Le pointeur sur la matrice
        int *_bloc_memoire; // Le bloc mémoire complet de la matrice
        int ligne;                 // indice pour le parcours des lignes
     
        // déclaration de l'espace nécessaire pour toute la matrice
        _bloc_memoire = malloc(nb_lignes * nb_colonnes * sizeof(int));
     
        // déclaration des pointeurs sur chaque ligne
        matrice = malloc(nb_lignes * sizeof(*int));
     
        // découpage du bloc de mémoire en nb_lignes
        for (ligne=0; ligne<nb_lignes; ligne++)
        {
            matrice[ligne] = _bloc_memoire + (nb_cols * ligne)
        }
    Mais bon, encore une fois, si c'est une très bonne manière de procéder, il vaut mieux commencer simplement.

  10. #10
    Membre émérite Avatar de crocodilex
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    697
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 697
    Par défaut
    Citation Envoyé par Garulfo
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
        matrice = malloc(nb_lignes * sizeof(*int));
    Ce n'est pas du C ça...

  11. #11
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Par défaut
    Citation Envoyé par Garulfo
    Mais cependant en faisant l'allocation telle que proposée par Mujigka tu alloues des espaces mémoires qui peuvent être disparates dans leurs localisations dans l'espace mémoire. De plus un tableau statique est alloué sur la pile d'appel (callstack) ce qui peut être génant (notamment si tu utilises beaucoup de fonctions récursives dans ton programme).
    Il vaut mieux allouer un bloc et le découper en morceaux.
    Je laisse tomber les vérifications sur les pointeurs:
    En quoi ma solution alloue des espaces mémoires qui peuvent être disparates dans leurs localisations dans l'espace mémoire? J'ai un espace contigü de Nx50, non? Par ailleurs, je n'alloue pas ground chose sur la pile...

    [Edit] Je pense que ma solution est adaptée dans la mesure où seule la première dimension du tableau varie, comme l'a mentionné le PO.

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  12. #12
    Inactif  
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    1 958
    Détails du profil
    Informations personnelles :
    Âge : 60
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 1 958
    Par défaut
    Citation Envoyé par mujigka
    [...]
    Thierry
    Te rends tu compte que la question posée montre que la personne n'en est pas rendu là ?

    On commence doucement... et on mène à la bonne réponse.

    D'où ma réponse à sa question.

  13. #13
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Par défaut
    Citation Envoyé par Garulfo
    Te rends tu compte que la question posée montre que la personne n'en est pas rendu là ?

    On commence doucement... et on mène à la bonne réponse.

    D'où ma réponse à sa question.
    Je n'ai fait que montrer comment faire correctement une saisie de chaîne de caractères, suite à ton intervention qui mentionnait une solution à base de A éviter comme la peste, comme gets() d'ailleurs. Les entrées utilisateur, c'est quelque chose de relaivement complexe en C. Je suis d'accord pour commencer en douceur, mais ce n'est pas une raison pour conseiller n'

    Le reste n'est qu'exemple...

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  14. #14
    Inactif  
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    1 958
    Détails du profil
    Informations personnelles :
    Âge : 60
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 1 958
    Par défaut
    Citation Envoyé par mujigka
    Je n'ai fait que montrer comment faire correctement une saisie de chaîne de caractères, suite à ton intervention qui mentionnait une solution à base de [...]

    Thierry
    Mais non ce n'est pas à éviter comme la peste.
    Mais je suis d'accord que ce n'est pas une bonne manière de faire...

    Tu as lu mon message disant que j'avais tort de ma remarque ??

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

Discussions similaires

  1. tableau de structure et allocation dynamique
    Par libliba dans le forum Débuter
    Réponses: 3
    Dernier message: 14/04/2011, 14h02
  2. Réponses: 13
    Dernier message: 18/07/2007, 09h01
  3. Réponses: 6
    Dernier message: 26/11/2005, 19h55
  4. Réponses: 18
    Dernier message: 06/07/2005, 14h58
  5. [Tableau] Allocation dynamique du contenu
    Par VincenzoR dans le forum Collection et Stream
    Réponses: 8
    Dernier message: 08/05/2004, 20h57

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