C'est un camerounais tout banal qui ecrit
ici chez nous c'est noel aussi c'est la fete aussi tout le monde est content et voudrait s'amuser mais comment le faire quand on a pas d'argent
un noel au cameroun n'a rien de chretien c'est juste un pretexte pour tomber dans tous les exès boisson sexe et j'en passe c'est devenu un moment aprecié par les commeçant qui font grimpoer tous les prix surtout dans le domaine du vetement
le consomateur reduit noel à ceci
- je boirais plus
- mangerais plus
- je pousserais toutes les limites pourvu que ce soit bon pour s'amuser
pourtant le matin ce sera le seul jour de l'année ou ils irons à la l'eglise et prierons
mais le soir venu feron exactement le contraire de ce qui aura été dit à l'eglise
pauvre enfant jesus
qu'est devenu NOEL aujourd'hui ?
dimanche 23 décembre 2007
mardi 31 juillet 2007
CORRIGES
CORRECTION DES EXERCICES
-- Ex ex_tva
-- Ex ex_puiss
-- Ex ex_jeu
-- Ex ex_moy
-- Ex ex_jeu_bis
-- Ex ex_calc
-- EX moy.a
-- Ex rot.b
-- Ex clas.c
-- Ex str
--Ex mat
-- Ex tel
-- Ex rec
-- Ex fichier
-- Ex pointeurs
-- Ex ex_tvaprogram tva(input,output);
var prix_unitaire,quantite,
total_ht,tva,total_ttc:real;
begin
writeln('prix de l''article ?');
readln(prix_unitaire);
writeln('quantité désirée ? ');
readln(quantite);
total_ht:=prix_unitaire*quantite;
tva:=total_ht*(18.6/100);
total_ttc:=total_ht+tva;
writeln('total ht : ',total_ht);
writeln('tva : ',tva);
writeln(' -------------');
writeln('total ttc : ',total_ttc)
end.
-- Ex ex_puissprogram puissances(input,output);
var n,max:integer;
begin
writeln('nombre maxi ? ');
readln(max);
n:=2;
while n<=max do begin writeln(n); n:=n*2 end; writeln('c''est fini') end. -- Ex ex_jeuprogram jeu(input,output);
var choix,rep,nb:integer;
begin
nb:=0;
choix:=random(11);
repeat
nb:=nb+1;
writeln('choix ndeg. ',nb,' ? ');
readln(rep)
until rep=choix;
writeln('trouvé en ',nb,' coups')
end.
-- Ex ex_moyprogram moyenne(input,output);
var n,i:integer;
note,total,moyenne:real;
begin
writeln('nombre notes à entrer ?');
readln(n);
total:=0;
for i:=1 to n do begin
writeln(i,'ième note ? ');
readln(note);
total:=total+note
end;
moyenne:=total/n;
writeln('la moyenne est : ',moyenne)
end.
-- Ex ex_jeu_bisprogram jeu_ameliore(input,output);
var choix,rep,nb:integer;
begin
nb:=0;
choix:=random(11);
repeat
nb:=nb+1;
writeln('choix ndeg. ',nb,' ? ');
readln(rep);
if repchoix then
writeln('c''est moins')
{le 2ème if empêche d'écrire si juste}
until rep=choix;
writeln('juste en ',nb,' coups')
end.
-- Ex ex_calcprogram calculatrice(input,output);
var val1,val2,resultat:real;
operation:char;
begin
writeln('première valeur ?');
readln(val1);
writeln('opération (+ - * /) ? ');
readln(operation)
writeln('deuxième valeur ? ');
readln(val2);
case operation of
'+':resultat:=val1+val2;
'-':resultat:=val1-val2;
'*':resultat:=val1*val2;
'/':resultat:=val1/val2
end;
writeln('résultat : ',resultat)
end.
-- EX moy.aprogram moyenne(input,output);
var n,compteur:integer
somme,moyenne,ecart:real;
note:array[1..100] of real;
begin
repeat
writeln('nb notes (100 maxi)?');
readln(n)
until (n>0) and (n<=100); {entrée notes et calcul de la somme} somme:=0; for compteur:=1 to n do begin writeln(compteur,'è note ?'); readln(note[compteur]); somme:=somme+note[compteur] end; {calcul et affichage de la moyenne} moyenne:=somme/n; writeln('moyenne : ',moyenne); {calcul et affichage des écarts} writeln('écarts :'); for compteur:=1 to n do begin ecart:=note[compteur]-moyenne; writeln(compteur,'ième note (', note[compteur], ') : écart : ',ecart) end end. -- Ex rot.b
program rotation(input,output);
var index,n:integer;
prem:real;
tableau:array[1..100]of real;
begin
repeat
writeln('nb valeurs (100 maxi)?');
readln(n)
until (n>0) and (n<=100); (* entrée des valeurs *) for index:=1 to n do begin writeln(index,'ième valeur ?'); readln(tableau[index]); end; writeln('on décale vers le haut'); prem:=tableau[1]; {ne pas écraser!} for index:=2 to n do tableau[index-1]:=tableau[index]; tableau[n]:=prem; for index:=1 to n do writeln(tableau[index]); writeln('on re-décale vers le bas'); prem:=tableau[n]; for index:=n downto 2 do tableau[index]:=tableau[index-1]; tableau[1]:=prem; for index:=1 to n do writeln(tableau[index]) end. -- Ex clas.cprogram classer(input,output);
var n,i,index,petit,indexpetit:integer;
avant,apres:array[1..100]of integer;
pris:array[1..100] of boolean;
{pour noter ceux déjà pris}
begin
repeat
writeln('nb valeurs (100 maxi) ?');
readln(n)
until (n>0) and (n<=100); {entrée valeurs - initialisation de pris} for index:=1 to n do begin writeln(index,'ième valeur ? '); readln(avant[index]); pris[index]:=false end; {ordre croissant,on cherche N valeurs} for i:=1 to n do begin petit:=maxint; {plus grand possible} {recherche du plus petit non pris} for index:=1 to n do if (not pris[index]) and (avant[index]<=petit) then begin petit:=avant[index]; indexpetit:=index end; { sauvegarde dans le tableau APRES et mise à jour de PRIS } apres[i]:=petit; pris[indexpetit]:=true end; { passage au prochain i } {affichage du tableau APRES} writeln('par ordre croissant : '); for i:=1 to N do writeln(apres[i]); {classement par ordre décroissant} writeln('par ordre décroissant : '); for i:=n downto 1 do writeln(apres[i]) {n'auriez-vous pas tout refait ?} end. -- Ex str
program position(input,output);
var ch,sch:string[255];
i,j,n,l,ls:integer;
begin
writeln('chaîne à tester ? ');
readln(ch);
writeln('sous-chaîne à trouver ?');
readln(sch);
l:=length(ch);ls:=length(sch);
n:=0;
for i:=1 to l-ls do begin
j:=1;
while (j<=l)and(ch[i+j-1]=sch[j]) do j:=j+1; if j>ls then begin
writeln('trouvé position ',i);
n:=n+1
end
end;
writeln(n,' fois ',sch,' dans ',ch)
end.
--Ex matprogram produit_mat(input,output);
var m1,m2,m3:array[1..10,1..10]of real;
l,m,n,jl,jm,jn:integer;
begin
writeln('nb lignes 1ère matrice ?');
readln(m);
writeln('nb colonnes 1è matrice ?');
readln(l);
writeln('nb colonnes 2è matrice ?');
readln(n);
(* entrée de m1 *)
writeln('première matrice');
for jm:=1 to m do for jl:=1 to l do
begin
writeln('lig',jm,', col',jl,'?');
readln(m1[jm,jl])
end;
(* entrée de m2 *)
writeln('2ième matrice');
for jl:=1 to l do for jn:=1 to n do
begin
writeln('lig',jl,', col',jn,'?');
readln(m2[jl,jn])
end;
(* calcul du produit *)
for jm:=1 to m do for jn:=1 to n do
begin {calcul composante m,n de m2}
m3[jm,jn]:=0;
for jl:=1 to l do m3[jm,jn]:=
m3[jm,jn]+(m1[jm,jl]*m2[jl,jn]);
end;
(* affichage du résultat *)
writeln('résultat');
for jm:=1 to m do for jn:=1 to n do
writeln('m[',jm,',',jn,']=',
m3[jm,jn])
end.
-- Ex telprogram annuaire(input,output);
(* version simplifiée *)
type ligne=string[40];
typepersonne=record
nom:ligne;
num_tel:ligne
(* integer malheureusement <>'Q' then begin
writeln('texte à chercher ? ');
readln(texte)
for i:=1 to nb do with pers[i] do
begin
case rep of
'N':imprimer:=nom=texte;
'T':imprimer:=num_tel=texte;
end;
if imprimer then begin
writeln('nom : ',nom);
writeln('tel : ',num_tel)
end
end
end
until rep='Q'
end.
-- Ex recprogram determ(input,output);
{ on se limite à 10x10, ce qui fait 7h
de calcul et 6.235.314 appels à DETN }
type tmat=array[1..10,1..10] of real;
var dim:integer;
{dimension matrice à calculer}
det:real; {résultat désiré}
mat:tmat; {matrice à calculer}
appel:real; {nb appels à }
procedure entree;
var lig,col:integer;
begin
writeln('dimension de la matrice ?');
readln(dim); {DIM variable globale}
writeln('entrez les composantes :');
for lig:=1 to dim do begin
writeln('pour la ligne ndeg. ',lig);
for col:=1 to dim do begin
writeln('colonne ',col,' ?');
readln(mat[lig,col])
end
end
end;
procedure sous_mat(mdeb:tmat; var mfin:
tmat; ind,dim:integer);
{on supprime la colonne 1 et la ligne
ind pour avoir la s/mat de dim-1}
var col,lig,l:integer;
begin
l:=0;
for lig:=1 to dim do begin
if lig<>ind then begin
l:=l+1;
for col:=2 to dim do
mfin[l,col-1]:=mdeb[lig,col]
end
end
end;
function detn(m:tmat;d:integer):real;
{dét ordre d en fonction ordre d-1}
var result:real;
mprim:tmat; {matrice intermédiaire}
lig,signe:integer;
begin
appel:=appel+1;
if d=1 then detn:=m[1,1]
(* fin de récursivité *)
else begin
result:=0;
signe:=-1;
for lig:=1 to d do begin
sous_mat(m,mprim,lig,d);
signe:=-signe;
{changer de signe à chaque ligne}
result:=result +
(signe*m[lig,1]*detn(mprim,d-1))
end;
detn:=result
end
end;
begin (* programme principal *)
entree;
appel:=0;
det:=detn(mat,dim);
writeln('résultat : ',det);
writeln('nb appels DETN : ',appel)
end.
-- Ex fichier
procedure lirefic;
var i:1..100;
f:file of typepersonne;
(* variables globales :
NB et le tableau PERS *)
begin
assign(f,'annuaire'); {non standard}
reset(f);
nb:=0;
while not EOF(f) do begin
nb:=nb+1;
read(f,pers[nb)
end;
close(f)
end;
{à vous de faire la suite}
-- Ex pointeurs
program liste(input,output);
TYPE tpoint=^tval;
tval=record
valeur:integer;
suivant:tpoint
end;
VAR prem:tpoint; {variable globale}
n:integer;
c:char;
procedure lire;
var precedent,point:tpoint;
i:integer;
{ modifie N et PREM }
begin
write('combien d''éléments?');
readln(n);
new(prem);
write('1ère valeur ? ');
readln(prem^.valeur);
precedent:=prem;
for i:=2 to n do begin
new(point);
write(i,'ième valeur ? ');
readln(point^.valeur);
precedent^.suivant:=point;
precedent:=point
end;
precedent^.suivant:=NIL
(* le dernier ne pointe sur rien *)
end;
procedure afficher;
var point:tpoint;
i:integer;
begin
point:=prem;
for i:=1 to n do begin
writeln(point^.valeur);
point:=point^.suivant
end
end;
procedure supprimer;
var point,prec:tpoint;
rep:char;
begin
point:=prem;
repeat
write(point^.valeur,' à ôter ?');
readln(rep);
if rep='O' then begin
n:=n-1;
if point<>prem then begin
prec^.suivant:=point^.suivant;
dispose(point);
point:=prec^.suivant
(* se préparer pour la suite *)
end
else begin
prem:=prem^.suivant;
dispose(point);
(* ancien premier *)
point:=prem
end
end
else begin
(* pointer sur le suivant *)
prec:=point;
point:=point^.suivant
end
until point=nil
end;
procedure rajouter;
var p1,p2,prec:tpoint;
rep:char;
begin
p1:=prem;
repeat
write(p1^.valeur,' rajouter un
élément avant (O/N) ? ');
readln(rep);
if rep='O' then begin
n:=n+1;
if p1<>prem then begin
new(p2);
write('valeur ? ');
readln(p2^.valeur);
prec^.suivant:=p2;
p2^.suivant:=p1;
prec:=p2;
end
else begin
new(p1);
write('valeur ? ');
readln(p1^.valeur);
p1^.suivant:=prem;
prem:=p1
end
end
else begin
(* pointer sur le suivant *)
prec:=p1;
p1:=p1^.suivant
end
until p1=nil;
p1:=prec;
repeat
write('ajouter un élément en fin
de liste (O/N) ? ');
readln(rep);
if rep='O' then begin
n:=n+1;
new(p2);
write('valeur ? ');
readln(p2^.valeur);
p1^.suivant:=p2;
p2^.suivant:=nil;
p1:=p2
end
until rep<>'O'
end;
BEGIN {prog principal}
lire;
repeat
writeln('A:afficher, S:supprimer R:rajouter, F:fin');
write('votre choix ? ');
readln(c);
case c of
'A':afficher;
'S':supprimer;
'R':rajouter
end
until c='F'
end.
-- Ex ex_tva
-- Ex ex_puiss
-- Ex ex_jeu
-- Ex ex_moy
-- Ex ex_jeu_bis
-- Ex ex_calc
-- EX moy.a
-- Ex rot.b
-- Ex clas.c
-- Ex str
--Ex mat
-- Ex tel
-- Ex rec
-- Ex fichier
-- Ex pointeurs
-- Ex ex_tvaprogram tva(input,output);
var prix_unitaire,quantite,
total_ht,tva,total_ttc:real;
begin
writeln('prix de l''article ?');
readln(prix_unitaire);
writeln('quantité désirée ? ');
readln(quantite);
total_ht:=prix_unitaire*quantite;
tva:=total_ht*(18.6/100);
total_ttc:=total_ht+tva;
writeln('total ht : ',total_ht);
writeln('tva : ',tva);
writeln(' -------------');
writeln('total ttc : ',total_ttc)
end.
-- Ex ex_puissprogram puissances(input,output);
var n,max:integer;
begin
writeln('nombre maxi ? ');
readln(max);
n:=2;
while n<=max do begin writeln(n); n:=n*2 end; writeln('c''est fini') end. -- Ex ex_jeuprogram jeu(input,output);
var choix,rep,nb:integer;
begin
nb:=0;
choix:=random(11);
repeat
nb:=nb+1;
writeln('choix ndeg. ',nb,' ? ');
readln(rep)
until rep=choix;
writeln('trouvé en ',nb,' coups')
end.
-- Ex ex_moyprogram moyenne(input,output);
var n,i:integer;
note,total,moyenne:real;
begin
writeln('nombre notes à entrer ?');
readln(n);
total:=0;
for i:=1 to n do begin
writeln(i,'ième note ? ');
readln(note);
total:=total+note
end;
moyenne:=total/n;
writeln('la moyenne est : ',moyenne)
end.
-- Ex ex_jeu_bisprogram jeu_ameliore(input,output);
var choix,rep,nb:integer;
begin
nb:=0;
choix:=random(11);
repeat
nb:=nb+1;
writeln('choix ndeg. ',nb,' ? ');
readln(rep);
if rep
writeln('c''est moins')
{le 2ème if empêche d'écrire si juste}
until rep=choix;
writeln('juste en ',nb,' coups')
end.
var val1,val2,resultat:real;
operation:char;
begin
writeln('première valeur ?');
readln(val1);
writeln('opération (+ - * /) ? ');
readln(operation)
writeln('deuxième valeur ? ');
readln(val2);
case operation of
'+':resultat:=val1+val2;
'-':resultat:=val1-val2;
'*':resultat:=val1*val2;
'/':resultat:=val1/val2
end;
writeln('résultat : ',resultat)
end.
-- EX moy.aprogram moyenne(input,output);
var n,compteur:integer
somme,moyenne,ecart:real;
note:array[1..100] of real;
begin
repeat
writeln('nb notes (100 maxi)?');
readln(n)
until (n>0) and (n<=100); {entrée notes et calcul de la somme} somme:=0; for compteur:=1 to n do begin writeln(compteur,'è note ?'); readln(note[compteur]); somme:=somme+note[compteur] end; {calcul et affichage de la moyenne} moyenne:=somme/n; writeln('moyenne : ',moyenne); {calcul et affichage des écarts} writeln('écarts :'); for compteur:=1 to n do begin ecart:=note[compteur]-moyenne; writeln(compteur,'ième note (', note[compteur], ') : écart : ',ecart) end end. -- Ex rot.b
program rotation(input,output);
var index,n:integer;
prem:real;
tableau:array[1..100]of real;
begin
repeat
writeln('nb valeurs (100 maxi)?');
readln(n)
until (n>0) and (n<=100); (* entrée des valeurs *) for index:=1 to n do begin writeln(index,'ième valeur ?'); readln(tableau[index]); end; writeln('on décale vers le haut'); prem:=tableau[1]; {ne pas écraser!} for index:=2 to n do tableau[index-1]:=tableau[index]; tableau[n]:=prem; for index:=1 to n do writeln(tableau[index]); writeln('on re-décale vers le bas'); prem:=tableau[n]; for index:=n downto 2 do tableau[index]:=tableau[index-1]; tableau[1]:=prem; for index:=1 to n do writeln(tableau[index]) end. -- Ex clas.cprogram classer(input,output);
var n,i,index,petit,indexpetit:integer;
avant,apres:array[1..100]of integer;
pris:array[1..100] of boolean;
{pour noter ceux déjà pris}
begin
repeat
writeln('nb valeurs (100 maxi) ?');
readln(n)
until (n>0) and (n<=100); {entrée valeurs - initialisation de pris} for index:=1 to n do begin writeln(index,'ième valeur ? '); readln(avant[index]); pris[index]:=false end; {ordre croissant,on cherche N valeurs} for i:=1 to n do begin petit:=maxint; {plus grand possible} {recherche du plus petit non pris} for index:=1 to n do if (not pris[index]) and (avant[index]<=petit) then begin petit:=avant[index]; indexpetit:=index end; { sauvegarde dans le tableau APRES et mise à jour de PRIS } apres[i]:=petit; pris[indexpetit]:=true end; { passage au prochain i } {affichage du tableau APRES} writeln('par ordre croissant : '); for i:=1 to N do writeln(apres[i]); {classement par ordre décroissant} writeln('par ordre décroissant : '); for i:=n downto 1 do writeln(apres[i]) {n'auriez-vous pas tout refait ?} end. -- Ex str
program position(input,output);
var ch,sch:string[255];
i,j,n,l,ls:integer;
begin
writeln('chaîne à tester ? ');
readln(ch);
writeln('sous-chaîne à trouver ?');
readln(sch);
l:=length(ch);ls:=length(sch);
n:=0;
for i:=1 to l-ls do begin
j:=1;
while (j<=l)and(ch[i+j-1]=sch[j]) do j:=j+1; if j>ls then begin
writeln('trouvé position ',i);
n:=n+1
end
end;
writeln(n,' fois ',sch,' dans ',ch)
end.
--Ex matprogram produit_mat(input,output);
var m1,m2,m3:array[1..10,1..10]of real;
l,m,n,jl,jm,jn:integer;
begin
writeln('nb lignes 1ère matrice ?');
readln(m);
writeln('nb colonnes 1è matrice ?');
readln(l);
writeln('nb colonnes 2è matrice ?');
readln(n);
(* entrée de m1 *)
writeln('première matrice');
for jm:=1 to m do for jl:=1 to l do
begin
writeln('lig',jm,', col',jl,'?');
readln(m1[jm,jl])
end;
(* entrée de m2 *)
writeln('2ième matrice');
for jl:=1 to l do for jn:=1 to n do
begin
writeln('lig',jl,', col',jn,'?');
readln(m2[jl,jn])
end;
(* calcul du produit *)
for jm:=1 to m do for jn:=1 to n do
begin {calcul composante m,n de m2}
m3[jm,jn]:=0;
for jl:=1 to l do m3[jm,jn]:=
m3[jm,jn]+(m1[jm,jl]*m2[jl,jn]);
end;
(* affichage du résultat *)
writeln('résultat');
for jm:=1 to m do for jn:=1 to n do
writeln('m[',jm,',',jn,']=',
m3[jm,jn])
end.
-- Ex telprogram annuaire(input,output);
(* version simplifiée *)
type ligne=string[40];
typepersonne=record
nom:ligne;
num_tel:ligne
(* integer malheureusement <>'Q' then begin
writeln('texte à chercher ? ');
readln(texte)
for i:=1 to nb do with pers[i] do
begin
case rep of
'N':imprimer:=nom=texte;
'T':imprimer:=num_tel=texte;
end;
if imprimer then begin
writeln('nom : ',nom);
writeln('tel : ',num_tel)
end
end
end
until rep='Q'
end.
-- Ex recprogram determ(input,output);
{ on se limite à 10x10, ce qui fait 7h
de calcul et 6.235.314 appels à DETN }
type tmat=array[1..10,1..10] of real;
var dim:integer;
{dimension matrice à calculer}
det:real; {résultat désiré}
mat:tmat; {matrice à calculer}
appel:real; {nb appels à }
procedure entree;
var lig,col:integer;
begin
writeln('dimension de la matrice ?');
readln(dim); {DIM variable globale}
writeln('entrez les composantes :');
for lig:=1 to dim do begin
writeln('pour la ligne ndeg. ',lig);
for col:=1 to dim do begin
writeln('colonne ',col,' ?');
readln(mat[lig,col])
end
end
end;
procedure sous_mat(mdeb:tmat; var mfin:
tmat; ind,dim:integer);
{on supprime la colonne 1 et la ligne
ind pour avoir la s/mat de dim-1}
var col,lig,l:integer;
begin
l:=0;
for lig:=1 to dim do begin
if lig<>ind then begin
l:=l+1;
for col:=2 to dim do
mfin[l,col-1]:=mdeb[lig,col]
end
end
end;
function detn(m:tmat;d:integer):real;
{dét ordre d en fonction ordre d-1}
var result:real;
mprim:tmat; {matrice intermédiaire}
lig,signe:integer;
begin
appel:=appel+1;
if d=1 then detn:=m[1,1]
(* fin de récursivité *)
else begin
result:=0;
signe:=-1;
for lig:=1 to d do begin
sous_mat(m,mprim,lig,d);
signe:=-signe;
{changer de signe à chaque ligne}
result:=result +
(signe*m[lig,1]*detn(mprim,d-1))
end;
detn:=result
end
end;
begin (* programme principal *)
entree;
appel:=0;
det:=detn(mat,dim);
writeln('résultat : ',det);
writeln('nb appels DETN : ',appel)
end.
-- Ex fichier
procedure lirefic;
var i:1..100;
f:file of typepersonne;
(* variables globales :
NB et le tableau PERS *)
begin
assign(f,'annuaire'); {non standard}
reset(f);
nb:=0;
while not EOF(f) do begin
nb:=nb+1;
read(f,pers[nb)
end;
close(f)
end;
{à vous de faire la suite}
-- Ex pointeurs
program liste(input,output);
TYPE tpoint=^tval;
tval=record
valeur:integer;
suivant:tpoint
end;
VAR prem:tpoint; {variable globale}
n:integer;
c:char;
procedure lire;
var precedent,point:tpoint;
i:integer;
{ modifie N et PREM }
begin
write('combien d''éléments?');
readln(n);
new(prem);
write('1ère valeur ? ');
readln(prem^.valeur);
precedent:=prem;
for i:=2 to n do begin
new(point);
write(i,'ième valeur ? ');
readln(point^.valeur);
precedent^.suivant:=point;
precedent:=point
end;
precedent^.suivant:=NIL
(* le dernier ne pointe sur rien *)
end;
procedure afficher;
var point:tpoint;
i:integer;
begin
point:=prem;
for i:=1 to n do begin
writeln(point^.valeur);
point:=point^.suivant
end
end;
procedure supprimer;
var point,prec:tpoint;
rep:char;
begin
point:=prem;
repeat
write(point^.valeur,' à ôter ?');
readln(rep);
if rep='O' then begin
n:=n-1;
if point<>prem then begin
prec^.suivant:=point^.suivant;
dispose(point);
point:=prec^.suivant
(* se préparer pour la suite *)
end
else begin
prem:=prem^.suivant;
dispose(point);
(* ancien premier *)
point:=prem
end
end
else begin
(* pointer sur le suivant *)
prec:=point;
point:=point^.suivant
end
until point=nil
end;
procedure rajouter;
var p1,p2,prec:tpoint;
rep:char;
begin
p1:=prem;
repeat
write(p1^.valeur,' rajouter un
élément avant (O/N) ? ');
readln(rep);
if rep='O' then begin
n:=n+1;
if p1<>prem then begin
new(p2);
write('valeur ? ');
readln(p2^.valeur);
prec^.suivant:=p2;
p2^.suivant:=p1;
prec:=p2;
end
else begin
new(p1);
write('valeur ? ');
readln(p1^.valeur);
p1^.suivant:=prem;
prem:=p1
end
end
else begin
(* pointer sur le suivant *)
prec:=p1;
p1:=p1^.suivant
end
until p1=nil;
p1:=prec;
repeat
write('ajouter un élément en fin
de liste (O/N) ? ');
readln(rep);
if rep='O' then begin
n:=n+1;
new(p2);
write('valeur ? ');
readln(p2^.valeur);
p1^.suivant:=p2;
p2^.suivant:=nil;
p1:=p2
end
until rep<>'O'
end;
BEGIN {prog principal}
lire;
repeat
writeln('A:afficher, S:supprimer R:rajouter, F:fin');
write('votre choix ? ');
readln(c);
case c of
'A':afficher;
'S':supprimer;
'R':rajouter
end
until c='F'
end.
Libellés :
CORRIGES
CORRIGES
CORRECTION DES EXERCICES
-- Ex ex_tva
-- Ex ex_puiss
-- Ex ex_jeu
-- Ex ex_moy
-- Ex ex_jeu_bis
-- Ex ex_calc
-- EX moy.a
-- Ex rot.b
-- Ex clas.c
-- Ex str
--Ex mat
-- Ex tel
-- Ex rec
-- Ex fichier
-- Ex pointeurs
-- Ex ex_tvaprogram tva(input,output);
var prix_unitaire,quantite,
total_ht,tva,total_ttc:real;
begin
writeln('prix de l''article ?');
readln(prix_unitaire);
writeln('quantité désirée ? ');
readln(quantite);
total_ht:=prix_unitaire*quantite;
tva:=total_ht*(18.6/100);
total_ttc:=total_ht+tva;
writeln('total ht : ',total_ht);
writeln('tva : ',tva);
writeln(' -------------');
writeln('total ttc : ',total_ttc)
end.
-- Ex ex_puissprogram puissances(input,output);
var n,max:integer;
begin
writeln('nombre maxi ? ');
readln(max);
n:=2;
while n<=max do begin
writeln(n);
n:=n*2
end;
writeln('c''est fini')
end.
-- Ex ex_jeuprogram jeu(input,output);
var choix,rep,nb:integer;
begin
nb:=0;
choix:=random(11);
repeat
nb:=nb+1;
writeln('choix ndeg. ',nb,' ? ');
readln(rep)
until rep=choix;
writeln('trouvé en ',nb,' coups')
end.
-- Ex ex_moyprogram moyenne(input,output);
var n,i:integer;
note,total,moyenne:real;
begin
writeln('nombre notes à entrer ?');
readln(n);
total:=0;
for i:=1 to n do begin
writeln(i,'ième note ? ');
readln(note);
total:=total+note
end;
moyenne:=total/n;
writeln('la moyenne est : ',moyenne)
end.
-- Ex ex_jeu_bisprogram jeu_ameliore(input,output);
var choix,rep,nb:integer;
begin
nb:=0;
choix:=random(11);
repeat
nb:=nb+1;
writeln('choix ndeg. ',nb,' ? ');
readln(rep);
if rep writeln('c''est plus')
else if rep>choix then
writeln('c''est moins')
{le 2ème if empêche d'écrire si juste}
until rep=choix;
writeln('juste en ',nb,' coups')
end.
-- Ex ex_calcprogram calculatrice(input,output);
var val1,val2,resultat:real;
operation:char;
begin
writeln('première valeur ?');
readln(val1);
writeln('opération (+ - * /) ? ');
readln(operation)
writeln('deuxième valeur ? ');
readln(val2);
case operation of
'+':resultat:=val1+val2;
'-':resultat:=val1-val2;
'*':resultat:=val1*val2;
'/':resultat:=val1/val2
end;
writeln('résultat : ',resultat)
end.
-- EX moy.aprogram moyenne(input,output);
var n,compteur:integer
somme,moyenne,ecart:real;
note:array[1..100] of real;
begin
repeat
writeln('nb notes (100 maxi)?');
readln(n)
until (n>0) and (n<=100);
{entrée notes et calcul de la somme}
somme:=0;
for compteur:=1 to n do
begin
writeln(compteur,'è note ?');
readln(note[compteur]);
somme:=somme+note[compteur]
end;
{calcul et affichage de la moyenne}
moyenne:=somme/n;
writeln('moyenne : ',moyenne);
{calcul et affichage des écarts}
writeln('écarts :');
for compteur:=1 to n do
begin
ecart:=note[compteur]-moyenne;
writeln(compteur,'ième note (',
note[compteur],
') : écart : ',ecart)
end
end.
-- Ex rot.b
program rotation(input,output);
var index,n:integer;
prem:real;
tableau:array[1..100]of real;
begin
repeat
writeln('nb valeurs (100 maxi)?');
readln(n)
until (n>0) and (n<=100);
(* entrée des valeurs *)
for index:=1 to n do
begin
writeln(index,'ième valeur ?');
readln(tableau[index]);
end;
writeln('on décale vers le haut');
prem:=tableau[1]; {ne pas écraser!}
for index:=2 to n do
tableau[index-1]:=tableau[index];
tableau[n]:=prem;
for index:=1 to n do
writeln(tableau[index]);
writeln('on re-décale vers le bas');
prem:=tableau[n];
for index:=n downto 2 do
tableau[index]:=tableau[index-1];
tableau[1]:=prem;
for index:=1 to n do
writeln(tableau[index])
end.
-- Ex clas.cprogram classer(input,output);
var n,i,index,petit,indexpetit:integer;
avant,apres:array[1..100]of integer;
pris:array[1..100] of boolean;
{pour noter ceux déjà pris}
begin
repeat
writeln('nb valeurs (100 maxi) ?');
readln(n)
until (n>0) and (n<=100);
{entrée valeurs - initialisation de pris}
for index:=1 to n do begin
writeln(index,'ième valeur ? ');
readln(avant[index]);
pris[index]:=false
end;
{ordre croissant,on cherche N valeurs}
for i:=1 to n do begin
petit:=maxint; {plus grand possible}
{recherche du plus petit non pris}
for index:=1 to n do
if (not pris[index]) and
(avant[index]<=petit) then begin
petit:=avant[index];
indexpetit:=index
end;
{ sauvegarde dans le tableau APRES et
mise à jour de PRIS }
apres[i]:=petit;
pris[indexpetit]:=true
end; { passage au prochain i }
{affichage du tableau APRES}
writeln('par ordre croissant : ');
for i:=1 to N do writeln(apres[i]);
{classement par ordre décroissant}
writeln('par ordre décroissant : ');
for i:=n downto 1 do writeln(apres[i])
{n'auriez-vous pas tout refait ?}
end.
-- Ex str
program position(input,output);
var ch,sch:string[255];
i,j,n,l,ls:integer;
begin
writeln('chaîne à tester ? ');
readln(ch);
writeln('sous-chaîne à trouver ?');
readln(sch);
l:=length(ch);ls:=length(sch);
n:=0;
for i:=1 to l-ls do begin
j:=1;
while (j<=l)and(ch[i+j-1]=sch[j])
do j:=j+1;
if j>ls then begin
writeln('trouvé position ',i);
n:=n+1
end
end;
writeln(n,' fois ',sch,' dans ',ch)
end.
--Ex matprogram produit_mat(input,output);
var m1,m2,m3:array[1..10,1..10]of real;
l,m,n,jl,jm,jn:integer;
begin
writeln('nb lignes 1ère matrice ?');
readln(m);
writeln('nb colonnes 1è matrice ?');
readln(l);
writeln('nb colonnes 2è matrice ?');
readln(n);
(* entrée de m1 *)
writeln('première matrice');
for jm:=1 to m do for jl:=1 to l do
begin
writeln('lig',jm,', col',jl,'?');
readln(m1[jm,jl])
end;
(* entrée de m2 *)
writeln('2ième matrice');
for jl:=1 to l do for jn:=1 to n do
begin
writeln('lig',jl,', col',jn,'?');
readln(m2[jl,jn])
end;
(* calcul du produit *)
for jm:=1 to m do for jn:=1 to n do
begin {calcul composante m,n de m2}
m3[jm,jn]:=0;
for jl:=1 to l do m3[jm,jn]:=
m3[jm,jn]+(m1[jm,jl]*m2[jl,jn]);
end;
(* affichage du résultat *)
writeln('résultat');
for jm:=1 to m do for jn:=1 to n do
writeln('m[',jm,',',jn,']=',
m3[jm,jn])
end.
-- Ex telprogram annuaire(input,output);
(* version simplifiée *)
type ligne=string[40];
typepersonne=record
nom:ligne;
num_tel:ligne
(* integer malheureusement < 32635 *)
end;
var pers:array[1..100]of
typepersonne;
nb,i:1..100;
rep:char;
imprimer:boolean;
texte:ligne;
begin
{on suppose avoir ici les instructions
permettant de lire sur fichier disque
NB et le tableau PERS }
repeat
writeln('recherche suivant : ');
writeln(' N : nom');
writeln(' T : numéro téléphone');
writeln(' Q : quitter le prog');
writeln('quel est votre choix ?');
readln(rep);
if rep<>'Q' then begin
writeln('texte à chercher ? ');
readln(texte)
for i:=1 to nb do with pers[i] do
begin
case rep of
'N':imprimer:=nom=texte;
'T':imprimer:=num_tel=texte;
end;
if imprimer then begin
writeln('nom : ',nom);
writeln('tel : ',num_tel)
end
end
end
until rep='Q'
end.
-- Ex recprogram determ(input,output);
{ on se limite à 10x10, ce qui fait 7h
de calcul et 6.235.314 appels à DETN }
type tmat=array[1..10,1..10] of real;
var dim:integer;
{dimension matrice à calculer}
det:real; {résultat désiré}
mat:tmat; {matrice à calculer}
appel:real; {nb appels à }
procedure entree;
var lig,col:integer;
begin
writeln('dimension de la matrice ?');
readln(dim); {DIM variable globale}
writeln('entrez les composantes :');
for lig:=1 to dim do begin
writeln('pour la ligne ndeg. ',lig);
for col:=1 to dim do begin
writeln('colonne ',col,' ?');
readln(mat[lig,col])
end
end
end;
procedure sous_mat(mdeb:tmat; var mfin:
tmat; ind,dim:integer);
{on supprime la colonne 1 et la ligne
ind pour avoir la s/mat de dim-1}
var col,lig,l:integer;
begin
l:=0;
for lig:=1 to dim do begin
if lig<>ind then begin
l:=l+1;
for col:=2 to dim do
mfin[l,col-1]:=mdeb[lig,col]
end
end
end;
function detn(m:tmat;d:integer):real;
{dét ordre d en fonction ordre d-1}
var result:real;
mprim:tmat; {matrice intermédiaire}
lig,signe:integer;
begin
appel:=appel+1;
if d=1 then detn:=m[1,1]
(* fin de récursivité *)
else begin
result:=0;
signe:=-1;
for lig:=1 to d do begin
sous_mat(m,mprim,lig,d);
signe:=-signe;
{changer de signe à chaque ligne}
result:=result +
(signe*m[lig,1]*detn(mprim,d-1))
end;
detn:=result
end
end;
begin (* programme principal *)
entree;
appel:=0;
det:=detn(mat,dim);
writeln('résultat : ',det);
writeln('nb appels DETN : ',appel)
end.
-- Ex fichier
procedure lirefic;
var i:1..100;
f:file of typepersonne;
(* variables globales :
NB et le tableau PERS *)
begin
assign(f,'annuaire'); {non standard}
reset(f);
nb:=0;
while not EOF(f) do begin
nb:=nb+1;
read(f,pers[nb)
end;
close(f)
end;
{à vous de faire la suite}
-- Ex pointeurs
program liste(input,output);
TYPE tpoint=^tval;
tval=record
valeur:integer;
suivant:tpoint
end;
VAR prem:tpoint; {variable globale}
n:integer;
c:char;
procedure lire;
var precedent,point:tpoint;
i:integer;
{ modifie N et PREM }
begin
write('combien d''éléments?');
readln(n);
new(prem);
write('1ère valeur ? ');
readln(prem^.valeur);
precedent:=prem;
for i:=2 to n do begin
new(point);
write(i,'ième valeur ? ');
readln(point^.valeur);
precedent^.suivant:=point;
precedent:=point
end;
precedent^.suivant:=NIL
(* le dernier ne pointe sur rien *)
end;
procedure afficher;
var point:tpoint;
i:integer;
begin
point:=prem;
for i:=1 to n do begin
writeln(point^.valeur);
point:=point^.suivant
end
end;
procedure supprimer;
var point,prec:tpoint;
rep:char;
begin
point:=prem;
repeat
write(point^.valeur,' à ôter ?');
readln(rep);
if rep='O' then begin
n:=n-1;
if point<>prem then begin
prec^.suivant:=point^.suivant;
dispose(point);
point:=prec^.suivant
(* se préparer pour la suite *)
end
else begin
prem:=prem^.suivant;
dispose(point);
(* ancien premier *)
point:=prem
end
end
else begin
(* pointer sur le suivant *)
prec:=point;
point:=point^.suivant
end
until point=nil
end;
procedure rajouter;
var p1,p2,prec:tpoint;
rep:char;
begin
p1:=prem;
repeat
write(p1^.valeur,' rajouter un
élément avant (O/N) ? ');
readln(rep);
if rep='O' then begin
n:=n+1;
if p1<>prem then begin
new(p2);
write('valeur ? ');
readln(p2^.valeur);
prec^.suivant:=p2;
p2^.suivant:=p1;
prec:=p2;
end
else begin
new(p1);
write('valeur ? ');
readln(p1^.valeur);
p1^.suivant:=prem;
prem:=p1
end
end
else begin
(* pointer sur le suivant *)
prec:=p1;
p1:=p1^.suivant
end
until p1=nil;
p1:=prec;
repeat
write('ajouter un élément en fin
de liste (O/N) ? ');
readln(rep);
if rep='O' then begin
n:=n+1;
new(p2);
write('valeur ? ');
readln(p2^.valeur);
p1^.suivant:=p2;
p2^.suivant:=nil;
p1:=p2
end
until rep<>'O'
end;
BEGIN {prog principal}
lire;
repeat
writeln('A:afficher, S:supprimer R:rajouter, F:fin');
write('votre choix ? ');
readln(c);
case c of
'A':afficher;
'S':supprimer;
'R':rajouter
end
until c='F'
end.
-- Ex ex_tva
-- Ex ex_puiss
-- Ex ex_jeu
-- Ex ex_moy
-- Ex ex_jeu_bis
-- Ex ex_calc
-- EX moy.a
-- Ex rot.b
-- Ex clas.c
-- Ex str
--Ex mat
-- Ex tel
-- Ex rec
-- Ex fichier
-- Ex pointeurs
-- Ex ex_tvaprogram tva(input,output);
var prix_unitaire,quantite,
total_ht,tva,total_ttc:real;
begin
writeln('prix de l''article ?');
readln(prix_unitaire);
writeln('quantité désirée ? ');
readln(quantite);
total_ht:=prix_unitaire*quantite;
tva:=total_ht*(18.6/100);
total_ttc:=total_ht+tva;
writeln('total ht : ',total_ht);
writeln('tva : ',tva);
writeln(' -------------');
writeln('total ttc : ',total_ttc)
end.
-- Ex ex_puissprogram puissances(input,output);
var n,max:integer;
begin
writeln('nombre maxi ? ');
readln(max);
n:=2;
while n<=max do begin
writeln(n);
n:=n*2
end;
writeln('c''est fini')
end.
-- Ex ex_jeuprogram jeu(input,output);
var choix,rep,nb:integer;
begin
nb:=0;
choix:=random(11);
repeat
nb:=nb+1;
writeln('choix ndeg. ',nb,' ? ');
readln(rep)
until rep=choix;
writeln('trouvé en ',nb,' coups')
end.
-- Ex ex_moyprogram moyenne(input,output);
var n,i:integer;
note,total,moyenne:real;
begin
writeln('nombre notes à entrer ?');
readln(n);
total:=0;
for i:=1 to n do begin
writeln(i,'ième note ? ');
readln(note);
total:=total+note
end;
moyenne:=total/n;
writeln('la moyenne est : ',moyenne)
end.
-- Ex ex_jeu_bisprogram jeu_ameliore(input,output);
var choix,rep,nb:integer;
begin
nb:=0;
choix:=random(11);
repeat
nb:=nb+1;
writeln('choix ndeg. ',nb,' ? ');
readln(rep);
if rep
else if rep>choix then
writeln('c''est moins')
{le 2ème if empêche d'écrire si juste}
until rep=choix;
writeln('juste en ',nb,' coups')
end.
-- Ex ex_calcprogram calculatrice(input,output);
var val1,val2,resultat:real;
operation:char;
begin
writeln('première valeur ?');
readln(val1);
writeln('opération (+ - * /) ? ');
readln(operation)
writeln('deuxième valeur ? ');
readln(val2);
case operation of
'+':resultat:=val1+val2;
'-':resultat:=val1-val2;
'*':resultat:=val1*val2;
'/':resultat:=val1/val2
end;
writeln('résultat : ',resultat)
end.
-- EX moy.aprogram moyenne(input,output);
var n,compteur:integer
somme,moyenne,ecart:real;
note:array[1..100] of real;
begin
repeat
writeln('nb notes (100 maxi)?');
readln(n)
until (n>0) and (n<=100);
{entrée notes et calcul de la somme}
somme:=0;
for compteur:=1 to n do
begin
writeln(compteur,'è note ?');
readln(note[compteur]);
somme:=somme+note[compteur]
end;
{calcul et affichage de la moyenne}
moyenne:=somme/n;
writeln('moyenne : ',moyenne);
{calcul et affichage des écarts}
writeln('écarts :');
for compteur:=1 to n do
begin
ecart:=note[compteur]-moyenne;
writeln(compteur,'ième note (',
note[compteur],
') : écart : ',ecart)
end
end.
-- Ex rot.b
program rotation(input,output);
var index,n:integer;
prem:real;
tableau:array[1..100]of real;
begin
repeat
writeln('nb valeurs (100 maxi)?');
readln(n)
until (n>0) and (n<=100);
(* entrée des valeurs *)
for index:=1 to n do
begin
writeln(index,'ième valeur ?');
readln(tableau[index]);
end;
writeln('on décale vers le haut');
prem:=tableau[1]; {ne pas écraser!}
for index:=2 to n do
tableau[index-1]:=tableau[index];
tableau[n]:=prem;
for index:=1 to n do
writeln(tableau[index]);
writeln('on re-décale vers le bas');
prem:=tableau[n];
for index:=n downto 2 do
tableau[index]:=tableau[index-1];
tableau[1]:=prem;
for index:=1 to n do
writeln(tableau[index])
end.
-- Ex clas.cprogram classer(input,output);
var n,i,index,petit,indexpetit:integer;
avant,apres:array[1..100]of integer;
pris:array[1..100] of boolean;
{pour noter ceux déjà pris}
begin
repeat
writeln('nb valeurs (100 maxi) ?');
readln(n)
until (n>0) and (n<=100);
{entrée valeurs - initialisation de pris}
for index:=1 to n do begin
writeln(index,'ième valeur ? ');
readln(avant[index]);
pris[index]:=false
end;
{ordre croissant,on cherche N valeurs}
for i:=1 to n do begin
petit:=maxint; {plus grand possible}
{recherche du plus petit non pris}
for index:=1 to n do
if (not pris[index]) and
(avant[index]<=petit) then begin
petit:=avant[index];
indexpetit:=index
end;
{ sauvegarde dans le tableau APRES et
mise à jour de PRIS }
apres[i]:=petit;
pris[indexpetit]:=true
end; { passage au prochain i }
{affichage du tableau APRES}
writeln('par ordre croissant : ');
for i:=1 to N do writeln(apres[i]);
{classement par ordre décroissant}
writeln('par ordre décroissant : ');
for i:=n downto 1 do writeln(apres[i])
{n'auriez-vous pas tout refait ?}
end.
-- Ex str
program position(input,output);
var ch,sch:string[255];
i,j,n,l,ls:integer;
begin
writeln('chaîne à tester ? ');
readln(ch);
writeln('sous-chaîne à trouver ?');
readln(sch);
l:=length(ch);ls:=length(sch);
n:=0;
for i:=1 to l-ls do begin
j:=1;
while (j<=l)and(ch[i+j-1]=sch[j])
do j:=j+1;
if j>ls then begin
writeln('trouvé position ',i);
n:=n+1
end
end;
writeln(n,' fois ',sch,' dans ',ch)
end.
--Ex matprogram produit_mat(input,output);
var m1,m2,m3:array[1..10,1..10]of real;
l,m,n,jl,jm,jn:integer;
begin
writeln('nb lignes 1ère matrice ?');
readln(m);
writeln('nb colonnes 1è matrice ?');
readln(l);
writeln('nb colonnes 2è matrice ?');
readln(n);
(* entrée de m1 *)
writeln('première matrice');
for jm:=1 to m do for jl:=1 to l do
begin
writeln('lig',jm,', col',jl,'?');
readln(m1[jm,jl])
end;
(* entrée de m2 *)
writeln('2ième matrice');
for jl:=1 to l do for jn:=1 to n do
begin
writeln('lig',jl,', col',jn,'?');
readln(m2[jl,jn])
end;
(* calcul du produit *)
for jm:=1 to m do for jn:=1 to n do
begin {calcul composante m,n de m2}
m3[jm,jn]:=0;
for jl:=1 to l do m3[jm,jn]:=
m3[jm,jn]+(m1[jm,jl]*m2[jl,jn]);
end;
(* affichage du résultat *)
writeln('résultat');
for jm:=1 to m do for jn:=1 to n do
writeln('m[',jm,',',jn,']=',
m3[jm,jn])
end.
-- Ex telprogram annuaire(input,output);
(* version simplifiée *)
type ligne=string[40];
typepersonne=record
nom:ligne;
num_tel:ligne
(* integer malheureusement < 32635 *)
end;
var pers:array[1..100]of
typepersonne;
nb,i:1..100;
rep:char;
imprimer:boolean;
texte:ligne;
begin
{on suppose avoir ici les instructions
permettant de lire sur fichier disque
NB et le tableau PERS }
repeat
writeln('recherche suivant : ');
writeln(' N : nom');
writeln(' T : numéro téléphone');
writeln(' Q : quitter le prog');
writeln('quel est votre choix ?');
readln(rep);
if rep<>'Q' then begin
writeln('texte à chercher ? ');
readln(texte)
for i:=1 to nb do with pers[i] do
begin
case rep of
'N':imprimer:=nom=texte;
'T':imprimer:=num_tel=texte;
end;
if imprimer then begin
writeln('nom : ',nom);
writeln('tel : ',num_tel)
end
end
end
until rep='Q'
end.
-- Ex recprogram determ(input,output);
{ on se limite à 10x10, ce qui fait 7h
de calcul et 6.235.314 appels à DETN }
type tmat=array[1..10,1..10] of real;
var dim:integer;
{dimension matrice à calculer}
det:real; {résultat désiré}
mat:tmat; {matrice à calculer}
appel:real; {nb appels à }
procedure entree;
var lig,col:integer;
begin
writeln('dimension de la matrice ?');
readln(dim); {DIM variable globale}
writeln('entrez les composantes :');
for lig:=1 to dim do begin
writeln('pour la ligne ndeg. ',lig);
for col:=1 to dim do begin
writeln('colonne ',col,' ?');
readln(mat[lig,col])
end
end
end;
procedure sous_mat(mdeb:tmat; var mfin:
tmat; ind,dim:integer);
{on supprime la colonne 1 et la ligne
ind pour avoir la s/mat de dim-1}
var col,lig,l:integer;
begin
l:=0;
for lig:=1 to dim do begin
if lig<>ind then begin
l:=l+1;
for col:=2 to dim do
mfin[l,col-1]:=mdeb[lig,col]
end
end
end;
function detn(m:tmat;d:integer):real;
{dét ordre d en fonction ordre d-1}
var result:real;
mprim:tmat; {matrice intermédiaire}
lig,signe:integer;
begin
appel:=appel+1;
if d=1 then detn:=m[1,1]
(* fin de récursivité *)
else begin
result:=0;
signe:=-1;
for lig:=1 to d do begin
sous_mat(m,mprim,lig,d);
signe:=-signe;
{changer de signe à chaque ligne}
result:=result +
(signe*m[lig,1]*detn(mprim,d-1))
end;
detn:=result
end
end;
begin (* programme principal *)
entree;
appel:=0;
det:=detn(mat,dim);
writeln('résultat : ',det);
writeln('nb appels DETN : ',appel)
end.
-- Ex fichier
procedure lirefic;
var i:1..100;
f:file of typepersonne;
(* variables globales :
NB et le tableau PERS *)
begin
assign(f,'annuaire'); {non standard}
reset(f);
nb:=0;
while not EOF(f) do begin
nb:=nb+1;
read(f,pers[nb)
end;
close(f)
end;
{à vous de faire la suite}
-- Ex pointeurs
program liste(input,output);
TYPE tpoint=^tval;
tval=record
valeur:integer;
suivant:tpoint
end;
VAR prem:tpoint; {variable globale}
n:integer;
c:char;
procedure lire;
var precedent,point:tpoint;
i:integer;
{ modifie N et PREM }
begin
write('combien d''éléments?');
readln(n);
new(prem);
write('1ère valeur ? ');
readln(prem^.valeur);
precedent:=prem;
for i:=2 to n do begin
new(point);
write(i,'ième valeur ? ');
readln(point^.valeur);
precedent^.suivant:=point;
precedent:=point
end;
precedent^.suivant:=NIL
(* le dernier ne pointe sur rien *)
end;
procedure afficher;
var point:tpoint;
i:integer;
begin
point:=prem;
for i:=1 to n do begin
writeln(point^.valeur);
point:=point^.suivant
end
end;
procedure supprimer;
var point,prec:tpoint;
rep:char;
begin
point:=prem;
repeat
write(point^.valeur,' à ôter ?');
readln(rep);
if rep='O' then begin
n:=n-1;
if point<>prem then begin
prec^.suivant:=point^.suivant;
dispose(point);
point:=prec^.suivant
(* se préparer pour la suite *)
end
else begin
prem:=prem^.suivant;
dispose(point);
(* ancien premier *)
point:=prem
end
end
else begin
(* pointer sur le suivant *)
prec:=point;
point:=point^.suivant
end
until point=nil
end;
procedure rajouter;
var p1,p2,prec:tpoint;
rep:char;
begin
p1:=prem;
repeat
write(p1^.valeur,' rajouter un
élément avant (O/N) ? ');
readln(rep);
if rep='O' then begin
n:=n+1;
if p1<>prem then begin
new(p2);
write('valeur ? ');
readln(p2^.valeur);
prec^.suivant:=p2;
p2^.suivant:=p1;
prec:=p2;
end
else begin
new(p1);
write('valeur ? ');
readln(p1^.valeur);
p1^.suivant:=prem;
prem:=p1
end
end
else begin
(* pointer sur le suivant *)
prec:=p1;
p1:=p1^.suivant
end
until p1=nil;
p1:=prec;
repeat
write('ajouter un élément en fin
de liste (O/N) ? ');
readln(rep);
if rep='O' then begin
n:=n+1;
new(p2);
write('valeur ? ');
readln(p2^.valeur);
p1^.suivant:=p2;
p2^.suivant:=nil;
p1:=p2
end
until rep<>'O'
end;
BEGIN {prog principal}
lire;
repeat
writeln('A:afficher, S:supprimer R:rajouter, F:fin');
write('votre choix ? ');
readln(c);
case c of
'A':afficher;
'S':supprimer;
'R':rajouter
end
until c='F'
end.
Libellés :
CORRECTION DES EXECICES
LES POINTEURS
POINTEURS
LES LISTES CHAINEES ET ARBRES
LES POINTEURS EN PASCAL
Un pointeur est une variable qui stocke l'adresse (c.a.d la position en mémoire) d'une variable.
LES LISTES CHAINEES ET ARBRES
Supposons une liste de 3 entiers. On suppose connaître pour chacun l'adresse du suivant :
si l'on veut insérer une valeur dans la liste, les modifications à apporter sont minimes :
Contrairement à l'insertion dans un tableau, il est inutile de décaler les termes suivants. Pour connaître la liste, il suffit de connaître l'adresse du premier terme.
Pour représenter un arbre, il suffit pour chaque élément de connaître l'adresse de chaque fils :
Rq : si le nombre de fils n'est pas constant, on a intérêt à stocker uniquement le fils aîné, ainsi que le frère suivant.
LES POINTEURS EN PASCAL
En pascal, on utilise les pointeurs pour représenter ces objets. La déclaration se fait de la manière suivante :
TYPE pointeur=^type_de_la_variable_pointéeex : TYPE tpoint=^tval; (* pointe sur des TVAL *)
tval=record
valeur:integer;
suivant:tpoint
end;
VAR p1,p2:tpoint;
Dans cet exemple, les variables de type TVAL contiendront un entier et l'adresse de la suivante (liste chaînée vue plus haut).
Contrairement aux tableaux, il n'est pas nécessaire de prévoir le nombre de variables pointées à l'avance. C'est "l'allocation dynamique de mémoire" : on réserve la place pour chaque variable en cours d'exécution du programme, par la commande NEW(nom_variable). On récupère la place, si la variable est devenue inutile, par DISPOSE(nom_variable).
P1 contient donc une adresse d'une variable de type TVAL. Cette variable sera P1^ (c.a.d pointée par P1). On la "remplit" donc par des affectations du type :
P1^.valeur:=15; P1^.suivant:=P2;
Examinons un programme qui lit puis affiche une liste chaînée d'entiers : program liste(input,output);
TYPE tpoint=^tval;
tval=record
valeur:integer;
suivant:tpoint
end;
VAR prem,precedent,point:tpoint;
i,n:integer;
begin
write('combien d''éléments comporte votre liste ?');
readln(n);
new(prem); (* le 1er est particulier : si on le perd, on perd la liste *)
write('1ère valeur ? ');
readln(prem^.valeur); (* lecture de l'enregistrement VALEUR
de la variable d'adresse (pointée par) PREM *)
precedent:=prem;
for i:=2 to n do begin
new(point); (* création d'une nouvelle variable *)
write(i,'ième valeur ? ');
readln(point^.valeur);
precedent^.suivant:=point; (* mise à jour du chaînage *)
precedent:=point (*se préparer pour la prochaine boucle*)
end;
precedent^.suivant:=NIL;
(* NIL signifie "rien" car 0 est un entier, non une adresse *)
point:=prem; (* heureusement, on se souvient du premier *)
for i:=1 to n do begin
writeln(point^.valeur);
point:=point^.suivant (* pour la prochaine boucle *)
end
end.
EXERCICE (pointeurs) modifier ce programme pour qu'il permette de rajouter ou supprimer des éléments. Décomposez le en routines.
LES LISTES CHAINEES ET ARBRES
LES POINTEURS EN PASCAL
Un pointeur est une variable qui stocke l'adresse (c.a.d la position en mémoire) d'une variable.
LES LISTES CHAINEES ET ARBRES
Supposons une liste de 3 entiers. On suppose connaître pour chacun l'adresse du suivant :
si l'on veut insérer une valeur dans la liste, les modifications à apporter sont minimes :
Contrairement à l'insertion dans un tableau, il est inutile de décaler les termes suivants. Pour connaître la liste, il suffit de connaître l'adresse du premier terme.
Pour représenter un arbre, il suffit pour chaque élément de connaître l'adresse de chaque fils :
Rq : si le nombre de fils n'est pas constant, on a intérêt à stocker uniquement le fils aîné, ainsi que le frère suivant.
LES POINTEURS EN PASCAL
En pascal, on utilise les pointeurs pour représenter ces objets. La déclaration se fait de la manière suivante :
TYPE pointeur=^type_de_la_variable_pointéeex : TYPE tpoint=^tval; (* pointe sur des TVAL *)
tval=record
valeur:integer;
suivant:tpoint
end;
VAR p1,p2:tpoint;
Dans cet exemple, les variables de type TVAL contiendront un entier et l'adresse de la suivante (liste chaînée vue plus haut).
Contrairement aux tableaux, il n'est pas nécessaire de prévoir le nombre de variables pointées à l'avance. C'est "l'allocation dynamique de mémoire" : on réserve la place pour chaque variable en cours d'exécution du programme, par la commande NEW(nom_variable). On récupère la place, si la variable est devenue inutile, par DISPOSE(nom_variable).
P1 contient donc une adresse d'une variable de type TVAL. Cette variable sera P1^ (c.a.d pointée par P1). On la "remplit" donc par des affectations du type :
P1^.valeur:=15; P1^.suivant:=P2;
Examinons un programme qui lit puis affiche une liste chaînée d'entiers : program liste(input,output);
TYPE tpoint=^tval;
tval=record
valeur:integer;
suivant:tpoint
end;
VAR prem,precedent,point:tpoint;
i,n:integer;
begin
write('combien d''éléments comporte votre liste ?');
readln(n);
new(prem); (* le 1er est particulier : si on le perd, on perd la liste *)
write('1ère valeur ? ');
readln(prem^.valeur); (* lecture de l'enregistrement VALEUR
de la variable d'adresse (pointée par) PREM *)
precedent:=prem;
for i:=2 to n do begin
new(point); (* création d'une nouvelle variable *)
write(i,'ième valeur ? ');
readln(point^.valeur);
precedent^.suivant:=point; (* mise à jour du chaînage *)
precedent:=point (*se préparer pour la prochaine boucle*)
end;
precedent^.suivant:=NIL;
(* NIL signifie "rien" car 0 est un entier, non une adresse *)
point:=prem; (* heureusement, on se souvient du premier *)
for i:=1 to n do begin
writeln(point^.valeur);
point:=point^.suivant (* pour la prochaine boucle *)
end
end.
EXERCICE (pointeurs) modifier ce programme pour qu'il permette de rajouter ou supprimer des éléments. Décomposez le en routines.
Libellés :
les pointeurs
LES ENSEMBLES
ENSEMBLES
Un ensemble est une "collection" d'éléments de même type (cf cours maths 6ème). Supposons vouloir représenter des vendeurs et leurs domaines d'action.
Le type ensemble est défini par SET OF : TYPE produits=(velos,motos,autos,accessoires);
VAR vendeur1,vendeur2 : SET OF produits;
On "remplit" un ensemble en donnant ses éléments entre crochets : vendeur1:=[velos,motos];
vendeur2:=[motos,accessoires];
l'ensemble vide est : []
On peut faire les opérations suivantes :
UNION : vendeur1+vendeur2=[velos,motos,accessoires]INTERSECTION : vendeur1*vendeur2=[motos]COMPLEMENT : vendeur1-vendeur2=[velos] vendeur2-vendeur1=[accessoires]
les tests booléens possibles sont : = , <> , <= (inclus) , >= (contenant).
On teste l'appartenance d'un élément par IN : si X vaut motos, alors X IN VENDEUR1 et [motos]<=VENDEUR1 sont équivalents (IN compare un élément et un ensemble, alors que <= compare deux ensembles.
Rq: En général, on ne pense pas à utiliser les ensembles (le prof de maths aurait-il oublié de nous dire à quoi ça sert ?), et l'on s'embrouille dans des programmes complexes. Voici par exemple, des idées pour programmer facilement un automatisme défini par plusieurs Grafcet complexes ([xx] se lisant "ensemble des xx") :[étapes actives]:=[étapes initiales]
pour chaque transition :
si [étapes immédiatement précédentes] <= [étapes actives]
et [capteurs nécessaires] <= [capteurs]
alors [ét. actives]:=[ét. actives]-[précédentes]+[suivantes]
activer [sorties] en fonction [étapes actives] et boucler
On peut trouver un exemple détaillé dans mon document sur la mise en oeuvre du Grafcet
Un ensemble est une "collection" d'éléments de même type (cf cours maths 6ème). Supposons vouloir représenter des vendeurs et leurs domaines d'action.
Le type ensemble est défini par SET OF : TYPE produits=(velos,motos,autos,accessoires);
VAR vendeur1,vendeur2 : SET OF produits;
On "remplit" un ensemble en donnant ses éléments entre crochets : vendeur1:=[velos,motos];
vendeur2:=[motos,accessoires];
l'ensemble vide est : []
On peut faire les opérations suivantes :
UNION : vendeur1+vendeur2=[velos,motos,accessoires]INTERSECTION : vendeur1*vendeur2=[motos]COMPLEMENT : vendeur1-vendeur2=[velos] vendeur2-vendeur1=[accessoires]
les tests booléens possibles sont : = , <> , <= (inclus) , >= (contenant).
On teste l'appartenance d'un élément par IN : si X vaut motos, alors X IN VENDEUR1 et [motos]<=VENDEUR1 sont équivalents (IN compare un élément et un ensemble, alors que <= compare deux ensembles.
Rq: En général, on ne pense pas à utiliser les ensembles (le prof de maths aurait-il oublié de nous dire à quoi ça sert ?), et l'on s'embrouille dans des programmes complexes. Voici par exemple, des idées pour programmer facilement un automatisme défini par plusieurs Grafcet complexes ([xx] se lisant "ensemble des xx") :[étapes actives]:=[étapes initiales]
pour chaque transition :
si [étapes immédiatement précédentes] <= [étapes actives]
et [capteurs nécessaires] <= [capteurs]
alors [ét. actives]:=[ét. actives]-[précédentes]+[suivantes]
activer [sorties] en fonction [étapes actives] et boucler
On peut trouver un exemple détaillé dans mon document sur la mise en oeuvre du Grafcet
Libellés :
ENSEMBLES
LES ENTREES /SORTIES
LES ENTREES / SORTIES
SUR LA CONSOLE
LES FICHIERS DE TEXTE
EXTENSIONS NON STANDARD
ACCES DIRECT
IMPRIMANTE
AUTRES
SUR LA CONSOLE
La procédure WRITELN permet d'afficher des résultats sur l'écran. Les différents arguments sont affichés les uns après les autres sur la même ligne. Le curseur est ensuite automatiquement mis en début de ligne suivante. Pour éviter ceci, on peut utiliser WRITE, qui s'utilise comme WRITELN mais le curseur est laissé derrière le dernier caractère. De même, READ fonctionne comme READLN, excepté le curseur qui reste sur la ligne.
WRITE et WRITELN acceptent le "formatage" : on peut imposer le nombre de caractères utilisés pour chaque variable. Soit I entier, R réel :
WRITE(I:5,' ',R:7:2) écrira I sur 5 caractères, et R sur 7 caractères dont 2 après la virgule. Si les valeurs sont trop petites pour entrer dans le format, des blancs sont mis devant. Si elles sont trop grandes, le format est ignoré.
SUR FICHIER
Un fichier est un ensemble de données, écrites sur un "support" lisible par l'ordinateur (disquette, cartes perforées,...), et regroupées sous un nom. Un fichier peut contenir des caractères (fichier de textes), des programmes, des valeurs (fichier de données).
Etudions l'exemple suivant : program recopier(input,output);
var fic_ent,fic_sor : file of real;
x:real;
begin
assign(fic_ent,'fichier1'); (* non standard *)
reset(fic_ent);
assign(fic_sor,'fichier2'); (* non standard *)
rewrite(fic_sor);
while not eof(fic_ent) do begin
read(fic_ent,x);
write(fic_sor,x)
end;
close(fic_ent);
close(fic_sor)
end.
On déclare les fichiers par :
VAR nomfic : FILE OF type_du_contenu
Un fichier peut contenir des éléments de n'importe quel type (aussi compliqué soit-il, même tableaux), mais tous les enregistrements du fichier doivent être du même type.
Avant d'utiliser le fichier, il faut relier son identificateur au nom effectif du fichier par ASSIGN. Ici, FIC_ENT correspondra à un fichier qui aura pour nom FICHIER1 sur la disquette. ASSIGN n'est pas une fonction standard, d'autres compilateurs utilisent OPEN.
Puis il faut préciser si l'on va écrire ou lire sur le fichier par RESET ou REWRITE. Ceci positionne en début du fichier.
On écrit dans le fichier par WRITE(nomfic,liste_des_variables). Idem pour READ.
Il ne faut pas oublier de fermer le fichier (close) quand on n'en a plus besoin. CLOSE est nécessaire également si l'on veut refaire un nouvel ASSIGN sur le même fichier.
La fonction standard EOF(nomfic) est TRUE quand on arrive en fin de fichier (End Of File).
Rq : Lors de la définition initiale du Pascal, on devait ouvrir les fichiers avant d'appeler le programme. Les fichiers étaient des variables globales déclarées en arguments du programme (et donc passés du système d'exploitation au programme). Nous les déclarons maintenant DANS le programme, les deux seuls fichiers donnés en paramètres du programme restant INPUT et OUTPUT.
LES FICHIERS DE TEXTE
Le principal problème des fichiers précédents est que tous les enregistrements sont du même type. De plus ils ne sont pas directement imprimables ni visibles par un traitement de textes ou un programme écrit dans un autre langage. On y remédie par les fichiers texte (aussi appelés fichiers formatés), déclarés par :
VAR nomfic:TEXT
Ce sont des fichiers de caractères, et se comportent comme l'écran ou le clavier (qui sont d'ailleurs les fichiers text INPUT et OUTPUT utilisés automatiquement si on ne précise pas de nomfic dans les READ et WRITE ). On a aussi les mêmes limitations (écriture d'entiers, réels et chaînes de caractères seulement).ex : program lire(input,output,fic);
type chaine=array[1..80]of char;
var fic:text;
ligne:chaine;
begin
assign(fic,'texte');
rewrite(fic);
writeln('tapez votre texte, il sera enregistré dans le fichier TEXTE ');
writeln('tapez FIN pour arrêter');
repeat
readln(ligne);
writeln(fic,ligne)
until ligne='FIN';
close(fic)
end.
EXTENSIONS NON STANDARD
ACCES DIRECT
La plupart des compilateurs acceptent la procédure SEEK(nomfic,position) qui permet de se positionner n'importe où dans le fichier (sans être obligé de lire dans l'ordre tous les éléments). Ceci n'est évidement possible que si la taille des éléments est constante, donc pour tous les fichiers exceptés ceux du type TEXT, puisque les lignes n'y sont pas de longueur constante. L'accès à une information est donc beaucoup plus rapide (à condition de connaître sa position) On appelle ceci l'ACCES DIRECT à un fichier, par opposition à l' ACCES SEQUENTIEL prévu en standard.
SEEK est d'autant plus utile que RESET autorise la lecture et l'écriture des fichiers à accès direct (REWRITE par contre efface tout le contenu du fichier, on ne peut donc plus qu'écrire).
IMPRIMANTE
Pour accéder à l'imprimante, deux solutions:
* ouvrir un fichier TEXT sur disque, le remplir, et lorsque le programme est terminé le copier (par le DOS) sur imprimante
* utiliser un nom de fichier prédéfini correspondant à l'imprimante. En Turbo, c'est LST. ex : writeln(lst, 'COUCOU'). LST n'a pas besoin d'être ouvert en TURBO (tout comme OUTPUT).
AUTRES
Turbo Pascal permet beaucoup d'autres opérations sur les fichiers (Delete, Rename, Path...) qui ne sont pas standard. Si vous les utilisez, rappelez vous qu'elles ne fonctionneront pas avec un autre compilateur (Microsoft par ex) ni sous un autre système d'exploitation (Unix par ex).
EXERCICE (fichier) Ecrire la procédure qui lit le fichier "annuaire" afin de rendre opérationnel l'exercice tel. Modifier ce programme pour permettre l'entrée et la modification du fichier annuaire.
SUR LA CONSOLE
LES FICHIERS DE TEXTE
EXTENSIONS NON STANDARD
ACCES DIRECT
IMPRIMANTE
AUTRES
SUR LA CONSOLE
La procédure WRITELN permet d'afficher des résultats sur l'écran. Les différents arguments sont affichés les uns après les autres sur la même ligne. Le curseur est ensuite automatiquement mis en début de ligne suivante. Pour éviter ceci, on peut utiliser WRITE, qui s'utilise comme WRITELN mais le curseur est laissé derrière le dernier caractère. De même, READ fonctionne comme READLN, excepté le curseur qui reste sur la ligne.
WRITE et WRITELN acceptent le "formatage" : on peut imposer le nombre de caractères utilisés pour chaque variable. Soit I entier, R réel :
WRITE(I:5,' ',R:7:2) écrira I sur 5 caractères, et R sur 7 caractères dont 2 après la virgule. Si les valeurs sont trop petites pour entrer dans le format, des blancs sont mis devant. Si elles sont trop grandes, le format est ignoré.
SUR FICHIER
Un fichier est un ensemble de données, écrites sur un "support" lisible par l'ordinateur (disquette, cartes perforées,...), et regroupées sous un nom. Un fichier peut contenir des caractères (fichier de textes), des programmes, des valeurs (fichier de données).
Etudions l'exemple suivant : program recopier(input,output);
var fic_ent,fic_sor : file of real;
x:real;
begin
assign(fic_ent,'fichier1'); (* non standard *)
reset(fic_ent);
assign(fic_sor,'fichier2'); (* non standard *)
rewrite(fic_sor);
while not eof(fic_ent) do begin
read(fic_ent,x);
write(fic_sor,x)
end;
close(fic_ent);
close(fic_sor)
end.
On déclare les fichiers par :
VAR nomfic : FILE OF type_du_contenu
Un fichier peut contenir des éléments de n'importe quel type (aussi compliqué soit-il, même tableaux), mais tous les enregistrements du fichier doivent être du même type.
Avant d'utiliser le fichier, il faut relier son identificateur au nom effectif du fichier par ASSIGN. Ici, FIC_ENT correspondra à un fichier qui aura pour nom FICHIER1 sur la disquette. ASSIGN n'est pas une fonction standard, d'autres compilateurs utilisent OPEN.
Puis il faut préciser si l'on va écrire ou lire sur le fichier par RESET ou REWRITE. Ceci positionne en début du fichier.
On écrit dans le fichier par WRITE(nomfic,liste_des_variables). Idem pour READ.
Il ne faut pas oublier de fermer le fichier (close) quand on n'en a plus besoin. CLOSE est nécessaire également si l'on veut refaire un nouvel ASSIGN sur le même fichier.
La fonction standard EOF(nomfic) est TRUE quand on arrive en fin de fichier (End Of File).
Rq : Lors de la définition initiale du Pascal, on devait ouvrir les fichiers avant d'appeler le programme. Les fichiers étaient des variables globales déclarées en arguments du programme (et donc passés du système d'exploitation au programme). Nous les déclarons maintenant DANS le programme, les deux seuls fichiers donnés en paramètres du programme restant INPUT et OUTPUT.
LES FICHIERS DE TEXTE
Le principal problème des fichiers précédents est que tous les enregistrements sont du même type. De plus ils ne sont pas directement imprimables ni visibles par un traitement de textes ou un programme écrit dans un autre langage. On y remédie par les fichiers texte (aussi appelés fichiers formatés), déclarés par :
VAR nomfic:TEXT
Ce sont des fichiers de caractères, et se comportent comme l'écran ou le clavier (qui sont d'ailleurs les fichiers text INPUT et OUTPUT utilisés automatiquement si on ne précise pas de nomfic dans les READ
type chaine=array[1..80]of char;
var fic:text;
ligne:chaine;
begin
assign(fic,'texte');
rewrite(fic);
writeln('tapez votre texte, il sera enregistré dans le fichier TEXTE ');
writeln('tapez FIN pour arrêter');
repeat
readln(ligne);
writeln(fic,ligne)
until ligne='FIN';
close(fic)
end.
ACCES DIRECT
La plupart des compilateurs acceptent la procédure SEEK(nomfic,position) qui permet de se positionner n'importe où dans le fichier (sans être obligé de lire dans l'ordre tous les éléments). Ceci n'est évidement possible que si la taille des éléments est constante, donc pour tous les fichiers exceptés ceux du type TEXT, puisque les lignes n'y sont pas de longueur constante. L'accès à une information est donc beaucoup plus rapide (à condition de connaître sa position) On appelle ceci l'ACCES DIRECT à un fichier, par opposition à l' ACCES SEQUENTIEL prévu en standard.
SEEK est d'autant plus utile que RESET autorise la lecture et l'écriture des fichiers à accès direct (REWRITE par contre efface tout le contenu du fichier, on ne peut donc plus qu'écrire).
IMPRIMANTE
Pour accéder à l'imprimante, deux solutions:
* ouvrir un fichier TEXT sur disque, le remplir, et lorsque le programme est terminé le copier (par le DOS) sur imprimante
* utiliser un nom de fichier prédéfini correspondant à l'imprimante. En Turbo, c'est LST. ex : writeln(lst, 'COUCOU'). LST n'a pas besoin d'être ouvert en TURBO (tout comme OUTPUT).
AUTRES
Turbo Pascal permet beaucoup d'autres opérations sur les fichiers (Delete, Rename, Path...) qui ne sont pas standard. Si vous les utilisez, rappelez vous qu'elles ne fonctionneront pas avec un autre compilateur (Microsoft par ex) ni sous un autre système d'exploitation (Unix par ex).
EXERCICE (fichier) Ecrire la procédure qui lit le fichier "annuaire" afin de rendre opérationnel l'exercice tel. Modifier ce programme pour permettre l'entrée et la modification du fichier annuaire.
Libellés :
ENTREES ET SORTIES
PROCEDURES ET FONCTIONS
GENERALITES
PORTEE DES DECLARATIONS
ARGUMENTS (OU PARAMETRES)
LES FONCTIONS
RECURSIVITE
Nous avons déjà vu un certain nombre de procédures (ex WRITELN) et fonctions (SQRT, SIN...) prédéfinies par le compilateur. Mais si l'on en désire d'autres, il suffit de les définir.
GENERALITES
On peut regrouper un ensemble d'instructions sous un même nom. On forme alors un sous-programme ou procédure. On utilise les procédures :
* chaque fois qu'une même suite d'instructions doit être répétée plusieurs fois dans un programme,
* quand une suite d'instruction forme une action globale. Le programme est alors plus clair et les erreurs plus facilement détectables.
Pour pouvoir utiliser une procédure, il faut d'abord la déclarer. La déclaration des procédures et fonctions se fait après toutes les autres déclarations.
structure d'une entité de programme (routine) :entête
déclaration des :
labels; {pour les GOTO, déconseillé}
constantes;
types;
variables;
définition des sous-routines; {sous-programmes}
BEGIN
instructions
ENDle programme principal comme les procédures et les fonctions ont toujours cette structure. L'entête est composée d'un mot clef (PROGRAM, PROCEDURE ou FUNCTION), suivi de l'identificateur (nom) de la routine, et de la liste des arguments entre parenthèses. Les arguments forment la liaison avec l'extérieur de la routine (clavier, écran et éventuellement fichiers pour le programme).
PROGRAM remplir (output);
{entête du prog principal}
var i:integer;
{déclarations prog princ.}
{dont déclaration LIGNE}
PROCEDURE ligne(n:integer);
{entête de la procédure}
var j:integer;
{déclarations procédure}
BEGIN
{corps de la procédure}
for j:=1 to n do write('*');
writeln
END;
BEGIN
{instructions du prog princ}
for i:=1 to 25 do ligne(70)
END.
la procédure LIGNE écrit N caractères '*' sur une même ligne. Le programme remplit donc l'écran (25 lignes 70 colonnes) d'étoiles.
On peut appeler une procédure déclarée dans une routine n'importe où dans cette routine en indiquant simplement son nom comme si c'était une instruction. A l'appel d'une procédure, le programme interrompt son déroulement normal, exécute les instructions de la procédure, puis retourne au programme appelant et exécute l'instruction suivante. Tout ce passe donc comme si le nom de la procédure était remplacé dans le programme par les instructions de la procédure (avec n=70).
PORTEE DES DECLARATIONS
Celle-ci est symbolisée dans l'exemple ci-dessus par deux cadres : la variable I et la procédure LIGNE (avec un argument entier) sont déclarées dans REMPLIR, et donc connues dans tout le programme (rectangle extérieur). Par contre N et J sont déclarés dans LIGNE et ne sont connus (et utilisables) que dans le rectangle intérieur.
En d'autres termes :
* Une variable est LOCALE pour une procédure X si elle est déclarée dans X. Elle n'existe que dans X (et dans les procédures déclarées à l'intérieur de X). La routine qui comporte la procédure X ne peut donc pas accéder à cette variable locale.
* Une variable est GLOBALE pour une procédure X si elle est déclarée dans une routine ENGLOBANT la procédure X. Elle peut être utilisée dans la procédure. La modifier la modifie également dans le routine appelante (englobante).
Si l'on avait déclaré une variable I dans la procédure LIGNE (au lieu de N ou J), celle-ci aurait été locale à la procédure, c'est à dire que, dans le programme principal, I désigne une autre case mémoire que dans la procédure. Modifier la variable locale I ne modifie pas la variable globale I (momentanément inaccessible).
Rq : Ceci s'applique à toutes les déclarations. En particulier, une procédure déclarée localement à l'intérieur d'une procédure est indéfinie à l'extérieur.
ARGUMENTS (OU PARAMETRES)
Les échanges d'informations entre une routine appelant une sous-routine peuvent se faire par l'intermédiaire des variables globales. Mais il est beaucoup plus intéressant d'utiliser les PARAMETRES :Ex : PROGRAM machin (input,output);
VAR a,b,c,d:real;
PROCEDURE aff_somme(x,y:real);
var z:real;
begin
z:=x+y;
writeln(x ,' + ', y ,' = ', z)
end;
BEGIN { programme principal }
writeln('entrez 4 valeurs : ');
readln(a,b,c,d);
aff_somme(a,b); aff_somme(3,5); aff_somme(c+a,d)
END.
En appelant AFF_SOMME(A,B), la procédure prend pour X la valeur de A, et pour Y la valeur de B. On dit que les arguments sont "passés par valeur". Mais si la procédure modifiait X ou Y, A et B ne seraient pas modifiés dans le programme appelant. Pour répercuter les modifications des arguments, il faut les déclarer comme "variables" (ils sont alors dits "passés par adresse").ex : procedure echange(VAR x,y:real);
var z:real;
begin
z:=x;
x:=y;
y:=z
end; {cette procédure échange les contenus des 2
arguments}
LES FONCTIONS
Tout ce qui a été dit pour les procédures s'applique également aux fonctions. La différence avec une procédure est qu'une fonction renvoie un résultat. L'entête est du type :
FUNCTION nom_fonction (liste_parametres):type_de_la_fonction
la liste des paramètres (en général passés par valeur) est de la même forme que pour une procédure, le type de la fonction étant le type du résultat retourné. On retourne le résultat par :
NOM_FONCTION := ... Cette affectation ne peut se faire qu'une seule fois par appel à la fonction.ex : program classer(input,output);
var a,b,c:real;
function MAX(x,y:real):real;
begin
if x>=y then MAX:=x else MAX:=y
end;
begin
writeln('entrez deux valeurs : ');
readln(a,b);
c:=max(a,b);
writeln('le plus grand est ',c)
end.
La fonction MAX a 2 paramètres réels (X et Y) et renvoie un réel.
RECURSIVITE
C'est ainsi que l'on appelle le fait qu'une routine puisse s'appeler elle-même.ex : function factorielle(n:integer):integer;
begin
if n<=1 then factorielle:=1
else factorielle:=n*factorielle(n-1)
end;
Par exemple en appelant factorielle(3), on calcule 3*factorielle(2). Or factorielle(2)=2*factorielle(1), qui lui vaut 1. Donc factorielle(3)=3*(2*1) (ce qui me parait juste). Faites un petit dessin, à chaque appel on recrée de nouvelles variables locales, donc on obtient 3 cases N distinctes valant 3, 2 et 1, on les supprime petit à petit en passant sur le END.
Rq : Il faut toujours vérifier qu'en aucun cas on ne puisse avoir une boucle infinie qui bloquerait la machine. Ce serait le cas en mettant le test IF N=1 et en appelant factorielle pour une valeur négative ou nulle.
Une procédure devant toujours être déclarée pour pouvoir être utilisée, on utilise FORWARD pour les cas de récursivité passant par 2 procédures :function prem(a,b:real):boolean; FORWARD;
{déclaration anticipée de l'entête }
procedure deux(x,y:real);
var bool:boolean;
begin
......
bool:=prem(x,y); {on peut utiliser PREM car déjà déclarée}
......
end;
function prem;
{ne plus donner les arguments car déjà déclarés}
begin
......
if pas_fini then deux(a,b); (* DEUX déjà
déclarée*)
......
end;EXERCICE (rec) écrire le programme qui calcule le déterminant d'une matrice carrée NxN sachant que celui-ci vaut : n
DETn = (-1)i+1 .M[i,1].DETn-1
i=1
où M[i,1] est l'élément de la matrice (ligne i, 1ère colonne),DETn-1 est le déterminant de la sous-matrice d'ordre n-1 obtenu en ôtant la ligne i et la 1ère colonne.
Le déterminant d'une matrice 1x1 est son seul élément.
On utilisera bien évidement une fonction récursive, et l'on séparera le calcul de sous-matrice dans une procédure.
Rq : Il existe des méthodes numériques permettant d'accéder au résultat beaucoup plus rapidement que par cette méthode.
GENERALITES
PORTEE DES DECLARATIONS
ARGUMENTS (OU PARAMETRES)
LES FONCTIONS
RECURSIVITE
Nous avons déjà vu un certain nombre de procédures (ex WRITELN) et fonctions (SQRT, SIN...) prédéfinies par le compilateur. Mais si l'on en désire d'autres, il suffit de les définir.
GENERALITES
On peut regrouper un ensemble d'instructions sous un même nom. On forme alors un sous-programme ou procédure. On utilise les procédures :
* chaque fois qu'une même suite d'instructions doit être répétée plusieurs fois dans un programme,
* quand une suite d'instruction forme une action globale. Le programme est alors plus clair et les erreurs plus facilement détectables.
Pour pouvoir utiliser une procédure, il faut d'abord la déclarer. La déclaration des procédures et fonctions se fait après toutes les autres déclarations.
structure d'une entité de programme (routine) :entête
déclaration des :
labels; {pour les GOTO, déconseillé}
constantes;
types;
variables;
définition des sous-routines; {sous-programmes}
BEGIN
instructions
ENDle programme principal comme les procédures et les fonctions ont toujours cette structure. L'entête est composée d'un mot clef (PROGRAM, PROCEDURE ou FUNCTION), suivi de l'identificateur (nom) de la routine, et de la liste des arguments entre parenthèses. Les arguments forment la liaison avec l'extérieur de la routine (clavier, écran et éventuellement fichiers pour le programme).
PROGRAM remplir (output);
{entête du prog principal}
var i:integer;
{déclarations prog princ.}
{dont déclaration LIGNE}
PROCEDURE ligne(n:integer);
{entête de la procédure}
var j:integer;
{déclarations procédure}
BEGIN
{corps de la procédure}
for j:=1 to n do write('*');
writeln
END;
BEGIN
{instructions du prog princ}
for i:=1 to 25 do ligne(70)
END.
la procédure LIGNE écrit N caractères '*' sur une même ligne. Le programme remplit donc l'écran (25 lignes 70 colonnes) d'étoiles.
On peut appeler une procédure déclarée dans une routine n'importe où dans cette routine en indiquant simplement son nom comme si c'était une instruction. A l'appel d'une procédure, le programme interrompt son déroulement normal, exécute les instructions de la procédure, puis retourne au programme appelant et exécute l'instruction suivante. Tout ce passe donc comme si le nom de la procédure était remplacé dans le programme par les instructions de la procédure (avec n=70).
PORTEE DES DECLARATIONS
Celle-ci est symbolisée dans l'exemple ci-dessus par deux cadres : la variable I et la procédure LIGNE (avec un argument entier) sont déclarées dans REMPLIR, et donc connues dans tout le programme (rectangle extérieur). Par contre N et J sont déclarés dans LIGNE et ne sont connus (et utilisables) que dans le rectangle intérieur.
En d'autres termes :
* Une variable est LOCALE pour une procédure X si elle est déclarée dans X. Elle n'existe que dans X (et dans les procédures déclarées à l'intérieur de X). La routine qui comporte la procédure X ne peut donc pas accéder à cette variable locale.
* Une variable est GLOBALE pour une procédure X si elle est déclarée dans une routine ENGLOBANT la procédure X. Elle peut être utilisée dans la procédure. La modifier la modifie également dans le routine appelante (englobante).
Si l'on avait déclaré une variable I dans la procédure LIGNE (au lieu de N ou J), celle-ci aurait été locale à la procédure, c'est à dire que, dans le programme principal, I désigne une autre case mémoire que dans la procédure. Modifier la variable locale I ne modifie pas la variable globale I (momentanément inaccessible).
Rq : Ceci s'applique à toutes les déclarations. En particulier, une procédure déclarée localement à l'intérieur d'une procédure est indéfinie à l'extérieur.
ARGUMENTS (OU PARAMETRES)
Les échanges d'informations entre une routine appelant une sous-routine peuvent se faire par l'intermédiaire des variables globales. Mais il est beaucoup plus intéressant d'utiliser les PARAMETRES :Ex : PROGRAM machin (input,output);
VAR a,b,c,d:real;
PROCEDURE aff_somme(x,y:real);
var z:real;
begin
z:=x+y;
writeln(x ,' + ', y ,' = ', z)
end;
BEGIN { programme principal }
writeln('entrez 4 valeurs : ');
readln(a,b,c,d);
aff_somme(a,b); aff_somme(3,5); aff_somme(c+a,d)
END.
En appelant AFF_SOMME(A,B), la procédure prend pour X la valeur de A, et pour Y la valeur de B. On dit que les arguments sont "passés par valeur". Mais si la procédure modifiait X ou Y, A et B ne seraient pas modifiés dans le programme appelant. Pour répercuter les modifications des arguments, il faut les déclarer comme "variables" (ils sont alors dits "passés par adresse").ex : procedure echange(VAR x,y:real);
var z:real;
begin
z:=x;
x:=y;
y:=z
end; {cette procédure échange les contenus des 2
arguments}
LES FONCTIONS
Tout ce qui a été dit pour les procédures s'applique également aux fonctions. La différence avec une procédure est qu'une fonction renvoie un résultat. L'entête est du type :
FUNCTION nom_fonction (liste_parametres):type_de_la_fonction
la liste des paramètres (en général passés par valeur) est de la même forme que pour une procédure, le type de la fonction étant le type du résultat retourné. On retourne le résultat par :
NOM_FONCTION := ... Cette affectation ne peut se faire qu'une seule fois par appel à la fonction.ex : program classer(input,output);
var a,b,c:real;
function MAX(x,y:real):real;
begin
if x>=y then MAX:=x else MAX:=y
end;
begin
writeln('entrez deux valeurs : ');
readln(a,b);
c:=max(a,b);
writeln('le plus grand est ',c)
end.
La fonction MAX a 2 paramètres réels (X et Y) et renvoie un réel.
RECURSIVITE
C'est ainsi que l'on appelle le fait qu'une routine puisse s'appeler elle-même.ex : function factorielle(n:integer):integer;
begin
if n<=1 then factorielle:=1
else factorielle:=n*factorielle(n-1)
end;
Par exemple en appelant factorielle(3), on calcule 3*factorielle(2). Or factorielle(2)=2*factorielle(1), qui lui vaut 1. Donc factorielle(3)=3*(2*1) (ce qui me parait juste). Faites un petit dessin, à chaque appel on recrée de nouvelles variables locales, donc on obtient 3 cases N distinctes valant 3, 2 et 1, on les supprime petit à petit en passant sur le END.
Rq : Il faut toujours vérifier qu'en aucun cas on ne puisse avoir une boucle infinie qui bloquerait la machine. Ce serait le cas en mettant le test IF N=1 et en appelant factorielle pour une valeur négative ou nulle.
Une procédure devant toujours être déclarée pour pouvoir être utilisée, on utilise FORWARD pour les cas de récursivité passant par 2 procédures :function prem(a,b:real):boolean; FORWARD;
{déclaration anticipée de l'entête }
procedure deux(x,y:real);
var bool:boolean;
begin
......
bool:=prem(x,y); {on peut utiliser PREM car déjà déclarée}
......
end;
function prem;
{ne plus donner les arguments car déjà déclarés}
begin
......
if pas_fini then deux(a,b); (* DEUX déjà
déclarée*)
......
end;EXERCICE (rec) écrire le programme qui calcule le déterminant d'une matrice carrée NxN sachant que celui-ci vaut : n
DETn = (-1)i+1 .M[i,1].DETn-1
i=1
où M[i,1] est l'élément de la matrice (ligne i, 1ère colonne),DETn-1 est le déterminant de la sous-matrice d'ordre n-1 obtenu en ôtant la ligne i et la 1ère colonne.
Le déterminant d'une matrice 1x1 est son seul élément.
On utilisera bien évidement une fonction récursive, et l'on séparera le calcul de sous-matrice dans une procédure.
Rq : Il existe des méthodes numériques permettant d'accéder au résultat beaucoup plus rapidement que par cette méthode.
Libellés :
procedures et fonctions
Inscription à :
Articles (Atom)