1 projet informatique 2a séances de soutien [email protected] [email protected] ces...

80
1 Projet informatique 2A Séances de soutien [email protected] [email protected] Ces transparents s’inspirent largement des cours 1A PET (M. Desvignes) et PMP (R Bressoux, E Moisan, N Castagne) Merci à eux

Upload: yvonne-guilbert

Post on 04-Apr-2015

111 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

1

Projet informatique 2A

Séances de soutien

[email protected]@imag.fr

Ces transparents s’inspirent largement des cours 1A PET (M. Desvignes) et PMP (R Bressoux, E Moisan, N Castagne)

Merci à eux

Page 2: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

2

Séance I. L’environnement LINUX

Premier programme de l'année scolaire

Compilation et exécution

Rappel sur les Types de base, E/S, Structures de contrôle

Séance II. Rappel sur les tableaux, pointeurs et fonctions

Compilation séparée et Makefile

Types structurés, tableaux et chaînes de caractères

Entrées sorties fichier

Séance III Allocation dynamique

Débogueur (DDD, Valgrind)

Types abstraits ; exemple des listes

Récursivité

Séance IV suite de la séance III

Arbres et graphes

Planning prévisionnel

Page 3: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

3

Tableaux

Page 4: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

44

Tableaux Tableaux

Collection de variables de même type, rangées continûment en mémoire Déclaration : spécifier

le type des éléments le nom du tableau le nombre des éléments

Exemples : float c[100]; /* tableau de 100 réels */ int tab[10]; /* tableau de 10 entiers*/

Exemple : tab1.cmain() { int i; int tab[10]; /* Tableau de 10 entiers */ float c[20]; /* Tableau de 20 réels */ for (i=0; i<10; i++) tab[i]= 2*i; /*Mettre 0,2,4,6..dans les elements*/ for (i=0; i<10; i++) printf("%d ",tab[i]); /* afficher les éléments de t */}

tab[9]: 18

tab[2]: 4

0

tab[1]: 2

tab[0]: 0tab &tab[0]

Adresse

&tab[1]

&tab[2]

&tab[9]

Page 5: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

55

Tableaux

18

4

0

2

0tab &tab[0]

Adresse

&tab[1]

tab[2]

&tab[-2]

&tab[9]

&tab[900]

tab+1

tab+2

tab+9

Remarques Nombre d’éléments constant, non modifiable Le nom du tableau est son adresse (ie l’endroit où il se trouve en mémoire

Accès à un élément du tableau : nom_du_tableau[expression entiere]

Exemple : tab[i]

Comment fait le compilateur : on part du début du tableau, on ajoute i : c’est l’endroit où se trouve notre élément

Attention : Pas de vérification sur les indices. Si on demande un élément avant ou après la fin du tableau, c’est une erreur à l’execution du programme mais pas d’erreurs à la compilation

Page 6: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

66

Tableaux : accès et débordements

Exemple 2 : tab2.cmain() { int i; int tab[10]; for (i=0; i<10; i++) tab[i]= 2*i; puts("Voici les elements : "); /* afficher les éléments de t */ for (i=0; i<5; i++) printf("%d ",tab[i]); puts(""); puts("Voici les adresses : "); /* afficher les adresses */ for (i=0; i<5; i++) printf("%p ",tab+i); puts(""); tab[-2]= 18952; printf("%d ",tab[900]); }

18

4

0

2

00xbffff384 &tab[0]

Adresse

&tab[1]

&tab[2]

&tab[-2]

&tab[9]

&tab[900]

0xbffff388

0xbffff38c

0xbffff3a8

0xbffff37c

0xc0000194

Page 7: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

77

Tableaux : opérations globales ? Attention : AUCUNE opération globale sur un tableau

les opérations et les E/S doivent se faire élément par élément En particulier

T1==T2 ne teste pas l’égalité de 2 tableaux T1=T2 ne recopie pas les éléments de T1 dans T2

Exemples : tab3.cmain() {int i; double t1[10], t2[10]; /* t1 et t2 sont 2 tableaux de 10 reéls */ for (i=0; i<10; i++) {t1[i]=2*i; t2[i]=log(100*i+1); } printf("Emplacement de t1:%p de t2:%p\n",t1,t2); printf("Emplacement de t1[1]:%p de t2[1]:%p\n",t1+1,t2+1); printf("Valeur de t1[0]:%lf de t2[0]:%lf\n",t1[0],t2[0]); if (t1==t2) printf("t1 et t2 sont au meme endroit\n"); else printf("t1 et t2 ne sont pas au meme endroit\n"); for (i=0; i<10; i++) t2[i]= t1[i]; /*Copie de t2 dans t1: on peut remplacer cette ligne par: memcpy(t2,t1,sizeof(t1)); Mais on ne peut pas utiliser t1=t2; */ for (i=0; i<10; i++) printf(”Valeur de t2[%d] : %lf\n”,i,t1[i]);}

Page 8: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

88

Tableaux : fonctions de la libc Les fonctions travaillant sur les zones mémoires : comme un tableau est une zone

mémoire continue, on peut utiliser ces fonctions avec les tableaux #include <string.h>

void * memmove(void *s1, const void *s2, size_t n); Copie n octets de la zone de mémoire src vers la zone dest. Les deux zones peuvent se chevaucher.

void *memcpy (void *dest, const void *src, size_t n); idem, mais les zones ne peuvent pas se chevaucher

int memcmp (const void *s1, const void *s2, size_t n); compare les n premiers octets des zones mémoire s1 et s2.

void *memset (void *s, int c, size_t n); remplit les n premiers octets de la zone mémoire pointée par s avec l’octet c.

void swab (const void * from, void * to, ssize_t n); copie n octets de la zone from dans la zone to, en échangeant les octets adjacents

Page 9: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

9

Pointeurs

Pointeurs

Page 10: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

1010

Pointeurs Variable contenant l’adresse d’un autre objet (variable ou fonction)

Adresse : numéro d’une case mémoire

Déclaration : type_pointé* identificateur; Exemples :

int* p1; /* p1 contient l’adresse d’un entier */double* p2; /* p2 contient l’adresse d’un réel */

ATTENTION : un pointeur doit toujours être initialisé avant d’être utilisé = Il doit contenir une adresse légale :

soit celle d’un objet existant soit celle obtenu par une demande d’allocation dynamique soit NULL, qui est la valeur 0. Il est interdit de lire et écrire à l'adresse 0

Remarque : on affiche la valeur d’un pointeur en hexadecimal par printf("Voici la valeur du pointeur %p\n",p);

Page 11: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

1111

PointeursPointeurs

Exemple : p1.cmain() {

int i=0;

int* p1=NULL; /* p1: pointeur sur un entier */

p1 = &i; /*p1 pointe i, ie contient l’adresse de i*/

/* ICI, i ou *p1 sont une seule et meme chose */

*p1 = 5; /* identique à i=5; */

printf("Valeur de i:%d, Adresse de i:%p\n",i,&i);

printf("Valeur de p:%p, Valeur pointée:%d\n",p1,*p1);

printf("Adresse de p:%p\n", &p1);

}

0

p= 0

i= 00xbffff38c &i

Adresse

&p

0xbffff388 p1=0xbffff38c

i= 5

Page 12: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

1212

Opérations sur pointeurs Affectation : donner une valeur au pointeur, celle d’une adresse légitime.

p1=&i; /* &i : l'adresse de i */

Indirection : trouver la valeur pointée par p.

j = *p1; /* *p1 : ce qu'il y a à l'adresse p1 */

Comparaison : == et != : p1==p2; p1 et p2 regardent ils la meme adresse ? <, >, <=, >= : par exemple, p1<p2 sur un meme tableau, p1 est il avant p2

Arithmétique Adresse + entier ==> adresse : p1 +1 est l’adresse de l’élément suivant p1

Adresse - Adresse ==> entier : p2 -p1 est donc le nombre d’éléments entre les adresses contenues dans p2 et p1. Valide uniquement si p1 et p2 sont de meme type.

ATTENTION : les pointeurs étant typés, les opérations se font en nombre d’éléments et non

en nombre d’octets

Page 13: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

1313

Adresse et tableaux Nom du tableau : adresse du tableau

Accès à un élément t[i] : on part de l‘adresse de début du tableau, on ajoute i et on obtient l’adresse du ième

élément. L’élément est obtenu par l’opérateur d’indirection *

Conséquences L’élément t[i] s ’écrit aussi *(t+i) L’adresse de t[i] s’écrit &t[i] ou bien (t+i)

Page 14: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

1414

Adresses et tableaux Exemple : p3.cmain() { int tab[10]; int i; for (i=0; i<10; i++) tab[i]= 2*i; puts("Voici l’element d’indice 2 : "); printf("%d %d",tab[2],*(tab+2)); puts(""); puts("Voici les adresses : "); for (i=0; i<5; i++) printf("%p %p",tab+i, &tab[i]); }

18

4

0

2

00xbffff364 &tab[0]

Adresse

&tab[1]

&tab[2]

&tab[9]

0xbffff368

0xbffff36c

0xbffff388

2 manières différentes d'ecrire l'adresse de t[i]

Page 15: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

1515

Parcourir un tableau avec un

pointeur Exemple : p4.cmain() {int* p=NULL; int i; int tab[5]; for (i=0; i<5; i++) tab[i]=2*i+1; p=tab; while (p<tab+5) { printf(" Pointeur: %p ",,p); printf(" Valeur %d",*p);

*p=234; printf("Valeur modifiee %d\n",*p); p++; }

9

5

0

3

10xbffff384 &tab[0]

Adresse

&tab[1]

&tab[2]

&tab[4]

0xbffff388

0xbffff38c

0xbffff394

7 &tab[3]0xbffff390

i= 5 &i0xbffff398

p= 0 &p0xbffff39c 0xbffff384

tab[0]=234

0xbffff388

tab[1]=234

0xbffff38c

tab[2]=234

0xbffff390

tab[3]=234

tab[4]=234

0xbffff394

Page 16: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

16

Structures

Structures, définition de types

Page 17: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

1717

Créer ses propres types

Pourquoi ? Clarifier l'écriture d’un programme

Exemple : j’aime pas les int* je veux indiquer clairement qu’une variable est un octet et pas un caractère

Définir un nouveau type : instruction typedef

• typedef ancien_type nouveau_type;

Page 18: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

1818

Créer ses propres types

typedef unsigned char OCTET; typedef int* POINTEUR;

void swap(POINTEUR p1, POINTEUR p2) { int c=*p1; *p1=*p2; *p2=c; } main() { OCTET a; int i,j; POINTEUR p; a=156; i=32546; p=&i; j=-5; printf("Valeur de l’octet a :%d\n",a);

printf("Valeur de i et de *p :%d %d\n",i,*p); swap(&i,&j); }

POINTEUR peut remplacer int* partout

Page 19: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

1919

Les structures

Regroupement d’informations de types identiques ou différents

Relatif à une même entité abstraite. permet de manipuler sous un même nom plusieurs

éléments d'informations

Exemple : Un point : une structure comportant les deux coordonnées

X et Y du point Un complexe : les parties réelle et imaginaire du

complexe. un etat civil : une structure regroupant le nom, prénom,

n°SS, age....

Déclaration de typestruct ident1 {

type nom_du_champ; ....

} /* fin de structure */

Définition de variable :struct nomdestructure identif_var;

a1.re

a1.im

a1

struct complex {double im,re;};

struct complex a1;

Nom du type

Nom de la variable

Page 20: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

2020

Structures (2)

Un élément chimique avec les informations de type différent:

struct element_atomique { char nom[20] ; char symbole[4] ; int nummeroatomique; double masseatomique; double densite ; double fusion ; /* Temperature de fusion en ° */ double vap; /* Temperature de vaporisation en ° */ double rayon; /* rayon atomique en A */ double rayon_cov; /* rayon de covalence en A */ char rayonionique[24] ; /* Rayon ionique */ } x;

x.nomX

x.symbole

x.numeroat

x.masseato

x.densitéLe type s’appelle

struct element_atomique

Page 21: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

2121

Structure (3)

Accès à un champ Pour une variable structurée :opérateur . Pour une structure pointée : opérateur ->

Opérations sur les structures : aucune sauf Affectation de structures meme type Passage et retour de structures par valeur dans les fonctions

Les éléments de la structure sont des variables à part entière : ils ont une adresse

typedef struct { int x,y} T_POINT;

void aff(T_POINT a) {

printf("%d %d\n",a.x,a.y);

}

main() { T_POINT a1, *pa1, a2;

a1.x=1; a1.y=-1;

pa1=&a1; pa1->x=0;

a2 = a1;

aff(a2);

aff(*pa1);

}

a1.x

a1.y a1

pa1

1

-1

0xbffff398

0

a2.x

a2.y

a2

-1

00xbffff38c

0xbffff394

0xbffff398

On définit une structure anonyme et un nouveau yype

pa1 est un pointeur. Donc, pa1->x est la partie x de a1

aff est une fonction qui utilise un T_POINT : elle a accès aux 2 coordonnées de a, a.x et a.y

Page 22: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

2222

Structures (4)

Aucune autre action globale, sauf la copie en particulier

Comparaison de structure a1==a2 Lecture/ecriture de structure : printf("%lf",a1);

Il faut tout faire champ par champ

Exemple : struct3.cmain() { T_POINT a3,a1,a2={1,-1};

scanf("%lf %lf",&a1.x, &a1.y); a3 = a2; /* Copîe a2 dans a3 : a3.x=1 et a3.y=-1 */ puts("Point a1"); aff(a1); /* affiche un point */ puts("Point a2"); aff(a2); /* affiche un point */ /* Ce code est impossible if (a1==a2) puts("a1 et a2 identiques"); else puts("a1 et a2 different"); */ if(a1.x==a3.x && a1.y==a3.y) puts("a1 et a3 identiques"); else puts("a1 et a3 different");}

Lecture clavier des 2 champs

Page 23: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

2323

Structure (5)

Une structure est un type utilisable pour construire d’autres types On peut faire

des tableaux de structuresdes structures de structures

Page 24: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

2424

Exos Ex1 : faire un programme qui calcule la somme des éléments d'un tableau en

utilisant uniquement des indices pointeurs (et pas entiers) Ex2 : faire un programme qui copie un tableau de N entiers (N=10) dans un

autre tableau en utilisant uniquement des indices pointeurs Ex3 : faire un programme qui génère 100 nombres entiers dans un tableau, les

affiche et trouve le minimum. Pour utiliser: $ man 3 rand, pour générer les nombres aléatoires

Ex4 : faire un programme qui utilise un tableau mono-dimensionel d'entiers comme une matrice. Pour cela faire une fonction int element(int mat, int M, int N, int i, int j) qui retourne l'élèment de la ie ligne et de la je colonne, ou M et N sont les dimensions de la matrice mat. Faites le programme principal qui teste cette fonction.

Ex5 ecrire une structure Image contenant un tableau pour stocker les pixels et deux champs pour stocker les dimensions. Ecrire deux fonctions pour initialiser (initialiser une image) et remplir aléatoirement l'image.

Je veux ajouter un champs à ma structure, quelles conséquences pour les deux foncctions ? Que se passe-t'il si je ne retourne pas la structure passée en paramètre ?

Page 25: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

25

VIII. Fonctions et procédures

VIII.1. Introduction

VIII.2. Le mécanisme de base

VIII.3. Passage par valeur et « passage par adresse »

VIII.4. Notion de contrat de fonction, prototype d’une fonction

Page 26: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

26

VIII.1. Introduction

#include <math.h>

x, y, z réels double x, y, z ; i entier int i ;

z ← | x | z = fabs(x) ; associe un réel à un réel, z ← arctg ( x ) z = atan(x) ; associe un réel à un réel, i ← ⌊ x ⌋ i = floor(x) ; associe un entier à un réel, z ← xy z = pow(x, y) ; associe un réel à deux réels.

Une fonction mathématique retourne une valeur de sortie (un résultat)

établie à partir de différents paramètres d’entrée (des arguments) :

VIII.1.1 En maths …

Page 27: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

27

En programmation, une fonction prend en entrée des données et renvoie des

résultats après avoir exécuté différentes instructions.

Une fonction ou procédure apparaît comme :

- un bloc d’instructions regroupées sous un nom particulier,

- qui pourra retourner une unique valeur de sortie (un résultat)

- qui pourra admettre 0, 1, 2, … paramètres d’entrée (des

arguments).Les avantages sont nombreux :

- réutilisation du même bloc d’instructions (sur des valeurs différentes),

- réutilisation dans d’autres programmes (bibliothèques).

- décomposition du problème en fonctions qui effectuent des actions

simples :

- conception du programme plus facile, structuration

- lisibilité du code accrue,

- débuggage facilité.

VIII.1. IntroductionVIII.1.2 En programmation…

Page 28: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

28

VIII.2. Le mécanisme de base

#include "stdio.h" // bibliothèque de fonctions d’entrées/sorties

float discr ( float x , float y , float z){

float discriminant ; // bloc d’instructions (entre {…} ) de ladiscriminant = y * y – 4 * x * z ; // fonction nommée discr

//return discriminant ; //

}

int main( ){

float a = 4. , b = 3. , c = -1.5 , d , e ;

d = discr ( a , b , c ) ;e = discr ( a , 3. , 9.) ;

return 0 ;} Le main est la fonction qui est automatiquement

appelée lors de l’exécution : c’est le point d’entrée du programme.

1/ appel de la fonction discr

2/ retour

VIII.2.1. Exemple

Page 29: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

29

float discr ( float x , float y , float z ){

float discriminant ;discriminant = y * y – 4 * x * z ;

return discriminant ;}

Le nom de la fonction

La liste des arguments (type et nom) en entrée de la fonction.

Les arguments sont des variables !

Cette liste peut être vide.

Le résultat renvoyé par la fonction.Ici, c’est la valeur de la variable locale discriminant

Le type retourné.C’est le type de la valeur retournée.Le type peut être void

(aucune valeur retournée)

Corps de la fonction.Bloc d’instructions qui seront exécutées à chaque appel de la fonction.

VIII.2.2. Déclaration d’une fonction

VIII.2. Le mécanisme de base

Variable locale

Page 30: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

30

int main(int argc, int ** argv){

float a = 4. , b = 3. , c = -1.5 , res ;

res = discr ( a , b , c ) ;

printf( " discr de %f %f %f vaut %f\n", a, b, c, res);

printf( " discr de %f %f %f vaut %f\n", a, 3., 9., discr ( a , 3. , 9 ) );

return 0 ;}

Appel de la fonction discr avec les valeurs de a, b et c.On suppose la fonction discr déclarée par ailleurs.La valeur retournée par discr est affectée à d.

VI.2.3. Appel de fonction

VIII.2. Le mécanisme de base

Page 31: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

31

float discr ( float a , float y , float z){

float discriminant ;

discriminant = y * y – 4 * a * z ;

return discriminant ;}

int main( ){ float a = 4. , b = 3. , d ;

d = discr ( a , b , -1.5 ) ;

return 0 ;}

VIII.2.4. ce qui se passe…

a = 4

b = 3

d = ???

Représentation

de la mémoire

Avant l’appel de fonction

VIII.2. Le mécanisme de base

Page 32: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

32

a, y et z

sont les

« paramètres »

discriminant

est une

« variable

locale »

float discr ( float a , float y , float z){

float discriminant ;

discriminant = y * y – 4 * a * z ;

return discriminant ;}

int main( ){ float a = 4. , b = 3. , d ;

d = discr ( a , b , -1.5 ) ;

return 0 ;}

a = 4

y = 3

z = -1,5

discriminant = ???

Appel de la fonction : copie des valeurs des paramètres effectifs dans de nouvelles variables

VIII.2.4. ce qui se passe…

VIII.2. Le mécanisme de base

a = 4

b = 3

d = ???

Page 33: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

33

float discr ( float a , float y , float z){

float discriminant ;

discriminant = y * y – 4 * a * z ;

return discriminant ;}

int main( ){ float a = 4. , b = 3. , d ;

d = discr ( a , b , -1.5 ) ;

return 0 ;}

a = 4

y = 3

z = -1,5

discriminant = ???

Appel de la fonction : copie des valeurs des paramètres effectifs dans de nouvelles variables

VIII.2.4. ce qui se passe…

VIII.2. Le mécanisme de base

Ce n’est pas

la même

variable

  "a" !

Elle est ailleurs

en mémoire !

!

a = 4

b = 3

d = ???

Page 34: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

34

float discr ( float a , float y , float z){

float discriminant ;

discriminant = y * y – 4 * a * z ;

return discriminant ;}

int main( ){ float a = 4. , b = 3. , d ;

d = discr ( a , b , -1.5 ) ;

return 0 ;}

a = 4

y = 3

z = -1,5

discriminant = 33

Appel de la fonction. Ca se passe comme d‘habitude dans le « main »

VIII.2.4. ce qui se passe…

VIII.2. Le mécanisme de base

a = 4

b = 3

d = ???

Page 35: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

35

float discr ( float a , float y , float z){

float discriminant ;

discriminant = y * y – 4 * a * z ;

return discriminant ;}

int main( ){ float a = 4. , b = 3. , d ;

d = discr ( a , b , -1.5 ) ;

return 0 ;}

Fin d’appel de fonction : destruction de toutes les variables locales et paramètres

d prend la

valeur

retournée

VIII.2.4. ce qui se passe…

VIII.2. Le mécanisme de base

discriminant = 33

a = 4

b = 3

d = 33

Page 36: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

36

VIII.2. Le mécanisme de baseVIII.2.5. Notion de portée de variable

float test( float a, float b){

float d = a * b ;c = a * b ;return d;

}

int main( ){ float a = 4., b = 5, c ;

c = test(a, b); // ou c =test(b,a) si on veut… d = 10.;

return 0 ;}

Erreur :

"c" n’est pas définie ici !!

Erreur :

"d" n’est pas définie ici !!

Ce code ne compile pas car :

Rappel :

Ce n’est pas le même a !Ce n’est pas le même b !

les variables sont locales au bloc ou elles sont définies ( entre { } )

Page 37: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

37

Lorsque l’on rencontre une instruction return, l’exécution de la fonction est arrêtée.

On reprend l’exécution des instructions qui suivent l’appel de la fonction.

Une fonction peut posséder plusieurs instructions return.

int maximum( int a , int b) {

if ( a > b )return a ;

elsereturn b ;

}

VIII.2.6. return

VIII.2. Le mécanisme de base

Page 38: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

38

Une fonction peut ne pas renvoyer de résultat : son type de retour est

noté void.

Une telle fonction est appelée une procédure.#include  "stdio.h »

void afficheMax( int a , int b ) { // procédure de type voidif ( a > b ) {

printf("a est le max\n”);return ;

}printf(”b est le max\n”);

}

int main( ) {afficheMax(3 , 5 ) ; // pas de valeur à récupérer !

return 0 ;}

Remarque : une procédure peut utiliser des instructions return, qui alors ne retourne rien.

VIII.2.7. Type void

VIII.2. Le mécanisme de base

Page 39: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

39

Écrire une fonction qui échange les valeurs de deux variables a et b de type int.

VIII.3.1. Le problème

#include <stdio.h>

void echange( int a , int b ) {

int temp ;temp = b ; b = a ; a = temp ;

}

int main( ){

int a = 1 , b = 2 ;echange( a, b ) ;printf("a: %d et b: %d\n", a, b);return 0 ;

}

Solution naïve :

Que valent a et b ?

Que valent a et b ?

VIII.3. Passage « par valeur » et « par adresse »

Page 40: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

40

Ceci ne fonctionne pas car a et b (du main) et a et b (de echange) sont des

variables différentes bien qu’étant des homonymes !

En fait, c’est comme si on avait écrit le programme suivant :

#include <stdio.h>

void echange( int n , int m ) {

int temp ;temp = n ; n = m ; m = temp ;

}

int main( ){

int a = 1 , b = 2 ;echange( b , a ) ;printf("a: %d et b: %d\n", a, b);return 0 ;

}

VIII.3.1. Le problème

VIII.3. Passage « par valeur » et « par adresse »

Page 41: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

41

Reprenons le déroulement du programme :

1) on définit a et b dans le main ; on leur affecte les valeurs 1 et 2.

2) on appelle la fonction echange avec les VALEURS de a et b.

3) les paramètres m et n reçoivent les valeurs 1 et 2.

4) la fonction echange échange les valeurs de m et n :

les paramètres m et n locaux à la fonction valent 2 et 1.

5) on revient dans le main … a et b valent toujours 1 et 2 !!!

Passage par

valeur.

!

VIII.3.1. Le problème

VIII.3. Passage « par valeur » et « par adresse »

Page 42: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

42

#include <stdio.h>

void echange( int * p_a , int * p_b ) {

int temp ;temp = *p_b ; *p_b = *p_a ; *p_a = temp ;

}

int main( ){

int a = 1 , b = 2 ;echange( &a , &b ) ;printf("a: %d et b: %d\n", a, b);return 0 ;

}

Les pointeurs viennent à notre

secours :

VIII.4.3. La solution

VIII.3. Passage « par valeur » et « par adresse »

Page 43: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

43

Reprenons le déroulement du programme :

1) on définit a et b dans le main ; on leur affecte les valeurs 1 et 2.

2) on appelle la fonction echange avec les ADRESSES de a et b.

3) p_a et p_b reçoivent les ADRESSES de a et b.

4) la fonction echange échange les valeurs des cases mémoire pointées

par p_a et p_b.

5) on revient dans le main … a et b valent maintenant 2 et 1 !

Passage par

adresse.

!

VIII.3.2. La solution

VIII.3. Passage « par valeur » et « par adresse »

Page 44: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

44

void echange( int * p_a , int * p_b ) {

int temp ;temp = *p_b ;

*p_b = *p_a ;

*p_a = temp ;}

int main( ){

int a = 1 , b = 2 ;echange( &a , &b ) ;

return 0 ;}

a = 1

b = 2

p_a = 0xbffff3b0

p_b =0xbfffff3b4

temp = 2

Appel de la fonction : copie des valeurs des paramètres effectifs dans de nouvelles variables

p_b vaut

l’adresse de b.

donc

*p_b vaut 2

valeurs adresses

0xbffff3b0

0xbffff3b4

0xbffff388

0xbffff3bc

0xbffff3c0

VIII.3.3. Exemple

VIII.3. Passage « par valeur » et « par adresse »

Page 45: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

45

void echange( int * p_a , int * p_b ) {

int temp ;temp = *p_b ;

*p_b = *p_a ;

*p_a = temp ;}

int main( ){

int a = 1 , b = 2 ;echange( &a , &b ) ;

return 0 ;}

a = 1

b = 1

p_a = 0xbffff3b0

p_b =0xbfffff3b4

temp = 2

Appel de la fonction : copie des valeurs des paramètres effectifs dans de nouvelles variables

valeurs adresses

0xbffff3b0

0xbffff3b4

0xbffff388

0xbffff3bc

0xbffff3c0*p_b est la

même case

mémoire que

la variable

« b » du main

=> On affecte

1 à cette

variable

(c’est à dire la

valeur de *p_b)

VIII.3.3. Exemple

VIII.3. Passage « par valeur » et « par adresse »

Page 46: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

46

Une variable “a” définie dans une fonction n’est utilisable que dans cette

fonction. On dit que a est locale à la fonction.

Une variable “a” définie dans une autre fonction est une variable homonyme

mais différente de la première ; elle occupera une autre case mémoire lors

de l’appel de la fonction.

Pour modifier la valeur d’une variable lorsqu’on appelle une

procédure, il faut utiliser le mécanisme du passage “par adresse”

avec des pointeurs …

Faire attention à la manipulation des & et des * !!!

Remarque : les termes “passage par valeur” et “passage par adresse” sont en fait des

abus de langage… En C, on passe toujours “par valeur”, valeurs qui valent parfois “des

adresses”..

!

VIII.4. Passage par valeur et par adresse

VIII.3.4. Résumé

Page 47: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

47

Avant même d’écrire le corps d’une fonction, il faut être très sur le

« contrat » qu’elle doit remplir, c’est à dire :

•Son rôle (ce qu’elle fait)•Son prototype. Le « prototype » ou la « signature » est constitué de :

nom de la fonction, type de retour, type et nom des

paramètres

Chacun des paramètres est soit :

IN : utilisé uniquement en entrée. Passé par valeur en C.

OUT : utilisé uniquement en sortie. Passé par pointeur en C.

IN/OUT : utilisé en entrée et en sortie. Passé par pointeur en C.

•Le champ d’utilisation de la fonction, et en particulier l’état que doit

respecter le système avant l’appel de la fonction : préconditions•L’état que dans lequel sera le système après l’appel de la fonction•Les cas d’erreur, et la façon dont la fonction réagit en cas d’erreur.

VIII.4.1. Introduction

VIII.4. Notion de contrat de fonction

Page 48: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

48

Le « contrat de fonction » peut être formalisé à l’aide de commentaire.

Exemple : définir une fonction résolvant dans une équation du second

degré.

Le « contrat » d’une telle fonction pourrait s’écrire :

VIII.4. Notion de contrat de fonctionVIII.4.2. Exemple

Prototype

Con

trat

Page 49: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

49

VIII.4. Notion de contrat de fonctionVIII.4.3. Utilisation du prototype comme promesse d’existence

Pour que le compilateur puisse vérifier les appels de fonctions, la fonction ou son

prototype doivent être définis avant le premier appel de la fonction.

#include <stdio.h>

//commentaire précisant « contrat »void echange( int * p_a , int * p_b) ; // Prototype de la fonction

int main( ){

int a = 1 , b = 2 ;echange( &a , & b ) ; // Appel de la fonctionreturn 0 ;

}

void echange( int * p_a , int * p_b) // Définition de la fonction{

int temp ;temp = *p_b ; *p_b = *p_a ; *p_a = temp ;

}

Page 50: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

50

/* ******************************************************* Titre ******************************************************* */// Entête (#include, #define, etc.)…// Prototypes des fonctions et procédures, accompagné de commentaires pour les « contrats »…int main( ) { // fonction principale

… // Définition des variables du main… // Appels des fonctions et procédures// Dorénavant le main sera être réduit à son minimum : // pour l’essentiel, définition de variables et appels de fonctions et procédures.return 0 ;

}

// Définition des fonctions// fonction exemple<type retour> exemple(<liste des arguments>) {

… // Définition des variables locales de la fonction exemple… // Instructions de la fonction exemple

return … ; // valeur de retour}

VIII.4. Notion de contrat de fonctionVIII.4.4 Structure générale d’un programme

Page 51: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

51

Exercice : Calcul des racines d’une équation du second degré – suite et fin !

Écrire un programme qui :

- demande les coefficients a, b, c de l’équation a x² + b x + c = 0 ;

- calcule la / les racine(s) réelle(s) de l’équation

- affiche les résultats

On écriera une fonction générique de résolution des équations du second degré,

qui traitera tous les cas possibles et qui ne ne fera aucune entrée/sortie.

Exercice

Page 52: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

52

Compilation séparée et Makefile

Page 53: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

53

Exercice : Calcul des racines d’une équation du second degré – suite et fin !

Récrire le programme précédent mais en séparant le main de la fonction de calcul

d'une équation du second degré, il devrait y avoir au moins les fichiers suivants :

- Makefile

- testcalcul.c

- fonction_equa.c

- fonction_equa.h

Écrire un autre main (calcul_alea.c) dans lequel on effectue 10 calculs à partir de

valeur aléatoires pour a,b et c. Ajouter une ligne à votre Makefile pour pouvoir le

compiler

Exercice

Page 54: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

54

Les chaines de caractères

Page 55: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

5555

Les chaînes de caractères En C, les chaînes de caractères ne sont pas un type particulier mais

sont : Des tableaux de char, exemple : char t[256]; Terminés par ’\0’.

"Ceci est une chaine" est une chaine de caractère constante

Pour utiliser une chaîne de caractère, 2 solutions Créer un tableau et utiliser les fonctions d’E/S sur les chaînes (scanf, gets) qui

ajoutent un \0 en fin de chaine. Créer un tableau et le remplir élément/élément, y compris le ’\0’ terminal.

Exemple : chaine0.cmain() {char s[256]; s[0]=’u’; s[1]=’n’; s[2]=’e’; s[3]=’\0’;

/* Affichage de s */ puts(s); /* ou printf("%s\n",s);}

????

’e’

0

’n’

’u’0xbffff2e0 &s[0]

Adresse

&s[1]

&s[2]

&s[255]

0xbffff3e1

0xbffff3df

’\0’ &s[3]

????les autres valeurs sont

aléatoires car on ne les a pas entrées

Page 56: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

5656

Les chaînes de caractères Exemple : chaine1.c : crée et lit 2 chaines au clavier avec 2 methodes

main() { int i; char s1[256], s2[256]; puts("Entrer une chaine");

/* Lecture d’une chaine. Gets positionne la marque de fin de chaine*/ gets(s1); /* On peut aussi utiliser scanf("%s",s1); *//* Affichage d’une chaine. Utilise la marque de fin de chaine pour afficher les éléments du

tableau réellement utilise*/ puts(s1); /* ou printf(”%s",s1); */

/* Lecture caractères/caractères de 10 caractères */ for (i=0; i< 10; i++) s2[i]=getchar();/* Ajout de la marque de fin de chaine */ s2[i]='\0';/* Affichage de s2 */ puts(s2);/* Affichage de s2 element/element*/ for (i=0; s2[i]!= '\0'; i++) printf("%c", s2[i]); }

Page 57: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

5757

Les chaînes de caractères

Les chaînes de caractères sont des tableaux

==> AUCUNE opération globale n’est possible : s1==s2 ne compare pas 2 chaînes s1=s2 ne copie pas s2 dans s1

Il faut utiliser les fonctions spécifiques Concaténation : strcat Copie : strcpy, strncpy Comparaison : strcmp, strncmp, strcasecmp, strncasecmp, strcoll Recherche : strstr, strchr Longueur : strlen Decoupage de la chaine en sous chaine : strtok

Toutes ces fonctions mettent le resultat dans une chaîne de caractères Attention : la chaîne recevant le résultat doit exister et doit avoir une taille

suffisante

Page 58: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

5858

Chaînes de caractères

Copie d'une chaînechar* strcpy (char* destin, char* source);

main() { char t1[256], t2[256]; printf("tapez une caine"); gets(t1);

strcpy(t2,t1); puts(t2);

strcpy("chaine", t1);}

Concaténation de 2 chaînes : char* strcat (char* destin, char * source);main() { char t1[256], t2[256];

printf("tapez 2 chaines"); gets(t1); gets(t2);

strcat(t1,t2); puts(t1);

strcat ("ceci est une chaine", t2);}

Duplication (allocation et copie) d'une chaîne Cbaine4.cchar* strdup (char* source);

main() { char t1[256], t2[256]; char* s1; :/* Pas de taille: pointeur */ gets(t1);

s1 = strdup(t1); puts(s1);

t2=strdup(t1);}

Autre exemplemain() { char t1[256], t2[256], t3[256]; gets(t1);

strcat(strcpy(t2,t1),".obj"); strcat(strcpy(t3,t1),".exe");

puts(t1); puts(t2); puts(t3);}

Page 59: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

59

Comparaison de 2 chaînesint strcmp (char* chain1, char* chain2)

Retourne : un entier négatif si chain1 inférieure à chain20 si chain1 identique à chain2un entier positif si chain1 supérieure à chain2 ordre lexicographique.

int strcasecmp (char* chain1, char* chain2) majuscules et minuscules indifférentes

Comparaison de 2 chaînes sur n octetsint strncmp(char* chain1, char* chain2, int n)/*n= Nombre de caractères à comparer */

59

Chaînes de caractères Formation/extraction dans des chaines

de caractèresint sprintf(char* s, char* format, valeurs)int sscanf(char* s, char* format, adresses) main() { char t1[256], t2[256]; int i; float x; double y;

sprintf(t1,"Valeurs %d et %f et %lf", i,x,y); puts(t1);

strcpy(t1,"1000 10.3 truc 3.14259"); sscanf(t1,"%d %f %s %lf ",&i,&x,t2,&y);

sscanf(t1, "%d %f %lf ",i,x,y) ;}

Page 60: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

6060

Chaînes de caractères

Longueur d'une chaîne unsigned strlen ( char* chaine)

Recherche d'une chaînechar* strstr (char* chain1, char* chain2)

Recherche de la chaine chain2 dans chaine1. Retourne l'adresse de la première occurrence de chaine2 dans chaine1

Recherche d'un caractèrechar* strchr (char* chain1, int n)

Recherche du caractère n dans chaine1. Retourne l'adresse de la première occurrence du caractère n dans chaine1

Page 61: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

6161

Chaînes de caractères Découpage d’une chaine en motsChar* strtok(char* str, char* separateur)

Découpe la chaine str en mots. Les séparateurs sont définis par les caractères de la chaine separateur.

#include <stdio.h>#include <string.h>main() { char t1[256], t2[256]; char* p; int i =0;/* Les separateurs sont espace, virgule, point et point virgule et d'interrogation */ strcpy(t2, " ;.,."); strcpy(t1,"Voici une chaine. Vide? Non"); /*Iniitalisation du decoupage */ p=strtok(t1, " ;.,."); while (p!=NULL) { printf("mot numero %d : %s \n",i,p); i++; /* On cherche le mot suivant */ p= strtok(NULL, " ;.,."); }}

Page 62: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

6262

Exo : Chaînes de caractères Ex1 : faire un programme qui initialise une chaine de caractères avec toutes les

lettres de l'alphabet et qui affiche la chaine obtenue. Quel caractère ne faut il pas oublier ?

Ex2 : en utilisant man 3 fgets faire un programme qui saisie un texte sur le terminal et qui l'affiche en retour

Ex3 : faire un programme qui demande le nom et le prénom à l'utilisateur et qui affiche “bonjour PRENOM NOM” en utilisant strcat.

Ex4 : faire un programme qui demande de deviner un chiffre entre 1 et 6 (tiré aléatoirement dans le programme). Lorsque le chiffre est trouvé le programme doit afficher : « il vous a fallu NOMBRE essai(s) pour trouver la solution ». Vous devez utiliser la fonction sprintf (man 3 sprintf) pour générer cette chaine.

Page 63: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

63

XIII. Entrées / sorties sur fichiers

XIII.1. Introduction

XIII.2. Ouverture et fermeture d’un fichier

XIII.3. Lecture et écriture dans un fichier texte

XIII.4. Exercice

Page 64: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

64

Pourquoi ?

Stockage des donnés dans un fichier

(nombres, caractères, …)

Acquisition de donnés nombreuses et complexes

Comment ?

Création d'un flux vers un fichier

Ouverture du fichier

Echange avec le fichier (lectures/écritures)

Fermeture du flux

XIII.1. Introduction

Page 65: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

65

Deux types de fichiers : Fichier texte, fichier binaire

Quand vous affichez un nombre sur l'écran avec printf("%d",i)

i est une variable entière, codée sur 4 octets, en base 2.

Il y a création d’une chaîne de caractères contenant les chiffres du nombre (base 10)

Si i vaut 10, la chaîne contient les 3 caractères ’1’ , ’0’ et fin de chaîne

Si i vaut 256845, la chaîne contient les 7 caractères ’2’ ,’5’ ,’6’ ,’8’ ,’4’ ,’5’ et fin de chaîne.

Ensuite, le système écrit la chaîne à l'écran.

Les nombres affichés prennent un nombre d’octets différent, chaque chiffre est codé sur un

octet

mais ils sont lisibles facilement sur n’importe quelle machine (less, more, editeur de texte,

etc..)

Dans un fichier, si il se passe la même chose, ce sont alors des fichiers texte.

L’autre solution est d’écrire directement les 4 octets composant le nombre

Tous les entiers sont alors écrits avec 4 octets, sans aucune transformation

Ce sont des fichiers binaires,

on les lit difficilement directement. Il faut utiliser la commande od, et interpréter soi-même la

sortie

XIII.1. Introduction

Page 66: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

66

Rappel : il existe deux types de fichiers :

Les fichiers texte qui contiennent des caractères

Exemple : un fichier source .c est un fichier texte

Exemple : un fichier image au format ppm est un fichier texte

Les fichiers binaires qui contiennent des données binaires

Exemple : un fichier exécutable .exe est un fichier binaire

Exemple : un fichier pdf .pdf est un fichier binaire

Exemple : un fichier image jpeg .jpg est un fichier binaire

En C, il est possible de travailler avec ces deux types de fichiers…

XIII.1. Introduction

Page 67: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

67

XIII.1. Introduction

67

En plus, sur INTEL, dans un entier, les octets de poids faible sont en tete

et ceux de poids fort en queue.

Code ascii du caractère 6, puis de 5, de 5, de 3 et de 6

Texte (n1.txt) ou binaire (n1.bin)

Page 68: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

68

Pour lire / écrire dans un fichier, il faut à chaque fois :

0. Inclure les headers nécessaires :

#include <stdlib.h>

#include <stdio.h>

1. Ouvrir le fichier avec la fonction fopen() qui renvoie un pointeur sur le fichier de

type FILE *.

2. Vérifier que l'ouverture s’est bien passé en testant la valeur du pointeur

qu'on a reçu. Si le pointeur vaut NULL, c'est que l'ouverture du fichier n'a pas

marché, dans ce cas on ne peut pas continuer (il faut afficher un message

d'erreur).

3. Si l'ouverture a marché alors on peut lire et/ou écrire dans le fichier

4. Une fois qu'on a terminé de travailler sur le fichier, il faut penser à le fermer

avec la fonction fclose().

XIII.1. Introduction

Page 69: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

69

Pour travailler avec un fichier, il faut commencer par l’ouvrir en appelant la

fonction fopen() dont le prototype est :

FILE* fopen(const char* nomDuFichier, const char* modeOuverture);

nomDuFichier : une chaine de caractères qui contient le chemin vers le fichier

a ouvrir

modeOuverture : une indication qui dit si vous voulez juste écrire dans le fichier,

juste lire dans le fichier, ou les deux à la fois

fopen() renvoie un pointeur de type FILE *.

En cas d’échec, le pointeur renvoyé vaut NULL.

ATTENTION : toujours tester si l’ouverture s’est bien passée ( le pointeur

renvoyé est non NULL).

Quand on a fini de travailler avec un fichier, il faut toujours le fermer avec fclose():

int fclose(FILE * ptrVersFichier);

XIII.2. Ouverture et fermeture d’un fichier

Page 70: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

70

Les modes d’ouverture à connaître sont :

"r" : ouverture en mode « fichier texte »

"b" : ouverture en mode « fichier binaire »

XIII.2. Ouverture et fermeture d’un fichier

Page 71: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

71

Les modes d’ouverture à connaître sont :

"r" : lecture seule. Vous pourrez lire le contenu du fichier, mais pas écrire dedans. Le fichier

doit avoir été créé au préalable.

"w" : écriture seule. Vous pourrez écrire dans le fichier, mais pas lire son contenu. Si le

fichier n'existe pas, il sera créé.

"a" : mode d'ajout. Vous écrirez dans le fichier, en partant de la fin du fichier. Vous

rajouterez donc du texte à la fin du fichier. Si le fichier n'existe pas, il sera créé.

"r+" : lecture et écriture. Vous pourrez lire et écrire dans le fichier. Le fichier doit avoir été

créé au préalable.

"w+" : lecture et écriture, avec suppression du contenu au préalable. Le fichier est donc

d'abord vidé de son contenu, et vous écrivez et lisez ensuite dedans. Si le fichier n'existe

pas, il sera créé.

"a+" : ajout en lecture / écriture à la fin. Vous écrivez et lisez du texte à partir de la fin du

fichier. Si le fichier n'existe pas, il sera créé.

XIII.2. Ouverture et fermeture d’un fichier

Page 72: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

72

int main() { FILE* filePtr =NULL ; // création du pointeur et initialisation filePtr = fopen("test.bin", "rb"); //ouverture en lecture seule, mode binaire de ./test.bin if (filePtr == NULL) { // vérification ouverture ! printf("erreur ouverture\n");

exit (-1); } // Maintenant, on peut lire dans le fichier… fclose(filePtr); // fermeture du fichier return 0;}

XIII.2. Ouverture et fermeture d’un fichier

int main() { FILE* filePtr =NULL ; // création du pointeur et initialisation filePtr = fopen("…/dossier/fichier.txt", "wt"); // ouverture en écriture seule, mode texte

// Si le fichier existe, son contenu est détruit ! if (filePtr == NULL) { // vérification ouverture ! printf("erreur ouverture\n");

exit (-1); } // Maintenant, on peut écrire dans le fichier… fclose(filePtr); // fermeture du fichier return 0;}

Page 73: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

73

Une fois que le fichier est ouvert (on dispose d’une variable de type FILE * non

nulle) avec le modeOuverture adéquat, il est possible de lire et/ou écrire dans le

fichier.

La lecture / l’écriture d’un fichier texte est très similaire à ce qui se passe quand

on lit au clavier ou écrit à l’écran. Les prototypes des principales fonctions sont:

// lecture

int fscanf(FILE *stream, const char *format, ...); //comme scanf ! Retourne le nombre de données lues

int fgetc(FILE *stream);

char * fgets(char *s, int n, FILE *stream);

// ecriture

int fprintf(FILE *stream, const char *format, ...); //comme printf ! Retourne le nombre de données écrites

int fputs(const char *s, FILE *stream);

Notes : toutes opération de lecture / écriture dans un fichier avancent dans le fichier…

XIII.3. Lecture et écriture dans un fichier texte

Page 74: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

74

Dans un fichier, les données sont organisées. C’est la notion de « format de fichier ». Pour

lire/écrire un fichier, il faut se mettre d’accord sur son format.

Le programme suivant lit un fichier contenant 3 valeurs entières, par exemple :

15 20 30 contenu du fichier test.txt (tel qu’affiché par exemple par gedit)

XIII.3. Lecture et écriture dans un fichier texte

int main() { FILE* fichier = NULL;int valeurs[3]; // Tableau ou on va stocker les 3 entiers du fichierint nbLus ;fichier = fopen("unRepertoire/test.txt", "r");if (fichier ==NULL ) { // verification erreur

printf("Impossible d'ouvrir le fichier test.txt\n");exit(-1);

}// si l’ouverture s’est bien passée…nbLus = scanf(fichier, "%d %d %d", &valeurs [0], &valeurs [1], valeurs + 2);printf( "Nombre de valeurs lues : %d\n", nbLus);printf("Les données du fichier sont : %d, %d et %d", valeurs[0], valeurs[1], valeurs[2]);fclose(fichier);return 0;

}

Page 75: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

75

Rappel : Fichier binaire : copie de la représentation mémoire Ouverture d'un fichier binaire : flag “b” dans le mode d’ouverture

lecture dans un fichier binaire

int fread(void* t, int size, int nbel, FILE *fp); lecture de nb objets de taille size à partir du flux fp range les objets lus (nb * size octets) à l'adresse de l’objet t. Cette adresse est souvent celle d'un tableau. Retourne le nombre d'objets lus ou 0 si erreur ou fin de fichier Le tableau doit être alloué et contenir assez de place

Ecriture dans un fichier binaire

int fwrite(void *t, int size, int nbel, FILE *fp); ecriture de nb objets de taille size à partir du flux fp dans l’objet t. Retourne le nombre d'objets lus ou 0 si erreur ou fin de fichier

XIII.4. Lecture et écriture dans un fichier binaire

Page 76: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

76

Dans un fichier binaire, on connait le nombre d’octets occupé par chaque donnée : c’est le nombre d’octet du type de la donnée 1 int = 4 octets, 1 double = 8 octets, ....

Accès direct à un élément possibleExemple : si on a a un fichier de double, tous les double occupent la même taille dans le fichieron sait calculer la position du i ième double par rapport au début du fichier !

Savoir où on est dans le fichier

long ftell(FILE *fp); Retourne la position courante dans le fichier, en nombre d’octets.

Se positionner dans le fichier à un octet donné

int fseek(FILE *fp, int offset, int from); Positionne la prochaine lecture/ecriture à offset octets de from Pour “from” : 0:debut du fichier, 2:fin du fichier ou 1:position actuelle)

XIII.4. Lecture et écriture dans un fichier binaire

Page 77: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

7777

Exemple : lecture de n1.bin (5 entiers) et ecriture de x+1 dans n2.binmain() { FILE* f1, *f2; int i;

int t[5];

f1=fopen("n1.bin","rb");

f2=fopen("n2.bin","wb");

if (fread(t,sizeof(*t),5,f1) <5) /* Lecture des 5 entiers */

printf("Impossible de lire 5 entiers");

else { for (i=0;i<5;i++) t[i]=t[i]+1; /* on ecrit aussi t[i]++; */

if (fwrite(t,sizeof(*t),5,f2) <5) /* ecriture des 5 entiers */

printf("Impossible d'ecrire 5 entiers");

}

fclose(f1); fclose(f2);

}

On ecrit les 5 entiers en 1 seule opération

On lit les 5 entiers en 1 seule opération,

mais il faut que t puisse contenir ces 5 entiers

XIII.4. Lecture et écriture dans un fichier binaire

Page 78: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

7878

Exemple de positionnement dans un fichier binaire avec int fseek(FILE *fp, int offset, int from);

Exemple : fichier5.cmain() {

FILE* fp; int a; /* Lecture ET ecriture */ fp=fopen("Fichier_a_lire","r+b"); fseek(fp,2*sizeof(*t),0); /* On se positionne sur le 3ième réel dans le file*/ a=16785; if (fwrite(&a,sizeof(*t),1,fp) <1) printf("Impossible d'ecrire"); /* On revient au debut du fichier */ fseek(fp,0,0); /* Lecture et affichage des nombres */ while (fread(&a,sizeof(a),1,fp) ==1) printf("%d ",a); puts("");

}}

65537

65536

127

1

Debut du fichier

123456789

16785

XIII.4. Lecture et écriture dans un fichier binaire

Page 79: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

79

Écrire un programme qui :

Ouvre un fichier "notes.bin" contenant des float

Lit tous les entiers dans un tableau

Recherche la note minimum (réutiliser la fonction de l’exercice « recherche de

minimum »

L’affiche.

XIII.4 Exercice

Page 80: 1 Projet informatique 2A Séances de soutien Francois.Portet@imag.fr Nicolas.Castagne@imag.fr Ces transparents sinspirent largement des cours 1A PET (M

8080

Exo : programme de traitement d'images

Nous utiliserons le format ppm Le programme doit être capable:

• De representer une image en memoire• D'initialiser une image • D'afficher la valeur des pixels à l'écran• De charger/écrire une image au format ppm vers/depuis un fichier ppm• D'effectuer différentes transformations : negatif, binarisation, etc.

Une image sera représentée par un grand tableau mono-dimensionel Commencez par organiser votre code en fichiers c et h Ecrivez votre makefile Definissez vos structures de données puis vos prototypes de fonctions Commencez par les fonctions les plus simples et compiler/tester regulièrement Pour les plus avancés, écrivez votre programme de façon à ce qu'il fonctionne

comme une commande du shell avec des arguments. Par ex: $ ./traiteimage negatif entree.ppm imagemodif.ppm où négatif est une option, entree.ppm est l'image à traitée et imagemodif est le

resultat du traitement