Vous êtes sur la page 1sur 37

COURS

DE

LANGAGE C

1. Prsentation 1.1 1.2 1.3 1.4 Historique Un premier programme Compilation et excution du programme Exercices

2. Les variables 2.1 2.2 2.3 2.4 2.5 Variables et types fondamentaux Oprateurs Saisir et afficher des donnes Un programme simple Exercices

3. Branchements conditionnels 3.1 3.2 3.3 3.4 3.5 if... if... else... switch... Un oprateur trs particulier : ?: Exercices

4. Les itrations 4.1 4.2 4.3 4.4 4.5 4.6 4.7 while... for... do... while... break et continue Comment faire n fois quelque chose Les piges infernaux des boucles Exercices

5. Les fonctions 5.1 Qu'est-ce qu'une fonction ? 5.2 Prototype 5.3 Dfinition 5.4 Visibilit des variables dans un programme 5.5 Quelques exemples de fonctions 5.6 Dclaration 5.7 Comprendre le passage par valeur 5.8 Comprendre la notion de valeur retourne 5.9 Erreurs courantes 5.10 Exercices

6. Porte des donnes au sein d'un programme 7. Les tableaux 7.1 7.2 7.3 7.4 Dclaration et initialisation Affectation Les dbordements Passage en argument de fonctions

ABDELKADER KERKOUR

PAGE 1

SUR

37

COURS

DE

LANGAGE C

7.5 Exercices

8. Chanes de caractres 8.1 Dfinition 8.2 Fonctions de manipulation de chanes 8.3 Exercices

9. Les pointeurs 9.1 9.2 9.3 9.4 9.5 9.6 9.7 9.8 9.9 Dfinition Dclaration Les oprateurs & et * Manipulation de pointeurs Pointeurs, tableaux et chanes littrales Pointeurs gnriques Une utilisation des pointeurs : le passage par adresse Utilisation avance Exercices

10. Passer des arguments un programme 10.1 Convertir les arguments rcuprs 10.2 Exercices

11. Les fonction d'entre/sortie 11.1 Les fonctions d'E/S

12. Types de donnes composs et type drivs 12.1 12.2 12.3 12.4 12.5 Structures Les unions Les numrations typedef Exercices

13. Les fonctions de manipulation de fichiers 13.1 13.2 13.3 13.4 Ouverture et fermeture d'un fichier Lecture criture Exercices

14. Le prprocesseur 15. Allocations dynamiques 15.1 Exercices

ABDELKADER KERKOUR

PAGE 2

SUR

37

COURS

DE

LANGAGE C

1. Prsentation Notions : langage interprt vs. langage compil, gcc, -Wall, a.out, shell. 1.1 Historique Le langage C a t cr par Brian Kernighan et Dennis Ritchie au dbut des annes 70 afin d'eviter autant que possible l'utilisation de l'assembleur dans l'criture du systme UNIX. L'avantage du C sur l'assembleur est qu'il permet aux programmes d'tre plus concis, plus simples crire et qu'ils sont facilement portables sur d'autres architectures. C est un langage : qui permet de tout faire, qui permet de crer des excutables trs rapides (compil), qui possde peu d'instructions.

1.2 Un premier programme 1 2 3 4 5 6 7 8 9 /* * Mon premier programme C. */ #include<stdio.h> int main() { printf("hello world\n"); return 0; }

Points importants noter : [1, 2, 3] Commentaire sur plusieurs lignes. [4] On indique un fichier #include pour pouvoir utiliser la fonction printf (fonction de la librairie stdio). [5] Fonction principale, point d'entre du programme. [6] Accolade ouvrante, dbute le code de la fonction. [7] La fonction printf permet d'afficher un message l'cran. Les guillemets dlimitent la chane de caractre. Le caractre \n signifie un saut de ligne suivi d'un retour chariot. Le point-virgule la fin de chaque phrase est indispensable. [8] Le programme renvoie la valeur 0 au shell appelant la fin de son excution. [9] Accolade fermante, fin de bloc de la fonction principale. 1.3 Compilation et excution du programme Pour compiler et excuter ce programme sous UNIX, il faut d'abord le copier dans un fichier se terminant par l'extension .c l'aide d'un diteur de texte (vi ou emacs). Appelons ce fichier "intro.c". On le compile sous Linux avec gcc (sous d'autre UNIX, le compilateur s'appelle le plus souvent cc) : $ gcc -o intro intro.c Cela gnre un fichier excutable qui s'appelle "intro". Pour le lancer : $ ./intro hello world

ABDELKADER KERKOUR

PAGE 3

SUR

37

COURS

DE

LANGAGE C

L'utilisation de l'option -Wall permet de s'assurer que le code est syntaxiquement impeccable (tolrance du compilateur gcc) : $ gcc -Wall -o intro intro.c 1.4 Exercices 1. "intro.c" : recopiez le programme prcdent, compilez-le et lancez le. Ensuite, modifiez le afin qu'il produise le rsultat suivant : 2. $ ./intro 3. hello 4. world 5. Modifiez la valeur retourne par la fonction main et une fois le programme compil et excut, testez la commande shell suivante : echo $?.

ABDELKADER KERKOUR

PAGE 4

SUR

37

COURS

DE

LANGAGE C

2. Les variables 2.1 Variables et types fondamentaux Notions : entiers (char, int, short, long), flottants (float, double), nombres signs et nonsigns (signed, unsigned), constantes (const), affectation, conversion, dbordement. Dclarer une variable pour pouvoir l'utiliser Une variable est un contenant qui stocke une valeur, comme un nombre. Une variable peut donc tre vue comme une boite. En C, toute variable doit tre dclare avant d'tre utilise. Un nom de variable doit commencer par une lettre ou bien par le caractre "_". La suite peut tre compose de chiffres, de lettres ou de "_". Attention, le compilateur fait la distinction entre minuscules et majuscules. Pour dclarer une variable, on crit son type suivit de son nom. Le type de la variable spcifie le format et la taille des donnes qui pourront tre stockes grce elle en mmoire. Il est possible de dclarer plusieurs variables d'un mme type sur la mme ligne en les sparant par des virgules. Exemple de dclarations de variable : int age; float prix, taux; long numero_secu; Une variable doit toujours tre dclare l'intrieur d'une fonction (exceptes les variables globales, voir le chapitre 6) et avant toute instruction. La fonction MAIN ne fait pas exception la rgle : int main() { int a, b; float x = 5; b = 0; /* une premiere instruction */ /* interdiction de declarer une variable a partir de la ! */ return 0; } Diffrents types de donnes Il y a plusieurs types de base :
CHAR,

qui correspond une variable d'un octet, sert reprsenter aussi bien des petits entiers que des caractres imprimables. Il est trs correct d'crire 'A' + 2 car 'A' est un entier. Attention, le jeu de caractres imprimables standard (caractres ASCII) est cod sur 7 bits. Il ne comprends pas les caractres accentus franais (codage sur 8 bits). SHORT INT pour stocker des petits entiers. INT pour stocker des entiers. LONG INT pour stocker des entiers plus grand. FLOAT et DOUBLE pour stocker des nombres rels.

Les entiers sont signs par dfaut mais ils peuvent tre non-sign grce la directive unsigned. Attention, sur certaines architectures, les char sont non-signs par dfaut ! Il est possible de les signer avec la directive signed.

ABDELKADER KERKOUR

PAGE 5

SUR

37

COURS

DE

LANGAGE C

La directive const permet d'empcher la modification d'une variable donne. Le contrle se fait au moment de la compilation : const int i = 70; /* i ne pourra etre modifie */ const char *p; /* pointeur sur constante */ char * const p; /* pointeur constant */ Il n'y a pas de type "chane de caractres". Pour ce faire, on utilise les tableaux (ici des tableaux de caractres, voir au chapitre 8). Taille et format des donnes sur une architecture de type i586 : Type char short int int long int unsigned unsigned unsigned unsigned float double Octets Porte 1 -128 +127 2 -32768 +32767 4 -2 147 483 648 +2 147 483 647 8 -4294967296 +4294967295 char 1 0 +255 short int 2 0 +65535 int 4 0 +4 294 967 295 long int 8 4 8

Exemple de dbordement : #include<stdio.h> main() { short a=65535, b=1, c; unsigned short ua=65535, ub=1, uc; c = a+b; printf("%d\n", c); uc = ua+ub; printf("%d\n", uc); return 0; } Affecter une valeur une variable On affecte une valeur une variable avec l'oprateur d'affectation =. La syntaxe d'une affectation est : nom = expression; . On peut initialiser une variable en lui fournissant une valeur au moment de sa dclaration. Exemples : int a, b, c = 7; a = 34; b = (a + 21) * c; a = a + 1; /* cas particulier */ Attention, avant d'utiliser le contenu d'une variable, il faut qu'elle ait t initialise, sinon, le rsultat est imprvisible : int main() { int truc; printf("%d\n", truc); } Une affectation renvoie une valeur. Cela permet de raliser des affectations combines :

ABDELKADER KERKOUR

PAGE 6

SUR

37

COURS

DE

LANGAGE C

int a, b; a = b = 10; /* l'expression b = 10 renvoie comme valeur 10 */ Conversion de valeurs et constantes littrales Si par exemple on additionne un int et un float, il y a une conversion implicite de l'int en float. Si le rsultat est stock dans un int, il y a aussi une conversion avec un risque d'altration du rsultat. Une conversion explicite est faite de la faon suivante : (nouveau_type) variable; /* la valeur stockee dans la variable est convertie */ Exemple de conversion : int a = 3, b = 6; float c; c = (float) a * (float) b; Par dfaut, un nombre utilis dans une expression, on parle de constante littrale, est de type int. Il est possible d'utiliser des constantes littrales de n'importe quel autre type en procdant de la faon suivante : 5 /* int */ 5u ou 5U /* unsigned */ 5l ou 5L /* long */ 5ul /* unsigned long */ 05 /* octal */ 0x5 /* hexadecimal */ 5.f /* float */ 5. /* double */ 2.2 Oprateurs Notions : oprateurs arithmtiques, operateurs binaires, expression, valuation, priorits. Oprateurs arithmtiques : + - * / % ++A A++ &HORBAR;-A A&HORBAR;Racourcis d'critures : variable (operateur)= (expression) Gestion des priorits : () Operateurs binaires : & | ^ ~ << >>

2.3 Saisir et afficher des donnes Notions : printf, scanf, format. La commande printf sert afficher des donnes. Sa syntaxe est printf("...",e1,e2,...,en). Il existe des caractres spciaux. Les plus utiliss sont : \n Dbut de ligne suivante \t Tabulation \\ Affiche un barre inverse Les indicateurs de formats les plus utiliss sont : %c %d caractre dcimal

ABDELKADER KERKOUR

PAGE 7

SUR

37

COURS

DE

LANGAGE C

%x et %f %.2f %s

%X hexadcimal float float avec deux chiffres aprs la virgule chane de caractres

2.4 Un programme simple Voici un autre exemple de programme simple mais qui cette fois ci utilise des variables : #include<stdio.h> int main() { int kilos = 50; /* initialisation lors de la dclaration */ int sacs, total; sacs = 300; total = sacs * kilos; printf("Il y a %d kilos dans %d sacs de haricots\n", total, sacs); } 2.5 Exercices 1. "taxe.c" : programme qui saisit un prix H.T. et affiche le prix T.T.C.. 2. "degresF.c" : programme qui convertit des degrs Celsius en degrs Farheneit : F(C) = (C*9/5)+32. 3. "add1.c" : Programme qui additionne 2 entiers saisis et qui affiche le rsultat. 4. "conv.c" : programme qui affiche en hexadcimal un nombre saisi en dcimal. Faire aussi l'inverse.

ABDELKADER KERKOUR

PAGE 8

SUR

37

COURS

DE

LANGAGE C

3. Branchements conditionnels Notions : if, else, switch, ?:. Dans la vie, on a souvent besoin de dcider du droulement des choses en fonction de certaines conditions. Par exemple : "Si il pleut, je prend mon parapluie" (ceci n'a d'ailleurs de sens que si je souhaite sortir !). De mmen en C, il est possible de dcider de n'excuter une action que si une condition particulire est remplie. Pour tester si une condition est vraie avant d'excuter une action, on dispose d'oprateurs de comparaison : == != < <= >= > et d'oprateurs logiques ! || &&. Une expression utilisant ces oprateurs renvoie 0 si la condition teste est fausse et 1 si elle est vraie. Une condition peut consister en une expression. Dans ce cas, si la valeur renvoye par l'expression gale zro, la condition est fausse. Elle est vraie pour toute autre valeur. 3.1 if... Si la condition de la structure if... est vraie, on peut excuter une instruction unique ou bien un ensemble d'instruction entre accolades. Dans ce dernier cas, attention, on ne met pas de au ; aprs l'accolade fermante ! if(condition) /* Si la condition est vraie... */ instruction; /* ...on execute une instruction unique */ if(condition) /* Si la condition est vraie... */ { /* ...on execute un bloc d'instructions */ instruction; ... instruction; } Exemples : if(n>20) printf("Vous avez droit au tarif de groupe\n"); if(x == 3){ printf("une instruction !\n"); printf("une autre instruction !\n"); } 3.2 if... else... L'instruction else permet d'excuter une instruction au cas ou la condition est fausse. C'est l'quivalent du "sinon" (exemple : "si il fait beau, je vais au zoo, sinon je vais au cinma"). if(condition) instruction; else instruction; Exemple : if(choix == 'o' || choix == 'O') printf("On va au cinema.\n");

ABDELKADER KERKOUR

PAGE 9

SUR

37

COURS

DE

LANGAGE C

else printf("On va au zoo.\n"); 3.3 switch... Remplace les if... else... les uns la suite des autres. switch(expression) { case constante : instructions; case constante : instructions; ... default : instructions; } Exemple : switch(choix) { case 't' : printf("vous voulez un triangle"); break; case 'c' : printf("vous voulez un carre"); break; case 'r' : printf("vous voulez un rectangle"); break; default : printf("erreur. recommencez !"); } L'instruction break est indispensable pour sortir du switch. Si on l'oublie, une fois le branchement excut, toutes les instructions qui suivent sont excutes. 3.4 Un oprateur trs particulier : ?: Il s'agit en ralit d'un oprateur qui teste une condition et qui renvoie la valeur de la premire expression si la condition est vraie ou de la seconde expression si c'est faux : (condition)?(instruction_si_vrai):(instruction_si_faux); Exemple : c = a<b ? 1 : 0; /* si a<b est vrai, on met 1 dans 'c' */ 3.5 Exercices 1. "vote.c" : programme qui demande l'ge de la personne. Si la personne a au moins 18 ans, alors on affiche "peut voter", sinon, on affiche "ne peut pas voter". 2. "div.c" : programme qui indique si un nombre est divisible par 2. Il existe 2 mthodes, l'une utilisant l'oprateur modulo % et l'autre les masques de bits. 3. "decal.c" : prendre un entier et oprer un dcalage de 1 bit gauche. Qu'observet-on ?

ABDELKADER KERKOUR

PAGE 10

SUR

37

COURS

DE

LANGAGE C

4. Les itrations Notions : while, for, break, continue. Principe : rpter plusieurs fois une srie d'instructions. 4.1 while... L'instruction while... permet d'excuter un bloc d'instructions tant qu'une condition est vraie. while(condition) instruction; Exemple : i=0; while(i<10){ printf("%d\n", i); i++; } 4.2 for... for(initialisation ; condition ; opration) instruction; Voici ce qui se passe : La premire fois qu'on rentre dans la boucle, on effectue gnralement une initialisation (par exemple, i=0). On teste ensuite la condition. Si elle est vrai, on effectue la ou les instructions du corps de la boucle. Sinon, on sort de la boucle (la boucle est termine). Aprs cela, on effectue une opration qui est en principe l'incrmentation d'un compteur. On re-teste la condition, etc...

Exemple : for(i=0;i<10;i++) printf("%d\n", i); Il est possible de procder plusieurs initialisations et plusieurs oprations en les sparant par des virgules. Pour procder plusieurs tests, il faut utiliser les connecteurs logiques && ou || : for(i=0,j=1 ; i<10 && j<100 ; i++, j=j*2) printf("%d %d\n", i, j); 4.3 do... while... C'est une variante de la boucle while vue prcdement. do

ABDELKADER KERKOUR

PAGE 11

SUR

37

COURS

DE

LANGAGE C

instruction; while(condition); 4.4 break et continue Les instructions break et continue permettent de sortir d'une itration. Exemple : i=0; while(1){ printf("%d\n", i); i++; if(i>10) break; } 4.5 Comment faire n fois quelque chose Chaque boucle du code suivant affiche 10 fois la mme phrase : /* en utilisant 'while' */ i=0; while(i<10){ printf("hello world !\n"); i++; } /* exactement la meme chose en utilisant 'for' */ for(i=0;i<10;i++) printf("hello world !\n"); On remarque que i est par convention d'criture toujours initialis zro. 4.6 Les piges infernaux des boucles Certaines erreurs sont trs courantes quand on dbute la programmation en C. En voici un certain nombre. Ici, i n'est pas initialis, ce qui rend le droulement de l'itration imprvisible : /* oups ! on a oublie d'initialiser 'i' */ while(i<10){ printf("hello world !\n"); i++; } Une autre erreur possible, se tromper dans la comparaison. Ici, la condition ne sera jamais vraie, donc la boucle ne sera pas excute : i=0; while(i>10){ /* on a mis '>' ou lieu de '<' */ printf("hello world !\n"); i++; }

ABDELKADER KERKOUR

PAGE 12

SUR

37

COURS

DE

LANGAGE C

Attention, l'erreur la plus frquente est sans doute d'oublier d'incrmenter i, il en rsulte une boucle infinie : i=0; while(i<10){ printf("hello world !\n"); } Attention aux ; en trop. La boucle suivante ne fait rien pendant 10 fois puis affiche la phrase hello world ! une seule fois : for(i=0;i<10;i++); printf("hello world !\n"); Par ailleurs, attention la syntaxe des boucles for. A l'intrieur du for, on spare les parties d'initialisation, de test et d'opration par des ;. Attention donc ne pas confondre avec les , : for(i=0,i<10,i++) /* ERREUR : des ',' au lieu des ';' */ printf("hello world !\n"); 4.7 Exercices 1. "simple.c" : afficher 5 fois la lettre x. 2. "boucles.c" : afficher les nombres de 1 10 puis de 20 1 de trois en trois (faire deux fois l'exercice : avec "for" et avec "while"). 3. "mult.c" : afficher les tables de multiplication de 1 9. 4. "puis1.c" : calculer 21 la puissance 3. 5. "puis2.c" : programme qui saisit deux nombres entiers non signs et calcule le premier la puissance du second. On affiche le rsultat. 6. "calc.c" : faire une mini calculette 4 oprations : 7. $ calc 8. > 3 4 + 9. 7 10. > 5 6 * 11. 30 12. > q 13. $ 14. "premiers.c" : saisir un nombre et indiquer si il est premier. 15. "bits.c" : afficher un nombre entier en binaire.

ABDELKADER KERKOUR

PAGE 13

SUR

37

COURS

DE

LANGAGE C

5. Les fonctions Notions : dclaration, prototype, arguments, valeur renvoye, return, void, passage par valeur. Jusqu' prsent, on a utilis des fonctions prdfinies (printf, scanf, etc.). Il est aussi possible d'crire ses propres fonctions. 5.1 Qu'est-ce qu'une fonction ? Un regroupement d'instructions Une fonction est un regroupement d'instruction. Imaginons une tortue qui sait seulement se dplacer tout droit et tourner droite ou gauche. On lui apprend dessiner un carr en la faisant aller tout droit, puis tourner droite, puis continuer tout droit, etc, quatre fois. Ces actions (en programmation, on parle d'instructions) peuvent tre regroupes au sein d'une procdure que l'on appelerais "dessiner_un_carr". Ainsi, quand on dirait la tortue "dessiner_un_carr", elle effectuerait les instructions de la procdure les unes la suite des autres et dessinerait un carr. Des arguments pour des rsultats diffrents Une fonction peut prendre des arguments. En reprenant la mtaphore prcdente, on pourrait apprendre la tortue dessiner un carr d'une taille spcifie. On dirait par exemple la tortue "dessiner_un_carr de 18 cm". On a l un exemple de fonction qui prend un argument. Des fonctions qui renvoient un rsultat Une fonction peut retourner une valeur. On peut trs bien imaginer une boite noire dans laquelle on peut insrer des jetons rouges par une fente et des jetons bleus par une autre. Selon le nombre de jetons insrs, la boite nous renvoie un certains nombre de jetons noirs. Nous avons l une fonction, la bote, qui prend des arguments, les jetons de couleur, et qui renvoie une valeur, des jetons noirs. 5.2 Prototype Le prototype d'une fonction permet de connaitre le nombre et le type de ses arguments. Il nous donne aussi une ide de ce qu'elle renvoie. Exemple : float taxe(float); int putchar (int); /* Fonction predefinie */ On peut souhaiter crer une fonction qui ne prend aucun argument et qui ne renvoie pas de valeur. En C, void est un type spcial qui signifie "rien". Il est utilisable la place des arguments et de la valeur renvoye. Exemple : void aff_menu(void); int getchar (void); /* Fonction predefinie */ 5.3 Dfinition

ABDELKADER KERKOUR

PAGE 14

SUR

37

COURS

DE

LANGAGE C

Une fonction est dfinie de la faon suivante : type nom(type var1, type var2, ..., type varn) { instruction; ... return valeur; } Une fonction doit se terminer par l'instruction RETURN pour se terminer. Cette instruction RETURN permet de retourner une valeur. Par exemple, la fonctions suivante prend en argument deux entiers et qui renvoie leur somme : int addition(int a, int b) { int c; c = a + b; return c; } int main() { int x = 2, y; y = addition(x,5) return 0; } L'appel la fonction
1. Dans le

ADDITION

fonctionne en plusieurs tapes :

MAIN, on fait appel la fonction ADDITION qui prend en argument la valeur de X et la valeur 5. 2. Ces valeurs sont copies dans les variables A et B dfinies dans l'en-tte de la fonction. 3. La fonction calcule et retourne la valeur de C. 4. On revient dans le MAIN. La fonction est remplace par la valeur qu'elle retourne. Cette valeur est mise dans Y.

5.4 Visibilit des variables dans un programme Les variables ne sont pas visibles en dehors de la fonction o elles ont t dfinies. Quand je suis dans une fonction, je n'ai accs qu'aux variables de cette fonction, c'est tout. La fonction main ne fait pas exeception la rgle. Pour comprendre cela, on peut prendre la mtaphore suivante. Une fonction est comme une boite noire avec des fentes pour insrer des jetons dedans. Examinons comment la boite est faite. Quand on insre des jetons, ceux-ci sont recueillis dans des petits casiers tiquets qui ont un nom. En informatique, ces casiers sont appels "variables". Ces casiers peuvent avoir n'importe quel nom, il n'y a aucune confusion possible avec les casiers en dehors de la boite. Par ailleurs, moi qui suit en dehors de la boite, je ne peut manipuler les casiers dans la boite. De la mme faon, il y a dans la boite un petit rat qui fait tourner une roue. Et bien ce petit rat ne peut manipuler que les casiers qui sont dans sa boite. Une variable peut tre dfinie en dehors de toute fonction, on dit alors d'elle qu'elle est "globale" ou "externe". Une telle variable est visible de toutes les fonctions, n'importe quel endroit du programme. 5.5 Quelques exemples de fonctions

ABDELKADER KERKOUR

PAGE 15

SUR

37

COURS

DE

LANGAGE C

Cette fonction affiche n fois une lettre. Attention, putchar prend en argument un int : void affiche_car(int c, int n) { while(n--) putchar(c); /* return implicite */ } Une fonction qui ne prend aucun argument et qui ne renvoie rien : void aff_hello(void) { printf("hello world !\n"); } 5.6 Dclaration Si une fonction est dfinie dans le code source avant la portion de code qui l'utilise, il n'est pas besoin de la dclarer. Dans le cas contraire il faut la dclarer en mettant son prototype dans l'entte du programme (c'est ce qu'on fait d'une manire particulire avec les fichiers d'include pour pouvoir utiliser des fonctions prdfinies). Exemple : void affiche_car(int, int); /* declaration */ int main() { char c = "x"; affiche_car("-", 10); /* appel de la fonction */ affiche_car((int) c, 5); return 0; } void affiche_car(int c, int n) /* definition */ { /* Fonction qui affiche n fois une lettre. */ while(n--) putchar(c); /* return implicite */ } 5.7 Comprendre le passage par valeur Une fonction ne prend en argument que des valeurs. Attention, si on passe en argument une variable, on passe en ralit une copie de sa valeur en argument. Une variable ou une expression complique passs en argument sont toujours remplacs par leur valeur : #include<stdio.h> int main() { int a = 2, b = 3; printf("%d\n", 5); printf("%d\n", a);

ABDELKADER KERKOUR

PAGE 16

SUR

37

COURS

DE

LANGAGE C

printf("(%d+%d)^2 = %d\n", a, b, (a*a+b*b+2*a*b)); return 0; } Ce programme affiche : $ ./a.out 5 2 (2+3)^2 = 25 Le passage par valeur implique qu'on ne peut changer la valeur d'une variable passe en argument. Par exemple, dans le programme suivant, la fonction ne modifie pas la valeur de a : #include<stdio.h> void mafonction(int x) { x = 0; } int main() { int a=1; mafonction(a); /* la valeur de 'a' n'est pas modifiee */ printf("%d", a); /* affiche 1 */ return 0; } 5.8 Comprendre la notion de valeur retourne L'instruction return, qui termine toujours une fonction, permet de retourner une valeur. Cela signifie que dans un programme, une fonction est remplace par la valeur qu'elle renvoie. Par exemple, dans le programme suivant, l'appel la fonction addition est tout fait autoris au sein d'une expression mathmatique ou dans une fonction : #include<stdio.h> int addition(int, int); int main() { int x=1, y=2, z; /* on affecte a 'z' la valeur retournee par la fonction */ z = addition(x+y); /* possible aussi */ printf("%d\n", addition(x+y) ); /* egalement possible ! */ z = addition(addition(x+3),5); return 0; } int addition(int a, int b) { return (a+b);

ABDELKADER KERKOUR

PAGE 17

SUR

37

COURS

DE

LANGAGE C

} 5.9 Erreurs courantes Oublier de dclarer un nom de variable dans la dfinition d'une fonction : int addition(int, int) /* oh, on a oublie les noms de variables ! */ { int c; c = a+b; return c; } Il y a aussi les ; en trop : int addition(int a, int b); { return a+b; } /* il y a un ';' en trop !!! */

Une autre erreur trs frquente est de redclarer les noms de variables : int addition(int a, int b) { int a, b; /* variables deja declarees dans l'en-tete de la fonction */ return a+b; } Si une fonction n'est pas de type void, attention bien retourner une valeur : int addition(int a, int b) { int c; c = a + b; return; /* on oublie de retourner un entier ! */ } 5.10 Exercices 1. "puis3.c" : crer une fonction qui prend deux arguments et qui renvoie le premier nombre puissance le second. 2. "puis4.c" : refaire l'exercice prcdent mais faire en sorte que la fonction cre soit rcursive. 3. "fact.c" : programme qui calcule la factorielle d'un nombre saisi. On utilisera deux mthodes diffrentes (itration et rcursion). Rappel : FACT(N) = N * (N-1) * ... * 3 * 2 * 1. 4. "rand.c" : crer une fonction qui prend en argument un entier et qui renvoie un nombre entre 0 et cet entier (vous utiliserez la fonction "rand"). Pour utiliser rand (lire ventuellement la manpage): 5. srand( time(NULL) ); 6. j=1+(int) (10.0*rand()/(RAND_MAX+1.0)); 7. "game.c" : le programme gnre un nombre au hasard entre 1 et 100 que le joueur doit deviner en un minimum de coup. Un menu propose de jouer ou de quitter. 8. "pyra.c" : programme qui demande de saisir un nombre et trace une pyramide de la faon suivante :

ABDELKADER KERKOUR

PAGE 18

SUR

37

COURS

DE

LANGAGE C

9. $ pyra 10. > 4 11. ^ 12. ^^^ 13. ^^^^^ 14. ^^^^^^^ 15. > 2 16. ^ 17. ^^^

ABDELKADER KERKOUR

PAGE 19

SUR

37

COURS

DE

LANGAGE C

6. Porte des donnes au sein d'un programme Notions : extern, static, variable locale, variable externe/globale. Une fonction ou une variable peut tre rendue confidentielle (c..d. inutilisable en dehors du fichier o elle a t dfinie) avec le mot cl static (voir aussi le chapitre sur la compilation spare). Une variable dclare static existe durant toute l'excution du programme et elle n'est pas visible en dehors de sa classe. Une telle variable est pratique pour savoir combien de fois une fonction a t appele.

ABDELKADER KERKOUR

PAGE 20

SUR

37

COURS

DE

LANGAGE C

7. Les tableaux Notions : dfinition, initialisation, affectation, indices de 0 n-1, dbordements, oprateur crochets [ ], tableaux n dimensions, conversion des noms de tableaux en pointeurs, passage de tableaux en argument pointeurs de tableaux. 7.1 Dclaration et initialisation Un tableau permet de regrouper plusieurs donnes de mme type en une entit. Les tableaux en C se dclarent avec l'oprateur [ ]. Tout comme avec les variables simples, il est possible d'initialiser un tableau lors de sa dclaration en mettant les valeurs du tableau entre accolades. Exemples de dclarations de tableaux : /* declaration d'un tableau de 10 caractres */ char tab[10]; /* declaration et initialisation d'un tableau de 3 entiers */ int a[3]={1,-1,0}; /* declaration et initialisation d'un tableau de 4 caracteres */ char msg[]={'a','b','c','\0'}; 7.2 Affectation On accde un lment d'un tableau avec son indice entre crochets. Attention, le premier lment a pour indice 0 et le dernier n-1. Le n-ime lment s'crit tab[n]. Les lments d'un tableau peuvent tre affects lors de la dclaration de celui-ci. Il n'est pas possible d'affecter directement un tableau un autre tableau. On ne peut affecter un tableau qu'lment par lment. Exemple : tab[i] = val; Attention, l'exemple suivant montre une affectation correcte et une autre incorrecte : int tab[5]; int tab2[5]={1,2,3,5,8}; /* ok */ tab = tab2; /* incorrect */ De la mme manire, il est incorrect d'utiliser les oprateurs de comparaison pour comparer deux tableaux. Affectation, comparaison... toutes ces oprations ne peuvent tre ralises qu'lment par lment. L'explication de tout cela est qu'un nom de tableau utilis dans une expression est converti en pointeur sur le premier lment de ce tableau. Ainsi, l'expression tab1 == tab2 revient comparer les adresses en mmoire o sont implants ces tableaux. Attention, une fonction ne peut jamais renvoyer un tableau. Exemple d'initialisation de tous les membres d'un tableau 0 : for(i=0;i<100;i++) t[i]=0; 7.3 Les dbordements

ABDELKADER KERKOUR

PAGE 21

SUR

37

COURS

DE

LANGAGE C

Attention, quand on affecte un lment d'un tableau, il n'y a aucun contrle fait pour savoir si on dborde ou non du tableau. Voici un exemple de dbordement : int tab[5]; tab[5] = 0; /* debordement : les indices vont de 0 a n-1 */ Une telle erreur ne sera pas repre par le compilateur et ne se manifestera qu' l'excution par un message du type Bus error ou Segmentation fault. 7.4 Passage en argument de fonctions Il est tout fait possible de passer des tableaux en argument d'une fonction. Mais attention, un tableau n'est pas une valeur et le passage en argument est trs particulier. Au niveau de la fonction tout d'abord. La dclaration de l'argument se fait en rajoutant des crochets pour indiquer que l'argument est un tableau. Exemple : void mafonction(int[]); /* le prototype */ void mafonction(int tab[]) /* la fonction */ { /* code de la fonction ... */ return; } Au niveau de l'appel de la fonction, on passe en argument juste le nom du tableau pass en argument. Exemple : int main() { int t[6]; mafonction(t); return 0; } Attention, le passage de tableaux en argument prsente des particularits. Quand on est dans la fonction, on n'a aucun moyen de savoir quelle est la taille du tableau pass en argument. Si on a besoin de savoir quelle est cette taille, il faut la passer par un deuxime argument. Un tableau est pass non par valeur mais par "adresse". Cela signifie que si le tableau est modifi dans la fonction, alors, comme par magie, le tableau pass en argument est rellement modifi ! Bon, a n'est pas vraiment de la magie, mais nous verrons cela plus tard...

7.5 Exercices 1. "notes.c" : programme qui saisit les notes de 10 lves, qui fait la moyenne des notes, puis qui affiche les notes au-dessus de la moyenne. 2. "tri.c" : programme qui saisit une liste de nombre (maximum 25), la trie puis la raffiche.

ABDELKADER KERKOUR

PAGE 22

SUR

37

COURS

DE

LANGAGE C

8. Chanes de caractres Notions : chanes de caractres, \0, sizeof, fonctions de manipulation de chanes (strlen, strcpy, strcmp, etc.). 8.1 Dfinition Une chane de caractre est tout simplement une suite de caractres stocks dans un tableau. Une chane doit imprativement se terminer par le caractre '\0'; Une chane littrale correspond une suite de caractres entre guillemets. char ch[]="hello"; /* tableau de 6 caracteres avec '\0' */ char ch2[6]="hello"; /* plus risque ! */ Attention les chanes littrales sont assimiles des constantes. Le code suivant est incorrect : char ch[]="hello"; char ch[3]='X'; /* incorrect */ 8.2 Fonctions de manipulation de chanes Afficher une chane On utilise la fonction printf avec l'indicateur de format %s et on met en argument le nom du tableau qui contient la chane : char ch[]="hello"; printf("%s world !\n", ch); Saisir une chane On utilise la fonction scanf avec l'indicateur de format %s et on met en argument le nom du tableau qui contient la chane. Attention, les tableau sont des cas particuliers et il n'est pas besoin de mettre le caractre & devant le nom : char ch[512]; scanf("%s", ch); Copier, comparer, mesurer... Une chane est un tableau, on ne peut donc raliser directement une affectation ou une comparaison. Pour copier une chane dans un tableau, on utilise la fonction strcpy : char ch[]="hello"; char ch2[512]; strcpy(ch2, ch); printf("%s\n", ch2); Pour comparer, on utilise la fonction STRCMP. Une autre fonction utile est la fonction STRLEN qui sert mesurer la longueur d'une chane (caractre nul non compris). 8.3 Exercices
1. "strlen.c", "strcpy.c" et "strcmp" : rimplmenter les fonctions C

suivantes : STRLEN, STRCPY et STRCMP. 2. "reverse.c" : programme qui saisit une chane et l'affiche l'envers.

ABDELKADER KERKOUR

PAGE 23

SUR

37

COURS

DE

LANGAGE C

9. Les pointeurs Notions : adresse mmoire, oprateurs * et &, passage d'arguments par adresse, pointeurs de pointeurs de ..., type void* (pointeurs generiques), const int *p et int * const p. 9.1 Dfinition Les pointeurs sont des variables qui ont pour valeur une adresse mmoire. On les utilise surtout lors du passage d'arguments une fonction ou lors d'allocation dynamique de mmoire. 9.2 Dclaration On dclare un pointeur d'un type donn en ajoutant le signe * avant le nom du pointeur : char *ptr; int* ptr2; /* possible aussi ! */ 9.3 Les oprateurs & et * L'oprateur & sert rcuprer l'adresse d'une variable. Exemple : int var = 4; int *ptr; /* declaration de ptr en tant que pointeur sur 'int' */ ptr = &var; /* 'ptr' pointe sur la variable 'var' */ L'oprateur * sert accder au contenu de la case mmoire pointe. Un pointeur est une adresse en mmoire, et grce l'oprateur *, on peut accder ce qu'il y a cette adresse (soit pour modifier ce qui y est stock, soit pour voir ce qu'il y a l) : int var = 5; int *p; p = &var; /* 'p' pointe sur 'var' */ printf("%d\n", *p); *p = 4; /* 'var' est modifie ! */ printf("%d\n", *p); /* on recupere la valeur */ Il est possible de pointer sur l'lment d'un tableau : int tab[5]; int *ptr; ptr = &tab[4]; /* ptr pointe sur le dernier element du tableau */ 9.4 Manipulation de pointeurs Les pointeurs peuvent tre incrments, dcrments, additionns ou soustraits. Dans ce cas, leur nouvelle valeur dpend de leur type. Incrmenter un pointeur de char ajoute 1 sa valeur. Incrmenter un pointeur de int ajoute 2 ou 4 (cela dpend de l'architecture). Tout comme avec les tableaux, il est possible d'utiliser les crochets pour accder au contenu d'un lment point. Les critures suivantes sont quivalentes : int tab[5], *p = tab; *(p+1) = n;

ABDELKADER KERKOUR

PAGE 24

SUR

37

COURS

DE

LANGAGE C

p[1] = n;

/* identique a la ligne precedente */

9.5 Pointeurs, tableaux et chanes littrales Il est possible de pointer sur un lment particulier d'un tableau : int tab[5]; int *ptr; ptr = &tab[2]; /* ptr pointe sur le 3eme element du tableau */ Un nom de tableau utilis dans une expression est converti en une adresse du dbut de ce tableau : int tab[5]; int *ptr; ptr = tab; /* equivalent a : "ptr = &tab[0]" */ Quand une chane littrale est utilise dans une expression, comme pour un tableau, elle est convertie en une adresse sur son dbut : int *ptr="abcd"; printf("%s\n", ptr); Attention, les chanes littrales sont assimiles des constantes et ne peuvent tre modifies. 9.6 Pointeurs gnriques Les pointeurs de type void * sont utiliss pour pointer sur quelque chose dont on ne connais pas le type. Les seuls oprateurs autoriss avec les pointeurs gnriques sont : l'affectation : = la conversion de type

Les autres oprateurs sont interdits. Parmi eux : l'indirection : *p l'addition : p+i la soustraction : p-i

9.7 Une utilisation des pointeurs : le passage par adresse Le passage d'arguments par adresse ne peut se faire qu'avec des pointeurs. Il permet de changer la valeur d'une variable dont l'adresse est passe en argument de la fonction : void incr(int *n) { *n = *n + 1; } int main() { int a = 3; incr(&a); printf("%d\n", a); return 0; }

ABDELKADER KERKOUR

PAGE 25

SUR

37

COURS

DE

LANGAGE C

L'appel la fonction incr fonctionne en plusieurs tapes : 1. Dans le main, on fait appel la fonction incr qui prend en argument l'adresse de la variable a (l'oprateur & retourne l'adresse d'une variable). 2. L'adresse de a est stocke dans la variable n de la fonction. 3. Grce l'oprateur *, on accde au contenu de la case pointe par n. 4. On revient dans le main. Attention, nous avons vu que le nom d'un tableau utilis seul dans une expression tait converti en un pointeur sur celui-ci. Cela signifie qu'un tableau est toujours pass par adresse une fonction. Pour reprendre la mtaphore, quand une fonction prend en argument un tableau, elle travaille toujours sur l'original. 9.8 Utilisation avance int int int int int *p; /* pointeur sur un entier */ *t[10]; /* tableau de 10 pointeurs sur des entiers */ (*pt) [5]; /* pointeur sur un tableau de 5 entiers */ *fonc(); /* fonction renvoyant un pointeur sur un entier */ (*pfonc) (); /* pointeur sur une fonction retournant un entier */

9.9 Exercices 1. "carre.c" : crer une fonction qui remplace la valeur de l'entier pass en argument par son carr. 2. "echange.c" : fonction qui change les valeurs de deux entiers passs en argument. 3. "echange2.c" : fonction qui change les valeurs de deux pointeurs passs en argument.

ABDELKADER KERKOUR

PAGE 26

SUR

37

COURS

DE

LANGAGE C

10. Passer des arguments un programme Notions : argc, argv, atoi. Le shell permet de transmettre des arguments au lancement d'un programme. Un programme C est capable de rcuprer ces arguments qui sont stocks sous forme de chanes de caractres. Un tableau habituellement nomm argv qui doit tre dclar dans la fonction main contient des pointeurs sur ces chanes. L'entier argc indique le nombre d'arguments passs au programme dans le tableau argv. Attention, le premier argument est toujours le nom du programme lui-mme (comme en shell). Exemple : int main(int argc, char *argv[]) { printf("%s\n", argv[0]); /* nom du programme lance */ } 10.1 Convertir les arguments rcuprs La principale conversion est celle d'une chane de caractres en un nombre entier. On utilise pour cela la fonction atoi : char ch[]="1234"; int n; n = atoi(ch); /* 'n' a maintenant pour valeur 1234 */ 10.2 Exercices 1. "params.c" : programme qui affiche tous les arguments passs en paramtre en indiquant leur position : 2. $ prog un pomme 1234 toto 3. 1 un 4. 2 pomme 5. 3 1234 6. 4 toto 7. "add.c" : programme qui additionne tous les nombres passs en argument et qui affiche le rsultat. 8. "basename.c" : implmenter une commande qui enlve le chemin d'accs d'un nom de fichier (cf. la manpage de basename). 9. "encadre.c" : programme qui encadre une phrase passe en argument de la faon suivante : 10. $ encadre + "Bonjour a tous" 11. ++++++++++++++++++ 12. + Bonjour a tous + 13. ++++++++++++++++++

ABDELKADER KERKOUR

PAGE 27

SUR

37

COURS

DE

LANGAGE C

11. Les fonction d'entre/sortie Notions : printf, scanf, putchar, getchar. Le langage C ne possde aucune instruction d'entre/sortie mais s'appuie sur une bibliothque de fonctions standard. 11.1 Les fonctions d'E/S E/S de caractres avec
GETCHAR

et

PUTCHAR

getchar renvoie un int, ce qui lui permet de renvoyer un caractres, sur 8 bits, en cas de succs ou -1 en cas d'chec. putchar prend en argument un int. E/S de chanes de caractres avec
GETS, FGETS

et

PUTS

gets est une fonction proscrire absolument (dangers de buffer overflow). Cette fonction lit une ligne de l'entre standard stdin et le copie dans le buffer pass en argument jusqu' ce que '\n' ou EOF soit rencontr. fgets permet de limiter le nombre de caractres lire et copier dans le tableau pass en argument. puts crit la chane passe en argument et rajoute \n la fin. E/S formates avec
PRINTF

et

SCANF

printf accepte les formats suivants : %s pour un argument de type chane de caractres %c pour un caractre %d pour un entier %e pour un rel flottant, notation scientifique %f pour un rel flottant, notation standard %g pour un rel flottant, notation la mieux adapte %o pour une conversion en octal %p pour afficher un pointeur %x pour une conversion en hexadcimal Il existe des modificateurs de format : %hd pour un <TT/short int/ %ld pour un <TT/long int/ %lf pour un <TT/double/ %.3f un flottant avec 3 chiffres aprs la virgule %20s une chane de 20 caractres %[^\n]s une chane de caractres avec les espaces Il est possible de dfinir une taille limite des donnes affiches (cf. manpage). scanf fonctionne comme printf mais effectue une lecture sur l'entre standard. scanf prend en argument les adresses des variables affecter. Elle renvoie le nombre de champs correctement lus. Contourner les piges de
SCANF

Attention, scanf est une fonction qui pose beaucoup de problmes et qu'il est fortement dconseiller d'utiliser telle quelle ! Parmis ces problmes, il y a les risques de bouclage

ABDELKADER KERKOUR

PAGE 28

SUR

37

COURS

DE

LANGAGE C

infini : quand scanf essaye de convertir une chaine vers un nombre et que la conversion choue, les caractres non numriques sont laisss dans le buffer. Pour fiabiliser la saisie avec scanf, voici un modle universel : while(1){ fgets(buf,sizemax,stdin); ret = sscanf(buf,"%c",&c); if(ret != 1) /* instructions excuter en cas d'erreur */ if((strlen(buf) == sizemax-1) && (buf[sizemax-2] != '\n')) do c=getchar(); while (c!='\n'); }

ABDELKADER KERKOUR

PAGE 29

SUR

37

COURS

DE

LANGAGE C

12. Types de donnes composs et type drivs Notions : struct, enum, union, typedef, initialisation, dclaration, utilisation, oprateurs . et ->. 12.1 Structures Crer de nouveaux types de donnes Trs souvent, nous avons manipuler des objets (au sens de "bidules" ou de "trucs") qui possdent plusieurs caractristiques. Il est possible d'associer ces caractristiques pour crer un nouveau type de variable que l'on appelle structures. Des reprsentation plus proches de la ralit : un code plus clair Admettons que nous voulions raliser une base de donne de navires qui permettra de stocker et de manipuler plusieurs de leurs caractristiques telles que leur anne de construction, leur capacit en nombre de passagers et la taille de leur quipage. Admettons que nous souhaitons une base de 2000 navires, jusqu' prsent, la seule mthode que nous connaissons pour implmenter cela est de crer autant de tableaux qu'il y a de caractristiques et de dire qu' chaque indice correspond un navire diffrent : char nom[2000][32]; unsigned short int annee_de_construction[2000]; unsigned short int nombre_de_passagers[2000]; unsigned short int taille_equipage[2000]; Cette implmentation a l'inconvnient de produire un code source clat dont la structure ne reflte pas la ralit du problme. Les caractristiques d'un navire sont clates sur plusieurs tableaux. La cratoin de structures permet heureusement une implmentation plus proche de la ralit en regroupant au sein d'une mme entit diffrentes donnes. Par exemple, la structure "bateau" : struct bateau { char nom[32]; unsigned short int annee_de_construction; unsigned short int nombre_de_passagers; unsigned short int taille_equipage; }; Dclarer une structure La dclaration d'une structure se fait par le mot rserv struct suivi d'une liste de dclaration de variables entre accolades. Attention car il y a un ; la fin des accolades. La syntaxe est : struct nom { type champ1; type champ2; ... type champn; };

ABDELKADER KERKOUR

PAGE 30

SUR

37

COURS

DE

LANGAGE C

Affectation et manipulation des structures Il est possible d'affecter une structure lors de sa dclaration : struct bateau mon_navire = {"Le Titanic", 1907, 2603, 900}; Contrairement aux tableaux, il est possible d'utiliser l'oprateur = pour affecter une structure partir d'une autre : struct bateau le_beau_bateau = {"Le Titanic", 1907, 2603, 900}; struct bateau oh_mon_bateau; oh_mon_bateau = le_beau_bateau; Pour accder aux membres de la structure, on utilise l'oprateur "." concatn au nom de la structure. Cela permet d'affecter une structure lment par lment : struct bateau mon_navire; strcpy(mon_navire.nom, "Le Titanic"); mon_navire.annee_de_construction = 1907; mon_navire.nombre_de_passagers = 2603; mon_navire.taille_equipage = 900; printf("Mon bateau s'appelle le %s\n", mon_navire.nom); Attention, on ne peut utiliser les oprateurs arithmtiques ou les oprateurs de comparaison sur des structures ! Les champs Les lments d'une structure peuvent aussi tre des portions d'entiers, ce qui permet de stocker plusieurs variables sur un seul entier (conomie de place). On parle de champs de bits pour qualifier ces donnes plus petites : struct secu_id { int sexe : 1; int annee : 11; int mois : 4; char dep; int code; }; Pointeurs de structures Il est possible d'accder aux membres d'une structure partir d'un pointeur sur celle ci : struct bateau *ptr; ptr = &mon_navire; printf("Mon bateau s'appelle le %s\n", (*ptr).nom); Mais l'ecriture prcdente est complexe. Une facilit est offerte par l'oprateur "->". Ainsi, les deux critures ci-dessous sont quivalentes : (*ptr).nom ptr->nom

ABDELKADER KERKOUR

PAGE 31

SUR

37

COURS

DE

LANGAGE C

Pour reprendre notre exemple : struct bateau *ptr; ptr = &mon_navire; printf("Mon bateau s'appelle le %s\n", ptr->nom); 12.2 Les unions Les unions permettent de stocker un choix de plusieurs choses en une mme zone mmoire. La dfinition d'une union est semblable celle d'une structure, de mme que la syntaxe d'accs. La diffrence est qu'on ne peut stocker qu'un seul lment la fois. 12.3 Les numrations Une numration permet de dfinir des constantes pour une liste de valeurs. Le compilateur assigne une valeur par dfaut chaque lment de la list en commenant par 0 et en incrmentant chaque fois. Exemple : enum statut { celibataire, marie, divorce, veuf }; Il est aussi possible d'assigner explicitement des valeurs : enum statut { celibataire = 2, marie = 3, divorce = 1, veuf =4 }; La variable s'utilise comme suit : enum statut paul; paul = celibataire; 12.4 typedef Cette directive permet d'assigner un nouveau nom un type de donnes. On l'utilise par commodit. Dans l'exemple suivant, on peut utiliser Navire la place de struct bateau : typedef struct bateau Navire; 12.5 Exercices 1. "annuaire.c" : on souhaite crer un programme d'annuaire trs simplifi qui associe un nom de personne un numro de tlphone. 1. Crer une structure PERSONNE pouvant contenir ces informations (nom et tlphone). Le nom peut contenir 32 caractres et le numro 16 caractres. 2. Crer une nouvelle structure qui va reprsenter le carnet d'adresses. Cette structure CARNET contiendra un tableau de 20 PERSONNE et un compteur indiquant le nombre de personnes dans le tableau. 3. Crer ensuite une fonction qui renvoie une structure PERSONNE en prenant en argument un nom et un tlphone. 4. Rajouter une fonction qui affiche les informations contenues dans la structure PERSONNE passe en argument. 5. Crer une fonction qui ajoute une personne dans un carnet. 6. Crer une fonction qui affiche un carnet. 7. Faire un programme qui demande de saisir 5 personnes, qui les ajoute dans un carnet puis qui affiche son contenu.

ABDELKADER KERKOUR

PAGE 32

SUR

37

COURS

DE

LANGAGE C

8. A partir des tapes prcdentes, faire programme grant un carnet d'adresse. Crer un menu qui propose d'ajouter une nouvelle personne, d'afficher le carnet ou de quitter. 9. Rajouter dans le menu une fonction qui sauvegarde les donnes dans un fichier. Ensuite, on fera en sorte que des donnes enregistres puissent tre charges au dmarrage.

ABDELKADER KERKOUR

PAGE 33

SUR

37

COURS

DE

LANGAGE C

13. Les fonctions de manipulation de fichiers Notions : open, read, write, close. 13.1 Ouverture et fermeture d'un fichier Avant de pouvoir lire ou crire dans un fichier, il faut que celui-ci soit ouvert. C'est ce que ralise la fonction open qui obit la syntaxe suivante : int open(const char *chemin, int oflag, mode_t mode); Cette fonction ouvre le fichier de nom chemin et retourne un descripteur de fichier qui permettra de l'identifier dans toutes les autres fonctions (lecture, criture, dplacement, etc.). En cas d'echec, elle retourne -1. Le paramtre oflag prcise le mode d'ouverture du fichier : O_RDONLY : ouverture en lecture seule O_WRONLY : ouverture en criture seule O_RDWR : ouverture en lecture et criture O_NDELAY : ouverture non bloquante O_APPEND : positionnement en fin de fichier avant chaque criture O_CREAT : cration du fichier si il n'existe pas O_TRUNC : ouverture avec troncature si le fichier existe O_EXCL : ouverture exclusive (retourne un code d'erreur si le fichier existe dja lors d'une cration)

Le paramtre mode dfinit les droits d'accs au fichier en cas de cration (dans les autres cas, il n'est ncessaire de positionner ce paramtre). On referme un fichier avec la fonction close : int close(int fd); Cette fonction referme le fichier dont le descripteur est fd. En cas de russite, elle retourne 0, sinon elle retourne -1. 13.2 Lecture La lecture dans un fichier se fait par la fonction read qui obit la syntaxe suivante : ssize_t read(int fd, void *buffer, size_t n); Cette fonction lit n octets dans le fichier dont le descripteur est fd et les place dans un buffer. En cas de russite, elle renvoie le nombre d'octets transfers, sinon elle retourne -1. Exemple : #include<fcntl.h> int main() { char c; int fd; fd = open("/etc/passwd", O_RDONLY); if(fd == -1){

ABDELKADER KERKOUR

PAGE 34

SUR

37

COURS

DE

LANGAGE C

fprintf(stderr,"impossible d'ouvrir le fichier\n"); exit(1); } while( read(fd, &c, 1) > 0 ) putchar(c); close(fd); return 0; } 13.3 criture L'criture dans un fichier se fait par la fonction write : ssize_t write(int fd, const void *buffer, size_t n); Cette fonction crit n octets dans le fichier dont le descripteur est fd partir d'un buffer. Cette fonction retourne le nombre d'octets crits ou -1 en cas d'erreur. Exemple : #include<fcntl.h> int main() { char buf[]="hello world !\n"; int fd; fd = open("foo", O_CREAT | O_RDWR, 0644); write(fd, buf, sizeof buf); return 0; } 13.4 Exercices 1. "nbline.c" : programme qui compte les lignes d'un fichier. 2. "wc.c" : programme qui mule la commande wc. 3. "accolade.c" : programme qui compte le nombre d'accolades fermantes et ouvrantes d'un code source en C. Il signale une erreur si les deux nombres obtenus ne sont pas identiques. 4. "comment.c" : programme qui supprime les commentaires (/* */).

ABDELKADER KERKOUR

PAGE 35

SUR

37

COURS

DE

LANGAGE C

14. Le prprocesseur Notions : prprocesseur, #define, #include, #if, #elif, #ifdef, #endif, #undef, ##. Le prprocesseur est appel au dbut d'une phase de compilation pour modifier le source. La directive #define symbole chaine remplace un symbole par une chane dans le code source du programme chaque fois qu'il apparait : #define MAX 256 Le symbole peut tre paramtr : #define max(a,b) ( (a)>(b) ? (a) : (b) ) Il est recommand de parenthser les arguments de la chane. Expliquez pourquoi l'exemple suivant produit un rsultat erron : #define carre(a) (a*a) ... carre(x+1); La directive #include <fichier> ou #include "fichier" permet d'inclure le code d'un autre fichier dans le code source de notre programme (voir le chapitre sur la compilation spare).

ABDELKADER KERKOUR

PAGE 36

SUR

37

COURS

DE

LANGAGE C

15. Allocations dynamiques Notions : malloc, calloc, realloc, free, listes chaines, tableaux dynamiques. 15.1 Exercices 1. "alloc.c" : allouez dynamiquement de la mmoire pour un tableau de 100 entiers. 2. "bigtab.c" : faire un programme qui saisit un nombre non prdtermin d'entiers, les stocke dans un tableau et les raffiche. 3. "annuaire2.c" : reprendre entirement le programme d'annuaire ralis au chapitre prcdent de faon ce que le carnet d'adresses soit une liste chane de personnes.

ABDELKADER KERKOUR

PAGE 37

SUR

37

Vous aimerez peut-être aussi