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 :

Passage d'un programme en fonctions pointeur.


Sujet :

C

  1. #1
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2008
    Messages
    17
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2008
    Messages : 17
    Points : 13
    Points
    13
    Par défaut Passage d'un programme en fonctions pointeur.
    bonjour,

    je suis en première année d'un Dut GEII (génie électrique et informatique industriel).

    mon dernier projet était de crée un programme qui permet de trouver des nombres palindromiques (qui sont identiques dans leurs deux sens de lecture).
    mon premier programme marche très bien. C'est au moment du passage en fonctions avec pointeur que ça se complique... j'utilise deux tableaux "malloc", donc deux pointeur de départ,mon problème est que je n'arrive pas à les prendre dans une fonction, les modifiers (voir les créer dans ce cas), et les renvoyer à la fonction "main".
    - Est-ce possible de créer un pointeur qu'on transforme en tableau dans une fonction avant de renvoyer ce tableau dans la fonction principal ?
    - Dans ce cas, me faut-il utiliser des pointeurs de pointeur ?

    Pour conclure :/ je me suis complètement embrouillé sur les différents pointeurs de mes tableaux dynamiques. Le programme est écrit de la façon qui me semble être la mieux, mais ça marche pas...

    Les erreurs de compilation me renvoient bien sur un problème de pointeur:

    Dev-C\SuitesPalindromiquesfonction.cpp: In function `int main()':
    Dev-C\SuitesPalindromiquesfonction.cpp:24: error: cannot convert `int*' to `int**' for argument `3' to `void allouer(int, int, int**)'
    Dev-C\SuitesPalindromiquesfonction.cpp:25: error: cannot convert `int*' to `int**' for argument `3' to `void inverser(int, int*, int**)'
    Dev-C\SuitesPalindromiquesfonction.cpp: In function `void allouer(int, int, int**)':
    Dev-C\SuitesPalindromiquesfonction.cpp:53: error: cannot convert `int*' to `int**' in assignment
    Dev-C\SuitesPalindromiquesfonction.cpp:59: error: invalid conversion from `int' to `int*'
    Dev-C\SuitesPalindromiquesfonction.cpp: In function `void inverser(int, int*, int**)':
    Dev-C\SuitesPalindromiquesfonction.cpp:68: error: cannot convert `int*' to `int**' in assignment
    Dev-C\SuitesPalindromiquesfonction.cpp:70: error: invalid conversion from `int' to `int*'
    sans plus attendre... voici mon programme avec en rouge les zones importantes:

    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
    #include <stdio.h>
    #include <stdlib.h>
    void calcul(int cycle, int temps, int entier,int *n_chiffre);
    // allouer crée le tableau dynamique "tab_chiffre".
    void allouer(int n_chiffre, int entier, int **tab_chiffre);
    // inverser prend le tableaux dynamique "tab_chiffre", et crée le tableau dynamique "tab_chiffre_inv".
    void inverser(int n_chiffre, int *tab_chiffre, int **tab_chiffre_inv);
    //verification reprend les tableaux sans les modifier.
    int verification(int cycle, int temps, int entier, int invariable, int n_chiffre, int *tab_chiffre, int *tab_chiffre_inv);
    // addition ---> verification.
    void addition(int *entier, int *n_chiffre, int *tab_chiffre, int *tab_chiffre_inv);
     
    int main(){
        int n_chiffre, entier, invariable;
        int temps, cycle;
       // je définis donc les pointeurs de "main".
       int *tab_chiffre, *tab_chiffre_inv;
     
        //calculer nb_chiffre
        printf("entrez un entier :");
        scanf("%d",&entier);
        printf("definissez le nombre de cycle maximum :");
        scanf("%d",&cycle);
        invariable=entier; 
     
        for (temps=cycle;temps>=0;temps--){
            calcul(cycle, temps, entier, &n_chiffre);
            //fonction donné à "main" passage par adresse ?.
           allouer(n_chiffre, entier,  &*tab_chiffre);
            inverser(n_chiffre, tab_chiffre, &*tab_chiffre_inv);
            verification(cycle, temps, entier, n_chiffre, invariable, tab_chiffre, tab_chiffre_inv);
            // ici je suis perplexe ^^... debut de tableau donc pas de * n'y [] ?
            addition(&entier, &n_chiffre, tab_chiffre, tab_chiffre_inv);
            }
     
     
        printf("\nle programme n'a pas trouve de palindrome au bout de %d etape\n",cycle); 
     
      system("PAUSE");	
      return 0;
    }
     
        void calcul(int cycle, int temps, int entier, int *n_chiffre){
             int i=0,n_temp;
     
             printf ("entier = %d, rang = %d\n",entier,(cycle-temps));
             n_temp=entier;
             do{
             i++;
             n_temp/=10;
             }while(n_temp!=0);
             *n_chiffre=i;
        }
     
        //allouer tab_chiffre
        // l'indication des variables d'entrée de fonction.
        void allouer(int n_chiffre, int entier, int **tab_chiffre){
             int n_temp, n_temp2, i;
             // création du tableau avec malloc. je précise au logiciel que tab_chiffre est un pointeur ?
             tab_chiffre=(int*)malloc(n_chiffre*sizeof(int));
             n_temp=entier;
             n_temp2=entier;
             for (i=n_chiffre-1;i>=0;i--){
                 n_temp/=10;
                 n_temp2%=10;        
                 tab_chiffre[i]=n_temp2;
                 n_temp2=n_temp;
                 }
        }
     
        //inverser tab_chiffre
        // l'indication des variables d'entrée de fonction.
        void inverser(int n_chiffre, int *tab_chiffre, int **tab_chiffre_inv){
             int i, j;
             // même problème que pour la précèdente fonction.
             tab_chiffre_inv=(int*)malloc(n_chiffre*sizeof(int));
             for(i=0,j=n_chiffre-1;i<n_chiffre;i++,j--){
                tab_chiffre_inv[j]=tab_chiffre[i];
             }
        }
     
        //verification de la propriete du nombre palindromique
        // l'indication des variables d'entrée de fonction.
        int verification(int cycle, int temps, int entier,int invariable, int n_chiffre, int *tab_chiffre, int *tab_chiffre_inv){
             int i, test;
     
             for (i=0,test=0;i<n_chiffre;i++){
                 if(tab_chiffre[i]==tab_chiffre_inv[i]){
                 test++;
                 }
             }
             if (test==n_chiffre){
                printf("votre nombre (%d) est bien un palyndrome. au rang %d il devient (%d)\n",invariable,(cycle-temps),entier);
     
                system("PAUSE");	
                return 0;
             }
        }
     
        // addition des tableaux
        // l'indication des variables d'entrée de fonction.
        void addition(int *entier, int *n_chiffre, int *tab_chiffre, int *tab_chiffre_inv){
             int i, puissance;
     
             entier=0;
             for (i=0,puissance=1;i<*n_chiffre;i++){
                 entier+=((tab_chiffre[i]+tab_chiffre_inv[i])*puissance);
                 puissance*=10;
                 }
             free(tab_chiffre);
             free(tab_chiffre_inv);
             n_chiffre=0;
        }
    voilà, j'ai essayé de rendre les écrits plus lisible, est-ce que ça l'est ?, Au cas ou j'ai à poster de nouveau sur ce forum. J'aimerais savoir aussi, couleur non comprise, si vous avez des reproches à faire à ma façon d'écrire en C, que je ne parte pas avec de mauvaise base.

    merci d'avance.

  2. #2
    Expert confirmé Avatar de fregolo52
    Homme Profil pro
    Développeur C
    Inscrit en
    Août 2004
    Messages
    2 366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Août 2004
    Messages : 2 366
    Points : 5 382
    Points
    5 382
    Par défaut
    salut,

    tu as au moins une erreur de syntaxe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    allouer(n_chiffre, entier,  &*tab_chiffre);
    est faux
    il faut faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    allouer(n_chiffre, entier,  &tab_chiffre);
    &*tab_chiffre : veut dire adresse(&) du contenu (*) donc &*tab_chiffre = tab_chiffre

    Dans la fonction alloue il faut faire ca :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    *tab_chiffre=(int*)malloc(n_chiffre*sizeof(int));
    Les pointeurs ne sont pas évidents à appréhender pour les débutants, alors des pointeurs de pointeurs !!!!

  3. #3
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2008
    Messages
    17
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2008
    Messages : 17
    Points : 13
    Points
    13
    Par défaut
    merci pour ton renseignement, le programme se lance a présent. Au niveau des pointeurs, plus de problème.
    Par contre, le logiciel me demande de choisir un nombre et plante après, si je me fis à mon professeur je dois chercher une boucle infini, bien que je n'ai pas eu ce genre de problème avec ma précédente version (sans fonction.) enfin... je vais essayer de voir ça.

  4. #4
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    D'abord, une erreur :
    Dans main, l'appel de vérification est incorrect : deux arguments ont été échangés :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    //  verification(cycle, temps, entier, n_chiffre, invariable, tab_chiffre, tab_chiffre_inv);
        verification(cycle, temps, entier, invariable, n_chiffre, tab_chiffre, tab_chiffre_inv);
    Quelques critiques sur ton code :
    1- Tu passes systématiquement le résultat des fonctions par l'intermédiaire de la liste des paramètres. La façon la plus naturelle de renvoyer une valeur pour une fonction est d'utiliser une valeur de retour dans le return. On utilise la liste de paramètres lorsque la fonction doit renvoyer plusieurs valeurs ou lorsque la valeur à renvoyer est volumineuse (comme une structure).

    Puisque la fonction allouer crée un tableau, il semble naturel qu'elle renvoie le tableau créé par sa valeur de retour. Il est inutile en C de caster le retour de malloc ; par contre, il faut tester si l'allocation a réussi
    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
    int * allouer(int n_chiffre, int entier)
    {
       int n_temp, n_temp2, i;
       int * tab_chiffre ;
       tab_chiffre=malloc(n_chiffre*sizeof(int));
       if(tab_chiffre != NULL)
       {
          n_temp=entier;
          n_temp2=entier;
          for (i=n_chiffre-1;i>=0;i--)
          {
             n_temp /= 10;
             n_temp2 %= 10;
             tab_chiffre[i]=n_temp2;
             n_temp2=n_temp;
          }
       }
       return tab_chiffre ;
    }
    // Dans main :
     
       tab_chiffre = allouer(n_chiffre, entier);
       if(tab_chiffre != NULL)
       {
        // continuer
       }
       else // ....
    Idem pour inverser qui crée le tableau inversé:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    int *  inverser(int n_chiffre, int *tab_chiffre)
    {
       int i, j;
       int * tab_chiffre_inv ;
       tab_chiffre_inv = malloc(n_chiffre*sizeof(int));
       if(tab_chiffre_inv != NULL)
          for(i=0,j=n_chiffre-1;i<n_chiffre;i++,j--)
             tab_chiffre_inv[j]=tab_chiffre[i];
       return tab_chiffre_inv;
    }
    2- Une fonction doit faire une seule chose bien précise et ce complètement.

    verification, fait deux choses : elle procède à la vérification annoncée et affiche un message en cas de succès. C'est en général néfaste : ce n'est pas à la fonction d'exploiter son résultat mais au code qui l'a appelé. Imagine que la fonction sin de la bibliothèque affiche son résultat sur l'écran. Elle serait inutilisable à cause de la pollution visuelle que cela engendrerai.
    Symptomatiquement, 4 des paramètres de verification ne servent à rien dans la vérification et ne sont là qu'à cause du printf. C'est beaucoup. Il serait plus astucieux que la fonction renvoie un indicateur (test==n_chiffre) et que la fonction main agisse en conséquence:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    int verification(int n_chiffre, int *tab_chiffre, int *tab_chiffre_inv)
    {
       int i, test;
       for (i=0,test=0;i<n_chiffre;i++)
             if(tab_chiffre[i]==tab_chiffre_inv[i]) test++;
       return test == n_chiffre ;
    }
    // dans main 
    if(verification(n_chiffre, tab_chiffre, tab_chiffre_inv))
       printf("votre nombre (%d) est bien un palyndrome. au rang %d il devient (%d)\n",invariable,(cycle-temps),entier);

    De même pour calcul, pourquoi passer par la liste de paramètres pour renvoyer la valeur obtenue ? La valeur de retour des fonctions est faite pour ça ! Placer le printf dans le main, comme pour verification
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    int calcul( int entier)
    {
       int i=0,n_temp;
       n_temp=entier;
       do
       {
          i++;
          n_temp/=10;
       }while(n_temp!=0);
       return i;
    }
    La fonction addition fait deux choses radicalement différentes : elle calcule une somme et elle réinitialise les variables, notamment en faisant les free. Il faut la couper en deux :
    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
    int addition(int n_chiffre, int *tab_chiffre, int *tab_chiffre_inv)
    {
       int i, puissance;
       int entier=0;
       for (i=0,puissance=1;i<n_chiffre;i++)
       {
          entier+=((tab_chiffre[i]+tab_chiffre_inv[i])*puissance);
          puissance*=10;
       }
       return entier;
    }
     
    void liberer(int *tab_chiffre, int *tab_chiffre_inv)
    {
       free(tab_chiffre);
       free(tab_chiffre_inv);
    }
    main devient quelque chose du genre :
    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
    ....
       for (temps=cycle;temps>=0;temps--)
       {
          printf ("entier = %d, rang = %d\n",entier,(cycle-temps));
          n_chiffre  = calcul(entier);
          tab_chiffre = allouer(n_chiffre, entier);
          if(tab_chiffre != NULL)
          {
             tab_chiffre_inv = inverser(n_chiffre, tab_chiffre);
             if(tab_chiffre_inv != NULL)
             {
                if( verification(n_chiffre, tab_chiffre, tab_chiffre_inv))
                   printf("votre nombre (%d) est bien un palyndrome. au rang %d il devient (%d)\n",invariable,(cycle-temps),entier);
                entier = addition(n_chiffre, tab_chiffre, tab_chiffre_inv);
             }
             else {/*par exemple un message d'erreur et temps = -1 pour sortir de la boucle for*/}
             liberer(tab_chiffre, tab_chiffre_inv);
          }
          else {/*par exemple un message d'erreur et temps = -1 pour sortir de la boucle for*/}
       }
    ....

  5. #5
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2008
    Messages
    17
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2008
    Messages : 17
    Points : 13
    Points
    13
    Par défaut
    Très bien, merci beaucoup. Il est dommage que les cours d'informatiques en GEII soient négligés, j'ai l'impression, à la fin de mon apprentissage en C, de ne rien avoir appris... (le génie électrique étant prioritaire.).
    En gros nous avons les bases, sans avoir eut le temps de comprendre les principes d'un codage propre et compréhensible, voir l'utilité du langage C face au C++.

    Donc en conclusion:

    1.)Une Fonction ne doit pas réaliser plus d'une tache, et ne doit pas directement agir sur la suite du programme, c'est à la fonction principale "main" de traiter les résultats des sous-fonctions pour ensuite avancer dans le programme.

    2.)Si la fonction ne renvoie pas plus d'une variable, il n'est pas nécessaire, n'y même recommandé, d'utiliser une fonction à pointeur, je dois, dans le cas d'une variable seul, utiliser une fonction avec renvoie "return". La fonction pointeur étant réservé aux renvoies de multiples variables ou au variable simple de valeur importante.

    mon professeur m'a vaguement interdit l'utilisation de variables globales. Pourquoi les fonctions à variables globales représentent-elles une gène dans un programme ? On les utilise encore ou ça vaut -5 points aux contrôles, au même titre que la commande "goto" ^^ ?

  6. #6
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    Citation Envoyé par bambam978 Voir le message
    ....
    1.)Une Fonction ne doit pas réaliser plus d'une tache, et ne doit pas directement agir sur la suite du programme, c'est à la fonction principale "main" de traiter les résultats des sous-fonctions pour ensuite avancer dans le programme.
    A main ou à une autre fonction qui regroupe des appels à ces fonctions pour construire UNE tâche plus importante. C'est comme des briques avec lesquels on fait des murs avec lesquels on fait une maison...
    Si une fonction réalise plus d'une tâche :
    - On ne voit plus qui fait quoi ni comment
    - Elle est difficilement réutilisable : Si on a besoin d'une partie de ses fonctionnalités seulement, c'est foutu.
    2.)Si la fonction ne renvoie pas plus d'une variable, il n'est pas nécessaire, n'y même recommandé, d'utiliser une fonction à pointeur, je dois, dans le cas d'une variable seul, utiliser une fonction avec renvoie "return". La fonction pointeur étant réservé aux renvoies de multiples variables ou au variable simple de valeur importante.
    C'est une question de logique : pourquoi se priver de cette possibilité qui rend en plus le code plus "naturel" ?

    mon professeur m'a vaguement interdit l'utilisation de variables globales. Pourquoi les fonctions à variables globales représentent-elles une gène dans un programme ? On les utilise encore ou ça vaut -5 points aux contrôles, au même titre que la commande "goto" ^^ ?
    Ton prof a doublement raison (et - 5 points n'est pas cher payé)

    Les variables globales sont (très) néfastes parce qu'on ne sait pas facilement par quelles fonctions, ni quand, ni sous quelles conditions,... elles sont modifiées ou non dans le code. De plus, si une fonction les utilise, elle cesse d'être une unité de programmation indépendante du reste du code : elle n'est plus autonome; elle interagit avec les autres fonctions de façon obscure. Les erreurs sont alors bien difficiles à situer. N'utiliser des variables globales que pour des raisons bien précises (et il y en a peu) et elles ne doivent pas servir à éviter le passage des paramètres aux fonctions. Ce n'est pas du tout leur rôle.

    Le goto déstructure le programme. Il est beaucoup plus facile de lire , d'écrire et de maintenir un programme utilisant des for, while,... que le même construit avec des goto. On peut admettre (si on veut) l'utilisation de goto pour terminer une fonction en cas d'erreur irrécupérable en sortant ainsi plus facilement de boucles imbriquées. Mais dans ce cas, il s'agit d'une liquidation de la fonction pour cause de problèmes. A s'interdire dans tous les cas des goto qui "remontent" dans le code du programme.

  7. #7
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2008
    Messages
    17
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2008
    Messages : 17
    Points : 13
    Points
    13
    Par défaut
    Ce message est juste un remerciement.

    j'ai modifié tout mon programme ce matin avec vos conseils. Le programme marche très bien.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Passage de structure en parametre fonction : Pointeur
    Par apicard3 dans le forum Débuter
    Réponses: 5
    Dernier message: 30/10/2013, 08h29
  2. Réponses: 6
    Dernier message: 31/05/2008, 15h45
  3. Réponses: 6
    Dernier message: 24/12/2004, 16h46
  4. [langage] Passage de paramètres dans une fonction
    Par And_the_problem_is dans le forum Langage
    Réponses: 11
    Dernier message: 28/06/2004, 08h20
  5. [langage] passage de paramètres à une fonction
    Par BARBIER dans le forum Langage
    Réponses: 4
    Dernier message: 07/05/2004, 15h46

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