Partage
  • Partager sur Facebook
  • Partager sur Twitter

Vérifier le type d'un élément en c

    21 novembre 2023 à 22:05:34

    Salut, je suis débutant en language C et j'aimerais savoir comment vérifier le type d'un élément (  un int ou float ) en C par exemple comme en Python où on utilise la fonction type().
    • Partager sur Facebook
    • Partager sur Twitter
      21 novembre 2023 à 23:01:02

      Ce n'est pas possible en C.
      • Partager sur Facebook
      • Partager sur Twitter
      ...
        22 novembre 2023 à 10:44:20

        Une fonction comme la fonction type() en Python n'est pas utile en C, car le C est un langage fortement typé et typé statiquement : le code tel qu'il est écrit par le programmeur doit permettre au compilateur, au stade de la compilation, d'établir le type. Le programmeur sait (doit savoir) à tout instant quel est le type d'une variable donnée.

        Python est un langage typé dynamiquement, où on peut changer le type d'une variable.

        En fait, si tu expliquais quel est ton problème et ce que tu essayes de faire avec quelque chose d'équivalent à la fonction type() Python, on pourrait certainement mieux t'aider et ta question serait mieux posée car tu indiquerais pourquoi tu veux utiliser une fonction (et tu décrirais donc le problème que tu veux résoudre) au lieu de demander si une telle fonction existe (là tu ne fais que présumer que c'est une solution possible à un problème que tu ne décris pas).

        -
        Edité par Dlks 22 novembre 2023 à 15:24:48

        • Partager sur Facebook
        • Partager sur Twitter
          22 novembre 2023 à 21:44:27

          Salut,

          En effet, les types, c'est pour la compilation.

          Une fois compilé, il n'existe plus de types,  il n'y a que des adresses mémoire :)

          • Partager sur Facebook
          • Partager sur Twitter

          Recueil de code C et C++  http://fvirtman.free.fr/recueil/index.html

            24 novembre 2023 à 22:50:39

            Merci beaucoup pour la participation de chacun de vous et pour répondre à DIks je voulais juste gérer des erreur d'entrée. En effet je veux contraindre l'utilisateur à n'entrer que des chiffres donc je me disais qu'il fallait vérifier le type de l'entrée de l'utilisateur et c'est pourquoi j'avais poser ma question !
            • Partager sur Facebook
            • Partager sur Twitter
              24 novembre 2023 à 22:57:49

              VivienHounleba a écrit:

              .... et pour répondre à Dlks je voulais juste gérer des erreur d'entrée. En effet je veux contraindre l'utilisateur à n'entrer que des chiffres....

              Peut-être un début de réponse ici.

              Et il y a le retour de la fonction scanf() qui permet ce genre de contrôle. Exemple (extrêmement succint, il y a beaucoup à écrire sur les entrées clavier en C)

              #include <stdio.h>
              
              int main(void) {
              	int nbr;
              	fputs("Entrez un nombre: ", stdout);
              	if(scanf("%d", &nbr)!=1)
              		puts("Je voulais un nombre !");
              	else
              		printf("%d bien lu, merci\n,", nbr);
              	
              	return(0);
              }

              -
              Edité par edgarjacobs 24 novembre 2023 à 23:08:20

              • Partager sur Facebook
              • Partager sur Twitter

              On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent

                24 novembre 2023 à 23:37:17

                Une autre idée possible, c'est de lire une chaîne de caractères. Ensuite, on parcourt les caractères un par un et on vérifie qu'il n'y a que des chiffres. Si oui, on utilise 'sscanf' pour récupérer le nombre entier à partir de la chaîne. (Si non, on affiche un message d'erreur et on reboucle.)

                Algorithme :

                nombre : tableau de 'char'
                n      : entier <-- c'est le nombre qu'on veut récupérer
                nbreOK : booléen
                
                nbreOK = false <-- on n'a encore rien lu, donc le nombre n'est pas OK
                Tant-que pas nbreOK :
                    Affiche("Entrer un nombre : ")
                    scanf("%s", nombre)
                    Si Est_Numérique(nombre) :
                        nombreOK = true
                        sscanf(nombre, "%d", &n) <-- on met la chaîne dans 'n'
                    Sinon :
                        Affiche_Msg_erreur
                Fin Tant-que
                

                -
                Edité par robun 24 novembre 2023 à 23:37:41

                • Partager sur Facebook
                • Partager sur Twitter
                  26 novembre 2023 à 19:52:38

                  VivienHounleba a écrit:

                  En effet je veux contraindre l'utilisateur à n'entrer que des chiffres

                  Euh, à moins de menacer physiquement l'utilisateur, il tape ce qu'il veut, et même de fois pas tout à fait, donc c'est pas possible.

                  Donc il va falloir faire avec ce qu'il a tapé, c'est à dire

                  • vérifier que ce qu'il a tapé est conforme à ce qui est souhaitable
                  • s'occuper des cas où ce n'est pas conforme :  reposer la question, revenir en arrière, abandonner, ... ?
                  Et ce n'est pas du tout facile, surtout en C.  En plus on est dans un dialogue texte où, pour répondre, l'utilisateur tape une ligne terminée par un retour chariot
                  ---
                  Exemple, si l'idée c'est "il faudrait que l'utilisateur tape un entier entre 1 et 100", est-ce qu'on admet qu'il y ait des espaces avant/après le nombre ? (normalement oui)  Et si il y a d'autres caractères, genre 10à au lieu de 100 parce qu'il a raté la frappe ?
                  Bref il faudrait par exemple
                  • lire une ligne entière (voir getline())
                  • faire un sscanf sur la ligne du genre
                  int number;
                  char garbage;
                  
                  if (sscanf(line, "%d%c", &number, &garbage) == 1) {
                      // traitement de la réponse
                  } else {
                      // erreur
                  }
                  
                  sscanf retourne le nombre de trucs qui ont été lus avec succès dans la chaine. Si c'est 1, c'est qu'en décortiquant la ligne, on trouve un enter (%d) mais pas de caractère "non-space" (%c) ensuite.

                  C'est un peu pénible à spécifier et réaliser correctement (et dans un exercice de débutant on n'en demande pas tant).
                  Une autre solution, lecture caractère par caractère avec
                  • une boucle pour absorber les espaces de début de ligne
                  • une boucle pour construire le nombre à partir des caractères numériques (au moins 1)
                  • une boucle pour manger la fin de la ligne, en vérifiant que ce sont des espaces / la fin de ligne.

                  -
                  Edité par michelbillaud 26 novembre 2023 à 20:09:26

                  • Partager sur Facebook
                  • Partager sur Twitter
                    27 novembre 2023 à 19:08:29

                    Pour valider qu'une chaîne consiste en un entier, il est recommandé d'utiliser strtol(), ou strtoul() pour un entier non signé.

                    https://cplusplus.com/reference/cstdlib/strtol/

                    https://cplusplus.com/reference/cstdlib/strtoul/

                    https://wiki.sei.cmu.edu/confluence/display/c/ERR34-C.+Detect+errors+when+converting+a+string+to+a+number

                    exemple de code tiré du lien ci-dessus :

                    #include <errno.h>
                    #include <limits.h>
                    #include <stdlib.h>
                    #include <stdio.h>
                      
                    void func(const char *buff) {
                      char *end;
                      int si;
                     
                      errno = 0;
                     
                      const long sl = strtol(buff, &end, 10);
                     
                      if (end == buff) {
                        (void) fprintf(stderr, "%s: not a decimal number\n", buff);
                      } else if ('\0' != *end) {
                        (void) fprintf(stderr, "%s: extra characters at end of input: %s\n", buff, end);
                      } else if ((LONG_MIN == sl || LONG_MAX == sl) && ERANGE == errno) {
                        (void) fprintf(stderr, "%s out of range of type long\n", buff);
                      } else if (sl > INT_MAX) {
                        (void) fprintf(stderr, "%ld greater than INT_MAX\n", sl);
                      } else if (sl < INT_MIN) {
                        (void) fprintf(stderr, "%ld less than INT_MIN\n", sl);
                      } else {
                        si = (int)sl;
                     
                        /* Process si */
                      }
                    }

                    Pour le test "extra characters at the end of input", on peut modifier en :

                    if ('\0' != *end && '\n' != *end) {
                        (void) fprintf(stderr, "%s: extra characters at end of input: %s\n", buff, end);
                    }

                    pour qu'une chaîne saisie avec fgets() qui laisse traîner '\n' à la fin ne soit pas invalidée si le retour à la ligne n'a pas déjà été purgé.


                    -
                    Edité par Dlks 27 novembre 2023 à 19:16:00

                    • Partager sur Facebook
                    • Partager sur Twitter
                      27 novembre 2023 à 19:46:37

                      Si on l'appelle avec des espaces derrière

                      int main() {
                      	func("123   ");
                      	return 0;
                      }
                      

                      ça râle

                      123   : extra characters at end of input

                      alors que des espaces devant, non.  On accepte les espaces, ou pas ? :-)  j'ai l'impression que le boulot a été fait à moitié. C'est bien que quelqu'un à Carnegie Mellon fournisse du code pour valider qu'une chaine contient un entier parce que C ne le fait pas directement, encore faut-il se donner la peine de spécifier d'abord précisément ce qu'est une chaîne valide.

                      C'est pas très clair non plus de voir pourquoi il rejette les valeurs d'entiers qui rentrent dans un long mais pas un int (un test sur ERANGE suffirait, non ?)

                      -
                      Edité par michelbillaud 27 novembre 2023 à 20:04:56

                      • Partager sur Facebook
                      • Partager sur Twitter
                        27 novembre 2023 à 23:10:14

                        Salut michelbillaud,

                        Je pense que le code est conçu comme une démo des possibilités de validation de strtol() par rapport aux autres fonctions dont l'usage est découragé, pas comme une vraie fonction conçue pour avoir une utilité dans un code de production, sinon elle ne retournerait pas void, pareil pour les printf() qui ne servent pas à la fonction appelante.

                        La démo montre une application de strtol(), laquelle retourne un long dont on peut s'assurer que la capacité n'a pas été dépassée avec errno. Comme ce qu'on récupère avec strtol( est un entier long convertit à partir de la chaîne, le code montre aussi comment vérifier qu'on n'explose pas la capacité d'un int avant d'affecter le résultat de la conversion à un int, dans un cas de figure où on voudrait en fait récupérer un int.

                        C'est pas juste un gus à Carnegie Mellon qui a pondu ce wiki : https://wiki.sei.cmu.edu/confluence/display/c/History

                        • Partager sur Facebook
                        • Partager sur Twitter
                          28 novembre 2023 à 11:00:39

                          Dlks a écrit:

                          C'est pas juste un gus à Carnegie Mellon qui a pondu ce wiki : https://wiki.sei.cmu.edu/confluence/display/c/History


                          C'est pas une circonstance atténuante.  Au delà de l'idée de prévenir qu'il faut faire gaffe en validant des nombres, que scanf ne le fait absolument pas et qu'on doit pouvoir s'en tirer avec strtoXXX, annoncer fièrement une "compliant solution" sans dire par rapport à quel objectif exactement, c'est un peu léger.

                          Là ça vérifie que la chaine contient

                          • d'éventuels espaces (ignorés par strtol),
                          • la représentation correcte d'un nombre décimal (dans les limites des int),
                          • et immédiatement le caractère nul (pas d'espace ni de retour chariot, merci)
                          C'est plus clair dans la page de manuel linux (strtol)
                              #include <errno.h>
                                 #include <limits.h>
                                 #include <stdio.h>
                                 #include <stdlib.h>
                          
                                 int
                                 main(int argc, char *argv[])
                                 {
                                     int base;
                                     char *endptr, *str;
                                     long val;
                          
                                     if (argc < 2) {
                                         fprintf(stderr, "Usage: %s str [base]\n", argv[0]);
                                         exit(EXIT_FAILURE);
                                     }
                          
                                     str = argv[1];
                                     base = (argc > 2) ? atoi(argv[2]) : 0;
                          
                                     errno = 0;    /* To distinguish success/failure after call */
                                     val = strtol(str, &endptr, base);
                          
                                     /* Check for various possible errors. */
                          
                                     if (errno != 0) {
                                         perror("strtol");
                                         exit(EXIT_FAILURE);
                                     }
                          
                                     if (endptr == str) {
                                         fprintf(stderr, "No digits were found\n");
                                         exit(EXIT_FAILURE);
                                    }
                          
                                     /* If we got here, strtol() successfully parsed a number. */
                          
                                     printf("strtol() returned %ld\n", val);
                          
                                     if (*endptr != '\0')        /* Not necessarily an error... */
                                         printf("Further characters after number: \"%s\"\n", endptr);
                          
                                     exit(EXIT_SUCCESS);
                                 }
                          
                          Le commentaire indiquant que la présence de caractères après la représentation du nombre n'est pas nécessairement une erreur.  Ils ne prétendent pas "valider la chaine".

                          -
                          Edité par michelbillaud 28 novembre 2023 à 11:16:48

                          • Partager sur Facebook
                          • Partager sur Twitter
                            28 novembre 2023 à 11:59:00

                            Visiblement tu aimes bien critiquer.

                            Je te laisse à tes critiques (qui sont elles mêmes critiquables) car j'ai mieux à faire.

                            En tout était de cause, sur ce fil, proposer des moyens de vérification de la saisie de chiffres sans parler de strtol() et compagnie est une omission que je ne comprenais pas et que je souhaitais réparer. Cette fonction dispose de moyens bien supérieurs à sscanf() de validation.

                            • Partager sur Facebook
                            • Partager sur Twitter
                              28 novembre 2023 à 13:59:54

                              J'aime bien proposer des solutions aussi (ici, 2, voir plus haut).

                              Et j'insiste sur le fait que pour des petits exercices en C de débutant (*), faut pas trop s'embêter avec la validation des entrées, parce que c'est une galère à faire sérieusement pour les raisons énoncées plus haut ( la difficulté de spécifier d'abord ce qu'on veut verifier). Preuve en que même à CMU, une maison sérieuse, ils y arrivent pas. :-)

                              Et du coup, on perd l'objectif pédagogique, qui est du genre faire faire une boucle avec un calcul dedans.

                              (*) Du niveau "tapez une suite de nombres et le programme affiche la moyenne". À comparer avec le niveau de technicité en C du passage à strtol de l'adresse d'un pointeur....

                              -
                              Edité par michelbillaud 28 novembre 2023 à 14:11:39

                              • Partager sur Facebook
                              • Partager sur Twitter

                              Vérifier le type d'un élément en c

                              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                              • Editeur
                              • Markdown