Partage
  • Partager sur Facebook
  • Partager sur Twitter

[Scanf] Questions diverses

    4 novembre 2006 à 14:42:45

    Bonjour vous ^^

    Alors aujourd'hui je me suis mis en quête d'informations pour comprendre le fonctionnement de la fonction Scanf, on voit partout que c'est pas bien, et patati et patata :D

    Je suis donc tombé sur ce Tutoriel expliquant assez bien sa fonction et les risques encourus par l'utilisation d'une telle fonction ^^

    Mais, bon pour moi pas mal de truc reste flous et je viens donc réclamer votre aide (On veut de l'aide, on veut de l'aide ! :lol: )

    Déjà une petite précision que je souhaiterais avoir: quel est la définition exacte de "flux"

    Citation : Tutoriel Scanf

    Cette fonction de la librairie standard prend en paramètre une chaîne de caractères décrivant le format du flux entrant "attendu"



    J'ai compris en gros ce que c'était mais j'aimerais bien une petite définition plus précise :)

    Ensuite une autre précision: buffer overflow, c'est bien un dépassement de la mémoire, une fuite?
    J'ai lu aussi que certaines personne pouvait retourner ce BO contre le programme? C'est à dire?


    Ensuite viens un passage dont je n'ai pas compris l'intêret:

    Citation : Tutoriel Scanf

    Si vous avez été attentifs, vous avez sûrement noté quel outil va nous permettre d'assurer ces contrôles. Il s'agit bien sûr du flag "taille" que l'on peut glisser entre le signe '%' et le formateur indiquant la conversion.

    Ainsi, lorsque vous allouez de la place en mémoire pour recevoir la chaîne de caractères (que ce soit statiquement ou dynamiquement), il vous faut conserver cette taille afin de la réutiliser dans ce champ taille, et ainsi sécuriser la saisie.

    On peut procéder de plusieurs façons pour positionner la taille dans la chaîne de formatage.
    Si vous avez déclaré un tableau de caractère de manière statique :



    char tab[80];


    Citation : Tutoriel Scanf

    La meilleure façon de faire dans ce cas là est de définir, via une macro, la longueur du tableau.
    Ainsi, cela devient :



    #define TAILLE 80
    <...>
    char tab[TAILLE+1] = {0}; /* +1 pour le caractere terminal */


    Citation : Tutoriel Scanf

    Puis, on utilise une astuce du préprocesseur (il suffit de lire la doc de CPP pour la connaître ;-)



    #define xstr(s) str(s)
    #define str(s) #s


    Citation : Tutoriel Scanf

    Ces macros nous permettent de transformer en chaîne de caractère des macros en les expansant d'abord.
    On peut donc l'utiliser ainsi :



    scanf("%"xstr(TAILLE)"s", tab);


    Citation : Tutoriel Scanf

    Si on passe uniquement le préprocesseur sur ce morceau de code, on observe que cpp a transormé cette notation en :



    scanf("%""80""s", tab);


    Citation : Tutoriel Scanf


    Ce qui équivaut à :



    scanf("%80s", tab);


    Citation : Tutoriel Scanf

    On a donc fait une saisie de chaîne de caractère déjouant le piège du buffer overflow. La même astuce peut être utilisée pour le formateur '%c', ainsi que pour tout autre nécessitant un contrôle.



    J'ai pas bien compris ce passage: Quel est l'intérêt de se compliquer la vie à utiliser des macros et autre pour au final arriver au même résultat: une saisie qui ne dépasseras pas 50 caractères.
    Je suis sur que c'est tout bête mais moi aussi je suis tout bête :euh::p


    Ensuite viens le passage avec getchar();

    Citation : Tutoriel Scanf


    La manière standard de vider le flux entrant est la suivante :



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


    J'ai pas bien compris comment fonctionnais cette boucle en While ^^


    Je vous donne le programme complet ^^


    #include <stdio.h>

    int main(void){

      int nombre = 0;
      int ok = 0;
      int retour;

      printf("saisissez un nombre :\n");
      while (!ok){

        retour = scanf("%d%*[^\n]", &nombre);
        printf("retour : %d\n", retour);
        if ( !retour ){
          /* erreur de saisie, on vide le flux */
          int c;
          while ( ((c = getchar()) != '\n') && c != EOF);

          printf("on vous a demande de saisir un nombre\n");
          printf("veuillez recommencer :\n");
        }
        else {
          /* reussite de la saisie */
          getchar(); /* on enleve le '\n' restant */

          printf("saisie acceptee\n");
          ok = 1/* sort de la boucle */
        }

      }

      return 0;
    }


    Et une autre chose dans ce programme...
    On utilise getchar(); , à la fin pour enlever le '\n' restant... Comment ça fonctionne?
    Je croyais que getchar(); attendais qu'on rentre une saisie et qu'on appuie sur entrer, or là, getchar(); ne demande rien et supprime le '\n' o_O
    Je sais que si j'en met à une deuxième alors là ça me demanderas de renter une saisie :)
    Comment expliquer ce comportement (liens vers tutoriels bienvenu aussi xD ), comment savoir quand ça va se produire?


    Merci d'avance pour vos réponses ^^
    Et pardon si j'ai dis une connerie quelque part ^^
    • Partager sur Facebook
    • Partager sur Twitter
      4 novembre 2006 à 14:56:17

      Citation : Pas de titre

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



      J'ai pas bien compris comment fonctionnais cette boucle en While ^^


      getchar() lit les caractères dans stdin jusqu'à rencontré le caractère '\n' (qui est la touche entrée si çà viens du clavier par ex) ou la fin du fichier (EOF = End Of File) (ou peut être simplement du flux)

      Citation : Pas de titre

      On utilise getchar(); , à la fin pour enlever le '\n' restant... Comment ça fonctionne?
      Je croyais que getchar(); attendais qu'on rentre une saisie et qu'on appuie sur entrer, or là, getchar(); ne demande rien et supprime le '\n' o_O


      en faite getchar() n'attends pas une saisie, il lit le caractère qui viens dans stdin, et si c'est vide, il bloque le programme jusqu'à avoir son caractère.
      • Partager sur Facebook
      • Partager sur Twitter
        4 novembre 2006 à 15:03:10

        Merci pour ces réponses, mais c'est quoi exactement stdin?

        merci :p
        • Partager sur Facebook
        • Partager sur Twitter
          4 novembre 2006 à 15:12:04

          Citation : diacred

          Merci pour ces réponses, mais c'est quoi exactement stdin?


          le flux d'entrée d'un programme (lien)
          • Partager sur Facebook
          • Partager sur Twitter
            4 novembre 2006 à 15:14:20

            Merci je vais voir :)

            Z'auriez pas un lien vers une explication exacte de comment fonction getchar(); ?
            Merci :)
            • Partager sur Facebook
            • Partager sur Twitter
              4 novembre 2006 à 15:46:09

              Citation : diacred


              Alors aujourd'hui je me suis mis en quête d'informations pour comprendre le fonctionnement de la fonction Scanf, on voit partout que c'est pas bien, et patati et patata


              Tu as raison de chercher à comprendre, c'est bien. Au fait, C'est scanf(), pas Scanf(). Je rappelle que le langage C est sensible à la casse.

              Citation : Pas de titre


              Je suis donc tombé sur ce Tutoriel expliquant assez bien sa fonction et les risques encourus par l'utilisation d'une telle fonction ^^


              Bon lien. OK. Mais il nécessite une bonne connaissance des bases du langage C...

              Citation : Pas de titre

              Déjà une petite précision que je souhaiterais avoir: quel est la définition exacte de "flux"


              ... comme ça, par exemple.

              Un flux est un moyen par lequel un programme écrit en C communique avec l'extérieur. C'est un conduit permettant de transférer des suites de char soit de l'extérieur vers le programme (flux entrants), soit du programme vers l'extérieur (flux sortants).

              Lorsque qu'un programme écrit en C démarre, 3 flux sont ouverts en mode texte par défaut :
              • stdin
              • stdout
              • stderr


              stdin est le flux entrant par défaut (généralement connecté à la partie clavier de la console)
              stdout est le flux sortant par défaut (généralement connecté à la partie écran de la console) pour les messages 'normaux'
              stderr est le flux sortant par défaut (généralement la console) pour les messages d'erreur.

              Citation : Pas de titre

              Ensuite une autre précision: buffer overflow, c'est bien un dépassement de la mémoire, une fuite?



              C'est un dépassement de tableau. Par exemple, si tu définis un tableau de 5 char :
                 char tab[5];

              tu peux écrire/lire de tab[0] à tab[5-1], c'est à dire tab[4]. (0 à 4, ça fait bien 5 cases). Mais si tu écris en 5 ou au-delà, et c'est techniquement possible car le C ne contrôle rien du tout, le comportement est indéfini.

              Cette possibilité d'accéder au-delà des limites d'un tableau, voire n'importe où avec un pointeur que l'on modifierait à volonté est (mal) appelée Buffer Overflow (en gros, Dépassement Mémoire, le terme Memory Overflow eut donc été plus adapté, mais le langage journalistique prend le pas sur le langage technique...).

              Citation : Pas de titre

              J'ai lu aussi que certaines personne pouvait retourner ce BO contre le programme? C'est à dire?


              Un BO est un bug grave et effectivement une technique de malveillant utilisée pour 'bricoler en mémoire'. (Voir The Big Internet Worm).

              Citation : Pas de titre

              J'ai pas bien compris ce passage: Quel est l'intérêt de se compliquer la vie à utiliser des macros et autre pour au final arriver au même résultat: une saisie qui ne dépasseras pas 50 caractères.



              A écrire du code plus facile à maintenir. Le but est que la définition de la taille soit unique. Comme ça, si elle doit être modifiée (un code, ça évolue : changement de spécification, correction de bug, optimisation...), on le fait en un seul endroit du programme, et la modification est automatiquement reportée partout où c'est nécessaire par une simple recompilation.

              2 avantages immédiats :
              • Une maintenance du code plus rapide.
              • Un code comportant moins d'erreurs.

              Citation : Pas de titre


              Ensuite viens le passage avec getchar();

              Citation : Tutoriel Scanf


              La manière standard de vider le flux entrant est la suivante :



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



              J'ai pas bien compris comment fonctionnais cette boucle en While ^^


              Déjà, et pour tes questions suivantes, il faut comprendre le fonctionnement de getchar() qui n'est pas trivial. Je recommande de lire ceci :

              http://mapage.noos.fr/emdel/notes.htm#fgetc

              Ensuite, pose des questions si tu ne comprends toujours pas.
              • Partager sur Facebook
              • Partager sur Twitter
              Music only !
                4 novembre 2006 à 16:14:19

                Han, ça c'est de la réponse, merci beaucoup :p

                Sinon je te cite :

                Citation : -ed-

                Mais il nécessite une bonne connaissance des bases du langage C...



                Si tu as un lien avec des renseignements concernant les bases plus précis que les cours de m@teo21 je suis preneur (car dieu sait qu'il en manque des trucs dans ses cours ^^ )

                Merci pour le lien pour getchar(); je cherchais justement un lien pour en savoir plus sur cette fonction :) en plus ça à l'air vachement complet, même sur d'autres sujets ^^

                Merci :p
                • Partager sur Facebook
                • Partager sur Twitter
                  4 novembre 2006 à 16:18:37

                  Citation : diacred


                  Sinon je te cite :

                  Citation : -ed-

                  Mais il nécessite une bonne connaissance des bases du langage C...



                  Si tu as un lien avec des renseignements concernant les bases plus précis que les cours de m@teo21 je suis preneur (car dieu sait qu'il en manque des trucs dans ses cours ^^ )



                  Il y a des liens sur mon site...

                  Citation : Pas de titre


                  Merci pour le lien pour getchar(); je cherchais justement un lien pour en savoir plus sur cette fonction :) en plus ça à l'air vachement complet, même sur d'autres sujets ^^


                  Be my guest...
                  • Partager sur Facebook
                  • Partager sur Twitter
                  Music only !

                  [Scanf] Questions diverses

                  × 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