Partage
  • Partager sur Facebook
  • Partager sur Twitter

Initialiser une variable avec la valeur 'NULL'

Sujet résolu
    13 juin 2022 à 20:22:11

    Bonjour J'ai un problème quant à l'initialisation de mes variable avec NULL.

    #include <stdio.h>
    #include <stdlib.h>
    
    int main(int argc, char *argv[]) {
    
    int nombre = NULL;
    
    return 0;
    }
    
    
    


    Me renvoie l'erreur ci-dessous

    gcc main.c -o -wall main
    main.c: In function ‘main’:
    main.c:6:22: warning: initialization of ‘int’ from ‘void *’ makes integer from pointer without a cast [-Wint-conversion]
        6 |         int nombre = NULL;
          |                      ^~~~
    /usr/bin/ld: cannot find main: No such file or directory
    collect2: error: ld returned 1 exit status

    Merci de vos réponses ;)

    -
    Edité par Nurvenco 13 juin 2022 à 20:24:36

    • Partager sur Facebook
    • Partager sur Twitter
      13 juin 2022 à 20:28:57

      nombre est un entier de type int tu ne peux donc pas l'initialiser à NULL qui ne peut être affecter qu'a un pointeur !
      • Partager sur Facebook
      • Partager sur Twitter
      ...
        13 juin 2022 à 20:36:09

        Hello,

        NULL est (parfois) déclaré en tant que pointeur, style #define NULL ((void *)0). Alors l'assigner à un integer provoque le message. Pourquoi ne pas écrire int nombre=0; ?

        • 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

          13 juin 2022 à 20:38:51

          D'accord je comprend mieux, je suis en train d'apprendre le C et c'étais un peu la confusion dans ma tête.

          Merci à vous deux !

          Ca m'amène à un second problème voici le code

          #include <stdio.h>
          #include <stdlib.h>
          #include <stddef.h>
          #include <string.h>
          
              int main(int argc, char *argv[]){
          
                  int n1 = 0, n2 = 0, resul = 0;
                  char carac;
          
                  printf("Donne moi une première valeur\n");
                  scanf("%d", &n1);
          
                  printf("Donne moi l'operateur (+\\-\\*\\/\\%%)\n");
                  scanf("%c", &carac);
          
                  printf("Donne moi une deuxième valeur\n");
                  scanf("%d", &n2);
          
          
                  printf("%d %c %d = ma bite", n1, carac, n2);
          
          
          
                  return 0;
              }


          Le code s'éxécute mais lorsque je rentre la première valeur il me demande directement les deux printf suivant d'affiler sans me laisser ecrire quel operateur je souhaite

          Je compile avec gcc

          gcc main.c -o -wall main

          Ca me renvoit cette erreur

          /usr/bin/ld: cannot use executable file 'main' as input to a link
          collect2: error: ld returned 1 exit status


          Je ne comprend pas..

          -
          Edité par Nurvenco 13 juin 2022 à 20:48:08

          • Partager sur Facebook
          • Partager sur Twitter
            13 juin 2022 à 21:48:04

            Ah, lire un caractère avec 'scanf'... J'ai essayé autrefois, et souvent (toujours ?) j'avais le même problème.

            Je ne sais plus exactement, mais c'est parce que pour saisir un caractère il faut taper "Entrée", or le caractère '\n' ne fait pas partie de la donnée saisie, contrairement au cas de la saisie d'un entier ou d'une chaîne de caractères, du coup il est laissé dans le tampon et lu au 'scanf' suivant, quelque chose comme ça.

            Suggestion : lire une chaîne :

            char operateur[2];         // un 'char' suivi de '\0'
            printf("Donne moi l'operateur (+\\-\\*\\/\\%%)\n");
            scanf("%1s", operateur);   // on lit une chaine de 1 caractère

            Mais je ne suis pas sûr que ça permette de contourner le problème.

            (Sinon il faut vider le tampon. C'est un grand classique des questions sur le C.)

            • Partager sur Facebook
            • Partager sur Twitter
              13 juin 2022 à 22:18:00

              Bonjour,

              Un moyen simple de vider du tampon le retour chariot qui restait de la saisie précédente, c'est d'écrire:

                      scanf(" %c", &carac);
              

              La différence avec ta ligne est infime, mais cette espace change beaucoup les choses.
               

              • Partager sur Facebook
              • Partager sur Twitter

              En recherche d'emploi.

                13 juin 2022 à 22:59:31

                J'ai regarder à vos deux réponse et en effet il fallait vidé le tampon sytème si j'ai bien compris, j'ai donc rajouter rewind(stdin) qui la vidé.

                Doc sur les tampons en C

                https://public.iutenligne.net/informatique/algorithme-et-programmation/priou/LangageC/622_gestion_du_tampon_par_scanf.html

                • Partager sur Facebook
                • Partager sur Twitter
                  14 juin 2022 à 0:03:54

                  rewind(stdin) est plutôt à éviter.

                  Deux raisons à cela:
                  - rewind(stdin) n'est pas portable. Donc pour certaines bibliothèques C cela ne fonctionnera pas.
                  - si stdin n'est pas directement sur une console, comme la redirection d'un flux ou d'un fichier, l'appeler aura une conséquence désastreuse.

                  On peut vider le buffer de manière portable en quelque lignes de code, et l'utilisation de l'espace est tout à fait portable et est suffisante dans les cas simples. Dans tous les cas, vider le buffer est surtout une bidouille liée au fait que scanf() est une fonction non adaptée à l'interaction avec un utilisateur. Le couple fgets()/sscanf() est bien plus sûr.

                  • Partager sur Facebook
                  • Partager sur Twitter

                  En recherche d'emploi.

                    14 juin 2022 à 0:46:10

                    Je vais aller voir les fonctions fgets()/sscanf() je ne les connais pas 

                    Au debut du topic on parler que seul les pointeurs peuvent avoir la valeur null mais comment ca se passe ? Je trouve pas de doc sur le sujet :/

                    • Partager sur Facebook
                    • Partager sur Twitter
                      14 juin 2022 à 8:14:48

                      • Partager sur Facebook
                      • Partager sur Twitter

                      Le Tout est souvent plus grand que la somme de ses parties.

                        14 juin 2022 à 10:38:52

                        Ce que dit la norme :

                        C11_n1570 écrit:

                        7.19 Common definitions <stddef.h>

                        ... The header <stddef.h> defines the following macros and declares the following types. Some are also defined in other headers, as noted in their respective subclauses. ...

                        The macros are NULL which expands to an implementation-defined null pointer constant; ...



                        • Partager sur Facebook
                        • Partager sur Twitter
                        ...
                          14 juin 2022 à 16:22:17

                          Dalfab a écrit:

                          Bonjour,

                          Un moyen simple de vider du tampon le retour chariot qui restait de la saisie précédente, c'est d'écrire:

                                  scanf(" %c", &carac);
                          

                          La différence avec ta ligne est infime, mais cette espace change beaucoup les choses.
                           

                          Ah oui, je m'en souviens ! C'est cette technique qu'il faut utiliser, pas besoin de chercher des choses plus compliquées.

                          • Partager sur Facebook
                          • Partager sur Twitter
                            14 juin 2022 à 20:01:32

                            Le problème c'est qu'il peut rester d'avantage de choses que le retour chariot ou des caractères "blancs" (espaces, tabulations) qui seront les seuls consommés par cette syntaxe.

                            Cette "astuce" ne traite donc qu'une partie du problème.

                            Par exemple, si je demande un int et que je tape 12,57, scanf() va s'arrêter à la virgule, qui va rester dans le tampon stdin avec tout ce qui va suivre, y compris le \n terminant la ligne.

                            Après chaque appel à scanf(), pour purger le tampon stdin, il suffit de faire :

                            {
                                int c;
                                while((c = getchar()) != '\n' && c != EOF)
                            		/* discard */ ;
                            }

                            http://c-faq.com/stdio/stdinflush2.html

                            On peut utiliser cela tel quel ou, mieux, se faire une fonction.

                            Le problème ne concerne pas juste scanf() qui est souvent décriée (voire honnie), c'est la même chose avec fgets() si la ligne qui est tapée dépasse la taille passée en paramètre, alors le reste va rester dans le tampon de la même manière.

                            Le cas où fgets() laisse des choses dans le tampon est, en fait, plus compliqué à gérer correctement, car ce n'est pas systématique.

                            Et dans le cas où la saisie ne dépasse pas la capacité passée à fgets(), un autre problème de cette fonction est qu'elle capture le \n dans la chaîne récupérée, ce qui n'est souvent pas souhaité et qu'il faut penser à retirer en modifiant la chaîne récupérée avant de pouvoir l'exploiter.

                            • Partager sur Facebook
                            • Partager sur Twitter
                              14 juin 2022 à 20:19:56

                              Disons que la solution de Dalfab fonctionne si l'utilisateur tape un truc correct.

                              Car rappelons qu'à l'origine, le programme de Nuvenco ne marche pas lorsque l'utilisateur tape un truc correct. Et c'est pour ça qu'il demandait de l'aide.

                              (Pour cette raison, je pense que la saisie rigoureuse est hors-sujet : ça ne va servir qu'à embrouiller.)

                              • Partager sur Facebook
                              • Partager sur Twitter
                                14 juin 2022 à 20:44:23

                                #include <stdio.h>
                                
                                int main()
                                {
                                    int nombre;
                                    char caractere;
                                
                                    scanf("%d%*[^\n]", &nombre);
                                    scanf(" %c", &caractere);
                                
                                    printf("%d %c", nombre, caractere);
                                
                                    return 0;
                                }
                                • Partager sur Facebook
                                • Partager sur Twitter
                                ...
                                  15 juin 2022 à 16:54:40

                                  @rouIoude : oui, c'est déjà mieux même si c'est un peu ésotérique ;-)

                                  @robun : si on veut faire simple, sans faire quelque chose de "rigoureux", alors il faut supposer que l'utilisateur est discipliné et fait ce qu'on lui demande de faire. Dans ce contexte limité, pour régler le problème des scanf() qui "sautent", on pourrait préférer se contenter de consommer le '\n' qui est sensé être juste après ce qu'a récupéré le scanf() avec un simple getchar().

                                  printf("Donne moi une première valeur\n");
                                  scanf("%d", &n1);
                                  getchar();

                                  cela permet de virer le '\n' tout de suite, au lieu de compter sur le fait de se rappeler l'éliminer dans le futur au prochain appel à scanf() en espérant ne pas oublier de précéder mes spécificateurs d'un espace vide.

                                  Bien sûr c'est juste une rustine juste pour que "çà marche".

                                  AMHA, les (vrais) programmes de ligne de commande qui attendent des saisies d'utilisateurs, il n'y en pas pas tant que cela. Ce n'est pas pratique (difficilement scriptable). Les inputs utilisateurs sont la plupart du temps limités à des options de ligne de commande (ou ce sont des démons et ils interagissent via le réseau), et s'il y a vraiment une interaction à gérer à l'écran on devrait penser à utiliser des choses plus robustes que les fonctions standard (du genre getline() sur les systèmes POSIX ou carrément une bibliothèque comme ncurses si on a une TUI à gérer).

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    15 juin 2022 à 17:40:21

                                    Il faut se mettre dans le contexte, ici on a affaire à un débutant qui fait des exercices de débutant. Il n'a pas encore vue les saisies sécurisés.

                                    Tous les cours de C pour débutant utilises scanf pour les saisies (même le cours très recommandé de ZDS).

                                    Et bien sur le '\n' laissé par la saisie d'un entier "%d" revient souvent quant le gars veux saisir un caractère ensuite (char) "%c".

                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                    ...
                                      15 juin 2022 à 17:41:47

                                      Nurvenco a écrit:

                                      Je compile avec gcc

                                      gcc main.c -o -wall main

                                      Ca me renvoit cette erreur

                                      /usr/bin/ld: cannot use executable file 'main' as input to a link
                                      collect2: error: ld returned 1 exit status


                                      Je ne comprend pas..

                                      -
                                      Edité par Nurvenco 13 juin 2022 à 20:48:08


                                      Tes options sont dans le désordre. 

                                      • l'option -o doit être suivie immédiatement du nom de fichier à fabriquer
                                      • avec ta commande, il faudrait fabriquer le fichier qui s'appellerait "-wall" à partir de main, qui se trouve être un exécutable. Ca va pas du tout. A sa place on protesterait aussi, avec le même message : on ne peut pas utiliser un exécutable comme entrée de l'édition des liens.
                                      • l'option pour les avertissements, c'est -Wall avec une majuscule
                                      La commande correcte c'est
                                      •   gcc -o main  -Wall  main.c
                                      •   ou toute autre permutation des trois éléments  "-o main"  "-Wall" "main.c"
                                      ---
                                      A propos de la lecture, une de mes idées fixes, c'est que si on cause avec un utilisateur en mode texte à coup de scanf printf, aller faire des getchar() c'est du bricolage maladroit. Tant pis pour vous, je ne peux pas résister :

                                      Le fonctionnement typique en "dialogue texte sur stdin/stout", c'est que quand le programme pose une question, l'utilisateur répond en tapant une LIGNE.

                                      Et donc la bonne approche, c'est de lire d'abord la LIGNE COMPLETE de réponse, et ENSUITE d'analyser son contenu pour voir si on peut en faire quelque chose.  Pas de lire un truc et se garder un bout de ligne pour plus tard, qu'on grignoterait peut être avec une boucle sur getchar != EOL.

                                      Donc typiquement getline ou readline, puis sscanf.

                                      Evidemment, jusqu'ici getline() c'est pas dans la bib standard C, ça serait trop facile, merci le comité de normalisation, mais bon, c'est dans POSIX depuis 2008. Et c'est quand même pas difficile à implémenter soi-même.



                                      -
                                      Edité par michelbillaud 15 juin 2022 à 17:58:29

                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        15 juin 2022 à 20:27:08

                                        michelbillaud a écrit:

                                        Evidemment, jusqu'ici getline() c'est pas dans la bib standard C, ça serait trop facile, merci le comité de normalisation, mais bon, c'est dans POSIX depuis 2008. Et c'est quand même pas difficile à implémenter soi-même.

                                        Pour un débutant qui ignore ce qu'est un pointeur et qui n'a sans doute jamais utilisé malloc() / realloc(), ça doit être extremement compliqué à écrire ;-)
                                        • 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

                                          15 juin 2022 à 23:26:46

                                          Ou alors on lit simplement dans un buffer jugé assez grand pour contenir une ligne tapée par l'utilisateur de taille raisonnable pour ce qui n'est qu'un exercice, genre 1Ko.

                                          -
                                          Edité par michelbillaud 15 juin 2022 à 23:27:31

                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                            16 juin 2022 à 2:07:23

                                            Et c'est quoi un "buffer"? Te répondrait le débutant ...
                                            Est-ce qu'ils comprennent ce qu'est un tableau de caractères Et une chaîne??
                                            • Partager sur Facebook
                                            • Partager sur Twitter

                                            Le Tout est souvent plus grand que la somme de ses parties.

                                              16 juin 2022 à 7:54:24

                                              Des qu'on a besoin de scanf, il vaut mieux au moins faire semblant de savoir ce qu'est une adresse.

                                              Pour les premiers exercices de débutant, il ne faut pas chercher à "securiser". Les moyens disponibles à ce niveau sont une galère que ce soit la boucle pour bouffer la fin de ligne ou les autres.

                                              Déjà que "sécuriser", ça voudrait dire avoir prealablement pris la peine de définir précisément le comportement du programme en cas de saisie invalide. 

                                              • Partager sur Facebook
                                              • Partager sur Twitter

                                              Initialiser une variable avec la valeur 'NULL'

                                              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                              × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                              • Editeur
                                              • Markdown