UE C avanc´e cours 1: introduction
Jean-Lou Desbarbieux et St´ephane Doncieux LI215
Licence Informatique UMPC 2013/2014
Sommaire
Introduction Pr´esentation
´Evaluation Calendrier Biblio Intro au C Types
Types simples Op´erateurs
Structures de contrˆole Fonctions
Pr´esentation du module
I Module avanc´e (niveau 200)
I Objectifs principaux :
I Gestion explicite de la m´emoire
I Structure de donn´ees autor´ef´erentielles : liste, pile, arbres
I Itin´eraire :
I Notions d’algorithmique
I Manipulation de fichiers
Pensez `a vous inscrire...
... si ce n’est pas encore fait
´Evaluation
I 60% pour l’examen final
I 40% pour le contrˆole continu
I 20% partiel
I 20% pour l’appr´eciation en TD/TME (corrections automatiques, mini-projets, appr´eciation g´en´erale)
Calendrier
I 11 semaines de cours, 11 semaines de TD/TME
I Les TD/TME commencent les jeudi et vendredi de la semaine du 9 septembre 2013
I Le dernier TD a lieu la semaine du 9 d´ecembre 2013
I Le partiel aura lieu entre le 4 novembre 2013
I L’examem aura lieu la semaine du 6 janvier 2014
Calendrier
Semaine 1.R´evisions ( ?)
I Introduction
I Types
I Expressions
I printf
I Fonctions
I Fonctions r´ecursives
I Passages de param`etres
Calendrier
Semaine 2.
I D´ecoupage d’un programme
I Compilation
I Environnement (Makefile, gcc, ddd)
I Chaˆınes de caract`eres Semaine 3.
I pointeurs
I manipulations et utilisations des pointeurs
I allocation dynamique
Calendrier
Semaines 4.
I structures
I fichiers Semaines 5.
I entr´ees/sorties
I retour sur les chaˆınes de caract`eres
Calendrier
Semaines 6.Respiration Semaine 7.Listes chaˆın´ees Semaine 8.Arbres
Semaine 9.Arbres bis
Semaine 10.Tables de hachage
Semaine 11.Ouverture et/ou r´evisions et conclusion du cours
Bibliographie et outils
I Le langage C : norme ANSI. Brian W. Kernighan & Denis M. Ritchie, Dunod
I Programmer en langage C. Claude Delannoy, Eyrolles
I C : a reference manual. Samuel P. Harbison & Guy L.
Steele Jr., Prentice Hall
I C : a software engineering approach. Peter A. Darnell &
Philip E. Margolis, Springer
I ...
Environnement : Linux.
Outils informatiques utilis´es :
I ´editeurs : emacs/vi/gvim/gedit
I compilateur : gcc
I d´ebogueur : gdb, ddd
Le Langage C : historique
I Le langage C a ´et´e invent´e en 1972 par Dennis Ritchie et Ken Thompson (AT&T Bell Laboratories) pour r´e´ecrire Unix et d´evelopper des programmes sous Unix.
I En 1978, Brian Kernighan et Dennis Ritchie publient la d´efinition classique du C dans le livre The C Programming language .
I C est une norme ANSI (ANSI-C) depuis 1989 et un
standard ISO depuis 1990, standard ´etendu en 1999 (C99) et en 2011 (C11).
I Toutes les distributions Linux fournissent des compilateurs C.
Introduction au langage C
Caract´eristiques du langage :
I imp´eratif
I bas-niveau
I (peu) typ´e
´Ecrire un message `a l’´ecran
Utiliser la fonctionint printf(const char *format, ...):
p r i n t f ( ” Bonjour , bienvenue a l ’UE LI215 annee 2009/2010!\n ” ) ; i n t n=215;
i n t an1=2010 ,an2=2011;
p r i n t f ( ” Bonjour , bienvenue a l ’UE LI%d !\n annee %d/%d ” , n , an1 , an2 ) ;
Quelques codes de format utiles : I %d: entier
I %c: caract`ere
I %s: chaˆıne de caract`eres I %f: nombre r´eel
ATTENTION : pour utiliserprintf, il faut ajouter la ligne suivante au tout d´ebut du fichier source :
#include <stdio.h>
Nous y reviendrons plus tard...
Introduction au langage C
Exemple de programme : fichier ”welcome.c”
#include<s t d i o . h>
i n t main (void){ i n t annee=2010;
i n t nUE=215;
p r i n t f ( ” Bonjour , bienvenue a l ’UE LI%d annee %d/%d !\n ” , nUE, annee , annee + 1 ) ;
return 0;
}
Compilation
gcc -o welcome welcome.c Ex´ecution
./welcome
Types
Types entiers
Type Signification Taille (o) Plage de valeurs
char Caract`ere 1 -128 `a 127
unsigned char Caract`ere 1 0 `a 255
short int Entier court 2 -32768 `a 32767
uns. short int Entier court non s. 2 0 `a 65535
int Entier 2(16 b) -32768 `a 32767
4(32 et 64 b) -2 147 483 648
`a 2 147 483 647 unsigned int Entier non sign´e 2(16 b) 0 `a 65 535
4(32 et 64 b) 0 `a 4 294 967 295
long int Entier long 4 -2 147 483 648
`a 2 147 483 647 8(64 b) -9 223 372 036 854 775 080
`a9 223 372 036 854 775 807 uns. long int Entier long non s. 4 0 `a 4 294 967 295
Types `a virgule flottante
Repr´esentation :signe×mantisse×baseexposant Plage de valeurs donn´ee pour un syst`eme Linux (non normalis´e).
Type Signification Taille (o) Plage de valeurs float Simple pr´ecision 4 +/-1.175494e-38 `a 3.402823e+38
double Double pr´ecision 8 +/-2.225074e-308 `a 1.797693e+308
long double Double pr´ec. long 12 +/-3.362103e-4932 `a 1.189731e+4932
Types `a virgule flottante
ATTENTION :les flottants sont repr´esent´es de mani`ere approch´ee. Cons´equences :
I L’associativit´e n’est plus assur´ee :a+ (b+c) = (a+b) +c
I Valeur approch´ee d’une somme et somme de valeurs approch´ees
I Tests :
f l o a t x =0.1 , y = 0 . 1 ;
i f ( x+y == 0 . 2 ) /∗ peut e t r e v r a i ou faux ∗/ . . .
Caract`eres
I il n’y a pas vraiment de type “Caract`eres”
I le type char est type entier (on peut l’utiliser pour les calculs) prenant un octet.
I un caract`ere est repr´esent´e par un entier, la
correspondance (code/caract`ere) est ´etablie par la table ASCII.Exemple :
char c= ’ a ’ ;
p r i n t f ( ” c= %c %d\n ” , c , c ) ; Donne :
c= a 97
Chaˆınes de caract`eres
Pas de type string en C mais on utilise la notation ””. Exemple : p r i n t f ( ” bonjour ” ) ;
correspond `a la d´eclaration d’un tableau de char initialis´e avec les codes ASCII (dans la section rodata).
En cas de besoin d’une variable de type chaˆıne de caract`eres, on d´eclare un tableau de char :
char message1 [ 8 ] = ” bonjour ” ; /∗ 7 l e t t r e s et ’\0 ’ a l a f i n ∗/ char message2 [ ] = ” bonjour ” ;
p r i n t f ( ”%s\n ” , message1 ) ; p r i n t f ( ”%s\n ” , message2 ) ;
Type enum´er´e
Permet de d´efinir une constante ´enum´er´ee.
Exemple :
enum mois {JAN = 1 , FEV, MAR, . . .}; enum mois m=3;
enum mois n=JAN ; i f ( m == MAR ) {
p r i n t f ( ”m=MAR\n ” ) ; }
Tableaux
Permet de stocker dans un espace m´emoire contigu¨e des
´el´ements de mˆeme type.
i n t T1 [ 3 ] ={2 , 1 , 5}; i n t T2 [ ] ={4 , 1 , 5}; i n t T2 [ ] ; impossible ! char message1 [ ] = ” bonjour ” ; char message2 [ 8 ] = ” bonjour ” ;
/∗ tableau a p l u s i e u r s dimensions ∗/
char TC[ 3 ] [ 2 ] ={ { ’ a ’ , ’ b ’},{ ’ c ’ , ’ d ’},{ ’ e ’ , ’ f ’} };
Op´erateurs
Par ordre de pr´ec´edence :
-. r´ef´erence: () [] -> .
-. unaire: ! ˜ ++ -- + - * & (type) sizeof -. arithm´etique: * / %
-. arithm´etique: + - -. d´ecalage: << >>
-. relationnels: < <= > >=
-. relationnels: == !=
-. manipulation de bits: &
-. manipulation de bits: ˆ -. manipulation de bits: | -. logique: &&
-. logique: ||
-. conditionnel: ?:
-. affectation: = += -= *= /= %= &= ˆ= |= <<= >>=
Structures de contrˆole
if
i f ( expression ) { i n s t r u c t i o n s ; }else
{ i n s t r u c t i o n s ; }
switch
switch ( expression )
{case expression−constante : i n s t r u c t i o n s ; case expression−constante : i n s t r u c t i o n s ; default : i n s t r u c t i o n s
}
ATTENTIONau break...
while
while ( expression ) {i n s t r u c t i o n s ; }
for
for ( expression1 ; expression2 ; expression3 ) {i n s t r u c t i o n s ;
} equivaut `a :
expression1 ;
while ( expression2 ) {i n s t r u c t i o n s ; expression3 ; }
do while
tr`es proche du while avec test `a la fin : do
{i n s t r u c t i o n s ; while} ( expression ) ;
perturbation du d´eroulement des boucles
I break : interrompt une boucle
I continue : passe `a l’it´eration suivante
I goto : existe, mais
INTERDIT ! !
Fonctions
Sert `a regrouper des instructions dans un mˆeme bloc.
Int´erˆet :
I Simplifier la lecture et la compr´ehension d’un programme en le d´ecoupant proprement
I Maximiser la r´eutilisation de code
Exemple
i n t main ( ) { i n t i , n=1 ,m=10;
for ( i =2; i<=m; i ++) { n∗= i ;
} }
i n t f a c t o r i e l l e (i n t m) { i n t i , n=1;
for ( i =2; i<=m; i ++) { n∗= i ;
}return n ; }i n t main ( ) {
i n t n= f a c t o r i e l l e ( 1 0 ) ; }
D´eclaration de fonctions : notion de prototype
Le prototype d’une fonction pr´ecise : 1. la valeur de retour
2. le nom de la fonction 3. le type des arguments Exemples :
i n t f a c t o r i e l l e (i n t ) ;
f l o a t a i r e r e c t a n g l e (f l o a t l ,f l o a t d ) ;
Valeur de retour
I De type quelconquesauf tableau....
I valeur renvoy´ee par l’instructionreturn i n t f a c t o r i e l l e (i n t m) {
i n t i , n=1;
i f (m==0) { return 1;
}for ( i =2; i<=m; i ++) { n∗= i ;
}return n ; }
Arguments
I De type quelconque.
I Dans un prototype, les identificateurs de variable n’ont aucune signification pour le compilateur (mais peuvent faire comprendre au lecteur `a quoi servent les
arguments...).
I
ATTENTION au cas des tableaux :
I Sp´ecifier la taille d’un tableau pass´e en argument ne sert `a rien, le compilateur ne la regarde mˆeme pas ...
I Sauf dans le cas d’un tableau `a plusieurs dimensions !
I Il n’y a aucun moyen de connaˆıtre la taille du tableau dans la fonction. Elle doit ˆetre d´efinie comme variable globale ou pass´ee en argument !
I Explications plus tard...
Port´ee d’une d´eclaration
Comme pour une variable...
Cas 1 :
i n t f (i n t ) ; i n t g (i n t i ) {
/∗ f est connue ∗/ }i n t f (i n t i ) {
. . .
}i n t h (i n t i ) {
/∗ f est connue ∗/ }
Cas 2 :
i n t g (i n t i ) {
/∗ f n ’ est pas connue ∗/ }i n t f (i n t ) ;
i n t h (i n t i ) {
/∗ f est connue ∗/ }i n t f (i n t i ) {
. . . }
Le ”type” void
1. Lorsqu’une fonction ne doit pas renvoyer de valeur.
Exemple :void afficher resultats(float f[10]);
Peut ˆetre vu comme une proc´edure.
2. Lorsqu’une fonction ne prend pas d’arguments.
Exemple :void effacer ecran(void);
Peut se d´eclarer aussi :void effacer ecran();
Passage de param`etres
Passage par valeur void f (i n t n ) {
n=n+1;
}i n t main (void) { i n t i =2;
p r i n t f ( ” 1: i=%d ” , i ) ; f ( i ) ;
p r i n t f ( ” 2: i=%d ” , i ) ; }
Donne le r´esultat suivant : 1: i =2
2: i =2
Comment faire si on veut que les modifications r´ealis´ees dans la fonction ne soient pas perdues ?→r´eponse plus tard ! ATTENTION au cas des tableaux :ils ne sont pas transmis par valeur... Pourquoi ?→r´eponse plus tard !
Fonctions de la libc
Beaucoup de fonctions `a connaˆıtre : gestion des fichiers, des chaˆınes de caract`eres, ...
I retenir dans un premier temps le nom uniquement
I faire des fiches ou savoir retrouver rapidement
l’information dans un livre (droit aux documents pendant partiel et examen !)
I sur ordinateur, dans un terminal, taper :
man 3 <nom de fonction>(touche ’q’ pour sortir)
Exemple
Pr´esentation du probl`eme
Construction d’une biblioth`eque
I besoin de planches de longueur vari´ee (largeur unique)
I planches vendues dans le commerce de longueur unique : 2 m`etres
I Probl`eme : combien de planches acheter pour pouvoir couper toutes les planches souhait´ees ?
3 2 1
Algorithme choisi
Hypoth`ese simplificatrice : 3 planches maximum `a d´ecouper par planche du commerce.
Tant qu’il reste des planches `a d´ecouper Initialiser max `a 0
Pour toutes les combinaisons de 3 planches `a d´ecouper Est-ce qu’il reste des planches de ces longueurs `a couper ?
Est-ce que la longueur est inf´erieure `a 2m Si la longueur est sup´erieure au max, on met `a jour le max
Fin pour
Mise `a jour du nombre de planches restantes Afficher r´esultat
Fin tant que
Algorithme choisi (2
emeversion)
Calcul par r´ecurrence. Fonction r´ecurrente utilis´ee :
Si la longueur restante est trop petite: on arrˆete S’il ne reste plus de planches: on arrˆete
Pour toutes les planches restantes Longueur restante=Appel recursif
Si Longueur restante<Min longueur restante On enregistre le nouveau min
On renvoie le min.
UE C avanc´e
cours 2: d´ecoupage, compilation et d´ebogage et chaˆınes de caract`eres
Jean-Lou Desbarbieux et St´ephane Doncieux UMPC 2013/2014
Sommaire
D´ecoupage d’un programme et compilation
Outils
Chaˆınes de caract`eres
D´ecoupage d’un programme
.h, .c : fichiers de source multiples
I Le code peut ˆetre divis´e entre plusieurs fichiers sources disctincts qui ne seront assembl´es que dans la derni`ere
´etape de cr´eation d’un ex´ecutable.
I Pour pouvoir utiliser des fonctions disponibles dans d’autres fichiers, on doit d´efinir la signature de la fonction que l’on souhaite r´eutiliser
I Pour pouvoir utiliser des variables d´efinies dans d’autres fichiers, il faut d´eclarer le type et le nom de la variable pr´ec´ed´es du mot cl´e extern
I Ces d´eclarations de variables et de fonctions peuvent ˆetre regroup´ees dans unfichier header(.h). Ces headers sont ensuite inclus dans tous les fichiers sources grˆace `a la macro#include
.h, .c : exemple
Fichier mes fonctions.h :
extern f l o a t ma variable ; i n t ma fonction1 (int, f l o a t) ; void ma fonction2 (f l o a t, char[ 1 0 ] ) ;
Fichier mes fonctions.c :
f l o a t ma variable = 1 2 . ;
i n t ma fonction1 (int, f l o a t) { . . .
}void ma fonction2 (f l o a t, char[ 1 0 ] ) { . . .
}
Fichier
mon programme.c, utilisant les fonctions d´efinies dans
mes fonctions.c :
#include ” mes fonctions . h ” i n t main ( ) {
i n t i =0 , j ;
f l o a t f =ma variable ; j =ma fonction1 ( i , f ) ; . . .
}
compilation, macros et pr´eprocesseur
Les ´etapes permettant de passer d’un fichier source `a un executable :
I Traitement de chaque fichier source ind´ependamment :
I pr´etraitement : gestion des macros et autres directives au preprocesseur
I compilation : transformation du source obtenu en un fichier objet
I ´Edition des liens entre les fichiers objets pour g´en´erer la biblioth`eque ou l’ex´ecutable.
compilation, macros et pr´eprocesseur : exemple
Compilation de l’exemple pr´ec´edent :
I Un header : mes fonctions.h
I Deux fichiers sources : mes fonctions.c, mon programme.c 1. preprocessing et compilation des sources :
gcc -c -o mes fonctions.o mes fonctions.c gcc -c -o mon programme.o mon programme.c 2. ´edition des liens :
gcc -o mon programme mon programme.o mes fonctions.o
(pas de traitement `a faire sur le header, il sera inclus dans les fichiers .c par la macro#includepar le pr´eprocesseur)
compilation, macros et pr´eprocesseur : macros
Intructions ex´ecut´ees avant compilation.
I #defineassociation d’une ´etiquette `a une valeur
I #includeinclusion d’un fichier
I #ifdef ou#ifndef ...
#endif
Qualifieurs : extern
I Indique au compilateur qu’une variable a ´et´e d´eclar´ee dans un autre fichier source
I Unicit´e de la variable : pas de nouvelle r´eservation d’espace m´emoire.
Qualifieurs : const
D´eclaration d’une variable constante : const <type> <nom de variable>
Exemple :
const i n t i =3;
const f l o a t x =2.∗3.1415926;
Port´ee des variables
I Variables globales : partout apr`es leur d´efinition
I Si pr´ec´ed´ee deextern: d´eclar´ee effectivement dans un autre fichier, mais peut ˆetre ensuite manipul´ee comme si d´ecrite dans le mˆeme fichier
I Variables locales : de leur d´eclaration `a la fin du bloc.
Outils
GCC
Pr´eprocesseur, compilateur, ´editeur de lien selon les options.
gcc [options] source1.c source2.c...
Options couramment utilis´ees :
I -c: ne pas faire l’´edition de lien
I -o fichier sortie: nom du fichier de destination (fichier .o ou ex´ecutable selon les cas). Si non sp´ecifi´e, a.outpour un ex´ecutable,source.opour un fichier objet.
I -Wall: affiche tous les warnings
I -g: inclure les informations de debogage Pour information :
I -E: ne fait que le pr´etraitement et envoie le r´esultat sur la sortie standard.
D´eboggage : GDB &DDD
I Le programme doit ˆetre compil´e avec l’option-g
I dddinterface graphique pourgdb
I Permet d’ex´ecuter pas `a pas.
I Permet de poser des points d’arrˆet.
I Permet d’observer les variables.
D´eboggage m´emoire : electricFence & valgrind
ElectricFence
I Biblioth`eque remplac¸ant les fonctions C de gestion de la m´emoire
I Objectifs : faciliter la d´etection de
I d´ebordements en m´emoire
I d’utilisation de m´emoire lib´er´ee
I Utilisation :gcc -lefence -o monprog monprog.c Valgrind
I Logiciel permettant (entre autres) de v´erifier l’utilisation de la m´emoire :
I D´etecte :
I l’utilisation de variables non initialis´ees
I l’utilisation de m´emoire lib´er´ee
I les fuites m´emoires
I Utilisation :valgrind ./monprog
Makefile
`A quoi c¸a sert : simplifier la compilation, prendre en compte automatiquement les d´ependances...
Exemple de makefile
a l l : mon programme
mes fonctions . o : mes fonctions . h mes fonctions . c gcc −c−o mes fonctions . o mes fonctions . c mon programme . o : mon programme . c mes fonctions . h
gcc −c −o mon programme . o mon programme . c mon programme : mon programme . o mes fonctions . o
gcc −o mon programme mon programme . o mes fonctions . o clean :
rm −f ∗. o mon programme
Chaˆınes de caract`eres
Chaˆınes de caract`eres : repr´esentation en m´emoire
I Dans un tableau, termin´e par un
’\0’
I Exemple :
char nom [ ] = ” david ” ; char nom2[ 7 ] = ” g o l i a t h ” ;
/∗ i l manque une case pour ’\0 ’ ∗/ char nom3 [ ] = ” david\0 g o l i a t h ” ;
p r i n t f ( ”nom2=%s\n ” ,nom2 ) ; /∗ r e s u l t a t ? ∗/ p r i n t f ( ”nom3=%s\n ” ,nom3 ) ; /∗ r e s u l t a t ? ∗/
Quelques fonctions utiles : strlen
#include <s t r i n g . h>
s i z e t s t r l e n (const char ∗s ) ;
Renvoie la longueur d’une chaˆıne de caract`eres.
Remarque : le typechar *correspond `a un tableau surchar.
Quelques fonctions utiles : strcmp
#include <s t r i n g . h>
i n t strcmp (const char ∗s1 , const char ∗s2 ) ; i n t strncmp (const char ∗s1 , const char ∗s2 ,
s i z e t n ) ;
Comparaison entre chaˆınes de caract`eres.
La valeur de retour est :
I 0 si les deux chaˆınes sont ´egales
I n´egative si s1 arrive avant s2
I positive sinon
Quelques fonctions utiles : strcpy
#include <s t r i n g . h>
char ∗s t r c p y (char ∗dest , const char ∗src ) ; char ∗strncpy (char ∗dest , const char ∗src ,
s i z e t n ) ;
Copie entre deux chaˆınes de caract`eres.
Renvoie un pointeur sur dest.
UE C avanc´e cours 3: pointeurs
Jean-Lou Desbarbieux et St´ephane Doncieux UMPC 2013/2014
Sommaire
D´eclaration
D´eclaration et initialisation
Exemples d’utilisation des pointeurs Le pointeur NULL
Remarques
Manipulations d’un pointeur
Manipulation directe des pointeurs Manipulation de la donn´ee point´ee Affectation entre pointeurs
Tableaux & Pointeurs Allocation
Vous avez dit pointeurs ?
Lesvariablesutilis´ees par un programme sont stock´ees en m´emoire `a uneadressedonn´ee.
Lespointeurspermettent de manipuler ces adresses directement. Ce sont des variables qui vont contenir une adresse m´emoire.
Dans quel but ? Exemples d’utilisation :
I modifier la valeur d’un param`etre d’une fonction
I allouer de la m´emoire dynamiquement
I cr´eer des structures complexes, autor´ef´erentes (listes chaˆın´ees)
I ...
Exemple
i n t i =2 , j =36 ,k =124;
i n t ∗l =& i ; 2
36 124 0x1234 0x1234
0x1238 0x123C 0x1240
i j k l Dans cet exemple, l contient l’adresse de la variable i.
D´eclaration et initialisation
I D´eclaration :on ajoute “*” au typede la donn´ee point´ee.
Exemples :int *i; char *c;
I L’adresse d’une variable est r´ecup´er´ee grˆace `a l’op´erateur
“&”. Exemple : i n t i =2;
i n t ∗l ; /∗ l est un p o i n t e u r sur e n t i e r ∗/ l =& i ; /∗ l p o i n t e sur i ∗/
I La valeur stock´ee en m´emoire `a l’adresse indiqu´ee par un pointeur peut ˆetre r´ecup´er´ee grˆace `al’op´erateur “*” (on parle ded´er´ef´erenciation). Ex :
i n t i =2;
i n t ∗l =& i ; /∗ l est un p o i n t e u r sur i ∗/
∗l =3; /∗ l a v a l e u r de i passe a 3 ∗/
Exemple : passage de param`etres `a une fonction
Passage par valeur void f (i n t n ) {
n=n+1;
}i n t main (void) { i n t i =2;
p r i n t f ( ” 1: i=%d ” , i ) ; f ( i ) ;
p r i n t f ( ” 2: i=%d ” , i ) ; }
Donne le r´esultat suivant :
1: i =2 2: i =2
Exemple : passage de param`etres `a une fonction
Passage par r´ef´erence void f (i n t ∗n ) {
∗n=∗n+1;
}
i n t main (void) { i n t i =2;
p r i n t f ( ” 1: i=%d ” , i ) ; f (& i ) ;
p r i n t f ( ” 2: i=%d ” , i ) ; }
Donne le r´esultat suivant :
1: i =2 2: i =3
Le pointeur NULL
NULL (ou 0) est une valeur sp´eciale pour un pointeur.
C’est une valeur, par d´efinition, qui ne pointe pas sur une zone m´emoire valide.
Peut-ˆetre utilis´e pour indiquer qu’un pointeur n’est pas encore initialis´e.
Exemple d’utilisation : i n t ∗p=NULL ;
. . .
i f( p==NULL) {
p r i n t f ( ” p n ’ a pas ete i n i t i a l i s e !\n ” ) ; }
Les pointeurs de pointeurs de ...
i n t i =3;
i n t ∗j =& i ; i n t ∗∗k=& j ;
3 0x1234 0x1238 0x1234
0x1238
i j k k est un pointeur de pointeur sur entier. Il contient donc l’adresse d’une variable contenant l’adresse d’une variable de type int.
Il est ´egalement possible de d´efinir des pointeurs de pointeurs de pointeurs sur une type donn´e et ainsi de suite...
Astuce
Pour retrouver `a quoi correspond un pointeur, il fautlire les
´el´ements composant sa d´eclaration de droite `a gauche:
I int *iest un pointeur (*) sur entier (int).
I const int *iest un pointeur (*) sur entier constant (const int).
I char **iest un pointeur sur un pointeur sur char
Types
I Les pointeurs sonttyp´es: i n t i =3;
f l o a t ∗p=& i ; /∗ genere un warning ∗/
I Pointeur g´en´erique :void *.
I pointeur non typ´e
I ne peut ˆetre d´er´ef´erenc´e
I doit ˆetre cast´e en un type d´efini i n t i =3;
void ∗p=& i ; i n t ∗q=p ;
∗p=4; /∗ i n t e r d i t ∗/
∗q=4; /∗ a u t o r i s e ∗/
Addition/soustraction d’un entier `a un pointeur
i n t i =3;
i n t ∗p=& i ; p=p+1;
ATTENTION : en pratique, lorsque l’on faitp=p+1on ajoute sizeof(int) `a p...
Sur IA32, on ajoute en fait 4 `a p. Si p est un pointeur sur double,p=p+1incr´emente p de 8.
Simplifie l’utilisation des pointeurs,p+1pointe sur l’´el´ement directement apr`es celui point´e par p, sans avoir besoin de se pr´eoccuper de sa taille.
Manipulation de la donn´ee point´ee
Le pointeur d´er´ef´erenc´e peut se manipuler comme la donn´ee point´ee :
i n t i =3;
i n t ∗j =& i ;
(∗j ) + + ; /∗ incremente i de 1 ∗/
∗( j + + ) ; /∗ incremente j de 1 ∗/
∗j = ∗j / 10 /∗ d i v i s e i par 10 ∗/
Affectation entre pointeurs
i n t i =3;
i n t ∗j =& i ; i n t ∗k ; k= j ;
Il est possible d’affecter `a un pointeur la valeur d’un autre pointeur de mˆeme type.
Tableaux & Pointeurs
Une r´ef´erence `a un tableau est ´equivalente `a un pointeur constant sur son premier ´el´ement !
i n t a [ 1 0 ] ; i n t ∗b=a ;
a⇐⇒b⇐⇒&a[0]⇐⇒&b[0]
Exception :
I sizeof(a)6=sizeof(&a[0]). sizeof(a) rend la taille du tableau, soit 10*sizeof(int) alors que sizeof(&a[0]) rend la taille d’un pointeur sur entier.
Tableaux & Pointeurs
Cons´equence : on ne peut pas connaitre la taille d’un tableau pass´e par argument
i n t f (i n t a [ 1 0 ] ) { unsigned i n t i ; for ( i =0; i<10; i ++) {
a [ i ]+=1;
} }
i n t main (void) {
i n t b [ 5 ] ={0 , 0 , 0 , 0 , 0}; f ( b ) ; /∗POSSIBLE ! !∗/
/∗ e r r e u r non detectee . . . ∗/ }
int f(int a[10])est
´equivalent `aint f(int *a). La taille sp´ecifi´ee n’est pas prise en compte !
Si la taille doit ˆetre connue dans la fonction, il faut la passer en param`etre.
Tableaux & Pointeurs
La notation avec [] est ´equivalente `a l’addition de l’indice : i n t a [ 1 0 ] ;
i n t ∗b=a ;
a[2]⇐⇒ ∗(a+2)⇐⇒b[2]⇐⇒ ∗(b+2)
Allocation dynamique
I Les pointeurs sont utilis´es pour manipuler la m´emoire
I Ils peuvent manipuler des donn´ees d´ej`a allou´ees
I Est-il possible d’allouerdynamiquementde la m´emoire ?
I Exemple d’utilisation : d´eclaration d’un tableau de taille variable
allocation de la m´emoire : malloc
#include <stdlib.h>
void *malloc(size t taille)
I Argument :tailleen octets
I size t: entier non sign´e
I Valeur renvoy´ee de typevoid *
I D´eclar´e dansstdlib.h
I ATTENTION :la zone m´emoire allou´ee n’est pas initialis´ee...
malloc : exemple
Allocation d’un tableau de taille donn´ee par une variable : i n t ∗allouerTableau (i n t t a i l l e ) {
i n t ∗tab =(i n t ∗) malloc ( t a i l l e∗sizeof(i n t ) ) ; i f ( tab==NULL) {
p r i n t f ( ” Probleme d ’ a l l o c a t i o n\n ” ) ; return NULL ;
}unsigned i n t i ;
for ( i =0; i<t a i l l e ; i ++) { tab [ i ] = 0 ;
/ / ou de facon e q u i va l e n t e : / / ∗( tab+ i )=0
}return tab ; }
autres fonctions d’allocation : realloc
#include <stdlib.h>
void *realloc(void *adr, size t taille)
I Changement de taille d’un emplacement m´emoire pr´ec´edemment allou´e
I La nouvelle taille esttaille, elle peut ˆetre inf´erieure ou sup´erieure
I Les octets conserv´es de l’ancien tableau sont identiques
I L’emplacement en m´emoire peut changer
I Exemple :
i n t n=10 ,m, ∗tab=malloc ( n∗sizeof(i n t) ) , ∗tab2 ; . . . /∗ code i n i t i a l i s a n t m ∗/
tab2= r e a l l o c ( tab ,m) ; i f( ! tab2 ) {
p r i n t f ( ” Erreur de r e a l l o c a t i o n\n ” ) ; e x i t ( 1 ) ;
}tab=tab2 ; . . .
Lib´eration de la m´emoire : free
#include <stdlib.h>
void free(void *adr)
I Lib´eration de la m´emoire
I Lib`ere, d’un coup, un bloc pr´ec´edemment allou´e par malloc, calloc ou realloc
I Il n’est pas possible de ne lib´erer la m´emoire que partiellement
I free(NULL)ne fait rien
I Lib´erer deux fois de suite la m´emoire conduit `a un comportement ind´etermin´e : g´en´eralement un seg fault...
Copie de blocs m´emoire : memcpy
#include <string.h>
void *memcpy(void *restrict s1, const void
*restrict s2, size t n);
I Copienoctets `a partir de l’adresse contenue dans le pointeurs2vers l’adresse stock´ee danss1
I Remarque :s2doit pointer vers une zone m´emoire de taille suffisante.
I la fonction renvoie la valeur des1
UE C avanc´e
cours 4: Fichiers et structures
Jean-Lou Desbarbieux et St´ephane Doncieux UMPC 2013/2014
Sommaire
Fichiers
Structures
Fichiers : principes
I Fichiers manipul´es au travers d’une structure (FILE)
I Cette structure est initialis´ee par une fonction d’ouverture de fichier, et est d´etruite par une fonction defermeturede fichier
Exemple :
#include<s t d i o . h>
i n t main ( ) {
FILE ∗m o n f i c h i e r ; i n t x , y , z ;
i f ( ( m o n f i c h i e r = fopen ( ” f i c h i e r . t x t ” , ” r ” ))==NULL) { p r i n t f ( ” Erreur a l ’ ouverture de f i c h i e r . t x t\n ” ) ; return 1;
}f s c a n f ( m o n f i c h i e r , ”%d %d %d ” ,&x ,&y ,& z ) ; p r i n t f ( ” Valeurs lues : %d %d %d\n ” , x , y , z ) ; f c l o s e ( m o n f i c h i e r ) ;
return 0;
}
Ouverture d’un fichier : fopen/fclose
I FILE *fopen(const char *nom fichier, const char *mode): ouvre le fichier selon le mode indiqu´e (“r”,
“w”, “a”,...)
I int fclose(FILE *flux): vide ´eventuellement le tampon de lecture/´ecriture, lib`ere la m´emoire
correspondante et ferme le fichier
Lecture/´ecriture format´ee
I int fscanf(FILE *flux,const char *format, ...): lecture de donn´ees `a partir d’un format depuis un fichier
I int fprintf(FILE *flux, const char
*format,...): ´ecriture de donn´ees selon un format sp´ecifi´e dans un fichier
I int fputc(int c, FILE *flux): ´ecrit un caract`ere dans un fichier
I int fgetc(FILE *flux): lit un caract`ere depuis un fichier
I char * fgets(char *buffer, int n, FILE
*flux): lit une ligne dans un fichier (longueur maximale=n)
Exemple
#include <s t d i o . h>
i n t main ( ) { FILE ∗src , ∗dest ; i n t car ;
i f ( ( src = fopen ( ” source . t x t ” , ” r ” ))==NULL) { p r i n t f ( ” Erreur a l ’ ouverture de source . t x t\n ” ) ; return 1;
}i f ( ( dest= fopen ( ” d e s t i n a t i o n . t x t ” , ”w” ))==NULL) { p r i n t f ( ” Erreur a l ’ ouverture de d e s t i n a t i o n . t x t\n ” ) ; return 1;
}car = f g e t c ( src ) ; while ( car !=EOF) {
f p u t c ( car , dest ) ; car = f g e t c ( src ) ; }f c l o s e ( src ) ; f c l o s e ( dest ) ; return 0;
}
Lecture d’un fichier ligne `a ligne
Lecture d’un fichier contenant 3 entiers par ligne avecfgetset sscanf
#include<s t d i o . h>
#define LONGUEURLIGNE 128 i n t main ( ) {
FILE ∗src ;
i f ( ( src = fopen ( ” source . t x t ” , ” r ” ))==NULL) { p r i n t f ( ” Erreur a l ’ ouverture de source . t x t\n ” ) ; return 1;
}char b u f f e r [LONGUEURLIGNE ] ;
char ∗res= f g e t s ( b u f f e r , LONGUEURLIGNE, src ) ; i n t a , b , c ;
while ( res != NULL) {
sscanf ( b u f f e r , ” %d %d %d ” ,&a , &b , &c ) ; res= f g e t s ( b u f f e r , LONGUEURLIGNE, src ) ;
p r i n t f ( ” Lu l e s e n t i e r s a=%d , b=%d , c=%d\n ” ,a , b , c ) ; }
f c l o s e ( src ) ; return 0;
}
La lecture binaire
s i z e t fread (void ∗p t r , s i z e t size , s i z e t nmemb, FILE ∗stream ) ;
La fonction fread lit nmemb ´el´ements de donn´ees, chacun d’eux repr´esentant size octets de long, depuis le flux point´e par stream, et les stocke `a l’emplacement point´e par ptr.
Les donn´ees peuvent ˆetre de type quelconque,ptrpeut ˆetre un pointeur sur un int, un float, une struct... Il peut ˆetre un tableau de donn´ees d’un type quelconque.
ATTENTION: il n’y a aucune esp`ece de format, les donn´ees
´ecrites dans le fichier sont recopi´ees directement en m´emoire.
La lecture binaire
FILE ∗f i c h i e r ;
/∗ ouverture du f i c h i e r ∗/
i f ( ( f i c h i e r =fopen ( n o m f i c h i e r , ” rb ” ))==NULL) {
p r i n t f ( ” Erreur l o r s de l a l e c t u r e de %s\n ” , n o m f i c h i e r ) ; e x i t ( 1 ) ;
}i n t i ;
i n t n b l u = fread (& i , sizeof(i n t) , 1 , f i c h i e r ) ; i f ( n b l u == 1) {
p r i n t f ( ‘ ‘ Lecture OK\n ’ ’ ) ; }else {
p r i n t f ( ‘ ‘ Lecture KO\n ’ ’ ) ; }
L’´ecriture binaire
s i z e t f w r i t e (const void ∗p t r , s i z e t size , s i z e t nmemb, FILE ∗stream ) ;
La fonctionfwrite ´ecritnmemb ´el´ements de donn´ees, chacun d’eux repr´esentantsizeoctets de long, dans le flux point´e par stream, apr`es les avoir lus depuis l’emplacement point´e par ptr.
L’´ecriture binaire
i n t tab [ 1 0 ] ;
/∗ I n i t i a l i s a t i o n de tab ∗/ . . .
/∗ ouverture du f i c h i e r ∗/
i f ( ( f i c h i e r =fopen ( n o m f i c h i e r , ”wb” ))==NULL) {
p r i n t f ( ” Erreur l o r s de l ’ e c r i t u r e de %s\n ” , n o m f i c h i e r ) ; e x i t ( 1 ) ;
}
/∗ ATTENTION : pas de ’& ’ car tab est un tableau ! ∗/ f w r i t e ( tab ,sizeof(i n t) , 1 0 , f i c h i e r ) ;
/∗ fermeture du f i c h i e r ∗/
f c l o s e ( f i c h i e r ) ;
Structures
Vous avez dit structures ?
I Les structures sont destypes compos´esd´efinis par le programmeur.
I Les structures regroupent `a l’int´erieur d’une mˆeme variable des variabless´emantiquement li´ees. Exemple : une fiche d’un r´epertoire contient le nom, le pr´enom, l’adresse, le num´ero de t´el´ephone...
Exemple simple
Point dans un espace 3D : struct p o i n t {
f l o a t x ; f l o a t y ; f l o a t z ; };
struct p o i n t p1 ; p1 . x = 1 2 . 0 ; p1 . y = 2 4 . 2 ; p1 . z = 4 2 . 0 ;
D´eclaration
struct <nom de type>
{ type1 var1 ; type2 var2 ;
. . .
typen varn ; };
Utilisation
I D´eclaration d’une variable du type d´efini
struct <nom de type> <nom de variable>;
Exemple :struct point p1;
struct point *pp1;
ATTENTION,il faut bien pr´eciser le mot-cl´estruct
I R´ecup´eration d’un champ : var.<nom du champ>
Exemple :p1.x=44.20;
pvar-><nom du champ>
Exemple :pp1->x=44.20;
typedef
I D´efinition de types synonymes. Exemple : typedef i n t e n t i e r ;
e n t i e r i =3;
I cas des tableaux :
typedef i n t vect [ 3 ] ; vect v1 , v2 ;
I cas des struct
typedef struct p o i n t {i n t x ;i n t y ;} p o i n t ; p o i n t A ;
Espaces de nom
I On ne peut pas utiliser deux fois un mˆeme nom dans une structure :
struct bidon { i n t var1 ;
f l o a t var1 ; /∗ INTERDIT ∗/ };
I Par contre il n’y a pas collision entre les noms de diff´erentes structures :
struct f i c h e { . . .
unsigned i n t i d ; . . .
};
struct c l i e n t { . . .
unsigned i n t i d ; . . .
};
Initialisation
Initialisation semblable `a celle de tableaux : typedef struct p o i n t {
f l o a t x ; f l o a t y ; f l o a t z ; } p o i n t ;
p o i n t p={ 1.0 , 2.0 , 3 . 0};
Affectation entre structures
Possibilit´e de copier directement une structure par affectation : p o i n t A={12 ,4 ,5},B ;
/∗ p o i n t equiv . a s t r u c t p o i n t ∗/
B=A ; ´equivalent `a B . x=A . x ;
B . y=A . y ; B . z=A . z ; ATTENTIONaux pointeurs ...
Tableaux et structures
Tableaux dans une structure
struct personne { char nom [ 3 0 ] ; char prenom [ 3 0 ] ;
unsigned i n t nb commande ; unsigned i n t n commande [ 1 0 ] ; };
. . .
struct personne c l i e n t 1 ={” Dupond ” , ” A l b e r t ” ,0 , {0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0}};
. . .
c l i e n t 1 . n commande [ c l i e n t 1 . nb commande ] = 3406;
c l i e n t 1 . nb commande++;
Tableaux de structure
struct personne c l i e n t s [ 1 0 0 ] ; . . .
c l i e n t s [ 2 0 ] . n commande [ c l i e n t s [ 2 0 ] . nb commande ] = 4807;
c l i e n t s [ 2 0 ] . nb commande++;
Structures dans une structure
struct date {
unsigned char j o u r ; unsigned char mois ; unsigned i n t annee ; };
struct personne { char nom [ 3 0 ] ; char prenom [ 3 0 ] ;
struct date date naissance ; };
. . .
struct personne c l i e n t ={” Dupond ” , ” A l b e r t ” , {24 ,5 ,1950}};
i f ( c l i e n t . date naissance . annee>1940) { . . .
}
Structure et pointeurs
typedef struct personne { char ∗ nom ;
char ∗ prenom ; } personne ;
personne p1 , p2 ;
p1 . nom = (char ∗) malloc ( 7 + 1 ) ; s t r c p y ( p1 . nom, ” Deckard ” ) ; p1 . prenom = strdup ( ” Rick ” ) ;
/ / strdup e q u i v a l e n t a malloc puis s t r c p y p2=p1 ; / / cela f a i t quoi ?
p r i n t f ( ” p2 . nom=%s p2 . prenom=%s\n ” , p2 . nom, p2 . prenom ) ; f r e e ( p1 . nom ) ;
f r e e ( p1 . prenom ) ;
/ / Quel est l e r e s u l t a t de cet appel ?
p r i n t f ( ” p2 . nom=%s p2 . prenom=%s\n ” , p2 . nom, p2 . prenom ) ;
UE C avanc´e cours 5: Entr´ees/sorties
Jean-Lou Desbarbieux et St´ephane Doncieux UMPC 2013/2014
Sommaire
Chaˆınes de caract`eres : le retour...
Entr´ees/sorties
Chaˆınes de caract`eres : le retour...
Retour sur strlen
s i z e t m y s t r l e n (const char ∗s ) {
}
Retour sur strcpy
char ∗my strcpy (char ∗dest , const char ∗src ) {
}
Quelques autres fonctions utiles : strdup
#include <s t r i n g . h>
char ∗strdup (const char ∗s1 ) ;
Alloue une nouvelle chaˆıne de caract`ere de longueur
strlen(s1)+1et l’initialise avec la chaˆınes1(´equivalent `a malloc+strcpy)
ATTENTION : il faut bien penser `a lib´erer par unfreela chaˆıne de caract`eres ainsi cr´e´ee.
Quelques autres fonctions utiles : strcat
#include <s t r i n g . h>
char ∗s t r c a t (char ∗dest , const char ∗src ) ; char ∗s t r n c a t (char ∗dest , const char ∗src ,
s i z e t n ) ;
Ajoute la chaˆıne de caract`ere src `a la fin de dest.
Renvoie un pointeur sur dest.
Entr´ees/sorties
Comment faire ...
... pour ´ecrire des donn´ees `a l’´ecran : m´ethode 1
I utiliser une fonction transformant les variables `a ´ecrire directement en chaˆınes de caract`eres (printf) m´ethode 2
I ´ecrire caract`eres par caract`eres
Comment faire ...
... pour lire des donn´ees tap´ees depuis le clavier : m´ethode 1
I utiliser une fonction de lecture traduisant directement la chaˆıne lue dans le(s) type(s) souhait´e(s)
m´ethode 2
I lire caract`eres par caract`eres
Comment faire ...
... pour lire des donn´ees depuis un fichier : m´ethode 1
I ouvrir le fichier
I utiliser une fonction de lecture traduisant directement la chaˆıne lue dans le(s) type(s) souhait´e(s)
I fermer le fichier m´ethode 2
I ouvrir le fichier
I utiliser une fonction de lecture caract`eres par caract`eres
I fermer le fichier m´ethode 3
I ouvrir le fichier
I utiliser une fonction de lecture copiant les donn´ees brutes depuis le fichier vers la m´emoire (lecture dite binaire)
I fermer le fichier
Comment faire ...
... pour ´ecrire des donn´ees depuis un fichier : m´ethode 1
I ouvrir le fichier
I utiliser une fonction d’´ecriture transformant les variables `a
´ecrire directement en chaˆınes de caract`eres
I fermer le fichier m´ethode 2
I ouvrir le fichier
I utiliser une fonction d’´ecriture caract`eres par caract`eres
I fermer le fichier m´ethode 3
I ouvrir le fichier
I utiliser une fonction d’´ecriture copiant la m´emoire vers le fichier sans transformation (´ecriture dite binaire)
I fermer le fichier
Retour sur printf
I Affichage d’un message `a l’´ecran.
I Renvoie un entier : nombre de caract`eres ´ecrits
I Message sp´ecifi´e par unformatcontenant descodes de format
I Exemples :
double p i =3.141592653589793;
p r i n t f ( ” Pi : %f\n ” , p i ) ;
p r i n t f ( ” Pi avec 2 decimales : %.2 f , 4 decimales : %.4 f\n ” , pi , p i ) ;
p r i n t f ( ” 2 Pi : %f\n ” ,2∗p i ) ;
scanf
I Lecture de donn´ees tap´ees au clavier
I Renvoie un entier : nombre d’entit´es lues
I Exploite ´egalement un format avec des codes de format f l o a t x ;
i n t n ;
scanf ( ”%f %d ” ,&x ,&n ) ;
scanf
ATTENTION: lors de la lecture, seul ce qui est demand´e est lu ! Exemple pathologique :
char c ;
scanf ( ”%c ” ,&c ) ;
p r i n t f ( ” Char l u : %c\n ” , c ) ; scanf ( ”%c ” ,&c ) ;
p r i n t f ( ” Char l u : %c\n ” , c ) ; Que fait le programme ?
Lecture d’un seul caract`ere ! Le 2eme ´etant le retour `a la ligne...
Solution ajouter un ’ ’ avant le premier code de format : scanf ( ” %c ” ,&c ) ;
→l’espace indique que lescanfdoit ”consommer” tous les espaces, retour `a la ligne et autre tabulation avant de lire quoi que ce soit...
scanf
ATTENTION: lors de la lecture, seul ce qui est demand´e est lu ! Exemple pathologique :
char c ;
scanf ( ”%c ” ,&c ) ;
p r i n t f ( ” Char l u : %c\n ” , c ) ; scanf ( ”%c ” ,&c ) ;
p r i n t f ( ” Char l u : %c\n ” , c ) ; Que fait le programme ?
Lecture d’un seul caract`ere ! Le 2eme ´etant le retour `a la ligne...
Solution ajouter un ’ ’ avant le premier code de format : scanf ( ” %c ” ,&c ) ;
→l’espace indique que lescanfdoit ”consommer” tous les espaces, retour `a la ligne et autre tabulation avant de lire quoi que ce soit...
Quelques codes de format courants
I %d : entier
I %u : entier non sign´e
I %f : flottant
I %c : caract`ere
I %s : chaˆıne de caract`eres (ATTENTION...)
I %p : pointeur
getchar/putchar
I int getchar(): lecture d’un caract`ere. Renvoie le code du caract`ere lu,EOFsi probl`eme. ´Equivalent `a
scanf("%c",&c lu)
I int putchar(int c): ´ecriture d’un caract`ere. Renvoie le code du caract`ere ´ecrit,EOFsi probl`eme. ´Equivalent `a printf("%c",c a ecrire)
I Fonctions plus simples et plus rapides
getchar
ATTENTION: mˆeme probl`eme sur legetcharque surscanf Exemple de solution :
i n t c ; do
c=getchar ( ) ; while ( c== ’\n ’ ) ;
ou pour ´eviter aussi espaces, retours `a la ligne et autres tabulations :
#include <ctype . h>
i n t c ; do
c=getchar ( ) ; while ( isspace ( c ) ) ;
Structures et entr´ees/sorties
typedef struct p o i n t { f l o a t x ;
f l o a t y ; f l o a t z ; } p o i n t ;
p o i n t p1={ 1.0 , 2.0 , 3.0}, p2 ; FILE ∗f =fopen ( ” m o n f i c h i e r ” , ”wb” ) ;
f w r i t e (&p1 ,sizeof( p o i n t ) , 1 , f ) ; f c l o s e ( f ) ;
f =fopen ( ” m o n f i c h i e r ” , ” rb ” ) ; fread (&p2 ,sizeof( p o i n t ) , 1 , f ) ;
Structures et entr´ees/sorties
/ / Avec un tableau ? typedef struct c o n t a c t {
char nom [ 3 0 ] ; char prenom [ 3 0 ] ; } contact ;
contact c1={” T y r e l l ” , ” Eldon ” }; FILE ∗f =fopen ( ” m o n f i c h i e r ” , ”wb” ) ;
f w r i t e (&c1 ,sizeof( contact ) , 1 , f ) ; f c l o s e ( f ) ;
/ / ca marche !
/ / Que c o n t i e n t l e f i c h i e r ?
Structures et entr´ees/sorties
/ / Avec des p o i n t e u r s ? typedef struct c o n t a c t {
char ∗ nom ; char ∗ prenom ; } contact ;
contact c1 ;
c1 . nom = strdup ( ” T y r e l l ” ) ; c1 . prenom = strdup ( ” Eldon ” ) ;
FILE ∗f =fopen ( ” m o n f i c h i e r ” , ”wb” ) ; f w r i t e (&c1 ,sizeof( contact ) , 1 , f ) ; f c l o s e ( f ) ;
/ / qu ’ est−ce qui est e c r i t ?
Structures et entr´ees/sorties
/ / Avec des p o i n t e u r s ? E c r i t u r e : typedef struct c o n t a c t {
char ∗ nom ; char ∗ prenom ; } contact ;
contact c1 ;
c1 . nom = strdup ( ” T y r e l l ” ) ; c1 . prenom = strdup ( ” Eldon ” ) ; FILE ∗f =fopen ( ” m o n f i c h i e r ” , ”w” ) ;
f p r i n t f ( f , ”%s\n ” , c1 . nom ) ; f p r i n t f ( f , ”%s\n ” , c1 . prenom ) ; f c l o s e ( f ) ;
/ / quel est l e contenu du f i c h i e r ?
Structures et entr´ees/sorties
/ / Avec des p o i n t e u r s ? Lecture contact c2 ;
FILE ∗f =fopen ( ” m o n f i c h i e r ” , ” r ” ) ; char b u f f e r [ 1 2 8 ] ;
f g e t s ( b u f f e r ,128 , f ) ; / / pour enlever l e ’\n ’
b u f f e r [ s t r l e n ( b u f f e r )−1]= ’\0 ’ ; c2 . nom= strdup ( b u f f e r ) ;
f g e t s ( b u f f e r ,128 , f ) ; / / pour enlever l e ’\n ’
b u f f e r [ s t r l e n ( b u f f e r )−1]= ’\0 ’ ; c2 . prenom= strdup ( b u f f e r ) ; f c l o s e ( f ) ;
UE C avanc´e
cours 6: r´evisions et exercices
Jean-Lou Desbarbieux et St´ephane Doncieux UMPC 2012/2013
Quizz pointeurs
Que font les instructions suivantes : i n t n =42;
i n t ∗m=n ;
∗m = 2 4 ;
Quizz pointeurs
Que font les instructions suivantes : i n t n =42;
i n t ∗m=n ;
∗m = 2 4 ;
→ erreur de segmentation ! ! Il manque un ’&’ `a la 2eme ligne :
i n t n =42;
i n t ∗m=&n ; // & a a j o u t e r
∗m = 2 4 ; R´esultat ?
Quizz pointeurs
Que font les instructions suivantes : i n t t [ 4 ] ={0 , 1 , 2 , 3};
i n t ∗m=t ;
∗(m++) += 3 ;
∗(++m) += 4 ; (∗m)++;
Que fait la fonction ? Comment y fait-on appel ?
v o i d m y s t e r e (i n t ∗n , i n t m) { i f( (m= = 0 )||(m==1)) {
∗n =1;
} e l s e {
m y s t e r e ( n ,m−1);
∗n ∗= m;
} }
Initialiser le contenu d’un tableau dans une fonction
I Possible ?
I Si oui :
I quel prototype ?
I quelle fonction ?
I comment utiliser la fonction ?
Initialiser le contenu d’un tableau dans une fonction
v o i d i n i t i a l i s e r (i n t ∗tab , i n t n , i n t v a l =0) { unsigned i n t i ;
f o r ( i =0; i<n ; i ++) { t a b [ i ]= v a l ; }
}
Allouer un tableau dans une fonction
I Possible ?
I Si oui :
I quel prototype ?
I quelle fonction ?
Allouer un tableau dans une fonction
i n t ∗a l l o u e r T a b l e a u (i n t n ) {
i n t ∗t a b =(i n t ∗) m a l l o c ( n∗s i z e o f(i n t ) ) ; i f ( t a b == NULL) {
p r i n t f ( ” Probleme p e n d a n t l ’ a l l o c a t i o n\n” ) ; }
r e t u r n t a b ; }
Changer la taille d’un tableau dans une fonction
I Possible ?
I Si oui :
I quel prototype ?
I quelle fonction ?
Changer la taille d’un tableau dans une fonction
i n t ∗c h a n g e r T a i l l e T a b l e a u (i n t ∗tab , i n t n ) { i n t ∗t a b 2 =(i n t ∗) r e a l l o c ( tab , n∗s i z e o f(i n t ) ) ; i f ( t a b 2 == NULL) {
p r i n t f ( ” Probleme p e n d a n t l ’ a l l o c a t i o n\n” ) ; r e t u r n t a b ;
}
r e t u r n t a b 2 ; }
Changer la taille d’un tableau dans une fonction (bis)
Autre ´ecriture : renvoievoid et modifie le param`etre transmettant le tableau.
v o i d c h a n g e r T a i l l e T a b l e a u 2 (i n t ∗∗tab , i n t n ) { // a t t e n t i o n , t a b e s t un ’ i n t ∗∗’
i n t ∗t a b 2 =(i n t ∗) r e a l l o c (∗tab , n∗s i z e o f(i n t ) ) ; i f ( t a b 2 == NULL) {
p r i n t f ( ” Probleme p e n d a n t l ’ a l l o c a t i o n\n” ) ; r e t u r n;
}
∗t a b=t a b 2 ; }
Structure
s t r u c t p o i n t { f l o a t x ; f l o a t y ; f l o a t z ; };
i n t main ( ) {
p r i n t f ( ” s i z e o f ( p o i n t)=%d\n” , s i z e o f(s t r u c t p o i n t ) ) ; }
Qu’est-ce qui est affich´e `a l’´ecran ?
Structure
s t r u c t p o i n t { f l o a t x ; f l o a t y ; f l o a t z ; };
i n t main ( ) {
p r i n t f ( ” s i z e o f ( p o i n t)=%d\n” , s i z e o f(s t r u c t p o i n t ) ) ; r e t u r n 0 ;
}
Qu’est-ce qui est affich´e `a l’´ecran ? sizeof(struct point)=12
Structure et passage de param`etres
v o i d f (s t r u c t p o i n t p ) { p . x =42;
p . y =24;
p . z =12;
}
i n t main ( ) {
s t r u c t p o i n t p ={1 , 2 , 3}; f ( p ) ;
p r i n t f ( ”p . x=%f p . y=%f p . z=%f\n” , p . x , p . y , p . z ) ; r e t u r n 0 ;
}
Qu’est-ce qui est affich´e `a l’´ecran ?