Documente Academic
Documente Profesional
Documente Cultură
- Le Langage C -
Sommaire
1. 2. 3. 4. 5. 6.
Histoire du langage C Introduction au langage lments de base (rgles dcriture, types) Les variables Oprateurs et expressions Les entres-Sorties (printf, scanf) Les structures de contrle
Sommaire
7. 8. 9. 10. 11. 12.
Classification des variables Les objets structurs (tableaux, structures) Les Fonctions Les pointeurs Les fichiers Le prprocesseur (#include, #define)
Histoire du C
Origines
C a trois anctres: les langages CPL, BCPL et B. CPL : (pour Combined Programming Language) a t conu au dbut des annes 1960 - universits de Cambridge et de Londres. Fortement typ mais trop complexe disparition dans las anne 70 BCPL : (pour Basic CPL) Cambridge en 1966 par Martin Richards. Version siplifie Ecriture dun 1er Compilateur et de divers systmes dexploitations B : Ken Thompson vers 1970 dans les laboratoires Bell Version simplifie du BCPL
Histoire du C
C: dvelopp par un collgue de Ken Thompson, Dennis Ritchie qui ajouta les tableaux, les pointeurs, les nombres virgule flottante, les structures... 1972 fut l'anne de dveloppement la plus productive et sans doute l'anne de baptme de C. En 1973, C fut suffisamment au point pour que 90% de UNIX puisse tre rcrit avec. - Une 1re dfinition du langage est apparue en 1978 avec louvrage de Ritchie et Kernighan The C programming language. - Son succs international a contribu sa normalisation: 1- ANSI (American National Standard Institute 2- ISO (International Standadization Organisation 3- CEN (Comit Europen de Normalisation) en 1993
1. Introduction au langage C
- Le langage C est un langage de bas niveaux, dans le sens o il permet la manipulation de donnes que manipulent les ordinateurs (Bit, octet, adresse) Langages volus (Pascal, Fortran, ADA) - Il est suffisamment gnral pour permettre de dvelopper des application de type scientifique ou de gestion base sur laccs aux bases de donnes (Word et Excel sont crits partir de C ou C++) - Il est un des 1ers langages offrant des possibilits de programmation modulaire: Un programme peut tre constitu de plusieurs module (module = fichier .c)
1. Introduction au langage C
- Un langage de programmation a pour finalit de communiquer avec la machine. Le langage maternel de la machine n'utilise que deux symboles (0 et 1): c'est le langage machine. Exemple: le nombre 5 est reconnu par une machine par la succession des symboles 101 (c'est la reprsentation du nombre en base 2). De mme, les oprations qu'une machine est capable d'excuter sont codes par des nombres, c'est--dire une succession de 0 et 1. Par exemple, l'instruction Machine 00011010 0001 0010 demande la machine d'effectuer l'opration 1+2. Ce langage est le seul qui soit compris par l'ordinateur, Est-il alors le seul moyen pour communiquer avec celui-ci??? Rponse : Non, utilisation du langage assembleur : add $1 $2
Il fut suivi par des langages plus sophistiqus et de plus en plus proche du langage humain
1. Introduction au langage C
- La programmation structure (Fortran, Pascal, C, Perl, Tcl ), - La programmation structure et modulaire (Ada, Modula), - La programmation fonctionnelle (Lisp) - La programmation logique (Prolog) - La programmation objet (C++, Java, VB.net, C# ).
Compilateur
1. Introduction au langage C
Quest ce quun programme C? Cest un texte crit avec un diteur de texte, respectant une certaine syntaxe et stock sous forme d'un ou plusieurs fichiers (gnralement avec l'extension .c). A l'oppos du langage assembleur, les instructions du langage C sont obligatoirement encapsules dans des fonctions et il existe une fonction privilgie appele main qui est le point de dpart de tout programme. Exemple: main() { printf(Bonjour!); } Source.c Compilation Objet.o Edition des liens Excutable
2. lments de base
2.1 les fichiers include
Exemple: # include <stdio.h> main() { printf(Bonjour!); } La directive #include inclu le fichier stdio.h au programme avant la compilation (pour pouvoir utiliser la fonction prdfinie printf. On parle alors de prproceseur
2. lments de base
2.2 les Commentaires
Exemple: # include <stdio.h> //pour pouvoir utiliser la fonction printf main() { printf(Bonjour!); } /*Ce programme imprime la chaine de caractre Bonjour! lcran*/
2. lments de base
2.3 Prsentation de quelques instructions du langage C
2. lments de base
2.3 Prsentation de quelques instructions du langage C
Exemple 2 :
2. lments de base
2.4 Les identificateurs
Les identificateurs servent dsigner les diffrents objets manipuls par le programme:Variables, fonctions, - Commence ncessairement par une lettre - une lettre majuscule est tenue pour diffrente de la lettre minuscule correspondante; - Au plus 31 caractre - Le caractre _ (appel blanc soulign ) est considr comme une lettre ; il peut donc figurer n'importe quelle place dans un identificateur: _Total2, Prix_unit
2. lments de base
2.5 Les Types dans C
Les types de base du langage C se rpartissent en 3 grande catgories en fonction de la nature des informations quils permettent de reprsenter: Nombres entiers (int) Nombres flottants (float ou double) Caractre (char): apparat en C comme un cas particulier de int.
Ils peuvent tre signs ou non signs : signed ou unsigned (unsigned int x;)
2. lments de base
a. Les Types Entiers
short int ou short (entier sur 16 bits : - 32 768 32 767) int (entier sur 32 bits : - 2 147 483 648 2 147 483 647) long int ou long (entier sur 32 bits ou 64 bits, selon les machines)
Chacun des 3 peut tre nuanc par lutilisation du qualificatif unsigned pour ne reprsenter que des nombres positifs: Exemple: unsigned short x; x peut aller de 0 65 535 pas de bit rserv pour le signe - C accepte les constantes entire en notation dcimale, hexadcimale ou octale
2. lments de base
b. Les Types Flottants
Float : cod sur 4 octets avec 1 bit de signe, 23 bits de mantisse et 8 bits d'exposant Double : cod sur 8 octets avec 1 bit de signe, 52 bits de mantisse et 11 bits d'exposant Long : cod sur 10 octets avec 1 bit de signe, 64 bits de mantisse et 15 bits d'exposant
- C accepte les constantes flottante en notation dcimale ou scientifique 3.5e+3 3500 2.43 -0.38 -.38 4. .27
2. lments de base
c. Le Type Char
En C, un caractre est un entier sign cod sur 1 octet Notation des constantes caractres : a , $ ..
Important:
a a
Il existe des caractres non imprimables, tel que le changement de ligne, de Tabulation, en voici un tableau rcapitulatif
2. lments de base
NOTATION \a \b \f \n \r \t \v \\ \' \ '' \? RESULTAT cloche ou bip (alert ou audible bell) Retour arrire (Backspace) Saut de page (Form Feed) Saut de Ligne (Line Feed) Retour chariot (Carriage Return) Tabulation horizontaLe (HorizontaL Tab) Tabutation verticale (VerticaL Tab) \ ?
2. lments de base
A propos du type boolen :
Pas de type boolen en C. Le type boolen est reprsent par un entier. Il se comporte comme la valeur boolenne vraie si cette valeur entire est non nulle. Dans un contexte qui exige une valeur boolenne (comme les tests, par exemple), un entier non nul quivaut vrai et la valeur zero quivaut faux
2. lments de base
2.6 Les Mots rservs
Les mots suivants sont rservs. Leur fonction est prvue par la syntaxe de C et ils ne peuvent pas tre utiliss dans un autre but :
auto double int struct break else long switch case enum register typedef char extern return union const float short unsigned continue for signed void default goto sizeof volatile do if static while
3. Les Variables
3.1 Declaration
Char Unsigned Auto Register Static extern Const volatile Float Double Long double Signed Short Int long identificateur = expression
Exemple:
3. Les Variables
3.2 Les variables statiques locale
Le qualificatif static, plac devant la dclaration d'une variable locale, produit une variable qui est: -Pour sa visibilit , locale -Pour sa dure de vie, statique (Permanente) Elle n'est accessible que depuis l'intrieur du bloc ou elle est dclare, mais elle est cre au dbut du programme et elle existe aussi longtemps que dure l'excution de celui-ci. Exemple : void bizarre(void) { static int cpt = 1000; printf("%d ", cpt); cpt++; } Appels conscutifs : 1000 1001 1002
4. Oprateurs et Expressions
C dispose d'un important ventail d'oprateurs originaux d'affectation et d'incrmentation.
Comme tous les langages, C dispose d'oprateurs classiques "binaires" , savoir l'addition (+), la soustraction (-), la multiplication (*) et la division (/), ainsi que d'un oprateur "unaire" correspondant l'oppos not - (comme dans -n ou -x+y). Les oprateurs binaires ne sont priori dfinis que pour deux oprandes ayant le mme type parmi: int, long int, float, double, long double et ils fournissent un rsultat de mme type que leurs oprandes.
4. Oprateurs et Expressions
4.1 Oprateurs arithmtiques en C
De plus, il existe un oprateur de "modulo" not % qui ne peut porter que sur des entiers et qui fournit le reste de la division de son premier oprande par son second. Par exemple, 11%4 vaut 3, 23%6 vaut 5 Remarque: le quotient de deux entiers fournit un entier. Ainsi 5/2 vaut 2; en revanche, le quotient de deux flottants (not, lui aussi, /) est bien un flottant (5.0/2.0 vaut bien approximativement 2.5). Priorit des oprateurs : les rgles sont "naturelles" et rejoignent celles de l'algbre traditionnelle
4. Oprateurs et Expressions
Conversions implicites :
On peut crire des expressions mixtes dans lesquelles interviennent des oprandes de types diffrents: Int n,p; float x; Conversion implicite: int float Mme mcanisme : n*x + p (int * float) + int ( float*float) + int float float + + int float float
4. Oprateurs et Expressions
Promotions numriques :
On a vu que les oprateurs numriques ne sont pas dfinis pour le types char et short :
C prvoit que toute valeur char ou short soit dabord convertie en int. short n,p; float x; Conversion systmatique: Conversion implicite : n*x + p (short * float) + short ( int * float) + int float + float float float * float + int
4. Oprateurs et Expressions
4.2 Oprateurs Relationnels
Comme tout langage, C permet de "comparer" des expressions l'aide d'oprateurs classiques de comparaison. exemple : 2*a > b +5
Par contre, C se distingue de la plupart des autres langages sur deux points: 1-le rsultat de la comparaison est, non pas une valeur "boolenne" (on dit aussi "logique") prenant l'une des deux valeurs vrai ou faux, mais un entier valant:
Ainsi, la comparaison ci-dessus devient en fait une expression de type entier. Cela signifie qu'elle pourra ventuellement intervenir dans des calculs arithmtiques;
4. Oprateurs et Expressions
4.2 Oprateurs Relationnels
2-les expressions compares pourront tre de type quelconque et seront soumises au rgles de conversion prsentes prcdemment. Liste des oprateurs: < <= > >= mme priorit Exemple: a < b == c < d == !=
(a < b) == (c < d)
Remarque: les oprateurs relationnels sont moins prioritaires que les oprateurs arithmtiques ( x+y < a+2 (x+y) < (a+2) )
4. Oprateurs et Expressions
4.3 Oprateurs Logiques
C dispose de trois oprateurs logiques classiques: et (not &&), ou (not | |) et non (not ! ). Par exemple: (a<b) && (c<d) prend la valeur 1 (vrai) si les deux expressions a<b et c<d sont toutes deux vraies ( de valeur 1), la valeur 0 (faux) dans le cas contraire. Ces oprateurs acceptent n'importe quel oprande numrique, y compris les types flottants, avec les rgles de conversion implicite dj rencontres. condition de considrer que:
4. Oprateurs et Expressions
4.3 Oprateurs Logiques Exemples: n et p sont des entiers, le compilateur accepte des expression telles que: n && p n||p if ( !n ) if (n == 0)
Remarque1: loprateur ! a une priorit suprieur celle de tous ls oprateurs arithmtiques et relationnels. La ngation de a==b serait !(a==b) et non !a==b
Remarque2: loprateur | | est moins prioritaire que &&. Tous deux sont de priorit infrieure aux oprateurs arithmtique et relationnels a<b && c<d quivaut (a<b) && (c<d)
4. Oprateurs et Expressions
4.4 Oprateur daffectation ordinaire
Nous avons dj eu l'occasion de remarquer que : i = 5 tait une expression qui ralisait une action : l'affectation de la valeur 5 i. Cet oprateur d'affectation (=) peut faire intervenir d'autres expressions comme dans : c=b + 3
4. Oprateurs et Expressions
4.5 Oprateurs dincrmentation et de dcrmentation ( ++
-- )
++ i : expression qui incrmente de 1 la valeur de i, et sa valeur est celle de i aprs incrmentation si la valeur de i est 5, l'expression : n = ++i - 5 affectera i la valeur 6 et n la valeur 1. n = i++ - 5 (n==0 , i++ vaut 5, i vaut 6)
On dit que ++ est: -un oprateur de pr incrmentation lorsqu'il est plac gauche -un oprateur de post incrmentation lorsqu'il est plac droite
4. Oprateurs et Expressions
4.5 Oprateurs dincrmentation et de dcrmentation ( ++
Priorit: 3 * i++ * j-- + k++ quivaut 3 * (i++) * (j--) + (k++)
-- )
La priorit leve de ces oprateurs unaires permet dcrire des expression assez compliques sans quil soit ncessaire demployer des ( )
4.6 Oprateurs daffectation largie: i=i+k i+=k a=a*b a*=b i=i-k i-=k a=a/b a/=b
4. Oprateurs et Expressions
4.7 Loprateur de CAST :
Exemple: n=10, p=3; (double) (n/p) (double) n/p aura comme valeur 3 aura comme valeur 3.33333
4.8 Loprateur conditionnel : (seul oprateur ternaire en C) syntaxe : condition ? Valeur si vrai : valeur si faux on utilise la valeur de lexpression la valeur de lexpression nest pas utilise
4. Oprateurs et Expressions
EXERCICES
Quelles sont les critures autoriss pour des nombres fournis en donnes? Que se passe-t-il lorsque lutilisateur ne les respecte pas?
Comment organiser les donnes lorsque lon mlange les types numriques et les types caractres?
c : char: caractre affich ''en clair" (convient aussi short ou int compte tenu des conversions systmatiques)
d : int (convient aussi char, compte tenu des conversions systmatiques) u : unsigned int (convient aussi unsigned char ou unsigned short, compte tenu des conversions systmatiques)
f : double ou float crit en notation "dcimale" avec six chiffres aprs le point e : double ou float crit en notation 'exponentielle'' (mantisse entre 1 et 9) avec six chiffres aprs le point dcimal, sous la forme x.xxxxxxe+yyy ou x.xxxxxxe-yyy pour les nombres positifs et -x.xxxxxxe+yyy ou -x.xxxxxxe-yyy pour les nombres ngatifs
s : chane de caractres dont on fournit l'adresse (notion qui sera tudie ultrieurement)
printf("%e" , x );
c : char d : int u : unsigned int hd : short int hu : unsigned short ld : long lu : unsigned long
f ou e : float crit en notation "dcimale" ou 'exponentielle'' Lf ou le : double crit en notation "dcimale" ou 'exponentielle'' s : chane de caractres dont on fournit l'adresse (notion qui sera tudie ultrieurement)
b. Premires notion de tampon et de sparateurs : Lorsque scanf attend des donnes, linformation frappe au clavier est range temporairement dans lemplacement mmoire nomm tampon . Ce dernier est explor caractre par caractre au fur et mesure des besoins. Certains caractres jouent un rle particulier: les sparateurs (lespace et la fin de ligne \n)
Les codes de format correspondant un nombre entranent lavancement du pointeur jusquau 1er caractre diffrent dun sparateur, puis scanf prend en compte tous les caractres suivants jusqu la rencontre dun sparateur.
Quand au code de format %c, il entrane la prise en compte du caractre dsign par le pointeur (mme un sparateur) et il est avanc sur le caractre suivant.
n indfini p inchang
Un arrt prmatur de scanf a lieu dans le cas o scanf nest pas en mesur de fabriquer une valeur adquate !!
excution
Instructions de contrle
Le langage C dispose d'instructions structures permettant de raliser : - des choix : instructions if...else et switch, - des boucles : instructions do...while, while et for.
La notion de branchement est aussi disponible en langage C - Instructions de branchement inconditionnel : goto, break et continue, - Instruction de choix multiple que constitue switch
Instructions de contrle
if (expression) instruction_1
Exemples if (a<=b) printf("min(a,b) est %f, a) ; else printf ("min(a,b) est %f", b) ; Ambigut ? if (a<=b) if (b<=c)printf ("ordonn") ; else printf ("non ordonn") ;
Instructions de contrle
switch (expression) { case constante_1 : [ suite_d'instructions_1 ] case constante_2 : [ suite_d'instructions_2 ] .............. case constante_n : [ suite_d'instructions_n ] [ default : suite_d'instructions ] }
Exemples int n ; nul printf ("donnez un entier : ") ; scanf ("%d", &n) ; switch (n) { case 0 : printf ("nul\n") ; _______ case 1 : printf ("un\n") ; case 2 : printf ("deux\n") ; }
Instructions de contrle
main() { Int n ; printf ("donnez un entier : ") ; scanf ("%d", &n) ; switch (n) { case 0 : printf("nul\n") ; break ; Case 1 : case 2 : printf("petit\n") ; Case 3 : Case 4 : case 5 : printf("moyen\n") ; break ; default : printf("grand\n") ; } }
donnez un entier : 1 petit moyen ___________ donnez un entier : 4 moyen ___________ donnez un entier : 25 grand
Instructions de contrle
do instruction while (expression) ;
Exemples do { printf ("donnez un nb > 0 : ) ; scanf ("%d", &n) ; printf("vous avez fourni %d", n); } while (n<= 0 ) Peut s'crire :
do { printf ("donnez un nb > 0 : ) ; scanf ("%d", &n) ; } while ( printf("vous avez fourni %d", n), n<= 0 )
ou encore :
do printf ("donnez un nb >0 : ") ; while ( scanf("%d", &n), printf ("vous avez fourni %d", n), n <= 0 ) ;
Instructions de contrle
while (expression) Instruction
while (som<100) donnez un nombre : 12 {printf ("donnez un nombre : ") ; donnez un nombre : 60 scanf ("%d", &n) ; somme obtenue : 112 som += n ; } printf ("somme obtenue : %d", som) ; }
Instructions de contrle
for ( [ expression_1 ] ; [ expression_2 ] ; [ expression_3 ] ) instruction
Exemples int i ; for ( i=1 ; i<=5 ; i++ ) { printf ("bonjour ") ; printf ("%d fois\n", i) ; } Cette instruction est quivalente : I = 1 ; for ( ; i<=5 ; i++ ) { printf ("bonjour ") ; printf ("%d fois\n", i) ; } ----------------i = 1 ; for ( ; i<=5 ; ) { printf ("bonjour ") ; printf ("%d fois\n", i) ; I++ ; }
Exercices
Exercices
Correction
Exercice
Quelles seront les valeurs lues dans les variables n et p (de type int), par l'instruction suivante ? scanf ("%4d %2d", &n, &p) ; lorsqu'on lui fournit les donnes suivantes (le symbole ^ reprsente un espace et le symbole @ reprsente une fin de ligne, c'est-dire une "validation") ? a) 12^45@ b) 123456@ c) 123456^7@ d) 1^458@ e) ^^^4567^^8912@
Programmation modulaire
On dcoupe les programmes en plusieurs parties : programme difficile lire pas de squence rptitives criture modulaire, programmation structure les modules sont dcomposs eux-mmes en sous-modules partage d'outils communs compilation spare. En gnral, on utilise deux types de module : Les fonctions prennent des arguments et ramnent un rsultat scalaire simple comme en mathmatique. Les procdures (sous-programmes) prennent des arguments, font une action et modifient des valeurs de variables.
Fonctions en C
Les fonctions en C :
faire des actions ne rien renvoyer fournir des rsultats complexes (structures) modifier la valeur des arguments et la valeur des variables dites "globales".
Le langage C autorise la compilation spare (programme source en plusieurs parties), ce qui facilite la cration de grand programme.
/* dclaration la fonction */
printf("Entrez un nombre entier :"); /* Lire la valeur du nombre suivant */ scanf("%d", &n); printf("Entrez l'exposant (positif) :"); /* lire l'exposant */ scanf("%d", &exp); r = puissance(exp+ 1, (long int) n); /* calcul de la puissance */ printf("le resultatest %ld\n",r); } /* Dfinition de la fonction puissance */ long int puissance(int exposant, long int base) { long int resultat; int i; resultat= base;
for(i = 0; i < exposant -1; i++) resultat= resultat* base; return resultat; }
Exemple de fonction
return
renvoie la valeur rsultat si l'argument de return n'est pas du mme type que celui dclar dans l'entte le compilateur convertit. fonction sans valeur de retour : void sans_de_retour(int n) on peut utiliser return sans argument. fonction sans paramtre: int sans_de_param(void)
La dclaration n'est ncessaire que lorsque la fonction appelante se trouve plus haut que l'appele. La dclaration reste fortement conseille. Dclaration partielle possible (interdit en C++): long int puissance(); viter. Sans dclaration, une fonction renvoie int et ces arguments sont quelconques. Les noms d'arguments sont admis dans le prototype (la dclaration). long int puissance(int exposant, long int base); on place la dclaration soit dans la fonction appelante avant la dfinition de la premire fonction.
La dclaration permet au compilateur : si la dfinition se situe dans le mme fichier source, le compilateur vrifie si les types d'argument formel est le mme que celui du prototype. Le contrle sur le nombre et le type d'argument mentionne dans les appels. La mise en place de conversion. Si le compilateur ne connat pas le type des arguments, il applique la conversion automatique. Char et short --> int et float --> double Seule une fonction dclare peut recevoir un float, short ou un char
Les fichiers .H sont inclus au source par la directive #include ils contiennent, entre autre, des dclarations.
Contrle sur le nombre et le type d'argument mentionn dans les appels. Mise en place des conversions adquates.
Les arguments sont transmis par valeur Ceci implique qu'une modification de la valeur d'un argument dans la fonction appel n'influe pas sur la fonction appelante. Exemple : void appelante(void) { int i = 10; change(i); printf("valeur de i =%d=", i); } void change(int i) { I = 20; // i vaut 20 }
i vaut 10 i vaut 10
i vaut 20
Les arguments
Pour remdier au passage par valeur :
passer l'adresse de l'argument : scanf("%d",&i); utiliser des variables globales.
Remarque :
l'ordre d'valuation d'un argument n'est pas garanti f(i++, i); l'argument effectif peut tre une expression grce au passage par valeur. Si le passage tait par adresse ou rfrence, on ne pourrait transmettre qu'une "lvalue"
La porte :
Les variables globales ne sont connues que dans la partie du programme source suivant leur dclaration. On nomme cet espace la porte de la variable
la classe d'allocation :
les variables globales font parties de la classe d'allocation statique. La place mmoire est attribue au dbut de l'excution du programme. Elles sont initialises zro sauf indication contraire.
chaque appel il y a allocation de mmoire pour les variables locales et les arguments On ne commence dpiler que lorsqu'on excute un return, et on libre la mmoire
Exerices
Exercice 1. crire une fonction qui calcule les racines d'une quation de second degr. On suppose Qu'elles sont relles. Exercice 2. crire une fonction rcursive calculant la valeur de la "fonction d'Ackermann" A dfinie pour m>0 et n>0 par : A(m,n) = A(m-1,A(m,n-1)) pour m>0 et n>0 A(0,n) = n+1 pour n>0 A(m,0) = A(m-1,1) pour m>0.
Dfinitions
Les tableaux : c'est une collection d'objets identiques (de mme type) dsigns par un identificateur unique (le pointeur sur le tableau). Int tab[2][5] Les pointeurs : Il s'agit d'une variable contenant l'adresse d'un autre objet, il est caractris par le type de l'objet sur lequel il pointe (variable, fonction, premier lment d'un tableau) Int * point;
Exemple d'utilisation du tableau : stocker les notes d'une classe de 20 lves. Float notes[20] les indices commencent toujours 0 et finissent donc au nombre d'lments moins 1. Dans notre exemple de 0 19. Attention il n'existe aucun contrle sur les bornes !!! notes[100] = 0; est valide mais o avons-nous crit ??? Utilisation d'un tableau notes[2] est une lvalue : possibilt d'affectation : notes[2] = 18; Affectation globale de tableau impossible : t1 = t2 non valide incrmentation : notes[2]++; --notes[16];
Les indices
Les indices peuvent tre le rsultat d'une expression arithmtique renvoyant un entier positif ou ngatif. notes[(2* n) + 1] De mme on peut utiliser des chars comme indice. C1 et C2 sont de type char : notes[c1 + 3], notes[c1] On peut utiliser des constantes comme indices mais pas les constantes symboliques (const) #define NB 5 Int tab[NB]; valide int tab2[NB+2]; valide Const int nb= 50; Int tab[nb]; non valide
Gnralement : Comme les scalaires, les tableaux de classe statique (globale + locale statique) sont initialiss zro. Les tableaux de classe automatique (locale non statique) ne sont pas initialiss. les tableaux une dimension : Int t[5] = { 1, 2, 3, 4, 5} on peut ne mentionner que les premiers lments : int t[5] = { 1, 2, 3} on peut omettre la dimension : int t[] = { 1, 2, 3, 4, 5} les tableaux plusieurs dimensions : int t[3][4] = { { 1, 2, 3, 4}, { 11,12, 13, 14}, { 21,22, 23, 24} } int t[3][4] = { 1, 2, 3, 4, 11,12, 13, 14, 21,22, 23, 24}
Les pointeurs
Les pointeurs : Il s'agit d'une variable contenant l'adresse d'un autre objet, le pointeur est aussi dtermin par le type sur lequel il pointe (variable, fonction, premier lment d'un tableau) Int * point; *point reprsente le contenu de l'entier point par point.
Rciproquement, int entier; &entier est l'adresse mmoire (le pointeur) de la variable entier.
Utilisation
Exemples
int n = 10, p = 10, *adr1, *adr2 ; adr1 = &n; adr2 = &p; *adr1 = *adr2 + 2; ==> ???? *adr1 += 3 ===> ??? (*adr2)++ ===> ????
Remarque
int n, *adr1; adr1 et *adr1 sont des lvalue, c'est dire que adr1++; ou *adr1= 3; sont valides. Au contraire &adr1 et &n ne sont pas des lvalue, car ces adresses sont ncessairement fixes puisque calcules par le compilateur; elles ne peuvent pas tre modifies. (&adr1)++; ou &n= 3; seront rejetes par le compilateur. Rservation mmoire : int *adr1; rserve de la mmoire pour le pointeur mais pas pour un entier.
Soustraction de pointeur entre pointeur de mme type; renvoie le nombre d'lments du type entre les deux pointeurs
Affectation de pointeur
On ne peut pas affecter 2 pointeurs de type diffrent. On peut affecter 2 pointeurs du mme type uniquement.
float *pf1, *pf2; pf1 = pf2;
Le pointeur NULL
Le pointeur nul est un pointeur qui ne pointe sur rien. On peut donc affecter lentier 0 nimporte quel pointeur. Il est conseill dutiliser la constante NULL (dfinie dans stdio.h). p = NULL On peut comparer un pointeur NULL. if (p = = 0) p = = NULL;
Comme nimporte quelle variable, un pointeur de la classe dallocation statique (par exemple les variables globales) est initialis 0 / NULL mais cela est dpendant de limplmentation. Par prudence, il vaut mieux initialiser le pointeur.
int *Pa = NULL;
Pointeurs constants
pc est non modifiable. const int *pc est un pointeur sur un entier constant, *pc est non modifiable.
Attention ! t n'est pas une lvalue : int t[10]; t = 2; impossible int i, t[10]; for( i = 0; i < 10; i++) *(t + i) = 1; int *p, t[10]; for( p = t; p < t+10; p++) *p = 1;
Exercices
Exercice . crire, de deux faons diffrentes, un programme qui lit 10 nombres entiers dans un tableau avant d'en rechercher le plus grand et le plus petit : a) en utilisant uniquement le "formalisme tableau", b) en utilisant le "formalisme pointeur", chaque fois que cela est possible.
Exercice 2. crire une fonction permettant de trier par ordre croissant les valeurs entires d'un tableau de taille quelconque (transmise en argument). Le tri pourra se faire par rarrangement des valeurs au sein du tableau lui-mme.
#include <stdio.h> #define NVAL 10 /* nombre de valeurs du tableau */ main() { int i, min, max ; int t[NVAL] ; printf ("donnez %d valeurs\n", NVAL) ; for (i=0 ; i<NVAL ; i++) scanf ("%d", &t[i]) ; max = min = t[0] ; for (i=1 ; i<NVAL ; i++) { if (t[i] > max) max = t[i] ; /* ou max = t[i]>max ? t[i] : max */ if (t[i] < min) min = t[i] ; /* ou min = t[i]<min ? t[i] : min */ } printf ("valeur max : %d\n", max) ; printf ("valeur min : %d\n", min) ; }
Correction
#include <stdio.h> #define NVAL 10 /* nombre de valeurs du tableau */ main() { int i, min, max ; int t[NVAL] ; printf ("donnez %d valeurs\n", NVAL) ; for (i=0 ; i<NVAL ; i++) scanf ("%d", t+i) ; /* et non *(t+i) !! */ max = min = *t ; for (i=1 ; i<NVAL ; i++) { if (*(t+i) > max) max = *(t+i) ; if (*(t+i) < min) min = *(t+i) ; } printf ("valeur max : %d\n", max) ; printf ("valeur min : %d\n", min) ; }
Dfinition et convention
Il n'y a pas de type chane ou string en C, on recourt un tableau de char. Il existe une convention de reprsentation des chanes.
Pour le compilateur les chanes constantes sont notes entre double quotes"bonjour" Pour les fonctions de traitement des chanes qui indiquent la fin de la chane par le caractre NUL '\0' : char chaine[10]; "bonjour" ==> bonjour\0
chaine[0] = 'b' chaine[1] = 'o' chaine[2] = 'n' chaine[3] = 'j' chaine[4] = 'o'
chaine[5] = 'u' chaine[6] = 'r' chaine[7] = '\0' chaine[8] = indfini chaine[9] = indfini
Rappel : 'a' != "a" car "a" vaut 'a' suivi de '\0' ou 65 suivi de 0 en ASCII.
Dfinition et convention
Vous n'avez pas le droit d'crire : char ch[20]; ch= "bonjour"; Vous pouvez utiliser : char ch[20] = "bonjour"; char ch[20] = {'b','o','n','j','o','u','r','\0'}; les 12 derniers caractres sont initialiss 0 ou non en fonction de la classe d'allocation. char ch2[] = "bonjour"; /* ch2 fait 8 caractres exactement */ Vous pouvez aussi utiliser : char *jour[7] = {"lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi", "dimanche"} jour est pointeur sur un tableau de chanes .
Initialisation
Attention au constante chane : char *ch= "bonjour"; est valide ; le compilateur remplace "bonjour" par l'adresse de l'emplacement o il a rang la chane. Mais vous ne pouvez pas modifier "bonjour" par: char *ch; ch= "bonjour"; *(ch+ 2) = 'X'; /* accept mais comportement indtermin */ On peut se prmunir contre cette faute par la dclaration char const*ch= "bonjour"; Par contre, si la dclaration est char *ch[20] = "bonjour"; La modification fonctionne
Plusieurs possibilits :
le format %s avec les fonctions scanf et printf. les fonctions spcifiques : lecture gets et criture puts d'une seule chane la fois. #include<stdio.h> main() {char nom[20], prenom[20], ville[20]; printf("quelle est votre ville :"); gets(ville); printf("donnez votre nom et prenom:\n"); scanf("%s %s",nom, prenom); printf(" %s %s habite %s \n", prenom, nom, ville); }
Scanf avec %s :
Le dlimiteur espace empche de saisir des chanes comportant des espaces. Le dlimiteur n'est pas consomm.
Gets :
Lit une chane et une seule. Le seul dlimiteur est la fin de ligne (\n). Le dlimiteur (\n ou EOF) est consomm mais remplac par \0 et est rajout la fin. Renvoie NULL si erreur ou le pointeur sur la chane saisie.
Puts:
Ajoute un saut de ligne la fin de chaque chane
Matrise du buffer, donc nous pouvons appeler sscanf sans nous soucier de la position du pointeur dans le buffer
#defineLG_LIGNE 41 char ligne[LG_LIGNE], mot [31],c; Int n, n_val_ok; Float x; while(1) {printf("Donnez un entier, un flottant et une chane de caractre:\n"); fgets(ligne, LG_LIGNE, stdin); n_val_ok= sscanf(ligne, "%d %f %s", &n, &x, mot); if(n_val_ok== 3) break; } printf('"Merci pour l\'entier %d le flottant %e la chaine%s \n", n, x, mot);
Concatnation de chanes
strcat: concatne 2 chanes strcat( but, source) char ch1[50] = "Comment"; char *ch2 = "cava"; strcat(ch1,ch2); ch1 ==> "Commentcava" strncat: concatne 2 chanes avec contrle de la longueur strcat( but, source, lgmax) char ch1[50] = "Comment"; char *ch2 = "cava"; strcat(ch1, ch2, 2); ch1 ==> "Commentca"
Comparaison de chanes
strcmp: compare 2 chanes, ordre des codes de caractre (ASCII). strcmp( ch1, ch1)
positif si ch1 > ch2 nul si ch1 = ch2 ngatif si ch1 < ch2
Copie de chanes
strcpy: copy source dans dest. strcpy( dest, source) strncpy: de mme que strcpy avec longeur max. strncpy( dest, source, lgmax) char ch1[20] = "123456789" char ch2[20] = "coucou" strncpy(ch1, ch2, 3); ==> ch1 = "cou456789" strncpy(ch1, ch2, strlen(ch2) + 1); ==> ch1 = "coucou"
On peut rechercher l'occurrence d'un caractre d'une sous chane, les fonctions renvoient un pointeur sur l'endroit recherch ou NULL dans le cas contraire. strchr( chane, caractre) en partant du dbut strrchr( chane, caractre) en partant de la fin strstr( chane, sous-chane) en partant du dbut
Conversion
Les fonctions de conversion ignorent les espaces de dbut de chane et utilisent les caractres suivants pour fabriquer une valeur numrique. Un caractre illgal arrte le traitement. Si aucun caractre n'est exploitable, renvoie nul. atoi( chane) int atol( chane) long atof( chane) double
Exercices
Exercice 1. crire un programme dterminant le nombre de lettres e (minuscules) prsentes dans un texte de moins d'une ligne (suppose ne pas dpasser 132 caractres) fourni au clavier.
Exercice 2. crire un programme qui supprime toutes les lettres e (minuscules) d'un texte de moins d'une ligne (suppose ne pas dpasser 132 caractres) fourni au clavier. Le texte ainsi modifi sera cr, en mmoire, la place de l'ancien.
Correction
#include <stdio.h> #include <string.h> #define CAR 'e' #define LGMAX 132 main() { char texte[LGMAX+1] ; char * adr ; int ncar ; printf ("donnez un texte termin par return\n") ; gets (texte) ; Ncar = 0 ; adr = texte ; while ( adr=strchr(adr,CAR) ) { ncar++ ; adr++ ;} printf ("votre texte comporte %d fois le caractre %c", ncar, CAR) ;
}
Correction
#include <stdio.h> #include <string.h> #define CAR 'e' #define LGMAX 132 main() { char texte[LGMAX+1] ; char * adr ; printf ("donnez un texte termin par return\n") ; gets (texte) ; adr = texte ; while ( adr=strchr(adr,CAR) ) strcpy (adr, adr+1) ; printf ("voici votre texte priv des caractres %c\n", CAR) ; puts (texte) ; }
Les structures
Dfinition
La structure permet de regrouper diffrentes variables en une seule.
Exemple : Struct produit { int id; int qte; Float prix; }; Struct produit oeuf; "produit" est un modle de structure, il n'y a pas de rservation de place mmoire. "id", "qte" et "prix" sont nomms champs. "oeuf" est une variable de type "produit", la place mmoire est rserve lors de la dclaration de "oeuf".
Accs au champs
L'affectation
L'affectation entre 2 structures de mme modle : Struct produit oeuf, tomate; tomate = oeuf; ce qui quivaut : tomate.prix = oeuf.prix; tomate.qte= oeuf.qte; tomate.id = oeuf.id; Remarque: l'affectation globale entre 2 tableaux est impossible, mais on peut la raliser en crant une structures contenant un tableau
Les structures suivent la rgle des classes d'allocation. Il est possible d'initialiser explicitement avec des expressions constantes et non des expressions quelconques, comme les tableaux.
Struct produit tomate = { 2, 2000, 2.15 };
Typedef
Typedef permet de dfinir des types synonymes typedef int entier;
entier i, j, k; typedef int * ptent; Ptent pti, ptj, ptk; Struct produit {int id; int qte; float prix; }; typedef struct produit t_produit; t_produit oeuf, tomate
Struct eleve {int id; char nom[20]; int note[10]; } Ali; Ali.note[4] = note_geo; Ali.nom est l'adresse du tableau "nom". strcpy(Ali.nom, "Ali"); Ali.nom[2] est la lettre 'i' Struct eleve Myrieme= {10, "Myrieme" , {0, 1, 2, 3, 4, 5}};
Struct point {char nom[10]; int x; int y}; Struct point courbe[50]; "point" est le modle de structure, courbe est tableau de 50 lments de type "point" courbe[3].x est valide, courbe.x[3] n'a pas de sens. courbe[3] est une structure "point" le 4 me point de la courbe. courbe[3].nom[2] pour accder au 3 me caractre de nom du 4 me point de la courbe. courbe est l'adresse du dbut du tableau. Initialisation : Struct point courbe2[25] = {{'a', 1, 2}, {'b', 1, 2}, , {'d', 1, 2}};
Struct date {int jour; int mois; int annee}; Struct person {char nom[10]; char prenom[10]; Struct date date_embauche; Struct date date_poste; } Mohammed; Mohammed.date_embauche.annee= 1985; Mohammed.date_poste.annee= Mohammed.date_embauche.annee;
Si le modle est dclar : A l'intrieur d'une fonction, la porte est limite la fonction. A l'extrieur d'une fonction, la porte est limite tout le fichier source mais pas dans les autres fichiers sources car la directive "extern" ne peut s'appliquer (seulement aux variables). Par contre on peut utiliser un fichier ".h" inclus par la directive include
On peut transmettre une structure par valeur (contrairement au tableau) et on travaille dans l'appele sur une copie. Pour changer les valeurs de la structure, on envoie un pointeur : f(&date_embauche) dfinition de l'appele : Void f(struct date *d); Dans l'appele on accde au champs par :(*d).annee= 1986 ou on peut aussi utiliser :d->annee= 1986 Structure en valeur de retour Struct date f(.)
Les unions
Les unions permettent de stocker dans un espace mmoire des variables de plusieurs types diffrents. union prime {int fixe; double taux; } sac, *pt_sac; La syntaxe est la mme que pour une structure : sac.val, pt_sac->taux struct salaire {char nom[10]; union prime prime_mensuelle; } employe[50]; employe[5]. prime_mensuelle.fixe, employe[6]. prime_mensuelle.taux L'initialisation explicite se fait par le premier type ici int
Exercices
Exercice 1. Dfinir une structure date contenant trois champs de type entier pour identifier le jours, le mois et lanne. Initialiser une variable de type structure date. Afficher cette structure : laide de la variable. laide dun pointeur. Exercice 2. Dfinir un tableau de structures date. Dfinir un pointeur sur ce tableau. Initialiser ce tableau. Imprimer le contenu du tableau
Correction
#include <stdio.h> struct date /* declaration du modele de structure date */ { int jour; int mois; int annee; }; main () { struct date dat, *ptdate = &dat; /* saisie de la date */ printf (" Entrez une date ( jj mm aaaa ) :"); scanf ("%d %d %d", &dat.jour, &dat.mois, &dat.annee); /* affichage de la date */ printf (" La date est : %d\t%d\t%d\n", dat.jour, dat.mois, dat.annee); /* affichage de la date avec le pointeur */ printf (" La date est : %d\t%d\t%d\n", ptdate->jour, ptdate->mois, ptdate->annee); }
Correction
#include <stdio.h> struct date{ int jour, mois, annee;}; main() { struct date dat[5], *ptdate=dat; int i = 0; printf ("Entrez 5 dates au format ( jj mm aaaa )\n"); while (i < 5){ scanf ("%d %d %d", &dat[i].jour, &dat[i].mois, &dat[i].annee); i++; } for (i = 0; i < 5; i++, ptdate++) { /* sans pointeur */ printf (" Date numero %d : %d\t%d\t%d\n", i + 1, dat[i].jour, dat[i].mois, dat[i].annee); /* avec pointeur */ printf (" Date numero %d : %d\t%d\t%d\n", i + 1, ptdate->jour,ptdate->mois, ptdate->annee); } }