1. Chaines de caractères
En programmation, une chaine de caractère est une suite de caractères pouvant former un mot ou une phrase. Par convention, une chaine de caractère est le plus souvent représentée par une suite de caractères entre guillemets, comme par exemple "Bonjour !". On appelle cette écriture une forme littérale.
Le langage C ne possède pas de type spécifique pour représenter les chaines de caractères. En revanche, il possède le type char pour représenter un caractère seul. La façon la plus simple de représenter une chaîne ce caractère en C est de le faire sous forme de tableau de char, ce qui est possible sous deux formes:
- char chaine[n]; ou la chaine est un tableau statique de n caractères
- char* chaine; ou la chaine est un tableau dynamique de caractères
1.1. Chaines statiques
Les chaines de caractères statiques sont définies comme des tableaux. D'après la définition standard du langage C, elles peuvent être initialisées en extension (en spécifiant les caractères qui la compose) comme par exemple:
char chaine[] = {'B', 'o', 'n', 'j', 'o', 'u', 'r', ' ', '!'};
Cette initialisation de chaine de caractère n'est pas pratique et peu lisible. Une autre syntaxe existe en utilisant une forme littérale:
char chaine[] = "Bonjour !";
Ces deux syntaxes sont équivalentes.
1.2. Chaines dynamiques
Les tableaux en langage C pouvant être définis comme des pointeurs, une chaine de caractère peut être représentée par une variable de type char*. L'initialisation correspondante étant:
char* chaine = "Bonjour !";
ATTENTION: En langage C, les formes littérales sont des constantes. En définissant une chaine de caractère comme char* et en l'initialisant avec une forme littérale, la variable obtenue est une constante et n'est pas modifiable.
1.3. Affichage de chaîne de caractère
Une chaine de caractère (définie comme char[] ou char*) peut être affichée en utilisant la fonction printf et en utilisant le format %s. Le code suivant:
char chaineA[] = "Bonjour !";
char* chaineB = "Ca va ?";
printf("%s\n", chaineA);
printf("%s\n", chaineB);
affiche sur la console:
Bonjour !
Ca va ?
| Exercice 1. |
|
Créer un fichier tp-chaines.c et y ajouter une fonction main qui déclare et initialise:
Compléter la fonction main afin d'afficher les valeurs de chaineA, chaineB et chaineC sur la console. Que remarquez-vous pour l'affichage de la chaineA ? |
1.4. Fin de chaine
Les chaines de caractères pouvant varier en taille, le langage C utilise un marqueur de fin de chaine pour signifier que la chaine de caractère est bien terminée. Ce marqueur est spécifié comme étant le caractère nul '\0'.
Lors de l'initialisation d'une chaine de caractère avec sa forme littérale, le caractère '\0' est ajouté automatiquement à la fin de la chaine. Ainsi, "Bonjour !" est en réalité stockée sous la forme "Bonjour !\0". Lors de l'initialisation d'une chaine de caractère par extension, le '\0' doit être explicitement défini.
| Exercice 2. |
|
Modifier le programme tp-chaines.c afin que l'affichage donne: Hello |
1.5. Saisie de chaine
La saisie d'une chaine de caractère peut être réalisée à l'aide de la fonction scanf en lui précisant le format "%s". La chaine à saisir doit absolument avoir été allouée avant l'appel à scanf afin d'avoir un espace mémoire ou la fonction puisse écrire la chaîne saisie.
Le code suivant illustre la saisie d'une chaine de caractère déclarée sous forme de tableau ou de pointeur:
char chaineA[10];
char* chaineB = (char*) malloc(sizeof(char)*10);
scanf("%s", chaineA);
scanf("%s", chaineB);
Lors de l'utilisation d'un scanf, la fonction lit au clavier des caractères et les stocke dans la chaine passée en paramètre. Si le nombre de caractères lus par le scanf dépasse la taille de la variable dans laquelle la chaîne doit être stockée, une erreur se produit. Il est possible de contraindre le scanf en lui donnant une limite de caractères à lire en utilisant le format "%<n>s" ou <n> est le nombre de caractères à lire. Par exemple:
char chaine[255];
scanf("%10s", chaine);
permet de saisir 10 caractères au clavier pour les stocker dans chaine.
ATTENTION: Lorsque l'on spécifie une limite de nombre de caractères à scanf, le caractère de fin de chaine '\0' ajouté automatiquement n'est pas compris dans le décompte. La limite du nombre de caractères doit alors toujours être strictement inférieure à la taille de la variable devant contenir la chaine:
char chaine[255];
scanf("%254s", chaine);
| Exercice 4. |
|
Modifier le programme tp-chaines.c écrit à l'exercice 3 afin de limiter les chaines lues à 10 caractères ('\0' compris). Tester l'exécution avec "Anticonstitutionnellement". Que se passe-t-il ? |
Si un scanf doit réaliser la saisie d'une chaine avec une limite de n caractères (via "%ns" et si le nombre m de caractères saisis est supérieur à n, alors les m-n caractères non utilisés restent dans le tampon de saisie et un nouvel appel à scanf utilisera ce tampon comme nouvelle entrée sans demander à l'utilisateur une nouvelle saisie.
Pour palier à ce comportement, il est recommandé de vider le tampon après chaque appel à scanf pour lequel "%s" ou "%ns" a été utilisé, ce qui est réalisable en retirant tous les caractères restants qui ne sont pas des fins de ligne:
while ( (c = getchar()) != '\n' && c != EOF ) { }
La constante EOF (pour End Of File) signifiant une fermeture de flux (cette notion sera étudiée plus tard).
Il est alors possible d'écrire une fonction clearInput() qui vide le tampon d'entrée:
void cleanInput(){
int c;
while ( (c = getchar()) != '\n' && c != EOF ) { }
}
| Exercice 5. |
|
Modifier le programme tp-chaines.c écrit à l'exercice 4 afin de vider le tampon d'entrée après chaque saisie de chaine de caractères. Exécuter le programme en saisissant "Anticonstitutionnellement" pour la chaine A et "Extraordinaire" pour la chaine B et observer son comportement. Exemple d'exécution: Saisir la chaine A: Anticonstitutionnellement Saisir maintenant les chaines "Tous ensemble !" pour la chaine A et "On va y arriver !" pour la chaine B. Que se passe-t-il ? |
Lors de l'utilisation de la fonction scanf, le format "%s" (ou "%ns") signifie toute suite de caractères n'étant pas un espace. La fonction scanf ne peut donc pas, par définition, lire de chaine de caractère contenant un espace (simple, tabulation, retour à la ligne, ...).
S'il est nécessaire de lire une chaine de caractères contenant des espaces, une fonction spécifique doit être écrite comme par exemple la fonction read_line(char* str, unsigned int length) définie ci-dessous:
int read_line(char *str, unsigned int length)
{
unsigned int i;
char c;
for (i = 0; i < length; ++i)
{
if (scanf("%c", &c) != 1)
return 1;
else if (c == '\n')
break;
str[i] = c;
}
str[i] = '\0';
return 0;
}
Cette fonction lit sur l'entrée standard caractère par caractère en les recopiant dans la chaine str. La lecture s'arrête lorsqu'un symbole de nouvelle ligne '\n' est lu ou lorsque le nombre voulu de caractères (length) est atteint. Même si des espaces sont tapés, ils sont conservés.
| Exercice 6. |
|
Modifier le programme tp-chaines.c écrit à l'exercice 5 et y ajouter la fonction int read_line(char* str, unsigned int length) définie ci-dessus. Dans la fonction main, remplacer les appels à la fonction scanf afin de pouvoir lire des chaines de caractères contenant des espaces. Exécuter le programme en saisissant "Je suis" pour la chaine A et "enfin la" pour la chaine B et observer son comportement. Exemple d'exécution: Saisir la chaine A: je suis ATTENTION: La fonction read_line(char* str, unsigned int length) vide le tampon, les appels à clearInput() ne sont plus nécessaires. |
1.6. Lecture / écriture depuis une chaîne de caractères
S’il est possible d’afficher et saisir une chaîne de caractères, il est également possible de lire depuis une chaîne et d’écrire dans une chaîne. Pour cela, deux fonctions existent : snprintf() et sscanf().
1.6.1. fonction snprintf
La fonction snprintf() est identique à la fonction printf() à la différence que celle-ci écrit dans une chaîne de caractères au lieu d'utiliser la sortie standard (comme la console). Elle est définie comme suit:
int snprintf(char *chaine, size_t taille, char *format, <valeurs>);
RAPPEL: Le type size_t est une redéfinition de type présente dans l'en-tête <stddef.h> représentant une taille (entier non signé). Dans la plupart des cas il s'agit en réalité d'un unsigned int ou un unsigned long en fonction de l'architecture.
Les paramètres de la fonction snprintf sont:
- chaine: la chaine de caractère (déjà allouée) dans laquelle écrire
- taille: la taille de la chaine de caractère
- format: le format d'écriture (le même que pour un printf)
- <valeurs>: une suite de valeurs (séparées par des virgules) correspondant au format (comme pour un printf)
La fonction snprintf() écrit au maximum taille - 1 caractères dans chaine et ajoute elle-même un caractère nul ('\0') à la fin. La fonction retourne le nombre de caractères écrit sans compter le caractère '\0' final ou bien un nombre négatif en cas d’erreur. Dans le cas où chaine est trop petite pour accueillir toutes les données à écrire, la fonction retourne le nombre de caractères qui aurait dû être écrit (hors caractère '\0') si la limite n’avait pas été atteinte.
L'exemple suivant illustre comment écrire une valeur entière, une valeur réelle et un caractère dans une chaine de caractères en utilisant sprintf:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char chaine[20];
int entier = 55;
float reel = 3.5;
char caractere = 'X';
snprintf(chaine, 20, "%d %f %c", entier, reel, caractere);
printf("chaine : %s\n", chaine);
return 0;
}
1.6.2. Fonction sscanf
La fonction sscanf() se comporte de la même façon que la fonction scanf() à la différence qu'elle extrait les données depuis une chaîne de caractères plutôt que depuis l'entrée standard (la console). La fonction sscanf retourne le nombre de conversions réussies ou un nombre inférieur si elles n’ont pas toutes été réalisées ou enfin un nombre négatif en cas d’erreur. Sa définition est:
int sscanf(char *chaine, char *format, <pointeurs>)
avec les paramètres:
- chaine: la chaine de caractère depuis laquelle extraire les données
- format: le format de lecture (le même que pour un scanf)
- <pointeurs>: une suite de pointeurs (séparées par des virgules) correspondant au format (comme pour un scanf)
L'exemple suivant illustre l'utilisation de sscanf en lisant depuis une chaine de caractère un réel, un caractère et un entier:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char* chaine = "5.2 x 12";
float f;
int i;
char c;
if (sscanf(chaine, "%f %c %d", &f, &c, &i) != 3)
{
printf("Erreur lors de l'examen de la chaîne\n");
return 1;
}
printf("%f %c %d\n", f, c, i);
return 0;
}
| Exercice 8. |
|
Modifier la fonction main du programme tp-chaines.c afin de:
Exemple d'exécution: Entrer une chaine au format A c B: 5.5 + 12.69 RAPPEL: Le format pour lire un double dans un scanf / sscanf est "%lf". AIDE: Il est possible d'utiliser la fonction read_line de l'exercice 6 pour la saisie de la chaine. |
1.7. La fonction main
La fonction main du langage C permet de récupérer des paramètres passés au programme depuis la console sous-forme de chaine de caractères. La définition complète de la fonction main est en effet:
int main (int argc, char** argv)
ou encore
int main (int argc, char* argv[])
avec la paramètres:
- argc qui donne le nombre de paramètres passés
- argv qui est un tableau de chaine de caractères contenant les paramètres.
Par convention, le premier paramètre argv[0] est la chaine de caractère contenant le nom du programme (la commande lancée).
L'exemple suivant illustre la récupération des arguments d'un programme sous forme de chaine de caractères:
#include <stdio.h>
int main(int argc, char** argv){
if (argc > 0){
char* command = argv[0];
if (argc > 1){
printf("Arguments du programme %s:\n", command);
for(int i = 1; i < argc; i++)
printf(" argument %d: %s\n", i, argv[i]);
} else {
printf("Le programme %s n'a pas d'argument\n", command);
}
return 0;
}
return 1;
}
2. Manipulation de chaînes de caractères
Les chaînes de caractères peuvent être utilisées de nombreuses façon différentes. Une des utilisation les plus répandue est le stockage de données et le langage C propose des outils pour passer de chaînes de caractères à différents types.
2.1. Conversion en type simple
La bibliothèque d'entrée sortie stdlib.h propose des fonctions pour passer d'une chaine de caractère aux types numériques du Langage C.
2.1.1. Fonction atoi
La fonction atoi (pour ASCII to Integer) permet d'extraire une valeur entière (int) représentée par une chaîne de caractères. Sa syntaxe est la suivante:
int atoi(const char* chaine);
La fonction retourne le nombre représenté dans la chaine ou 0 si elle n'a pu extraire aucun nombre. Il n'est donc pas possible de savoir si chaine représente bien un 0 ou si il y a eu une erreur de lecture.
2.1.2. Fonction atof
La fonction atof (pour ASCII to Float) permet d'extraire une valeur réelle (double) représentée par une chaîne de caractère. Sa syntaxe est:
double atof(const char* chaine);
La fonction retourne le nombre représenté dans la chaine ou 0 si elle n'a pu extraire aucun nombre. Il n'est donc pas possible de savoir si chaine représente bien un 0.0 ou si il y a eu une erreur de lecture.
2.1.3. Fonctions atol et atoll
Las fonctions atol (ASCII to Long) et atoll (ASCII To Long Long) permettent d'extraire respectivement une valeur entière (long) ou longue entière (long long) représentée par une chaîne de caractère. Leurs définitions sont:
long atol(const char* chaine);
long atoll(const char* chaine);
Les fonctions retournent le nombre représenté dans la chaine ou 0 si elle n'ont pu extraire aucun nombre. Il n'est donc pas possible de savoir si chaine représente bien un 0 ou si il y a eu une erreur de lecture.
2.2. Bibliothèque String
Afin de proposer des outils de manipulation de chaines de caractères plus avancés, le langage C met à disposition des programmeurs la bibliothèque dédiée String. Pour utiliser les fonctions de cette bibliothèque, l'inclusion suivante doit être utilisée:
#include <string.h>
La bibliothèque String propose de nombreuses fonctions, nous en détaillons quelques une des plus utiles.
2.2.1. Fonction strlen
La fonction strlen() retourne la longueur (nombre de caractères qui la compose) d'une chaîne de caractères. Sa définition est la suivante:
size_t strlen(char* chaine);
Le nombre retourné est le nombre de caractères utiles, c'est à dire sans prendre en compte le caractère nul ('\0') marquant la fin de la chaine. Il y a donc une différence entre la longueur d'une chaine de caractère et le nombre de caractères effectifs stockés en mémoire. L'exemple suivant illustre l'utilisation de strlen():
#include <stdio.h>
#include <string.h>
int main(void)
{
char* chaine = "Bonjour !";
size_t longueur = strlen(chaine);
printf("Longueur de %s: %zu\n", chaine, longueur);
return 0;
}
2.2.2. Fonction strcmp
La fonction strcmp() retourne le résultat de la comparaison entre 2 chaines de caractères. Sa définition est la suivante:
int strcmp(char* chaine1, char* chaine2);
La fonction strcmp() retourne:
- 0 si les deux chaines sont égales (de même longueur et composées d'exactement les mêmes caractères)
- une valeur positive si chaine1 est plus grande que chaine2
- une valeur négative si chaine1 est plus petite que chaine2
La relation d'ordre utilisée pour la comparaison est l'ordre lexicographique. Celui-ci ordonne des chaines en comparant un à un ses caractères selon un ordre alpha numérique donné par la table ASCII (ou UNICODE). Un caractère est plus petit qu'un ordre si son codage est inférieur au codage de l'autre caractère. Par exemple, dans l'ordre lexicographique ASCII:
- Les majuscules sont plus petites que les minuscules: [A...Z] < [a...z]
- Les chiffres sont plus petits que les lettres: [0...9] < [A...Z] < [a...z]
La comparaison de deux chaines est obtenue en comparant le premier caractère de chacune d'elle. Si l'un est plus petit que l'autre, la chaine correspondante est considérée comme plus petite. Si ce n'est pas le cas, on recommence la comparaison à partir du deuxième caractère et ainsi de suite. Si deux chaines on des caractères identiques, la plus longue est considérée comme la plus grande ("AAA" > "AA").
2.2.3. Fonction strcpy
Les chaines de caractères en langage C sont des pointeurs vers des tableaux de char. Comme pour tout pointeur, le code suivant:
char* chaineA = "Bonjour";
char* chaineB = chaineA;
fait que chaineB n'est pas une copie de chaineA mais pointe vers le même contenu et le code suivant:
#include <stdio.h>
int main()
{
char chaineA[] = "Bonjour";
char* chaineB = chaineA;
chaineA[2] = 'N';
printf("Chaine A: %s\n", chaineA);
printf("Chaine B: %s\n", chaineB);
return 0;
}
provoque la sortie:
Chaine A: BoNjour
Chaine B: BoNjour
Les deux variables pointant vers la même zone mémoire, toute modification de l'une est visible dans l'autre.
Pour réaliser la copie d'une chaine de caractère vers une autre, il faut:
- Que les deux chaines aient chacune un espace mémoire alloué indépendamment
- Le contenu de la première soit recopié vers la seconde caractère par caractère
C'est ce travail que réalise la fonction strcpy() dont la définition est:
char* strcpy(char* destination, char *source);
Cette fonction recopie caractère par caractère la chaine source dans la chaine destination (caractère nul '\0' compris). La valeur retournée est la même valeur que destination.
La fonction strcpy() ne fait aucune vérification et considère que les chaines source et destination sont valides, c'est à dire:
- destination et source sont bien allouées
- destination à une taille suffisante pour recevoir le contenu de source
L'exemple suivant illustre l'utilisation de strcyp() en copiant le contenu d'une chaine A dans une chaine B au préalablement allouée:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char* chaineA = "Bonjour !";
char* chaineB = (char*) malloc(sizeof(char)*strlen(chaineA)+1);
strcpy(chaineB, chaineA);
printf("Chaine A: %s\n", chaineA);
printf("Chaine B: %s\n", chaineB);
return 0;
}
REMARQUE: Afin de garantir que chaineB puisse recevoir le contenu de chaineA, elle est allouée avec la longueur de chaineA + 1 (pour le caractère nul '\0')
2.2.4 Fonction strcat
Une des opération les plus utilisées sur les chaines de caractères est la concaténation. Celle-ci produit une nouvelle chaine de caractère composée de la mise à la suite de deux chaines existantes. Formellement, l'opérateur de concaténation est noté . et peut s'utiliser comme le montre l'exemple suivant:
"Anti"."virus" = "Antivirus"
La bibliothèque String du langage C permet la concaténation de chaines de caractères par la fonction strcat():
char* strcat(char* destination, char* source);
Cette fonction concatène source et destination et stocke le résultat dans destination (qui est également retourné). L'exemple suivant montre son utilisation:
#include <stdio.h>
#include <string.h>
int main(void)
{
char chaine[25] = "Bonjour";
strcat(chaine, " tout le monde");
printf("%s\n", chaine);
return 0;
}
Comme les autres fonctions de la bibliothèque, strcat() ne fait aucune vérification et les conditions suivantes doivent être remplies avant son utilisation:
- source et destination doivent être allouées
- destination doit avoir une taille suffisante pour contenir le résultat de la concaténation
2.2.5. Fonctions strchr et strstr
Une fonctionnalité importante avec les chaînes de caractères et la possibilité de faire de rechercher des informations à l'intérieur. Les fonctions strchr() et strstr() permettent de rechercher dans une chaine de caractère respectivement un caractère ou une chaine de caractères.
La fonction strchr() est définie par:
char* strchr(char* chaine, int ch);
Le paramètre chaine est la chaine de caractères dans laquelle la recherche est effectuée et le paramètre ch est le caractère recherché. La fonction renvoi un pointeur vers la première occurrence de ch dans chaine ou NULL si le caractère n'a pas été trouvé. Par exemple, le code:
#include <stddef.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
char chaine[] = "Bonjour";
char* p = strchr(chaine, 'o');
if (p != NULL)
printf("La chaîne '%s' contient la lettre %c\n", chaine, *p);
return 0;
}
affiche:
La chaîne 'Bonjour' contient la lettre o
De la même façon, la fonction strstr() permet de rechercher une chaine de caractères à l'intérieur d'une autre chaine de caractères. Elle est définie par:
char* strstr(char* chaineA, char* chaineB);
Le paramètre chaineA est la chaîne de caractère dans laquelle chercher et le paramètre chaineB est la chaîne à rechercher. La fonction retourne un pointeur vers le début de la première occurrence de chaineB trouvée dans chaineA ou NULL si rien n'est trouvé. Par exemple, le code:
#include <stddef.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
char chaine[] = "Bonjour";
char* p = strstr(chaine, "jour");
if (p != NULL)
printf("La chaîne '%s' contient la chaîne '%s'\n", chaine, p);
return 0;
}
affiche:
La chaîne 'Bonjour' contient la chaîne 'jour'
3. Fichiers
Le langage C propose des fonctionnalités pour interagir avec les fichiers du système sur lequel un programme s'exécute. Pour rappel, un fichier est un ensemble de données stockée sur un support non volatile (disque dur, bande magnétique, ...). En informatique ces données sont des ensembles d'octets représentant une information.
Texte ou binaire
Les fichiers sont généralement regroupés en deux catégories distinctes:
- les fichiers textes qui contiennent comme données des suites de caractères lisibles directement
- les fichiers binaires qui contiennent des données encodées dans divers formats (image, son, vidéo, ...)
Cette catégorisation est purement logique étant donné que le stockage physique d'un fichier reste toujours le même (succession d'octets). Cependant, la façon d'utiliser des fichier de l'une ou l'autre catégorie étant différente, des fonctions spécifiques sont proposées par le langage C.
Accès à une ressource
Du point de vue du système, un fichier est une ressource pouvant être partagée et certaines règles doivent être respectées:
- Ouverture: L'accès à un fichier doit être demandé au système
- Fermeture: Une fois l'utilisation d'un fichier terminée, son accès doit être fermé pour permettre à d'autres programmes d'y accéder
Ne pas faire une demande d'accès à un fichier peut entrainer une erreur tout comme ne pas relâcher un accès peut entrainer le blocage du fichier.
3.1. Structure FILE
Le langage C propose une structure FILE, définie dans stdio.h qui permet d'interagir avec les fichiers du système. Comme un fichier est un espace mémoire particulier, la structure FILE est toujours utilisée sous forme de pointeur FILE*. L'exemple suivant illustre la déclaration d'une variable f permettant d'interagir avec un fichier:
#include <stdio.h>
int main(void)
{
FILE *f = NULL;
return 0;
}
3.2. Accès à un fichier
Les fichiers sont des ressources du système d'exploitation avec une gestion des accès. Le langage C propose 2 fonctions pour acquérir et relâcher l'accès à un fichier.
3.2.1. Fonction fopen
L'accès au contenu d'un fichier nécessite une demande auprès du système d'exploitation. La fonction fopen() du langage C réalise cette opération. Sa définition est:
FILE* fopen(char* chemin, char* mode);
ou chemin est le chemin système du fichier à ouvrir et mode et le mode d'accès à utiliser. La fonction renvoie un pointeur valide vers un FILE* si l'accès est autorisé et NULL sinon.
Le mode d'ouverture indique l'utilisation souhaitée pour le fichier. Plusieurs valeurs sont possibles:
| Mode (valeur) | Type d'opérations | Fonctionnement |
| "r" | Lecture | Accède au fichier déjà existant |
| "r+" | Lecture et Ecriture | Accède au fichier déjà existant |
| "w" | Ecriture | Le fichier est créé s'il n'existe pas sinon il est effacé |
| "w+" | Lecture et Ecriture | Le fichier est créé s'il n'existe pas sinon il est effacé |
| "a" | Ecriture | Le fichier est créé s'il n'existe pas. Le contenu est conservé et l'écriture se fait à partir de la fin. |
| "a+" | Lecture et Ecriture | Le fichier est créé s'il n'existe pas. Le contenu est conservé et l'écriture se fait à partir de la fin. |
L'utilisation de fopen() est la suivante:
#include <stdio.h>
int main(void)
{
char* chemin = "fichier.txt";
FILE *fp = fopen(chemin, "r");
if (fp == NULL)
{
printf("Le fichier texte.txt n'a pas pu être ouvert\n");
return 1;
} else {
printf("Le fichier texte.txt est ouvert\n");
}
return 0;
}
Le fichier dont le chemin est "fichier.txt" est ouvert en lecture ("r") si celui-ci existe. La variable fp peut alors être utilisée pour effectuer des opérations sur le fichier.
3.2.2. Fonction fclose
Lorsque l'accès à un fichier n'est plus nécessaire, la ressource doit être libérée afin d'être accessible par d'autres programmes. La fonction fclose() permet d'indiquer au système de fermer l'accès au fichier pour le programme en cours. Sa définition est la suivante:
int fclose(FILE* flichier);
La fonction fclose() s'assure que toutes les opérations en cours sur le fichier se terminent et ferme l'accès à celui-ci. Elle renvoie 0 si la fermeture est réussie et EOF si une erreur est survenue.
A chaque appel à fopen() doit correspondre un fclose() au risque de ne pas fermer l'accès à une ressource et de bloquer celle-ci.
3.3. Lecture et écriture textuelle
Les fichier textes ont pour contenu des suites de caractères encodés dans un format prédéfini (ASCII, UNICODE, ...). Les opérations les plus simples pour interagir avec ces contenus sont la lecture et l'écriture de caractères.
Par définition, des fichiers différents possèdent des contenus de taille variée. De façon similaire aux chaines de caractères pour lesquelles '\0' est un marqueur de fin, le caractère EOF indique la fin d'un fichier.
3.3.1. La fonction fgetc
La fonction fgetc() permet de lire un caractère depuis un fichier. Sa définition est:
int fgetc(FILE* fichier);
Cette fonction lit et retourne le caractère courant dans le fichier et pointe ensuite vers le suivant. Si la fin de fichier est atteinte ou si plus aucun caractère n'est lisible, la fonction retourne EOF.
Le code suivant illustre la lecture et l'affichage du premier caractère du fichier texte.txt:
#include <stdio.h>
int main(void)
{
char* chemin = "texte.txt";
FILE *fp = fopen(chemin, "r");
if (fp == NULL)
{
printf("Le fichier %s n'a pas pu être ouvert\n", chemin);
return 1;
}
int ch = fgetc(fp);
if (ch != EOF)
printf("Premier caractere: %c\n", ch);
if (fclose(fp) == EOF)
{
printf("Erreur lors de la fermeture du flux\n");
return 1;
}
return 0;
}
3.3.2. La fonction fputc
La fonction fputc() permet d'écrire un caractère vers un fichier. Sa définition est:
int fputc(int ch, FILE* fichier);
Cette fonction écrit le caractère ch à la suite du dernier caractère de fichier. Si la fin de fichier est atteinte ou si plus aucun caractère n'est lisible, la fonction retourne EOF. Dans le cas contraire, la fonction retourne le caractère écrit (ch).
Le code suivant illustre l'écriture du caractère 'C' dans le fichier texte.txt:
#include <stdio.h>
int main(void)
{
char* chemin = "texte.txt"
FILE *fp = fopen(chemin, "w");
if (fp == NULL)
{
printf("Impossible d'ouvrir le fichier\n");
return 1;
}
if (fputc('C', fp) == EOF)
{
printf("Erreur lors de l'écriture d'un caractère\n");
return 1;
}
if (fclose(fp) == EOF)
{
printf("Erreur lors de la fermeture du fichier\n");
return 1;
}
return 0;
}
| Exercice 17. |
|
Ecrire un programme write.c qui prend en argument un chemin vers un fichier et qui demande à l'utilisateur de saisir une chaine de caractères. Cette chaine de caractère sera ajoutée au fichier dont le chemin est passé en argument. Si le fichier n'existe pas, il devra être créé. Si le fichier existe, la nouvelle chaine de caractère doit le compléter. Si le nombre d'arguments du programme est incorrect ou si l'accès au fichier ne peut être ouvert, la phrase "Impossible d'ouvrir le fichier" doit être affichée. Chaque ligne saisie doit être sur une ligne séparée dans le fichier. Le programme doit être compilé en utilisant la commande: gcc write.c -o write Exemples d'exécution: ./write fichier.txt fichier.txt contient alors: Hello ! ./write fichier.txt fichier.txt contient alors: Hello ! AIDE: Il est possible d'utiliser la fonction read_line de l'exercice 6 pour la saisie de la chaine. |
X. Pour aller plus loin
To be continued...