• Aucun résultat trouvé

Introduction `a la programmation en C

N/A
N/A
Protected

Academic year: 2022

Partager "Introduction `a la programmation en C"

Copied!
35
0
0

Texte intégral

(1)

Introduction ` a la programmation en C

Cours 1 Premiers pas en C

12 f´ evrier 2014

(2)

Avant de commencer

page web du cours :

http://monge.univ-mlv.fr/~pivoteau/INTROC/index.html + Moodle

B transparents de cours, sujets de TD

B sujets de TP, programmes, quelques corrections B bibliographie et lien utiles

3 s´ eances de cours 5 s´ eances de TD 6 s´ eances de TP

contrˆ ole des connaissances : B contrˆ ole continu : TPs B exam

B TP not´ e/micro-projet ?

(3)

But du cours

Intro ` a la programmation en C

B comparaison avec un autre langage imp´ eratif (Python) Familiarisation avec la syntaxe

Questions autour de la gestion de la m´ emoire Pr´ eparation au cours de 2e ann´ ee

B Tout ce qui est vu en TD (fini ou non) doit ˆ etre su.

B Tous les TPs sont ` a finir et ` a rendre.

(4)

Syntaxe et ´ el´ ements du

langage C

(5)

Pr´ esentation du langage C

Kernighan et Ritchie 1972

Langage tr` es r´ epandu, imp´ eratif, non objet, utilis´ e pour la programmation syst` eme

Langage compil´ e, compilateur gcc Peu de librairies

Langage bas-niveau, proche du syst` eme, gestion manuelle de la m´ emoire, pas de garbage collector

Langage typ´ e (` a la diff´ erence de Python)

Syntaxe similaire en Java

(6)

Structure d’un programme C

Programme helloWorld.c :

# i n c l u d e < s t d i o . h >

/* f o n c t i o n p r i n c i p a l e */

int m a i n (int argc , c h a r * a r g v [ ] ) {

p r i n t f (" H e l l o w o r l d \ n "); // a f f i c h a g e r e t u r n 0;

}

Remarques :

points-virgules, blocs fonction main

pas de top-level

types

(7)

Syntaxe : variables et types

Toutes les variables ont un type !

t y p e n a m e ; // d ´e c l a r a t i o n n a m e = v a l u e ; // a f f e c t a t i o n

t y p e n a m e = v a l u e ; // i n i t i a l i s a t i o n

Types primitifs en C :

int entier (relatif) court 2 octets

long entier long 4 octets

float flottant court 4 octets double flottant long 8 octets

char caract` ere 1 octet

unsigned modificateur

pas de bool´ eens : 0 est faux et tout le reste est vrai !

(8)

Variables et types : exemples

int i = 0;

i = 3;

i ++; // i n c r ´e m e n t a t i o n ++ i ; // i n c r ´e m e n t a t i o n d o u b l e z = i * 1 . 0 ;

f l o a t g , h ; // d ´e c l a r a t i o n s m u l t i p l e s g = i /3; // d i v i s i o n e n t i `e r e

h = z /3; // d i v i s i o n r ´e e l l e c h a r c =’ s ’;

c - -; // les c a r a c t `e r e s s o n t des e n t i e r s c + = 5 ;

u n s i g n e d int x = -1; // et p o u r t a n t , c ’ est p o s i t i f ...

(9)

Syntaxe : op´ erateurs et priorit´ es

Cat´ egorie d’op´ erateurs Op´ erateurs Assoc.

( ) [ ] . −> G→D unaires − ++ −− ! ˜ ∗ & sizeof (type) D→G

mult., div., mod. * / % G→D

addition, soustraction + − G→D

binaires de d´ ecalage << >> G→D

relationnels < <= > >= G→D

de comparaison == ! = G→D

et binaire & G→D

ou exclusif binaire ˆ G→D

ou binaire | G→D

et logique && G→D

ou logique || G→D

conditionnel ?: D→G

affectation = + = − = ∗ = etc... D→G

virgule , G→D

(10)

Affichage (format)

#include <stdio.h>

int i = 0;

p r i n t f (" % d \ n ", i );

i = 3;

p r i n t f (" % d \ n ", i );

i ++;

p r i n t f (" % d \ n ", i );

++ i ;

p r i n t f (" % d \ n ", i );

p r i n t f (" % d \ n ", i + + ) ; p r i n t f (" % d \ n ",++ i );

d o u b l e z = i * 1 . 0 ;

p r i n t f (" % d % f \ n ",z , z );

f l o a t g , h ; g = i /3;

h = z /3;

p r i n t f (" % f % f \ n ",g , h );

c h a r c =’ s ’;

p r i n t f (" % d \ n ", c );

p r i n t f (" % c \ n ", c );

c - -;

p r i n t f (" % c \ n ", c );

c + = 5 ;

p r i n t f (" % c \ n ", c );

Page de manuel : man 3 printf

p r i n t f (" % s , %.2 f , *% -4 d * , *%4 d *\ n ", " t o t o : ", 1/3. , 2 , 1);

(11)

Saisie au clavier

La fonction scanf permet de choisir le type des donn´ ees saisies grˆ ace ` a un format (comme printf).

Attention, scanf utilise les adresses des variables pour stocker le r´ esultat !

# i n c l u d e < s t d i o . h >

c h a r c ;

int i = 0;

s c a n f (" % c ",& c );

s c a n f (" % d ",& i );

p r i n t f (" *** % d ,% c * * * \ n ",i , c );

(12)

Conditions : exemple

Exemple :

u n s i g n e d int x = -1;

int y = -1;

if ( x < 0) if ( y < 0){

p r i n t f (" % d n e g a t i f \ n ", x );

p r i n t f (" % d n e g a t i f \ n ", y );

} e l s e

p r i n t f (" % d n e g a t i f \ n % d p o s i t i f \ n ", x , y );

if ( x > 0 && y < 0)

p r i n t f (" % d p o s i t i f \ n % d n e g a t i f \ n ", x , y );

e l s e{

p r i n t f (" % d p o s i t i f \ n ", x );

p r i n t f (" % d p o s i t i f \ n ", y );

}

Est-ce correct ? Qu’est-ce que ¸ ca affiche ?

(13)

Conditions

if ( < c o n d i t i o n >) // ne pas o u b l i e r les p a r e n t h `e s e s !

< s t a t e m e n t 1 >

// / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / if ( < c o n d i t i o n >)

< s t a t e m e n t 1 >

e l s e

< s t a t e m e n t 2 >

Les instructions ( <statement> ) peuvent ˆ etre remplac´ ees par des blocs :

{

< o p t i o n a l - d e c l a r a t i o n - list >

< o p t i o n a l - s t a t e m e n t - list >

}

(14)

Conditions : variantes

if ( a > b ) r e s u l t = x ; e l s e

r e s u l t = y ; // ´e q u i v a u t `a :

r e s u l t = a > b ? x : y ; // if t e r n a i r e

s w i t c h ( < e x p r e s s i o n >){

c a s e < label1 > :

< s t a t e m e n t s 1 > // a t t e n t i o n `a la t r a p p e ! c a s e < label2 > :

< s t a t e m e n t s 2 >

b r e a k;

d e f a u l t :

< s t a t e m e n t s 3 >

}

(15)

Switch : exemple

int t o t o = . . . ; s w i t c h ( t o t o ){

c a s e 0:

p r i n t f (" 0\ n ");

c a s e 1 :

p r i n t f (" 1\ n ");

b r e a k; c a s e 2 :

p r i n t f (" 2\ n ");

d e f a u l t :

p r i n t f (" ni 0 , ni 1 , ni 2\ n ");

}

Qu’affiche-t-on si toto vaut 0, 1, 2 ou 3 ?

(16)

Boucles

2 types de boucles while:

w h i l e( < c o n d i t i o n > ){

< s t a t e m e n t >;

}

do{

< s t a t e m e n t >;

}w h i l e( < c o n d i t i o n > );

B break sort de la boucle (seulement la plus imbriqu´ ee).

B continue recommence la boucle depuis le d´ ebut du bloc (pour un for, l’instruction d’incr´ ement est ex´ ecut´ ee).

Mais quelle est la diff´ erence ?

int i = 0 ;

w h i l e ( i < 1 0 ) { p r i n t f (" % d ", i );

i ++;

}

p r i n t f (" % d \ n ", i );

int i = 0 ;

do{

p r i n t f (" % d ", i );

i ++;

}w h i l e ( i < 1 0 ) ; p r i n t f (" % d \ n ", i );

(17)

Boucles – suite

Si vous avez besoin de r´ ealiser les instructions de la boucle au moins une fois, et avant le test...

int k ;

w h i l e( k <0 || k > = 1 0 ) { p r i n t f (" k ? ");

s c a n f (" % d ", & k );

}

int j ; do {

p r i n t f (" j ? ");

s c a n f (" % d ", & j );

} w h i l e( j <0 || j > = 1 0 ) ;

Les instructions ne peuvent ˆ etre effectu´ ees que si le test est vrai

p r i n t f (" E n t r e z une v a l e u r > 0\ n ");

s c a n f (" % i ",& i );

w h i l e ( i > 0){

p r i n t f (" 9/% d =% d \ n ",i ,9/ i );

i - -;

}

do{

p r i n t f (" 9/% d =% d \ n ",i ,9/ i );

i - -;

}w h i l e ( i > 0);

(18)

Boucles – suite

Attention, la boucle for de C n’est pas un for each comme en Python. La fonction range n’existe pas non plus.

Syntaxe :

for ( < init >; < c o n d i t i o n >; < i n c r e m e n t > ){

< s t a t e m e n t >;

}

init est execut´ e en premier, une seule fois.

Tant que la condition est vraie, le programme rentre dans le corps de la boucle.

Apr` es l’execution du corps de la boucle, la partie increment est execut´ ee, avant de refaire le test.

Exemple :

for (int i = 0; i < 10; i + + ) { p r i n t f (" % d ", i );

}

(19)

Boucles – suite

Autres exemples :

for ( c h a r c = ’ z ’; c >= ’ a ’; c - -){

p r i n t f (" c o d e a s c i i de % c = % d \ n ",c , c );

}

int cpt = 1 0 ;

for (int i = 1; cpt !=0 && i < I N T _ M A X ; i * = 2 ) { p r i n t f (" % d ", i );

cpt - -;

}

for ( i =0 ; i != 10 ; i = r a n d ( ) % 2 0 ) ) { p r i n t f (" % d ", i );

}

Bof :

for ( s c a n f (" % d ",& i ); i != 0; i - -){

p r i n t f (" % d ",i - = 2 ) ;

}

(20)

Fonctions

Attention aux types !

v o i d h e l l o (){

p r i n t f (" h e l l o ");

}

v o i d h e l l o s (int n ){

w h i l e ( n ! = 0 ) { p r i n t f (" h e l l o ");

n - -; // ok , car les p a r a m `e t r e s s o n t p a s s ´e s par v a l e u r . }

}

int p1 (int a , int b ){

int res =1;

for (int i = 0; i < b ; ++ i ) res *= a ;

r e t u r n res ; }

int p2 (int a , int b ){

r e t u r n b == 0 ? 1 : a * p2 ( a , b - 1 ) ;

}

(21)

Structures de donn´ ees

standard

(22)

Structures de donn´ ees

´

enum´ eration

type structur´ e (pour faire des tuples) tableaux automatiques

matrices

chaines de caract` eres (tableaux de caract` eres avec marqueur de fin)

mais pas de listes ni de dictionnaires !

(23)

Type ´ enum´ er´ e, type structur´ e

e n u m c a r d _ c o l o r { CLUB ,

DIAMOND , HEART , S P A D E };

s t r u c t c a r d {

e n u m c a r d _ c o l o r c o l o r ; int v a l u e ;

};

int m a i n (int argc , c h a r * a r g v [ ] ) { e n u m c a r d _ c o l o r t r u m p = S P A D E ; p r i n t f (" % d \ n ", t r u m p );

s t r u c t c a r d m y _ c a r d = { trump , 1 0 } ;

p r i n t f (" % d ,% d \ n ", m y _ c a r d . color , m y _ c a r d . v a l u e );

r e t u r n 0;

}

(24)

Tableaux automatiques

B Un “objet” automatique est un objet dont l’emplacement en m´ emoire est r´ eserv´ e lors de la compilation (et pas ` a l’ex´ ecution).

B AVANT (C Ansi), la taille d’un tableau automatique devait ˆ etre connue lors de la compilation ; c’´ etait :

soit une constante enti` ere : 4, 18, 150, ...

soit une constante symbolique : #define N 1000

B MAINTENANT (C 99), on a les variable length arrays. La taille n’a plus besoin d’ˆ etre connue ` a la compilation !

On peut ´ ecrire char tab[n], o` u n est un entier.

Mais on ne peut toujours pas d´ eclarer : int tab[];

B Le type des ´ el´ ements du tableau doit ˆ etre sp´ ecifi´ e lors de la

d´ eclaration : type nom tableau[taille];

(25)

D´ eclarer et initialiser un tableau (automatique)

# d e f i n e T A I L L E 100 ...

int i ; int n = 1 0 ;

int t a b 0 [ n ]; /* !! ok en C 99 , m a i s pas en C A n s i */

int t a b 1 [ T A I L L E ];

c h a r t a b 2 [ 2 0 ] ;

s h o r t t a b 3 []={0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9}; /* t a i l l e = 10 */

d o u b l e t a b 4 [ ] = { 1 2 . 2 , 3 . 0 , 8 . 1 , 4 . 7 7 7 } ; /* t a i l l e = 4 */

c h a r mot []=" T o t o "; /* { ’ T ’ , ’ o ’ , ’ t ’ , ’ o ’ , ’\0 ’} */

for( i =0; i <= TAILLE -1; i ++) // a t t e n t i o n aux b o r n e s ! t a b 1 [ i ]= i * n ;

for( i =0; i < 2 0 ; i ++) // a t t e n t i o n aux b o r n e s ! t a b 2 [ i ]=’ a ’+ i ;

Attention, pour l’initialisation, il n’existe pas de m´ ecanisme de

(26)

Parcourir un tableau

En C, tous les tableaux commencent ` a l’indice 0.

On acc´ ede aux cases d’indice 0 ` a n − 1 (tab. de longueur n).

Une tentative d’acc` es ` a une case d’indice ≥ n provoquera un r´ esultat al´ eatoire et risque en particulier de provoquer une segmentation fault.

for( i =0; i < T A I L L E ; i ++) p r i n t f (" % d ", t a b 1 [ i ]);

for( i = TAILLE -1; i > = 0 ; i - -) p r i n t f (" % d ", t a b 1 [ i ]);

Le cas d’une chaˆıne de caract` eres :

c’est un tableau de caract` eres char[] dont le dernier est obligatoirement ’\0’.

soit on connaˆıt sa taille et on peut proc´ eder de mˆ eme ; soit on utilise la sentinelle ’\0’ pour stopper le parcours.

for( i =0; mot [ i ] ! = \ 0 ; i ++) p r i n t f (" % c ", mot [ i ]);

(27)

Tableaux et fonctions

Attention : TABLEAU = POINTEUR ! !

la variable nom tableau contient l’adresse de la premi` ere case du tableau.

B Cons´ equence : un tableau pass´ e en param` etre d’une fonction peut ˆ etre modifi´ e ! !

MAIS : une fonction ne peut pas renvoyer un tableau automatique cr´ e´ e dans cette fonction.

Pourquoi ? Parce que l’espace r´ eserv´ e (allou´ e ) au tableau dans la fonction est d´ etruit ` a la sortie de la fonction.

Par contre, on peut passer en param` etre de la fonction un

tableau d´ ej` a d´ eclar´ e et le modifier.

(28)

Exemple

v o i d a f f i c h e T a b (int tab [] , int l g T a b ){

int i ;

for( i =0; i < l g T a b ; i ++) p r i n t f (" % d ", tab [ i ]);

p r i n t f (" \ n ");

}

v o i d m o d i f T a b (int tab []} , int i , int e l e m ){

tab [ i ]= e l e m ; }

int m a i n (int argc , c h a r * a r g v [ ] ) {

int tab []={0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9}; /* t a i l l e = 10 */

a f f i c h e T a b ( tab , 1 0 ) ; /* 0 1 2 3 4 5 6 7 8 9 */

m o d i f T a b ( tab ,5 , -1);

a f f i c h e T a b ( tab , 1 0 ) ; /* 0 1 2 3 4 -1 6 7 8 9 */

r e t u r n 0;

}

(29)

D´ eclarer et initialiser une matrice

Matrice = Tableau ` a 2 dimensions.

Matrice = Tableau dont les cases sont des tableaux.

B comme pour un tableau classique, on indique sa taille lors de la d´ eclaration :

int m a t r i c e [ 2 ] [ 3 ] ; // ou c h a r m a t r i c e [ n ][ m ];

B comme pour un tableau classique, on peut l’initialiser lors de la d´ eclaration ...

int m a t r i c e [ 2 ] [ 3 ] = {{1 , 2 , 3} , {4 , 5 , 6 } } ; // ou int m a t r i c e [ ] [ 3 ] = {{1 , 2 , 3} , {4 , 5 , 6 } } ;

B ... ou apr` es

m a t r i c e [ 0 ] [ 0 ] = 1;

m a t r i c e [ 0 ] [ 1 ] = 2;

m a t r i c e [ 0 ] [ 2 ] = 3;

m a t r i c e [ 1 ] [ 0 ] = 4; // ...

(30)

Parcourir une matrice

int i , j ;

int m a t r i c e [ 3 ] [ 5 ] ; for( i =0; i <3; i ++)

for( j =0; j <5; j ++) m a t r i c e [ i ][ j ]= i + j ;

0 1 2 3 4 1 2 3 4 5 2 3 4 5 6

0 1 2 1 2 3 2 3 4 3 4 5 4 5 6

ou ?

B Convention :

type nomMatrice[nb lignes][nb colonnes];

B matrice[i][j] → case sur la i

e

ligne, dans la j

e

colonne .

(31)

Compl´ ements

(32)

Chaˆınes de caract` eres

Attention, toute chaˆıne de caract` eres est un tableau de caract` eres mais la r´ eciproque n’est pas vraie !

Ce qui caract´ erise une chaˆıne de caract` ere est l’\0 final.

Les chaˆınes (d´ eclar´ ees avec la notation []) sont mutables.

Il existe un certain nombre de fonctions pr´ ed´ efinies sur les chaˆınes dans les biblioth` eques standard stdlib.h et string.h :

strlen qui prend un chaˆıne et renvoie sa taille (sans compter l’\0).

atoi et atof qui transforme une chaine en entier/flottant.

...

Lecture au clavier : il faut choisir sa taille ` a l’avance !

c h a r s t r i n g [ 1 0 0 ] ; s c a n f (" % s ", s t r i n g );

p r i n t f (" % s \ n ", s t r i n g );

// p l u s s^ur : c h a r s t r i n g [ 1 0 0 ] ;

f g e t s ( string , 100 , s t d i n );

Qu’est-ce qu’un char[][] ?

Struct 32/35

(33)

Chaˆınes de caract` eres - Exemple

int d (c h a r s [] , c h a r t [ ] ) { int a = s t r l e n ( s );

for (int i = 0; i < a ; i ++) if ( s [ i ]!= t [ i ])

r e t u r n 0;

r e t u r n 1;

}

v o i d f (c h a r s [ ] ) { int a = s t r l e n ( s );

c h a r t ;

for(int i =0; i < a /2; i + + ) { t = s [ i ];

s [ i ]= s [ a - i - 1 ] ; s [ a - i - 1 ] = t ; }

}

int g (c h a r s [ ] ) { int a = s t r l e n ( s );

c h a r t [ a + 1 ] ;

for(int i =0; i < a ; i ++) t [ i ]= s [ i ];

t [ a ]=’ \0 ’;

f ( t );

r e t u r n d ( s , t );

}

int h (c h a r s [ ] ) { int a = s t r l e n ( s );

for(int i =0; i < a /2; i + + ) { if ( s [ i ]!= s [ a - i - 1 ] )

r e t u r n 0;

}

r e t u r n 1;

}

(34)

Compilation - Ex´ ecution - Arguments

fichier my prog.c :

# i n c l u d e < s t d i o . h >

# i n c l u d e < s t d l i b . h >

# i n c l u d e " m y _ l i b . h "

# d e f i n e R M A X 2

int m a i n (int argc , c h a r * a r g v [ ] ) { p r i n t f (" p r o g : % s \ n ", a r g v [ 0 ] ) ; if( a r g c = = 3 ) {

int nb = a t o i ( a r g v [ 1 ] ) ;

for (int i = 0; i < nb ; ++ i ) p r i n t f (" % d ", m y R a n d ( R M A X ));

}

e l s e p r i n t f (" b e u h . . . \ n ");

r e t u r n 0;

}

fichier my lib.h :

int m y R a n d (int n );

fichier my lib.c :

# i n c l u d e < s t d l i b . h >

int m y R a n d (int n ){

r e t u r n r a n d o m ()% n ;

}

pour compiler :

gcc my lib.c my prog.c pour executer :

./a.out ou :

gcc my lib.c my prog.c -o my prog

./my prog 20

(35)

Contrˆ ole d’erreur

Pas d’exception, donc pas de m´ ecanisme try ... catch.

Il faut tester avant d’utiliser une fonction qui peut ”rater”.

Il faut tester les valeurs de retour des fonctions qui peuvent rencontrer des probl` emes.

Exemple :

int i ;

int try = s c a n f (" % d ",& i );

if( try ==0 || try == EOF )

p r i n t f (" on d o i t l i r e un e n t i e r !\ n ");

e l s e

if ( i ! = 0 )

p r i n t f (" % d \ n ", 4/ i );

e l s e p r i n t f (" i d o i t ^e t r e non nul !\ n ");

r e t u r n 0;

Références

Documents relatifs

En d´ eduire l’´ equation r´ eduite (Si besoin, on pourra s’aider de calcul pour calculer l’ordonn´ ee ` a

[r]

[r]

[r]

N’utilisez surtout pas la notation ln(z) si z n’est pas un r´ eel strictement

En rassemblant les deux tableaux pr´ec´edents, on va d´eterminer le signe de f (x)

• Le port de Canton est en 2005 le troisi` eme port chinois en terme de trafic de marchandises avec 250 millions de tonnes de trafic, soit une progression de plus de 16% par rapport `

Pour cela, ` a partir d’un texte (en fran¸ cais par exemple), on calcule les probabilit´ es qu’une lettre donn´ ee se trouve im´ ediatement apr` es une autre lettre donn´ ee1.