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 :

[C] comment retourner un tab a 2 dim dans une fonction?


Sujet :

C

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    2
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 2
    Points : 2
    Points
    2
    Par défaut [C] comment retourner un tab a 2 dim dans une fonction?
    Bonsoir,

    J'ai un petit probleme en C je voudrais retourné un tableau a 2 dimensions en apellant par exemple cette fonction:
    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
     
    void genMat (int n, int k){
    	int i, j, nbrli, m;
    	nbrli=(n/k);
    	int tabGenMat[nbrli][n];
     
    	for (i=0;i<nbrli;i++){
    		for (j=0;j<n;j++)
    		{
    			tabGenMat[i][j]=0;
    		}
    	}
     
    	for(i=0;i<nbrli;i++){
    		for(j=0;j<n;j++){
    			m=(j+1) +k*i;
    			if (m<=k*(i+1)){
    				tabGenMat[i][m-1]=1;
    			}
    		}
    	}
     
    	for (i=0;i<nbrli;i++){
    		for (j=0;j<n;j++){
    			printf ("%d ", tabGenMat[i][j]);
    		}
    		printf("\n");
    	}
     
    }
    Bien sur avec le main qui va avec, il n'y a pas de probleme..
    Mais je voudrais bien utiliser cette meme fonction dans une autre or dans mon cas ce que je fais c'est seulement afficher le tableau tabGenMat obtenu..

    Please aidez moi.. merci d'avance..;p

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

    Informations forums :
    Inscription : Décembre 2004
    Messages : 2 210
    Points : 3 015
    Points
    3 015
    Par défaut
    je voudrais retourné un tableau a 2 dimensions en apellant par exemple cette fonction:
    Le C n'a jamais été mon fort (et c'est lointain), mais tu dois utiliser des pointeurs ( pfiou ça fait froid dans le dos de parler de pointeur)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void MaFonction(int **tabGenMat, int i, int j)
    {
      // tu joues avec tabGenMat ici
    }
    Dans le main, tu fais un truc du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int main(void)
    {
            int i,j;
            double F[i][j];
     
            MaFonction(F,i,j);
    }
    Bien sûr c'est à confirmer hein ... moi je peux pas t'en dire plus (et puis j'ai dépassé mon quota de C pour l'année )

  3. #3
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par binoo Voir le message
    Le C n'a jamais été mon fort<...>
    Bien sûr c'est à confirmer hein ... moi je peux pas t'en dire plus (et puis j'ai dépassé mon quota de C pour l'année )
    Ce code est malheureusement incorrect. Le type de double F[i][j]; n'est pas int **tabGenMat, ni même double **tabGenMat
    Pas de Wi-Fi à la maison : CPL

  4. #4
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par memo67 Voir le message
    Bonsoir,

    J'ai un petit probleme en C je voudrais retourné un tableau a 2 dimensions en apellant par exemple cette fonction:
    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
     
    void genMat (int n, int k){
    	int i, j, nbrli, m;
    	nbrli=(n/k);
    	int tabGenMat[nbrli][n];
     
    	for (i=0;i<nbrli;i++){
    		for (j=0;j<n;j++)
    		{
    			tabGenMat[i][j]=0;
    		}
    	}
     
    	for(i=0;i<nbrli;i++){
    		for(j=0;j<n;j++){
    			m=(j+1) +k*i;
    			if (m<=k*(i+1)){
    				tabGenMat[i][m-1]=1;
    			}
    		}
    	}
     
    	for (i=0;i<nbrli;i++){
    		for (j=0;j<n;j++){
    			printf ("%d ", tabGenMat[i][j]);
    		}
    		printf("\n");
    	}
     
    }
    Bien sur avec le main qui va avec, il n'y a pas de probleme..
    Mais je voudrais bien utiliser cette meme fonction dans une autre or dans mon cas ce que je fais c'est seulement afficher le tableau tabGenMat obtenu..

    Please aidez moi.. merci d'avance..;p
    Il n'est pas possible de retourner l'adresse d'une variable locale. De plus, tu utilises la technique du VLA qui n'existe qu'en C99, et qui n'est pas implémentée corectement partout (avec gcc, cette possibilité est 'broken').

    Il faut utiliser l'allocation dynamique et retourner l'adresse du tableau de base (T**). Mais il faut aussi les dimensions. Je recommande donc de définir une structure qui contient les éléments utiles à la définition du tableau 2D :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    struct tab2D
    {
       T **tab;
        size_t nb_lin;
        size_t nb_col;
    };
    On peut définir une telle structure, l'initaliser à 0 dans la fonction appelante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    {
       struct tab2D tab = {NULL, 0, 0};
    Puis passer son adresse à la fonction :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    {
       ...
       fonction (&tab);
    Ensuite, l'allocation dynamique se fait dans la fonction selon ce principe :

    http://emmanuel-delahaye.developpez.....htm#tabdyn_2d

    Voir aussi :

    http://emmanuel-delahaye.developpez.com/tad.htm

    l'exemple correspond exactement à ce que tu veux...
    Pas de Wi-Fi à la maison : CPL

  5. #5
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Mars 2008
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2008
    Messages : 15
    Points : 23
    Points
    23
    Par défaut
    Le plus simple, déclarer un pointeur sur tableau à 2D dans ta fonction
    double** T;

    Lui allouer la mémoire par un malloc (le tableau sera conservé après la fermeture de la fonction)
    T = malloc(heuteur*largeur*taille d'une case)

    Et en fin de fonction tu retournes T.
    A noter que ta fonction doit être déclarée comme double**
    ___

    Nicolas Morey-Chaisemartin
    http://nicolas.morey-chaisemartin.com

  6. #6
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par Darkfang Voir le message
    Le plus simple, déclarer un pointeur sur tableau à 2D dans ta fonction
    double** T;
    OK
    Lui allouer la mémoire par un malloc (le tableau sera conservé après la fermeture de la fonction)
    T = malloc(heuteur*largeur)
    Non, ça, c'est faux.

    La méthode a déjà été expliquée. Je redonne le lien :

    http://emmanuel-delahaye.developpez.....htm#tabdyn_2d
    Pas de Wi-Fi à la maison : CPL

  7. #7
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Mars 2008
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2008
    Messages : 15
    Points : 23
    Points
    23
    Par défaut
    Effectivement j'ai oublié de préciser que l'accès se fait aps de la même manière.
    Pour y acceder avec la formule normale Tab[i][j] mon allocation ne marche pas.

    Avec mon allocation, on accede en faisant Tab[i*largeur+j] ce qui peut se faire facilement avec une macro histoire d'avoir un accès ressemblant (du genre Tab(i)(j) )

    L'avantage de cette méthode:
    - Moins de mémoire consommée. On a hauteur*largeur*taille d'une case. Alors que l'autre méthode donne la meme chose + hauteur*taille d'un pointeur.
    - Potentiellement plus rapide. Du fait que l'alloc soit fait en un coup, le tableau est contigu en mémoire et globalement ca simplifie la vie au cache
    - Gain de temps pour l'alloc/libération. Le tout se fait en une alloc et un free au lieu de hauteur+1
    ______
    Nicolas Morey-Chaisemartin
    http://nicolas.morey-chaisemartin.com

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    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.

  9. #9
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par Darkfang Voir le message
    Effectivement j'ai oublié de préciser que l'accès se fait aps de la même manière.
    Pas seulement ça. Le type est faux. C'est pas T**a, mais T*a (tableau 1D linéaire à accès en 2 dimensions calculées).
    Pas de Wi-Fi à la maison : CPL

  10. #10
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Points : 8 389
    Points
    8 389
    Par défaut
    Citation Envoyé par Emmanuel Delahaye
    Il n'est pas possible de retourner l'adresse d'une variable locale
    Sauf si la variable locale est statique . Mais une variable locale statique c'est pas vraiment une variable locale ... .

  11. #11
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par Melem Voir le message
    Sauf si la variable locale est statique . Mais une variable locale statique c'est pas vraiment une variable locale ... .
    Mmmm, oui, il y a un problème de terminologie...

    Il faut distinguer les variables automatiques et les variables statiques de portées locales

    J 'aurais du dire "Il n'est pas possible de retourner l'adresse d'une variable automatique".

    Et encore, techniquement, c'est possible, simplement, l'usage de cette adresse (déréférencement) implique un comportement indéterminé.

    Ca devient :

    "Bien qu'il soit techniquement possible de retourner l'adresse d'une variable automatique, le déréférencement de celle-ci entraine un comportement indéterminé"

    Amen.
    Pas de Wi-Fi à la maison : CPL

  12. #12
    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 : 47
    Localisation : Suisse

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

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Points : 5 360
    Points
    5 360
    Par défaut
    Personnellement, la méthode publiée par Médinoc est celle que j'utilise pour la représentation des tableaux à dimensions. Cette méthode a, selon moi, l'avantage de simplifier la libération de la mémoire et la gestion des erreurs, tout en permettant un accès "classique" aux différentes de la matrice. Pour les tenseurs et autres tableaux de dimension supérieure, il est intéressant de fabriquer un type abstrait de donnée (TAD) avec une seule allocation à la manière de Darkfang. Voici un exemple d'un tel TAD (ici pour une matrice):

    Fichier d'en-tête mat.h
    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
    #ifndef H_TC_MAT_20080325095622
    #define H_TC_MAT_20080325095622
     
    #ifdef __cplusplus
    extern "C" {
    #endif
     
    enum
    {
        MAT_OK,
        MAT_ARGUMENT_ERR,
        MAT_ALLOCATION_ERR,
        MAT_OUT_OF_BOUNDS_ERR,
        MAT_NB
    };
     
    typedef struct Mat_ Mat_s;
     
    int mat_new(Mat_s **p_self, size_t n, size_t m);
    int mat_get(Mat_s *self, size_t i, size_t j, double *value_out);
    int mat_set(Mat_s *self, size_t i, size_t j, double value);
    int mat_display(Mat_s *self);
    int mat_delete(Mat_s **p_self);
     
    #ifdef __cplusplus
    }
    #endif
     
    #endif /* guard H_TC_MAT_20080325095622 */
    Fichier d'implantation mat.c
    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
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    #include <stdio.h>
    #include <stdlib.h>
    #include "mat.h"
     
    struct Mat_
    {
        double *data;
        size_t n; /* -tc- number of lines*/
        size_t m; /* -tc- number of columns */
    };
     
    int mat_new(Mat_s **p_self, size_t n, size_t m)
    {
        int err = MAT_OK;
     
        if (p_self != NULL && n > 0 && m > 0)
        {
            Mat_s *p = NULL;
     
            p = malloc(sizeof *p);
            if (p != NULL)
            {
                /* -tc- initializes all fields to zero */
                static Mat_s const tmp = {0};
                *p = tmp;
     
                p->data = malloc(n * m * sizeof *p->data);
                if (p->data != NULL)
                {
                    size_t i;
     
                    /* -tc- initialization of the array */
                    for (i = 0; i < n * m; i++)
                    {
                        p->data[i] = 0.0;
                    }
                    p->n = n;
                    p->m = m;
     
                    *p_self = p;
                }
                else
                {
                    /* -tc- Error: allocation failed */
                    err = MAT_ALLOCATION_ERR;
                    /* -tc- clean up */
                    free(p), p = NULL;
                }
            }
            else
            {
                /* -tc- Error: allocation failed */
                err = MAT_ALLOCATION_ERR;
            }
        }
        else
        {
            /* -tc- Error: bad argument */
            err = MAT_ARGUMENT_ERR;
        }
     
        return err;
    }
     
    int mat_get(Mat_s *self, size_t i, size_t j, double *value_out)
    {
        int err = MAT_OK;
     
        if (self != NULL && value_out != NULL)
        {
            if (i < self->n && j < self->m)
            {
                *value_out = self->data[i * self->m + j];
            }
            else
            {
                /* -tc- Error: out of bounds access */
                err = MAT_OUT_OF_BOUNDS_ERR;
            }
        }
        else
        {
            /* -tc- Error: bad argument */
            err = MAT_ARGUMENT_ERR;
        }
     
        return err;
    }
     
    int mat_set(Mat_s *self, size_t i, size_t j, double value)
    {
        int err = MAT_OK;
     
        if (self != NULL)
        {
            if (i < self->n && j < self->m)
            {
                self->data[i * self->m + j] = value;
            }
            else
            {
                /* -tc- Error: out of bounds access */
                err = MAT_OUT_OF_BOUNDS_ERR;
            }
        }
        else
        {
            /* -tc- Error: bad argument */
            err = MAT_ARGUMENT_ERR;
        }
     
        return err;
    }
     
    int mat_display(Mat_s *self)
    {
        int err = MAT_OK;
     
        if (self != NULL)
        {
            size_t i, j;
     
            for (i = 0; i < self->n; i++)
            {
                for (j = 0; j < self->m; j++)
                {
                    printf("%6.2f ", self->data[i * self->m + j]);
                }
                printf("\n");
            }
        }
     
        return err;
    }
     
    int mat_delete(Mat_s **p_self)
    {
        int err = MAT_OK;
     
        if (p_self != NULL && *p_self != NULL)
        {
            free((*p_self)->data);
            free(*p_self), *p_self = NULL;
        }
     
        return err;
    }
    Un exemple d'utilisation
    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
    #include <stdlib.h>
    #include "mat.h"
     
    #define N_LINES 3
    #define N_COLS 4
     
    /* -tc- test */
    int main(void)
    {
        int ret = EXIT_SUCCESS;
        Mat_s *matrix = NULL;
     
        if (mat_new(&matrix, N_LINES, N_COLS) == MAT_OK)
        {
            size_t i, j;
     
            for (i = 0; i < N_LINES; i++)
            {
                for (j = 0; j < N_COLS; j++)
                {
                    mat_set(matrix, i, j, i * N_COLS + j);
                }
            }
     
            mat_display(matrix);
            mat_delete(&matrix);
        }
        else
        {
            /* -tc- Erreur: Allocation de memoire impossible */
            ret = EXIT_FAILURE;
        }
     
        return ret;
    }
    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++

    +

Discussions similaires

  1. [XL-2010] Comment prendre en compte un tableau (Array) dans une fonction vba?
    Par statista dans le forum Macros et VBA Excel
    Réponses: 5
    Dernier message: 07/04/2011, 15h16
  2. Réponses: 4
    Dernier message: 15/08/2007, 22h05
  3. Réponses: 13
    Dernier message: 08/03/2007, 14h53
  4. Réponses: 12
    Dernier message: 22/11/2005, 13h17
  5. Réponses: 10
    Dernier message: 19/09/2005, 22h24

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