#define dim_pile 100
#define composante float
/* static pour empecher l'acces direct exterieur*/
static composante pile[dim_pile];
static int sommet;
void init_pile(void)
{sommet=0;}
int pile_vide(void)
{return(sommet=0);}
int empiler(composante x)
/* retourne 0 si pas d'erreur (donc il restait de la place dans la pile) */
{
if(sommet<dim_pile)
{pile[sommet++]=x;return(0);}
else
{puts("pile saturee");return(1);}
}
composante depiler(void)
{
if (sommet>0) return(pile[--sommet]);
else puts("pile vide");return(0);
}
Si l'on desire un dimensionnement totalement dynamique
de la pile, on utilisera une liste (base_p_l) :#include <alloc.h>
#include <stdio.h>
#define composante float
typedef struct s_comp
{composante val;struct s_comp *prec;}type_comp;
static type_comp *sommet=NULL;
int empiler(composante x)
/* retourne 0 si pas d'erreur (donc il restait de la place dans la pile)*/
{
type_comp *nouv;
if((nouv=(type_comp*)malloc(sizeof(type_comp)))!=NULL)
{
nouv->val=x;
nouv->prec=sommet;
sommet=nouv;
return(0);}
else
{puts("pile saturee");return(1);}
}
composante depiler(void)
{
composante x;
if (sommet!=NULL)
{
x=sommet->val;
free(sommet); /*pour plus de surete, on peut passer par
une variable*/
sommet=sommet->prec;
return(x);
}
else puts("pile vide");return(0);
}
void init_pile(void)
{while(sommet!=NULL)depiler();}
int pile_vide(void)
{return(sommet==NULL);}
Pour certaines applications, on pourra preferer ne pas
liberer la memoire au depilage pour gagner du temps : au
depilage, mais aussi a l'empilage, on ne prend du temps que s'il
faut agrandir la pile. On peut egalement utiliser une pile de tableaux
dynamiques, ce qui permet d'economiser de la place memoire, sans
etre limite en taille.Pour les files, l'implantation des fonctions de base est similaire, par exemple par tableaux (base_f_t) :
#define dim_file 100
#define composante float
static composante file[dim_file];
static int bas,sommet,taille;
#define suiv(i) ((i)<dim_file-1 ? ((i)+1) : 0)
void init_file(void)
{bas=sommet=taille=0;}
int file_vide(void)
{return(taille=0);}
int enfiler(composante x)
/* retourne 0 si pas d'erreur (donc il restait de la place dans la pile)
*/
{
if(taille<dim_file)
{file[sommet]=x;sommet=suiv(sommet);taille++;return(0);}
else
{puts("file saturee");return(1);}
}
composante depiler(void)
{
composante x;
if (taille>0) {x=file[bas];bas=suiv(bas);taille--;return(x);}
else {puts("file vide");return(0);}
}
Il faut prevoir un indice pour chaque extremite
de la file. Il en serait de meme pour une implantation par liste
chainee (un pointeur pour chaque extremite).
#define operande 1
#define operateur 0
typedef struct
{int type;
union {float op_r;char op_c;}val;
}composante;
void saisie(void)
/* marche pour toute notation puisque ne verifie rien */
{
composante x;
char txt[100],*deb;
char rep;
init_pile();
printf("entrez operandes (nombres) et operateurs (+,-,*,/,C (cos),S)\n");
printf("separes par des blancs ou virgules\n");
fflush(stdin);
gets(txt); /* on lit un texte qui sera traite par apres */
deb=txt; /* deb pointe le debut du texte non encore traite */
do
{
while(*deb==' '||*deb==',') deb++;
if(*deb==0)break;
if(isdigit(*deb)||*deb=='.'||(*deb=='-'&&isdigit(*(deb+1))))
{
x.type=operande;
sscanf(deb,"%f",&(x.val.op_r));
empiler(&x);
while(isdigit(*deb)||*deb=='.') deb++; /*pointer la suite*/
}
else /*cas d'un operateur */
{
x.val.op_c=toupper(*(deb++));
x.type=operateur;
empiler(&x);
}
}
while(1);
}
float eval_post(void)
{
float r1,r2;
composante x;
if(depiler(&x)!=0) {puts("expression non postfixee");return(0);}
if(x.type==operande) return(x.val.op_r);
/* else inutile car les autres cas se finissent par return */
/* on traite d'abord les operateurs unaires */
if (x.val.op_c=='C') return(cos(eval_post()));
if (x.val.op_c=='S') return(sin(eval_post()));
/* les deuxaires maintenant */
r2=eval_post();
r1=eval_post();
switch (x.val.op_c)
{
case '+':return(r1+r2);
case '-':return(r1-r2);
case '*':return(r1*r2);
case '/':return(r1/r2);
}
puts("erreur (code operatoire inconnu par exemple)");
return(0);
}
void main(void)
{
saisie();
printf("l'expression postfixee vaut %6.1f\n",eval_post());
}
Les piles permettent tres souvent de clarifier l'implantation d'un
algorithme, bien qu'evidemment on puisse utiliser le principe tout en
n'utilisant que des tableaux ou listes.