Travaux dirigés 2

  • Boucles "While" et "For"
  • Notions sur les adresses
  • Tri d'un tableau


Conversion de type

La conversion d'un type vers un autre s'effectue en faisant précéder la valeur à convertir du nouveau type entre parenthèses

char c='a';
int i=0;
float j;
...
j = (float)i;
i = (int)c; /* i reçoit le code ASCII de 'a' */


Attention, certaines conversions peuvent générer des "warnings" à la compilation et des erreurs à l'exécution.

Exemple :
char c;
int i = 257; /* un entier est codé sur 16 ou 32 bits */
c = (char)i; /* un caractère est codé sur 8 bits (1 octet), la conversion risque de produire une perte d'information */


Exercice 1

Ecrire un programme qui affiche une table de conversion des degrés Farenheit en degrés Celsius (voir modèle co-dessous) en utilisant une boucle "While".

Farenheit Celsius
   
0 -17
20 -6
40 4
60 15
80 26
100 37
... ...
300 148

Remarque : La conversion Farenheit (F) - Celsius (C) est assurée par la formule suivante :
C = (5 / 9)*(F - 32).


Exercice 2

Reprendre l'exercice précédant en remplaçant la boucle "While" par une boucle "For".


Rappels de cours

La boucle "For"

L'instruction :

for (expr1;expr2;expr3) action;

est équivalente à :

expr1;
while(expr2)
{ action; expr3;
}

expr1 et expr3 peuvent être absentes, auquel cas, d'après l'équivalence donnée ci-dessus, la boucle "For" se comporte comme une boucle "While". Si expr2 est absente, cela signifie que la condition est vraie en permanence.

Exemple : for(;;) est une boucle infinie.

Dans une boucle "For", deux expressions séparées par une virgule sont évaluées de la gauche vers la droite et le résultat renvoyé est celui de l'expression de droite. La virgule permet de gérer notamment deux indices en parallèle dans une seule boucle "For".

Exemple :
Langage C Equivalent Pascal
for(i=0,j=20;j>i;i+=5,j+=2); i:=0;
j:=20;
WHILE j>i DO
BEGIN
i:=i+5;
j:=j+2
END;

Sous-programmes

La structure d'un sous-programme en C est de la forme suivante :

[type_retourné] [nom_fonction]([liste de paramètres typés])
{

[corps de la fonction]
return([valeur]);

}

Exemple :
Langage C Equivalent Pascal
void ss_prog(int a, int b, float c)



{
char d; /*variable locale*/
fflush(stdin);
d=getchar();
printf("%d %d %f %c\n",a,b,c,d);
fflush(stdout);
}

ou :
void ss_prog(a, b, c)
int a, b;
float c;
{
...
}
PROCEDURE ss_prog(a,b : INTEGER; c : REAL);
VAR d : CHAR;

BEGIN


read(d);
writeln(a,' ',b,' ',c,' ',d)

END;

Si [type_retourné] = void (qui signifie "vide" en anglais), alors le sous-programme ne renvoie pas de valeur. Il n'y a pas d'instruction return.

Evaluation d'une affectation

L'affectation d'une valeur V à une variable x se décompose en deux phases :

  1. la variable x reçoit la valeur V;
  2. le système retourne, comme résultat de cette affectation, la valeur V (ce qui n'est pas le cas en Pascal). Il n'est pas nécessaire d'utiliser ce résultat.

Exemples :


Exercice 3

Ecrire un programme qui, après avoir lu un texte contenant moins de 1000 caractères se terminant par un caractère $ (ce texte sera stocké dans un tableau), inverse l'ordre des caractères dans ce tableau, puis affiche le texte inversé.

Exemple : MESSAGE A INVERSER$ devient RESREVNI A EGASSEM


Adresse d'une variable

Passage de paramètres

Dans un programme en C, le passage des paramètres à un sous-programme ne peut se faire que par valeur (pas par variable). Par exemple, le programme suivant affiche à l'écran "6 est le triple de 2" :

#include "stdio.h"

int triple(int a)
{

a=a*3;
return(a);

}
main()
{

int b = 2;
printf("%d est le triple de %d\n",triple(b),b);

}

Remarque : la valeur de b n'a pas été modifiée dans le programme principal, après l'appel au sous-programme triple.

Adresse d'une variable

Pour que la valeur d'une variable soit modifiée par un appel à un sous-programme, il faut transmettre l'adresse de cette variable dans la mémoire. Lorsqu'on déclare :
int a;
le système réserve un espace suffisant dans la mémoire pour ranger un entier. L'adresse de cet espace réservé est : &a
Ainsi, lorsqu'on veut lire une valeur au clavier, on utilise généralement l'instruction scanf("%d",&a);
(Pour lire un caractère, on utilise le spécificateur de format %c).
Pour que la valeur de la variable a soit effectivement modifiée par cette opération de lecture, il faut en passer l'adresse (&a).

Langage C Equivalent Pascal
scanf("%d",&a);
printf("Valeur : %d\n",a);
readln(a);
writeln('Valeur : ',a);

Exercice 4

Ecrire un programme C qui calcule la factorielle d'autant de nombres lus au clavier que demandé par l'utilisateur. Utiliser un sous-programme pour le calcul de la factorielle.


Adresse d'un tableau

Le passage d'un tableau en paramètre se fait toujours à partir de son adresse ("par adresse"), contrairement à une variable simple, dont le passage en paramètre peut être fait par adresse ou "par valeur". La raison de cette différence est simple : une variable simple possède une adresse et une valeur, alors qu'un tableau possède une adresse mais plusieurs valeurs (en revanche, une case d'un tableau possède une adresse et une valeur).
Un tableau déclaré de la manière suivante :
int tab[100];
a pour adresse tab ou encore &tab[0]
L'exemple ci-dessous donne une solution pour récupérer l'adresse d'un tableau dans un sous-programme :

Langage C Equivalent Pascal

#include "stdio.h"



int lecture(int tab2[],int nbcar)
{
int i;

for (i = 0;i <nbcar; i++)
scanf("%d",&tab2[i]);
return(1);
}

main()
{
int i,tab1[100];
if (lecture(tab1, 5))
for(i = 0; i < 5; i++)
printf("%d ", tab1[i]);
}

PROGRAM inittab;
USES CRT;
TYPE tableau=ARRAY[0..99] OF INTEGER;
VAR i:INTEGER;
tab1 : tableau;
FUNCTION lecture(VAR tab2:TABLEAU; nbcar : INTEGER) : INTEGER;
VAR i : INTEGER;
BEGIN
FOR i:=0 TO nbcar DO readln(tab2[i]);

lecture := 1
END;


BEGIN

IF lecture(tab1,5) > 0 THEN
 
FOR i:=0 TO 4 DO write(tab1[i],' ')

END.

Les valeurs des cinq premières cellules de tab1 sont modifiées lors de l'appel du sous-programme (par la lecture de nombres tapés au clavier). Par contre, dans le programme suivant, dans lequel le paramètre n'est plus un tableau mais une variable simple :

Langage C Equivalent Pascal

#include "stdio.h"

int lecture_inutile(int t2)
{
scanf("%d",&t2);
return(1);
}

main()
{
int t1 = 0;
if (lecture_inutile(t1))
printf("%d ", t1);
}

PROGRAM initvar;
USES CRT;
VAR t1:INTEGER;
FUNCTION lecture_inutile(t2 : INTEGER) : INTEGER;
BEGIN
readln(t2);
lecture_inutile := 1
END;


BEGIN
t1:=0;
IF lecture_inutile(t1) <> 0 THEN
write(t1,' ')
END.

la valeur de t1 n'est pas modifiée par l'appel au sous-programme lecture_inutile (dans les deux versions). Le programme principal produira l'affichage de la valeur 0 initialement affectée à t1.


Exercice 5

Ecrire un programme C qui assure l'initialisation d'un tableau de n entiers lus au clavier. Effectuer ensuite le tri de ce tableau dans l'ordre croissant par un algorithme de tri bulle. Une fois le tableau trié, le programme demandera à l'utilisateur une valeur et cherchera dans le tableau (par dichotomie) si cette valeur est présente.

Le tri et la recherche d'une valeur par dichotomie devront être assurés par des sous-programmes.
Les valeurs entrées au clavier par l'utilisateur seront dans l'ordre :


Ces pages ont été adaptées à partir de celles réalisées par J.D. Durou et Ph. Joly avec leur aimable autorisation.