Cours gratuits » Cours informatique » Cours programmation » Cours langage C » Cours C 2 Types entrees sorties de base et structures de controle

Cours C 2 Types entrees sorties de base et structures de controle


Télécharger



★★★★★★★★★★3.5 étoiles sur 5 basé sur 1 votes.
Votez ce document:

Cours C 2 Types entrees sorties de base et structures de controle

Comme nous l'avons vu, le langage C est de bas niveau. La bibliothèque du langage C fournit des traitements assez courants de plus haut niveau et permet, entre autres, la réalisation des entrées-sorties. La bibliothèque standard contient :

  1. les fonctions permettant la gestion des entrées-sorties (E/S);
  2. des fonctions de manipulation de chaînes de caractères;
  3. des fonctions d'allocation dynamique de mémoire;
  4. des fonctions à caractère général qui permettent l'accès au s
ystème.

Ces fonctions et les structures associées sont décrites dans le fichier <stdio.h>. Tout programme désirant manipuler les E/S devra contenir la directive : #include <stdio.h>. Ce fichier contient : ➫ la définition de macro-expressions;

 ➫ le prototype des fonctions;

➫ la définition de constantes : EOF (cf. note de bas de page 1, page 39), etc;

➫ la définition du tableau des fichiers ouverts.

Le langage C donne une vision « UNIXienne » des E/S. La même interface d'accès aux fichiers peut être utilisée sur les périphériques; ainsi, même l'écran et le clavier qui permettent la communication avec l'utilisateur, seront appelés fichier ou flux.

En langage C, un fichier est une suite d'octets (un caractère 1 octet). Le fichier n'a pas de structure propre qui lui est attachée. Il est cependant possible au niveau programme de considérer un fichier comme une suite d'enregistrements correspondant à une structure. Le principe de la manipulation d'un fichier est le suivant :

  1. ouverture du fichier;
  2. lecture, écriture, et déplacement dans le fichier;
  3. fermeture du fichier.

En ce qui concerne les flux de communication avec l'utilisateur, l'ouverture et la fermeture sont effectuées automatiquement.

11.1 Entrées-sorties standard

Ce sont des fonctions pré-définies qui permettent de réaliser les opérations suivantes : ➫ lecture et écriture caractère par caractère;

➫ lecture et écriture ligne par ligne;

➫ lecture et écriture formatées.

11.1.1 Échanges caractère par caractère

Dans ces échanges, l'unité de base est le caractère que le système considère comme un octet parfois réduit à une version de l'ASCII sur sept bits.

Les deux fonctions que nous présentons ici sont souvent des macro-expressions du préprocesseur (voir chapitre 7), nous les considérerons comme des fonctions pour simplifier la présentation.

int getchar(void);

synopsis : cette fonction permet de lire un caractère sur l'entrée standard s'il y en a un. Ce caractère est considéré comme étant du type unsigned char.

argument : rien.

retour : la fonction retourne un entier pour permettre la reconnaissance de la valeur de fin de fichier (EOF). L'entier contient soit la valeur du caractère lu soit EOF.

conditions d'erreur : en fin de fichier la fonction retourne la valeur EOF. int putchar(int);

synopsis : Cette fonction permet d'écrire un caractère sur la sortie standard.

argument : Elle est définie comme recevant un entier1 pour être conforme à getchar(). Ceci permet d'écrire putchar(getchar()).

retour : Elle retourne la valeur du caractère écrit toujours considéré comme un entier. conditions d'erreur : en cas d'erreur la fonction retourne EOF.

 LE programme 11.1 réalise la lecture de son fichier standard d'entrée caractère par caractère et reproduit les caractères sur son fichier standard de sortie.

Prog. 11.1 Lecture et écriture caractère par

caractère sur les E/S standard.

#include <stdio.h>

void main(){

int c;

while(( cgetchar ()) ! EOF)

putchar(c);

}

11.1.2 Échanges ligne par ligne

Dans ces échanges, l'unité de base est la ligne de caractères. La ligne est considérée comme une suite de caractères char terminée par un caractère de fin de ligne ou par la détection de la fin du fichier. Le caractère de fin de ligne a une valeur entière égale à 10 et est représenté par l'abréviation '\n'.

char* gets(char*);

synopsis : lire une ligne sur l'entrée standard; les caractères de la ligne sont rangés (un caractère par octet) dans la mémoire à partir de l'adresse donnée en argument à la fonction. Le retour chariot est lu mais n'est pas rangé en mémoire. Il est remplacé par le caractère nul '\0' de manière à ce que la ligne, une fois placée en mémoire, puisse être utilisée comme une chaîne de caractères.

argument : l'adresse d'une zone mémoire dans laquelle la fonction doit ranger les caractères lus.

retour : Si des caractères ont été lus, la fonction retourne l'adresse de son argument pour per-mettre une imbrication dans les appels de fonction.

conditions d'erreur : Si la fin de fichier est atteinte, lors de l'appel (aucun caractère n'est lu), la fonction retourne un pointeur de caractère de valeur 0 ou NULL (défini dans <stdio.h».

remarque : Cette fonction ne peut pas vérifier que la taille de la ligne lue est inférieure à la taille de la zone mémoire dans laquelle il lui est demandé de placer les caractères. Il faut lui préférer la fonction fgets() pour tout logiciel de qualité.

int puts(char*);

synopsis : cette fonction permet d'écrire une chaîne de caractères, suivie d'un retour chariot sur la sortie standard.

argument : l'adresse d'une chaîne de caractères.

retour : une valeur entière non négative en cas de succès.

conditions d'erreur : Elle retourne la valeur EOF en cas de problème.

Le programme 11.2 est une nouvelle version du programme précédent, cette fois-ci ligne par ligne. Le choix d'un tableau de 256 caractères permet d'espérer qu'aucune ligne lue ne provoquera un débordement par la fonction gets(). Ceci reste un espoir et peut être démenti si le programme est confronté à une ligne de plus grande taille, dans ce cas le comportement du programme est non défini.

 Prog. 11.2 Lecture ligne par ligne sur les fi

chiers standard.

#include <stdio.h> void main(){

char BigBuf [256];

while(gets (BigBuf)!~NULL)

puts (BigBuf) ;

}

11.1.3 Échanges avec formats

Les fonctions permettant de faire des E/S formatées sur les fichiers standard d'entrée et de sortie sont les suivantes :

int scanf(const char*, ...);

synopsis : lecture formatée sur l'entrée standard.

arguments : comme l'indique la spécification "...", cette fonction accepte une liste d'arguments variable à partir du second argument.

  1. le premier argument est une chaîne de caractères qui doit contenir la description des variables à saisir.
  2. les autres arguments sont les adresses des variables (conformément à la description donnée dans le premier argument) qui sont affectées par la lecture.

retour : nombre de variables saisies.

conditions d'erreur : la valeur EOF est retournée en cas d'appel sur un fichier standard d'entrée fermé.

int printf(const char*, ...);

synopsis : écriture formatée sur la sortie standard a

arguments : chaîne de caractères contenant des commentaires et des descriptions d'arguments à écrire, suivie des valeurs des variables.

retour : nombre de caractères écrits.

conditions d'erreur : la valeur EOF est retournée en cas d'appel sur un fichier standard de sortie fermé.

Des exemples de formats sont donnés dans le tableau 3.1, page 23. Les possibilités en matière de format sont données de manière exhaustive dans la partie sur les E/S formatées (voir section 11.5).

11.2 Ouverture d'un fichier

Tout fichier doit être ouvert pour pouvoir accéder à son contenu en lecture, écriture ou modification.

L'ouverture d'un fichier est l'association d'un objet extérieur (le fichier) au programme en cours d'exécution. Une fonction d'ouverture spécifie le nom du fichier à l'intérieur de l'arborescence du système de fichiers et des attributs d'ouverture.

L'ouverture d'un fichier est réalisée par la fonction fopen selon la description suivante : FILE* fopen(const char*, const char* );

synopsis : ouverture d'un fichier référencé par le premier argument (nom du fichier dans le système de fichiers sous forme d'une chaîne de caractères) selon le mode d'ouverture décrit par le second argument (chaîne de caractères).

arguments :

  1. la première chaîne de caractères contient le nom du fichier de manière à référencer le fichier dans l'arborescence. Ce nom est dépendant du système d'exploitation dans lequel le programme s'exécute.
  2. Le deuxième argument est lui aussi une chaîne de caractères. Il spécifie le type d'ouver¬ture.

retour : pointeur sur un objet de type FILE (type défini dans <stdio.h» qui sera utilisé par les opérations de manipulation du fichier ouvert (lecture, écriture ou déplacement).

conditions d'erreur : le pointeur NULL est retourné si le fichier n'a pas pu être ouvert (pro¬blèmes d'existence du fichier ou de droits d'accès).

Le type d'ouverture est spécifié à partir d'un mode de base et de compléments. A priori, le fichier est considéré comme une fichier de type texte (c'est-à-dire qu'il ne contient que des caractères ASCII).

Le type d'ouverture de base peut être :

➫ "r" le fichier est ouvert en lecture. Si le fichier n'existe pas, la fonction ne le crée pas.

➫ "w" le fichier est ouvert en écriture. Si le fichier n'existe pas, la fonction le crée. Si le fichier existe la fonction le vide.

? "a" le fichier est ouvert en ajout. Si le fichier n'existe pas, la fonction le crée. Les écritures auront lieu à la fin du fichier. Le type d'ouverture peut être agrémenté de deux caractères qui sont :

? "b" le fichier est considéré en mode binaire. Il peut donc contenir des données qui sont transférées sans interprétation par les fonctions de la bibliothèque.

➫ "+" le fichier est ouvert dans le mode complémentaire du mode de base. Par exemple s'il est ouvert dans le mode "r+" cela signifie qu'il est ouvert en mode lecture et plus, soit lecture et écriture.

La combinaison des modes de base et des compléments donne les possibilités suivantes :

➫ "r+" le fichier est ouvert en lecture plus écriture. Si le fichier n'existe pas, la fonction ne le crée pas. Le fichier peut être lu, modifié et agrandi.

➫ "w+" le fichier est ouvert en écriture plus lecture. Si le fichier n'existe pas, la fonction le crée. Si le fichier existe, la fonction le vide. Le fichier peut être manipulé en écriture et relecture.

➫ "a+" le fichier est ouvert en ajout plus lecture. Si le fichier n'existe pas, la fonction le crée. Les écritures auront lieu à la fin du fichier. Le fichier peut être lu.

➫ "rb" le fichier est ouvert en lecture et en mode binaire. Si le fichier n'existe pas, la fonction ne le crée pas.

➫ "wb" le fichier est ouvert en écriture et en mode binaire. Si le fichier n'existe pas, la fonction le crée. Si le fichier existe, la fonction le vide.

➫ "ab" le fichier est ouvert en ajout et en mode binaire. Si le fichier n'existe pas, la fonction le crée. Les écritures auront lieu à la fin du fichier.

➫ "r+b" ou "rb+"le fichier est ouvert en lecture plus écriture et en mode binaire. Si le fichier n'existe pas, la fonction ne le crée pas. Le fichier peut être lu, modifié et agrandi.

➫ "w+b" ou "wb+" le fichier est ouvert en écriture plus lecture et en mode binaire. Si le fichier n'existe pas, la fonction le crée. Si le fichier existe, la fonction le vide. Le fichier peut être écrit puis lu et écrit.

➫ "a+b" ou "ab+" le fichier est ouvert en ajout plus lecture et en mode binaire. Si le fichier n'existe pas, la fonction le crée. Les écritures auront lieu à la fin du fichier.

La fonction fopen() retourne un descripteur de fichier qui servira pour toutes les autres opérations. Le descripteur de fichier doit être déclaré comme dans l'exemple : si le système ne peut pas ouvrir le

fichier, il retourne un descripteur de fichier égal au pointeur NULL. Si un fichier qui n'existe pas est ouvert en mode écriture ou ajout, il est créé par le système.

Prog. 11.3 Ouverture d'un fichier.

#include <stdio .h< void main(){ FILE* MyFich;

MyFich fopen("d:\temp\passwd" ,"r") ;

}

11.3 Fermeture d'un fichier

Avant d'étudier les fonctions permettant d'accéder aux données d'un fichier ouvert, considérons la fonction qui permet de terminer la manipulation d'un fichier ouvert. Cette fonction réalise la fermeture du fichier ouvert. Elle a le prototype suivant :

int fclose(FILE*);

synopsis : c'est la fonction inverse de fopen. Elle détruit le lien entre le descripteur de fichier ouvert et le fichier physique. Si le fichier ouvert est en mode écriture, la fermeture provoque l'écriture physique des données du tampon (voir 11.7).

arguments : un descripteur de fichier ouvert valide. retour : 0 dans le cas normal.

conditions d'erreur : la fonction retourne EOF en cas d'erreur.

Tout programme manipulant un fichier doit donc être encadré par les deux appels de fonctions fopen() et fclose() comme le montre le programme 11.4.

Prog. 11.4 Ouverture et fermeture d'un fichier.

#include <stdio .h< void main(){ FILE* MyFich;

MyFich fopen("d:\temp\passwd" ,"r") ;

fclose (MyFich) ;

}

11.4 Accès au contenu du fichier

Une fois le fichier ouvert, le langage C permet plusieurs types d'accès à un fichier :

➫ par caractère,

➫ par ligne,

➫ par enregistrement,

➫ par données formatées.

Dans tous les cas, les fonctions d'accès au fichier (sauf les opérations de déplacement) ont un com¬portement séquentiel. L'appel de ces fonctions provoque le déplacement du pointeur courant relatif au fichier ouvert. Si le fichier est ouvert en mode lecture, les opérations de lecture donnent une im¬pression de consommation des données contenues dans le fichier jusqu'à la rencontre de la fin du fichier.

11.4.1 Accès caractère par caractère

Les fonctions suivantes permettent l'accès caractère par caractère ~ int fgetc(FILE*);

synopsis : lit un caractère (unsigned char) dans le fichier associé; argument : descripteur de fichier ouvert;

retour : la valeur du caractère lu promue dans un entier;

conditions d'erreur : à la rencontre de la fin de fichier, la fonction retourne EOF et positionne les indicateurs associés (voir section 11.8).

int getc(FILE*);

synopsis : cette fonction est identique à fgetc() mais peut être réalisée par une macro définie dans <stdio.h>.

int ungetc(int, FILE*);

synopsis : cette fonction permet de remettre un caractère dans le buffer de lecture associé à un flux d'entrée.

int fputc(int , FILE*);

synopsis : écrit dans le fichier associé décrit par le second argument un caractère spécifié dans le premier argument. Ce caractère est converti en un unsigned char;

argument : le premier argument contient le caractère à écrire et le second contient le descripteur de fichier ouvert;

retour : la valeur du caractère écrit promue dans un entier sauf en cas d'erreur;

conditions d'erreur : en cas d'erreur d'écriture, la fonction retourne EOF et positionne les in-dicateurs associés (voir section 11.8).

int putc(int , FILE*);

synopsis : cette fonction est identique à fputc() mais elle est réalisée par une macro définie dans <stdio.h>.

Les fonctions (macros) getc() et putc() sont en fait la base de getchar() et putchar() que nous avons utilisées jusqu'ici.

➫ putchar(c) est défini comme putc(c,stdout);

➫ getchar() est défini comme getc(stdin).

Comme getchar(), la fonction getc() retourne un entier pour pouvoir retourner la valeur EOF en fin de fichier. Dans le cas général, l'entier retourné correspond à un octet lu dans le fichier et rangé dans un entier en considérant l'octet comme étant du type caractère non signé (unsigned char).

Voici un exemple d'écriture à l'écran du contenu d'un fichier dont le nom est donné en argument. Le fichier est ouvert en mode lecture et il est considéré comme étant en mode texte.

 Prog. 11.5 Lecture caractère par caractère d'un fichier après ouverture.

#include <stdio.h<

void main(int argc , char** argv){ if(argc ! 2) return 1;

FILE* MyFichfopen ( argv [1] , "r") ;

if (MyFic NULL) {

printf ("Ouverture Aimpossible A%s AAn" , argv [1]) ; return 2;

}

int TheCar ;

while((TheCarfgetc (MyFic) )!EOF) fputc (TheCar, stdout) ;

fclose (MyFic) ;

}

11.4.2 Accès par ligne

Comme pour les E/S standards, il est possible de réaliser des opérations de lecture et d'écriture ligne par ligne à l'intérieur de fichiers ouverts. Cet accès ligne par ligne se fait grâce aux fonctions :

char* fgets(char*, int , FILE*);

synopsis : lit une ligne de caractères dans le fichier associé, les caractères de la ligne sont rangés dans la mémoire à partir de l'adresse donnée en argument à la fonction. Le retour chariot est lu et rangé en mémoire. Il est suivi par le caractère nul '\0' de manière à ce que la ligne, une fois placée en mémoire, puisse être utilisée comme une chaîne de caractères.

arguments :

  1. adresse de la zone de stockage des caractères en mémoire,
  2. nombre maximum de caractères (taille de la zone de stockage),
  3. et descripteur de fichier ouvert.

retour : adresse reçue en entrée sauf en cas d'erreur;

conditions d'erreur : à la rencontre de la fin de fichier, la fonction retourne NULL et positionne les indicateurs associés (voir section 11.8).

int fputs(const char*, FILE*);

synopsis : cette fonction permet d'écrire une chaîne de caractères référencée par le premier argument dans le fichier décrit par le second argument.argument:

  1. le premier argument contient l'adresse de la zone mémoire qui contient les caractères à écrire. Cette zone doit être un chaîne de caractères (terminée par le caractère nul). Elle doit contenir un retour chariot pour obtenir un passage à la ligne suivante.
  2. le second argument contient le descripteur de fichier ouvert dans lequel les caractères seront écrits.

retour : une valeur positive si l'écriture s'est correctement déroulée. conditions d'erreur : en cas d'erreur d'écriture, la fonction retourne EOF et positionne les in-dicateurs associés (voir section 11.8).

Pour la lecture ligne à ligne, il est nécessaire de donner l'adresse d'un tableau pouvant contenir la ligne. De plus, il faut donner la taille de ce tableau pour que la fonction fgets ne déborde pas du tableau. La fonction fgets() lit au plus n-1 caractères et elle ajoute un caractère nul ('\0') après le dernier caractère qu'elle a mis dans le tableau. La rencontre du caractère de fin de ligne ou de la fin de fichier provoque la fin de lecture. Le caractère de fin de ligne n'est pas mis dans le tableau avant le caractère nul.

La fonction fputs() écrit une ligne dans le fichier. Le tableau de caractères doit être terminé par un caractère nul ('\0'). Il faut mettre explicitement la fin de ligne dans ce tableau pour qu'elle soit présente dans le fichier.

Voici le programme précédent écrit à l'aide de ces fonctions :

Prog. 11.6 Lecture ligne à ligne d'un fichier après ouverture.

#include <stdio.h<

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

if(argc!2) return 1;

FILE* TheFicfopen ( argv [1] , "r") ;

if (TheFic NULL) {

printf ("Ouverture Aimpossible A%s AAn" , argv [1]) ; return 2;

}

char BigBuf[256];

while( fgets (BigBuf, sizeof(BigBuf) , TheFic) ! NULL )

fputs (BigBuf , stdout) ;

fclose (TheFic) ;

}

Les différences entre gets() et fgets(), d'une part, et puts() et fputs(), d'autre part, peuvent s'expliquer par le fait que les fonctions puts et gets agissent sur les E/S standards qui sont le plus souvent des terminaux (écran + clavier).

Les différences sont les suivantes : ➫ la fonction gets() :

  1. ne nécessite pas que lui soit fournie la taille du tableau de lecture. Il faut espérer que les lignes saisies seront plus courtes que la taille du tableau. Comme ces lignes viennent a priori d'un terminal, elles font souvent moins de 80 caractères.
  2. ne met pas le caractère de fin de ligne dans le tableau. Ce caractère est remplacé par le caractère de fin de chaîne.

➫ la fonction puts() : ne nécessite pas la présence du caractère de fin de ligne dans le tableau. Ce caractère est ajouté automatiquement lors de l'écriture.

11.4.3 Accès par enregistrement

L'accès par enregistrement permet de lire et d'écrire des objets structurés dans un fichier. Ces objets structurés sont le plus souvent représentés en mémoire par des structures. Pour ce type d'accès, le fichier doit être ouvert en mode binaire (voir exemple 11.7 ligne 11). Les données échangées ne sont pas traitées comme des caractères.

 L'accès par enregistrement se fait grâce aux fonctions :

➫ size_t fread (void* Zone, size_t Taille, size_t Nbr, FILE* fp);

➫ size_t fwrite(void* Zone, size_t Taille, size_t Nbr, FILE* fp);

Ces fonctions ont une interface homogène. Elles acceptent une liste identique d'arguments, et re  tournent le même type de résultat. Les arguments sont les suivants :

  1. le premier argument, que nous avons appelé Zone, est l'adresse de l'espace mémoire à partir duquel l'échange avec le fichier est fait. L'espace mémoire correspondant reçoit les enregistrements lus, ou fournit les données à écrire dans les enregistrements. Il faut, bien entendu, que l'espace mémoire correspondant à l'adresse soit de taille suffisante pour supporter le transfert des données, c'est-à-dire d'une taille au moins égale à (Taille* Nbr).
  2. le deuxième argument, que nous avons appelé Taille, est la taille d'un enregistrement en nombre d'octets.
  3. le troisième argument, que nous avons appelé Nbr, est le nombre d'enregistrements que l'on désire échanger.
  4. le dernier argument, que nous avons appelé fp, est un descripteur de fichier ouvert dans un mode de transfert binaire.

Ces deux fonctions retournent le nombre d'enregistrements échangés. Elles ont été conçues de manière à permettre l'échange de plusieurs structures, ce qui explique la présence des deux arguments qui fournissent la taille totale des données à transférer.

Voici un exemple d'utilisation de la fonction fread(). Cet exemple est une lecture du contenu d'un fichier appelé FicParcAuto avec stockage du contenu de ce fichier dans un tableau en mémoire ParcAuto. Les cases du tableau sont des structures contenant un entier, une chaîne de vingt caractères et trois chaînes de dix caractères.

Prog. 11.7 Lecture d'enregistrements dans un fichier.

#include <stdio.h> #include <stddef .h>

struct auto { int age;

char couleur [20] , numero[10] , type [10] , marque [10];

} ParcAuto [ 2 0 ] ;

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

FILE* TheFicfopen ( argv [1] , "rb+") ;

if (TheFic NULL) {

printf ("Ouverture Aimpossible A%s AAn" , argv [1]) ; return 1;

}

size~t fait ;

for (int i 0; i <20; i++){

faitfread(kParcAuto[ i ] , sizeof(struct auto) , 1, TheFic) ;

if ( fait ! 1) {

printf ("Erreur Alecture A%s AAn" , argv [1]) ;

return 2;

}

}

fclose (TheFic) ;

}

Il est possible de demander la lecture des vingt enregistrements en une seule opération, en remplaçant les lignes 18 à 24 par les lignes suivantes :

faitfread(ParcAuto, sizeof(struct auto), 20, TheFic); ou bien encore par :

faitfread(ParcAuto, sizeof(ParcAuto) , 1, TheFic) ;

11.5 Entrées-sorties formatées

Nous avons déjà vu comment utiliser printf et scanf. Nous allons approfondir nos connaissances sur ces fonctions et sur les autres fonctions qui font des conversions de format. Les fonctions que nous allons voir utilisent des formats de conversion entre le modèle des données machines et le modèle nécessaire à la vision humaine (chaîne de caractères).

Les lectures formatées nécessitent :

➫ le format de description des lectures à faire;

➫ une adresse2 pour chaque variable simple ou pour un tableau de caractères3.

Les écritures formatées nécessitent :

➫ le format de description des écritures à faire;

➫ les valeurs des variables simples à écrire. Comme dans le cas de la lecture, l'écriture d'un ensemble de caractères est une opération particulière qui peut se faire à partir de l'adresse du premier caractère.

11.5.1 Formats : cas de la lecture

Les formats de conversion servent à décrire les types externes et internes des données à lire. Les formats peuvent contenir :

  1. des caractères "blancs" (espace, tabulation). La présence d'un caractère blanc provoque la lecture et la mise à la poubelle des caractères "blancs" (espace, tabulation, retour chariot) qui seront lus;
  2. des caractères ordinaires (ni blanc, ni %). Ces caractères devront être rencontrés à la lecture;
  3. des spécifications de conversion, commençant par le caractère %. Une conversion consiste en :
  4. un caractère de pourcentage (%);
  5. un caractère (optionnel) d'effacement (*); dans ce cas la donnée lue est mise à la poubelle;
  6. un champ (optionnel) définissant la taille de la donnée à lire exprimée par une valeur entière en base dix;
  7. un caractère (optionnel) de précision de taille qui peut être : l, h ou L. Ces caractères agissent sur les modes de spécification de la manière suivante :

(a) si le format initial est du type d, i ou n, les caractères l et h précisent respectivement que la donnée est du type entier long (long int) ou entier court (short int) plutôt qu'entier ordinaire (int).

(b) si le format initial est du type o, x ou u, les caractères l et h précisent respectivement que la donnée est du type entier long non signé (unsigned long int) ou entier court non signé (unsigned short int) plutôt qu'entier non signé (unsigned int).

  1. Ce qui explique pourquoi il faut un & devant les noms de données à lire quand ces noms ne sont pas des tableaux.
  2. Des formats particuliers permettent la lecture de plusieurs caractères à l'intérieur d'un tableau de caractères.

(c) si le format initial est du type e ou f ou g, les caractères l et L précisent respectivement que la donnée est du type nombre avec point décimal de grande précision (double) ou nombre avec point décimal de très grande précision (long double) plutôt que du type nombre avec point décimal (float).

(d) dans tous les autres cas, le comportement est indéfini. 5. un code de conversion. Les codes de conversion sont décrits dans le tableau 11.1.

...

La spécification entre les crochets définit un alphabet' de caractères. La donnée lue doit être conforme à cette spécification. La lecture avec un format de spécification retourne une chaîne de caractères.

11.5.2 Formats : cas de l'écriture

Les formats de conversion servent à décrire les types externes et internes des données à écrire. Les formats peuvent contenir :

  1. des caractères qui sont recopiés dans la chaîne engendrée par l'écriture;
  2. et des spécifications de conversion. Une conversion consiste en :
  3. un caractère de pourcentage (%);
  4. des drapeaux (flags) qui modifient la signification de la conversion;
  5. la taille minimum du champ dans lequel est insérée l'écriture de la donnée;

(a) la taille est donnée en nombre de caractères,

(b) pour les chiffres, si la taille commence par - la donnée est cadrée à gauche.

(c) pour une chaîne de caractère, si la taille est précédée de 0, la chaîne est cadrée à droite et est précédée de zéros;

  1. Cet alphabet est défini soit par la liste des caractères significatifs, soit par le premier caractère suivi d'un tiret et le dernier caractère dans l'ordre croissant de la table ASCII (cf. annexe A). La négation de l'alphabet peut être obtenue en mettant un ∧ après le crochet ouvrant. Pour que le crochet fermant soit dans l'alphabet, il faut qu'il suive immédiatement le crochet ouvrant.
  2. un point suivi de la précision. La précision définit le nombre de chiffres significatifs pour une donnée de type entier, ou le nombre de chiffres après la virgule (.!) pour une donnée de type flottant. Elle indique le nombre de caractères pour une chaîne;
  3. un h, un l ou un L signifiant court ou long et permettant de préciser :

(a) dans le cas d'une conversion d'un entier (format d, i, o, u, x, X) que l'entier à écrire est un entier court (h) ou long (l);

(b) dans le cas d'une conversion d'un nombre avec partie décimale (format e, f, g, E, G) que le nombre à écrire est un nombre avec point décimal de très grande précision (long double).

  1. un code de conversion.

Les champs taille et précision peuvent contenir une *. Dans ce cas la taille doit être passée dans un argument à [sf1printf. Par exemple les lignes suivantes d'appel à printf() sont équivalentes :

printf ("Valeur Ade Al'entier AIndice A: A%*d\n" , 6, Indice) ; printf ("Valeur Ade Al'entier AIndice A: A%6d\n" , Indice);

Les codes de conversion sont décrits dans le tableau 11.2.

...

La différence entre x et X vient de la forme d'écriture des valeurs décimales entre 10 et 15. Dans le premier cas, elles sont écrites en minuscule (a-f), dans le second cas, elles sont écrites en majuscule (A-F). De même, le caractère E de la notation exponentielle est mis en minuscule par les formats e et g. Il est mis en majuscule par les formats E et G. Le nombre maximum de caractères qui peuvent être construits dans un appel aux fonctions de type fprintf() ne doit pas dépasser 509. Les drapeaux sont décrits dans le tableau 11.3.

11.5.3 Conversion sur les entrées-sorties standards

 int printf (const char* format , ~ ~ ~ ) ;

 int scanf (const char* format , ~ ~ ~ ) ;

11.5.4 Conversion en mémoire  

...

int sprintf(char* string, const char* format, ...);

synopsis : conversion de données en mémoire par transformation en chaîne de caractères. arguments :

  1. zone dans laquelle les caractères sont stockés;
  2. format d'écriture des données;
  3. valeurs des données.

retour : nombre de caractères stockés.

int sscanf(char* string, const char* format, ...); synopsis : lecture formatée à partir d'une zone mémoire. arguments :

  1. zone dans laquelle les caractères sont acquis;
  2. format de lecture des données;
  3. adresse des variables à affecter à partir des données. retour : nombre de variables saisies. conditions d'erreur : la valeur EOF est retournée en cas d'erreur empêchant toute lecture.

sprintf convertit les arguments arg1, ..., argn suivant le format de contrôle et met le résultat dans string (chaîne de caractères).

Inversement, sscanf extrait d'une chaîne de caractères des valeurs qui sont stockées dans des variables suivant le format de contrôle.

11.5.5 Conversion dans les fichiers

Deux fonctions fprintf et fscanf permettent de réaliser le même travail que printf et scanf sur des fichiers ouverts en mode texte :

int fprintf(FILE*, const char*, ...);

synopsis : écriture formatée sur un fichier ouvert en mode texte. arguments :

  1. descripteur de fichier ouvert valide dans lequel les caractères sont rangés;
  2. format d'écriture des données;

654