Les membres ayant 30 points peuvent parler sur les canaux annonces, projets et hs du chat.

Forum Casio - Vos tutoriels et astuces


Index du Forum » Vos tutoriels et astuces » [C] Envoyer des tableaux multidimensionnels à des fonctions
Dark storm Hors ligne Labélisateur Points: 11538 Défis: 176 Message

[C] Envoyer des tableaux multidimensionnels à des fonctions

Posté le 18/08/2014 11:53

Qui n'as jamais eu besoin d'envoyer des tableaux multidimensionnels à des fonctions pour pouvoir les modifier ? Malheureusement, il n'est pas possible d'envoyer un pointeur sur ce tableau puis d'y accéder comme ceci : mon_tableau[y][x]. Toutefois, des astuces existent, je vais vous en présenter quelques unes ici, à vous de faire votre choix.

Prérequis : avoir une bonne connaissance des pointeurs et des structures.


Méthode 1 : accès direct

Un tableau à 2 dimensions n'est rien d'autre qu'un regroupement d'un certain nombre (nombre de lignes) de tableaux 1D qui se suivent dans la mémoire. De la même manière, les tableaux 3D sont des regroupements de tableaux 2D, et donc de manière générale un tableau nD est un regroupement de tableaux (n-1)D. On peut alors acceder manuellement à une case en multipliant chaque indice par le nombre de case de sa dimension.
Exemple : je veux créer une fonction qui initialise un tableau de dimensions dim_x et dim_y en matrice diagonale (des 1 dans la diagonale, 0 ailleurs). >>> Accéder au code <<<

Avantages :
- Le tableau peut être de taille variable, il suffit d'envoyer les dimensions à la fonction, celle-ci s'adapte automatiquement.
Inconvénients :
- Le nombre de dimensions ne peut pas être variable.
- Plus il y a de dimensions, plus la déclaration de la fonction est lourde. On peut toutefois utiliser un tableau 1D contenant les dimensions du tableau.
- Le code d'accès aux cases du tableau peut vite devenir incompréhensible.


Méthode 2 : accès par pointeur sur structure

Une autre méthode consiste à créer une structure contenant un tableau puis à envoyer un pointeur sur cette structure aux fonctions en ayant besoin. Les dimensions du tableau étant contenues dans la déclaration de la structure, on peut alors y accéder facilement.
Exemple de la matrice diagonale avec cette méthode : >>> Accéder au code <<<

Avantages :
- La lisibilité du code n'est que peut perturbée (il ne faut que penser à accéder au tableau dans la structure avec l'opérateur –>)
- On peut ajouter des informations dans la structure "Tableau" : un nom, etc., l'accès aux données ne changera pas.
- Un seul argument suffit pour passer le tableau.
Inconvénients :
- Les dimensions du tableaux ne sont pas variables. Pour créer des tableaux de dimensions différentes, il faut plusieurs structures différentes.
- On ne peut se passer de l'opérateur –> pour accéder aux données du tableau.


Méthode 3 : accès par pointeur sur union.

Cette dernière méthode, qui utilise les unions, permet de palier à certains désavantages de la méthode 2. On créé une union "Tableau" dans laquelle on défini tout les types de tableaux que l'on va utiliser. On peut alors créer des tableaux de tailles diverses et y accéder comme avec les structures. Exemple : >>> Accéder au code <<<

Avantages :
- La lisibilité du code n'est que peut perturbée (il ne faut que penser à accéder au tableau dans la structure avec l'opérateur –>)
- On peut utiliser beaucoup de types différents de tableaux.
- Deux arguments suffisent pour passer le tableau et son type de données.
Inconvénients :
- L'union fait le poids du tableau le plus lourd, et ce quel que soit le type utilisé.
- On ne peut se passer de l'opérateur –> pour accéder aux données du tableau.


Je pense avoir fait le tour, si vous avez d'autres techniques, faites m'en part, je me ferais un plaisir de les ajouter ici. De même, n'hésitez pas à signaler d'éventuelles erreurs.

A bientôt sur Planète Casio !


Lephenixnoir Hors ligne Administrateur Points: 20789 Défis: 143 Message

Citer : Posté le 18/08/2014 11:57 | #


Bon, ça, c'est fait.
Peut-être que ça pourra nous éviter quelques problèmes...
Smashmaster Hors ligne Ancien modérateur Points: 4561 Défis: 253 Message

Citer : Posté le 18/08/2014 12:57 | #


πEn allouant dynamiquement un tableau à deux dimensions, on peut l'envoyer à une fonction sans problème.

Une petite class que j'avais programmé (en C++, il y a très peu de méthode, libre à vous d'en rajouter):


template <class T>
class Matrix
/** class permettant de définir un tableau à deux dimensions **/
{
    private :
        unsigned int _h;
        unsigned int _l;
        T** _t;
    public :

        Matrix(){
            _h = 0;
            _l = 0;
            _t = NULL;
        }


        
        Matrix( unsigned int h, unsigned int l ) {
            _t = (T**) malloc ( sizeof (T*) * h) ;
            for (unsigned int i = 0 ; i < l ; i++)
                _t[i] = (T*) malloc ( sizeof (T) * l ) ;

            _h = h;
            _l = l;
        }


        virtual ~Matrix(){
            this->free();
        }

        unsigned int get_h() const{
            return _h;
        }


        unsigned int get_l() const{
            return _l;
        }


        void free() {
            for (unsigned int i = 0 ; i < _h ; i++)
                free(_t[i]);
            free(_t);
            _h = 0;
            _l = 0;
        }


        void init(T obj){
            for (unsigned int i = 0 ; i < _h ; i++)
                for (unsigned int j = 0 ; j < _l ; j++)
                    _t[i][j] = obj;
        }


        T* operator[] (int i) {
            return _t[i];
        }
};


Exemple d'utilisation :

Matrix <int> tableau(5,5); //On créé un tableau de taille 5*5
tableau[2][1] = 2;


La même chose en C

int** Matrix_new( int h, int l)
{
    int** tab = NULL;
    tab = (int**) malloc ( sizeof (int*) * h) ;
    for (int i = 0 ; i < l ; i++)
        tab[i] = (int*) malloc ( sizeof (int) * l );
    return tab;
}

void Matrix_free(int** tab, int h, int l) {
    for (int i = 0 ; i < h ; i++)
        free(tab[i]);
    free(tab);
}


void Matrix_init(int** tab, int h, int l, int val){
    for (int i = 0 ; i < h ; i++)
        for (int j = 0 ; j < l ; j++)
            tab[i][j] = val;
}


L'utilisation est différent :


int**tab = Matrix_new(10,10);

tab[9][9] = 5;
  
Matrix_free(tab,10,10);


Etant donné que les templates n'existent pas en C, on est obligé de modifier les fonction si on veut que la fonction Matrix_new() retourne un long** ou un struct t** par exemple.
Lephenixnoir Hors ligne Administrateur Points: 20789 Défis: 143 Message

Citer : Posté le 18/08/2014 13:41 | #


Oui mais là c'est un vrai tableau de pointeurs, alors que dans le cas habituel c'est juste un unique bloc de donnees.

LienAjouter une imageAjouter une vidéoAjouter un lien vers un profilAjouter du codeCiterAjouter un spoiler(texte affichable/masquable par un clic)Ajouter une barre de progressionItaliqueGrasSoulignéAfficher du texte barréCentréJustifiéPlus petitPlus grandPlus de smileys !
Cliquez pour épingler Cliquez pour détacher Cliquez pour fermer
Alignement de l'image: Redimensionnement de l'image (en pixel):
Afficher la liste des membres
:bow: :cool: :good: :love: ^^
:omg: :fusil: :aie: :argh: :mdr:
:boulet2: :thx: :champ: :whistle: :bounce:
valider
 :)  ;)  :D  :p
 :lol:  8)  :(  :@
 0_0  :oops:  :grr:  :E
 :O  :sry:  :mmm:  :waza:
 :'(  :here:  ^^  >:)

Σ π θ ± α β γ δ Δ σ λ
Veuillez donner la réponse en chiffre
Vous devez activer le Javascript dans votre navigateur pour pouvoir valider ce formulaire.

Si vous n'avez pas volontairement désactivé cette fonctionnalité de votre navigateur, il s'agit probablement d'un bug : contactez l'équipe de Planète Casio.

Planète Casio v42 © créé par Neuronix et Muelsaco 2004 - 2021 | Il y a 57 connectés | Nous contacter | Qui sommes-nous ? | Licences et remerciements

Planète Casio est un site communautaire non affilié à Casio. Toute reproduction de Planète Casio, même partielle, est interdite.
Les programmes et autres publications présentes sur Planète Casio restent la propriété de leurs auteurs et peuvent être soumis à des licences ou copyrights.
CASIO est une marque déposée par CASIO Computer Co., Ltd