Langage C - Sites personnels de Télécom ParisTech ?· Eric Lecolinet - Télécom ParisTech - Langage…

  • Published on
    12-Sep-2018

  • View
    212

  • Download
    0

Transcript

Langage CEric LecolinetTlcom ParisTechSeptembre 2017Extension du C par Bjarne Stroustrup aux Bell LabsC++11 : rvision majeure en 2011/2014Autre extension du C de NeXt puis ApplePuissant, syntaxe inhabituelle inspire de SmalltalkVise la simplicit/rapidit d'criture, cr par G. van RossumInterprt, typage dynamiqueSimplification du C++ de Sun Microsystems puis OracleEgalement inspir de Smalltalk, ADA ...A l'origine, le Java de MicrosoftEgalement inspir de Delphi, C++ ...Le successeur d'Objective C, par AppleDbut 70 : Langage CDbut 80 : C++Dbut 80 : Objective CFin 80... : PythonMi-90 : JavaDbut 2000: C#Mi-2000: Swift3Eric Lecolinet - Tlcom ParisTech - Langage CAperuUn programme C comprend : un ou plusieurs fichiers C dfinissant des fonctions (ventuellement) des variables globales une seule fonction main() = la 1re fonction appele une difficult : faire en sorte que les appels et des dfinitions des fonctions correspondent4Eric Lecolinet - Tlcom ParisTech - Langage CAperuExemple : un programme compos de 2 fichiers#include void foo(const char* name) {printf("hello %s \n", name);}int main() {const char* name = "hubert";foo(name);dupondt();}_________________________________________________// dans un autre fichiervoid dupondt() {foo("dupondt");}Problme cl : assurer la correspondance entre les appels et les dfinitions des fonctions5Eric Lecolinet - Tlcom ParisTech - Langage CTypes de baseTypes de base char : caractre ou petit nombre (1 octet) int : entier (short = 32 bits) bool : boolen (depuis C99, inclure stdbool.h)Attention: les tailles varient selon la plate-forme ! cf. limits.h et float.h headers standards (dans: /usr/include sous Linux) example : short = 16 / int = long = 32 / float = 32 / double = 64 bitsfloat : flottant simple prcisiondouble : flottant double prcisionlong double : encore plus prcis !6Eric Lecolinet - Tlcom ParisTech - Langage CTypes et signe signed int unsigned longTous les types sont signs par dfaut sauf char qui dpend de la plate-forme ! unsigned char : de 0 255 signed char : de -128 127 char : sign ou pas sign => source derreurs si on change de plate-forme7Eric Lecolinet - Tlcom ParisTech - Langage CVariablesDclarations de variablesint i, res, truc; trois entiersfloat vect[1000]; vecteur de 1000 entiers double mat[5][10]; matrice de 5 lignes et 10 colonnesATTENTION : les valeurs sont indfinies => initialiser les variables !int i = 0;char new_line = \n; char * p = NULL; ne pas confondre = (affectation) avec == (galit) avant C99 : variables dclares avant les instructions (!= Java, C++)8Eric Lecolinet - Tlcom ParisTech - Langage CConstantesTypes des constantes1234 037 (octal) 0x1f (hexadcimal) 1.234 1. 1e-2 => type double a (caractre) => type int"abcd" (littral) => type char *Caractres: a sont des int (et non des char !) en ASCII: A = 65, O (la lettre) = 78, 0 (le chiffre) = 48, \0 (NUL char) = 0Littraux: "abcd" sont des chanes de caractres constantes (ne pas modifier leur contenu !) un \0 est automatiquement rajout la fin par le compilateur char* message = "hello word";Caractres spciaux: \0 = le caractre nul; valeur = 0 \n = new line, \t = tabulation, etc. \xxx = caractre dfini en octal ex : \007 = caractre BELL9Eric Lecolinet - Tlcom ParisTech - Langage CCode ASCII10Eric Lecolinet - Tlcom ParisTech - Langage CVariables constantes, numrationsVariables valeur constanteconst float pi = 3.14; // cette valeur ne peut pas changerEnumrationsenum Jour {LUNDI=1, MARDI, MERCREDI, JEUDI, VENDREDI, SAMEDI, DIMANCHE};enum Jour j = JEUDI; if (j == SAMEDI) printf("en week end\n") commencent 0 par dfaut moyen simple et efficace de spcifier des constantes entires11Eric Lecolinet - Tlcom ParisTech - Langage CMacros #define TAILLE 1024#define BELL \007#define MESSAGE "hello word"char tableau[TAILLE]; // paramtrer : ne pas crire char tableau[1024] !!! substitution textuelle par le prprocesseur C avant la compilation les macros permettent de paramtrer le programme viter les macros si possible : prfrer les numrations ou variables constMacros paramtres #define MIN(X,Y) ((X) < (Y) ? (X) : (Y)) int i = 1, j = 2; int k = MIN(i, j);12Eric Lecolinet - Tlcom ParisTech - Langage COprateurs arithmtiquesOrdre de priorit - unaire -x * / % + - binaire x-y l = i + j * k; // attention la prcdence des oprateurs ! m = (i + j) * k; / est la division entire ou relle suivant le cas : !!! attention : 2 / 4 vaut 0 mais 2. / 4 vaut 0.5 !!! % = reste de la division entire13Eric Lecolinet - Tlcom ParisTech - Langage CTranstypage implicitePar dfaut : conversion implicite vers le type le plus grandAttention : les conversions implicites peuvent tre dangereuses !int i = 2, j = 4;char c = \n;float x = 4., y1, y2, y3;i = c;c = i; x = i;i = x; y1 = i + x;y2 = i / x;y3 = i / j;Que vaut y3 ?14Eric Lecolinet - Tlcom ParisTech - Langage CTranstypage implicitePar dfaut : conversion implicite vers le type le plus grandAttention : les conversions implicites peuvent tre dangereuses !int i = 2, j = 4;char c = \n;float x = 4., y1, y2, y3;i = c;c = i; /* entier tronqu */x = i;i = x; /* rel tronqu */y1 = i + x;y2 = i / x;y3 = i / j; !!! y3 vaut 0 car i et j sont des int15Eric Lecolinet - Tlcom ParisTech - Langage CTranstypage expliciteL'oprateur de cast fait une conversion de type explicite int i = 2, j = 4; float y, z; y = i / j; // y = ? z = (float) i / j; // z = ? 16Eric Lecolinet - Tlcom ParisTech - Langage CTranstypage expliciteL'oprateur de cast fait une conversion de type explicite int i = 2, j = 4; float y, z; y = i / j; // y = 0.0 z = (float) i / j; // Z = 0.5 17Eric Lecolinet - Tlcom ParisTech - Langage CTranstypage expliciteL'oprateur de cast fait une conversion de type explicite!!! Attention : ne convertit pas les donnes ! (seulement le type) (Mauvais) exemple : transformer une chane en nombre (et inversement) char * s = "33"; int i = 12; s = (char*) i; // compile mais faux !!! i = (int) s; // compile mais faux !!!18Eric Lecolinet - Tlcom ParisTech - Langage CIncrmentationOprateurs i++ et ++i signifient: i = i + 1 i += n signifie: i = i + n mme chose avec: i--, --i, i -= ni++ versus ++ii = 5; a = ++i; /* i = ? , a = ? */i = 5; a = i++; /* i = ? , a = ? */19Eric Lecolinet - Tlcom ParisTech - Langage CIncrmentationOprateurs i++ et ++i signifient: i = i + 1 i += n signifie: i = i + n mme chose avec: i--, --i, i -= ni++ versus ++ii = 5; a = ++i; /* i = 6 , a = 6 */i = 5; a = i++; /* i = 6 , a = 5 */Attention aux ambiguts ! un seul ++ ou -- par ligne!20Eric Lecolinet - Tlcom ParisTech - Langage COprateurs logiques et relationnelsOrdre de priorit! (ngation unaire)> >= < Eric Lecolinet - Tlcom ParisTech - Langage CManipulation de bitsOprateurs& ET | OU inclusif^ OU exclusif> dcalage droite~ complment un int n = 0xff, m = 0; m = n & 0x10; m = n Eric Lecolinet - Tlcom ParisTech - Langage CTests et bouclesExpressions conditionnelles ne pas oublier les ( ) autour du test ; la fin des deux instructions else optionnel if (a > b) z = a; else z = b; if (k < tabsize && tab[k] != 0) doit(tab[k]);Rappel : arrt de lvaluation ds que : condition fausse pour && condition vraie pour | | if (test) action1; else action2;if (test) action1;else action2; if (test) action1;25Eric Lecolinet - Tlcom ParisTech - Langage CActions imbriques if (n > 0) if (a > b) z = a; else z = b; le else se rapporte au if le plus proche mettre des { } pour viter les ambiguts !!! indenter le code !!! => utiliser un diteur de texte appropri if (n > 0) { if (a > b) z = a; else z = b; } if (n > 0) { if (a > b) z = a; } else z = b;26Eric Lecolinet - Tlcom ParisTech - Langage Celse if cascads if (test1) action1; else if (test2) action2 ; else if (test3) action3 ; else action_par_dfaut; structure de tests en "rateau" ne pas mettre des { } inutiles alternative: le switch27Eric Lecolinet - Tlcom ParisTech - Langage Cswitch if (test1) action1; else if (test2) action2 ; else if (test3) action3 ; else action_par_dfaut; switch (expression) { case const1: action1a; action1b; action1c; break; case const2: case const3: action2; break; default: action3; break; }Remarques const1, const2 .... doivent tre des constantes valeur entire break ou return pour sortir du switch (sinon on continue jusqu la fin) 28Eric Lecolinet - Tlcom ParisTech - Langage COprateur ?PrincipeLexpression: test ? expr1 : expr2renvoie : expr1 si test est vrai (cad. != 0) expr2 sinonExemplez = a > b ? a : b ;quivaut :if (a > b) z = a; else z = b;#define MAX(a,b) ((a)>(b) ? (a):(b)) // penser mettre des ( )float x = 55., y = 77.; // attention aux effets de bord !........float res = MAX(x, y);29Eric Lecolinet - Tlcom ParisTech - Langage CBoucles while et for for (init; test; incr) { actions; }Equivaut : init; while (test) { actions; incr; } init, test et incr sont des expressions quelconques continue tant que test != 0 test effectu avant dentrer dans la boucle prfrer for while : vite doublier des clauses !30Eric Lecolinet - Tlcom ParisTech - Langage CExemples// Toujours dfinir les tailles par des MACROS#define TAB_SIZE 20int tab[TAB_SIZE];int i = 0;// Les tableaux commencent lindice 0 => balayer tab de 0 TAB_SIZE-1for (i = 0; i < TAB_SIZE; i++) { tab[i] = 0;}// formes quivalentes :i = 0;while (i < TAB_SIZE) tab[i++] = 0;i = -1;while (++i < TAB_SIZE) tab[i] = 0;31Eric Lecolinet - Tlcom ParisTech - Langage CDiversBoucle do while do { actions; } while (test); actions excutes au moins 1 fois continue tant que test != 0Break et continue break permet de sortir dune boucle ou dun switch continue passe litration suivanteGoto et Labels viter sauf cas particuliers32Eric Lecolinet - Tlcom ParisTech - Langage CExemplesQue fait ce fragment de code et que faut-il rajouter ?char line[] = "il pleut parfois le lundi";int i = 0;for (i = 0; ???; i++) { if (line[i] == ) break;}33Eric Lecolinet - Tlcom ParisTech - Langage CExemplesUn cas o goto peut tre utile bool foo() { for (....) { ... if (niveau_gasoil == 0) goto BIG_PROBLEM; ... for (....) { .... if (Touch(iceberg)) goto BIG_PROBLEM; } } return true; BIG_PROBLEM : // tous les cas d'erreurs printf("Fatal error: The Titanic has sunk!\n") return false;}34Eric Lecolinet - Tlcom ParisTech - Langage CInterlude#include int main() { int tab[] = {1,2,3}; int a1 = tab[1]; int a2 = 1[tab]; int a3 = *(tab+1); int a4 = *(1+tab); printf("%d %d %d %d \n", a1, a2, a3, a4); } 35Eric Lecolinet - Tlcom ParisTech - Langage CInterlude#include int main() { int tab[] = {1,2,3}; int a1 = tab[1]; int a2 = 1[tab]; int a3 = *(tab+1); int a4 = *(1+tab); printf("%d %d %d %d \n", a1, a2, a3, a4); } $ make tt$ ./tt2 2 2 2 36Eric Lecolinet - Tlcom ParisTech - Langage CFonctionsObjectifDcouper un programme en petites entits : indpendantes rutilisables plus lisiblesLibrairies et compilation spareLes fonctions peuvent tre dfinies : dans plusieurs fichiers dans des librairiesSyntaxe de dfinition dune fonctiontype nom_fonction(paramtres) {dclarations;instructions;return type;}37Eric Lecolinet - Tlcom ParisTech - Langage CChercheVal V1 (un seul fichier main.c)#include int ChercheVal(float tab[ ], int tabCount, float val) {int k;for (k = 0; k < tabCount; k++) { if (tab[k] == val) return k;}return -1;}int main() {float donnees[ ] = {1., 2., 3., 4., 5., 6., 7., 8., 9., 10.};int indice = ChercheVal(donnees, 10, 4.); /* que manque til ici ? */printf("indice = %d , valeur = %f \n", indice, donnees[indice] );return 0;}Question valeur de lindice ?Remarques noter linitialisation des tableaux il manque un test : pourquoi ?38Eric Lecolinet - Tlcom ParisTech - Langage CReturn et voidint ChercheVal(float tab[ ], int tabCount, float val) {int k;for (k = 0; k < tabCount; k++) { if (tab[k] == val) return k;}return -1;} ne pas oublier return sinon la fonction renvoie nimporte quoi !!!void foo(void) {.....} void si la fonction ne retourne rien ou na aucun paramtre Remarque: syntaxe obsolte void foo(i, j) int i, j; { ..... } aucune vrification des arguments vieilles versions du langage C39Eric Lecolinet - Tlcom ParisTech - Langage CPassage des argumentsPassage par valeur les valeurs passes en argument des fonctions sont recopies dans leurs paramtres int ChercheVal(float tab[ ], int tabCount, float val) { .......}int main() { float donnees[ ] = {1., 2., 3., 4., 5., 6., 7., 8., 9., 10.}; indice = ChercheVal(donnees, 10, 4.); .......}40Eric Lecolinet - Tlcom ParisTech - Langage CPassage des argumentsPassage par valeur les valeurs passes en argument des fonctions sont recopies dans leurs paramtres Sauf pour les tableaux !!! cest leur adresse qui est recopie, pas leur contenu (passage par adresse)int ChercheVal(float tab[ ], int tabCount, float val) { .......}int main() { float donnees[ ] = {1., 2., 3., 4., 5., 6., 7., 8., 9., 10.}; indice = ChercheVal(donnees, 10, 4.); .......}Attention : tab ne connat pas son nombre dlments, tabCount est indispensable tab est en fait un pointeur41Eric Lecolinet - Tlcom ParisTech - Langage CPassage des argumentsQuestion : quelles sont les valeurs affiches ?void swap(int i, int j) {int aux;aux = i; i = j; j = aux;}int main() {int i = 5, j = 7;swap( i, j );printf( " i = %d , j = %d \n", i , j );}Solution ?42Eric Lecolinet - Tlcom ParisTech - Langage CArgc, argvint main(int argc, char *argv[]) {if (argc Eric Lecolinet - Tlcom ParisTech - Langage CStyle et commentaires /// retourne la largeur. unsigned int getWidth(); unsigned int getHeight(); ///< retourne la hauteur.Rgles tre cohrent indenter (utiliser un IDE qui le fait automatiquement : TAB ou Ctrl-I en gnral) arer, viter plus de 80 colonnes commenter quand c'est utile camelCase /// change la position. /** voir aussi setX() et setY(). */ void setPos(int x, int y); void setX(int); /**< @brief change l'abscisse. * voir aussi setY() et setPos(). */45Eric Lecolinet - Tlcom ParisTech - Langage CCompilation spareFonctions rparties dans plusieurs fichiers et les bibliothques (librairies systme)Librairies standard headers dans: /usr/include binaires dans: /usr/lib ou dans : /usr/local/... etc.Edition de lienscompilation46Eric Lecolinet - Tlcom ParisTech - Langage CBibliothques statiques et dynamiquesLibrairies statiques extension .a (sous Unix) simples "archives" de fichiers .o le code est insr dans lexcutable la compilationLibrairies dynamiques (DLLs) extension .so, dylib, etc. le code nest pas insr dans lexcutable il est charg dynamiquement lexcution47Eric Lecolinet - Tlcom ParisTech - Langage CBibliothques dynamiquesAvantages des librairies dynamiques les programmes prennent beaucoup moins de place ils sont plus rapides (moins de swapping car le binaire est partag)Inconvnients lutilisateur doit avoir cette librairie sur son systme => attention aux licences (souvent diffrentes si lib. statique ou dynamique) => attention aux versionsSous UnixLes DLLs sont recherches dans lordre indiqu par la variable:LD_LIBRARY_PATH (ou quivalent) du shell Unix48Eric Lecolinet - Tlcom ParisTech - Langage CCompilateur et diteur de liensPrincipales options du compilateur C -g pour deboguer -O/-O1/-O2... pour optimiser -Wall pour afficher plus dinfos avec gcc (toujours mettre cette option!) -Idirectory : chercher les headers dans ce rpertoire (*)Principales options de lditeur de liens -Ldirectory : chercher les librairies dans ce rpertoire (*) -llibrary : chercher les fonctions dans cette librairie (*) on peut mettre plusieurs -Idirectory et -Ldirectory mais lordre importe49Eric Lecolinet - Tlcom ParisTech - Langage CMakefileMakefile = fichier de rgles indiquant: les fichiers compiler les compilateurs et leurs options les librairies...Typiquement : un Makefile par rpertoireLa commande make lit le Makefile appelle automatiquement les outils adquats (compilateurs, diteur de lien ...) vrifie les dates et ne recompile que ce qui doit ltreRgle dor ne pas taper les commandes de compilation la main (toujours fausses!) utiliser un Makefile ou un IDE50Eric Lecolinet - Tlcom ParisTech - Langage CExemple de Makefile# compilateur C et ses optionsCC= gccCFLAGS= -g -Wall -std=c99 -I/usr/local/qt/include# librairies utilisesLDLIBS = -L/usr/local/qt/lib -lqt# fichiers objet de lapplication et nom de lexcutableOBJS= tri.o donnees.oEXEC= tri# rgle de production de l'application (la 2e ligne commence par une tabulation!)$(EXEC) : $(OBJS)$(CC) $(CFLAGS) -o $@ $(OBJS) $(LDLIBS)# nettoyageclean:-$(RM) $(EXEC) $(OBJS)make : lance la 1ere rgle (qui compile tout)make clean : lance la rgle "clean"51Eric Lecolinet - Tlcom ParisTech - Langage CComplmentsLe Makefile prcdent est incomplet : pas de rgles pour crer les .o : cest fait implicitement mais sans tenir compte des .h !Il faut: soit mettre les rgles la main soit utiliser makedepend, configure ou un outil plus voluExemple => cf Makefile du TP52Eric Lecolinet - Tlcom ParisTech - Langage CComplmentsAutres outils utiles emacs, xemacs, etc. gdb, xxgdb, ddd grep, nm ar tar, gtar, gzip, gunzip eclipse, kdevelop ...53Eric Lecolinet - Tlcom ParisTech - Langage CRetour la compilation spareFonctions rparties dans plusieurs fichiers et les bibliothques (librairies systme)CompilationEdition de liens54Eric Lecolinet - Tlcom ParisTech - Langage CChercheVal V2 (version incorrecte)int ChercheVal(float tab[ ], int tabCount, float val) {int k;for (k = 0; k < tabCount; k++) { if (tab[k] == val) return k;}return -1;}___________________________________________________________________________#include int main() {float donnees[ ] = {1., 2., 3., 4., 5., 6., 7., 8., 9., 10.};int indice = ChercheVal(donnees, 10, 4.); if (indice >= 0) printf("indice = %d , valeur = %f \n", indice, donnees[indice] );return 0;}fichier cherche.c fichier main.c Quel est le problme ?55Eric Lecolinet - Tlcom ParisTech - Langage CProblmeLes fichiers C sont compils indpendamment => pas de vrification de cohrence entre la dfinition et lappel !Quand on appelle une fonction inconnue le compilateur C suppose quelle existe et renvoie un int Formidable source derreurs !Compilation indpendante des .c56Eric Lecolinet - Tlcom ParisTech - Langage CProblme Les fichiers C sont compils indpendamment => pas de vrification de cohrence entre la dfinition et lappel !Quand on appelle une fonction inconnue le compilateur C suppose quelle existe et renvoie un intTrois cas possibles fonction dfinie nulle part : erreur ddition de lien Symbol not found fonction dfinie avec la mme signature : excutable cr et correct fonction dfinie avec une autre signature : lexcutable cr mais comportement indtermin57Eric Lecolinet - Tlcom ParisTech - Langage CSolution : header partagsPrincipe chaque fichier .c qui dfinit des fonctions associer un fichier .h (header) qui dclare ces fonctions inclure ce header : dans le fichier .c qui dfinit ces fonctions dans les fichiers .c qui appellent ces fonctions Cohrence vrifie par transitivit !58Eric Lecolinet - Tlcom ParisTech - Langage CChercheVal V3 (version correcte)int ChercheVal(float tab[ ], int tabCount, float val) ;___________________________________________________________________________#include cherche.hint ChercheVal(float tab[ ], int tabCount, float val) {int k;for (k = 0; k < taille; k++) {if (tab[k] == val) return k;}return -1;}___________________________________________________________________________#include #include cherche.hint main() {float donnees[ ] = {1., 2., 3., 4., 5., 6., 7., 8., 9., 10.};int indice = ChercheVal(donnees, 10, 4.); if (indice >= 0) printf("indice = %d , valeur = %f \n", indice, donnees[indice] );return 0;}fichier cherche.c fichier main.c fichier cherche.h 59Eric Lecolinet - Tlcom ParisTech - Langage CRemarquesDclaration de fonction int ChercheVal(float tab[ ], int taille, float val) ; // ; la fin dclare la signature (valeur de retour et paramtres) de cette fonctionRecherche des headers#include // cherche dans le mme rpertoire#include cherche.h // cherche dans rpertoires standards (e.g. /usr/include) pour chercher dans des rpertoires supplmentaires : option -Igcc -I/usr/local/qt/include truc.c -o truc60Eric Lecolinet - Tlcom ParisTech - Langage CAppel de fonctions des bibliothquesCe qui prcde vaut aussi pour les fonctions des bibliothques#include int main() {double x = cos(0.5);printf("Rsultat: %f \n", x);}61Eric Lecolinet - Tlcom ParisTech - Langage CAppel de fonctions des bibliothquesCe qui prcde vaut aussi pour les fonctions des bibliothques#include #include // !!!!!!int main() {double x = cos(0.5);printf("Rsultat: %f \n", x);} compile mais rsultat indtermin sans le #include !62Eric Lecolinet - Tlcom ParisTech - Langage CHeaders standards des bibliothquesLes plus courants : entres/sorties (printf, scanf) : fonctions gnrales (malloc, rand) : dfinitions gnrales (dclaration de la constante NULL) : chanes de caractres (strcmp, strlen) : fonctions mathmatiques (sqrt, cos)Egalement : assertions (assert) : caractres (isalnum, tolower) : gestion des erreurs (dclaration de la variable errno) : gestion des signaux (signal et raise) : manipulation du temps (time, ctime) et bien dautres lis au systme (cf. /usr/include sous Unix)63Eric Lecolinet - Tlcom ParisTech - Langage CVariables localesVariables locales (et paramtres) accessibles uniquement dans cette fonction dans la pile : cres (dtruites) quand on entre (sort) de la fonctionint ChercheVal(float tab[ ], int tabCount, float val) { // paramtres formelsint k = 0; // variable automatiquefor (k = 0; k < tabCount; k++) { if (tab[k] == val) return k; }return -1;} k : variable locale (automatique en jargon C) tab, taille, val : paramtres formels (cas particulier de variables locales) valeur initiale indfinie => toujours initialiser les variables locales !64Eric Lecolinet - Tlcom ParisTech - Langage CVariables globales#include float donnees[ ] = {1., 2., 3., 4., 5., 6., 7., 8., 9., 10.}; // variable globaleint tabCount = 10; // variable globaleint ChercheVal(float val) {int k = 0;for (k = 0; k < tabCount; k++) {if (donnees[k] == val) return k;}return -1;}int main() {int indice = ChercheVal(4.); if (indice >= 0) printf("indice = %d , valeur = %f \n", indice, donnees[indice] );return 0;}Variables globales dclares en dehors des fonctions, accessibles dans tout le programme existent pendant toute la dure du programme initialises 0 65Eric Lecolinet - Tlcom ParisTech - Langage CVariables globalesLes variables globales sont dangereuses et doivent tre proscrites comment comprendre et vrifier qui modifie quoi ? empchent la rutilisation du code : tout dpend de tout entranent des collisions de noms : mme nom de variable dans plusieurs fichiersDans les rares cas o elles sont utiles, les dclarer dans des headers commepour les fonctions :extern float donnees[ ]; // dclare lexistence dune variable globaleextern int taille; // qui est dfinie ailleurs66Eric Lecolinet - Tlcom ParisTech - Langage CVariables statiques (de fichier)#include static float donnees[ ] = {1., 2., 3., 4., 5., 6., 7., 8., 9., 10.}; // variable statiquestatic int tabCount = 10; // variable statiqueint ChercheVal(float val) {int k = 0;for (k = 0; k < tabCount; k++) {if (donnees[k] == val) return k;}return -1;}int main() {int indice = ChercheVal(4.); if (indice >= 0) printf("indice = %d , valeur = %f \n", indice, donnees[indice] );return 0;}Variables statiques dclares en dehors des fonctions, accessibles uniquement dans ce fichier existent pendant toute la dure du programme initialises 067Eric Lecolinet - Tlcom ParisTech - Langage CVariables statiques (de fichier)Variables statiques de fichier similaires aux variables globales sauf quelles sont propres un fichier et inconnues des autres=> beaucoup moins dangereuses que les variables globales68Eric Lecolinet - Tlcom ParisTech - Langage CVariables statiques (de fonction)Variables statiques de fonction similaires aux prcdentes sauf quelles sont propres une fonction et inconnues des autres servent conserver une valeur entre les appels fonctionnelsExemplevoid Affiche(float tab[ ], int taille) { static int n_ieme_fois = 1; // variable statique int k = 0; printf("Jaffiche pour la %d e fois\n", n_ieme_fois++); for (k = 0; k < taille; k++) printf(" tab[%d] = %f \n", k, tab[k]);}69Eric Lecolinet - Tlcom ParisTech - Langage CVariables: complmentsRegistres variables register : utilises trs frquemment pour optimiser lexcution (inutiles avec compilateurs actuels)Structure de bloc : code entre { et } les blocs peuvent tre imbriqus chaque bloc peut contenir des dclarations de variables{int i = 0, taille = 100;....etc....if (i > taille) return -1;else {int k;for (k = 0; k < taille; k++)}}70Eric Lecolinet - Tlcom ParisTech - Langage CTableauxDfinitiontype nom[nb_elements];type nom[nb_lignes][nb_colonnes]; lments contigus indices allant de 0 taille-1 tableaux multi-dimensionnels => lments placs en squenceint vect[10];float mat[5][10];double cube[5][10][20];71Eric Lecolinet - Tlcom ParisTech - Langage CInitialisation des tableauxDfinition avec initialisationint vect[10] = {1, 2, 3};int toto[] = {1, 2, 3}; // taille implicitefloat mat[5][10] = {{1, 2, 3, 4}, {5, 6}, {7, 8, 9}}; // initialisation ligne par lignefloat truc[][10] = {{1, 2, 3, 4}, {5, 6}, {7, 8, 9}}; les initialiseurs doivent tre des constantes (sauf si extensions) la dimension la plus gauche peut tre omise72Eric Lecolinet - Tlcom ParisTech - Langage CReprsentation mmoire des tableauxVecteurMatrice 2D73Eric Lecolinet - Tlcom ParisTech - Langage CAdresses et drfrencementOperateurs &c : adresse dune entit c *a : valeur pointe par une adresse a (oprateur de drfrencement) Adresse du 1er lment. de vect : &vect[0] == &(vect[0]) == vect (cf. passage des tableaux en argument des fonctions) Adresse du ime elt. de vect: &vect[i] == &(vect[i]) == vect + i Valeur du ime elt. de vect : vect[i] == *(vect + i) Adresse de lelt. (x,y) de mat : &mat[y][x] == mat + y * nb_col + x Valeur de lelt. (x,y) de mat : mat[y][x] == *(mat + y * nb_col + x)74Eric Lecolinet - Tlcom ParisTech - Langage CPointeurs variables contenant une adresse les pointeurs sont (normalement) typsExempleint i = 0, *p =NULL; // p = pointeur dentier p = &i;*p = 5;printf("%d %d \n", *p, i);i = 7;printf("%d %d \n", *p, i);75Eric Lecolinet - Tlcom ParisTech - Langage CPassage des argumentsRappel: passage darguments dans les fonctions passage par valeur : les arguments sont recopis dans les paramtres sauf pour les tableaux (car cest leur adresse qui est recopie)76Eric Lecolinet - Tlcom ParisTech - Langage CPassage des argumentsRappel: passage darguments dans les fonctions passage par valeur : les arguments sont recopis dans les paramtres sauf pour les tableaux (car cest leur adresse qui est recopie)Les pointeurs permettent de rcuprer une valeur via une indirectionvoid foo() {int i; float x;scanf("%d %f", &i, &x);} scanf() rcupre les adresses des variables i et j de foo() ce qui lui permet de modifier leurs valeurs (= ce quelles contiennent en mmoire)77Eric Lecolinet - Tlcom ParisTech - Langage CExemplevoid swap1(int i, int j) {int aux;aux = i; i = j; j = aux;}int main() {int a = 5, b = 0;swap1(a, b);printf(" a = %d, b = %d \n", a, b);}78Eric Lecolinet - Tlcom ParisTech - Langage CExemplevoid swap1(int i, int j) {int aux;aux = i; i = j; j = aux;}int main() {int a = 5, b = 0;swap1(a, b);printf(" a = %d, b = %d \n", a, b);} a et b inchangsvoid swap2(int* pi, int* pj) { int aux;aux = *pi; *pi = *pj; *pj = aux;}int main() {int a = 5, b = 0;swap2(&a, &b);printf(" a = %d, b = %d \n", a, b);} swap2 change les valeurs de a et b car pi et pj de swap2() pointent sur les variables a et b de main()79Eric Lecolinet - Tlcom ParisTech - Langage CPointeurs et tableauxLes pointeurs et les tableaux sont intimement lis :float *p = NULL, *q = NULL, tab[] = {1, 2, 3, 4, 5};p = &tab[2];printf("%f %f \n", *p, tab[2]);p = tab + 2;printf("%f %f \n", *p, tab[2]);*p = 0.0;printf("%f %f \n", *p, tab[2]);q = p++;*(q+2) = 666.666;printf("%f %f \n", *p, *q) Valeur des lments de tab ?80Eric Lecolinet - Tlcom ParisTech - Langage CRemarquesPar dfinition tab == &tab[0] : adresse du tableau void foo(float tab[ ]) quivaut : void foo(float * tab)81Eric Lecolinet - Tlcom ParisTech - Langage CRemarquesPar dfinition tab == &tab[0] : adresse du tableau void foo(float tab[ ]) quivaut : void foo(float * tab)Consquence void foo(float tab[ ], unsigned int tab_count) { ... } tab est en ralit un pointeur => passer le nombre dlments en argument 82Eric Lecolinet - Tlcom ParisTech - Langage CRemarques float *p = NULL, tab[] = {1, 2, 3, 4, 5}; un pointeur est une variable (et peut donc changer de valeur)p = tab; CORRECT p++; CORRECT un tableau nest pas une variable !tab = p; NE COMPILE PAS !!! tab++; NE COMPILE PAS !!! mais dans les 2 cas :float val = tab[i]; CORRECT float val = p[i]; CORRECT83Eric Lecolinet - Tlcom ParisTech - Langage CArithmtique des pointeurschar tabchar[10];char* pc = tabchar;int tabint[10];int* pi = tabint;pc = pc + 5 // 5 caractres plus loin (= 5 octets)pi = pi + 5; // 5 entiers plus loin (= 20 octets si int sur 4 octets)Larithmtique sur les pointeurs na de sens que sils sont typs !84Eric Lecolinet - Tlcom ParisTech - Langage CPointeurs non typs (void*)Type des pointeurs et void* void* p : pointeur non typ affectation entre pointeurs de types diffrents possible via des casts attention aux erreurs !int i; /* un int occupe 4 octets */char* pc; /* un char occupe 1 octet */pc = (char*) &i; /* pc pointe sur le 1er octet de i */Attention les tailles dpendent de la machine (et des options de compilation) les int, float... doivent commencer certaines adresses : (exemple : tous les 4 octets pour certains processeur 32 bits)85Eric Lecolinet - Tlcom ParisTech - Langage CChanes de caractres (strings)En C, une chane de caractres est : une suite de caractres termine par un 0 (la valeur entire nulle)Deux manires de les dfinir : par un tableau : char s[ ] = "abcd"; par un pointeur pointant sur un littral : char* p = "abcd";Dans les deux cas le 0 final est rajout automatiquement sizeof(s) = ? sizeof(p) = ?86Eric Lecolinet - Tlcom ParisTech - Langage CChanes de caractres (strings)En C, une chane de caractres est : une suite de caractres termine par un 0 (la valeur entire nulle)Deux manires de les dfinir : par un tableau : char s[ ] = "abcd"; par un pointeur pointant sur un littral : char* p = "abcd";Dans les deux cas le 0 final est rajout automatiquementAttention ! sizeof(s) = 5 : nombre de caractres + 0 final sizeof(p) = taille du pointeur (ex : 4 pour processeur 32 bits)Consquence void foo(float tab[ ], unsigned int tab_count) { // sizeof(tab) = taille du pointeur ! .}87Eric Lecolinet - Tlcom ParisTech - Langage CExempleCalcul de la longueur dune chane de caractresint strlen(const char* s) { /* Version 1 */int n;for (n = 0; *s != '\0'; s++) n++;return n;} const : valeur qui ne peut pas tre modifie88Eric Lecolinet - Tlcom ParisTech - Langage CExempleCalcul de la longueur dune chane de caractresint strlen(const char* s) { /* Version 1 */int n;for (n = 0; *s != '\0'; s++) n++;return n;}int strlen(const char* s) { /* Version 2 */char* p = s;while (*p) p++; // quivaut : while (p != '\0') p++;return p - s; } p - s : nombre de char entre s et p89Eric Lecolinet - Tlcom ParisTech - Langage CLire une chane de caractres depuis le terminalchar* s; // OK ?scanf("%s", s);char s[20]; // OK ?scanf("%s", s);char s[1000]; // OK ? scanf("%s", s); 90Eric Lecolinet - Tlcom ParisTech - Langage CLire une chane de caractres depuis le terminalchar* s; // FAUX !!!scanf("%s", s);char s[20]; // DANGEREUX !!!scanf("%s", s);char s[1000]; // DANGEREUX (mais un peu moins)scanf("%s", s); Pourquoi ? parce que la mmoire nest pas alloue (1er cas) ou possiblement trop petite (2e et 3e cas)91Eric Lecolinet - Tlcom ParisTech - Langage CExemple#include #include #include #define CODE_SECRET "1234" int main(int argc, char**argv) { bool is_valid = false; char code[5]; printf("Enter password: "); scanf("%s", code); if (strcmp(code, CODE_SECRET) == 0) is_valid = true; if (is_valid) printf("Welcome dear customer ;-)\n"); else printf("Invalid password !!!\n"); return 0; }Questions :Que fait ce programme ?Est-il sr ?92Eric Lecolinet - Tlcom ParisTech - Langage CMmoire et piratageAvec LLVM sous MacOSX 10.7.1 : Enter password: 111111 Welcome dear customer ;-) Adresses: 0x7fff5fbff98a 0x7fff5fbff98f 0x7fff5fbff998 0x7fff5fbff900 Dbordement mmoire : technique de piratage informatique typiquement pour changer ladresse de retour dans la pile#include #include #include #define CODE_SECRET "1234" int main(int argc, char**argv) { bool is_valid = false; char code[5]; printf("Enter password: "); scanf("%s", code); if (strcmp(code, CODE_SECRET) == 0) is_valid = true; if (is_valid) printf("Welcome dear customer ;-)\n"); else printf("Invalid password !!!\n"); printf("Adresses: %p %p %p %p\n", code, &is_valid, &argc, argv); return 0; }93Eric Lecolinet - Tlcom ParisTech - Langage CLire une chane de caractres depuis le terminalPlus sr : char s[20]; scanf("%19s", s); lit au plus 19 caractres (19 = 20-1 : attention au 0 final !) sarrte au premier espace (ou tabulation ou retour chariot)94Eric Lecolinet - Tlcom ParisTech - Langage CLire une chane de caractres depuis le terminalPlus gnral : char buffer[100]; fgets(buffer, sizeof(buffer), stdin)); // stdin = entre standardchar* fgets(char* str, int taille, FILE* stream) lit la ligne entire depuis le fichier, mais au plus taille-1 caractres (le reste sera lu par le prochain appel fgets()) retourne NULL en fin de fichier ou en cas derreur while (fgets(buffer, sizeof(buffer), file)) { ... }Note : fgets() lit toute la ligne contrairement scanf() 95Eric Lecolinet - Tlcom ParisTech - Langage CAutres fonctions dentres/sortiesDepuis/dans un fichierint fscanf(FILE* stream, const char* format, ...)int fprintf(FILE* stream, const char* format, )int fputs(const char* str, FILE* stream) renvoient le nombre dlments lus (ou imprims) entres/sorties console : pseudo fichiers: stdin, stdout, stderrDepuis/dans une chane de caractresint sscanf(const char* str, const char* format, )int sprintf(char* str, const char* format, ...) // danger : dbordement si str trop petit !int snprintf(char* str, size_t taille, const char* format, ); voir complments la fin du poly 96Eric Lecolinet - Tlcom ParisTech - Langage CMmoire dynamiqueBut crer ou dtruire dynamiquement des objets pendant l'excutionPrincipe allouer une zone mmoire et faire pointer un pointeur dessus librer cette zone mmoire quand elle nest plus utilise97Eric Lecolinet - Tlcom ParisTech - Langage CMmoire dynamiqueUtilisation void* malloc(size_t size) : alloue de la mmoirevoid free(void * ptr) : libre la mmoire pointesize_t sizeof(datatype) : taille en octets dun type ou dune variable int * tab = (int *) malloc(tabCount * sizeof(int)); for (int k = 0; k < tabCount; ++k) tab[k] = 0; // C99 (sinon dclarer int k avant le for) free(tab); // Attention : free() net met pas tab NULL tab = NULL; // NULL indique que tab pointe sur rien98Eric Lecolinet - Tlcom ParisTech - Langage CMmoire dynamiqueUtilisation void* malloc(size_t size) : alloue de la mmoirevoid free(void * ptr) : libre la mmoire pointesize_t sizeof(datatype) : taille en octets dun type ou dune variable int * tab = (int *) malloc(tabCount * sizeof(int)); for (int k = 0; k < tabCount; ++k) tab[k] = 0; free(tab); // Attention : free() net met pas tab NULL tab = NULL; // NULL indique que tab pointe sur rienvoid* calloc(size_t count, size_t size) : alloue de la mmoire et la met 0void* realloc(void *ptr, size_t size) : change la taille de la zone mmoire appelle ventuellement malloc(), free() et memcpy() malloc(), calloc(), realloc(), renvoient NULL si plus de mmoire99Eric Lecolinet - Tlcom ParisTech - Langage CMmoire dynamiqueATTENTION toujours initialiser les pointeurs toujours mettre leur valeur NULL quand ils ne pointent sur rien free(tab); tab = NULL; // par mgarde on fait un 2e free() aprs dautres calculs free(tab); // pas de problme car tab = NULL (sinon ca planterait !)100Eric Lecolinet - Tlcom ParisTech - Langage CMmoire dynamiqueATTENTION toujours initialiser les pointeurs toujours mettre leur valeur NULL quand ils ne pointent sur rien free(tab); tab = NULL; // par mgarde on fait un 2e free() aprs dautres calculs free(tab); // pas de problme car tab = NULL (sinon ca planterait !)Remarque malloc() consomme un temps non ngligeable de mme que new en Java, C#, C++, etc. cest mme souvent ce qui prend le plus de temps dans un programme ! => ne pas en faire inutilement101Eric Lecolinet - Tlcom ParisTech - Langage CExemple (solution naive)#include /* pour printf */#include /* pour malloc */float* NewVect(int card) {float *v = (float*) malloc(card * sizeof(float));if (v == NULL) fprintf(stderr, "NewVect: No more memory\n");return v;}float* AddVect(float* v1, float* v2, int card) {float* res = NULL;if (v1 == NULL || v2 == NULL) {fprintf(stderr, "AddVect: Null argument\n");}else if ((res= NewVect(card)) != NULL) { int k;for (k = 0; k < card; k++) res[k] = v1[k] + v2[k];}return res;}void foo() {float a[3] = {1., 2., 3.};float b[3] = {4., 5., 6.};float *x = NULL, *y = NULL;x = AddVect(a, b, 3);y = AddVect(x, a, 3); .. free(x); //ne pas oublier ! free(y);}102Eric Lecolinet - Tlcom ParisTech - Langage CAmliorations Lexemple prcdent prsente plusieurs inconvnients lequels ? que faut-il faire ?103Eric Lecolinet - Tlcom ParisTech - Langage CAmliorations Lexemple prcdent prsente plusieurs inconvnientsLes oprations effectuent un malloc() : 1) cot non ngligeable (si beaucoup doprations) 2) il faut faire des free() pour librer la mmoire=> complique le code et peut occasionner des erreurs 3) rsultat (via return) pas compatible avec les tableaux104Eric Lecolinet - Tlcom ParisTech - Langage CAmliorations Lexemple prcdent prsente plusieurs inconvnientsLes oprations effectuent un malloc() : 1) cot non ngligeable (si beaucoup doprations) 2) il faut faire des free() pour librer la mmoire=> complique le code et peut occasionner des erreurs 3) rsultat (via return) pas compatible avec les tableauxSolutionLes oprations : ne doivent pas allouer de mmoire doivent avoir un 3eme paramtre pour stocker pour le rsultat105Eric Lecolinet - Tlcom ParisTech - Langage CExemple#include #include #include void VectError(const char* message) { fprintf(stderr, "%s \n", message); // suivre}bool AddVect(float* v1, float* v2, float* res, int card) {if (v1 == NULL || v2 == NULL || res == NULL)) { VectError("AddVect: Null argument"); return false; } else { int k; for (k = 0; k < card; k++) res[k] = v1[k] + v2[k]; return true;}}void foo() {float a[3] = {1., 2., 3.};float b[3] = {4., 5., 6.};float x[3];float* y = NewVect(3);AddVect(a, b, x, 3); // x = tableauAddVect(x, a, y, 3); // y = pointeur free(y);}106Eric Lecolinet - Tlcom ParisTech - Langage CStructuresStructure agrgat de donnes anctre des classes (classes sans mthodes)Exemplesstruct POINT { double x, y;};struct ELEVE { char * nom; char * prenom; unsigned int age;};107Eric Lecolinet - Tlcom ParisTech - Langage CExemple: points dans le planstruct POINT {double x, y;};void foo() { struct POINT p1, tab[10]; // le mot cl struct est ncessairestruct POINT p2 = {4.1, 7.3}; // initialisation similaire aux tableauxp1 = p2; // = copie les structures champ par champp1.x = 1.; // . accde un membre de la structuretab[7] = p2;tab[7].x = p2.x;}Note les struct sont passs par valeur (= copis) dans les appels de fonctions108Eric Lecolinet - Tlcom ParisTech - Langage CTypedefstruct POINT {double x, y;};typedef struct POINT Point;void foo() { // plus besoin de rpter structPoint p1, tab[10], p2 = {4.1, 7.3};.....}typedef dfinit un nouveau type PointForme contractetypedef struct POINT {double x, y;} Point;typedef struct {double x, y;} Point;109Eric Lecolinet - Tlcom ParisTech - Langage CStructures imbriques#include typedef struct { typedef struct { double x, y; } Point p1, p2; // Point est imbriqu dans Rect} Rect;void foo() { Point a = {1., 2.}, b = {3., 4.} Rect r1; Rect r2 = {{1., 2.}, {3., 4.}}; r1.p1 = a; r1.p2 = b; printf(" rect1 = (%d, %d) x (%d, %d) \n", r1.p1.x, r1.p1.y, r1.p2.x, r1.p2.y);}110Eric Lecolinet - Tlcom ParisTech - Langage CStructures et pointeurstypedef struct { char * nom; char * prenom; unsigned int age;} Eleve; void foo() { Eleve * eleves = NULL; int elevesNbr = 0; eleves = lireEleves(&elevesNbr); afficherEleves(eleves, elevesNbr);}nom prenom agenom prenom agenom prenom ageeleves(pseudo)tableau de structures111Eric Lecolinet - Tlcom ParisTech - Langage CStructures et pointeurstypedef struct { char * nom; char * prenom; unsigned int age;} Eleve; void foo() { Eleve * eleves = NULL; int elevesNbr = 0; eleves = lireEleves(&elevesNbr); afficherEleves(eleves, elevesNbr);}Eleve* lireEleves(int * elevesNbr) { printf("Entrer le nombre dlves : "); scanf("%d", elevesNbr); eleves = (Eleve*) calloc(*elevesNbr, sizeof(Eleve)); return eleves;}112Eric Lecolinet - Tlcom ParisTech - Langage CStructures et pointeurstypedef struct { char * nom; char * prenom; unsigned int age;} Eleve; void foo() { Eleve * eleves = NULL; int elevesNbr = 0; eleves = lireEleves(&elevesNbr); afficherEleves(eleves, elevesNbr);}la notation: p->a quivaut : (*p).avoid afficherEleves(Eleve* eleves, unsigned int elevesNbr) { if (eleves == NULL || elevesNbr == 0) return;Eleve* p = NULL;for (p = eleves; p < eleves+elevesNbr; ++p) {printf("Eleve : %s %s\n", p->nom, p->prenom);printf("age : %d\n\n, p->age);}}Eleve* lireEleves(int * elevesNbr) { printf("Entrer le nombre dlves : "); scanf("%d", elevesNbr); eleves = (Eleve*) calloc(*elevesNbr, sizeof(Eleve)); return eleves;}113Eric Lecolinet - Tlcom ParisTech - Langage CRemarquetypedef struct { char * nom; char * prenom; unsigned int age;} Eleve; nom et prenom sont des pointeurs => allouer la mmoire dynamiquement avec malloc() ou strdup()char buffer[100];if (fgets(buffer, sizeof(buffer), stdin) != NULL ) { p->nom = strdup(buffer);}char * strdup(const char * str) : fait un malloc et une copie (cf. manuel et string.h)114Eric Lecolinet - Tlcom ParisTech - Langage CTableaux de pointeurstypedef struct { char * nom; char * prenom; unsigned int age;} Eleve; void foo() { Eleve ** eleves = NULL; int elevesNbr = 0; eleves = lireEleves(&elevesNbr); afficherEleves(eleves, elevesNbr);}nom prenom ageelevesnom prenom agenom prenom agenom prenom age(pseudo)tableau de structures115Eric Lecolinet - Tlcom ParisTech - Langage CStructures et pointeurstypedef struct { char * nom; char * prenom; unsigned int age;} Eleve; void foo() { Eleve ** eleves = NULL; int elevesNbr = 0; eleves = lireEleves(&elevesNbr); afficherEleves(eleves, elevesNbr);}Eleve ** lireEleves(int * elevesNbr) { printf("Entrer le nombre dlves : "); scanf("%d", elevesNbr); eleves = (Eleve**) calloc(*elevesNbr, sizeof(Eleve*)); for (p = eleves; p < eleves+elevesNbr; ++p) { *p = (Eleve*) calloc(1, sizeof(Eleve)); } return eleves;}116Eric Lecolinet - Tlcom ParisTech - Langage CTableaux de tableauxchar * jour[ ] = {"Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi","Dimanche",};c'est une autre manire de crer des tableaux bi-dimensionnelsAutres exemples tableau dobjets que lon veut trier tableau avec des lignes de longueurs diffrentesetc...117Eric Lecolinet - Tlcom ParisTech - Langage CRcursivitLes variables locales et les paramtres sont stocks dans la pile(sauf contenu des tableaux passs en argument)Exemplesint fact(int n) {if (n Eric Lecolinet - Tlcom ParisTech - Langage CParcours darbre#include void prefix(Node* n) {printf(" %s ", n->val);if (n->left) prefix(n->left);if (n->right) prefix(n->right);}void infix(Node* n) {if (n->left) infix(n->left);printf(" %s ", n->val);if (n->right) infix(n->right);}void postfix(Node* n) {if (n->left) postfix(n->left);if (n->right) postfix(n->right);printf(" %s ", n->val);}typedef struct NODE {struct NODE *left;char* val;struct NODE* right;} Node;Self-rfrence NODE !119Eric Lecolinet - Tlcom ParisTech - Langage CParcours darbreint main() {Node a = {NULL, "a", NULL}; /* feuilles */Node b = {NULL, "b", NULL};Node c = {NULL, "c", NULL};Node d = {NULL, "d", NULL};Node plus = {&a, "+", &b}; /* noeuds intermediaires */Node div = {&c, "/", &d};Node star = {&plus, "*", &div}; /* racine */prefix(&star);printf("\n");infix(&star);printf("\n");postfix(&star);printf("\n");return 0;}Rsultat ?120Eric Lecolinet - Tlcom ParisTech - Langage CEntres/sortiesType : FILE flux de donnes : entres/sorties bufferisesOuvrir un fichier FILE * fopen(const char * chemin, const char * mode)Fermer un fichier int fclose(FILE * fichier)121Eric Lecolinet - Tlcom ParisTech - Langage CExemplebool openFiles(const char * inputFileName, const char * outputFileName) {FILE * in = fopen(inputFileName, "r"); // r = mode lecture if (in == NULL) { fprintf(stderr, "Can't open input file %!s\n", inputFileName); return false;}FILE * out = fopen(outputFileName, "w"); // w = mode critureif (out == NULL) { fprintf(stderr, "Can't open output file %s!\n", outputFilename); return false;}while (!feof(in)) { ...}fclose(in); // ne pas oublier fclose() !fclose(out);return true;}122Eric Lecolinet - Tlcom ParisTech - Langage CEntres/sorties au format texteE/S formatesint fscanf(FILE* stream, const char* format, ...)int fprintf(FILE* stream, const char* format, ) renvoient le nombre dlments lus ou imprims entres/sorties depuis la console : pseudo-fichiers: stdin, stdout, stderr fonctions scanf() et printf()E/S par ligne char* fgets(char* str, int taille, FILE* stream)int fputs(const char* str, FILE* stream) fgets() renvoie str (ou NULL en cas derreur ou en fin de fichier)123Eric Lecolinet - Tlcom ParisTech - Langage CEntres/sorties binairesDepuis/dans un fichiersize_t fread(void* ptr, size_t size, size_t count, FILE* stream)size_t fwrite(const void* ptr, size_t size, size_t count, FILE* stream) plus rapides que les E/S formates mais pas portables il existe galement des fonctions de plus bas niveau : read() et write()124Eric Lecolinet - Tlcom ParisTech - Langage CComplmentsFin de fichier int feof(FILE * fichier)Synchronisation int fflush(FILE * fichier)Dplacement dans le fichier int fseek(FILE * flux, long offset, int from); // from = SEEK_SET, SEEK_CUR, SEEK_END long ftell(FILE * flux);125Eric Lecolinet - Tlcom ParisTech - Langage CDirectives de compilation#ifndef Person_h #define Person_h #include #include #if defined(RAW_POINTERS) # define PTR(TYPE) TYPE* #elif defined(INTRUSIVE_POINTERS) # include "intrusive_ptr.h" # define PTR(TYPE) intrusive_ptr #else # error "Undefined pointer mode" #endif #endif /* Person_h */126Ctypedef struct { char* name; long id; } User; User* createUser(const char* name, int id); void destroyUser(User*); void setUserName(User*, const char* name); void printUser(const User*); .... void foo() { User * u = createUser("Dupont"); setUserName(u, "Durand"); ..... destroyUser(u); u = NULL; }C++class User { char* name; // il faudrait utiliser string long id; public: User(const char* name, int id); virtual ~User(); virtual void setName(const char* name); virtual void print() const; .... }; void foo() { User * u = new User("Dupont"); u->setName("Durand"); .... delete u; u = nullptr; }Pseudo-objet en C127typedef struct User { int a; void (*print) (const struct User*); } User; typedef struct Player { // subclass User base; int b; } Player; void print(const User* u) { (u->print)(u); } void printUser(const User *u) { printf("printUser a=%d \n", u->a); } void printPlayer(const Player *u) { printf("printPlayer a=%d b=%d\n", u->base.a, u->b); }User* newUser() { User* p = (User*) malloc(sizeof(User)); p->a = 0; p->print = printUser; return p; } Player* newPlayer() { Player* p = (Player*) malloc(sizeof(Player)); p->base.a = 0; p->base.print = printPlayer; //cast ncessaire p->b = 0; return p; } int main() { Player* p = newPlayer(); p->base.a = 1; p->b = 2; print(p); }Pseudo-hritage en C128Eric Lecolinet - Tlcom ParisTech - Langage C

Recommended

View more >