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 :

Problème de pointeur, fonction et tab (encore!)


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Nouveau membre du Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Avril 2015
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2015
    Messages : 5
    Par défaut Problème de pointeur, fonction et tab (encore!)
    Bonsoir à tous,

    j'ai déja posté il y a de ça, deux semaines environ sur un exo qui me posait probleme à cause des pointeurs.
    Aujourd'hui je reviens. Je bug au niveau des pointeurs à chaque fois que j'en utilise j'ai trop d'erreur que je n'arrive pas à corriger. En plus de ça se mélange les tableaux et du coup je modifie pleins de trucs pour voir si ça change quelque chose ce qui fait que je ne sais plus trop ou j'en suis.

    Alors voilà mon énoncé :

    Ecrire une fonction C de nom mixageTableaux permettant de mixer (voir définition plus loin) deux tableaux d'entiers ayant la même taille et de mettre le resultat dans un autre tableau. On supposera que le tableau contenant le résultat a une taille suffisante.
    Définition du "mixage" de deux tableaux :
    La première case du tableau 1 va dans la premère case du tableau résultat, la première
    case du tableau 2 va dans la deuxième case du tableau résultat.
    Puis, la deuxième case du tableau 1 va dans la troisième case du tableau résultat, la deuxième case du tableau 2 va dans la quatrième case du tableau résultat.
    Etc...
    Exemple : soient T1={1,2,3,4,5} et T2= {6,7,8,9,10}
    après "mixage" de T1 et T2, on obtient dans un autre tableau TR={1,6,2,7,3,8,4,9,5,10}
    alors je vous montre ci dessous mon programme, je sais pas si il execute correctement l'énoncé mais c'est surtout les probleme de pointeurs et de tableaux que j'aimerai comprendre. La suite je corrigerai en voyant le résultat. Si quelqu'un pouvait m'expliquer mes erreurs

    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
    #include <stdio.h>
     
    void mixageTableaux(int t1[], int t2[], int *t3[])
    {
     
     int i, size=10 ; 
     
     for (i=0; i<size; i=i+1)
     
     { if (i%2 == 0 && i-1<=size && i!=0) 
       { *t3[i]= t1[i-1] ;}
     
       else 
        { if(i%2 != 0 && i-1<=size)
          { *t3[i] = t2[i-1] ; }
          else { if(i==0) { *t3[i]= t1[i] ; }
               }
        }
     }
    }
     int main ()
    {
     
      int t1[5]= { 1,2,3,4,5};
      int t2[5]= { 6, 7,8,9,10};
      int t3[10], i ;
     
      mixageTableaux(t1, t2, &t3);
      for (i= 0; i<10; i=i+1)
      { printf("%d\n", t3[i]) ; }
     
     return 0 ;
    }

    Merci

  2. #2
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    Il n'y a aucune raison d'avoir peur d'un pointeur, il s'agit d'une variable comme une autre.

    Un tableau de N truc est un séquence de truc, numéroté de 0 à N-1.
    Ces numéros sont appelés des indices, et sont stockés dans des entiers (idéalement, non signés)

    La mémoire est une immense séquence de bytes numérotés de 0 à beaucoup.
    Ces numéros sont appelé des adresses mémoire, et sont stockés dans des entiers particuliers, les pointeurs, qui portent une informations complémentaires: le type de ce que la case mémoire est sensée contenir.

    Ca fonctionne globalement pareil.

    Toute variable a une adresse, mais aussi un nom propre.
    Certaines choses ont une adresse, mais pas de nom propre, c'est le cas des éléments d'un tableau, qui sont nommé par référence au tableau.
    ainsi, avec int a[4];, a est une variable, dont le type est int[4], par contre, son premier élément n'a pas de nom, mais est obtenable via a[0].

    l'expression a[1] signifie précisément le int dont l'adresse est l'adresse de a plus 1 fois la taille d'un int, c'est pourquoi, en C, les tableaux commencent à 0: pour que le premier élément soit à la meme adresse que le tableau lui-même, et ainsi ne pas gaspiller de mémoire pour rien.
    Le même résultat peut s'obtenir avec ce qu'on appelle l'arithmétique des pointeurs. le nom d'un tableau (ici a) pouvant se convertir implicitement en l'adresse de son premier élément (&a[0]), (a+1) est l'adresse situé un int plus loin que a (car a est l'adresse d'un int), c'est la même valeur que &a[1].
    Et l'entier à cet endroit est a[1], *&a[1] ou encore *(a+1), ou même *((&a[0])+1).

    évidemment, la plupart de ces notations sont pertubantes, sauf quand on utilise des variables: pour indexer une matrice, on peut utiliser *(matrix+rows*row_size + column), ou son équivalent: matrix[rows*row_size + column].


    La où le pointeur devient intéressant, c'est que malloc retourne une adresse, mais pas celle d'une variable que tu as toi-même déclarée.
    Et c'est là que les choses peuvent devenir complexes, car il faut absoluement libérer une et une seule fois chaque bloc mémoire obtenu ainsi.
    Complexes, mais en étant rigoureux, c'est gérable.

    A cette lumière, que penses-tu de ton programme?
    C'est à dire, ou devines-tu des erreurs, et lesquelles?

  3. #3
    Expert confirmé Avatar de BufferBob
    Profil pro
    responsable R&D vidage de truites
    Inscrit en
    Novembre 2010
    Messages
    3 041
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : responsable R&D vidage de truites

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 041
    Par défaut
    salut,

    c'est assez tarabiscoté ton code, au niveau des pointeurs tu passes t1 et t2 correctement, t3 est un tableau d'entiers également je vois pas pourquoi tu le passe différemment à la fonction ^^

    par ailleurs tu devrais à mon sens passer la taille du tableau (...) en paramètre de la fonction, ça prend son sens vu qu'en dehors de l'exercice la fonction n'est pas censée connaitre et ne peut pas déterminer la taille des tableaux qu'elle reçoit en paramètre

    en revanche les if {} else {if {} else {if {}}} en cascade c'est pas très heureux, et en plus tu te prends la tête pour rien, par exemple i-1<=size, dans la mesure où i varie de 0 inclus à size exclus la condition est toujours vraie et ne sert donc à rien

    l'exercice est assez simple, mais tu le prends un peu "à l'envers" à mon avis, tu devrais essayer de réfléchir comment tourner ton code autrement en prenant size=5 par exemple

  4. #4
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2013
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 610
    Billets dans le blog
    21
    Par défaut
    A lire l'énoncé, la question de l'allocation de la mémoire ne se pose pas, puisqu'on suppose que la tableau des résultats est de taille suffisante.

    Il s'agit juste de faire avancer les deux pointeurs des tableaux de départ et celui sur le pointeur d'arrivée à un rythme correct.

    Pour copier un tableau, l'algorithme est le suivant:

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void copy(int* src, int* dest, int size) { // int* src = int src[] pour les arguments de fonction: c'est un pointeur sur le début du tableau qui est passé de toute façon
      for (int i = 0; i < size; ++i) {
        dest++ = src++;
      }
    }

    pour copier deux tableaux, maintenant:

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    void copy(int* src1, int* src2, int* dest, int src_size) {
      // comment à ton avis copier un élément de src1 puis un élément de src2? Ce n'est pas différent de l'algorithme de base, c'est juste l'un après l'autre!
    }

  5. #5
    Membre chevronné
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    1 854
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 854
    Par défaut
    Hello,

    Pour compléter la réponse de Leternel.

    Un pointeur c'est quoi ?
    => Simplement une variable qui contient la valeur d'une adresse mémoire.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    int myVal = 1000; // déclaration d'une variable de type entier
    int * ptInt; // déclaration d'un pointeur d'entier (int) 
     
    ptInt= &myVal; // l'opérateur '&' indique de récupérer l'adresse mémoire où est stockée la variable myVal
    printf("%p\n", ptInt); // affiche la valeur de l'adresse mémoire où est stockée la variable myVal
    Imaginons que l'adresse mémoire où est stockée myVal est 12345
    On a donc :
    - myVal = 1000
    - ptInt = 12345
    Si on veut afficher la valeur si situant à l'adresse pointée par le pointeur ptInt, il faut utiliser l'opérateur '*'
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    // Ces trois lignes font la même chose : elle affiche la valeur de myVal
    printf("%i\n", myVal); 
    printf("%i\n", *ptInt);
    printf("%i\n", *((int*)1234));
    => la taille mémoire dépend de sont type. Ex : char (1 octet), int (4 octets), ... (attention la taille des variables dépend du compilateur utilisé et de ses paramètres de configuration)
    => la taille mémoire d'un pointeur est toujours la même quelque soit sont type : un pointeur contient uniquement des valeurs d'adresse mémoire, donc sa taille est la taille permettant de stockée ces adresses

    ***************************
    si on déclare des tableaux de plusieurs types :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    char tabChar[20];
    int tabInt[20];
    l'adresse de chaque élément du tableau est :
    adresse de l'élément n = adresse du tableau + n x taille de l'élément
    Donc :
    Si l'adresse de tabChar est 1000 et que la taille d'un char est 1 octet, l'adresse de l'élément 5 de tabChar est 1000+5x1=1005.
    => &tabChar[5] = adresse de cet élément
    Si l'adresse de tabInt est 2000 et que la taille d'un int est 4 octets, l'adresse de l'élément 5 de tabInt est 2000+5x4=2020.
    => &tabInt[5] = adresse de cet élément
    Un dernier exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    int tabInt[20];
    int * ptInt;
     
    ptInt = &tabInt[0]; // Peut aussi d'écrire : ptInt = tabInt;
     
    // Les deux lignes suivant affiche le même résultat (valeur de l'élément 4 du tableau) :
    printf("%i\n", tabInt[4]);
    printf("%i\n", *(ptInt+4)); // peut aussi s'écrire : printf("%i\n", ptInt[4]);
    // => printf("%i\n", tabInt[4]); peut aussi s'écrire : printf("%i\n", *(tabInt+4));
     
    // Attention :  si ptInt vaut l'adresse mémoire 2000, ptInt + 4 ne vaut pas 2004 mais 2000 + sizeof(int) x 4 = 2000 + 4x4 = 2016
    // => le pas d'incrémentation dépend du type du pointeur
    N'hésite pas à poser des question si tu n'as pas tout compris

  6. #6
    Nouveau membre du Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Avril 2015
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2015
    Messages : 5
    Par défaut
    Merci à tous de m'avoir répondue. Je reviens un peu tardivement.

    Alors l'histoire des pointeurs, nos profs ne nous l'ont jamais expliqué aussi précisement. Ce qui fait que dans les explications en TP par exemple on nous dit : "tu mets un pointeur quand tu dois retourner deux résultat dans ta fonction ou quand un élément de tes paramêtres est modifié. C'est pour ça que je voulais mettre un pointeur devant t3. J'a irefais cette exo, et fais un double post (completement oublié celui là....)

    et voilà ce que ça me donne comme programme (du coup avec un pointeur devant t3 toujours). Ca m'enerve cette histoire de pointeurs; j'arrive pas à comprendre.

    http://www.developpez.net/forums/d15...c/#post8243869

Discussions similaires

  1. Probléme structure pointeur fonction
    Par babouoles dans le forum Bibliothèque standard
    Réponses: 9
    Dernier message: 14/05/2008, 17h34
  2. Problème de pointeur sur une fonction
    Par CodeurNé dans le forum C
    Réponses: 4
    Dernier message: 03/10/2007, 22h45
  3. Probléme de pointeur sur fonction
    Par TSalm dans le forum C++/CLI
    Réponses: 11
    Dernier message: 25/07/2007, 22h53
  4. Réponses: 11
    Dernier message: 14/10/2006, 21h26
  5. Problème de pointeur (encore un)
    Par Arry_C dans le forum C
    Réponses: 16
    Dernier message: 30/05/2006, 19h47

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