Programmation en C Chapitre 1 Concepts de base I - Structure générale d’un programme en C #include <stdio.h> // declaration des fichiers d’en-tête //Décalaration des constantes // déclaration des types et fonctions //déclarations des variables globales int main()// Début du programme principal { // Déclaration des variables printf("Hello, world\n"); return 0 } Un programme est toujours subdivisé en plusieurs parties : Importation des bibliothèques #include<stdio.h> #include<conio.h> Selon ce que l'on souhaite faire dans notre programme, on peut avoir besoin de différentes fonctions. Celles-ci sont disponibles dans des bibliothèques. On parle aussi de fichier d’en-tête. Déclaration des constantes La valeur d'une constante ne doit jamais changée quelque soit l'instant où le programme est exécuté. La décalaration se fait par la syntaxe : #define nom_cte val où nom_cte est le nom utilisé pour le désigner dans le programme et val sa valeur fixée Exemple : #define DEUX 5 Corps du programme int main ( ) { printf ( "Bonjour à tous \n! " ) ; getch ( ) ; return 0 ; } La fonction main() est la fonction principale, un programme C n’a qu’une seule. Les instructions du main sont toujours placées entre alcollades, même la déclaration des variables. L’instruction return permet de retourner le résultat de la fonction. Pour le « main » cette valeur est généralement 0. La syntaxe générale de la fonction main() est la suivante : int main ( ) {déclaration des variables <instructions à exécuter> return 0 ; } Chaque instruction se termine toujours par un point-virgule getch() ; permet de suspendre l'exécution du programme jusqu'à ce que l'utilisateur appuie sur une touche. Cette fonction est dans la bibliothèque conio.h Commentaires Un commentaire est une séquence de caractères ignoré par le compilateur, on s'en sert pour expliquer des portions de code On délimite un commentaire par /* et */ ou sur la ligne par // (jusqu’à la fin de ligne). Par exemple /* Commentaire sur plusieurs lignes */ // Commentaire jusqu'à la fin de ligne Variables Chaque variable porte un nom permettant de l’identifier. Pour utiliser une variable, il faut toujours la déclarer avant. Cette déclaration peut se faire n’importe où dans le programme, mais la variable n’est visible que partout dans les accolades qui entourent cette déclaration. La déclaration suit la syntaxe suivante : <Type> <liste des variables> ; Exemple : Déclarer une variable n de type entier ……………………………………………………………………………….. II- Instructions de base Affectation Elle se fait avec le symbole = (variable = expression;) → Expression est évaluée est sa valeur sauvegardée dans variable. Exemple : Affecter à la variable n la valeur 5. ……………………………………………….. NB : on peut affecter la valeur initiale à la variable lors de sa déclaration. Exemple : Initialiser n à 10 lors de sa déclaration ……………………………….. Saisie des valeurs Pour récupérer les valeurs saisies par un utilisateur et la placer dans une variable var, on utilise la fonction suivante : scanf ( "%descripteur" , &var); Le programme attend jusqu'à ce que l'utilisateur ait saisi une valeur et valide. La valeur saisie est alors affectée à la variable <variable>. Attention à l’adresse &. Exemple : lire un entier n ; …………………………………… Affichage Pour afficher le contenu d’une variable à l’écran, on utilise la fonction : printf ( "%descripteur" , <variable >); Exemple : afficher le message et la variable n printf ( " la valeur lue est %d" ,n ) ; ou autre exemple printf ( " les valeurs sont x=%d , y=%d e t z = %d ’’, x , y , z ) ; Les caractères spéciaux : Fin de ligne : \n Tabulation : \t Types de données Trois types de base servent à représenter les entiers : Nom taille(t) nombre de valeurs Short Int Long 1 octet 2 octets 4 octets 28 valeurs 216 valeurs 232 valeurs chaîne format %hd %d %ld de Entiers non signés Par défaut, les entiers permettent de stocker des valeurs de signe quelconque. Il est préfixé de unsigned, Nom taille (t) nombre de valeur min valeur format valeurs max (28t) unsigned 1 octet 28 valeurs 0 28 -1 %hu short unsigned 2 octets 216 valeurs 0 216 -1 %u int unsigned 4 octets 232 valeurs 0 232 -1 %lu long Entiers signés Si par contre les données sont signées, on a comme plage de valeurs Nom taille (t) nombre de plus petite plus grande valeurs valeur valeur Short 1 octet 28 valeurs -27 27 - 1 Int 2 octets 216 valeurs -215 215 - 1 Long 4 octets 232 valeurs -231 231 - 1 Caractères Le type d’un caractère est char. Un char sert à représenter le code ASCII d'un caractère, il est donc codé sur 1 octet. Le descripteur d’un char est %c. Affectation char a ; ……………………………. Constantes Une constante est une valeur portant un nom, elles ne sont donc pas modifiables. On les définit dans l'entête de la source, juste en dessous des #include. La syntaxe est #define <NOM CONSTANTE> <valeurConstante>, Exemple : créer une constante Max ayant la valeur 100 ………………………………… Opérateurs Les opérateurs en C peuvent être d’arité 1 (opérateur unaire) ou 2 (opérateur binaire). Un opérateur peut être préfixé (opération avant l’opérande) ou postfixé (opérateur près opérande) Les opérateurs unaires Opposée L’opposée d’un nombre x s’obtient en –x. Complément binaire Le complément binaire d’une variable x s’obtient en ~x ; cet opérateur complémente bit à bit l’opérande x. Le cast Il consiste à convertir une variable à un type compatible, par exemple de l’entier au réel. Tous les opérateurs unaires sont de priorité équivalente, le parenthésage implicite est fait le plus à droite possible, on dit que ces opérateurs sont associatifs à droite. Opérateurs binaires décalages de bits 1. L'opération a >> n effectue n décalages des bits de la représentation binaire de a vers la droite. 2. L’opération a << n effectue n décalage des bits de la représentation binaire de a vers la gauche. NB : n est un entier positif. Opérations logiques 1. L'opérateur & permet de faire l’opération binaire ET de deux représentations binaires. 2. L'opérateur | permet de faire l’opération binaire OU de deux représentations binaires. 3. L'opérateur ^ associe à deux opérandes le OU exclusif de représentations Les deux opérateurs de décalage sont de priorité équivalente : >>, << ; les autres opérateurs ont une priorité inférieure à celle des précédents. Du plus prioritaire au moins on a: &, ^, |. & Opérateurs arithmétiques (*, /, %, +, -) Ils permettent de faire respectivement la multiplication, la division, le modulo, l’addition et la soustraction. Les multiplications et divisions sont prioritaires sur les sommes et différence : Noms opérateurs produit *, /, % Sommes +, Formes contractées Unaires Il est possible d'incrémenter (augmenter de 1) la valeur d'une variable i en écrivant i++, ou bien ++i. De la même façon on peut décrémenter (diminuer de 1) i en écrivant i-- (forme postfixe), ou bien –-i (forme préfixe). Binaires Toutes les affectations de la forme variable = variable operateurBinaire expression peuvent être contractées sous la forme variable operateurBinaire= expression. Avant a=a+b a=a–b a=a*b a=a/b a=a%b a=a&b a=a^b a=a|b après a += b a -= b a *= b a /= b a %= b a &= b a ^= b a |= b Traitements conditionnels Si ... Alors Syntaxe i f (<condi t ion >) { <Bloc instructions > } Les parenthèses ne sont pas obligatoires lorsque le bloc d’instructions contient une seule instruction. Comparaisons La formulation d'une condition se fait souvent à l'aide des opérateurs de comparaison. Les opérateurs de comparaison disponibles sont : Opérateurs Définitions == égalité ! Négation - complément <, <= Strictement inférieur à, inférieur ou égal à >, >= Strictement supérieur à, supérieur ou égal à Exemple : écrire un programme qui demande à l’utilisateur de lire un nombre n, puis affiche le message « nombre positif » si n est positif. …………………………………………………………………………………………………………… …………………………………………………………………………………………………………… …………………………………………………………………………………………………………… …………………………………………………………………………………………………………… …………………………………………………………………………………………………………… …………………………………………………………. Si ... Alors ... Sinon Syntaxe if (<condition >) { <bloc instructions 1 > } el se { <bloc instructions 2 > } Exemple : modifier l’exemple précédent les messages indiquant le signe du nombre lu. …………………………………………………………………………………………………………… …………………………………………………………………………………………………………… …………………………………………………………………………………………………………… …………………………………………………………………………………………………………… …………………………………………………………………………………………………………… ……………………………………………………………………………………………………… Opérateur ternaire En plaçant l'instruction suivante à droite d'une affectation, <variable> = (<condition >) ? <valeur si vrai> : < valeur si faux> ; Où Valeur si vrai: …………………………………………………………………………………………………. Valeur si faux : …………………………………………………………………………………………… condition :………………………………………………………………………………………. Exemple: donner l’expression pour calculer max le maximum de deux nombres n et m. ……………………………………………………………………………………. Switch La syntaxe est la suivante : switch(<nomvariable >) { case <valeur 1> : <bloc instructions 1 > ; break ; case <valeur 2> : <bloc instructions 2 > ; break ; ... case <valeur n> : <bloc instructions n > ; break ; default : <Bloc instructions par défaut> } NB : Le « break » à la fin permet de sortir du switch en sautant les valeurs suivantes. Exemple : écrire un programme qui lit un numéro compris entre 1 et 7 et affiche le jour de la semaine correspondant …………………………………………………………………………………………………………… …………………………………………………………………………………………………………… …………………………………………………………………………………………………………… …………………………………………………………………………………………………………… …………………………………………………………………………………………………………… …………………………………………………………………………………………………………… …………………………………………………………………………………………………………… …………………………………………………………………………………………………………… …………………………………………………………………………………………………………… …………………………………………………………………………………………………….. Booléens Une variable booléenne ne peut prendre que deux valeurs : vrai et faux. Il n'existe pas de type booléen à proprement parler en C. On utilise des int pour simuler le comportement des booléens. On représente la valeur booléenne faux avec la valeur entière 0, toutes les autres valeurs entières servent à représenter vrai. Utilisation dans des if Lorsqu'une condition est évaluée dans un test, cette condition prend à ce moment la valeur vrai si le test est vérifié, faux dans le cas contraire Connecteurs logiques Ils permettent de tester simultanément deux ou plusieurs expressions logiques dans la condition. Les connecteurs || et && représentent respectivement le OU et le ET logiques entre deux expressions booléennes, et peuvent s'appliquer à des valeurs (ou variables) entières Exemple : Ecrire une condition pour tester si un nombre n est paire et positif …………………………………………………………………………………………………………… ………………….. Les priorités Dans l’ordre décroissant, les priorités des opérations sont : Noms opérateurs opérateurs unaires cast, -, ~, !, ++, -Produit *, /, % Somme +, décalage binaire >>, << Comparaison >, <, >=, <= Egalité, différence ==, != ET binaire & OU Exclusif binaire ^ OU binaire | connecteurs logiques &&, || if ternaire () ? : Affectations =, +=, -=, : : : Préprocesseur Macro-instructions Ce sont des instructions écrites une fois et que l’on peut les appeler à n’importe quel endroit du programme pour faire une tâche. A la compilation, son code est simplement recopié à l’endroit où l’appel est fait. La syntaxe est : #define NOM_MACRO <instruction> Exemple : aller à la ligne suivante #define LS printf ( "\n" ) Et dans le programme, il suffira d’écrire : LS ; // comme toute autre instruction pour faire le saut de ligne. Il est possible de paramétrer les instructions du préprocesseur. Cela se fait en plaçant le paramètre entre parenthèses devant le nom de la macro. Exemple : calculer le double de n par une macro #define DOUBLE(n) (2* (n ) ) Et dans le programme, écrire DOUBLE(k) pour calculer 2*k. Boucles for for(<initialisation > ; <condition> ; <pas>) { <bloc instructions> } Exemple : écrire un programme qui lit un nombre n positif et affiche les nombres de 1 à n. …………………………………………………………………………………………………………… …………………………………………………………………………………………………………… …………………………………………………………………………………………………………… …………………………………………………………………………………………………………… ……………………………………. while while(<condition >) { <bloc instructions > } La condition est évaluée avant chaque passage dans la boucle, à chaque fois qu'elle est vérifiée, on exécute les instructions de la boucle. Exemple : lire une suite de nombres entiers qui se termine par un nombre négatif. …………………………………………………………………………………………………………… …………………………………………………………………………………………………………… …………………………………………………………………………………………………………… …………………………………………………………………………………………………………… ………………………………………. do ... while La syntaxe de cette boucle : do { <bloc instructions > } while(<condition >); Le fonctionnement est analogue à celui de la boucle tant que à quelques détails près : -la condition est évaluée après chaque passage dans la boucle. -On exécute le corps de la boucle tant que la condition est vérifiée. En C, la boucle répéter ... jusqu'à est en fait une boucle répéter ... tant que, c'està-dire une boucle tant que dans laquelle la condition est évaluée à la fin. Une boucle do ... while est donc exécutée donc au moins une fois. De la même façon que pour la boucle while, le compteur est initialisé avant le premier passage dans la boucle. Exemple : reprendre l’exemple précédent avec une boucle do…while …………………………………………………………………………………………………………… …………………………………………………………………………………………………………… …………………………………………………………………………………………………………… …………………………… On peut convertir une boucle for en boucle while en procédant de la sorte : <initialisation > while(<condition >) { <bloc instruction > <faire le pas> } Chapitre 2 : Types de données structurés I- Tableaux Un tableau est un regroupement de variables de même type, il est identifié par un nom. Chacune des variables du tableau est numérotée, ce numéro s'appelle un indice. Chaque variable du tableau est donc caractérisée par le nom du tableau et son indice. En C, les indices commencent toujours à 0. Déclaration La syntaxe est la suivante : <type> <nomdutableau>[<taille >] ; Exemple : Déclarer un tableau de 10 entiers. …………………………………………………………………………………………………………… Initialisation Il est possible d'initialiser les éléments d'un tableau à la déclaration, on fait cela comme pour des variables scalaires : <type> <nom>[<taille >] = <valeur d’initialisation >; On peut aussi disposer par ordre d'indice croissant en les séparant par des virgules les éléments du tableau. La syntaxe générale de la valeur d'initialisation est donc : <type> <nom>[<taille >] = {<valeur 0 >, <valeur 1 >, . . . , <valeur n-1>} Exemple : Déclarer un tableau initialisé par les valeurs 0,2,4,6,8; ………………………………………………………………….. Accès aux éléments Pour accéder à l’élément d’indice i, il faut faire T[i]. Il faut que i soit compris entre 0 et n-1. Généralement, on traite les éléments du tableau avec une boucle for. tableaux à plusieurs indices Déclaration La syntaxe est la suivante : <type> <nomdutableau>[<taille1 >][taille2]... ; Exemple : Déclarer une matrice de 3*3 entiers. ………………………………………………………………………………………………………… Initialisation Comme les tableaux à une dimension, il est possible d'initialiser les éléments d'un tableau à la déclaration, on fait cela comme pour des variables scalaires : <type> <nom>[<taille1 >][taille2] = {liste des valeurs}; Attention : le nombre d'éléments doit être ………………………………………. On peut aussi disposer les éléments ligne par ligne entre alcollades La syntaxe générale de la valeur d'initialisation est donc : <type> <nom>[<taille >] [ligne]= {{ligne1},{ligne2},….} II- Chaînes de caractères 1. Définition Une chaîne de caractères est un tableau de char contenant un caractère nul. Le caractère nul a 0 pour code ASCII et s'écrit '\0'. Les valeurs significatives de la chaîne de caractères sont toutes celles placées avant le caractère nul, donc le caractère nul est la fin de chaîn.. 2. Déclaration Comme une chaîne de caractères est un tableau de char, on le déclare : char <nom chaine>[<taille >] ; Exemple : déclarer une chaine de 200 caractères. Attention le dernier caractère est ‘\0’ ……………………………………… Initialisation On peut initialiser une chaîne à la déclaration : char <nom chaine>[<taille >] = <valeur_initiale>; valeur initiale :……………………………………………………………………………………….. Exemple : déclarer une chaîne initialisée à votre nom. …………………………………………………………………….. ; Accès aux éléments Par accéder à l’élément d’indice i+1 de la chaîne ch, il faut écrire la sorte : ch[i] Exemple : écrire un programme (instruction) pour tester si un caractère est en majuscule. ……………………………………………………………………………………………….. Affichage On peut afficher une chaîne comme un tableau de caractères, ou comme une chaîne avec le descripteur ‘%s’. Exemple : afficher la variable qui contient votre nom. Saisie Pour obtenir une chaîne ch par saisie au clavier, on utilise la fonction gets(ch) Une autre syntaxe est la suivante : fgets (<chaine >, <taille >, stdin ) ; La taille de la chaîne saisie est limitée par <taille>, caractère nul compris. Le résultat est placé dans <chaine>. Tous les caractères supplémentaires saisis par l'utilisateur ne sont pas placés dans <chaine>, seuls les (<taille> - 1) premiers caractères sont récupérés par fgets. Nous saisirons donc la phrase de notre programme de la sorte : fgets ( c , 200 , stdin ) ; La bibliothèque string.h Elle propose des fonctions de maniement de chaînes de caractères, à savoir : strcmp : comparer deux chaînes. strlen : longueur d'une chaîne de caractères strsubs : rechercher une sous-chaîne strcat : concaténer deux chaînes strcpy : copier une chaîne Il vous est conseillé d'examiner de quelle façon fonctionnent ces fonctions, et comment elles gèrent le caractère nul. III- Les pointeurs L'opérateur & pour désigner l’adresse d’une lvalue. D’une manière générale, le langage C permet de manipuler des adresses par l’intermédiaire de variables nommées pointeurs. Considérons les instructions : int * ad ; int n ; n = 20 ; ad = &n ; *ad = 30 ; La première réserve une variable nommée ad comme étant un pointeur sur des entiers. * est un opérateur qui désigne le contenu de l’adresse qui le suit. Ainsi, à titre mnémonique, on peut dire que cette déclaration signifie que *ad. Une variable pointeur ad a été déclarée ainsi : int * ad ; une expression telle que : ad + 1 a un sens pour C. En effet, ad est censée contenir l’adresse d’un entier et, pour C, l’expression cidessus représente l’adresse de l’entier suivant. En ptr++ avance ptr du nombre sizeof(). Par exemple ad++ avance ad de sizeof(int). Supposons, par exemple, que l’on effectue la déclaration suivante : int t[10] ; La notation t est alors totalement équivalente à &t[0] . L’identificateur t est considéré comme étant de type pointeur sur le type correspondant aux éléments du tableau, c’est-à-dire, int *. Ainsi, les notations équivalentes : t+1 → &t[1] t+i → &t[i] t[i] → * (t+i) Pour illustrer ces nouvelles possibilités de notation, voici plusieurs façons de placer la valeur 1 dans chacun des 10 éléments de notre tableau t : for (int i=0 ; i<10 ; i++) * (t+i) = 1 ; V- Les structures et les énumérations 1. Structure Il s'agit de l'équivalent de l'enregistrement en algorithmique. Déclaration d’une structure Voyez tout d’abord cette déclaration : struct enreg { type champ ; type champ ; type champ ; ……. }; Celle-ci définit un modèle de structure mais ne réserve pas de variables correspondant à cette structure. Ce modèle s’appelle ici enreg et il précise le nom et le type de chacun des champs constituant la structure. Déclaration d'une variable struct enreg var exemple : un article est caractérisé par un numéro, une quantité et un prix. Donner la déclaration. struct enreg { int numero ; int qte ; float prix ; }; struct enreg art1, art2 ; On peut aussi procéder de la manière suivante : struct article { int numero ; int qte ; float prix ; } art1, art2 ; En mettant le mot typedef à la création, cela évite d'utiliser le mot struct à la création des variables. Utilisation La désignation d’un champ se note en faisant suivre le nom de la variable structure de l’opérateur « point » ( . ) (comme en algorithmique) suivi du nom de champ tel qu’il a été défini dans le modèle (le nom de modèle lui-même n’intervenant d’ailleurs pas). Exemple : art1.qte=20 ; printf ("%e", art1.prix) ; scanf ("%e", &art2.prix) ; art1.numero++ ; Il est possible d’affecter à une structure le contenu d’une structure définie à partir du même modèle. Par exemple, si les structures art1 et art2 ont été déclarées suivant le modèle enreg défini précédemment, nous pourrons écrire : art1 = art2 ; Une telle affectation globale remplace avantageusement : art1.numero = art2.numero ; art1.qte = art2.qte ; art1.prix = art2.prix ; Initialisation On peut initilisaer une structure de la manière : struct enreg var={val1, val2,…} Attention : les valeurs sont dans l'ordre des champs à la création de la structure. Exemple : struct article art1 = { 100, 285, 2000 } ; Chapitre 3 : les sous programmes I - Les procédures Une procédure est un ensemble d'instructions portant un nom. La syntaxe de définition est : void nomprocedure (paramètres) { <bloc d’instructions> } Son exécution se fait comme celle d’une instruction en utilisant son nom. Exemple : printf(……….) La procédure main() désigne la principale et se lance automatiquement au début du programme. Variables locales Dans une procédure, il est possible de définir les variables, ces variables sont traitées de variables locales. Elles sont déclarées comme dans la procédure main(). Les variables locales ne sont visibles que dans la procédure où elles ont été déclarées. La structure d’une procédure est la suivante : void nomprocedure (paramètres) { /* Declaration des variables locales */ <bloc d’instructions> } Passage de paramètres Il est possible que la valeur d'une variable locale d'une procédure ne soit connue qu'au moment de l'appel de la procédure. A l’appel d’une procédure, les paramètres effectifs lui sont communiqués. Chaque paramètre N°i représente l’argument N°i de la définition ou de la déclaration. Les types doivent être respectés. Ces paramètres doivent être des variables déclarées dans la procédure appelante. Exemple : écrire une procédure qui prend un entier n en paramètres et affiche tous les nombres compris entre 0 et n. Ecrire la procédure main() qui lit un entier m et passe en paramètre à la procédure. …………………………………………………………………………………………………………… …………………………………………………………………………………………………………… …………………………………………………………………………………………………………… …………………………………………………………………………………………………………… …………………………………………………………………………………………………………… …………………………………………………………………………………………………………… …………………………………………………………………………………………………………… …………. II- Les fonctions principe Nous avons vu qu'un sous-programme appelant peut communiquer des valeurs au sous-programme appelé. Il est aussi possible pour un sous-programme appelé de communiquer une valeur au sous-programme appelant. Une fonction est un sous-programme qui communique une valeur au sous-programme appelant. Cette valeur s'appelle valeur de retour, ou valeur retournée. La syntaxe de définition d’une fonction est : Type nomFonction (paramètres) { /* Declaration des variables locales */ <bloc d’instructions> Return <valeur de retour> } Return : …………………………………………………………………………………………………………… …………. NB : en C les procédures sont les fonctions qui ont pour type void. La syntaxe pour appeler une fonction est : v = nomFonction (paramètres) ; L'instruction ci-dessus place dans la variable v la valeur retournée par la fonction nomFonction quand lui passe les paramètres. Exemple : écrire une fonction qui prend un nombre en paramètre et retourne son carré. Appelez cette fonction dans le main(). Passages de paramètre par référence En C, lorsque vous invoquez une fonction, toutes les valeurs des paramètres effectifs sont recopiés dans les paramètres formels. On dit dans ce cas que le passage de paramètre se fait par valeur. Dans ce cas seule la valeur de retour vous permettra de communiquer une valeur au programme appelante une seule valeur. Lorsque vous passez un tableau en paramètre, la valeur qui est recopiée dans le paramètre formel est l'adresse de ce tableau (l'adresse est une valeur scalaire). Par conséquent toute modification effectuée sur les éléments d'un tableau dont l'adresse est passée en paramètre par valeur sera repercutée sur le paramètre effectif (i.e. le tableau d'origine). On dit alors le paramètre passé par Référence. Donc un paramètre doit contenir un résultat à la fin d’une procédure, il faut le passer par référence. Les règles sont les suivantes : Les variables scalaires se passent en paramètre par valeur Les variables non scalaires se passent en paramètre par référence Une fonction ne peut retourner que des valeurs scalaires chapitre 4 : Fichiers Définitions Le problème qui se pose est que lorsque l'on sort de ce programme, les données saisies sont perdues. Si l'on souhaite les avoir à disposition pour d'une exécution ultérieure, il convient d'utiliser un fichier. Un fichier peut être vu comme une mémoire stockée de façon permanente sur un disque et à laquelle on accède avec un nom. Les données dans un fichier se présentent de façon séquentielle, et donc se lisent ou s'écrivent du début vers la fin. Ouverture et fermeture Pour accéder au contenu d'un fichier en lecture ou en écriture, on utilise la fonction fopen() et pour fermer la fonction fclose(). La fonction fopen() fopen permet, comme son nom l'indique, d'ouvrir un fichier. Sa syntaxe est : FILE *fopen(const char *chemin, const char *mode) ; Où Chemin : ……………………………………………………………… ……………………………… …………………………………………………………………………………………………………… …………………….. mode : …………………………………………………… ………………………………………… FILE* est un type permettant de référencer un fichier ouvert, La fonction fopen retourne NULL s'il est impossible d'ouvrir le fichier. La valeur retournée devra être placée dans une variable de type FILE*, c'est cette valeur qui permettra par la suite d'accéder au contenu du fichier. La fonction fclose fclose sert à fermer un fichier. Son prototype est int fclose(FILE *fp) ; Cette fonction retourne 0 si la fermeture s'est bien passée. Dans le cas contraire, des indications sur l'erreur survenue sont accessibles dans des variables globales. Utilisation Exemple : Ouvrir et fermer le fichier des étudiants …………………………………………………………………………………………………………… …………………………………………………………………………………………………………… …………………………………………………………………………………………. Lecture et écriture Il existe plusieurs façons de lire dans un fichier : caractère par caractère, ligne par ligne, par paquets de caractères, etc. Chaque lecture se fait à l'aide d'une fonction appropriée. Lors d'un traitement se faisant à partir d'une lecture dans un fichier, on appelle de façon itérée une fonction de lecture faisant avancer un curseur dans un fichier jusqu'à ce que la fin du fichier soit atteinte. L'écriture fonctionne de façon analogue, à un détail près : il est inutile d'écrire le caractère de fin de fichier, il est ajouté automatiquement lors du fclose. Caractère par caractère La fonction int fgetc(FILE* stream) retourne un caractère lu dans le fichier f. Bien que le caractère lu soit un octet, il est retourné dans un int. Le caractère EOF indique que la fin du fichier a été atteinte. Exemple: afficher le contenu du fichier des étudiants #include<stdio.h> int main ( ) { FILE* f ; char c ; f = fopen ( "toto.txt " , " r " ) ; i f ( f == NULL) {printf ( "Erreur lors de l 'ouverture du fichier toto.txt \n" ) ; return -1;} while ( ( c = fgetc ( f ) ) != EOF) printf ( " %c” , c ) ; i f ( fclose ( f ) != 0) {printf ( "Erreur lors de l a fermeture du fichier toto.txt \n" ) ; return -1;} return 0 ; } On écrit un caractère dans un fichier à l'aide de la fonction int fputc(int c, FILE* stream) ; Par chaînes de caractères Les deux fonctions char *fgets(char *s, int size, FILE *stream) et int fputs(const char*s, FILE *stream) permettent de lire et d'écrire des chaînes de caractères dans des fichiers. Par paquets Les deux fonctions size t fread(void *ptr, size t size, size t nmemb, FILE *stream) et size t fwrite(const void *ptr, size t size, size t nmemb, FILE *stream) sont très utiles lorsque l'on veut sauvegarder un tableau dans un fichier, ou recopier un fichier dans un tableau.