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 :

(Matrice) Tableaux de tableaux de strings, malloc et fscanf


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    aEssao
    Invité(e)
    Par défaut (Matrice) Tableaux de tableaux de strings, malloc et fscanf
    Bonjour,
    Comme le titre l'indique, le problème ici est par rapport aux tableaux de tableaux...
    Je travaille actuellement sur un petit projet et je tombe sur ceci:

    Je veux créer une matrice de strings: ma première intuition était alors de créer ceci directement en écrivant:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    int nb_V;//               sera lu dans un fichier donné
    .
    .
    .
    char Vet_and_accused[nb_V][nb_V][MAX_NAME_SIZE];
     
    //MAX_NAME_SIZE est fixé par une macro, et reprèsente la taille maximale des mots dans la matrice
     
    for(k=0;k<nb_V;k++){
      for(l=0;l<nb_V;l++){
        Vet_and_accused[k][l][0]='\0';//LIGNE A
       }
    }
    Les valeurs de la matrice sont ensuite définies grâce à un fscanf réalisé plutard dans le code à partir d'un fichier donné...
    Le problème c'est que, quand nb_V (qui est la taille de la matrice carrée en question) est petit, de l'ordre de 10 le programme marche bien...
    MAIS quand les données et donc la taille de la matrice deviennent de l'ordre de 1 000 000, je tombe sur un segmentation fault à la compilation...
    J'ai donc utilisé le ddd pour executer pas à pas le programme afin de savoir où ça coince et je vois qu'en fait le programme ne veut pas executer la LIGNE A comme il le faisait pour un nb_V petit.


    J'ai ensuite essayé de faire les choses autrement, et d'essayer l'allocation dynamique dans ma définition de la matrice, arrêtez moi si je dis n'importe quoi mais je l'ai fait comme suit:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    char* **Vet_and_accused =(char***)malloc(nb_V*MAX_NAME_SIZE*sizeof(char));
     
    for(i=0;i<nb_V;i++){
     
      Vet_and_accused[i] = (char**)malloc(nb_V*MAX_NAME_SIZE*sizeof(char));
    //Création des sous tableaux...
      for(l=0;l<nb_V;l++){
        Vet_and_accused[i][l]="";//                Initialisation de chaque case de la matrice
      }
    }
    Là, Rien ne marche plus, que nb_V soit grand ou petit, je reçois un Segmentation Fault.

    Quand, j'ai executé le programme pas à pas avec ddd, je vois que maintenant, l'étape d'initialisation ne pose plus problème, mais il y a un problème avec le fscanf: comme j'ai dit précedemment, les cases de la matrices sont définies par un fscanf dans un fichier donné.

    Je soupçonne ma définition avec le malloc de la matrice...
    Mon fscanf est à priori bien définit vu qu'il a marché dans le premier cas. D'ailleurs voilà à quoi il ressemble:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    fscanf(f,"%s %d",Vet_and_accused[i][0], &nb_Accused);

    Voilà, Merci déjà d'avoir pris le temps de me lire
    et merci d'avance pour votre réponse

  2. #2
    Membre éprouvé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 299
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 299
    Par défaut
    Salut, pour faire une matrice tu aussi peux faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    char ** tab = malloc(nb_V * nb_V * sizeof(*tab);
    Ensuite, avec des jeux d'indices tu peux accéder à l'élément (i, j) de ta matrice (i * nb_v + j).

    Pour remplir ta matrice, tu peux faire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    tab[i] = strdup(mastring);
    n'oublie pas ensuite de libérer toute ta mémoire

    quand tu utilises fscanf, n'oublie pas de tester ton code erreur de retour

  3. #3
    Membre Expert Avatar de jabbounet
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juin 2009
    Messages
    1 909
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 909
    Par défaut
    Salut,

    1 000 000 * 1 000 000 * MAX_NAME_SIZE dépasse peu être les limites autorisées par ton système.

    Ensuite:
    Sur l'allocation dynamique de tableau à plus de une dimension je te conseil de regarder ici
    http://c.developpez.com/faq/index.ph...LOC_tableau_2D

    Dans ton cas il faut considérer que tu as un tableau a 3 dimensions, un chaine de caractère étant aussi un tableau.
    Tu auras donc deux boucles imbriquées, pour tes allocations.

    Il faut vérifier si tes allocation dynamiques ont bien été effectuées, malloc retourne NULL en cas d'échec.

    les malloc n'ont pas besoin d'être casté.

  4. #4
    aEssao
    Invité(e)
    Par défaut
    Rebonjour,

    Tout d'abord, Merci pour vos réponses...
    Après reflexions:

    En effet pour peu que MAX_NAME_SIZE soit 10 et nb_V= 1 000 000 et comme un char est de taille un octet, on tombe dans une allocation de 10^13 octet, et ça je ne vois pas trop le système me l'autoriser

    Ce que je vais essayer de faire maintenant c'est de mieux utiliser l'allocation dynamique pour éviter toutes pertes: au lieu d'une matrice je vais plutôt utiliser des tableaux de tableaux avec des tableaux qui varient suivant les données, ça ne fera que me faire gagner de l'espace...

    Voilà tout, je vais essayer tout ça

    Merci encore !

  5. #5
    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
    Le plantage quand le tableau Vet_and_accused devient trop grand vient de ce qu'il est alloué sur la pile où la place disponible est limitée. Dans ce genre de cas, deux possibilités sont envisageables à priori :

    1- Utiliser un tableau en allocation statique (donc le déclarer static ou en global), mais cette solution suppose que sa taille soit connue à la compilation. Ce ne peut donc être un VLA (Variable Length Array du C99) comme dans ton premier code.

    2- Utiliser un tableau en allocation dynamique comme tu as essayé de le faire : allouer un tableau de nb_V*nb_V*MAX_NAME_SIZE char. Mais tel que, pour accéder à un char, on ne pourra pas écrire Vet_and_accused[i][j][k] mais Vet_and_accused[m] et il faudra gérer soi-même le calcul de m en fonction de i, j, k.

    Si on veut conserver cette notation bien commode, il faut compléter cette structure de données :
    On peut créer un tableau T1 de nb_V1*nb_V2 pointeurs sur char initialisé avec l'adresse de début de chaque segment de MAX_NAME_SIZE char dans la mémoire allouée . Dans ce cas, on peut écrire T1[n] pour accèder à l'un des tableaux de char et T1[n][k] pour accéder à un char et il faudra gérer soi-même le calcul de n en fonction de i, j. Toutefois cette procédure nous a permis de passer d'un problème sur un tableau à 3 dimensions au même problème sur un tableau à 2 dimensions.

    On peut utiliser à nouveau la même procédure : allouer un tableau T2 de nb_V1 pointeurs sur des pointeurs sur char et l'initialiser avec l'adresse de début de chaque segment de nb_V2 pointeurs sur char.

    Ceci correspond au code suivant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    // code à compléter pour tester la réussite des allocations demandées 
    // et en cas d'échec détruire ce qui a déjà été alloué avec succès
      char*** Vet_and_accused = malloc(nb_V1*sizeof(char**));    // allocation de T2
      Vet_and_accused[0] = malloc(nb_V1*nb_V2*sizeof(char*));    // allocation de T1
      Vet_and_accused[0][0] = malloc(nb_V1*nb_V2*MAX_NAME_SIZE); //allocation du tableau de char
      for(i = 1; i< nb_V1*nb_V2 ; i++)                           //initialisation de T1
        Vet_and_accused[0][i] = Vet_and_accused[0][i-1]+MAX_NAME_SIZE; 
      for(i = 1; i< nb_V1 ; i++)                                 //initialisation de T2
        Vet_and_accused[i] = Vet_and_accused[i-1]+nb_V2;

    On peut utiliser des variantes où les tableaux ne sont pas alloués en un seul bloc, par exemple en nb_V1 tableaux de nb_V2 pointeurs sur char au lieu d'un seul tableau de nb_V1*nb_V2 pointeurs sur char ou/et en nb_V1*nb_V2 tableaux de MAX_NAME_SIZE char au lieu d'un seul tableau de nb_V1*nb_V2*MAX_NAME_SIZE char.

Discussions similaires

  1. Tableaux php, array to string
    Par Lekno dans le forum EDI, CMS, Outils, Scripts et API
    Réponses: 12
    Dernier message: 10/12/2013, 11h52
  2. Réponses: 2
    Dernier message: 10/04/2008, 18h16
  3. Réponses: 2
    Dernier message: 28/12/2007, 12h09
  4. [Tableaux] Supprimer morceaux de string dans string
    Par zulot dans le forum Langage
    Réponses: 9
    Dernier message: 04/03/2006, 16h35
  5. [Tableaux] les tableaux
    Par jeanfrancois dans le forum Langage
    Réponses: 2
    Dernier message: 03/03/2006, 11h02

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