GameCorp - Index des forumsGame MakingProgrammationLangages C et C++Fonctions Saisie --- Expression mathématique
Fonctions Saisie --- Expression mathématique
| Tersaken |
Posté le 08 Avr 2008 à 23:00
|
|
![]() Messages : 302 GCPoints : 23103 |
Oulà, a l'origine je voulais tester une fonction du forum et me voilà dans l'impossibilité de supprimer mon propre poste ... Bon bref, je vais en profiter pour vous demandez "une astuce" J'ai conçu une fonction de saisie qui vous permet de rentrer une expression mathématique ( ne travaille qu'avec des nombres entiers pour le moment ). A titre d'exemple, vous pourrez demander au programme de calculer "2+3*(3+5)+2*2". Celui ci est censé retourner le bon résultat. J'aimerais convertir cette fonction en dll, Y a t-il a priori une méthode simple pour arriver a mes fins ... merci d'avance Code : #include <cstdlib>
#include <iostream>
#include <string>
#include <math.h>
using namespace std;
// Prototypes de fonctions.
int value( char c ) ;
double GetNumber( string s );
int length( string s );
double Compute( string s );
string Calculer( string s ) ;
string FromIntToString( double ent );
string AddTo( string s, char c, int p );
string Convert( string s );
string AfficherCalculs(string s);
string ClearSpace( string s );
// ...
int main()
{
string v ;
cin >> v ;
cout << AfficherCalculs(v) << "n" ;
system("PAUSE");
}
// calcul d'une expression avec gestion des priorités ( parentheses seulement )
string AfficherCalculs(string s)
{
s = ClearSpace(s);
s = Convert(s);
return Calculer(s) ;
}
string Calculer( string s )
{
int lg = length(s);
int i = 0 ; // le compteur ;
bool etat = false ;
string s2 = "" ; // une chaine intermediaire ! :-)
string s3 = "" ; // la chaine a renvoyer
int Compt = 0 ; // compte le nombre de " ( ";
while ( i < lg )
{
if ( s[i] == '(' && etat == false )
{
etat = true ; i++ ; Compt = 1 ;
}
// on est dans une parenthese
if ( etat == true )
{
if ( s[i] == '(' ) { Compt ++ ;}
if ( s[i] == ')' ) { Compt -- ;}
if ( Compt != 0 )
{
s2 = s2 + s[i] ;
}
else
{
s3 = s3+Calculer(s2);
s2 = "";
etat = false ;
}
}
else
{
s3 = s3 + s[i] ;
}
i++;
}
return FromIntToString( Compute(s3) ) ;
}
// Calcul la valeur d'une expression... [ fonctionne parfaitement !! ]
double Compute( string s )
{
int i = 0 ; // pointeur!
int somme = 0 ; // contient la somme a renvoyer ;
string s_ = "" ; // chaine intermediaire
int lg = length(s) ; // longueur de s ;
char OldOp = '+' ; // contient l'operation a effectuer
while ( i < lg )
{
while ( s[i] != '+' && s[i] != '-' && s[i] != '*' && s[i] != '/' && i < lg )
{
s_ = s_+s[i] ;
i++;
}
switch ( OldOp ){
case '+' : somme = somme+GetNumber(s_);break;
case '-' : somme = somme-GetNumber(s_);break;
case '*' : somme = somme*GetNumber(s_);break;
case '/' : somme = somme/GetNumber(s_);break;
}
OldOp = s[i];
s_ = "" ;
i++;
}
return somme ;
}
// Extrait un nombre d'une expression.
double GetNumber( string s )
{
double a = 0 ;
int i = 0 ;
int lg = length(s);
while ( value(s[i]) >= 0 && value(s[i]) <= 9 && i < lg )
{
a = a*10+value(s[i]) ; i++ ;
}
return a ;
}
// renvoit la valeur du chiffre contenu dans c.
int value( char c )
{
return int(c)-48 ;
}
// renvoit la longueur i d'une chaine ;
int length( string s )
{
int i = 0 ;
while ( s[i] != '�' )
{
i++;
}
return i ;
}
// convertie un entier en string !
string FromIntToString( double ent )
{
int lg = log(ent)/log(10);
string s = "" ; // le string de retour !
int e = 0 ; // l'entier a traiter !
for( int x = lg ; x >= 0 ; x-- )
{
e = int(ent/pow(10,x));
s = s+char( e+48 ) ;
ent = ent - e*pow(10,x) ;
}
return s ;
}
// rajoute a la chaine s le caractere c a la position p
string AddTo( string s, char c, int p )
{
int lg = length(s);
string s2 = "" ; // chaine de retour.
for( int x = 0 ; x < lg ; x++ )
{
if (x == p){ s2=s2+c ; }
s2 = s2+s[x] ;
}
return s2 ;
}
// Adresse le parenthesage d'une expression.
string Convert( string s )
{
int lg = length(s) ;
int i = 0 ;
int old = 0 ;
int nw = 0 ;
string s2 = "" ;
bool etat = true ;
bool para = false ;
while ( i < lg )
{
if ( s[i] == '(' ) { para = true ; }
if ( s[i] == ')' ) { para = false ; }
if ( ( s[i] == '+' || s[i] == '-') && para == false )
{
if ( etat == false )
{
etat = true ;
}
else
{
nw = i ;
etat = false;
s = AddTo(s,')', nw );
s = AddTo(s,'(', old );
old = nw+3;
lg = length(s) ;
}
}
i++;
}
// en sortie on ferme la parenthese si besoin est !
if ( etat == true)
{
s = AddTo(s,'(', old );
s = s+')';
}
return s;
}
// on supprime tous les espaces nocifs a la comprehension du calcul.
string ClearSpace( string s )
{
int lg = length(s);
string s2 = "" ; // la chaine de retour
for( int x = 0 ; x < lg ; x++ )
{
if ( s[x] != ' ' )
{
s2 = s2+s[x];
}
}
return s2;
}
Dernière édition le 08 Avr 2008 à 23:05
|
|
| Loack |
Posté le 09 Avr 2008 à 12:54
|
|
![]() Messages : 62 GCPoints : 24761 |
Pourquoi tu n'es pas passé par un arbre binaire pour analyser ton expression mathématique ? | |
| Tersaken |
Posté le 09 Avr 2008 à 13:42
|
|
![]() Messages : 302 GCPoints : 23103 |
Parce que je ne connais pas cette méthode J'ai ensuite mis au point un programme qui applique les parentheses de façon a ce que l'expression soit comprehensible par la fonction precedente ... Franchement il n'y a rien de compliquer, j'ai du refaire des fonctions qui sont peut etre deja presente dans les librairies dont je me sers ici ( length, conversion d'un entier en chaine et reciproquement ). Si jamais tu as un tuto sur les arbres, je suis prenneur... On avait tout de même vu les arbres binaires en cours avec le langage "scheme" ( si certains connaissent ) mais en y repensant, ça revient au même qu'un systeme qui applique des "parentheses". [ edit : @mod, ça serait sympa de mettre au point qui cache le code par defaut, et qui permet, via un simple clique de le rendre visible )
Dernière édition le 09 Avr 2008 à 13:44
|
|
| Loack |
Posté le 09 Avr 2008 à 17:19
|
|
![]() Messages : 62 GCPoints : 24761 |
Hellow, Voilà le site où ma prof a prit ses cours: http://depinfo.u-cergy.fr/~bourdon/enseignement/indexL1-MPI-I200.html Il faut fouiller dans les differentes parties, tu trouvera vers la partie 10 les arbres :) Tu lis donc le cours sur les arbres binaire, et puis après tu verras comment l'appliquer pour les expressions arithmetiques (avec le lien suivant: http://www.chambily.com/recursivite/chap_VII_3.htm ) Si tu as des questions hésites pas à prendre mon MSN j'pourrai t'aider :) Tu verras les arbres, une fois qu'on y goute, on s'en passe plu ^_^ |
|
| Tersaken |
Posté le 09 Avr 2008 à 19:09
|
|
![]() Messages : 302 GCPoints : 23103 |
Merci, trés bon cours, extrement bien ficelé ! |
|
| Darktib |
Posté le 09 Avr 2008 à 21:43
|
|
![]() Messages : 4017 GCPoints : 347288 |
Pas mal comme code... Et le cours est bien écrit^^ Sinon pour la dll tu peux créer un projet dll (avec MSVCC ou C::B Puis quand tu veux utiliser la dll il te faudra mettre les prototypes des fonctions au déébut de ton main, et de linker la lib créée avec la dll. Normalement ca marche^^ |
|
| Tersaken |
Posté le 08 Juin 2008 à 15:34
|
|
![]() Messages : 302 GCPoints : 23103 |
Bonjour, je me suis finalement résigné, ( mais quel plaisir ! ) à coder le programme précédent sous forme d'arbre binaire Je pense que je suis arrivé à maturité du programme, mais avant toute diffusion ( notamment sous forme de dll ) je souhaiterais ( du moins ça me serait trés utile [ C'est logiquement un .zip, mais vu que j'heberge le fichier sur ifrance, je l'ai renommé en .zop pour que vous puissiez le télécharger , il suffit donc de renommer l'extension Attention, les expressions doivent être correctement écrites ( pensez aux parenthèses ) ... Le programme ne "comprend" pas les espaces de vos expressions ( bien que j'avais mis au point une fonction pour les supprimer mais par je ne sais quel mystère, elle ne veut pas fonctionner ) ... Si vous rencontrez le moindre bug, exprimez vous ! ( tout en soulignant ce que vous avez tapez pour réussir a obtenir un resultat incorrect ou voir, a ce que le programme plante ) Merci d'avance ! [edit : ah j'oubliais, pour séparer la partie entiere et décimale, il suffit d'utiliser un point ( genre 3.2 ) et non une virgule ( bon ça peut vous paraitre logique mais j'en connais qui se tromperaient ^^' ) Le resultat est un type float, donc ne vous attendez pas une à une grande précision au niveau du nombre de décimales ... voilà [edit 2 ; arg j'ai crié victoire trop tot il y a au moins un bug qui persiste 8-/ ) edit 3 ; bon normalement ça devrait fonctionner comme sur des roulettes ( le même lien ! )
Dernière édition le 08 Juin 2008 à 18:00
|
|
| Darktib |
Posté le 08 Juin 2008 à 15:49
|
|
![]() Messages : 4017 GCPoints : 347288 |
Pour moi ca marche pas mal^^ Par contre j'ai remarqué que les lettres ont aussi une valeur, genre A=17 ou 'exit' = 60000 et des poussieres Je n'ai eu aucun bug et apparement les décimals sont plutot précis. |
|
| Tersaken |
Posté le 09 Juin 2008 à 13:59
|
|
![]() Messages : 302 GCPoints : 23103 |
Merci d'avoir tester Je ferais un automate qui vérifira si l'expression entrée est correcte ! ça serait sympa que d'autres testent, j'ai tendance a rentrer des chaînes qui se ressemblent un peu, donc c'est un peu dur d'avoir du recul |
|
| Mod |
Posté le 09 Juin 2008 à 14:25
|
|
![]() Messages : 4954 GCPoints : 2100823 |
Après test, ça fonctionne sans problème si on reste dans les chiffres. Je serai curieux de savoir comment tu as codé ton analyseur syntaxique, car il donne des résultats assez étranges par moment. Je pense à l'utilisation de lettres. Par exemple, si je met p2, sachant que p <=> 64 , il me répond 642, comme s'il s'agissait d'une concaténation. Assez inattendu ^^. Ah, et sinon, pas de puissance ? J'aurais bien testé un petit 4^(1/2) :p |
|
| Darktib |
Posté le 09 Juin 2008 à 18:47
|
|
![]() Messages : 4017 GCPoints : 347288 |
Pour les lettres et les chiffres, normalement 0~9 <=> ASCII 48~57. Donc apres il te suffit de vérifier la plage du nombre rentré. @Mod : ca me parait logique, vu qu'il s'agit du meme comportement avec les chiffres (si tu rentre 32 tu aura bien 32 et non 6) |
|
| Tersaken |
Posté le 09 Juin 2008 à 19:03
|
|
![]() Messages : 302 GCPoints : 23103 |
Darktib a raison ( concernant la comportement " étrange " ) Citation :
Oui je m'en suis servis pour convertir mes strings en entier, toutes les fonctions ou presque sont codés main ^^' Pour l'automate, c'est un peu plus compliqué que cela, il faut voir s'il n'y a pas d'opération " illégale " [ du genre (*3) ] ; rien d'infaisable cependant [ en gros je divise a chaque fois l'expression en deux, genre (a*b) devient (a)*(b) , il suffit de voir quand a ou b n'est pas un nombre et renvoyer une erreur ) Sinon je vais rajouter certaines constantes ( e pour l'exponentiel, Pi etc ) les fonctions usuelles et effectivement, les puissances^^' Je vais tenter d'y rajouter le calcul de dérivée ( a une variable pour le moment ) voir le calcul d'intégral ( ça va être beaucoup plus dur J'ai réussi a en faire une dll, mais j'avoue que le comportement est assez étrange ... fin je me pencherai dessus plus tard ... Merci en tout cas |
|
| Loack |
Posté le 10 Juin 2008 à 01:15
|
|
![]() Messages : 62 GCPoints : 24761 |
Hm, sinon tu pouvais faire ça: Code : int number, number2; std::string s = "123 124"; std::istringstream iss(s); iss >> number >> number2; Par exemple si |s| = "123 124" tu auras |number| = 123 |number2| = 124 (pense à inclure l'entête sstream: #include <sstream>) -- (j'espère pas t'avoir dit de bêtise, j'ai pas testé ce que je viens de te dire.) J'espère que ça pourra t'aider en tout cas. :) |
|
GameCorp - Index des forumsGame MakingProgrammationLangages C et C++Fonctions Saisie --- Expression mathématique
Répondre



