Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 23/07/2016, à 13:18

Hitec-user

Langage C : transformer une chaîne de caractères numériques en nombre

Bonjour,

Suite à l'exercice cité ici, je souhaite maintenant transformer ma chaîne de caractères numériques (char saisie[4]) en nombre de type int ou long int. La fonction strtol me renvoie l'erreur :

1-exo_5.1.c: In function ‘convertir_saisie’:
1-exo_5.1.c:114:3: warning: passing argument 2 of ‘strtol’ from incompatible pointer type [enabled by default]
   nombre=strtol(saisie, &sr, 10);
   ^
In file included from 1-exo_5.1.c:2:0:
/usr/include/stdlib.h:183:17: note: expected ‘char ** __restrict__’ but argument is of type ‘int **’
extern long int strtol (const char *__restrict __nptr,

J'ai essayé avec une boucle pour appliquer strtol (testé avec &saisie[x] et saisie[x]) comme ceci:
nombre=nombre+(strtol(&saisie[x], &sr, 10)*(long int)pow(10,x));

et là ça me dit:

1-exo_5.1.c: In function ‘convertir_saisie’:
1-exo_5.1.c:116:5: warning: passing argument 2 of ‘strtol’ from incompatible pointer type [enabled by default]
     nombre=nombre+(strtol(&saisie[x], &sr, 10)*(long int)pow(10,x));
     ^
In file included from 1-exo_5.1.c:2:0:
/usr/include/stdlib.h:183:17: note: expected ‘char ** __restrict__’ but argument is of type ‘int **’
extern long int strtol (const char *__restrict __nptr,

Voici le code complet:

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<string.h>
#include<math.h>

/* Variables communes */
int nb_alea=0;
char saisie[5];

/* Index des fonctions */
void affiche_regle(); /* Affiche :e titre et la règle du jeu */
void choisir_nombre(); /* Choisit un nombre aléatoire pour nb_alea */
void lire_choix(); /* Capture la saisie du clavier et le stocke dans 'saisie' */
void clean(const char *buffer, FILE *fp); /* pour la purge de stdin, utilisé dans lire_choix */
int saisie_valide(); /* Vérifie si chaque caractère de 'saisie' est bien un chiffre */
int convertir_saisie(); /* Lit la chaine 'saisie' et la convertit en long int */
int result_essai(int nombre); /* Compare 'nombre' et 'nb_alea' => rend -1 si c'est moins, +1 si c'est plus et +2 si c'est = */
void affiche_result(int resultat); /* dit si c'est >, <, si la partie est gagnée ou perdue(essais épuisés) */

/* Programme principal */
int main() {

  int nb_essais=0, nombre=0, resultat=0, fini=0;

  affiche_regle();
  choisir_nombre();

  while (fini==0) {
    printf("Saisissez un nombre ebtre 1 et 1000 : ");

    lire_choix();

    while (saisie_valide()==0) {
      printf("Saisie invalide... entrez un nombre entre 1 et 1000 : ");
      lire_choix();
    }

    nombre=convertir_saisie();
    resultat=result_essai(nombre);

    if (resultat==2 || nb_essais>=15)
      fini=1;

    affiche_result(resultat);
    nb_essais++;
  }

  return 0;
}

/* Sous-programmes */
/*******************************************************/
void affiche_regle() {

  printf("\n");
  printf("                    ****************************************\n");
  printf("                    *    Jeu de recherche stratégique      *\n");
  printf("                    *   réalisé par Sylvio Desjardins%d.    *\n", 169);
  printf("                    ****************************************\n");
  printf("\n");
  printf("                 Un nombre entre 1 et 1000 est tiré au hazard,\n");
  printf("                 vous devez le trouver en moins de 15 essais.\n");
  printf("\n");
}

/*******************************************************/
void choisir_nombre() {

  srand(time(NULL));

  nb_alea=1+(rand() % 999);
}

/*******************************************************/
void lire_choix() {

  fgets(saisie, sizeof(saisie), stdin);
  clean(saisie, stdin);

}

/*******************************************************/
void clean(const char *buffer, FILE *fp) {

  char *p=strchr(buffer, '\n');
  if (p!=NULL)
    *p=0;
  else {
    int c;
    while ((c=fgetc(fp))!='\n' && c!=EOF);
  }
}

/*******************************************************/
int saisie_valide() {

  int i=0;
  int test=1;

  while (i<sizeof(saisie) && test==1) {
    if (((int)saisie[i]<48 || (int)saisie[i]>57) && (int)saisie[i]!=0)
      test=0;
    i++;
  }
  return test;
}

/*******************************************************/
int convertir_saisie() {

  long int nombre=0;
  int *sr;

  nombre=strtol(saisie, &sr, 10);

  return (int)nombre;
}
/*******************************************************/
int result_essai(int nombre) {

  int r=0;

  if (nombre==nb_alea)
    r=2;
  else if (nombre>nb_alea)
    r=-1;
  else if (nombre<nb_alea)
    r=1;
  else {
    printf("ERREUR, valeur eronnée pour \'nombre(=%i)\' ou \'nb_alea(=%i)\'\n", nombre, nb_alea);
    exit(0);
  }

  return r;
}

/*******************************************************/
void affiche_result(int resultat) {

  if (resultat==2)
    printf("Bravo, vous avez gagné, la réponse est bien %i.\n", nb_alea);
  else if (resultat==-1)
    printf("C'est moins.\n");
  else if (resultat==1)
    printf("C'est plus.\n");
  else {
    printf("affiche_result : Valeur eronnée pour \'resultat\'(=%d).\n", resultat);
    exit(0);
  }
}

Quelqu'un peut-il m'aider svp?

Dernière modification par Hitec-user (Le 25/07/2016, à 17:45)

Hors ligne

#2 Le 23/07/2016, à 14:29

grigouille

Re : Langage C : transformer une chaîne de caractères numériques en nombre

man strtol

À la fin tu as un exemple d'utilisation de strtol.


Debian (xfce) 12
HP LaserJet M1132 MFP

Hors ligne

#3 Le 25/07/2016, à 10:27

Hitec-user

Re : Langage C : transformer une chaîne de caractères numériques en nombre

Bonjour Grigouille,

Cet exemple je l'ai vu, et justement tout exemple que j'ai pu lire dans le man et sur le net partent d'une variable char simple, mais pas de tableau. Or si j'utilise "char saisie" au lieu de "char saisie[4]", dans ce cas, comment je peut faire d'une part ma capture initiale de nombre sous forme 'char' et le test donné par ma sous-fonction saisie_valide() (possible grâce à ce type de capture) car je n'ai pas trouvé comment récupérer le code ascii d'une variable de type int ?

Dernière modification par Hitec-user (Le 25/07/2016, à 10:30)

Hors ligne

#4 Le 25/07/2016, à 10:49

grigouille

Re : Langage C : transformer une chaîne de caractères numériques en nombre

Comme tu ne fais aucun contrôle après strtol, tu peux utiliser atoi à la place.


Debian (xfce) 12
HP LaserJet M1132 MFP

Hors ligne

#5 Le 25/07/2016, à 17:46

Hitec-user

Re : Langage C : transformer une chaîne de caractères numériques en nombre

Re-bonjour Grigouille,

Encore merci de me suivre, je vais regarder atoi et je reviens.

Hors ligne

#6 Le 25/07/2016, à 17:58

Hitec-user

Re : Langage C : transformer une chaîne de caractères numériques en nombre

Je viens de tester, et ÇA MARCHE !
Mille merci s.
Pour ceux qui veulent se détendre, voici le code final.

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<string.h>
#include<math.h>

/* Variables communes */
int nb_alea=0;
char saisie[5];

/* Index des fonctions */
void affiche_regle(); /* Affiche :e titre et la règle du jeu */
void choisir_nombre(); /* Choisit un nombre aléatoire pour nb_alea */
void lire_choix(); /* Capture la saisie du clavier et le stocke dans 'saisie' */
void clean(const char *buffer, FILE *fp); /* pour la purge de stdin, utilisé dans lire_choix */
int saisie_valide(); /* Vérifie si chaque caractère de 'saisie' est bien un chiffre */
int convertir_saisie(); /* Lit la chaine 'saisie' et la convertit en long int */
int result_essai(int nombre); /* Compare 'nombre' et 'nb_alea' => rend -1 si c'est moins, +1 si c'est plus et +2 si c'est = */
void affiche_result(int resultat); /* dit si c'est >, <, si la partie est gagnée ou perdue(essais épuisés) */

/* Programme principal */
int main() {

  int nb_essais=0, nombre=0, resultat=0, fini=0;

  affiche_regle();
  choisir_nombre();

  while (fini==0) {
    printf("Saisissez un nombre entre 1 et 1000 : ");

    lire_choix();

    while (saisie_valide()==0) {
      printf("Saisie invalide... entrez un nombre entre 1 et 1000 : ");
      lire_choix();
    }

    nombre=convertir_saisie();
    resultat=result_essai(nombre);

    if (resultat==2 || nb_essais>=15)
      fini=1;

    affiche_result(resultat);
    nb_essais++;
  }

  return 0;
}

/* Sous-programmes */
/*******************************************************/
void affiche_regle() {

  printf("\n");
  printf("                    ****************************************\n");
  printf("                    *    Jeu de recherche stratégique      *\n");
  printf("                    *   réalisé par Sylvio Desjardins%d.    *\n", 169);
  printf("                    ****************************************\n");
  printf("\n");
  printf("                 Un nombre entre 1 et 1000 est tiré au hazard,\n");
  printf("                 vous devez le trouver en moins de 15 essais.\n");
  printf("\n");
}

/*******************************************************/
void choisir_nombre() {

  srand(time(NULL));

  nb_alea=1+(rand() % 999);
}

/*******************************************************/
void lire_choix() {

  fgets(saisie, sizeof(saisie), stdin);
  clean(saisie, stdin);

}

/*******************************************************/
void clean(const char *buffer, FILE *fp) {

  char *p=strchr(buffer, '\n');
  if (p!=NULL)
    *p=0;
  else {
    int c;
    while ((c=fgetc(fp))!='\n' && c!=EOF);
  }
}

/*******************************************************/
int saisie_valide() {

  int i=0;
  int test=1;

  while (i<sizeof(saisie) && test==1) {
    if (((int)saisie[i]<48 || (int)saisie[i]>57) && (int)saisie[i]!=0)
      test=0;
  i++;
  }
  return test;
}

/*******************************************************/
int convertir_saisie() {

  int nombre=0;
  
  nombre=atoi(saisie);

  return (int)nombre;
}
/*******************************************************/
int result_essai(int nombre) {

  int r=0;

  if (nombre==nb_alea)
    r=2;
  else if (nombre>nb_alea)
    r=-1;
  else if (nombre<nb_alea)
    r=1;
  else {
    printf("ERREUR, valeur eronnée pour \'nombre(=%i)\' ou \'nb_alea(=%i)\'\n", nombre, nb_alea);
    exit(0);
  }

  return r;
}

/*******************************************************/
void affiche_result(int resultat) {

  if (resultat==2)
    printf("Bravo, vous avez gagné, la réponse est bien %i.\n", nb_alea);
  else if (resultat==-1)
    printf("C'est moins.\n");
  else if (resultat==1)
    printf("C'est plus.\n");
  else {
    printf("affiche_result : Valeur eronnée pour \'resultat\'(=%d).\n", resultat);
    exit(0);
  }
}

C Libre... smile
Je passe à l'exercice suivant.
Très bonne journée.

Hors ligne

#7 Le 25/07/2016, à 22:47

claudius01

Re : Langage C : transformer une chaîne de caractères numériques en nombre

Bonsoir,

Hitec-user a écrit :

... @ (post #8) [RESOLU] Langage C : code ascii d'un entier: Mon test fonctionne. isdigit ne m'a pas servi, j'ai préféré faire le test "à la main".

Très mauvaise habitude de refaire ce qui a déjà été écrit et qui fonctionne depuis des lustres ;-).

En reprenant uniquement la fonction int saisie_valide() à périmètre fonctionnel équivalent:

#include <stdio.h>
#include <ctype.h>

char saisie[5] = { '0', '2', '3', '4', '9' };

int saisie_valide() {

   int i=0;
   int test=1;

   while (i<sizeof(saisie) && test==1) {
      printf("saisie[%d] = [%d] = '%c'\n", i,  saisie[i], saisie[i]);

      /* if (((int)saisie[i]<48 || (int)saisie[i]>57) && (int)saisie[i]!=0) ou encore
         if (((int)saisie[i]<'0' || (int)saisie[i]>'9') && (int)saisie[i]!=0)
         => Expression dans laquelle on reconnait un isdigit() ;-)
      */
      if (!isdigit((int)saisie[i]) && (int)saisie[i] != 0)
         test=0;

      i++;
   }
   return test;
}

int main(void)
{
   int rtn = saisie_valide();
   printf("rtn saisie_valide() = [%d]\n\n", rtn);

   saisie[0] = '/';  /* Erreur volontaire sur 1er caractère */
   rtn = saisie_valide();
   printf("rtn saisie_valide() = [%d]\n\n", rtn);

   saisie[0] = '0';
   saisie[4] = ':';  /* Erreur volontaire sur dernier caractère */
   rtn = saisie_valide();
   printf("rtn saisie_valide() = [%d]\n\n", rtn);
   return 0;
}

pi@raspberrypi ~/Tmp $ gcc -Wall -o Hitec-user Hitec-user.c && ./Hitec-user
saisie[0] = [48] = '0'
saisie[1] = [50] = '2'
saisie[2] = [51] = '3'
saisie[3] = [52] = '4'
saisie[4] = [57] = '9'
rtn saisie_valide() = [1]

saisie[0] = [47] = '/'
rtn saisie_valide() = [0]

saisie[0] = [48] = '0'
saisie[1] = [50] = '2'
saisie[2] = [51] = '3'
saisie[3] = [52] = '4'
saisie[4] = [58] = ':'
rtn saisie_valide() = [0]

A l'occasion Hitec-user, jette un coup d'oeil sur: GNU libc: Function and Macro Index, liste exhaustive ou presque qui devrait être apprise et connue ou du moins consultée en 1er lieu car la syntaxe du Langage ... ne fait pas tout. Ceci est valable quel que soit le Langage et son écosystème...

Dernière modification par claudius01 (Le 25/07/2016, à 23:08)

Hors ligne