Partage
  • Partager sur Facebook
  • Partager sur Twitter

La fonction Scanf

    29 octobre 2019 à 16:05:34

    Bonjour, 

    Je tente de realiser un petit programme qui prend en compte une chaine de caractere a rentrer par l'utilisateur de max 30 characteres et minimum 3, cependant dès que je lance le programme, j'ai une erreur sur la fonction du scanf, je peux correctement rentrer un mot, mais le programme plante directement apres avoir cliqué sur entrer, sans segfault.

    Si quelqu'un a une idée je suis preneur, voici le code : 

    char *createword(int i)
    {
        int lol;
        lol = 0;
    char nom[31];
        ft_isblank();
        printf("Parfait!, maintenant le Joueur 1 va devoir rentrer un mot de longueur maximum %d lettres : ", i);
        scanf("%s", nom);
    	printf("Test-1");
        while((ft_strlen(nom) <= 3) || (ft_strlen(nom) >= i))
        {
            if(ft_strlen(nom) <= 3)
            {
                printf("%s ne fait pas au minimum 3 lettres, veuillez reessayer : ", nom);
                scanf("%s", nom);
            }
    	printf("TEst0");
            if(ft_strlen(nom) >= i)
            {
                printf("%s est plus long que la limite de lettres, veuillez reessayer : ", nom);
                scanf("%s", nom);
            }
        }



    • Partager sur Facebook
    • Partager sur Twitter
      29 octobre 2019 à 16:32:28

      Hello,

      Comme tu n'as pas mis tout le code de ta fonction, je suppose que tu fais un return(nom) à la fin de la fonction. Or nom[ ] est local à la fonction, et cesse d'exister lorsque la fonction est quittée. D'où le plantage.

      La bonne méthode (sans allocation dynamique), c'est de passer le tableau à la fonction.

      Edit:

      • emploie des noms de variables corrects. Par exemple, i → longueur_maximum, nom → mot
      • évite le franglais: createword et nom

      -
      Edité par edgarjacobs 29 octobre 2019 à 16:41:09

      • 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

        31 octobre 2019 à 15:36:04

        Merci beaucoup, mais le soucis c'est que la fonction bloque avant meme le retour, c'est dès que je tente le scanf en chaine de caractere que ca bloque.


        Voici mon code en entier (enfin le debut de ce fameux code )

        #include <string.h>
        #include <stdlib.h>
        #include <stdio.h>
        
        void ft_isblank(void)
        {
            printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
        }
        
        int ft_strlen(char *str)
        {
            int i;
            i = 0;
            while(str[i])
            {
                i++;
            }
            return(i);
        }
        
        int ftnomisword(char *str)
        {
            int i;
            i = 0;
            while(str[i])
            {
                if(!((str[i] >= 'a' && str[i] <= 'z') || (str[i] >= 'A' && str[i] <= 'Z')))
                    return(2);
            }
            return(8);
        }
        
        char *createword(int i)
        {
            int i = 0;
            char *nom;
            nom = malloc(sizeof(char) * 31)
            ft_isblank();
            printf("Parfait!, maintenant le Joueur 1 va devoir rentrer un mot de longueur maximum %d lettres : ", i);
            scanf("%s", nom);
            while((ft_strlen(nom) <= 3) || (ft_strlen(nom) >= i))
            {
                if(ft_strlen(nom) <= 3)
                {
                    printf("%s ne fait pas au minimum 3 lettres, veuillez reessayer : ", nom);
                    scanf("%s", nom);
                }
                if(ft_strlen(nom) >= i)
                {
                    printf("%s est plus long que la limite de lettres, veuillez reessayer : ", nom);
                    scanf("%s", nom);
                }
            }
            while(ftnomisword(nom) == 2)
            {
                printf("ERREUR\nTon mot ne doit pas contenir d'espace ou de caracteres speciaux, reessaye : ");
                scanf("%s", nom);
            }
            printf("Parfait! Voici le mot a deviner : %s\nTape entree pour commencer la partie !\n", nom);
            scanf("%d", &i);
            return(*nom);
        }
        
        int main(void)
        {
            int i;
            i = 0;
            ft_isblank();
            printf("---Bienvenue au jeu du PENDU !---\n");
            printf("Premierement, veuillez fixer une limite de lettre pour le mot a deviner : ");
            while(!(i <= 30 && i > 2))
            {
                scanf("%d", &i);
                if(i <= 2)
                {
                    ft_isblank();
                    printf("Humm, %d est trop petit, tu dois rentrer au minimum 3, Reessaye : ", i);
                }
                if(i > 30)
                {
                    ft_isblank();
                    printf("Humm, %d est trop grand, tu dois rentrer au maximum 30, Reessaye : ", i);
                }
            }
            ft_isblank();
            printf("%s\n", createword(i));
        }
        



        • Partager sur Facebook
        • Partager sur Twitter
          31 octobre 2019 à 15:42:46

          C'est parce que le scanf avec une chaine de caractère est spéciale tu dois mettre un

          fflush(stdin);

          entre ton printf et scanf pour les chaines de caractère pour effacer la mémoire cache à chaque fois.

          Sinon ça plante et n'oublie pas le "&" dans ton scanf aussi avant le nom de ta variable ça devrait mieux fonctionner...

           comme ci-dessous :

          printf("%s ne fait pas au minimum 3 lettres, veuillez reessayer : ", nom);
          fflush(stdin);
          scanf("%s",&nom);
          • Partager sur Facebook
          • Partager sur Twitter
            31 octobre 2019 à 15:52:57

            38rom1 a écrit:

            C'est parce que le scanf avec une chaine de caractère est spéciale tu dois mettre un

            fflush(stdin);

            entre ton printf et scanf pour les chaines de caractère pour effacer la mémoire cache à chaque fois.

            Sinon ça plante et n'oublie pas le "&" dans ton scanf aussi avant le nom de ta variable ça devrait mieux fonctionner...

             comme ci-dessous :

            printf("%s ne fait pas au minimum 3 lettres, veuillez reessayer : ", nom);
            fflush(stdin);
            scanf("%s",&nom);


            Non et non

            1) on ne fflush() pas stdin, cela peut amner un comportement indéterminé

            2) nom est déjà une adresse, c'est une erreur d'envoyer l'adresse de nom à scanf()

            Par contre, voir ici

            Pour le problème: pas return(*nom) !

            -
            Edité par edgarjacobs 31 octobre 2019 à 15:56:29

            • 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

              31 octobre 2019 à 16:11:09

              Quand je tente de mettre une `&` jai directement un segfault, le fflush(stdin); ne fonctionne pas non plus..

              Je vous avoue que je suis pas mal perdu jai du mal a comprendre le probleme.... 

              • Partager sur Facebook
              • Partager sur Twitter
                31 octobre 2019 à 16:18:57

                edgarjacobs a écrit:

                38rom1 a écrit:

                C'est parce que le scanf avec une chaine de caractère est spéciale tu dois mettre un

                fflush(stdin);

                entre ton printf et scanf pour les chaines de caractère pour effacer la mémoire cache à chaque fois.

                Sinon ça plante et n'oublie pas le "&" dans ton scanf aussi avant le nom de ta variable ça devrait mieux fonctionner...

                 comme ci-dessous :

                printf("%s ne fait pas au minimum 3 lettres, veuillez reessayer : ", nom);
                fflush(stdin);
                scanf("%s",&nom);


                Non et non

                1) on ne fflush() pas stdin, cela peut amner un comportement indéterminé

                2) nom est déjà une adresse, c'est une erreur d'envoyer l'adresse de nom à scanf()

                Par contre, voir ici

                Pour le problème: pas return(*nom) !

                -
                Edité par edgarjacobs il y a 14 minutes


                effectivement je n'ai pas prêté attention à l'adressage déjà présent pour le nom..

                cependant pour se qui est du fflush je suis en IUT Informatique et durant mes cours de C on nous apprends à utiliser le fflush(stdin); pour nos scanf  seulement pour les chaines de charactère qui sans eux ne fonctionne pas... Donc je ne vois pas qu'elle autre solution peut-être utilisé ? Si vous l'avez pouvez-vous me la faire parvenir je serais très curieux de la connaître. J'aimerais également savoir quels sont les comportement indéterminé que cela apporte ?

                • Partager sur Facebook
                • Partager sur Twitter
                  31 octobre 2019 à 16:36:18

                  norme c11

                  2 If stream points to an output stream or an update stream in which the most recent operation was not input, the fflush function causes any unwritten data for that stream to be delivered to the host environment to be written to the file; otherwise, the behavior is undefined.


                  38rom1 a écrit:

                  J'aimerais également savoir quels sont les comportement indéterminé que cela apporte ?

                  Puisque le comportement est indéterminé, comment prévoir :p

                  38rom1 a écrit:

                  Donc je ne vois pas qu'elle autre solution peut-être utilisé ? Si vous l'avez pouvez-vous me la faire parvenir je serais très curieux de la connaître

                  Une fonction qui se trouve des centaines de fois sur ce forum, pour vider le buffer clavier
                  void fct(void) {
                      int c;
                  
                      while((c=getchar())!=EOF && c!='\n');
                  }



                  -
                  Edité par edgarjacobs 31 octobre 2019 à 16:39:33

                  • 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

                    31 octobre 2019 à 16:51:12

                    Je viens d'essayer en remplacant les scanf par des fgets, mais toujours le meme probleme, si quelquun comprend... J'ai aussi essayé de vider le buffer clavier, mais rien a faire toujours le meme probleme... 

                    Je rebalance le code si quelquun a une nouvelle idee..

                    Merci encore :)

                    #include <string.h>
                    #include <stdlib.h>
                    #include <stdio.h>
                    
                    void ft_isblank(void)
                    {
                        printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
                    }
                    
                    int ft_strlen(char *str)
                    {
                        int i;
                        i = 0;
                        while(str[i])
                        {
                            i++;
                        }
                        return(i);
                    }
                    
                    int ftnomisword(char *str)
                    {
                        int i;
                        i = 0;
                        while(str[i])
                        {
                            if(!((str[i] >= 'a' && str[i] <= 'z') || (str[i] >= 'A' && str[i] <= 'Z')))
                                return(2);
                        }
                        return(8);
                    }
                    
                    char *createword(int i)
                    {
                        int u = 0;
                        char *nom;
                        nom = malloc(sizeof(char) * 31);
                        ft_isblank();
                        printf("Parfait! Maintenant le Joueur 1 va devoir rentrer un mot de longueur maximum %d lettres : ", i);
                        fgets(nom, 31, stdin);
                        while((ft_strlen(nom) <= 3) || (ft_strlen(nom) >= i))
                        {
                            if(ft_strlen(nom) <= 3)
                            {
                                printf("%s ne fait pas au minimum 3 lettres, veuillez reessayer : ", nom);
                                fgets(nom, 31, stdin);
                            }
                            if(ft_strlen(nom) >= i)
                            {
                                printf("%s est plus long que la limite de lettres, veuillez reessayer : ", nom);
                                fgets(nom, 31, stdin);
                            }
                        }
                        while(ftnomisword(nom) == 2)
                        {
                            printf("ERREUR\nTon mot ne doit pas contenir d'espace ou de caracteres speciaux, reessaye : ");
                            fgets(nom, 31, stdin);
                        }
                        printf("Parfait! Voici le mot a deviner : %s\nTape entree pour commencer la partie !\n", nom);
                        scanf("%d", &u);
                        return(nom);
                    }
                    
                    int main(void)
                    {
                        int i;
                        i = 0;
                        ft_isblank();
                        printf("---Bienvenue au jeu du PENDU !---\n");
                        printf("Premierement, veuillez fixer une limite de lettre pour le mot a deviner : ");
                        while(!(i <= 30 && i > 2))
                        {
                            scanf("%d", &i);
                            if(i <= 2)
                            {
                                ft_isblank();
                                printf("Humm, %d est trop petit, tu dois rentrer au minimum 3, Reessaye : ", i);
                            }
                            if(i > 30)
                            {
                                ft_isblank();
                                printf("Humm, %d est trop grand, tu dois rentrer au maximum 30, Reessaye : ", i);
                            }
                        }
                        ft_isblank();
                        printf("%s\n", createword(i));
                    }
                    



                    • Partager sur Facebook
                    • Partager sur Twitter
                      31 octobre 2019 à 16:52:20

                      la fonction ftnomisword va tourner en boucle infinie ...

                      -
                      Edité par magma 31 octobre 2019 à 16:53:53

                      • Partager sur Facebook
                      • Partager sur Twitter
                        31 octobre 2019 à 17:03:54

                        :)

                        Cetait si con!

                        Merci beaucoup je viens de rectifier ca et ca fonctionne :)



                        -
                        Edité par JosephCluzet 31 octobre 2019 à 17:04:43

                        • Partager sur Facebook
                        • Partager sur Twitter

                        La fonction Scanf

                        × 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