7.2 Pointeurs et passage de paramètres par adresse
Le passage d'arguments en C se fait par valeur. Afin de modifier la
valeur de sortie d'un argument, on peut utiliser un pointeur.
Exercice 7.4 --- Échange de variable par une procédure.
On considère le code suivant :
void permuter ( ... ){
....
}
int main(void){
int a = 3;
int b = 4;
permuter( ... ) ;
return 1 ;
}
Complétez la fonction echanger qui permet de permuter le
contenu des variables a et b.
Exercice 7.5 --- Passage de tableau en paramètre.
Expliquez le comportement du code suivant :
#include<stdio.h>
void fct(char tab[]){
tab[11] = 'm' ;
tab[12] = 'o' ;
tab[13] = 'c' ;
tab[14] = 'h' ;
tab[15] = 'e' ;
}
int main(void){
char tab[] = "La vie est belle" ;
unsigned int i = 0 ;
fct(tab) ;
do{
putchar(tab[i++]);
} while(tab[i]) ;
putchar('\n') ;
return 0 ;
}
7.2.1 Allocation dynamique
Exercice 7.6 --- Copie d'une chaîne de caractère.
Programmez la fonction de prototype :
char * strcopie(char *) ;
qui prend en paramètre une chaîne de caractère et retourne
un pointeur sur une copie de cette chaîne.
7.2.2 Les paramètres de la fonction main
Exercice 7.7 --- .
Construisez un exécutable qui prend en argument sur la ligne de
commande un entier n et qui affiche n fois le contenu de la
variable d'environnements USER si cette dernière est définie.
7.2.3 Implantation d'une pile par un tableau
La notion de pile intervient couramment en programmation.
Par exemple, on l'utilise pour implanter les passages d'arguments lors
d'appels de procédures.
Schématiquement, une pile est une structure de données linéaire
pour laquelle les insertions et les suppressions d'éléments se font
toutes du même coté. On parle de structure
LIFO : Last In First Out.
Plus formellement, on peut considérer un ensemble d'éléments E
et noter Pil(E) l'ensemble de toutes les piles sur E.
Par exemple, les entiers peuvent constituer l'ensemble E ; la pile
vide P0 est dans Pil(E). Les opérations usuelles
sur une pile sont :
-
estVide est une application de Pil(E)
dans (vrai,faux), estVide(P) est
vrai si, et seulement si, P est la pile P0.
- ajouter est une application
de E×Pil(E)) dans Pil(E).
- extraire est une application
de Pil(E)\ P0 dans Pil(E).
- supprimer est une application
de Pil(E)\ P0 dans Pil(E).
Si x est un élément de E, les relations satisfaites par une
pile P et ces opérations sont :
-
estVide(P0)=vrai
- supprimer(ajouter(x,P))=P
- estVide(ajouter(x,P))=faux
- extraire(ajouter(x,P))=x
Cette dernière règle caractérise les piles.
Généralement, on implante une pile par un couple constitué par
un tableau contenant les éléments de la pile et un entier qui
représente la hauteur i.e. le nombre d'éléments de la pile.
#define Max 30
typedef struct Pile{
int hauteur ;
char tab[Max] ;
} Pile ;
Notons que la hauteur est ainsi le premier indice disponible.
7.2.4 Conversion d'une expression infixe en postfixe
Afin d'illustrer l'utilisation d'une pile, on se propose l'exercice
suivant.
Exercice 7.8 --- Convertion d'une expression infixe en postfixe.
On suppose fournie une chaîne de caractères prise en entrée
dans le shell. Cette chaîne est une formule infixe composée
des opérateurs +,* où les opérandes sont des chiffres de 0
à 9. On s'impose l'utilisation du parenthésage pour pouvoir
traiter + et * de la même façon. Les parenthèses sont
représentées par des crochets []. On se propose de convertir de
la chaîne infixe en une forme postfixe (passer de 4*[3+5]
à 4,3,5,+,*).
Pour ce faire, on va utiliser trois piles :
-
une pile SRC qui contiendra la chaîne prise en entrée ;
- une pile TMP temporaire nécessaire aux opérations ;
- une pile RES qui contiendra le résultat.
Pour implanter notre première étape, on va s'aider d'un
automate. Il s'agit d'une représentation d'un algorithme
composée d'états et de transitions. Dans la
figure 7.1, les transitions correspondent
aux flèches du diagramme et les états aux encadrés.
Figure 7.1 : Automate représentant un algorithme de convertion de l'infixe vers le postfixe
Dans notre cas, on s'impose les états suivants :
-
Dépiler de SRC dans TMP ;
- Dépiler de TMP dans RES ;
- Dépiler SRC et dépiler TMP ;
- Erreur ;
- Fin ;
- Dépiler de SRC dans RES.
Quand un caractère est dépilé de SRC, il est empilé soit
dans TMP soit dans RES. Un chiffre est toujours empilé dans RES.
Par contre, si le caractère est un symbole (-,+,/,*, etc.), l'action a
effectuée dépend de ce que contient la pile. Considérons le
cas où la chaîne de départ est 1+1+1 ; les tableaux
suivants (1) représente à chaque étape la pile SRC, (2)
représente la pile TMP et (3) la la pile RES :
Le tableau suivant indique les transitions effectuées à partir de
l'état analyse et décision. Il est malheureusement
incomplet ; n'y figure que les transitions déduites des tableaux
précédents.
| sommet de TMP |
| |
sommet de SRC |
| |
- |
+ |
* |
/ |
[ |
] |
vide |
| - |
|
|
|
|
|
|
|
| + |
|
|
|
|
|
|
|
| * |
|
|
|
|
|
|
|
| / |
|
|
|
|
|
|
|
[ |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
| vide |
|
|
|
|
|
|
|
Figure 7.2 : Table de décisions utilisées dans l'état analyse et décision
Questions.
-
Complétez le tableaux de décisions ;
- Implantez le programme de convertion. On impose que les piles
soient des variables locales de la fonction main.
- On se propose maintenant de réaliser une calculette. Il s'agit
d'un programme qui prend en entrée une chaîne de caractères
du type 4*[3+5] et qui retourne 32.
Pour tout commentaire : Alexandre Sedoglavic.