vangeurmasker
Messages postés99Date d'inscriptionmercredi 12 mai 2004StatutMembreDernière intervention29 mars 2006
-
29 déc. 2004 à 17:04
cs_JCDjcd
Messages postés1138Date d'inscriptionmardi 10 juin 2003StatutMembreDernière intervention25 janvier 2009
-
30 déc. 2004 à 12:55
J'ai créé un projet sous VC++ 6 pour faire une calcullette qui annalyse une chaine entrée. Lors de la compilation je n'ai aucune erreur. C'est a l'execution que l'erreur apparait.
Si je tape : ((1)) le prog plante
mais si je tape ((12)) ou ((1*1)) j'ai le bon résultat.
Je ne comprend pas d'ou vient l'erreur.
voici le code :
// supercalc.cpp : Defines the entry point for the console application.
//
int testchaine(char * calcul)//vérifie si la chaine entrée est correcte(voir main pour les erreurs)
{
unsigned int x;
if (calcul[0]=='-'&&isalpha(calcul[1])) return 2;
for (x=0;x<strlen(calcul);x++)
{
if (!isalnum(calcul[x])&&!(calcul[x]=='+'||calcul[x]=='('||calcul[x]==')'||calcul[x]=='-'||calcul[x]=='*'||calcul[x]=='/'||calcul[x]=='.')) return 3;
if ((calcul[x]=='+'||calcul[x]=='-'||calcul[x]=='*'||calcul[x]=='/')&&(calcul[x+1]=='*'||calcul[x+1]=='/')) return 4;
if (calcul[x]==')'&&isalnum(calcul[x+1])) return 5;
if (isalpha(calcul[x])&&isdigit(calcul[x+1])) return 6;
if (!isalnum(calcul[x])&&calcul[x]!=')'&&calcul[x+1]=='-'&&isalpha(calcul[x+2])) return 7;
}
return 0;
}
double valeur (char lettre)
{
if (ERREUR==0)
{
char valeur[40];
cout<<"Quelle est la valeur de "<<lettre<<" ?"<<endl;
cin>>valeur;
return calculer(valeur);
}
else return 9845687576.143266545654;//pour ne pas avoir a demander de valeurs en cas d'erreurs
}
char *analyser(char *calcul)//essaye de corriger la chaine entrée
{
int x;
int nb=0;
for (x=0;(unsigned)x<strlen(calcul)+1;x++)//remplace les ',' par des '.' les ':' par des '/' et supprime les espaces
{
if(calcul[x]==',') calcul[x]='.';
if(calcul[x]==':') calcul[x]='/';
calcul[x-nb]=calcul[x];
if(calcul[x]==' ') nb++;
}
nb=0;
for (x=0;(unsigned)x<strlen(calcul);x++)//compte les parentheses manquantes
{
switch (calcul[x])
{
case '(':nb++;break;
case ')':nb--;
}
}
calcul=(char *)realloc(calcul,(strlen(calcul)+abs(nb)+1)*sizeof(char));
if (nb<0)//rajoute des parentheses en cas d'oubli
{
for (x=strlen(calcul)+1;x>=0;x--) calcul[x-nb]=calcul[x];
for (x=0;(signed)x<-nb;x++) calcul[x]='(';
}
if (nb>0)//idem
{
int longueur=strlen(calcul);
for (x=longueur;(signed)x<longueur+nb;x++) calcul[x]=')';
calcul[x]='\0';
}
nb=0;
for (x=0;(unsigned)x<strlen(calcul)+1;x++) if((calcul[x]==')'&&calcul[x+1]=='(')||(isalpha(calcul[x])&&isalpha(calcul[x+1]))||((isdigit(calcul[x])||calcul[x]=='.')&&(isalpha(calcul[x+1])||calcul[x+1]=='('))||(calcul[x]=='.'&&calcul[x+1]=='.')) nb++;
calcul=(char *)realloc(calcul,(strlen(calcul)+nb+1)*sizeof(char));
for (x=strlen(calcul)+nb;x>=0;x--)//explicite les multiplication implicites
{
calcul[x]=calcul[x-nb];
if((calcul[x]==')'&&calcul[x+1]=='(')||(isalpha(calcul[x])&&isalpha(calcul[x+1]))||((isdigit(calcul[x])||calcul[x]=='.')&&(isalpha(calcul[x+1])||calcul[x+1]=='('))||(calcul[x]=='.'&&calcul[x+1]=='.'))
{
nb--;
calcul[x]='*';
}
}
nb=0;
for (x=0;(unsigned)x<strlen(calcul)+1;x++) if((!isdigit(calcul[x])&&calcul[x+1]=='.')||(calcul[x]=='.'&&!isdigit(calcul[x+1]))) nb++;
calcul=(char *)realloc(calcul,(strlen(calcul)+nb+1)*sizeof(char));
for (x=strlen(calcul)+nb;x>=0;x--)//place les zero implicite(.1->0.1)
{
calcul[x]=calcul[x-nb];
if((!isdigit(calcul[x])&&calcul[x+1]=='.')||(calcul[x]=='.'&&!isdigit(calcul[x+1])))
{
nb--;
calcul[x]='0';
}
}
ERREUR=testchaine(calcul);
return calcul;
}
double evaluer(char *calcul)//rend le resultat d'une opération elementaire
{
char operateur=0;
int x;
int position;
char left[40],right[40];
double gauche,droite;
for(x=strlen(calcul)-1;x>=0;x--)//recherche la position de l'opérateur
{
switch (calcul[x])
{
case '+':operateur=1;position=x;break;
case '-':
{
if(x!=0)
{
operateur=2;
position=x;
}
break;
}
case '*':operateur=3;position=x;break;
case '/':operateur=4;position=x;
}
}
if (operateur==0) return atofm(calcul);//si aucun opérateur
for(x=0;x=0;x--) cvaleur[x+1]=cvaleur[x];
cvaleur[0]='-';
}
else itoa((int)resultat,cvaleur,10);
char caractere[2]=".";
strcat(cvaleur,caractere);
resultat-=(int)resultat;
for (x=0;x<15;x++)//ecriture de la partie décimale
{
resultat*=10;
itoa((int)resultat,caractere,10);
strcat(cvaleur,caractere);
resultat-=(int)resultat;
}
if (debut>=0&&calcul[debut-1]=='(')//deplace les limites de chaine pour supprimer les parenthese
{
debut--;
fin++;
}
souschaine=(char *)realloc(souschaine,(debut+strlen(cvaleur)+strlen(calcul)-fin)*sizeof(char));
for (x=0;x<debut;x++) souschaine[x]=calcul[x];//réécrit la premiere partie de la chaine identique
for (x;(unsigned)x<(debut+strlen(cvaleur));x++) souschaine[x]=cvaleur[x-debut];//écrit la resultat
for (x;(unsigned)x<(debut+strlen(cvaleur)+strlen(calcul)-fin-1);x++) souschaine[x]=calcul[x-debut-strlen(cvaleur)+fin+1];//réécrit la fin de la chaine
souschaine[x]='\0';
calcul=(char *)realloc(calcul,(strlen(souschaine)+1)*sizeof(char));
for(x=0;(unsigned)x<=strlen(souschaine);x++) calcul[x]=souschaine[x];//met la souschaine dans calcul
// free(souschaine);
free(cvaleur);
return calcul;
}
double calculer(char *calcul)
{
calcul=analyser(calcul);
int longueur;
int position, x,priorite,mini;
int nombre=1;
int debut,fin;
while(1)
{
longueur=strlen(calcul);
position=0;
priorite=4;
mini=4;
for(x=0;x<longueur;x++)//recherche le calcul a effectuer (priorité la plus basse)
{
switch (calcul[x])
{
case '(':
case ')':priorite=1;break;
case '*':
case '/':priorite=2;break;
case '+':
case '-':if(x>0||calcul[x]=='+') priorite=3;
}
if(priorite<mini)
{
mini=priorite;
position=x;
}
}
switch (mini)
{
case 1://si parentheses, calcul l'interieur
{
nombre=1;
for(x=position+1;x<longueur;x++)
{
if (calcul[x]=='(') nombre++;
if (calcul[x]==')') nombre--;
if (nombre==0) break;
}
if (calcul[x]==')') x--;
fin=x;
debut=position+1;
calcul=decoupe(debut,fin,calcul);
break;
}
case 2:
case 3://si il y a un opérateur détermine les limites a droite et a gauche puis calcule
{
if (calcul[0]=='-')
{
mini=0;
for (x=1;(unsigned)x<=strlen(calcul);x++) if (calcul[x]=='+'||calcul[x]=='-'||calcul[x]=='*'||calcul[x]=='/'||calcul[x]=='('||calcul[x]==')') mini++;
if (mini==0) return atofm(calcul);
}
for(x=position+2;(unsigned)x<=strlen(calcul);x++) if(calcul[x]=='+'||calcul[x]=='*'||calcul[x]=='/'||(calcul[x]=='-'&&x!=position+2))break;
if(calcul[x]=='+'||calcul[x]=='-'||calcul[x]=='*'||calcul[x]=='/'||(unsigned)x>strlen(calcul)) x--;
fin=x;
for(x=position-1;x>=0;x--) if(calcul[x]=='+'||calcul[x]=='-'||calcul[x]=='*'||calcul[x]=='/')break;
if(calcul[x]=='+'||(calcul[x]=='-'&&(x!=0&&(calcul[x-1]!='+'||calcul[x-1]!='-'||calcul[x-1]!='*'||calcul[x-1]!='/')))||calcul[x]=='*'||calcul[x]=='/'||x<0) x++;
debut=x;
calcul=decoupe(debut,fin,calcul);
break;
}
case 4:
{
double resultat=atofm(calcul);//si aucun calcul a effectuer retourne valeur
// free (calcul);
return resultat;
}
}
}
}
void TailleEcran(short x,short y)//redimensionne la fenetre de la console
{
const HANDLE MaConsoleEcran=GetStdHandle(STD_OUTPUT_HANDLE);
COORD MaTailleEcran={x,y};
SMALL_RECT MonRectangle={0,0,(short)(x-1),(short)(y-1)};
SetConsoleScreenBufferSize(MaConsoleEcran,MaTailleEcran);
SetConsoleWindowInfo(MaConsoleEcran,FALSE,&MonRectangle);
}
void main()
{
TailleEcran(80,300);
char * calcul=(char *)malloc(256*sizeof(char));
while (1)
{
if (ERREUR==0)
{
calcul=(char *)realloc(calcul,256*sizeof(char));
cout<<"Supercalc\n\nTapez le calcul a effectuer\n"<<flush;
gets(calcul);
if (calcul[0]=='\0')
{
free(calcul);
break;
}
double resultat;
resultat=calculer(calcul);
if(ERREUR==0) cout<<"Le resultat est :"<<setprecision(15)<<resultat<<endl;
}
else
{
cout<<"ERREUR : ";
switch (ERREUR)
{
case 1:cout<<"division par 0";break;
case 2:cout<<"affectation de signe impossible a une variable";break;
case 3:cout<<"Un caractere est incomprehensible dans le calcul";break;
case 4:cout<<"Deux operateur incompatibles se suivent dans le calcul";break;
case 5:cout<<"Une parenthese ne peut etre suivie d'une valeur";break;
case 6:cout<<"Une variable ne peut etre suivie d'un chiffre";break;
case 7:cout<<"Affectation de signe impossible a une variable";break;
default:cout<<"Erreur indeterminée";
}
cout<<endl;
ERREUR=0;
}
}
exit(1);
}
vangeurmasker
Messages postés99Date d'inscriptionmercredi 12 mai 2004StatutMembreDernière intervention29 mars 2006 29 déc. 2004 à 19:22
dans mon code la ligne qui provoque l'erreur est :
return resultat;
a la fin de la fonction double calculer(char *calcul)
Le debugger m'envoie a la ligne 947 du fichier Sbheap.c
L'erreur est une violation d'acces.
Si je supprime cette ligne dans Sbheap.c il y a quand meme l'erreur sur une ligne vide !!! Et si je saute une ou des lignes avant l'erreur est toujours a la ligne 947.
Je comprend rien.
Merci de m'aider.
vangeurmasker
Messages postés99Date d'inscriptionmercredi 12 mai 2004StatutMembreDernière intervention29 mars 2006 30 déc. 2004 à 00:38
l'ensemble du switch est dans un "while(1)".
le switch boucle jusqu'a arriver dans le "case 4".
Le "case 4" correspond au cas ou aucune parenthese ni aucun operateur n'est présent dans la chaine(valeur ou lettre).
La fonction "atofm(calcul)" met la valeur correspondante dans la variable resultat. et on retourne le resultat a main ou a la fonction appelante("atofm" ou "decoupe").
vangeurmasker
Messages postés99Date d'inscriptionmercredi 12 mai 2004StatutMembreDernière intervention29 mars 2006 30 déc. 2004 à 00:59
J'ai essayé de compiler avec dev C++. la chaine "((1" ne plante plus mais au bout de deux ou trois calcul le prog se ferme tout seul(je n'ai pas ce probleme avec visual C++).
Si quelqu'un connait les differences de compilation entre VC++ et Dev C++ se serai super sympa de m'aider.