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 :

Tab2d et pointeur


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Développeur Java
    Inscrit en
    Mars 2014
    Messages
    85
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Mars 2014
    Messages : 85
    Par défaut Tab2d et pointeur
    Bonjour à tous,

    Après une soirée de recherche je me décide à faire appel à votre aide, je ne capte pas quelque chose pour faire passer un tableau 2d dans un fonction, je pense que j'ai bien capté le principe des pointeurs mais je ne trouve pas pour le tableau 2D.

    Voici un petit truc rapide pour illustrer ma difficulté, je cherche à faire passer dans une fonction un tableau 2d et simplement faire le double des valeurs dans ce tableau.
    Bon on a pas vraiment d'utiliser les pointeurs pour faire ça mais je cherche à le faire avec pointeurs pour bien comprendre la base.

    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
    void doubleTab(int *pTab[2][2])
    {
        int i, j;
        for (i=0; i<4; i++) {
            for (j=0; j<4; j++) {
                *pTab[i][j] *= 2;
            }
        }
    }
     
    void affichageTab(int pTab[2][2])
    {
        int i, j;
        for (i=0; i<4; i++) {
            for (j=0; j<4; j++) {
                printf("%d", pTab[i][j]);
            }
        }
    }
     
    int main(int argc, const char * argv[]) {
     
        int tTab[2][2] = {{0,1},{2,3}};
        int (*pTab)[2][2] = &tTab;
     
        doubleTab((*pTab)[2][2]);
        affichageTab(pTab[2][2]);
     
    }
    Ce n'est qu'une version car j'ai essayé pas mal d'écriture sans vraiment capter ce qu'il ne va pas


    Merci d'avance pour votre aide
    Ersch

  2. #2
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 480
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 480
    Par défaut
    Bonjour,

    • Dans tes fonctions, tes indices i et j parcourent chacune quatre positions alors que les dimensions de tes tableaux n'en comptent que deux ;
    • Dans la fonction doubleTab(), tu fais croire à ta fonction que tu lui passe un tableau [2][2] de « pointeurs sur des entiers » alors que ce n'est pas du tout le cas (il ne contient que les entiers eux-mêmes). Il aurait au minimum fallu ajouter les parenthèses comme pour la déclaration de pTab dans main.
    • En indexant le tableau et en le déréférençant avec « * », tu fais croire au compilateur que les éléments du tableau (les valeurs 0, 1, 2 et 3) sont les adresses en mémoire de ce que tu veux modifier. Tu sors de ton espace d'adressage et tu déclenches une segfault ;
    • Enfin, lorsque tu appelles tes fonctions, il ne faut pas re-spécifier les « [2][2] » après tes identifiants, sinon c'est l'élément se trouvant à cette position qui sera passé, et pas le tableau lui-même (ou plus précisément son adresse, ou bien la valeur de pTab), donc l'objet transmis à ta fonction n'aura rien à voir avec ce que tu penses lui passer ;
    • Comme les dimensions de ton tableau sont justement « [2][2] », les dimensions ne courent que de 0 à 1 et la case indexée sera en dehors de ton tableau. Tu risqueras à nouveau la segfault, même si c'est peu probable étant donné la faible excursion. Par contre la valeur extraite sera totalement indéfinie.

  3. #3
    Membre confirmé
    Homme Profil pro
    Développeur Java
    Inscrit en
    Mars 2014
    Messages
    85
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Mars 2014
    Messages : 85
    Par défaut
    Bonjour et merci pour ton aide,

    voici une version corrigé en fonction de tes remarques

    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
     
    void doubleTab(int (*pTab)[2][2])
    {
        int i, j;
        for (i=0; i<2; i++) {
            for (j=0; j<2; j++) {
                (*pTab)[i][j] *= 2;
            }
        }
    }
     
    void affichageTab(int pTab[2][2])
    {
        int i, j;
        for (i=0; i<2; i++) {
            for (j=0; j<2; j++) {
                printf("%d", pTab[i][j]);
            }
        }
    }
     
    int main(int argc, const char * argv[]) {
     
        int tTab[2][2] = {{0,1},{2,3}};
        int (*pTab)[2][2] = &tTab;
     
        doubleTab(pTab);
        affichageTab(*pTab);
    }
    J'ai cependant des points ou ce n'est pas clair

    Dans la fonction doubleTab(), tu fais croire à ta fonction que tu lui passe un tableau [2][2] de « pointeurs sur des entiers » alors que ce n'est pas du tout le cas (il ne contient que les entiers eux-mêmes). Il aurait au minimum fallu ajouter les parenthèses comme pour la déclaration de pTab dans main.
    J'ai compris pourquoi mettre les parenthèses sur (*pTab) mais tu dis qu'il aurait fallu au minimum ajouter les ajouter. Pourquoi au minimum, est ce qu'il y a une façon "plus propre" au niveau de l'écriture?

    Enfin, lorsque tu appelles tes fonctions, il ne faut pas re-spécifier les « [2][2] » après tes identifiants, sinon c'est l'élément se trouvant à cette position qui sera passé, et pas le tableau lui-même (ou plus précisément son adresse, ou bien la valeur de pTab), donc l'objet transmis à ta fonction n'aura rien à voir avec ce que tu penses lui passer ;
    Imaginons mon exercice, au lieu d'avoir des valeurs fixes, je passe par une fonction lecture ou je rentre les valeurs avant de faire doubleTab, quid de comment j'appelle ma fonction? En fait on m'a expliqué en classe quelque chose à propos des indices mais ce n'est plus très clair. De souvenir le second indice n'était pas obligatoire mais il permettait de préciser l'indice par après (pas très clair je te l'accorde) l'écriture donc ressemblerait à pTab[][indice]

    Merci encore pour ton aide

  4. #4
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 833
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 833
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Ersch Voir le message
    J'ai compris pourquoi mettre les parenthèses sur (*pTab) mais tu dis qu'il aurait fallu au minimum ajouter les ajouter. Pourquoi au minimum, est ce qu'il y a une façon "plus propre" au niveau de l'écriture?
    Bonjour

    Non, pas d'autre façon. Obsidian a (probablement) écrit "au minimum" dans un effet de style et non comme sous-entendu qu'il y avait une autre façon.

    Ou alors si, il y en avait bien une mais c'est en n'utilisant pas l'adresse du tableau mais le tableau lui-même

    Code c : 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
    void doubleTab(int Tab[2][2])
    {
        int i, j;
        for (i=0; i<2; i++) {
            for (j=0; j<2; j++) {
                Tab[i][j] *= 2;
            }
        }
    }
     
    void affichageTab(int Tab[2][2])
    {
        int i, j;
        for (i=0; i<2; i++) {
            for (j=0; j<2; j++) {
                printf("%d", Tab[i][j]);
            }
        }
    }
     
    int main(int argc, const char * argv[]) {
     
        int tTab[2][2] = {{0,1},{2,3}};
     
        doubleTab(tTab);
        affichageTab(tTab);
    }
    Après-tout, ce que tu veux modifier c'est le contenu du tableau et non le tableau (qui restera un tableau de [2][2]). Donc inutile de passer l'adresse du tableau à ta fonction, le nom du tableau en lui-même suffit car ce nom correspond à l'adresse de son premier élément et comme les éléments se suivent, une fois qu'on a le premier on a alors tous les autres...

    Citation Envoyé par Ersch Voir le message
    Imaginons mon exercice, au lieu d'avoir des valeurs fixes, je passe par une fonction lecture ou je rentre les valeurs avant de faire doubleTab, quid de comment j'appelle ma fonction?
    Pareil. Ta fonction ne fait rien d'autre qu'écrire des valeurs dans le tableau reçu, et ce serait la même chose si les valeurs étaient saisies au clavier au lieu d'êtres prises dans celles déjà présentes dans le tableau.

    Citation Envoyé par Ersch Voir le message
    En fait on m'a expliqué en classe quelque chose à propos des indices mais ce n'est plus très clair. De souvenir le second indice n'était pas obligatoire mais il permettait de préciser l'indice par après (pas très clair je te l'accorde) l'écriture donc ressemblerait à pTab[][indice]
    Exact. Dans les tableaux à "n" dimensions, la valeur de la dernière dimension n'est pas utile et peut alors être omise ("dernière" prise dans le sens mathématique "de la droite vers la gauche").

    En fait, il faut bien comprendre qu'au niveau de la mémoire, il n'y a qu'une seule dimension. C'est une longue suite de cases qui se suivent.
    Prends par exemple un jeu d'échecs 8x8 où chaque case serait numérotée de 1 (A1) jusqu'à 64 (H8). Comment calculer la valeur de la case par exemple C5 ? Hé bien c'est la 5° ligne, chaque ligne faisant 8 colonnes donc ce sera déjà 5*8. Puis c'est la colonne C donc la 3° donc ce sera 5*8+3=43. Et dans ce calcul, le nombre de lignes "8" n'intervient absolument pas.

    Hé bien c'est pareil en C. Dans un tableau par exemple à 2 dimensions comme int tab[5][20], une case référencée [x][y] sera alors convertie en case indicée [z] et ce z est calculé à partir de x, de y et de la première dimension "20" sous la formule z=x*20+y. Et dans cette formule, la valeur "5" n'intervient pas et peut donc être oubliée. Et c'est pareil avec 3, 4, n dimensions.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  5. #5
    Membre confirmé
    Homme Profil pro
    Développeur Java
    Inscrit en
    Mars 2014
    Messages
    85
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Mars 2014
    Messages : 85
    Par défaut
    Un grand merci pour votre aide

    Ersch

  6. #6
    Membre confirmé
    Homme Profil pro
    Développeur Java
    Inscrit en
    Mars 2014
    Messages
    85
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Mars 2014
    Messages : 85
    Par défaut
    Je sollicite encore votre aide car il semble que ce n'est pas encore clair.

    Je veux encoder dans un tableau tTab[][3] une série de jours/mois/années mais pas moyen de trouver ce qui ne va pas dans mon code.

    Dans mon main:

    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
    #include "stdafx.h"
    #include "fonctions.h"
    #define dMaxDate 5
     
     
    int _tmain(int argc, _TCHAR* argv[])
    {
    	int tDate[dMaxDate][3] = { 0 };
    	char tDateConvert[dMaxDate][16];
    	int dNbrLues = 0;
    	int (*pDate)[dMaxDate][3] = &tDate;
     
    	ecLectDates(pDate, dMaxDate, &dNbrLues);
     
    	return 0;
    }
    fichier fonctions.h

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void ecLectDates(int (*pDate)[][3], int dMaxDate, int *pNbrLues);
    fichier fonctions.cpp

    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
    #include "stdafx.h"
    #include "fonctions.h"
     
    #define MSG_1   11
    #define MSG_2   12
    #define MSG_3   13
    #define jour    0
    #define mois    1
    #define annee   2
     
    void ecLectDates(int (*pDate)[][3], int dMaxDate, int *pNbrLues)
    {
    	do
    	{
    		/* encodage jour */
    		affichageMessage(MSG_1);
     
    		//scanf("%d", &dValeur);
    		scanf("%d", (*pDate)[*pNbrLues][jour]);
     
    		/* encodage mois */
    		affichageMessage(MSG_2);
    		scanf("%d", (*pDate)[*pNbrLues][mois]);
     
    		/* encodage annee */
    		affichageMessage(MSG_3);
    		scanf("%d", (*pDate)[*pNbrLues][annee]);
     
    		(*pNbrLues)++;
    	} while (*pNbrLues < dMaxDate);
    }

    Lorsque je compile ce code, le compliquer me dit:

    Erreur 1 error C2664: 'void ecLectDates(int (*)[][3],int,int *)'*: impossible de convertir l'argument 1 de 'int [5][3]' en 'int (*)[][3]' \\vmware-host\shared folders\drive\langage procédurale\prj24_visual\prj24_visual\prj24_visual.cpp 20 1 PRj24_visual
    J'avoue que je pensais avoir compris avec mon exemple et je ne vois pas trop la différence entre mon example et mon problème ici.

    Merci d'avance pour votre aide.

    Ersch

Discussions similaires

  1. pointeurs
    Par ghost74 dans le forum C
    Réponses: 3
    Dernier message: 14/12/2002, 02h52
  2. Pointeur vers un tableau
    Par Nikos dans le forum C
    Réponses: 3
    Dernier message: 09/12/2002, 00h43
  3. [Turbo Pascal] Allocation et désallocation de pointeurs dans une fonction
    Par neird dans le forum Turbo Pascal
    Réponses: 13
    Dernier message: 17/11/2002, 20h14
  4. djgpp et pointeurs far -2
    Par elvivo dans le forum Autres éditeurs
    Réponses: 16
    Dernier message: 29/07/2002, 22h43
  5. djgpp et pointeurs far
    Par elvivo dans le forum C
    Réponses: 2
    Dernier message: 13/07/2002, 00h44

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