Tableaux à diverses dimensions avec diverses taille

Fermé
leoliom Messages postés 171 Date d'inscription jeudi 21 juillet 2016 Statut Membre Dernière intervention 20 février 2024 - 3 mai 2022 à 16:30
leoliom Messages postés 171 Date d'inscription jeudi 21 juillet 2016 Statut Membre Dernière intervention 20 février 2024 - 9 mai 2022 à 05:22
Bonjour,je veux créer non pas un tableau multidimensionnel mais un tableau du genre:

T=[[1,2,3],[4,1],[1,6,9,0,1]]
T est un tableau composé de 3 sous-tableaux avec chacun leur dimensions
le 1er sous tableau est de taille 3,le 2ieme est de taille 2 et le 3ieme de taille 5

Comment m'y prendre,créer un type qui permet de manipuler un tel type de tableau

Ensuite ,j'aimerais créer une fonction qui ajoute un sous-tableau dans T,une autre qui permet de supprimer un sous-tableau...
A voir également:

26 réponses

yg_be Messages postés 23405 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 20 décembre 2024 Ambassadeur 1 557
3 mai 2022 à 20:14
0
leoliom Messages postés 171 Date d'inscription jeudi 21 juillet 2016 Statut Membre Dernière intervention 20 février 2024 2
Modifié le 4 mai 2022 à 05:23
Bonjour,vous avez mal compris j’ai pas demandé qu’on fasse le travail à la place,j’ai juste besoin qu’on me donne des pistes et autre pour m’aider à résoudre ce problème,je suis bloqué dessus depuis plusieurs jours .Si j’avais pas des difficultés ou si il y avait une solution sur le net ou des choses qui y ressemble je n’aurais pas posté
Ce genre de tableau ressemble un peu au tableau multidimensionnel sauf que les sous tableau peuvent avoir des taille différente

Je sais comment créer un type tableau qui pointe sur les éléments d’un tableau à 1 dimensions
struct tableau{
int taille;
int *tab;
}
Sauf pour le tableau que j’ai je suis perdu,je sais comment démarrer .Si je pouvais savoir comment faire (le principe) pour accéder aux éléments de mo. Tableau ca m’aiderait à avancer et essayer de faire mon exo
0
yg_be Messages postés 23405 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 20 décembre 2024 1 557
4 mai 2022 à 11:06
Comment déclarerais-tu ce tableau?
Si tu es bloqué, c'est peut-être qu'il te manque les bases. Au lieu de rester bloqué, tu apprendras mieux en faisant des exercices plus simples.
0
[Dal] Messages postés 6198 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 13 décembre 2024 1 096
4 mai 2022 à 11:08
Tu ne pourras pas vraiment utiliser la notation avec l'opérateur crochets pour accéder aux éléments de ton "tableau" avec ce type
struct tableau
, mais si cela n'est pas un obstacle, c'est faisable de créer une structure de données permettant de stocker dans un tableau des moyens d'accéder à ces éléments de taille variable.

Si cela te suffit, c'est trivial à faire. Pour stocker les données que tu montres en exemple, il te suffit de créer tableau de
struct tableau
avec une dimension définie de 3 (une seule), où tu stockes tes
struct tableau
(les "lignes" du "tableau"), et pour chacune d'elles, tu initialises la struct avec le nombre d'éléments qu'elle doit contenir et alloues la mémoire pour le tab.

Tu peux aussi faire une allocation dynamique.
0
leoliom Messages postés 171 Date d'inscription jeudi 21 juillet 2016 Statut Membre Dernière intervention 20 février 2024 2
4 mai 2022 à 11:47
Esce que je dois faire comme ceci:
struct tableau{
  int 3;//car vous avait dit que je dois définir avec une dimension de 3           
   int *tab
}
struct tableau_multidimensionnel{
      struct tableau;
      int taille;//taille pour chaque tableau

}





Par contre comment alloue la mémoire pour le tab
esce que c’est tab=(int *)(sizeof(int)*3)
0
[Dal] Messages postés 6198 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 13 décembre 2024 1 096
4 mai 2022 à 13:21
[Dal] a écrit :
il te suffit de créer tableau de struct tableau avec une dimension définie de 3

Ce n'est pas du tout ce que tu fais.

leoliom a écrit :
Par contre comment alloue la mémoire pour le tab
esce que c’est tab=(int *)(sizeof(int)*3)
  • il manque l'appel à la fonction malloc dans ce que tu écris
  • en C on ne caste pas le résultat de malloc, c'est en C++ que cela doit être fait
1
leoliom Messages postés 171 Date d'inscription jeudi 21 juillet 2016 Statut Membre Dernière intervention 20 février 2024 2
4 mai 2022 à 14:30
Ah bon c’est pas ça .J’ai mal interprété alors fesje vous avez dit
Créer tableau de struct tableau ça veut dire j’ai une structure dans une autre ou bien? comme ceci:
Struct tableau {

struct tableau{
int 3;
int *tab=malloc(3*sizeof(int));
}
}
0
[Dal] Messages postés 6198 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 13 décembre 2024 1 096
Modifié le 4 mai 2022 à 16:52
1.

a. Non, pas besoin de struct imbriquées ;
b. Tu ne peux pas écrire une déclaration de struct avec un appel à malloc dedans, et
int 3;
ne fait pas ce que tu penses et est syntaxiquement interdit aussi (un nom de variable ne peut pas être un chiffre ou commencer par un chiffre en C).
(ce que tu as posté, tu l'as peut-être écrit à la va vite et sans trop réfléchir, mais cela n'a aucun sens et ton compilateur va te hurler dessus si tu tentes de compiler cela. fais un peu attention stp et avant de poster, vérifie que ton code compile sans avertissements ni erreurs)

2.

Si je veux déclarer tableau d'un certain type avec un certain nombre d'éléments, la syntaxe, en C, c'est :

<type> <identifiant>[<nombre d'éléments];


Par exemple, un tableau de 150 double, qui s’appellerait mon_tableau :

double mon_tableau[150];


C'est un concept de base.

Lorsque tu définis une struct, en C, tu définis en réalité un type (composite).

struct tableau {
    int taille;
    int *tab;
};


définit un type qui s'appelle
struct tableau


Pour définir un un tableau de 150 éléments de ce type, qui s’appellerait mon_tableau, c'est la même syntaxe, tu utilises juste ce type pour indiquer le type de chaque élément de ton tableau :

struct tableau mon_tableau[150];


Maintenant, tu peux accéder à chacun des 150 éléments que mon_tableau peut stocker, en initialisant chaque struct accessible par ce que tu souhaites.

mon_tableau[0].taille = 3;
mon_tableau[0].tab = malloc(sizeof(int) * 3);
mon_tableau[0].tab[0] = 1;
mon_tableau[0].tab[1] = 2;
mon_tableau[0].tab[2] = 3;


Edit : correction de coquilles et erreurs
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
leoliom Messages postés 171 Date d'inscription jeudi 21 juillet 2016 Statut Membre Dernière intervention 20 février 2024 2
4 mai 2022 à 18:31
Ah je vois tout est plus clair dans ma tête,je n’avais jamais encore fait ce type de chose mais maintenant ça me parait plus simple


Du coup en se basant à peu près sur ce que vous avez dit je vais essayer de traduire en C 3 fonctions


1)Créer un tableau vide
tableau creer_tableau_vide(){
    tableau T;
    T.taille=0;
     return T;


}


T sera ainsi composé d’aucun sous tableau


2)Ajouter un sous tableau à T
tableau ajout(tableau T,mon_tableau T1){
    int dernier_indice_T=T.taille-1;
    T.taille=T.taille+1// on augmente la taille du tableau de 1 
     T[dernier_indice]=T1;
      return T;
}




3)Ajouter un tableau à une position quelconque


tableau ajout(tableau T,mon_tableau T1,int i){
  int j;
  for(j=T.taille-1;j>=i;j++){
     T[j+1]=T[j];
   }
T[i]=T1;
T.taille++;

}


0
[Dal] Messages postés 6198 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 13 décembre 2024 1 096
Modifié le 4 mai 2022 à 19:32
Tu as dû définir des typedef sur des types pour
tableau
et
mon_tableau
.

Peux-tu nous dire comment ils sont définis stp, afin qu'on sache de quoi tu parles.

Tu pourrais aussi nous dire quel est ton but, plutôt que de poster du code et nous laisser deviner si cela est adéquat.
0
leoliom Messages postés 171 Date d'inscription jeudi 21 juillet 2016 Statut Membre Dernière intervention 20 février 2024 2
4 mai 2022 à 19:50
Non j’ai pas fait de typedef j’ai utilisé vos types

Tout à l’heure vous avez défini
 struct tableau mon_tableau[150];

Tableau par exemple T=[[1,2],[5,6]]
Mon_tableau est comme par exemple T’=[7,6]


Ma fonction créer_tableau_vide permet de créer un tableau avec 0 élément

Ma fonction 2) ajout permet d’ajouter à la fin d’un tableau de type T(comme tout à l’heure) un tableau du genre comme T’
Exemple :ajouter T’ à T de sorte que
T= [[1,2],[5,6],[7,6]]

3) ajout ça permet d’ajouter un tableau du type de T’ à une position quelconque dans un tableau du type comme T
0
[Dal] Messages postés 6198 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 13 décembre 2024 1 096
Modifié le 4 mai 2022 à 23:19
Je n'ai défini aucun type.

C'est toi qui l'a fait en proposant :

struct tableau {
    int taille;
    int *tab;
};


tu as défini un type
struct tableau
(c'est à 3ème fois que je te le dis, là j'ai atteint mon quota. Si ne sais pas de quoi je parle, tu dois revoir ton cours ou un manuel de toute urgence.

Si tu as cela dans ton code, et que tu n'as pas défini de typedef pour type
Tableau
, ou
mon_tableau
, tu n'as pas de type
Tableau
, ni un type
mon_tableau
et donc ces prototypes de fonctions ne peuvent pas compiler :

tableau creer_tableau_vide();
tableau ajout(tableau T,mon_tableau T1);
tableau ajout(tableau T,mon_tableau T1,int i);


Donc, si tu n'as aucun des types retournés par les fonctions ou passés en paramètres (à part int) ton code ne risque pas de compiler (de nouveau, tu n'as manifestement pas tenté de le compiler avant de poster).

Tu parles aussi d'un
tableau de type T(comme tout à l’heure)

On n'a définit aucun type T. Sais tu ce qu'est un type ?

Ecris un code tentant de mettre en oeuvre quelque chose de simple, qui compile et qui fonctionne, et qui te soit utile pour aller dans la direction où tu veux aller (que tu n'as toujours pas expliquée).

Fais le à partir du code que j'ai posté.

Après si tu veux essayer des choses plus compliquées, en ayant un tableau qui puisse avoir un nombre variable de
struct tableau
comprenant tes sous-tableaux, tu ne pourras pas définir ton tableau de
struct tableau
avec une taille fixe, mais utiliser des pointeurs de pointeurs sur struct et allouer dynamiquement la mémoire nécessaire pour stocker l'ensemble.

Quelque chose, comme ceci :

#include <stdlib.h>

struct tableau {
    int taille;
    int *tab;
};

int main(void) {
        int nb_de_sous_tableaux = 3;

        struct tableau ** mon_tableau = malloc(sizeof(struct tableau *) * nb_de_sous_tableaux);
        for (int i = 0; i < nb_de_sous_tableaux; i++) {
                mon_tableau[i] = malloc(sizeof(struct tableau));
        }

        mon_tableau[0]->taille = 3;
        mon_tableau[0]->tab = malloc(sizeof(int) * 3);
        mon_tableau[0]->tab[0] = 1;
        mon_tableau[0]->tab[1] = 2;
        mon_tableau[0]->tab[2] = 3;

        free(mon_tableau[0]->tab);

        for (int i = 0; i < nb_de_sous_tableaux; i++) {
                free(mon_tableau[i]);
        }
        free(mon_tableau);

        return 0;
}
0
leoliom Messages postés 171 Date d'inscription jeudi 21 juillet 2016 Statut Membre Dernière intervention 20 février 2024 2
5 mai 2022 à 12:35
Bonjour je me suis dit que typedef c'etait pas nécessaire vu que je voulais pas renommer mon type.Mais maintenant je vois pourquoi a chaque fois on met typedef ok

En fait les T,T1 c'etait juste des exemples pour vous dire que je veux que T soit de type tableau et T1 de type mon_tableau

D'accord je vais donner le but de l'exercice
En fait mon exercice me donne T=[1,2,3,-1,4,8,9,-1,6,1,4,-1]
On me demande de transforme T de sorte à avoir T'=[[1,2,3],[4,8,9],[6,1,4]]
Donc on tient pas compte des -1
Pour pouvoir y parvenir je me suis dis qu'il faut que j'ai un type tableau(unidimensionnel comme T),un type mon_tableau(comme celui de T' de l'exo)
Je me suis dit qu'il faut aussi que je crée une fonction creer un tableau vide et ajoute un sous tableau à la fin un tableau du même type que le tableau T' de mon exo

l'algorithme que j'ai en tête en me basant sur le tableau donné dans mon exo est le suivant:

transforme(tableau T)
Pour i allant de 0 à T.taille-1
Trouver les indices où se trouve -1


mon_tableau[0]->taille=4( 1er indice ou se trouve le -1)
//Aprés ca on remet le compteur de -1 à 0
//De base je voulais faire créer un tableau T' du type mon_tableau
//Créer un tableau du type tableau(unidimensionnel avec 1,2,3)=>T1=[1,2,3]
//Ensuite faire appel a ma fonction ajout pour ajouter T1 dans T'=>T'=[[1,2,3]]
//Mais je vois qu'on pouvait faire autrement comme ce que vous avez proposé
mon_tableau[0]->tab[0]=1
mon_tableau[0]->tab[1]=2
mon_tableau[0]->tab[3]=3


//On compte les éléments avant le trouver le second -1
mon_tableau[1]->taille=3
mon_tableau[1]->tab[0]=4
mon_tableau[1]->tab[1]=8
mon_tableau[1]->tab[3]=9


//Idem
mon_tableau[2]->taille=3
mon_tableau[2]->tab[0]=6
mon_tableau[2]->tab[1]=1
mon_tableau[2]->tab[3]=4
0
[Dal] Messages postés 6198 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 13 décembre 2024 1 096
5 mai 2022 à 17:22
Je n'ai pas le temps de regarder tout de suite en détails, mais lorsque tu dis ceci :
D'accord je vais donner le but de l'exercice
En fait mon exercice me donne T=[1,2,3,-1,4,8,9,-1,6,1,4,-1]
On me demande de transforme T de sorte à avoir T'=[[1,2,3],[4,8,9],[6,1,4]]
Donc on tient pas compte des -1


Tu dis quelque chose de différent du problème initial que tu posais, qui était de pouvoir structurer en mémoire des données (int) avec des dimensions variables. Là, tu un tableau de 3x3 et pas ce que postais au début, qui était : [[1,2,3],[4,1],[1,6,9,0,1]].

Avec un tableau de 3x3, tu peux représenter tes données dans un espace contigu de mémoire et y accéder avec la notation [][].

Par exemple :

#include <stdio.h>
#include <stdlib.h>
 
int main(void) {
    int row = 3, col = 4, i, j, count;
 
    int (*arr)[col] = calloc(row, sizeof *arr);
     
    count = 0;
    for (i = 0; i < row; i++)
        for (j = 0; j < col; j++)
            arr[i][j] = ++count;
 
    for (i = 0; i < row; i++)
        for (j = 0; j < col; j++)
            printf("%d ", arr[i][j]);
 
    free(arr);
     
    return 0;
}


Tu dois juste déterminer le nombre de lignes et de colonnes souhaitées, et réserver l'espace mémoire pour le tableau à 2 dimensions avec le prototype adéquat, comme ci-dessus, et tu peux y accéder aux données avec la notation crochets comme dans l'exemple ci-dessus pour le remplir avec les données provenant de ton tableau plat à 1D.

Ton idée d'utiliser une struct n'est pas nécessaire, puisque le langage te permet de faire plus naturellement ou sous la forme d'un vrai tableau C adressable en 2D, et non pas d'un tableau de struct.

Dal
0
leoliom Messages postés 171 Date d'inscription jeudi 21 juillet 2016 Statut Membre Dernière intervention 20 février 2024 2
5 mai 2022 à 19:31
En fait mon exo c'est 2 partie

1er partie:tableau composé de sous tableau de taille différente

2ieme partie:tableau composé de sous tableau de même taille


les lignes et colonnes de votre code ca veut dire on a combien de sous-tableau
3 ligne et 4 colonnes veut dire 3 sous tableau avec dedans chacun 4 éléments?
0
leoliom Messages postés 171 Date d'inscription jeudi 21 juillet 2016 Statut Membre Dernière intervention 20 février 2024 2
Modifié le 5 mai 2022 à 19:34


int (*arr)[col] = calloc(row, sizeof *arr);


Le crochet [col] est censé faire quoi
C'est quoi cette notation [][],j'en avais jamais vu encore
0
[Dal] Messages postés 6198 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 13 décembre 2024 1 096
Modifié le 5 mai 2022 à 21:57
Alors, voilà quelques précisions.

col
est une variable du programme contenant une valeur entière, dans mon exemple un 4. Dans
row
, je mets le nombre de lignes souhaitées.

dans
int (*arr)[col] = calloc(row, sizeof *arr);
, la partie à gauche du signe égal déclare une variable
arr
en tant que pointeur sur un tableau de
col
int.

Ce type de déclaration est possible en langage C depuis le standard C99, où on peut utiliser la notation VLA pour spécifier à l'exécution la taille d'un tableau. C'est juste la notation VLA qui est utilisée dans mon exemple et le tableau n'est pas un tableau VLA. En effet, la mémoire n'est pas affectée sur la pile, mais sur le tas, avec calloc().
On aurait aussi pu utiliser malloc().

Comme on alloue à ce pointeur un espace mémoire de la taille occupée par les données pointées par le tableau multiplié par autant que fois que l'on veut de lignes (cf. doc de calloc()), on obtient un espace mémoire contigu qui permet de stocker col x row int (initialisé à 0 par calloc() ou avec un contenu arbitraire si on utilise malloc()).

[]
est un opérateur en C. L'opérateur crochets permet d'accéder à la donnée existante à un emplacement mémoire augmenté de l'indice qui figure entre crochets (fois la taille de l'objet stocké), autrement dit, il facilite l'accès au contenu d'un tableau, par exemple :

int arr[5] = { 0, 1, 2, 3, 4 };
printf("Le 3ème élément de arr est : %d\n", arr[2]);


Ce code affichera : 2, car l'opérateur crochets aura permis d'accéder à l'int stocké à l'adresse de arr + (2 x la taille d'un int).

Cet opérateur peut être combiné pour simuler un tableau 2D sous réserve que la dimension d'une ligne soit connue, ce qui permet de faciliter l'accès à un élément figurant à une ligne et colonne précise, par exemple :
int arr[2][5] = {
    { 0, 1, 2, 3, 4},
    { 5, 6, 7, 8, 9}
};
printf("L'élément présent en 2ème ligne, 3ème colonne est : %d\n",
    arr[1][2]);


Ce code affichera : 7

La déclaration que je propose permet d'effectuer une réservation, lors de l'exécution du programme, de l'espace mémoire nécessaire au stockage d'un tableau 2D d'une taille connue à l'exécution, tout en conservant la possibilité d'adresser son contenu avec les opérateurs crochets combinés.

Est-ce plus clair ?
0
leoliom Messages postés 171 Date d'inscription jeudi 21 juillet 2016 Statut Membre Dernière intervention 20 février 2024 2
5 mai 2022 à 22:10
Oui c’est plus clair
Mais j’ai essayé d’utiliser votre code pour répondre à la question partie 1 de mon exo(taille sous tableau différente) mais j’arrive pas ,le compilateur me renvoie que des erreurs

Esceque l’algorithme que j’ai mis tout à l’heure à 12h15 est correct?
0
[Dal] Messages postés 6198 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 13 décembre 2024 1 096
5 mai 2022 à 22:55
Si tu veux dire celui-ci à 12:35 : https://forums.commentcamarche.net/forum/affich-37585534-tableaux-a-diverses-dimensions-avec-diverses-taille#13

non, il n'est pas "correct".

Je ne vois pas comment tu alloues la mémoire, mais en tout cas tes indices ne sont pas consécutifs. De plus, les "sous-tableaux" ont une taille fixe et je ne sais pas ce que tu veux dire par la partie 1 de ton exo.

j’ai essayé d’utiliser votre code pour répondre à la question partie 1 de mon exo(taille sous tableau différente) mais j’arrive pas ,le compilateur me renvoie que des erreurs

Mon code en https://forums.commentcamarche.net/forum/affich-37585534-tableaux-a-diverses-dimensions-avec-diverses-taille#14 compile très bien et sans avertissements ni erreurs avec gcc version 8.3.0
0
leoliom Messages postés 171 Date d'inscription jeudi 21 juillet 2016 Statut Membre Dernière intervention 20 février 2024 2
6 mai 2022 à 04:59
Non j’ai dit que la partie 1 de mon exo les sous tableaux ont des tailles différentes et pouf la partie 2 la taille
Pour l’instant,je préfère qu’on traite d’abord la partie 1 de mon exo

Non votre code marche,je voulais dire que si j’essaye de l’adapter à ma façon de sorte qu’il fasse ce que j’attend ca marche pas

Je vais essayer de voir ce qui cloche dans mon algo et code et après plus tard je posterais ce que j’ai fait
0
Theo_0055 Messages postés 275 Date d'inscription mardi 21 juillet 2020 Statut Membre Dernière intervention 19 janvier 2023 1
Modifié le 6 mai 2022 à 11:23
Bonjour j'ai écrit une fonctionne qui ne retourne qu'une erreur,a savoir le return mon_tableau
mon_tableau est un pointeur or moi je veux renvoyer un type TABLEAU mais ca marche pas et je vois pas comment faire.Comment faire pour que le pointeur mon_tableau soit du type TABLEAU

#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
typedef struct tableau {
    int taille;
    int *tab;
}tableau;


typedef struct tableau TABLEAU TABLEAU;

int compte_moins_1(tableau T){
  int nb=0;
  int i;
  for(i=0;i<T.taille;i++){
    if(T.tab[i]==-1)
      nb++;
  }
  return nb;
}

TABLEAU transforme(tableau T){
    int nb_de_sous_tableaux=compte_moins_1(T) ;
    TABLEAU struct tableau ** mon_tableau = malloc(sizeof(struct tableau *) * nb_de_sous_tableaux);
    int i,compteur;
    
    bool debut_moins1=true;
    for(i=0;i<T.taille;i++){
        if(T.tab[i]!=-1){
            if(debut_moins1){
                if (i>=1){
                    int j;
                    for (j= 0; i < nb_de_sous_tableaux; i++) {
                        mon_tableau[i] = malloc(sizeof(struct tableau));
                    }
                    int k,l;
                    for(k=0;k < nb_de_sous_tableaux;k++){
                        for(l=0;l < nb_de_sous_tableaux;k++){
                            mon_tableau[k]->taille = compteur;
                            mon_tableau[k]->tab = malloc(sizeof(int) * compteur);
                            mon_tableau[k]->tab[l] = T.tab[i];
                        }
                    }
                    
                    
                }
                compteur=1;
                  
                debut_moins1=false;
            }
            else{
                int k,l;
               for(k=0;k < nb_de_sous_tableaux;k++){
                    for(l=0;l < nb_de_sous_tableaux;k++){
                        mon_tableau[k]->taille = compteur;
                        mon_tableau[k]->tab = malloc(sizeof(int) * compteur);
                        mon_tableau[k]->tab[l] = T.tab[i];
                    }
                }
              compteur+=1;
            }
        }
        else
            debut_moins1=true;
    }
    return mon_tableau;
}
0
Theo_0055 Messages postés 275 Date d'inscription mardi 21 juillet 2020 Statut Membre Dernière intervention 19 janvier 2023 1
6 mai 2022 à 11:19
 TABLEAU struct tableau ** mon_tableau = malloc(sizeof(struct tableau *) * nb_de_sous_tableaux);


Ceci renvoie une erreur
0
[Dal] Messages postés 6198 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 13 décembre 2024 1 096
Modifié le 6 mai 2022 à 12:41
1.

typedef sert à définir un alias de type. Il n'est pas obligatoire de définir un typedef pour utiliser un type struct, et tu peux faire sans, comme je l'ai montré dans mon code d'exemple en https://forums.commentcamarche.net/forum/affich-37585534-tableaux-a-diverses-dimensions-avec-diverses-taille#12 mais certaines personnes préfèrent le faire pour éviter d'avoir à taper
struct truc ma_structure;
pour déclarer une variable, ils définissent un alias de ce type sous un nom "truc" pour pouvoir juste taper
truc ma_structure;
pour faire la même chose.

Comme tu veux manifestement utiliser ce type d'écriture (personnellement je ne suis pas fan), tu dois utiliser des typedef, et il faut les définir et utiliser correctement.

La syntaxe est :

typedef <type existant> <alias du type existant>;


et ensuite, tu peux utiliser "alias du type existant" à la place de "type existant"

2.

Dans ce que tu postes, tu fais ceci :

typedef struct tableau {
    int taille;
    int *tab;
}tableau;
  • après
    typedef
    tu as ton type
    struct tableau { int taille; int *tab; }
    qui est le "type existant" (qui est lui-même défini de façon compacte dans le typedef lui-même)
  • et après l'accolade fermante tu as l' "alias du type existant" qui est défini comme étant "tableau"


Cette construction est conforme à la syntaxe de typedef, sous une forme compacte.

Personnellement, je n'ai pas trop cette façon de faire, style couteaux suisses, car elle mélange trop de choses et les débutants en C ne comprennent pas, en général ce qu'ils font.

C'est plus clair, à mon sens de faire :

struct tableau {
    int taille;
    int *tab;
};
typedef struct tableau tableau;


Les deux sont équivalents, et te permettent désormais d'écrire :
tableau mon_tableau
à la place de
struct tableau mon_tableau
.

3.

La suite de ce que tu définis, en revanche, n'a pas de sens et donne une erreur de compilation, car tu respectes pas la syntaxe de typedef :

typedef struct tableau TABLEAU TABLEAU;


Ceci ne compile pas chez moi et renvoie :

$ gcc -Wall -Wextra 37585534.c 
37585534.c:15:32: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘TABLEAU’
typedef struct tableau TABLEAU TABLEAU;
^~~~~~~


Que veux-tu faire avec ce second typedef que tu veux appeler TABLEAU alors que tu as déjà un typedef pour la
struct tableau
que tu as appelé
tableau
?

TABLEAU struct tableau ** mon_tableau
ne peut pas fonctionner non plus, même si tu avais définit correctement un typedef dénommé TABLEAU, car la déclaration est syntaxiquement incorrecte. Soit tu utilises le type
struct tableau
soit tu utilises un alias de ce type, mais pas les deux en même temps.

C'est comme si tu écrivais :
int int un_entier;
, ou
float int un_nombre;
le compilateur ne saurait pas quoi en faire...

En revanche
tableau ** mon_tableau
ou
struct tableau ** mon_tableau
(comme je l'avais écrit) devraient ne pas renvoyer d'erreurs.
0
[Dal] Messages postés 6198 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 13 décembre 2024 1 096 > [Dal] Messages postés 6198 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 13 décembre 2024
Modifié le 6 mai 2022 à 13:03
Je ne suis pas sûr que tu sois allé revoir ton cours ou manuel sur les struct comme je te conseillais de le faire, alors voilà quelques précisions pouvant être utiles à ta compréhension :

Quand tu écris :

struct tableau {
    int taille;
    int *tab;
};
  • struct
    est un mot clef du langage C, il permet ici au compilateur de comprendre que tu veux définir un type composite struct
  • tableau
    est étiquette du type struct, elle identifie le type struct créé
  • le contenu des accolades définit les éléments du type composite
  • après l'accolade fermante, tu mets un
    ;
    car c'est une instruction que tu viens d'écrire et tu la termines


En faisant cela, tu n'as pas défini un type
tableau
("tableau" est juste une étiquette, pas un type), tu as défini un type
struct tableau
. Pour désigner et utiliser ce type tu dois taper
struct tableau
.

Pour que "tableau" devienne un type à lui seul, tu dois créer un alias sur le type
struct tableau
au moyen de
typedef
.

Je ne peux pas expliquer plus clairement :-)
0
Theo_0055 Messages postés 275 Date d'inscription mardi 21 juillet 2020 Statut Membre Dernière intervention 19 janvier 2023 1
Modifié le 6 mai 2022 à 13:15
Pour le 1 et 2 j'ai compris et je vois ce que vous voulez dire/

Pour le 3. En fait je veux définir un type TABLEAU .Ce type sera composé de tableau de type tableau
Esce que vous voyez ce que je eux dire?
TABLEAU c'est comme un énorme tableau et dans ce tableau il ya dedans des tableaux(sous_tableau) de tailles différentes)

A un moment j'avais pensé a faire
typedef struct TABLEAU TABLEAU{
      tableau *tab
      int taille;
}



Mais le problème c'est que si je fais ca je pourrais pas utiliser le double pointeur mon_tableau et je pourrais pas faire les mêmes opérations de ce dernier
0
Theo_0055 Messages postés 275 Date d'inscription mardi 21 juillet 2020 Statut Membre Dernière intervention 19 janvier 2023 1
6 mai 2022 à 13:15
desolé j'avais oublie de mettre l e typedef
0
[Dal] Messages postés 6198 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 13 décembre 2024 1 096
Modifié le 6 mai 2022 à 13:46
Dans ce cas tu peux définir :

typedef tableau ** TABLEAU;


Mais c'est une très mauvaise pratique que de camoufler un type pointeur dans un typedef.

En utilisant les 2 typedef, si tu veux / dois faire cette atrocité en dépit du bon sens, mon code précédent peut s'écrire comme ceci :

#include <stdlib.h>

struct tableau {
    int taille;
    int *tab;
};
typedef struct tableau tableau;

typedef tableau ** TABLEAU;

int main(void) {
        int nb_de_sous_tableaux = 3;

        TABLEAU mon_tableau = malloc(sizeof(tableau *) * nb_de_sous_tableaux);
        for (int i = 0; i < nb_de_sous_tableaux; i++) {
                mon_tableau[i] = malloc(sizeof(tableau));
        }

        mon_tableau[0]->taille = 3;
        mon_tableau[0]->tab = malloc(sizeof(int) * 3);
        mon_tableau[0]->tab[0] = 1;
        mon_tableau[0]->tab[1] = 2;
        mon_tableau[0]->tab[2] = 3;

        free(mon_tableau[0]->tab);

        for (int i = 0; i < nb_de_sous_tableaux; i++) {
                free(mon_tableau[i]);
        }
        free(mon_tableau);

        return 0;
}


C'est "mal" de cacher un pointeur (et là qui plus est un pointeur sur un pointeur) parce que le typedef occulte une information importante et que le risque est que demain toi ou une autre personne reprenant ton code ne le comprenne pas et déréférence un pointeur non initialisé ou autres joyeusetés.

C'est le genre de trucs qui fait hurler Linus Tolvards si un contributeur au noyau Linux s'amuse à faire cela (et ce n'est pas le seul).

https://www.kernel.org/doc/html/v4.10/process/coding-style.html#typedefs
0
leoliom Messages postés 171 Date d'inscription jeudi 21 juillet 2016 Statut Membre Dernière intervention 20 février 2024 2
6 mai 2022 à 15:14
En fait vous,vous avez défini un type double pointeur sur un tableau appelé TABLEAU

Le problème c’est que si je fais return mon_tableau dans la fonction que j’ai écris tout à l’heure ça me renvoie un pointeur et moi je peux pas ça mais je veux qu’il me renvoie un tableau multidimensionnel avec des sous tableaux de tailles différentes

En fait je veux que dans mon main il y ait ceci :

Etc
tableau t=[1,2,3,-1,4,5,6,7,8,-1,4,2,-1]
TABLEAU T=transforme(t);
afficher_tableau(T);

Et je veux que ma console me renvoie
[[1,2,3],[4,5,6,7,8],[4,2]]

A peu près c’est ça que je cherche à faire
0
[Dal] Messages postés 6198 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 13 décembre 2024 1 096
Modifié le 6 mai 2022 à 16:43
En fait vous,vous avez défini un type double pointeur sur un tableau appelé TABLEAU

Soyons précis stp. TABLEAU est un pointeur sur un pointeur sur struct. N'oublie pas que ce que tu veux appeler "tableau" avec ton typedef n'est pas de type tableau en C (array en anglais).

Le problème c’est que si je fais return mon_tableau dans la fonction que j’ai écris tout à l’heure ça me renvoie un pointeur et moi je peux pas ça mais je veux qu’il me renvoie un tableau multidimensionnel avec des sous tableaux de tailles différentes

Une fonction ne peut pas retourner un tableau en C (qu'il soit à une dimension ou deux). Tu peux, par contre, retourner un pointeur vers un emplacement d'une zone mémoire allouée permettant d'accéder à des données d'un certain type accessibles avec l'opérateur crochets
[]
ce qui semblait te convenir tout à l'heure... tu as changé d'avis ?

tableau t=[1,2,3,-1,4,5,6,7,8,-1,4,2,-1] 


ceci n'est pas du C valide et ce n'est pas le type "tableau" tel que définit dans ton code avec le typedef auquel correspond ce qui suit, mais juste un tableau d'int

int t[] = { 1, 2, 3, -1, 4, 5, 6, 7, 8, -1, 4, 2, -1 };


(pour mémoire, le typedef définit avec le nom "tableau" dans ton code est le
struct tableau
qui te permet d'imbriquer des "tableaux" à dimensions variables dans TABLEAU, il ne faut pas tout mélanger stp ... voilà, en fait une illustration du danger des typedef ... tu ne sais même plus ce que tu tapes !)

Ensuite, lorsque tu passes
t
en paramètre de la fonction
transforme()
, la fonction en question n'a aucun moyen de savoir quel est le nombre d'éléments du tableau passé. Tu dois passer cette information en paramètre, sinon elle n'est pas accessible à la fonction
transforme()
, qui reçoit juste un pointeur sur le premier élément int et perd l'information sur la taille du tableau.

par exemple, l'appel pourrait se faire comme ceci :

TABLEAU T = transforme(t, sizeof(t) / sizeof(int)); 


et le prototype de la fonction
transforme()
devrait alors être quelque chose comme :

TABLEAU transforme(int * t, size_t nb_elements);
0
[Dal] Messages postés 6198 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 13 décembre 2024 1 096 > [Dal] Messages postés 6198 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 13 décembre 2024
Modifié le 6 mai 2022 à 18:43
il y a un topic sur SO sur la question "Returning an array using C" :

https://stackoverflow.com/questions/11656532/returning-an-array-using-c

la réponse courte est "You can't return arrays from functions in C." comme je te le disais

après, si tu veux entrer dans le détail de choses, tu peux lire toutes les contributions proposant différentes solutions, sachant que retourner un pointeur vers une zone mémoire allouée dans la fonction est l'une d'elle classique et que c'est celle que tu mets en oeuvre
0
Theo_0055 Messages postés 275 Date d'inscription mardi 21 juillet 2020 Statut Membre Dernière intervention 19 janvier 2023 1
Modifié le 6 mai 2022 à 18:36
Je pense qu'il faut que je sache manipuler correctement d'abord des tableaux simples avant de faire les tableaux un peu plus compliqué

Pour les tableau simple j'ai fait ceci et ca a l'air de marcher



#include <stdio.h>
typedef struct tableau {
    int taille;
    int *tab;
}tableau;



tableau creer_tab_vide(){
    tableau t;
 t.taille = 0;
 t.tab = malloc(9* sizeof(int));
 return t;
    
    
}

tableau ajouter_entier(tableau t,int n){
    t.taille=t.taille+1;
    int dernier_indice=t.taille-1;
    
    t.tab[dernier_indice]=n;
    return t;
    
}

tableau creer_tab_vide(){
    tableau t;
 t.taille = 0;
 t.tab = malloc(9* sizeof(int));
 return t;
    
    
}

tableau ajouter_entier(tableau t,int n){
    t.taille=t.taille+1;
    int dernier_indice=t.taille-1;
    
    t.tab[dernier_indice]=n;
    return t;
    
}

int main(void){
    tableau t;
    t=creer_tab_vide();
    t=ajouter_entier(t,1);
    t=ajouter_entier(t,2);
    t=ajouter_entier(t,3);
    t=ajouter_entier(t,4);
    t=ajouter_entier(t,-1);
    t=ajouter_entier(t,6);
    t=ajouter_entier(t,7);
    t=ajouter_entier(t,8);
    t=ajouter_entier(t,-1);
    afficher_tableau(t);
   return 0;
}



Seul bémol dans creer tableau vide j'ai mis le nombre 9 car je sais que dans le main mon tableau est de taille 9
Comment faire pour connaitre d'avance le nombre d'espace qu'on doit stocker
ou sinon si on veut ajouter un entier,je veux que la taille augmente de 1 pour mettre l'entier(reservation dynamique)



Une fois que j'aurais compris le fonctionnement des tableaux simples,je pourrais revenir a mon exo et appliquer vos conseils
0
[Dal] Messages postés 6198 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 13 décembre 2024 1 096
Modifié le 6 mai 2022 à 18:59
dans creer tableau vide j'ai mis le nombre 9 car je sais que dans le main mon tableau est de taille 9
Comment faire pour connaitre d'avance le nombre d'espace qu'on doit stocker


Puisque tu disposes de cette information dans main, tu devrais la passer en paramètre de ta fonction, non ?

ou sinon si on veut ajouter un entier,je veux que la taille augmente de 1 pour mettre l'entier(reservation dynamique)

Si main ne sait pas à l'avance, cela peut se justifier.

Tu peux alors faire des realloc() en augmentant la capacité mémoire réservée lorsque tu approches de la saturation.

https://www.cplusplus.com/reference/cstdlib/realloc/

une stratégie classique est de procéder par doublements successifs de la capacité, pour limiter le nombre d'appels système générés par realloc(), plutôt que d'augmenter par unités.

Heu, juste pour mon information Theo_0055 == leoliom ou j'ai affaire à deux personnes différentes ?
0
leoliom Messages postés 171 Date d'inscription jeudi 21 juillet 2016 Statut Membre Dernière intervention 20 février 2024 2
Modifié le 6 mai 2022 à 19:31
Non c'est mon 2ieme compte que j'utilise pas beaucoup,ah j'ai écris mon message avec ce compte sans faire exprès désolé
Mon vrai compte est leoliom


Pour résoudre ce problème,j'ai modifié le code en faisant
typedef struct tableau {
    int taille;
    int *tab;
    int T_MAX;
}tableau;




tableau creer_tab_vide(){
    tableau t;
 t.taille = 0;
 t.T_MAX=10;
 t.tab = malloc(9* sizeof(int));
 return t;
    
    
}

tableau ajouter_entier(tableau t,int n){
    if( t.taille==t.T_MAX)
         t.tab=realloc(t.tab,2*sizeof(int));
    t.taille=t.taille+1;
    int dernier_indice=t.taille-1;
    
    t.tab[dernier_indice]=n;
    return t;
    
}



Mais bizarrement à un moment il y a un nombre bizarre



Ai-je mal uttilisé realloc pourtant j'ai lu le site que vous m'avez donné
0
leoliom Messages postés 171 Date d'inscription jeudi 21 juillet 2016 Statut Membre Dernière intervention 20 février 2024 2
6 mai 2022 à 19:42
finalement c'est bon probleme résolu j'ai modifié
t.tab=realloc(t.tab,2*t.T_MAX*sizeof(int));
0
leoliom Messages postés 171 Date d'inscription jeudi 21 juillet 2016 Statut Membre Dernière intervention 20 février 2024 2
6 mai 2022 à 19:44
Maintenant je vais essayer d'appliquer le même principe sur tableaux avec des sous_tableau et je reviens plus tard

Aussi esceque la methode de réallocation que j'ai utilisé est compliqué,y avait il plus simple?
0
[Dal] Messages postés 6198 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 13 décembre 2024 1 096
6 mai 2022 à 23:55
tu dois mettre à jour T_MAX avec la nouvelle valeur.

le realloc() doit se faire avec un pointeur intermédiaire, au cas où realloc() échoue faute de mémoire (vois la doc dont j'ai posté le lien et l'exemple de celle ci).
0