Comprendre l'usage de STDIN ???

salmamk27 Messages postés 3 Date d'inscription   Statut Membre Dernière intervention   -  
salmamk27 Messages postés 3 Date d'inscription   Statut Membre Dernière intervention   -
Bien bonjour !
je viens de commencer les fichiers et j'ai trouvé un mot que je n'est pas colpris l'usage qui est :
printf("input a sentence for the file :");
fgets(str,sizeof str,stdin);
fprintf(fptr,"%s",str);
printf("the file (filesalma.txt) is created ");

STDIN ???

1 réponse

  1. [Dal] Messages postés 6122 Date d'inscription   Statut Contributeur Dernière intervention   1 108
     
    Bonjour salmamk27,

    fgets()
    est une fonction définie dans l'entête standard
    stdio.h
    et dont le prototype est le suivant :

    char * fgets ( char * str, int num, FILE * stream );

    cf. http://www.cplusplus.com/reference/cstdio/fgets/

    Son 3ème argument est un pointeur sur
    FILE
    permettant d'accéder à un flux de lecture.

    Puisque tu dis que étudies les fichiers, tu dois savoir qu'un tel pointeur sur
    FILE
    sur un flux de lecture peut être défini par l'ouverture d'un fichier avec
    fopen()
    en lecture.

    De fait, tu peux, bien sûr, utiliser
    fgets()
    pour lire le contenu disponible dans un fichier.

    Mais tu peux aussi passer à
    fgets()
    le pointeur sur
    FILE
    "stdin" qui est définit par
    stdio.h
    .

    La norme du C prévoit que
    stdin
    est un pointeur sur FILE permettant d'accéder au flux de l'entrée standard (que tu n'as pas à ouvrir avec
    fopen()
    , car il est déjà disponible selon le standard du C, et que tu ne devrais pas fermer avec
    fclose()
    ).

    http://www.cplusplus.com/reference/cstdio/stdin/?kw=stdin

    Ce flux de l'entrée standard est, normalement, le flux des caractères entrés au clavier (cela peut être aussi un flux redirigé ayant une autre origine), mis en tampon par le système et qui est accessible par cette fonction
    fgets()
    si tu lui passes
    stdin
    en 3ème argument. Le même flux
    stdin
    est accédé par d'autres fonctions définies par
    stdio.h
    conçues pour lire ce flux seulement (comme
    scanf()
    ou
    getchar()
    , qui ne nécessitent pas que tu précises le flux, car elles n'opèrent que sur l'entrée standard).

    Ici,
    stdin
    se comporte exactement comme le flux d'un fichier ouvert en lecture.

    Utilisée pour lire des informations provenant d'une saisie par l'utilisateur au clavier, la fonction
    fgets()
    a cet avantage qu'il est facile au programme de limiter la lecture du flux à un nombre maximal de
    char
    à lire, pour ne pas dépasser la capacité de l'espace mémoire utilisé pour stocker ce qui est lu : dans ton cas l'emplacement pointé par
    str
    . La lecture du flux est donc limitée à ce qui figure en 2ème argument (
    sizeof str
    la fonction prenant en compte le caractère terminateur
    '\0'
    qui est ajouté).

    C'est une façon recommandée d'éviter les risques de débordement de tampon et de corruption de la mémoire, qui peut occasionner des plantages, comportements imprévisibles ou des problèmes de sécurité, en ignorant les
    char
    saisis en plus qui dépasseraient la capacité de stockage indiquée y compris le caractère terminateur.

    Cette limitation du nombre de
    char
    lus sur le flux d'entrée standard est également possible avec
    scanf()
    , en utilisant les spécificateurs de taille de cette fonction, mais cette façon de faire est moins naturelle et peut être omise par les programmeurs inattentifs.

    Par exemple :

            char str[50] = { '\0' };
    
            printf("Veuillez taper 49 caractères au plus\n");
            if (scanf("%49[^\n]", str) == 1) {
                printf("J'ai récupéré : [%s]\n", str);
            }

    Tu dois déduire toi même de la taille disponible l'espace nécessaire au caractère terminateur
    '\0'
    ajouté par
    scanf()
    .

    Il y a d'autres différences et subtilités, concernant ces fonctions mais je m'arrêterai là pour le moment :-)

    Il y a aussi d'autres flux standard définis par le C :
    • le flux de sortie standard (écran du terminal normalement, sauf redirection) :
      stdout
      (là où va le résultat de printf() par exemple)
    • le flux (de sortie) d'erreur standard (idem) :
      stderr
      (là où va le résultat de perror() par exemple)

    Voir :
    http://www.cplusplus.com/reference/cstdio/stdout/
    http://www.cplusplus.com/reference/cstdio/stderr/

    Dal
    3
    1. Dalfab Messages postés 638 Date d'inscription   Statut Membre Dernière intervention   102
       
      Quand on voit le nombre de codes qui utilisent des
      scanf()
      en
      "%s"
      ou en
      "%[]"
      qui omettent de préciser la taille maximum du buffer, on peut affirmer qu'il y a énormément de programmeurs inattentifs ;-)
      0
    2. [Dal] Messages postés 6122 Date d'inscription   Statut Contributeur Dernière intervention   1 108
       
      Oui, c'est vrai que cet oubli est très fréquent.

      Dans l'enseignement initial du C il peut même être volontaire par l'enseignant, pour utiliser intentionnellement
      scanf()
      de façon simplifiée avec
      "%s"
      (un peu comme un pendant "naturel" à
      printf()
      avec ce qui semble être le même
      "%s"
      ), pour gérer une entrée au clavier sans considérations de robustesse ou de sécurisation du code à ce stade pour ne pas "embrouiller" les personnes débutantes.

      La réalité est que
      scanf()
      est une des fonctions les plus délicates à (bien) utiliser du langage C... il n'y a qu'à voir la taille de la page de manuel de cette fonction.

      Elle est quand même pratique lorsqu'elle est bien utilisée...

      Comme tu le sais,
      fgets()
      pour gérer
      stdin
      a ses propres problèmes ou contraintes : possible inclusion du retour chariot
      '\n'
      avant le caractère terminateur (si la taille de la saisie le permet), supposant un retraitement de la chaîne obtenue au clavier, si ce retour chariot est indésirable... d'un autre côté
      scanf()
      ne prend pas le retour chariot, qui reste dans
      stdin
      ...

      @salmamk27 : on peut en dire plus sur ces aspects, car tu ne fais qu'entrevoir la partie immergée de l'iceberg. Les deux fonctions nécessitent d'être attentifs au contenu obtenu et à celui restant dans le tampon
      stdin
      , non consommé par
      scanf()
      ou
      fgets()
      qui peut être différent, si on ne veut pas se retrouver avec des surprises selon les opérations suivantes de lecture de
      stdin
      à réaliser.

      Il est aussi déconseillé de mélanger l'usage des deux fonctions, compte tenu de leurs comportements différents.
      0
    3. salmamk27 Messages postés 3 Date d'inscription   Statut Membre Dernière intervention  
       
      merci beaucoup je tiendrais a ne pas melanger l'usage comme vous avez dit
      0