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 :

Convertir un nombre d'une chaine de caratrère en un nombre


Sujet :

C

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Août 2006
    Messages
    256
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 256
    Par défaut Convertir un nombre d'une chaine de caratrère en un nombre
    Bonjour tout le monde,

    Je débute en C, et je suis en train de faire un petit jeu "plus ou moins".
    Le programme marche très bien si on lui rentre des chiffres, mais il fais une boucle infinie si on rentre des caractères.

    Donc, ce que je veut maintenant arriver à faire, c'est pouvoir tester ce que rentre l'utilisateur, et lui afficher par exemple "veuillez rentrer un nombre svp".
    La où je bloque, c'est que les caractères sont enregistrés en mémoire comme des nombres, donc comment détécter si l'utilisateur à rentré un caractère ou un nombre ?

    Sinon, avez-vous un bout de code qui ressemble à ce que je veut faire pour que je vois comment aurais fait un non-débutant ?

    Merci.
    Pierre.

    PS : si ça peut servir, voilà mon code actuel :
    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
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h> // pour la génération du nombre aléatoire
     
    int main(void)
    {
      printf("Jeu \"Plus ou moins\"\n");
      printf("Essayez de trouver le plus rapidement possible le nombre entre 0 et 101 :\n\n");
     
      srand(time(NULL));
      #define max 100
      #define min 1
      char nbATrouver=(rand() % (max - min + 1)) + min;
     
      int nombre, i;
     
      for (i=1; nombre!=nbATrouver; ++i)
      {
        printf("Essai %ld : ", i);
        scanf("%ld", &nombre);
     
        if (nombre==nbATrouver)
        {
          printf("\nBravo !\n\n");
        }
        else if (nombre<nbATrouver)
        {
          printf("Trop petit\n\n", nombre);
        }
        else
        {
          printf("Trop grand\n\n", nombre);
        }
      }
     
      system("PAUSE");
      return 0;
    }

  2. #2
    Membre expérimenté Avatar de Gamdwin
    Inscrit en
    Avril 2005
    Messages
    186
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 186
    Par défaut
    Faut pas utiliser scanf(), en tout cas pas de cette façon-là. Ce n'est pas une fonction facile à utiliser, pour débuter il vaut mieux utiliser fgets(), puis convertir la chaîne lue en nombre avec, par exemple, strtol().

  3. #3
    Expert confirmé

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Par défaut
    Voici une version corrigée avec des remarques en commentaires...
    Poses des questions si tu ne comprends pas quelque chose...

    Jc

    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
    63
    #include <string.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h> // pour la génération du nombre aléatoire
     
    /* -fy- Constantes hors du main, c'est plus joli et en majuscules... */
    #define MAX 100
    #define MIN 1
     
    int main(void)
    {
        char nbATrouver, buf[16];
     
        /* -fy- on met nombre a une valeur qui ne peut pas etre nbATrouver */
        int nombre = MIN-1, i;
     
        printf("Jeu \"Plus ou moins\"\n");
        printf("Essayez de trouver le plus rapidement possible le nombre entre 0 et 101 :\n\n");
     
        srand(time(NULL));
        nbATrouver=(rand() % (MAX - MIN + 1)) + MIN;
     
        /* -fy- On ne sait pas combien d'iterations -> while */
        i=1;
        while(nombre!=nbATrouver)
        {
            /* -fy- i est un int donc %d pas %ld */
            printf("Essai %d : ", i);
     
            /* -fy- scanf est deconseille, on utilise fgets */
            if(fgets(buf,sizeof(buf),stdin)==NULL)
                return EXIT_FAILURE;
            /* On regarde si on a reussi a avoir une ligne entiere */
            if(strchr(buf,'\n')==NULL)
            {
                printf("Chaine entree trop grande\n");
                return EXIT_FAILURE;
            }
            else 
            {   
                nombre = strtol(buf,NULL,0);
     
                if (nombre==nbATrouver)
                {
                    printf("\nBravo !\n\n");
                }
                else if (nombre<nbATrouver)
                {
                    printf("Trop petit\n\n");
                }
                else
                {
                    printf("Trop grand\n\n");
                }
                ++i;
            }
        }
     
        /* -fy- Ce n'est pas portable 
           system("PAUSE"); */
     
        return EXIT_SUCCESS;
    }

  4. #4
    Membre éclairé
    Profil pro
    Inscrit en
    Août 2006
    Messages
    256
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 256
    Par défaut
    OK, merci pour ces réponses, j'ai un truc plus ou moins urgent à faire et je regarde ça plus en détail après, je vais avoir quelques questions.

  5. #5
    Membre éclairé
    Profil pro
    Inscrit en
    Août 2006
    Messages
    256
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 256
    Par défaut
    Bon, je viens de regarder tout ça, ça marche, mais il y as quelques trucs que je n'arrive pas à comprendre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    if(fgets(buf, sizeof(buf), stdin)==NULL)
    return EXIT_FAILURE;
    1. Ici, on lis dans l'entrée standard, ça c'est ok.
    Mais ce que je ne comprend pas c'est que le if(fgets...) est juste après l'affichage de "Essai x : ", donc fgets attend de trouver un \n pour passer au reste ?

    2. On teste que fgets a bien réussis à lire quelque chose dans stdin, mais est-il possible que ça n'y arrive pas ? est-ce que c'est pour les OS exotiques ?

    3. Le code ne plante plus quand on rentre des caractères, mais est-il possible des les détécter (pour mettre par exemple : "veuillez entrer un nombre") ?
    Faut il utiliser des expressions régulières comme en PHP ?

    4. Pour remplacer le system("PAUSE"); j'utilise :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    printf("Validez pour quitter\n");
    fflush(stdin);
    getchar();
    Mais la fonction getchar s'arrète seulement si on appuis sur entrée, quelle est la fonction qui s'arrête avec l'appuis sur n'importe quelle touche ?

    5. Pour finir, comment capter quand l'utilisateur appuis sur la touche echap ?


    Merci beaucoup.
    Pierre.

  6. #6
    Membre expérimenté Avatar de Gamdwin
    Inscrit en
    Avril 2005
    Messages
    186
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 186
    Par défaut
    Citation Envoyé par Pierre.g
    1. Ici, on lis dans l'entrée standard, ça c'est ok.
    Mais ce que je ne comprend pas c'est que le if(fgets...) est juste après l'affichage de "Essai x : ", donc fgets attend de trouver un \n pour passer au reste ?
    On peut dire ça comme ça.

    Citation Envoyé par Pierre.g
    2. On teste que fgets a bien réussis à lire quelque chose dans stdin, mais est-il possible que ça n'y arrive pas ? est-ce que c'est pour les OS exotiques ?
    Pourquoi exotique ?
    Il suffit de saisir un EOF et fgets() interprète cela comme une fin de fichier, comme cette fonction lit un flux quelconque (donc potentiellement, un fichier), cela permet de détecter la fin de lecture.

    Tu peux simuler ce comportement très simplement : sous Unix il te suffit de taper ctrl+d.
    Sur Windows, il suffit de taper ctrl+z, puis [entrée] (contrainte : sous windows un EOF sur le flux d'entrée standard n'est détecté que s'il est le premier caractère de la ligne lue.)

    fgets() peut aussi retourner NULL si une erreur s'est produite (la détection d'un EOF n'étant pas une erreur).
    Au lieu de retourner EXIT_FAILURE lorsque fgets() renvoie NULL, il vaut mieux vérifier si une erreur a eu lieu à l'aide de ferror(). Si ce n'est pas le cas, on peut continuer le programme normalement.

    Citation Envoyé par Pierre.g
    3. Le code ne plante plus quand on rentre des caractères, mais est-il possible des les détécter (pour mettre par exemple : "veuillez entrer un nombre") ?
    Faut il utiliser des expressions régulières comme en PHP ?
    Ce ne sont pas des expressions régulières (hélas), mais des patterns particuliers.
    Tu en sauras plus en lisant attentivement l'aide des fonctions ...scanf().

    Citation Envoyé par Pierre.g
    4. Pour remplacer le system("PAUSE"); j'utilise :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    printf("Validez pour quitter\n");
    fflush(stdin);
    getchar();
    Mais la fonction getchar s'arrète seulement si on appuis sur entrée, quelle est la fonction qui s'arrête avec l'appuis sur n'importe quelle touche ?
    Non : fflush() ne s'utilise qu'avec des flux d'écriture !
    Cette fonction a un comportement indéfini sur des flux tels que stdin.

    Quant à détecter l'appui quelconque d'une touche, il n'y a pas de méthode standard en C pour faire ça.

    Citation Envoyé par Pierre.g
    5. Pour finir, comment capter quand l'utilisateur appuis sur la touche echap ?
    Pas de méthode standard, donc. Mais avec les bibliothèques que l'on trouve pour tel ou tel OS, tu trouveras que le code de la touche echap est, en général, 27.

  7. #7
    Membre Expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Par défaut
    il vaut mieux vérifier si une erreur a eu lieu à l'aide de ferror()
    D'ailleurs comment savoir les erreurs que peut lever "fgets"?
    Existe il une liste pour chaque fonction des erreurs potentielles?

  8. #8
    Rédacteur

    Avatar de gege2061
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Juin 2004
    Messages
    5 840
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 42
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Juin 2004
    Messages : 5 840
    Par défaut
    Citation Envoyé par seriousme
    D'ailleurs comment savoir les erreurs que peut lever "fgets"?
    Existe il une liste pour chaque fonction des erreurs potentielles?
    man fgets

    Après tu peux utiliser feof pour savoir si la fin du fichier à été atteinte ou ferror s'il s'agit d'une erreur.

    Comme fgets n'utilise errno, il est impossible d'en savoir plus

    [edit][/edit]

  9. #9
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 398
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 398
    Par défaut
    On voit rarement ça dans l'aide MSDN, mais c'est généralement marqué dans le man d'une fonction.
    Code man fgets() : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ERRORS
           Refer to fgetc() .
    Code man fgetc() : 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
    ERRORS
           The fgetc() function shall fail if data needs to be read and:
     
           EAGAIN The O_NONBLOCK flag is set for the file  descriptor  underlying
                  stream  and  the process would be delayed in the fgetc() opera-
                  tion.
     
           EBADF  The file descriptor underlying  stream  is  not  a  valid  file
                  descriptor open for reading.
     
           EINTR  The  read operation was terminated due to the receipt of a sig-
                  nal, and no data was transferred.
     
           EIO    A physical I/O error has occurred, or the process is in a back-
                  ground  process  group  attempting to read from its controlling
                  terminal, and either the process is ignoring  or  blocking  the
                  SIGTTIN signal or the process group is orphaned. This error may
                  also be generated for implementation-defined reasons.
     
           EOVERFLOW
                  The file is a regular file and an attempt was made to  read  at
                  or  beyond the offset maximum associated with the corresponding
                  stream.
     
           The fgetc() function may fail if:
     
           ENOMEM Insufficient storage space is available.
     
           ENXIO  A request was made of a nonexistent device, or the request  was
                  outside the capabilities of the device.


    Edit: Devancé par gege2061...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  10. #10
    Membre émérite Avatar de homeostasie
    Homme Profil pro
    Inscrit en
    Mai 2005
    Messages
    939
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 939
    Par défaut
    Le code ne plante plus quand on rentre des caractères, mais est-il possible des les détécter (pour mettre par exemple : "veuillez entrer un nombre") ?
    Il est possible de vérifier si l'utilisateur a saisi seulement des chiffres ou "digit", grâce à la fonction isdigit();

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    /*Check the data capture (an integer number)*/
    while(Buf[i] != '\0'){
          if((int)isdigit(Buf[i]) == 0){
          printf("ERROR: Bad value\n");
          return (ERROR);
          }
    i++;
    }
    fflush() ne s'utilise qu'avec des flux d'écriture !
    Cette fonction a un comportement indéfini sur des flux tels que stdin.
    En effet, utiliser la fonction purge() suivante pour vider le buffer (stdin dans notre cas):
    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
     
    static void PurgeFile (char *s, FILE *fp)
    {
       /* search ... */
       char *p = strchr (s, '\n');
       if (p != NULL)
       {
          /* ... and kill */
          *p = 0;
       }
       else
       {
          /* purge */
          int c;
          while ((c = fgetc(fp)) != '\n' && c != EOF)
          {
          }
       }
    }
    et appellez la fonction ainsi:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    /* Purge the keyboard(stdin) buffer */
    PurgeFile(Buf, stdin);
    Nicolas

  11. #11
    Membre éclairé
    Profil pro
    Inscrit en
    Août 2006
    Messages
    256
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 256
    Par défaut
    Merci à tout le monde,

    Finalement j'ai réussis à faire ce que je voulais avec le scanf en jouant sur le formatage, ça ne marche pas forcement pour tout, mais pour mon cas ça marche impecable. J'ai mis "%3[0-9]" comme ça, ça ne prend que les 3 premiers chiffres.

    Merci pour vos idées, elle ne sont pas passés à la trap, je les ais observés et j'en ais appris quelques trucs.

    Merci.
    A+

    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
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h> // pour la génération du nombre aléatoire
    #include <windows.h> // pour changer le titre de la console
     
    #define MAX 99
    #define MIN 1
     
    int main(void)
    {
        SetConsoleTitle("Jeu du plus ou moins");
     
        char nbATrouver;
     
        int nombre=MIN-1, i=1;
     
        printf("Plus ou moins\n");
        printf("But : trouver le plus rapidement possible le nombre entre 0 et 100 :\n\n");
     
        srand(time(NULL));
        nbATrouver=(rand() % (MAX - MIN + 1)) + MIN;
     
        while(nombre!=nbATrouver)
        {
            int buffer[3]={0};
     
            printf("Essai %d : ", i);
            scanf("%3[0-9]", &buffer);
     
            nombre=strtol(buffer, NULL, 0);
     
            if (buffer[0]!=0 & nombre<100 & nombre>0)
            {
                if (nombre==nbATrouver)
                {
                    printf("\nBravo !\n\n");
                }
                else if (nombre<nbATrouver)
                {
                    printf("Trop petit\n\n");
                }
                else
                {
                    printf("Trop grand\n\n");
                }
     
                ++i;
            }
            else
            {
                printf("Veuillez entrer un nombre compris entre 0 et 100 svp\n\n");
            }
     
            fflush(stdin);
        }
     
        printf("Appuyez sur une touche pour pour quitter\n");
        getch();
     
        return EXIT_SUCCESS;
    }

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

Discussions similaires

  1. Extraire un nombre dans une chaine
    Par SIGOliv dans le forum Access
    Réponses: 16
    Dernier message: 13/03/2006, 16h44
  2. [MySQL] extraire des nombre d'une chaine de caractères et addition
    Par Yotho dans le forum PHP & Base de données
    Réponses: 1
    Dernier message: 04/03/2006, 17h54
  3. Réponses: 4
    Dernier message: 20/02/2006, 01h33
  4. Récuperer un nombre dans une chaine de caractère
    Par ColonelHati dans le forum C
    Réponses: 4
    Dernier message: 27/04/2005, 15h50
  5. [LG]Extraire des nombres d'une chaine
    Par audreym31 dans le forum Langage
    Réponses: 4
    Dernier message: 18/01/2004, 22h24

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