Programme permetant de faire un calcul simple. [Résolu]

Signaler
Messages postés
8
Date d'inscription
mercredi 18 février 2009
Statut
Membre
Dernière intervention
20 mars 2009
-
Messages postés
21
Date d'inscription
vendredi 13 octobre 2006
Statut
Membre
Dernière intervention
25 mars 2011
-
Salut tout le monde,
J'ai créé un programme en C qui permet de faire un calcul simple.
Pour se faire, l'utilisateur doit saisir une chaine de caractères sous la forme "opérande1 opérateur opérande2",
une fonction suprEspaces supprimera les espaces, une fonction extractop fera l'extraction de l'opérateur, deux fonctions
extractx1 et extractx2 extrairont les deux opérandes enfin la fonction calcul effectuera l'opération :
voici mon code :
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void suprEspace(char *expr);
void extractop(char *expr,int *ind,char *op);
int extractx1(char *expr,int ind);
int extractx2(char *expr,int ind);
int calcul(int x1,int op,int x2);
void main()
{char expr[255];int ind;char op;int x1,x2,ans;
 printf("Donnez l'expression : ");
 gets(expr);
 suprEspace(expr);
 extractop(expr,&ind,&op);
 x1=extractx1(expr,ind);
 x2=extractx2(expr,ind);
 printf("\n%d\n",x1);
 printf("\n%d\n",x2);
 puts(expr);
 ans=calcul(x1,op,x2);
 printf("\n%s=%d",expr,ans);
 getch();
}

void suprEspace(char *expr)
{int i,j,n;
n=strlen(expr);
for (i=0;i<n;i++)
  if (expr[i]==' ')
                   {
                    for(j=i;j<(n);j++)
                     expr[j]=expr[j+1];
                   }
}

void extractop(char *expr,int *ind,char *op)
{int n,i;
n=strlen(expr);
for (i=0;i<n;i++)
  if ((expr[i]=='+')||(expr[i]=='-')||(expr[i]=='*')||(expr[i]=='/'))
  {*ind=i;
  *op=expr[i];}
  }

int extractx1(char *expr,int ind)
{int i,x;char iks[100];
 for (i=0;i<ind;i++)
    iks[i]=expr[i] ;

x=atoi(iks);
return x;
}
int extractx2(char *expr,int ind)
{int i=0,y;char igrg[100];
 while (expr[i]!='\0')
 {
    igrg[i]=expr[ind+i] ;
    i++; }

y=atoi(igrg);

return y;
}
int calcul(int x1,int op,int x2)
{
 switch(op)
 {
  case '+':
       return (x1+x2);
  case '-':
       return (x1-x2);
  case '*':
       return (x1*x2);

}
return(x1%x2);
}

Borland arrive  a compiler le code mais le programme plante lorsque j'essaie d'effectuer une division et je pense que c'est dû au type de retour lors d'une division.
aussi j'aimerais créer une fonction qui permet de vérifier si l'expression saisie est valide ou pas alors svp faites moi part de vos idées.
MERCI d'avance

12 réponses

Messages postés
1054
Date d'inscription
samedi 2 octobre 2004
Statut
Membre
Dernière intervention
9 juillet 2013
6
Dans ta fonction int extractx2(char *expr,int ind)
il faut mettre:
igrg[i]=expr[ind+i+1] ;
Si tu ne mets pas le +1, le premier caractère est l'opérateur. Ca ne gène pas pour atoi() pour le  + et le - mais pour le \, ça ne passe pas.
A+
____________________________________________________________________________
Mon site internet :  
http://ImAnalyse.free.fr
Messages postés
1054
Date d'inscription
samedi 2 octobre 2004
Statut
Membre
Dernière intervention
9 juillet 2013
6
Salut
Pourquoi dans ta fonction calcule la division n'a pas le droit à son "case" dans le switch?
et return(x1%x2);  donne le reste de la division euclidienne, et non pas la division. Il faut utiliser /.
Mais il faut toujours avant une division vérifier que l'on ne divise pas par 0...
A+

____________________________________________________________________________
Mon site internet :  
http://ImAnalyse.free.fr
Messages postés
8
Date d'inscription
mercredi 18 février 2009
Statut
Membre
Dernière intervention
20 mars 2009

Re,
J'ai fait sortir la division de la structure conditionnelle case parce que si je la remet dans le case le compilateur m'affiche un warning qui est "Function should return a value" et puis quand je l'exécute et que j'effectue une division une fenêtre s'affiche m'indiquant "Thread stopped".
Messages postés
21
Date d'inscription
vendredi 13 octobre 2006
Statut
Membre
Dernière intervention
25 mars 2011
26
A mon humble avis, le plus simple c'est ce qui suit
Attention : pas de test ou presque donc il faut peut-être vérifier avant la syntaxe de la chaîne passée (interdire qu'il y ait des doubles opérateurs comme dans "1 +* 2", et vérifier qu'on a bien 2 nombres).

#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main()
{
   char expr[255];
   char   *ptr;
   int op1, op2, res;
   char operation;

   printf("Donnez l'expression : ");
   gets(expr);
   ptr = strtok(expr, "+-/*%");
   if (ptr != NULL)
      operation = *ptr;
   else
   {
      printf("Il faut un opérateur parmi +,-,/,* et %\n");
      return;
   }
   op1 = atoi(expr);    // premier opérateur
   op2 = atoi(ptr+1);   // second opérateur
   switch(operation)
   {
   case '+':
      res = op1 + op2;
      break;
   case '-':
      res = op1 - op2;
      break;
   case '*':
      res = op1 * op2;
      break;
   case '/':
      if (!op2)
      {
         printf("Le diviseur ne doit pas être nul\n");
         return;
      }
      res = op1 / op2;
      break;
   case '%':
      if (!op2)
      {
         printf("Le diviseur ne doit pas être nul\n");
         return;
      }
      res = op1 % op2;
      break;
   }
   printf("%d %c %d = %d", op1, operation, op2, res);
}

Cordialement
Messages postés
8
Date d'inscription
mercredi 18 février 2009
Statut
Membre
Dernière intervention
20 mars 2009

Merci Pistol_pete, grâce a cette petite modification le programme fonctionne et effectue les opérations correctement.
mais je voudrais aussi pouvoir effectuer les division qui ont un résultat de type réel.
quant a ton code bzrd apres avoir mis un getch() a la fin quand j'entre une opératon ("1+2") ça m'affiche (1 1 0 = 1).
Messages postés
1054
Date d'inscription
samedi 2 octobre 2004
Statut
Membre
Dernière intervention
9 juillet 2013
6
Pour les reels il faut faire un cast;
int x1=5,x2=2;
double Res = x1/(double) x2;
printf("%f,\n",Res);    //Affiche 2.5

A+

____________________________________________________________________________
Mon site internet :  
http://ImAnalyse.free.fr
Messages postés
21
Date d'inscription
vendredi 13 octobre 2006
Statut
Membre
Dernière intervention
25 mars 2011
26
Désolé, erreur au début du code :

void

main()

{
   char expr[255];

   char *ptr;

   int op1, op2, res;
   int   len;                              // changer là

   char operation;

   printf("Donnez l'expression : ");

   gets(expr);

   len = strspn(expr, "1234567890 \t");   // changer là

   ptr = expr + len;                      // et là
...
// le reste est identique
Messages postés
8
Date d'inscription
mercredi 18 février 2009
Statut
Membre
Dernière intervention
20 mars 2009

je n'arrive pas a intégrer le cast dans ma fonction calcul. 
Messages postés
1054
Date d'inscription
samedi 2 octobre 2004
Statut
Membre
Dernière intervention
9 juillet 2013
6
Le plus simple est de faire tous tes calcules avec des double...

____________________________________________________________________________
Mon site internet :  
http://ImAnalyse.free.fr
Messages postés
21
Date d'inscription
vendredi 13 octobre 2006
Statut
Membre
Dernière intervention
25 mars 2011
26
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main()
{
   char expr[255];
   char   *ptr;
   float   op1, op2, res;      // Modif  <<<<<<
   char operation;

   printf("Donnez l'expression : ");
   gets(expr);
   ptr = strtok(expr, "+-/*%");
   if (ptr != NULL)
      operation = *ptr;
   else
   {
      printf("Il faut un opérateur parmi +,-,/,* et %\n");
      return;
   }
   op1 = atof(expr);    // premier opérateur      <<<<<<
   op2 = atof(ptr+1);   // second opérateur      <<<<<<

...

  printf("%f %c %f = %f", op1, operation, op2, res);
}

Voilà : tout en float, pas besoin de cast !
Messages postés
8
Date d'inscription
mercredi 18 février 2009
Statut
Membre
Dernière intervention
20 mars 2009

Merci bzrd pour ton code.
j'aimerais introduire une boucle pour toutes les instructions du genre :
do
 {
 printf("Donnez l'expression : ");
 gets(expr);
 suprEspace(expr);
 extractop(expr,&ind,&op);
 x1=extractx1(expr,ind);
 x2=extractx2(expr,ind);
 printf("\n%d\n",x1);
 printf("\n%d\n",x2);
 puts(expr);
 ans=calcul(x1,op,x2);
 printf("\n%s=%d",expr,ans);

 do
 {printf("\nVoulez vous effectuer une autre opération? o=OUI/n=NON\n\nChoix :\t");
 scanf("%c",&rep);
 }
 while ((rep='o')||(rep='O')||(rep='n')||(rep='N'));

le code comporte quelques warnings mais il s'execute le probleme c'est que la boucle ne fonctionne pas comme je le souhaite.
Messages postés
21
Date d'inscription
vendredi 13 octobre 2006
Statut
Membre
Dernière intervention
25 mars 2011
26
Salut,

on dirait que ton while n'est pas bon :
 while ((rep='o')||(rep='O')||(rep='n')||(rep='N'));Comme tu as mis des simples et pas des, tu as des affectations (d'où surement les warnings).

En fait l'équivalent de ton while c'est ça en gros :
rep = 'o';
if (rep == 0) rep='O';
if (rep == 0) rep='n';
if (rep == 0) rep='N';
donc tu te retrouves systématiquement avec rep='o'

Il faudrait mettre 
 while ((rep=='o')||(rep=='O')||(rep=='n')||(rep=='N'));

Mais en plus ton test est inversé, puisque ton while doit s'arrêter quand tu as 'o', 'O', 'N' ou 'n', donc il faut
 while ((rep!='o') && (rep!='O') && (rep!='n') && (rep='N'));

Enfin il manque un while dans l'extrait que tu donnes.
Je te conseille ça :

rep = 'o';   // init pour entrer dans la bouclewhile (rep 'O' || rep 'o')
{
   printf("Donnez l'expression : ");
   gets(expr);
   suprEspace(expr);

   extractop(expr, &ind, &op);
   x1 = extractx1(expr, ind);
   x2 = extractx2(expr, ind);
   printf("\n%d\n", x1);
   printf("\n%d\n", x2);
   puts(expr);
   ans = calcul(x1, op, x2);
   printf("\n%s=%d", expr, ans);

  do
  {
     printf("\nVoulez vous effectuer une autre opération? o=OUI, n=NON\n\nChoix :\t");
     scanf("%c", &rep);
  }
  while ((rep!='o') && (rep!='O') && (rep!='n') && (rep='N'));
}

C'est un peu "simpliste", mais ça me semble correct !

Petite remarque personnelle, je te conseille de mettre systématiquement un espace après chaque virgule (comme en français) pour aérer ton code et idem avant/après la plupart des opérateurs :
      ans = calcul(x1, op, x2);
plutôt que
      ans=calcul(x1,op,x2);
Ca ne coûte rien et c'est plus facile à relire.

Dernier point, en ce qui me concerne j'indente en mettant (comme toi) les { sur une ligne séparée. Avant je les mettais en fin de ligne mais j'ai passé trop de temps à chercher des bugs dûs à une mauvaise indentation, et en plus ça aère le code ! (tout à fait personnel et d'autres défendent la position inverse).

Cordialement