467,146 Members | 1,313 Online
Bytes | Developer Community
Ask Question

Home New Posts Topics Members FAQ

Post your question to a community of 467,146 developers. It's quick & easy.

Un plotter de fonctions mathematiques

Voila un plotter de fonctions simple ecrit
/*
* PLOT.CPP - Dessiner un graph
* Design & Programmation : ELAATIFI Sidi Mohamed
* <el******@menara.ma>
* 01/2005
*/
#include <conio.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <graphics.h>
#include <stdlib.h>
#include <dos.h>

#include "pile.h"
/*
******** Interpreteur ****************************
*/
/*
* Constantes & Macros
*/
#define MAXBUF 300
#define ZEROBUF(x) memset(x,0,MAXBUF)
/*
* la liste des symbole support‚s
*/
typedef enum
{
LeX = 1000, // variable x
Pi,
E1,
Nombre, // nombre entier
ParD, // prenthese droit
ParG, // --------- Gauche
Plus, // +
Moin, // -
Multiplier, // *
Diviser, // /
Sin, // Sinus
Cos, // Cosinus
Tan, // ...
Sqrt,
Ln,
Exp,
ACos,
ATan,
Sinh,
Cosh,
Tanh,
Pow,
Abs,
ASin,
Separateur, // Separateurs tel espace ' ' et nouvelle ligne '\n'
Erreur // Token indefini ou erreur
}Token;
/*
* Type lexical
*/
typedef struct
{
int s;
int d[100];
}Fonction;

typedef struct
{
int size;
char data[100];
}Buffer;
/*
* Donn‚es Globales utilis‚es dans tout le programme
*/
char valeurLex[MAXBUF];
int valeurLexTaille=0;
int valeurLexEntier=0;
/*
* Analyse lexicale
* ****************
* Ici on decrit toute les fonctions que l'analyseur peut
* utiliser ...
*/
int est_Num(char c)
{
return c >='0' && c <='9';
}
int est_Alpha(char c)
{
return c>='a'&& c<='z';
}
int est_Oper(char c)
{
return c=='+'||c=='*'||c=='-'||c=='/'||c=='^';
}
int est_Sep(char c)
{
return c==' '||c=='\n';
}
int est_Pars(char c)
{
return c==')'||c=='(';
}
char Get(Buffer* b)
{
return b->data[b->size++];
}
void Put(Buffer* b,char c)
{
//b->data[b->size--] = c;
b->size--;
}
Token AnalyseLexic(Buffer* b)
{
char c;
char done = 0; // false
ZEROBUF(valeurLex);
valeurLexTaille = 0;
//char* pstr = *p;

c = Get(b)/*fgetc(f)*/ ;

if(est_Num(c)) {
Put(b,c)/*ungetc(c,f)*/;
int s = sscanf((char*)(b->data+b->size),"%d",&valeurLexEntier);
b->size += s;
return Nombre;
}
else if(est_Oper(c)) {
switch(c)
{
case '+':
return Plus;
case '-':
return Moin;
case '/':
return Diviser;
case '*':
return Multiplier;
case '^':
return Pow;
}
}
else if(est_Alpha(c)) {
if( c == 'x' )
return LeX;
else
{
char buf[6];
int index=0;
while(c!=EOF && !done)
{
buf[index++] = c;
c = Get(b)/*fgetc(f)*/;
if(!est_Alpha(c))
{
Put(b,c) /*ungetc(c,f)*/;
done = 1;
}
}
buf[index] = 0;
strcpy(valeurLex,buf);

#define SI_F(x) if(!strcmp(buf,x))
#define ESI_F(x) else if(!strcmp(buf,x))
SI_F("sin")
return Sin;
ESI_F("cos")
return Cos;
ESI_F("tan")
return Tan;
ESI_F("exp")
return Exp;
ESI_F("sqrt")
return Sqrt;
ESI_F("ln")
return Ln;
ESI_F("asin")
return ASin;
ESI_F("acos")
return ACos;
ESI_F("atan")
return ATan;
ESI_F("sinh")
return Sinh;
ESI_F("cosh")
return Cosh;
ESI_F("tanh")
return Tanh;
ESI_F("abs")
return Abs;
ESI_F("pi")
return Pi;
return Erreur;

}
}
else if(est_Pars(c))
{
if( c == ')' )
return ParD;
return ParG;
}
else if(est_Sep(c))
return Separateur;
return Erreur;
}
/*
* Analyseur syntaxique
* ********************
* L'autre part du ce p'tit evaluateur d'expression ;-)
* ici j'aurais … decrir les fonctions du analyseur syntaxique
*/
void compileExpr(Fonction* fn,Buffer* b)
{
Pile pile;
char done = 0;
Token t;
fn->s = 0;
Pile_Init(&pile);

while(!done)
{
t = AnalyseLexic(b);

if( t == ParD)
{

Token t1 = (Token)Pile_Pop(&pile);//operation
Token t2 = (Token)Pile_Pop(&pile);// ParG
Token t = t1;
if( t1 == ParG )
t = t2;
fn->d[fn->s++] = t;
}
else if( t == Nombre )
{
fn->d[fn->s++] = valeurLexEntier;
}
else if( t == LeX )
{
fn->d[fn->s++] = LeX;
}
else if( t == Erreur)
{
while(pile.index > 0)
fn->d[fn->s++] = Pile_Pop(&pile);
done = 1;
}
else if( t == Separateur)
{
while(pile.index > 0)
fn->d[fn->s++] = Pile_Pop(&pile);
done = 1;
}
else
{
Pile_Push(&pile,t);
}
}
}
/*
* Evaluation de l'experssion compil‚
*/
#define INDEF 3000
double evalueExpr(Fonction f,double x)
{
rPile p;
double a = 0.0;

rPile_Init(&p);

double ans = 0.0;
for(int i=0;i<f.s;i++)
{
if( f.d[i] < LeX )
rPile_Push(&p,f.d[i]);
else
{
switch(f.d[i] )
{
case LeX:
rPile_Push(&p,x);
break;
case Plus:
ans = rPile_Pop(&p) + rPile_Pop(&p);
rPile_Push(&p,ans);
break;
case Moin:
ans = -rPile_Pop(&p);
if( p.index>0)
ans+=rPile_Pop(&p);
rPile_Push(&p,ans);
break;
case Multiplier:
ans = rPile_Pop(&p) * rPile_Pop(&p);
rPile_Push(&p,ans);
break;
case Diviser:
a = rPile_Pop(&p);
ans = rPile_Pop(&p);
if( a!= 0)
ans /= a;
else
return INDEF;
rPile_Push(&p,ans);
break;
case Sin:
ans = sin( rPile_Pop(&p) );
rPile_Push(&p,ans);
break;
/*case Sin:
ans = rPile_Pop(&p)
rPile_Push(&p,ans);
break;
*/
case Cos:
ans = cos( (double)rPile_Pop(&p) );
rPile_Push(&p,ans);
break;
case Tan:
ans = rPile_Pop(&p);
if( abs(ans) != M_PI_2)
ans = tan(ans);
else
return INDEF;
rPile_Push(&p,ans);
break;
case Ln:
ans = rPile_Pop(&p);
if( ans > 0)
ans = log( ans );
else
return INDEF;
rPile_Push(&p,ans);
break;
case Sqrt:
ans = rPile_Pop(&p);
if( ans >= 0)
ans = sqrt(ans);
else
return INDEF;
rPile_Push(&p,ans);
break;
case ASin:
a = rPile_Pop(&p);
if( a >= -1 && a <= 1)
ans = asin(a);
rPile_Push(&p,ans);
break;
case ACos:
a = rPile_Pop(&p);
if( a >= -1 && a <= 1)
ans = acos(a);
rPile_Push(&p,ans);
break;
case ATan:
a = rPile_Pop(&p);
ans = atan(a);
rPile_Push(&p,ans);
case Sinh:
a = rPile_Pop(&p);
ans = sinh(a);
rPile_Push(&p,ans);
break;
case Cosh:
ans = cosh(a);
a = rPile_Pop(&p);
rPile_Push(&p,ans);
break;
case Tanh:
a = rPile_Pop(&p);
tanh(a);
rPile_Push(&p,ans);
break;
case Exp:
ans = exp(rPile_Pop(&p));
rPile_Push(&p,ans);
break;
case Pow:
double b = rPile_Pop(&p);
a = rPile_Pop(&p);
if(b>0)
ans = pow(b,a);
else if( b!= 0)
if(a>0)
ans = mypow(b,(unsigned)a);
rPile_Push(&p,ans);
break;
case Abs:
a = rPile_Pop(&p);
ans = fabs(a);
rPile_Push(&p,ans);
break;
}
}

}
return rPile_Pop(&p);
}

/*
* Gestion graphique
*/
#define MINY 0
#define MINX 0
#define MAXX 639
#define MAXY 400
#define MIDX (MAXX+MINX)/2
#define MIDY (MAXY+MINY)/2
#define STER 30

int timeout = 0;
void const_graph()
{
int gdriver = DETECT, gmode, errorcode;
int xmax, ymax;
initgraph(&gdriver, &gmode, "..\\BGI");
}

void dessiner_fenetre(char * titre)
{
// cadre
setlinestyle(SOLID_LINE,1,1);
setcolor(15);
outtextxy(MIDX-4*strlen(titre),MAXY+70,titre);
setfillstyle(SOLID_FILL,1);
bar(MINX,MINY,MAXX,MAXY);
rectangle(MINX,MINY,MAXX,MAXY);

setlinestyle(DOTTED_LINE,1,1);
setcolor(9);

for(int i=-MIDX/STER;i<=MIDX/STER;i++)
{
line(MIDX+i*STER,MINY,MIDX+i*STER,MAXY);
}

for(i=-MIDY/STER;i<=MIDY/STER;i++)
{
line(MINX,MIDY+i*STER,MAXX,MIDY+i*STER);
}
// echele
setcolor(15);
setlinestyle(SOLID_LINE,1,1);
line(MIDX,MINY,MIDX,MAXY);
line(MINX,MIDY,MAXX,MIDY);
}

void dessiner_erreur(char* str)
{
setcolor(4);
outtextxy(MIDX-strlen(str)*4,MAXY+10,str);
}

void dessiner_foncstr(char *str)
{
setfillstyle(SOLID_FILL,0);
bar(MINX,MAXY+50,MINX+300,MAXY+60);
setcolor(15);
outtextxy(MINX,MAXY+50,"f(x) = ");
setcolor(7);
outtextxy(MINX+64,MAXY+50,str);
}
void lire_fonction(Fonction *fn,char *chaine)
{
char done = 0;
int index = 0;
char c;
while(!done)
{
dessiner_foncstr(chaine);
c = getch();
if( c == 13 )
{
done = 1;
chaine[index] = 0;
}
else
if( c == 8)
{
chaine[--index] = 0;
}
else
chaine[index++] = c;
}
Buffer b;
b.size = 0;
strcpy(b.data,chaine);
compileExpr(fn,&b);

}
void dessiner_fonction(Fonction fn,int zoomx,int zoomy)
{

const float fact = 1;

int y = 0;
float x = 0;
double e;
int gr[MIDX*2];

setlinestyle(SOLID_LINE,1,1);

for(int i=-MIDX;i<MIDX;i++)
{
x = (float) i / zoomx;
e = evalueExpr(fn,x);
if(e != INDEF)
{
y = (float) zoomy*e;
gr[MIDX+i] = MIDY-y;
}
else
{
gr[MIDX+i] = INDEF;
}

}
setcolor(14);
for(i=-MIDX;i<MIDX-1;i++)
{
int j = MIDX+i;
if((gr[j+1] <MAXY && gr[j+1] >MINY) && (gr[j]>=MINY && gr[j] <= MAXY))
{
if(timeout == 1)
delay(20);
line(j,gr[j],j+1,gr[j+1]);
}
//putpixel(j,gr[j],14);
}
}

void detr_graph()
{
closegraph();
}

/*
* Main
*/

char* INFO = "Par ELAATIFI Sidi Mohamed 2005 <el******@menara.ma>";
void main()
{
char choix;
char chaine[100];

clrscr();
Fonction f;
Buffer b;
b.size = 0;

f.d[0] = LeX;
f.s = 1;
strcpy(chaine,"x");
const_graph();
int zoomx = STER;
int zoomy = STER;
choix = 0;
while(choix != 27 && choix!='q')
{

if( zoomx <= 10 )
zoomx = 10;
if( zoomy <= 10)
zoomy = 10;
dessiner_fenetre(INFO);
dessiner_fonction(f,zoomx,zoomy);
dessiner_erreur("+ - * / Pour agrandir ou deminuer l'echelle |
s:entr‚e nouvelle | r:redefinir l'echelle");
dessiner_foncstr(chaine);
choix = getch();
switch(choix)
{
case '+':
zoomx+=5;
break;
case '-':
zoomx-=5;
break;
case '*':
zoomy+=5;
break;
case '/':
zoomy-=5;
break;
case 's':
memset(chaine,0,100);
memset(&f,0,sizeof(f));
lire_fonction(&f,chaine);
break;
case 'd':
dessiner_fenetre(INFO);
timeout = 1;
dessiner_fonction(f,zoomx,zoomy);
dessiner_erreur("+ - * / Pour agrandir ou deminuer l'echelle |
s:entr‚e nouvelle | r:redefinir l'echelle");
dessiner_foncstr(chaine);
timeout = 0;
break;
case 'r':
zoomx = STER;
zoomy = STER;
break;
}
}

detr_graph();

}
Nov 14 '05 #1
  • viewed: 1744
Share:
2 Replies
ELAATIFI Sidi Mohamed a écrit :
Voila un plotter de fonctions simple ecrit
/*
* PLOT.CPP - Dessiner un graph
* Design & Programmation : ELAATIFI Sidi Mohamed
* <el******@menara.ma>
Tu ne devrais pas mettre en clair ton adresse de courriel sur les
newsgroups, tu risques de te faire spammer.
* 01/2005
*/
#include <conio.h>
Pas portable
#include <graphics.h>
Pas portable
#include <dos.h>


Pas portable
Le reste a l'air intéressant, mais comme ce n'est pas portable, je ne
peux pas le compiler chez moi pour le tester, et je me vois mal analyser
toutes ces lignes de code pour essayer de déterminer ce que c'est censé
faire.
Dommage ...

De plus, tu crucipostes sans remplir le champs "Faire suivre à"
("Follow-up to" dans les lecteurs de news non francisés), et c'est ce
qu'on appelle communément quelque chose de *mal*.
Enfin, tu crucipostes en français sur un newsgroup non francophone, ce
qui est aussi, et bien, *mal*.

Je positionnes donc le fu2 sur fr.comp.lang.c ...
--
Florent "flure" C.
http://flure.free.fr
Nov 14 '05 #2
flure wrote:
ELAATIFI Sidi Mohamed a écrit :
Voila un plotter de fonctions simple ecrit
/*
* PLOT.CPP - Dessiner un graph
* Design & Programmation : ELAATIFI Sidi Mohamed
* <el******@menara.ma>
Tu ne devrais pas mettre en clair ton adresse de courriel sur les
newsgroups, tu risques de te faire spammer.
* 01/2005
*/
#include <conio.h>


Pas portable
#include <graphics.h>


Pas portable
#include <dos.h>


Pas portable

Le reste a l'air intéressant, mais comme ce n'est pas portable, je
ne peux pas le compiler chez moi pour le tester, et je me vois mal
analyser toutes ces lignes de code pour essayer de déterminer ce
que c'est censé faire.
Dommage ...


I believe this translates to roughly "It appears interesting, but
since it is non portable I have no way of compiling or testing it,
and I am not about to fix it. Pity".

De plus, tu crucipostes sans remplir le champs "Faire suivre à"
("Follow-up to" dans les lecteurs de news non francisés), et c'est
ce qu'on appelle communément quelque chose de *mal*.
Enfin, tu crucipostes en français sur un newsgroup non francophone,
ce qui est aussi, et bien, *mal*.
This I can't translate satisfactorily except that it is about
cross-posting. The following line announces that follow-ups have
been set.

Je positionnes donc le fu2 sur fr.comp.lang.c ...


I could not quote from the original, since it is so large that my
newsreader refuses to quote it at all. Thus this, and I am not
snipping anything because my french is too poor to do so
intelligently.

I believe you have adequately made the point that this code is
totally non-portable, and has no business on c.l.c. The OP might
have at least specified what system he ran it on, without which the
meaning of <graphics.h> <conio.h> <dos.h> can be absolutely
anything. There is a finite chance that it used the Borland 2.01
Turbo C, available in their museum.

However I also see that the original has tied itself to the ASCII
char set with the various "est_*" functions. This is again
unnecessary, and the reason that the things in <ctype.h> exist.

His avoidance of spaces causes confusion and warnings in systems
that can accept "=-" as synonymous with "-=". Most of them do the
right thing. Seems rather silly to conserve blanks when he uses
such excessive indentation in the first place.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
Nov 14 '05 #3

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

5 posts views Thread by Liberal | last post: by
2 posts views Thread by Charles Krug | last post: by
reply views Thread by Anand Ganesh | last post: by
7 posts views Thread by Jacky Luk | last post: by
3 posts views Thread by jamminc | last post: by
11 posts views Thread by mailforpr@googlemail.com | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.