IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

lecture entier via fget [Débutant(e)]


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Novembre 2007
    Messages
    46
    Détails du profil
    Informations forums :
    Inscription : Novembre 2007
    Messages : 46
    Par défaut lecture entier via fget
    Bonjour, j'ai dernièrement demandé de l'aide pour lire une chaîne via le clavier. Je souhaite maintenant aller plus loin. Je voudrais réaliser un programme qui lit une chaîne et la convertisse en entier. Celui-ci devra faire 5 digits maxi sinon il retourne une erreur. Il sera affiché tout d'abord normalement puis en float puis en hexa puis comme un entier (ce pour travailler le format).
    J'arrive à ce code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    int main()
    {
        char tab[7];
        char *pend = NULL;
        int nbr = 0;
     
        printf("Entrer un entier de 5 digits maxi\n");
     
        fgets(tab,6,stdin);
        char *line_feed_found = strchr(tab, '\n');
        if (!line_feed_found)
        {
            fprintf(stderr,"votre entrée fait plus de 5 digits!!!\n");
    		return 1;
        }
        else
        {
            line_feed_found=0;
            nbr = (int)strtol(tab, &pend, 0);
            if (*pend != 0)
            {
                fprintf(stderr, "ERROR: Conversion en entier raté!\n");
                return 1;
            }
            printf("%5d\n",nbr);
            printf("Float:%5f\n",nbr);
            printf("Hexa:%5h\n",nbr);
            printf("Entier:%5i\n",nbr);
    		return 0;
        }
    }
    J'ai testé ce code et il s'avère que en lui donnant un entier de 5 digits de long, il me dit quand même que j'ai mis un entier trop long. Et quand j'en met un plus court, il n'arrive pas à convertir. Pouvez vous m'aider?
    Merci d'avance
    Jo

  2. #2
    Membre confirmé
    Avatar de Nykoo
    Profil pro
    Inscrit en
    Février 2007
    Messages
    234
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 234
    Par défaut
    Citation Envoyé par jocelyn54 Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
        fgets(tab,6,stdin);
        char *line_feed_found = strchr(tab, '\n');
        if (!line_feed_found)
        {
            fprintf(stderr,"votre entrée fait plus de 5 digits!!!\n");
    		return 1;
        }
    Je pense que si tu rentres 5 digits tu auras: 1,2,3,4,5,'\n'
    fgets va lire jusqu'a 6-1 caractères et ajouter '\0' au 6ème: 1,2,3,4,5,'\0'

    Donc avec 5 digits tu ne trouveras pas le caractère de retour à la ligne. Donc la condition !line_feed_found sera vraie.

  3. #3
    Membre averti
    Inscrit en
    Novembre 2007
    Messages
    46
    Détails du profil
    Informations forums :
    Inscription : Novembre 2007
    Messages : 46
    Par défaut
    fgets va lire jusqu'a 6-1 caractères et ajouter '\0' au 6ème: 1,2,3,4,5,'\0'
    Ah? Je pensais que elle allait lire les 6 char et rajouter le '\0' après la lecture...
    Je dois donc mettre la size de mon fgets à 7?
    et sinon pour le pb de conversion tu char à l'int, je m'y prends mal? C'est surement à cause du \n et du \0 que ça bug?



    tester la longueur de la chaine saisie : strlen()
    mais oui... j'aurais du penser à ça pour tester la longueur!
    Pour faire ce teste, j'utilise le tab? Ca donnerait quelquechose comme ça?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
         int max = 5;
         if (strlen(tab)>max)
            {
                fprintf(stderr,"ERROR: chaine trop longue\n");
                return 1;
            }
    Et pour retirer ce \n, je fait une getchar() c'est bien ça?

  4. #4
    Membre confirmé
    Avatar de Nykoo
    Profil pro
    Inscrit en
    Février 2007
    Messages
    234
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 234
    Par défaut
    Citation Envoyé par jocelyn54 Voir le message
    Ah? Je pensais que elle allait lire les 6 char et rajouter le '\0' après la lecture...
    Non fgets lit jusqu'a 6-1 caractères ou jusqu'a ce qu'il rencontre '\n' ou une fin de fichier. Ensuite seulement il rajoute le caractère NULL à la 6ème place ou après le '\n'.

    Citation Envoyé par jocelyn54 Voir le message
    Je dois donc mettre la size de mon fgets à 7?
    Comme l'a dit Emmanuel je pense qu'il vaudrait mieux utiliser strlen. En gros fait comme il t'as dit.

    Citation Envoyé par jocelyn54 Voir le message
    et sinon pour le pb de conversion tu char à l'int, je m'y prends mal? C'est surement à cause du \n et du \0 que ça bug?
    Fais comme Emmanuel te dis

  5. #5
    Membre averti
    Inscrit en
    Novembre 2007
    Messages
    46
    Détails du profil
    Informations forums :
    Inscription : Novembre 2007
    Messages : 46
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    int main()
    {
        char tab[7];
        char *pend = NULL;
        int nbr = 0;
     
        printf("Entrer un entier de 5 digits maxi\n");
     
        fgets(tab,6,stdin);
        char *line_feed_found = strchr(tab, '\n');
        if (!line_feed_found)
        {
            fprintf(stderr,"votre entrée fait plus de 5 digits!!!\n");
            int c;
            while ((c = getchar()) != '\n' && c != EOF)   // je purge
            {}
    		return 1;
        }
        else
        {
            *line_feed_found=0; // je delete le \n
             if (strlen(tab)>max)   //je teste la longueur
            {
                fprintf(stderr,"ERROR: syotteessa liikaa numeroita\n");
                return 1;
            }
            else
            {
                nbr = (int)strtol(tab, &pend, 0);
                if (*pend != 0)  // je teste si la conversion est réussi
                {
                    fprintf(stderr, "ERROR: Conversion en entier raté!\n");
                    return 1;
                }
            //enfin j'affiche
            printf("%d\n",nbr);
            printf("Float:%f\n",nbr);
            printf("Hexa:%h\n",nbr);
            printf("Entier:%i\n",nbr);
    		return 0;
        }
    }
    J'ai essayé de suivre les conseils qui m'ont été donné. J'arrive au code ci dessus. Le programme ne fait plus d'erreur quand je lui entre "01234" en entrée mais il ne m'affiche pas ce que je veux. Est-ce à cause de mes printf() ou d'autre chose?
    Il m'affiche :
    668
    Float:0.000000
    Hexa:
    Entier:668
    De plus j'aimerais limiter l'affichage du float à 2 chiffres àpres la virgule.

  6. #6
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par jocelyn54 Voir le message
    J'ai essayé de suivre les conseils qui m'ont été donné. J'arrive au code ci dessus.
    Huh !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
    Project   : Forums
    Compiler  : GNU GCC Compiler (called directly)
    Directory : C:\dev\forums\
    --------------------------------------------------------------------------------
    Switching to target: default
    Compiling: main.c
    main.c:6: warning: function declaration isn't a prototype
    main.c: In function `main':
    main.c:26: error: `max' undeclared (first use in this function)
    main.c:26: error: (Each undeclared identifier is reported only once
    main.c:26: error: for each function it appears in.)
    main.c:41: warning: double format, different type arg (arg 2)
    main.c:42: warning: unknown conversion type character 0xa in format
    main.c:42: warning: too many arguments for format
    main.c:46: error: syntax error at end of input
    Process terminated with status 1 (0 minutes, 1 seconds)
    Le programme ne fait plus d'erreur quand je lui entre "01234" en entrée mais il ne m'affiche pas ce que je veux. Est-ce à cause de mes printf() ou d'autre chose?
    Il m'affiche :
    668
    Float:0.000000
    Hexa:
    Entier:668
    668 est bien la valeur décimale de l'entier codé en octal "01234". As-tu bien lu ma réponse complètement ? Il faut tout lire dans le détail. Je ne parle pas pour ne rien dire...

    De plus j'aimerais limiter l'affichage du float à 2 chiffres àpres la virgule.
    Quel intérêt pour un entier ? Si tu y tiens : "%.2f"

  7. #7
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par jocelyn54 Voir le message
    Bonjour, j'ai dernièrement demandé de l'aide pour lire une chaîne via le clavier. Je souhaite maintenant aller plus loin. Je voudrais réaliser un programme qui lit une chaîne et la convertisse en entier. Celui-ci devra faire 5 digits maxi sinon il retourne une erreur. Il sera affiché tout d'abord normalement puis en float puis en hexa puis comme un entier (ce pour travailler le format).
    J'arrive à ce code :
    <...>
    J'ai testé ce code et il s'avère que en lui donnant un entier de 5 digits de long, il me dit quand même que j'ai mis un entier trop long. Et quand j'en met un plus court, il n'arrive pas à convertir. Pouvez vous m'aider?
    Merci d'avance
    Jo
    Il y a des problèmes avec ce code...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    Project   : Forums
    Compiler  : GNU GCC Compiler (called directly)
    Directory : C:\dev\forums\
    --------------------------------------------------------------------------------
    Switching to target: default
    Compiling: main.c
    main.c:6: warning: function declaration isn't a prototype
    main.c: In function `main':
    main.c:30: warning: double format, different type arg (arg 2)
    main.c:31: warning: unknown conversion type character 0xa in format
    main.c:31: warning: too many arguments for format
    Linking console executable: console.exe
    Process terminated with status 0 (0 minutes, 8 seconds)
    0 errors, 4 warnings
    Le bug est ici :
    c'est
    Il faut que tu te sortes de la tête que fgets() sert à faire des entrées limitées en largeur. Ce n'est pas le but de cette fonction. Si tu fais ça, il va se produire un phénomène désagréable qui est que le '\n' va rester dans stdin et que l'appel suivant de fgets() ne sera pas bloquant.

    Il faut suivre cette procédure :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    - saisie d'une chaine de taille suffisante pour les besoins : fgets()
    - recherce du '\n'
      si présent : l'éliminer
      sinon : purger le flux
    - tester la longueur de la chaine saisie : strlen()
      si elle est supérieure longueur max : message d'erreur
      sinon : convertir : strtol()
       si erreur : message d'erreur
    Ceci fonctionne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    int main (void)
    {
       int fin = 0;
       do
       {
          char tab[8];
     
          printf ("Entrer un entier de 5 digits maxi (\"\" pour quitter)\n");
     
          fgets (tab, sizeof tab, stdin);
          char *line_feed_found = strchr (tab, '\n');
          if (!line_feed_found)
          {
             /* purge */
             int c;
             while ((c = getchar ()) != '\n' && c != EOF)
             {
             }
             fprintf (stderr, "votre entrée fait plus de %d digits!!!\n",
                      (int) sizeof tab - 2);
          }
          else
          {
             *line_feed_found = 0;
             if (*tab == 0)
             {
                fin = 1;
             }
             else
             {
                if (strlen (tab) > 5)
                {
                   fprintf (stderr, "votre entrée fait plus de 5 digits!!!\n");
                }
                else
                {
     
                   char *pend = NULL;
                   int nbr = (int) strtol (tab, &pend, 0);
                   if (*pend != 0)
                   {
                      fprintf (stderr, "ERROR: Conversion en entier raté!\n");
                   }
                   else
                   {
                      printf ("%d\n", nbr);
                      printf ("Float:%f\n", (double) nbr);
                      printf ("Hexa:%x\n", nbr);
                      printf ("Entier:%i\n", nbr);
                   }
                }
             }
          }
       }
       while (!fin);
       return 0;
    }
    Remarques :
    • La base '0' de strtol admet les conversion automatiques de décimal, octal (0...) et hexa (0x...). Les 5 digits sont-ils suffisants ? Sinon, imposer la base 10...
    • Et les nombres négatifs ? est-ce que -12345 est acceptable ? Si ouil il ne faut pas compter le '-' dans les 5 digits...
    • %i et %d ont la même signification avec printf()
    • Ca n'a pas trop de sens de convertir un entier en flottant...

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Ouvrir un fichier excel en lecture seule via VBA
    Par mbellemax dans le forum Macros et VBA Excel
    Réponses: 6
    Dernier message: 01/12/2017, 13h35
  2. Optimisation lecture fichier via un shell script
    Par macleod dans le forum Shell et commandes GNU
    Réponses: 5
    Dernier message: 31/07/2007, 12h46
  3. Lecture fichier via url ou file, différence ?
    Par kij dans le forum Entrée/Sortie
    Réponses: 28
    Dernier message: 03/01/2007, 13h30
  4. forcer la lecture entiere d'un textarea
    Par enzo21 dans le forum Général JavaScript
    Réponses: 11
    Dernier message: 23/10/2006, 10h19
  5. Réponses: 4
    Dernier message: 05/06/2002, 12h15

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo