Documente Academic
Documente Profesional
Documente Cultură
1 Tableaux
scrira en C :
var=0.0;
for (i=a;i<=b;++i)
var += expr(i);
Le parcours dun tableau de n lments en langage C se fait en gnral par une boucle allant
de lindice 0 lindice n 1 (inclus). Il vaut mieux crire la condition de rptition sous la forme
i < n que sous la forme i <= n-1 , ce qui permet dune part de gagner une soustraction par tour
de boucle, et dautre part de garder sous forme explicite le nombre dlments traiter dans lcriture
du programme.
Ce qui donne la solution possible suivante :
double moyenne(double *t, int n) {
int i;
double total=0.0;
for (i = 0 ; i < n ; ++i) {
total += t[i];
}
return total/n;
}
***************************************************************************
Exercice 2. Recherche dlments sur critre(*)
crivez la fonction qui retourne lindice du premier lment strictement ngatif parmi les n
premiers lments dun tableau de double ( -1 si aucun lment nest ngatif).
Prototype : int indice_premier_negatif (double t[], int n);
Corrig
***************************************************************************
Ici, lanalyse du problme nous conduit la solution suivante :
1/13
ESIEE IGI-3008 TP Langage C no 2 (corrig) 2014-2015
on parcourt le tableau
si lon rencontre un lment ngatif, on termine la fonction en retournant lindice courant
si lon a parcouru lintgralit du tableau sans avoir rencontr dlment ngatif, on retourne
1 comme indiqu dans la spcification.
Attention : cest aprs la boucle que lon peut constater labsence dlment ngatif. Une erreur
courante de programmation consiste retourner 1 trop tt, avec un test du style
if (t[i]<0) return i; else return -1;
ce qui conduit retourner -1 si le premier un lment nest pas ngatif. Cest toute la diffrence
entre une recherche existentielle : i t[i] < 0 et une recherche universelle i t[i] 0.
int indice_premier_negatif (double t[], int n) {
int i;
for (i=0; i<n ; ++i) {
if (t[i]<0)
return i;
}
return -1;
}
***************************************************************************
Exercice 3. Maximum (*)
crivez la fonction qui retourne la valeur du plus grand des n premiers lments dun tableau
de double .
Prototype : double valeur_plus_grand (double t[], int n);
Corrig
***************************************************************************
Un parcours du tableau simpose, avec une mmorisation du plus grand lment rencontr. En
effet, le plus grand lment du tableau peut se situer nimporte o (en dbut, en cours ou en fin de
tableau) et donc on ne peut le connatre quaprs avoir examin tous les lments du tableau, et le
mmoriser permettra de le retourner en fin de parcours.
Linitialisation de ce maximum pourra se faire par le premier lment du tableau ( t[0] ), et la
boucle peut commencer par lindice 1. Le corps de la boucle consistera comparer llment courant
au maximum, et, sil lui est suprieur, le mmoriser dans le maximum.
Ce qui conduit la solution suivante :
double valeur_plus_grand (double t[], int n) {
int i;
double maxi=t[0];
for (i=1;i<n;++i) {
if (t[i]>maxi)
maxi=t[i];
}
return maxi;
}
***************************************************************************
Exercice 4. Position du maximum (*)
crivez la fonction qui retourne lindice du plus grand des n premiers lments dun tableau
de double (en cas dex-quo, lindice du premier dentre eux).
Prototype : int indice_plus_grand (double t[], int n);
Corrig
***************************************************************************
2/13
ESIEE IGI-3008 TP Langage C no 2 (corrig) 2014-2015
Le programme est semblable au prcdent. Un parcours du tableau simpose, avec une mmorisa-
tion de lindice du plus grand lment rencontr. En effet, le plus grand lment du tableau peut se
situer nimporte o (en dbut, en cours ou en fin de tableau) et donc on ne peut le connatre quaprs
avoir examin tous les lments du tableau ; mmoriser sa position permettra de la retourner en fin
de parcours.
Linitialisation de cet indice maximum pourra se faire par lindice du premier lment du tableau
( 0 ), et la boucle peut commencer par lindice 1.
Ce qui conduit la solution suivante :
int indice_plus_grand (double t[], int n) {
int i;
int imax=0;
for (i=1;i<n;++i) {
if (t[i]>t[imax])
imax=i;
}
return imax;
}
***************************************************************************
Exercice 5. Rsistance quivalente (**)
crivez une fonction qui calcule la rsistance quivalente dun nombre quelconque de rsis-
tances en parallle.
n
1 X 1
Rappel : =
R Ri
i=1
Prototype : double resistance (double r[], int n);
Corrig
***************************************************************************
Cest un schma classique daccumulation (somme des inverses des lments du tableau), puis
retour de linverse de laccumulateur. Un cueil viter est loubli du cas o un des lments est
nul, ce qui conduirait une division par 0. La solution consiste retourner directement 0 si lun des
lments est nul.
double resistance (double r[], int n) {
double req=0.0;
int i;
for (i=0;i<n;++i) {
if (r[i]==0.0)
return 0.0;
req += 1/r[i];
}
return 1/req;
}
***************************************************************************
Exercice 6. Conversion chane de caractres en entier (**)
crivez une fonction qui prend en argument une chane de caractres reprsentant un entier
en dcimal et retourne lentier quivalent. ( "123"123 ). On supposera que la chane est
correcte et reprsente bien un entier.
Prototype : int chaine_vers_entier (char *s);
Corrig
***************************************************************************
3/13
ESIEE IGI-3008 TP Langage C no 2 (corrig) 2014-2015
Une chane reprsentant un entier est compose dune suite de caractres chiffres (compris entre
'0' et '9' ), ventuellement prcde dune caractre '' ou '+'.
Lentier correspondant un caractre chiffre est gal ce caractre moins le caractre '0' . ( '2''0'
2)
Sil y a un signe, on le mmorise sous le forme dune variable valant 1 ou +1. Puis, on accumule
dans un rsultat le nombre reprsent selon le principe suivant :
pour chaque chiffre, on multiplie par 10 la valeur accumule et on ajoute la valeur du chiffre.
En fin de calcul, on retourne le rsultat multipl par le signe.
int chaine_vers_entier (char * s) {
int i=0, signe=1, res=0;
if (s[i]=='+')
++i;
else if (s[i]=='-') {
signe=-1;
++i;
}
for(;s[i]!='\0';++i) {
res=res*10+s[i]-'0';
}
return signe*res;
}
Note : cest ainsi que les fontions atoi (conversion dune chane en int ) et atol (conversion
dune chane en long ) de la librairie libc oprent. Elles permettent galement la conversion dune
chane exprimant un nombre en base 8 (commenant par un 0) ou en base 16 (commenant par 0x
ou 0X). De plus, elles interrompent le calcul lorsquelles parviennent un caractre non autoris et
retournent le rsultat courant.
***************************************************************************
Exercice 7. Miroir (*)
crivez une fonction qui prend en argument une chane de caractres, la renverse sur elle-
mme ( "toto""otot" ) et retourne ladresse de cette chane.
Prototype : char * miroir (char *s);
Corrig
***************************************************************************
Il faut dj parcourir la chane pour accder son dernier caractre. Puis permuter les couples de
caractres symtriques en vitant de le faire deux fois, ce qui laisserait la chane inchange.
char * miroir (char * s) {
int g,d; /* indice gauche et droit de parcours */
char c;
for (d=0;s[d]!=0;++d);
for (g=0,--d;g<d;++g,--d) {
c=s[g];
s[g]=s[d];
s[d]=c;
}
return s;
}
***************************************************************************
Exercice 8. Rptition (*)
crivez une fonction qui prend en argument une chane de caractres et laffiche en rptant
chaque caractre n fois (lappel avec "toto" et 3 affichera "tttoootttooo" ).
4/13
ESIEE IGI-3008 TP Langage C no 2 (corrig) 2014-2015
5/13
ESIEE IGI-3008 TP Langage C no 2 (corrig) 2014-2015
return 1;
}
***************************************************************************
Exercice 11. Recherche de motif (2)(**)
crivez une fonction qui prend en argument deux chanes de caractres et retourne la position
de la premire occurrence de la chane2 dans la chane1 si elle y est prsente et -1 sinon.
Prototype : int presence (char * chaine1, char * chaine2);
Corrig
***************************************************************************
Un appel itratif debute_par permettra de dtecter la prsence de la sous-chane.
Note : ce programme considre que la chane vide dbute toute chane (retour 0).
int presence (char * chaine1, char * chaine2) {
int i;
for (i=0;chaine1[i]!='\0';++i)
if (debute_par(&chaine1[i],chaine2))
return i;
return -1;
}
***************************************************************************
Exercice 12. Frquence (**)
crivez une fonction qui compte le nombre doccurrences dun caractre c dans une chane s.
La fonction devra tre rcursive. crivez un programme pour tester cette fonction.
Prototype : int compte (char c, char * s)
Corrig
***************************************************************************
int compte (char c, char * s) {
if (*s=='\0') {
return 0;
}
return compte(c,s+1) + (*s==c?1:0)
}
***************************************************************************
Exercice 13. Chercher/remplacer (**)
crivez une fonction qui recherche dans une chane chaque caractre c pour le remplacer par
un caractre r et retourne ladresse de la chane.
Prototype : char * cherche_remplace (char c, char r, char * s);
Corrig
***************************************************************************
Cest un parcours simple avec remplacement lorsque lon tombe sur le caractre remplacer :
char * cherche_remplace (char c, char r, char * s) {
int i;
for (i=0;s[i]!='\0';++i)
if (s[i]==c)
s[i]=r;
return(s);
}
***************************************************************************
6/13
ESIEE IGI-3008 TP Langage C no 2 (corrig) 2014-2015
2 Mmoire et pointeurs
int a;
int *pa;
double x;
int **p;
a=8;
pa=&a;
x=3.14159;
p=&pa;
**p=281;
En supposant que la mmoire soit structure en octets, que les entiers soient cods sur 4
octets, les pointeurs sur 4 octets et que la zone de mmoire automatique soit situe en dbut
dexcution ladresse 2004, reprsentez la mmoire finale de ce programme.
Corrig
***************************************************************************
Aprs lexcution de ce programme, la mmoire ressemblera au schma suivant :
variable adresse mmoire contenu
a 2004 281
2005
2006
2007
pa 2008 2004
2009
2010
2011
x 2012 3.14159
2013
2014
2015
2016
2017
2018
2019
p 2020 2008
2021
2022
2023
La dernire instruction (p=281;) sera value comme suit :
laffectation =281; va mettre 281 en mmoire. Mais o ?
p vaut 2008
p est la mmoire dont ladresse est la valeur de p (2008), donc p est le pointeur dentier (p
est un int , donc p est un int ) situ en 2008 et sa valeur est 2004
7/13
ESIEE IGI-3008 TP Langage C no 2 (corrig) 2014-2015
p est la mmoire dont ladresse est la valeur de p (2004), donc lentier (p est un int ,
donc p est un int ) situ en 2004.
laffectation p=281; va mettre 281 dans la mmoire situe en 2004, donc indirectement
dans a. Do la valeur finale de a : 281.
***************************************************************************
Exercice 15. changes (1) (*)
Soit la fonction suivante :
8/13
ESIEE IGI-3008 TP Langage C no 2 (corrig) 2014-2015
int a int b
2 3
Tout ce travail pour rien...
***************************************************************************
Exercice 16. changes (2) (*)
Soit la fonction suivante :
9/13
ESIEE IGI-3008 TP Langage C no 2 (corrig) 2014-2015
10/13
ESIEE IGI-3008 TP Langage C no 2 (corrig) 2014-2015
11/13
ESIEE IGI-3008 TP Langage C no 2 (corrig) 2014-2015
***************************************************************************
Exercice 20. Copie (**)
crivez la fonction qui copie les n premiers lments dun tableau source de double dans
le tableau destination de double et retourne ladresse du tableau destination. On prendra en
compte le fait que les deux tableaux peuvent se recouvrir partiellement.
Prototype : double * copie (double * destination, double * source, int n);
Corrig
***************************************************************************
La solution naturelle est base sur le principe : on parcourt paralllement les deux tableaux et on
copie lment par lment le contenu du tableau source dans le tableau destination, ce qui donne :
double *copie(double *destination, double *source, int n) {
/* Attention : ne fonctionne que si
* les tableaux ne se recouvrent pas
*/
int i;
for (i=0 ; i<n ; ++i) {
destination[i] = source[i];
}
return destination;
}
Une erreur peut survenir lorsque lon appelle cette fonction avec deux tableaux se recouvrant. Par
exemple, avec le morceau de programme suivant :
double tab[]={8,2,103,-4,5,8};
copie(&tab[1],tab,5);/* tentative de decalage droite */
on voudrait dcaler dune position vers la fin de tableau les cinq premiers lments. Or la fonction
va craser succesivement les lments du tableau quelle na pas encore copis, ce qui conduira au
rsultat suivant :
8 8 8 8 8 8
alors que lon aurait voulu obtenir :
8 8 2 103 -4 5
Faire la boucle dans lautre sens (de la fin vers le dbut) poserait le mme problme pour un
dcalage vers la gauche.
Une solution consiste tester la position de la source par rapport la destination :
si source est avant destination, on copie de la fin vers le dbut
si source est aprs destination, on copie du dbut vers la fin
Pour tester le positionnement des deux tableaux, il suffit de les soustraire. La diffrence de deux
pointeurs de mme type donne le nombre dlments de ce type situs entre ces deux pointeurs
( &t[5] - &t[3] vaut 2, &t[3] - &t[5] vaut 2, quel que soit le type de t .
Ce qui conduit :
double *copie2(double *destination, double *source, int n) {
/* fonctionne meme si les tableaux se recouvrent */
int i;
if (destination - source < 0 ) {
for (i=0 ; i<n ; ++i) {
destination[i] = source[i];
}
}
else {
for (i=n-1 ; i>=0 ; --i) {
destination[i] = source[i];
12/13
ESIEE IGI-3008 TP Langage C no 2 (corrig) 2014-2015
}
}
return destination;
}
Attention : les fontions memcpy (copie de zones mmoires) et strcpy (copies de chanes
de caractres) de la librairie libc ne grent pas les recouvrements. Ci-dessous, un extrait de la
documentation de memcpy :
***************************************************************************
13/13