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 avec une fonction, incompréhension !


Sujet :

C

  1. #1
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2020
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 24
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2020
    Messages : 18
    Points : 11
    Points
    11
    Par défaut Problème avec une fonction, incompréhension !
    Bonjour, ou bonsoir peut-être, j'aimerais que quelqu'un m'aide sur quelque chose que je ne comprends pas ! Ma fonction decomposition() doit retourner normalement le même nombre passé en paramètre ! quand je test sur des petits nombres de l'ordre de 10**3 à 10*9 cela marche mais quand je rentre par exemple 9999999999999 cela ne marche pas ! Et je ne comprends pas pourquoi ! si une personne peut me résoudre ce problème j'en serais ravi, merci d'avance pour toutes aides en tout cas ^^ et si vous avez d'autre chose à me conseiller sur mon code je suis preneur !
    Normalement je vous ai mis en pièce jointe mon projet complet si nécessaire, avec mon .h et des tests aussi !

    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
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <limits.h>
    #include <errno.h>
     
    #include "./spell-number.h"
     
    Number is_negative(const Number N) {
      Number nb = {N.negative, N.number, N.language};
      if (N.number < 0) {
        nb.negative = 1;
      }
      return nb;
    }
     
    //cette fonction renvoie le nombre pivot associé au nombre
    long long pivot_number(const long long nb) {
     
      if (60 <= nb && HUNDRED - 1 >= nb) {
        return TWENTY;
      }
      else if (10 <= nb && 60 > nb) {
        return 10;
      }
      else if (HUNDRED <= nb && THOUSAND - 1 >= nb) {
        return HUNDRED;
      }
      else if (THOUSAND <= nb && MILLION - 1 >= nb) {
        return THOUSAND;
      }
      else if (MILLION <= nb && BILLION - 1 >= nb) {
        return MILLION;
      }
      else if (BILLION <= nb && TRILLION - 1 >= nb) {
        return BILLION;
      }
      else if (TRILLION <= nb && QUADRILLION - 1 >= nb) {
        return TRILLION;
      }
      else if (QUADRILLION <= nb && QUINTILLION - 1 >= nb) {
        return QUADRILLION;
      }
      else if (QUINTILLION <= nb && LLONG_MAX >= nb) {
        return QUINTILLION;
      }
    }
     
    long long power(const int a, const int n) { //cette fonction retourne a**n ou a^n
      if(n == 0) {
        return(1);
      }
      return(a * power(a, n-1));
    }
     
    // cette fonction est encore en phase de développement elle n'est pas terminée mais elle doit décomposé un nombre
    // prenons l'éxemple de 10050200, après traitement la fonction doit retournée 10050200 = (10) * 10**6 + (50) * 10**3 + 2 * 100
    // c.f http://yann.coscoy.free.fr/nombre/info.html pour l'algorithme, rubrique décomposition arithmétique
    long long decomposition(const long long nb) {
      long long p = pivot_number(nb);
      printf("p = %lld\n", p);
      long long rest = nb % p;
      long long quotient = nb / p;
      printf("quotient = %lld\n", quotient);
      printf("rest = %lld\n", rest);
      return quotient * p + rest;
    }
     
    int main(int argc, char *argv[]) {
      if (argc > 3) { //3 car argv[0] = ./spell-number
     
        printf("Vous avez rensigné trop d'arguments !\n");
        printf("Exemple : ./spell-number language number\n");
        return EXIT_FAILURE;
     
      } else if(argc == 3) {
     
        errno = 0; //je suis obligé d'utiliser la variable errno pour la gestion d'erreurs de atoi()
     
        long long nb = atoi(argv[2]); //convertion de la chaine de caractère en nombre
        char *lg_array = malloc(strlen(argv[1]) + 1); //Allocation de mémoire "+1" pour "\0"
        strcpy(lg_array, argv[1]); //copie des arguments vers lg_array
     
        Number nombre = {nombre.negative = 0, nombre.number = nb, nombre.language = lg_array}; //par défaut le nombre n'est pas négatif
     
        if (errno == 34) { //34 correspond à l'erreur : Numerical result out of range
          fprintf(stderr, "atoi : %s\n", strerror(errno)); //perror("atoi"); fait exactement la même chose
          printf("Votre valeur ne doit pas être inférieur au minimum = %lld, ou ne doit pas être supérieur au maximum = %lld.\n", LLONG_MIN, LLONG_MAX);
          return EXIT_FAILURE;
        }
     
        nombre = is_negative(nombre); //traitement de is_negative()
     
        if (nombre.negative == 1) {
          nombre.number = nombre.number * -1; //pour le rendre positif afin de rendre le traitement plus facile
        }
     
        long long d = decomposition(nombre.number);
        printf("decomposition = %lld\n", d);
     
        return EXIT_SUCCESS;
     
      } else {
     
        printf("Le nombre d'argument renseigné est insuffisant !\n");
        printf("Exemple : ./spell-number language number\n");
        return EXIT_FAILURE;
     
      }
    }
    Fichiers attachés Fichiers attachés

  2. #2
    Membre averti
    Homme Profil pro
    très occupé
    Inscrit en
    Juillet 2014
    Messages
    137
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : très occupé

    Informations forums :
    Inscription : Juillet 2014
    Messages : 137
    Points : 411
    Points
    411
    Par défaut
    Salut Modaak,

    Ma fonction decomposition() doit retourner normalement le même nombre passé en paramètre ! quand je test sur des petits nombres de l'ordre de 10**3 à 10*9 cela marche mais quand je rentre par exemple 9999999999999 cela ne marche pas !
    chez-moi cela a l'air de fonctionner, avec un processeur 64 bits et une machine Linux Debian Buster x86_64 GNU/Linux et gcc 64 bits version 8.3.0.

    Avec le code de test suivant :

    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
    #include <stdio.h>
    #include <stdio.h>
    #include <assert.h>
    #include <limits.h>
     
    #include "./spell-number.h"
     
    int main(void) {
        long long int my_number = 9999999999999;
        printf("LLONG_MAX on this machine = %lld\n", LLONG_MAX);
        printf("my number                 = %lld\n", my_number);
        printf("pivot number              = %lld\n", pivot_number(my_number));
     
        assert(pivot_number(my_number) == TRILLION);
        assert(decomposition(9999999999999) == 9999999999999);
        printf("All tests completed\n");
     
      return 0;
    }
    J'obtiens :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    LLONG_MAX on this machine = 9223372036854775807
    my number                 = 9999999999999
    pivot number              = 1000000000000
    p = 1000000000000
    quotient = 9
    rest = 999999999999
    All tests completed

  3. #3
    Membre expérimenté
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Juillet 2020
    Messages
    352
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet NTIC

    Informations forums :
    Inscription : Juillet 2020
    Messages : 352
    Points : 1 376
    Points
    1 376
    Par défaut
    Bonjour,

    Il y a plusieurs soucis :
    • fonction pivot_number
      Il y a un warning →
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      spell-number.c: In function ‘pivot_number’:
      spell-number.c:47:1: warning: control reaches end of non-void function [-Wreturn-type]
      En effet cela posera un problème si nb < 10
      Une implémentation plus classique serait :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      9
      //cette fonction renvoie le nombre pivot associé au nombre
      long long pivot_number(const long long nb) {
          if (nb<10) return 0;
          else if (nb<60) return 10;
          else if (nb<HUNDRED) return TWENTY;
          else if ....
          else if (nb<QUINTILLION) return QUADRILLION;
          return QUINTILLION;
      }
    • fonction is_negative
      Mal nommée.
      En lisant le nom on suppose qu'elle renvoie un booléen indiquant si oui ou non le paramètre est négatif, en lisant le code on s'aperçoit qu'elle donne une valeur à un champ de la structure qui indique si le nombre est négatif ou pas et renvoie une copie du paramètre.
      Ce n'est pas clair, d'autant plus que tu modifie le signe de Nombre.nombre ensuite dans le code …
      Il aurait mieux valu créer une fonction genre normalize(Number *) →
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      void normalize(Number *n)
      {
          assert(n!=NULL);
          if (n->number<0) {
              n->negative = 1;
              n->number = - n->number;
          }
      }
    • fonction power
      attention aux mélanges de int et long long …

    • fonction decomposition
      no comment car en cours de dev;

    • dans main :

      je remarque le commentaire : «je suis obligé d'utiliser la variable errno pour la gestion d'erreurs de atoi()»
      non → atoi n'utilise pas errno. atoi essaye de faire ce qu'elle peut sans permettre de déterminer s'il y a eu ou non une erreur. De plus elle renvoie un int et non un long long, tu aurais dû utiliser atoll.
      Le mieux est d'utiliser une des fonctions de la famille strto*, en particulier strtoll dans ton cas. Elle est plus robuste et permet de faire une gestion d'erreur.


    Sinon le plus simple serait de commencer à utiliser un debuger et de faire du pas à pas pour débusquer l'erreur qui implique clairement l'utilisation de atoi.

    Edit:

    Après y avoir songé un peu plus, je vais rajouter deux remarques :

    • on pourrait utiliser un int64_t (inttype.h) à la place du long long pour s'assurer de bien avoir les 2^63 et utiliser sscanf pour la lecture de l'entier et la gestion des erreurs ;
    • il serait encore plus simple de ne pas utiliser des entiers mais de faire le traitement directement sur la chaîne de caractères ; le plus grand entier dont on aurait besoin serait <1.000 si on utiulise les ION/IARD ou <1.000.000 si on se restreint aux ION.

  4. #4
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2020
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 24
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2020
    Messages : 18
    Points : 11
    Points
    11
    Par défaut Merci
    Citation Envoyé par -Eks- Voir le message
    Salut Modaak,



    chez-moi cela a l'air de fonctionner, avec un processeur 64 bits et une machine Linux Debian Buster x86_64 GNU/Linux et gcc 64 bits version 8.3.0.

    Avec le code de test suivant :

    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
    #include <stdio.h>
    #include <stdio.h>
    #include <assert.h>
    #include <limits.h>
     
    #include "./spell-number.h"
     
    int main(void) {
        long long int my_number = 9999999999999;
        printf("LLONG_MAX on this machine = %lld\n", LLONG_MAX);
        printf("my number                 = %lld\n", my_number);
        printf("pivot number              = %lld\n", pivot_number(my_number));
     
        assert(pivot_number(my_number) == TRILLION);
        assert(decomposition(9999999999999) == 9999999999999);
        printf("All tests completed\n");
     
      return 0;
    }
    J'obtiens :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    LLONG_MAX on this machine = 9223372036854775807
    my number                 = 9999999999999
    pivot number              = 1000000000000
    p = 1000000000000
    quotient = 9
    rest = 999999999999
    All tests completed

    Merci de votre aide mais j'ai trouvé mes erreurs et j'ai adapté mon code en conséquence ! c'était à cause de atoi() il fallait utiliser atoll() à la place !

  5. #5
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2020
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 24
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2020
    Messages : 18
    Points : 11
    Points
    11
    Par défaut Super !
    Merci pour votre aide ! j'ai adapter mon code en conséquence, mais petite question quand même ! j'ai essayé de modifier la fonction power() comme vous me l'avez conseillé mais j'ai une erreur que je ne comprend pas !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    long long power(const long long a, const long long n) {
      if (n == 0)
        return 1;
      return (a * power(a, n-1));
    }
    et cela ne fonctionne pas ! peut-être que j'ai mal compris votre conseil alors ! "attention aux mélanges de int et long long …"

  6. #6
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 630
    Points : 10 556
    Points
    10 556
    Par défaut
    Essaye (le const sur 1 paramètre par valeur n'est pas utile)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    long long power(long long a, long long n) {
        if (n == 0L) {
            return 1L;
        }
     
        return (a * power(a, n-1));
    }
    Mais ton code récursif sur de grands nombres, ce n'est pas gloup glop

  7. #7
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 565
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

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

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 565
    Points : 7 648
    Points
    7 648
    Par défaut
    Citation Envoyé par Modaak Voir le message
    et cela ne fonctionne pas ! peut-être que j'ai mal compris votre conseil alors ! "attention aux mélanges de int et long long …"
    Quelle erreur obtiens tu? Ce code me parait très correct. Indiquer par const qu'il n'y aura aucune modification de a et de n est un plus pour le lecteur et donc c'est plutôt une bonne idée. L'utilisation récursive, je dirais là pourquoi pas, dans ton cas l'optimiseur peut tout à fait transformer la fonction en une boucle.
    Mais on peut l'optimiser. Si on veut faire 12**9, on voit qu'il suffit de 4 multiplications, alors que ton code en nécessite 10:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
        r = a*a;   // puissance 2
        r = r*r;   // puissance 4
        r = r*r;   // puissance 8
        r *= a;    // puissance 9
    On peut par exemple écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    long long  power( long long a, unsigned int n ) { // a et n sont modifiés donc ne sont plus const
        long long  res = 1LL;
        while ( n > 0u ) {
            if ( n & 1u )      // n est impair
                res *= a;
            n >>= 1u;          // on divise n par 2 puis 4 puis 8 ...
            a *= a;            // on passe au carré, puissance4,  puissance8, ...
        }
        return  res;
    }

  8. #8
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 630
    Points : 10 556
    Points
    10 556
    Par défaut
    Citation Envoyé par dalfab Voir le message
    Indiquer par const qu'il n'y aura aucune modification de a et de n est un plus pour le lecteur et donc c'est plutôt une bonne idée.

    // a et n sont modifiés donc ne sont plus const
    Je sais que tu veux m’écraser avec tes idées mais je précise ma pensée.

    Lorsque tu passes des types de base en paramètre (int, double, char, ... même classe et structure), tous sauf des pointeurs et des références, on va prendre la valeur de la variable et passer 1 copie à la fonction.
    Donc dire que le paramètre est constant (que l'on ne va pas le modifier) n'est utile que pour dire que la variable qui est passée en paramètre ne va pas être modifiée.
    Dire que la copie d'1 valeur est constante n'est vraiment pas utile : ce n'est qu'1 valeur et non pas 1 variable, et c'est 1 copie (temporaire)

  9. #9
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Le const dans un paramètre copié est aussi utile que les variables temporaires const.
    Il est inutile dans le header/prototype, mais dans l'implémentation il t'assure que tu modifies pas cette variable par erreur.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  10. #10
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 690
    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 690
    Points : 30 985
    Points
    30 985
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par foetus Voir le message
    le const sur 1 paramètre par valeur n'est pas utile
    Perso moi dans mes travaux officiels (et justement on m'a demandé un travail en C il n'y a pas longtemps) je le fais. En réalité je me "force" à le faire parce que il faut bien avouer que ça me casse les c... mais ça me garantit que je ne pourrai pas écrire par inadvertance param=autre_chose et s'il m'arrive de l'écrire, alors ça plante à la compilation et ça me force à réfléchir si cette modif est vraiment utile. Je ne dis pas que c'est obligatoire mais je ne trouve pas ça trop mauvais comme idée...

    Citation Envoyé par foetus Voir le message
    Mais ton code récursif sur de grands nombres, ce n'est pas gloup
    Je crois que l'expression officielle c'est pas glop
    Mais c'est d'une façon plus générale qu'un code récursif là où un code itératif peut s'écrire, quelle que soit la nature de l'élément traité (petit nombre, grand nombre, ...), c'est "pas glop".

    Citation Envoyé par Bousk Voir le message
    Il est inutile dans le header/prototype
    Pas tout à fait (et j'en ai chié pour le découvrir). Si le paramètre est un pointeur, il est alors inutile pour le pointeur dans le prototype, mais reste obligatoire pour le pointé
    Exemple
    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
    #include <stdio.h>
     
    // Prototype fct
    void fct(const int* const);		// Le premier "const" (valeur pointée) est obligatoire, mais pas le second (le pointeur)
     
    void fct(const int* const n)		// Le premier "const" indique que la valeur pointée est constante (interdit d'écrire "*n=0"), et le second que le pointeur est constante (interdit d'écrire "n=NULL"). 
    {
    	printf("n=%d\n", *n);
    }
     
    int main() {
    	int n=5;
    	fct(&n);
    }
    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]

  11. #11
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Pas tout à fait (et j'en ai chié pour le découvrir). Si le paramètre est un pointeur, il est alors inutile pour le pointeur dans le prototype, mais reste obligatoire pour le pointé
    Oui, parce que c'est le pointeur qui est le paramètre copié, donc qu'il soit constant ou non n'est pas important pour l'appelant, alors que la valeur pointée si. On te fournit un pointeur, tu assures que sa valeur changera pas pendant l'appel.
    Et si tu passes plusieurs niveaux de pointeurs (**, ***, ...), même combat sur plusieurs niveaux.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  12. #12
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 690
    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 690
    Points : 30 985
    Points
    30 985
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Bousk Voir le message
    Oui, parce que c'est le pointeur qui est le paramètre copié, donc qu'il soit constant ou non n'est pas important pour l'appelant,
    Cela n'explique pas pourquoi ce n'est pas obligatoire dans le prototype même si on l'indique dans la fonction...

    Citation Envoyé par Bousk Voir le message
    Et si tu passes plusieurs niveaux de pointeurs (**, ***, ...), même combat sur plusieurs niveaux.
    Ah oui, je viens de constater...
    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
    #include <stdio.h>
     
    void fct(const int* const * /*const */);
     
    void fct(const int* const* const n) {
    	// n=NULL => interdit à cause du dernier "const"
    	// *n=NULL => interdit à cause du "const" milieu
    	// **n=0 => interdit à cause du premier "const"
    	printf("n=%d\n", **n);
    }
     
    int main() {
    	int i;
    	i=5;
    	int *pt=&i;
    	fct((const int **)&pt);
    }
    ... et j'ai même été obligé de caster à l'appel...
    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]

  13. #13
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 630
    Points : 10 556
    Points
    10 556
    Par défaut
    Effectivement, le const permet de dire que le paramètre ne sera pas modifié à l'intérieur de la fonction
    Mais, est-ce bien utile pour 1 fonction power : c'est 1 puissance a^b.

    Et désolé, si je viens de pourrir ce fil de discussion avec ma remarque

    Citation Envoyé par Sve@r Voir le message
    Pas tout à fait (et j'en ai chié pour le découvrir). Si le paramètre est un pointeur, il est alors inutile pour le pointeur dans le prototype, mais reste obligatoire pour le pointé
    C'est 1 grand classique des recruteurs en C++ lorsque dans le QCM, tu as 1 question du style la différence entre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    void dummy01(int* prt);
    void dummy02(const int* prt); // ici c'est le pointé qui est constant
    void dummy03(int const * prt); // ici c'est le pointeur qui est constant
    void dummy04(int* const prt) ; // ici c'est la variable qui est constante
    void dummy05(const int* const prt) const; // ici le pointé, la variable et la fonction sont constants
    void dummy06(const int const * const prt) const; // ici tout est constant
    void dummy07(int const & prt); // ici c'est la référence qui est constante
    void dummy08(int const & prt) const; // ici c'est la référence et la fonction qui sont constantes
    void dummy08(const int& prt); // ici c'est le pointé qui est constant
    // ...
    Citation Envoyé par Sve@r Voir le message
    ... et j'ai même été obligé de caster à l'appel...
    En C++ tu as le const cast justement : fct( const_cast<int **>(&pt) );.

  14. #14
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 565
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

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

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 565
    Points : 7 648
    Points
    7 648
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Cela n'explique pas pourquoi ce n'est pas obligatoire dans le prototype même si on l'indique dans la fonction...


    Ah oui, je viens de constater...
    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
    #include <stdio.h>
     
    void fct(const int* const * /*const */);
     
    void fct(const int* const* const n) {
    	// n=NULL => interdit à cause du dernier "const"
    	// *n=NULL => interdit à cause du "const" milieu
    	// **n=0 => interdit à cause du premier "const"
    	printf("n=%d\n", **n);
    }
     
    int main() {
    	int i;
    	i=5;
    	int *pt=&i;
    	fct((const int **)&pt);
    }
    ... et j'ai même été obligé de caster à l'appel...
    Le const concernant la variable transmise ne joue aucun rôle pour l'appelant, il n'a de sens que dans corps de la fonction. La syntaxe nous amène ce cas qui d'ailleurs est traité de la même manière en C++.

    Le cast que tu as dû faire est lui particulier au C. Pour ceux qui comme moi travaillent aussi en C++, les 2 langages ne gèrent pas les conversions avec des const avec la même "tolérance". Le C++ est plus intrangisant sur les conversions douteuses mais ici le cast y est inutile.
    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
    void fct_nC(const int* * const N); //ou fct_nC(const int* * n)
    void fct_CC(const int* const* const N); //ou fct_CC(const int* const* n)
    void fct_Cn(int* const* const N); //ou fct_Cn(int* const* n)
     
    const int  I = 4;
    const int*  pT = &I;
    fct_nC( &pT );   // valide en C et C++, mêmes types
    fct_CC( &pT );   // valide en C et C++, ajout de const au 1er pointé
    fct_Cn( &pT );   // warning en C, error en C++, perte de const au 2nd pointé
     
    int  j = 5;
    int* pt = &j;
    fct_nC( &pt );   // warning en C, error en C++ (pas facile de voir pourquoi mais les 2 ont raison)
    fct_CC( &pt );   // warning en C, valide en C++ (pourtant il n'y a aucun problème)
    fct_Cn( &pt );   // valide en C et C++, ajout de const au 1er pointé
    La règle en C est: Au niveau zéro de la variable le const peut apparaître/disparaître, au premier niveau pointé le const peut apparaître, les autres niveaux doivent être identiques.
    La règle en C++ est plus subtile à interpréter: tout ce qui peut amener à modifier une constante directement ou indirectement est interdit, le reste est autorisé. C'est du pur bon sens.

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

Discussions similaires

  1. Problème avec une fonction
    Par mademoizel dans le forum Général JavaScript
    Réponses: 6
    Dernier message: 24/06/2006, 10h51
  2. problème avec une fonction javaScript
    Par volthur dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 16/05/2006, 18h04
  3. Problème avec une fonction utilisateur !
    Par nalou dans le forum MS SQL Server
    Réponses: 4
    Dernier message: 20/04/2006, 17h06
  4. Problème avec une fonction et un array
    Par Neal Morse dans le forum Général JavaScript
    Réponses: 1
    Dernier message: 28/08/2005, 12h04
  5. Problème avec une fonction date.
    Par kmayoyota dans le forum ASP
    Réponses: 8
    Dernier message: 09/09/2004, 12h33

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