#define dim_pile 100
#define composante float
/* static pour empêcher l'accès direct extérieur*/
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 saturée");return(1);}
}
composante depiler(void)
{
if (sommet>0) return(pile[--sommet]);
else puts("pile vide");return(0);
}
Si l'on désire 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 saturée");return(1);}
}
composante depiler(void)
{
composante x;
if (sommet!=NULL)
{
x=sommet->val;
free(sommet); /*pour plus de sûreté, 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 préférer ne pas
libérer la mémoire au dépilage pour gagner du temps : au
dépilage, mais aussi à l'empilage, on ne prend du temps que s'il
faut agrandir la pile. On peut également utiliser une pile de tableaux
dynamiques, ce qui permet d'économiser de la place mémoire, sans
être limité 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 saturée");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 prévoir un indice pour chaque extrémité
de la file. Il en serait de même pour une implantation par liste
chaînée (un pointeur pour chaque extrémité).
#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 vérifie rien */
{
composante x;
char txt[100],*deb;
char rep;
init_pile();
printf("entrez opérandes (nombres) et opérateurs (+,-,*,/,C (cos),S)\n");
printf("séparés par des blancs ou virgules\n");
fflush(stdin);
gets(txt); /* on lit un texte qui sera traité par après */
deb=txt; /* deb pointe le début du texte non encore traité */
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 opérateur */
{
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 postfixée");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 opérateurs 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 opératoire inconnu par exemple)");
return(0);
}
void main(void)
{
saisie();
printf("l'expression postfixée vaut %6.1f\n",eval_post());
}
Les piles permettent très souvent de clarifier l'implantation d'un
algorithme, bien qu'évidemment on puisse utiliser le principe tout en
n'utilisant que des tableaux ou listes.