Lecture du fichier c en blocs. Travailler avec des fichiers texte en C

Pour faciliter l'accès, les informations contenues dans les périphériques de stockage sont stockées sous forme de fichiers.

Un fichier est une zone nommée de mémoire externe allouée au stockage d'un tableau de données. Les données contenues dans les fichiers sont de nature très diverse : programmes en langage algorithmique ou machine ; données initiales pour le fonctionnement du programme ou les résultats de l'exécution du programme ; textes libres; images graphiques, etc.

Répertoire (dossier, répertoire) - une collection nommée d'octets sur un support de stockage contenant les noms des sous-répertoires et des fichiers, utilisée dans le système de fichiers pour simplifier l'organisation des fichiers.

Système de fichiers appelé la partie fonctionnelle du système d'exploitation qui effectue des opérations sur les fichiers. Des exemples de systèmes de fichiers sont FAT (FAT - File Allocation Table), NTFS, UDF (utilisés sur les CD).

Il existe trois versions principales de FAT : FAT12, FAT16 et FAT32. Ils diffèrent par la profondeur de bits des enregistrements dans la structure du disque, c'est-à-dire le nombre de bits alloués pour stocker le numéro de cluster. FAT12 est principalement utilisé pour les disquettes (jusqu'à 4 Ko), FAT16 - pour les disques de petite capacité, FAT32 - pour les lecteurs FLASH haute capacité (jusqu'à 32 Go).

Examinons la structure du système de fichiers en utilisant FAT32 comme exemple.

Structure du fichier FAT32

Les périphériques de mémoire externes du système FAT32 ont un adressage par bloc plutôt que par octet. Les informations sont écrites sur un périphérique de mémoire externe sous forme de blocs ou de secteurs.

Un secteur est l’unité adressable minimale de stockage d’informations sur des périphériques de stockage externes. Généralement, la taille du secteur est fixée à 512 octets. Pour augmenter l'espace d'adressage des périphériques de mémoire externes, les secteurs sont regroupés en groupes appelés clusters.

Un cluster est une union de plusieurs secteurs, qui peuvent être considérés comme une unité indépendante possédant certaines propriétés. La principale propriété d'un cluster est sa taille, mesurée en nombre de secteurs ou en nombre d'octets.

Le système de fichiers FAT32 a la structure suivante.

Les clusters utilisés pour l'écriture des fichiers sont numérotés à partir de 2. En règle générale, le cluster n°2 est utilisé par le répertoire racine, et à partir du cluster n°3, le tableau de données est stocké. Les secteurs utilisés pour stocker les informations au-dessus du répertoire racine ne sont pas regroupés.
La taille minimale de fichier requise sur le disque correspond à 1 cluster.

Le secteur de démarrage commence par les informations suivantes :

  • EB 58 90 – saut inconditionnel et signature ;
  • 4D 53 44 4F 53 35 2E 30 MSDOS5.0 ;
  • 00 02 – nombre d'octets dans le secteur (généralement 512) ;
  • 1 octet – nombre de secteurs dans le cluster ;
  • 2 octets – nombre de secteurs de réserve.

De plus, le secteur de démarrage contient les informations importantes suivantes :

  • 0x10 (1 octet) – nombre de tables FAT (généralement 2) ;
  • 0x20 (4 octets) – nombre de secteurs sur le disque ;
  • 0x2С (4 octets) – numéro de cluster du répertoire racine ;
  • 0x47 (11 octets) – étiquette de volume ;
  • 0x1FE (2 octets) – signature du secteur de démarrage (55 AA).

Le secteur d'informations du système de fichiers contient :

  • 0x00 (4 octets) – signature (52 52 61 41) ;
  • 0x1E4 (4 octets) – signature (72 72 41 61) ;
  • 0x1E8 (4 octets) – nombre de clusters libres, -1 si inconnu ;
  • 0x1EC (4 octets) – numéro du dernier cluster enregistré ;
  • 0x1FE (2 octets) – signature (55 AA).

La table FAT contient des informations sur l'état de chaque cluster sur le disque. Les 2 octets inférieurs de la table FAT stockent F8 FF FF 0F FF FF FF FF (ce qui correspond à l'état des clusters 0 et 1, physiquement absents). Ensuite, l'état de chaque cluster contient le numéro du cluster dans lequel se poursuit le fichier en cours ou les informations suivantes :

  • 00 00 00 00 – le cluster est gratuit ;
  • FF FF FF 0F – fin du fichier en cours.
  • 8 octets – nom du fichier ;
  • 3 octets – extension de fichier ;

Le répertoire racine contient un ensemble d'enregistrements d'informations 32 bits sur chaque fichier, contenant les informations suivantes :

Lorsque vous travaillez avec des noms de fichiers longs (y compris les noms russes), le nom du fichier est codé à l'aide du système de codage UTF-16. Dans ce cas, 2 octets sont alloués pour coder chaque caractère. Dans ce cas, le nom du fichier est écrit dans la structure suivante :

  • 1 octet de séquence ;
  • 10 octets contiennent les 5 caractères inférieurs du nom de fichier ;
  • attribut de 1 octet ;
  • 1 octet réservé ;
  • 1 octet – somme de contrôle du nom DOS ;
  • 12 octets contiennent les 3 caractères inférieurs du nom de fichier ;
  • 2 octets – numéro du premier cluster ;
  • les caractères restants du nom long.

Travailler avec des fichiers en langage C

Pour le programmeur, un fichier ouvert est représenté comme une séquence de données en cours de lecture ou d'écriture. Lorsqu'un fichier est ouvert, il est associé à Flux d'E/S. Les informations de sortie sont écrites dans le flux, les informations d'entrée sont lues à partir du flux.

Lorsqu'un flux est ouvert pour les E/S, il est associé à une structure FILE standard, définie dans stdio.h. La structure FILE contient les informations nécessaires sur le fichier.

L'ouverture d'un fichier se fait à l'aide de la fonction fopen(), qui renvoie un pointeur vers une structure FILE pouvant être utilisée pour des opérations ultérieures sur le fichier.

FICHIER *fopen(nom, type);


nom – nom du fichier à ouvrir (y compris le chemin),
type est un pointeur vers une chaîne de caractères qui définit la manière dont le fichier est accessible :
  • "r" - ouvre le fichier en lecture (le fichier doit exister) ;
  • "w" - ouvre un fichier vide en écriture ; si le fichier existe, son contenu est perdu ;
  • "a" - ouvre le fichier pour l'écrire jusqu'à la fin (pour l'ajouter) ; le fichier est créé s'il n'existe pas ;
  • "r+" - ouvre le fichier en lecture et en écriture (le fichier doit exister) ;
  • "w+" - ouvre un fichier vide en lecture et en écriture ; si le fichier existe, son contenu est perdu ;
  • "a+" - ouvre le fichier pour le lire et l'ajouter ; si le fichier n'existe pas, il est créé.

La valeur de retour est un pointeur vers le flux ouvert. Si une erreur est rencontrée, NULL est renvoyé.

La fonction fclose() ferme le ou les flux associés aux fichiers ouverts à l'aide de la fonction fopen(). Le flux à fermer est déterminé par l'argument de la fonction fclose().

Valeur de retour : valeur 0 si le flux a été fermé avec succès ; EOF constant si une erreur survient.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

#inclure
int main() (
FICHIER *fp;
nom du caractère = "mon.txt" ;
if ((fp = fopen(name, "r" )) == NULL )
{
printf( "Échec de l'ouverture du fichier");
getchar();
renvoie 0 ;
}
// réussi à ouvrir le fichier
... // actions requises sur les données
fclose(fp);
getchar();
renvoie 0 ;
}

Lire un caractère à partir d'un fichier:

char fgetc(flux);


L'argument de la fonction est un pointeur vers un flux de type FILE. La fonction renvoie le code du caractère lu. Si la fin du fichier est atteinte ou qu'une erreur se produit, la constante EOF est renvoyée.

Écrire un symbole dans un fichier:

fputc(char, flux);

Les arguments de la fonction sont un caractère et un pointeur vers un flux de type FILE. La fonction renvoie le code du caractère lu.

Les fonctions fscanf() et fprintf() sont similaires aux fonctions scanf() et printf(), mais fonctionnent avec des fichiers de données et ont un pointeur de fichier comme premier argument.

fscanf(flux, "InputFormat", arguments);

Mots clés: Fichiers texte, fopen, fclose, feof, setbuf, setvbuf, fflush, fgetc, fprintf, fscanf, fgets, flux tamponné, flux non tamponné.

Travailler avec des fichiers texte

Travailler avec un fichier texte est similaire à travailler avec la console : en utilisant des fonctions d'entrée formatées, nous enregistrons les données dans un fichier, en utilisant des fonctions de sortie formatées, nous lisons les données d'un fichier. Il existe de nombreuses nuances que nous examinerons plus tard. Les principales opérations à effectuer sont

  • 1. Ouvrez le fichier pour pouvoir y accéder. En conséquence, vous pouvez l'ouvrir pour lire, écrire, lire et écrire, réécrire ou écrire jusqu'à la fin du fichier, etc. Lorsque vous ouvrez un fichier, de nombreuses erreurs peuvent également se produire : le fichier peut ne pas exister, il peut s'agir d'un type de fichier incorrect, vous n'êtes peut-être pas autorisé à travailler avec le fichier, etc. Tout cela doit être pris en compte.
  • 2. Travailler directement avec le fichier - écriture et lecture. Ici, nous devons également nous rappeler que nous ne travaillons pas avec de la mémoire vive, mais avec un flux tamponné, qui ajoute ses propres spécificités.
  • 3. Fermez le fichier. Puisque le fichier est une ressource externe au programme, s'il n'est pas fermé, il continuera à rester en mémoire, éventuellement même après la fermeture du programme (par exemple, il ne sera pas possible de supprimer un fichier ouvert ou d'apporter des modifications, etc.). De plus, il est parfois nécessaire non pas de fermer, mais de « rouvrir » un fichier pour, par exemple, changer le mode d'accès.

De plus, il existe un certain nombre de tâches pour lesquelles nous n'avons pas besoin d'accéder au contenu du fichier : renommer, déplacer, copier, etc. Malheureusement, le standard C ne contient pas de description des fonctions répondant à ces besoins. Ils sont bien entendu disponibles pour chacune des implémentations du compilateur. Lire le contenu d'un répertoire (dossier, répertoire), c'est aussi accéder à un fichier, car le dossier lui-même est un fichier avec des métainformations.

Parfois, il est nécessaire d'effectuer certaines opérations auxiliaires : se déplacer à l'emplacement souhaité dans le fichier, mémoriser la position actuelle, déterminer la longueur du fichier, etc.

Pour travailler avec un fichier, vous avez besoin d'un objet FILE. Cet objet stocke l'identifiant du flux de fichiers et les informations nécessaires à sa gestion, notamment un pointeur vers son tampon, un indicateur de position de fichier et des indicateurs d'état.

L'objet FILE est lui-même une structure, mais ses champs ne sont pas accessibles. Le programme portable doit traiter le fichier comme un objet abstrait permettant d'accéder au flux de fichiers.

La création et l'allocation de mémoire pour un objet de type FILE s'effectuent à l'aide de la fonction fopen ou tmpfile (il en existe d'autres, mais nous nous concentrerons uniquement sur celles-ci).

La fonction fopen ouvre un fichier. Il reçoit deux arguments : une chaîne avec l'adresse du fichier et une chaîne avec le mode d'accès au fichier. Le nom du fichier peut être absolu ou relatif. fopen renvoie un pointeur vers un objet FILE qui peut être utilisé pour accéder davantage au fichier.

FILE* fopen(const char* nom de fichier, const char* mode);

Par exemple, ouvrons un fichier et écrivons-y Hello World

#inclure #inclure #inclure void main() ( //En utilisant la variable file, nous accéderons au fichier FILE *file; //Ouvre un fichier texte avec les autorisations d'écriture file = fopen("C:/c/test.txt", "w+t") ; //Écrire dans le fichier fprintf(file, "Hello, World!"); //Fermer le fichier fclose(file); getch(); )

La fonction fopen alloue elle-même de la mémoire pour l'objet, le nettoyage est effectué par la fonction fclose. Il est nécessaire de fermer le fichier, il ne se fermera pas tout seul.

La fonction fopen peut ouvrir un fichier en mode texte ou binaire. La valeur par défaut est le texte. Le mode d'accès peut être le suivant

Options d'accès aux fichiers.
Taper Description
r En lisant. Le fichier doit exister.
w Écrivez un nouveau fichier. Si un fichier du même nom existe déjà, son contenu sera perdu.
un Écrivez à la fin du fichier. Les opérations de positionnement (fseek, fsetpos, frewind) sont ignorées. Le fichier est créé s'il n'existait pas.
r+ Lecture et mise à jour. Vous pouvez à la fois lire et écrire. Le fichier doit exister.
w+ Enregistrement et mise à jour. Un nouveau fichier est créé. Si un fichier du même nom existe déjà, son contenu sera perdu. Vous pouvez à la fois écrire et lire.
un+ Fin du message et mise à jour. Les opérations de positionnement sont en lecture seule et ignorées pour les écritures. Si le fichier n'existait pas, un nouveau sera créé.

S'il est nécessaire d'ouvrir le fichier en mode binaire, alors la lettre b est ajoutée à la fin de la ligne, par exemple « rb », « wb », « ab », ou, pour le mode mixte, « ab+ », « wb+", "ab+". Au lieu de b, vous pouvez ajouter la lettre t, le fichier s'ouvrira alors en mode texte. Cela dépend de la mise en œuvre. Dans la nouvelle norme C (2011), la lettre x signifie que fopen devrait échouer si le fichier existe déjà. Complétons notre ancien programme : rouvrez le fichier et considérez ce que nous y avons écrit.

#inclure #inclure #inclure void main() ( FILE *file; char buffer; file = fopen("C:/c/test.txt", "w"); fprintf(file, "Hello, World!"); fclose(file); file = fopen("C:/c/test.txt", "r"); fgets(buffer, 127, file); printf("%s", buffer); fclose(file); getch(); )

Au lieu de la fonction fgets, vous pouvez utiliser fscanf, mais vous devez vous rappeler qu'elle ne peut lire la ligne que jusqu'au premier espace.
fscanf(fichier, "%127s", tampon);

De plus, au lieu d'ouvrir et de fermer un fichier, vous pouvez utiliser la fonction freopen, qui « rouvre » le fichier avec de nouveaux droits d'accès.

#inclure #inclure #inclure void main() ( FILE *file; char buffer; file = fopen("C:/c/test.txt", "w"); fprintf(file, "Hello, World!"); freopen("C:/ c/test.txt", "r", fichier); fgets(buffer, 127, file); printf("%s", buffer); fclose(file); getch(); )

Les fonctions fprintf et fscanf diffèrent de printf et scanf uniquement en ce qu'elles prennent comme premier argument un pointeur vers le FILE vers lequel elles vont sortir ou à partir duquel elles vont lire des données. Il convient d'ajouter tout de suite que les fonctions printf et scanf peuvent être facilement remplacées par les fonctions fprintf et fscanf. Dans le système d'exploitation (nous considérons les systèmes d'exploitation les plus courants et les plus adéquats), il existe trois flux standard : le flux de sortie standard stdout, le flux d'entrée standard stdin et le flux de sortie d'erreur standard stderr. Ils s'ouvrent automatiquement au lancement de l'application et sont associés à la console. Exemple

#inclure #inclure #inclure void main() ( int a, b; fprintf(stdout, "Entrez deux nombres\n"); fscanf(stdin, "%d", &a); fscanf(stdin, "%d", &b); if (b == 0) ( fprintf(stderr, "Erreur : diviser par zéro"); ) else ( fprintf(stdout, "%.3f", (float) a / (float) b); ) getch(); )

Erreur lors de l'ouverture du fichier

Si l'appel de la fonction fopen échoue, il renverra NULL. Les erreurs lors du travail avec des fichiers se produisent assez souvent, donc chaque fois que nous ouvrons un fichier, nous devons vérifier le résultat du travail

#inclure #inclure #inclure #define ERROR_OPEN_FILE -3 void main() ( FILE *file; char buffer; file = fopen("C:/c/test.txt", "w"); if (file == NULL) ( printf("Erreur d'ouverture file"); getch(); exit(ERROR_OPEN_FILE); ) fprintf(file, "Hello, World!"); freopen("C:/c/test.txt", "r", file); if (file = = NULL) ( printf("Erreur d'ouverture du fichier"); getch(); exit(ERROR_OPEN_FILE); ) fgets(buffer, 127, file); printf("%s", buffer); fclose(file); getch() ; )

Le problème se pose lorsque plusieurs fichiers sont ouverts à la fois : si l'un d'entre eux ne peut pas être ouvert, alors les autres doivent également être fermés.

FICHIER *inputFile, *outputFile ; non signé m, n; non signé i, j; inputFile = fopen(INPUT_FILE, READ_ONLY); if (inputFile == NULL) ( printf("Erreur d'ouverture du fichier %s", INPUT_FILE); getch(); exit(3); ) outputFile = fopen(OUTPUT_FILE, WRITE_ONLY); if (outputFile == NULL) ( printf("Erreur d'ouverture du fichier %s", OUTPUT_FILE); getch(); if (inputFile != NULL) ( fclose(inputFile); ) exit(4); ) ...

Dans des cas simples, vous pouvez agir de front, comme dans le morceau de code précédent. Dans les cas plus complexes, on utilise des méthodes qui remplacent RAII du C++ : wrappers, ou fonctionnalités du compilateur (nettoyage dans GCC), etc.

Mise en mémoire tampon des données

Comme mentionné précédemment, lorsque nous produisons des données, elles sont d'abord placées dans un tampon. Le tampon est vidé

  • 1) S'il est plein
  • 2) Si le flux est fermé
  • 3) Si nous indiquons explicitement qu'il est nécessaire de vider le tampon (il y a aussi des exceptions ici :)).
  • 4) Également effacé si le programme s'est terminé avec succès. En même temps, tous les dossiers sont fermés. En cas d'erreur d'exécution, cela peut ne pas se produire.

Vous pouvez forcer le déchargement du tampon en appelant la fonction fflush(File *). Regardons deux exemples – avec et sans nettoyage.

#inclure #inclure #inclure void main() ( FILE *file; char c; file = fopen("C:/c/test.txt", "w"); do ( c = getch(); fprintf(file, "%c", c ); fprintf(stdout, "%c", c); //fflush(file); ) while(c != "q"); fclose(file); getch(); )

Décommentez l'appel fflush. Au moment de l'exécution, ouvrez le fichier texte et examinez le comportement.

Vous pouvez attribuer vous-même un tampon de fichier en définissant votre propre taille. Cela se fait à l'aide de la fonction

Void setbuf(FILE * flux, char * tampon);

qui prend un FILE déjà ouvert et un pointeur vers un nouveau tampon. La taille du nouveau tampon ne doit pas être inférieure à BUFSIZ (par exemple, sur le poste de travail actuel, BUFSIZ est de 512 octets). Si vous transmettez NULL comme tampon, le flux n'est plus tamponné. Vous pouvez également utiliser la fonction

Int setvbuf(FILE * stream, char * buffer, int mode, size_t size);

qui accepte un tampon de taille arbitraire. Le mode peut prendre les valeurs suivantes

  • _IOFBF- mise en mémoire tampon complète. Les données sont écrites dans le fichier lorsqu'il est plein. En lecture, le tampon est considéré comme plein lorsqu'une opération d'entrée est demandée et le tampon est vide.
  • _IOLBF- mise en mémoire tampon linéaire. Les données sont écrites dans le fichier lorsqu'il est plein ou lorsqu'un caractère de nouvelle ligne est rencontré. En lecture, le tampon est rempli jusqu'au caractère de nouvelle ligne lorsqu'une opération d'entrée est demandée et le tampon est vide.
  • _IONBF– pas de mise en mémoire tampon. Dans ce cas, les paramètres size et buffer sont ignorés.
En cas de succès, la fonction renvoie 0.

Exemple : définissons notre propre tampon et voyons comment s'effectue la lecture d'un fichier. Laissez le fichier être court (quelque chose comme Hello, World !), et nous le lisons caractère par caractère

#inclure #inclure #inclure void main() ( FILE *input = NULL; char c; char buffer = (0); input = fopen("D:/c/text.txt", "rt"); setbuf(input, buffer); while ( !feof(input)) ( c = fgetc(input); printf("%c\n", c); printf("%s\n", buffer); _getch(); ) fclose(input); )

On voit que les données sont déjà dans le tampon. La lecture caractère par caractère se fait depuis le buffer.

feof

Fonction int feof(FILE * stream); renvoie vrai si la fin du fichier est atteinte. La fonction est pratique à utiliser lorsque vous devez parcourir l'intégralité du fichier du début à la fin. Soit un fichier avec du contenu textuel text.txt. Nous lisons le fichier caractère par caractère et l'affichons à l'écran.

#inclure #inclure #inclure void main() ( FILE *input = NULL; char c; input = fopen("D:/c/text.txt", "rt"); if (input == NULL) ( printf("Erreur d'ouverture du fichier") ; _getch(); exit(0); ) while (!feof(input)) ( c = fgetc(input); fprintf(stdout, "%c", c); ) fclose(input); _getch(); )

Tout irait bien, mais la fonction feof ne fonctionne pas correctement... Cela est dû au fait que la notion de « fin de fichier » n'est pas définie. Une erreur qui se produit souvent lors de l'utilisation de feof est que les dernières données lues sont imprimées deux fois. Cela est dû au fait que les données sont écrites dans le tampon d'entrée, la dernière lecture se produit avec une erreur et la fonction renvoie l'ancienne valeur lue.

#inclure #inclure #inclure void main() ( FILE *input = NULL; char c; input = fopen("D:/c/text.txt", "rt"); if (input == NULL) ( printf("Erreur d'ouverture du fichier") ; _getch(); exit(0); ) while (!feof(input)) ( fscanf(input, "%c", &c); fprintf(stdout, "%c", c); ) fclose(input); _getch(); )

Cet exemple échouera (très probablement) et imprimera deux fois le dernier caractère du fichier.

La solution n'est pas d'utiliser feof. Par exemple, stockez le nombre total d'enregistrements ou utilisez le fait que les fonctions fscanf etc. renvoient généralement le nombre de valeurs correctement lues et mises en correspondance.

#inclure #inclure #inclure void main() ( FILE *input = NULL; char c; input = fopen("D:/c/text.txt", "rt"); if (input == NULL) ( printf("Erreur d'ouverture du fichier") ; _getch(); exit(0); ) while (fscanf(input, "%c", &c) == 1) ( fprintf(stdout, "%c", c); ) fclose(input); _getch() ; )

Exemples

1. Un fichier contient deux nombres : les dimensions du tableau. Remplissons le deuxième fichier avec un tableau de nombres aléatoires.

#inclure #inclure #inclure #inclure //Noms de fichiers et autorisations #define INPUT_FILE "D:/c/input.txt" #define OUTPUT_FILE "D:/c/output.txt" #define READ_ONLY "r" #define WRITE_ONLY "w" //Valeur maximale pour le tableau size #define MAX_DIMENSION 100 //Erreur lors de l'ouverture du fichier #define ERROR_OPEN_FILE -3 void main() ( FILE *inputFile, *outputFile; non signé m, n; non signé i, j; inputFile = fopen(INPUT_FILE, READ_ONLY); if ( inputFile == NULL) ( printf("Erreur d'ouverture du fichier %s", INPUT_FILE); getch(); exit(ERROR_OPEN_FILE); ) outputFile = fopen(OUTPUT_FILE, WRITE_ONLY); if (outputFile == NULL) ( printf("Erreur ouverture du fichier %s", OUTPUT_FILE); getch(); //Si le fichier peut être ouvert en lecture, alors il doit être fermé if (inputFile != NULL) ( fclose(inputFile); ) exit(ERROR_OPEN_FILE); ) fscanf (inputFile, "%ud %ud", &m, &n); si (m > MAX_DIMENSION) ( m = MAX_DIMENSION; ) if (n > MAX_DIMENSION) ( n = MAX_DIMENSION; ) srand(time(NULL)); pour (i = 0 ; je< n; i++) { for (j = 0; j < m; j++) { fprintf(outputFile, "%8d ", rand()); } fprintf(outputFile, "\n"); } //Закрываем файлы fclose(inputFile); fclose(outputFile); }

2. L'utilisateur copie le fichier et sélectionne d'abord le mode de fonctionnement : le fichier peut être sorti sur la console ou copié dans un nouveau fichier.

#inclure #inclure #inclure #define ERROR_FILE_OPEN -3 void main() ( FILE *origin = NULL; FILE *output = NULL; char filename; int mode; printf("Entrez le nom de fichier: "); scanf("%1023s", nom de fichier); origin = fopen (nom de fichier, "r"); if (origine == NULL) ( printf("Erreur d'ouverture du fichier %s", nom de fichier); getch(); exit(ERROR_FILE_OPEN); ) printf("enter mode: "); scanf( "%d", &mode); if (mode == 1) ( printf("Entrez le nom de fichier : "); scanf("%1023s", nom de fichier); sortie = fopen(nom de fichier, "w"); if (sortie = = NULL) ( printf("Erreur d'ouverture du fichier %s", nom de fichier); getch(); fclose(origin); exit(ERROR_FILE_OPEN); ) ) else ( output = stdout; ) while (!feof(origin)) ( fprintf (sortie, "%c", fgetc(origine)); ) fclose(origine); fclose(sortie); getch(); )

3. L'utilisateur saisit les données à partir de la console et celles-ci sont écrites dans un fichier jusqu'à ce que la touche Échap soit enfoncée. Consultez le programme et voyez. comment il se comporte si vous entrez en arrière : ce qui est affiché dans le fichier et ce qui est affiché dans la console.

#inclure #inclure #inclure #define ERROR_FILE_OPEN -3 void main() ( FILE *output = NULL; char c; output = fopen("D:/c/test_output.txt", "w+t"); if (output == NULL) ( printf ("Erreur d'ouverture du fichier"); _getch(); exit(ERROR_FILE_OPEN); ) for (;;) ( c = _getch(); if (c == 27) ( break; ) fputc(c, sortie); fputc( c, sortie standard); ) fclose(output); )

4. Le fichier contient des entiers. Trouvez-en le maximum. Profitons du fait que la fonction fscanf renvoie le nombre d'objets correctement lus et correspondants. Le chiffre 1 doit être renvoyé à chaque fois.

#inclure #inclure #inclure #define ERROR_FILE_OPEN -3 void main() ( FILE *input = NULL; int num, maxn, hasRead; input = fopen("D:/c/input.txt", "r"); if (input == NULL) ( printf("Erreur d'ouverture du fichier"); _getch(); exit(ERROR_FILE_OPEN); ) maxn = INT_MIN; hasRead = 1; while (hasRead == 1) ( hasRead = fscanf(input, "%d", &num); if (hasRead != 1) ( continuer; ) if (num >

Une autre solution consiste à lire les nombres jusqu’à la fin du fichier.

#inclure #inclure #inclure #inclure #define ERROR_FILE_OPEN -3 void main() ( FILE *input = NULL; int num, maxn, hasRead; input = fopen("D:/c/input.txt", "r"); if (input == NULL) ( printf("Erreur d'ouverture du fichier"); _getch(); exit(ERROR_FILE_OPEN); ) maxn = INT_MIN; while (!feof(input)) ( fscanf(input, "%d", &num); if (num > maxn ) ( maxn = num; ) ) printf("nombre max = %d", maxn); fclose(input); _getch(); )

5. Le fichier contient des mots : mot russe, tabulation, mot anglais, sur plusieurs lignes. L'utilisateur saisit un mot anglais, il faut sortir le mot russe.

Le fichier de traduction ressemble à ceci

soleil Soleil
stylo à crayon
stylo à bille crayon
porte porte
fenêtre fenêtre
chaise chaise
fauteuil

et enregistré dans l'encodage cp866 (OEM 866). C'est important : la dernière paire de mots se termine également par un saut de ligne.

L'algorithme est le suivant : on lit une ligne d'un fichier, on trouve un caractère de tabulation dans la ligne, on remplace le caractère de tabulation par un zéro, on copie un mot russe du tampon, on copie un mot anglais depuis le tampon, on vérifie l'égalité.

#inclure #inclure #inclure #inclure #define ERROR_FILE_OPEN -3 void main() ( FILE *input = NULL; char buffer; char enWord; char ruWord; char usrWord; index non signé; int length; int wasFound; input = fopen("D:/c/input.txt ", "r"); if (input == NULL) ( printf("Erreur d'ouverture du fichier"); _getch(); exit(ERROR_FILE_OPEN); ) printf("enter word: "); fgets(usrWord, 127, stdin ); wasFound = 0; while (!feof(input)) ( fgets(buffer, 511, input); length = strlen(buffer); for (index = 0; index< length; index++) { if (buffer == "\t") { buffer = "\0"; break; } } strcpy(ruWord, buffer); strcpy(enWord, &buffer); if (!strcmp(enWord, usrWord)) { wasFound = 1; break; } } if (wasFound) { printf("%s", ruWord); } else { printf("Word not found"); } fclose(input); _getch(); }

6. Comptez le nombre de lignes dans le fichier. Nous allons lire le fichier caractère par caractère, en comptant le nombre de caractères "\n" jusqu'à rencontrer le caractère EOF. EOF est un caractère spécial qui indique que la saisie est terminée et qu'il n'y a plus de données à lire. La fonction renvoie une valeur négative en cas d'erreur.
REMARQUE : EOF est de type int, vous devez donc utiliser int pour lire les caractères. De plus, la valeur de EOF n’est pas définie par la norme.

#define _CRT_SECURE_NO_WARNINGS #include #inclure #inclure int cntLines(const char *filename) ( int lines = 0; int any; //any est de type int car EOF est de type int! FILE *f = fopen(filename, "r"); if (f == NULL ) ( return -1; ) do ( any = fgetc(f); //printf("%c", any);//debug if (any == "\n") ( lignes++; ) ) while(any ! = EOF); ​​​​fclose(f); return lignes; ) void main() ( printf("%d\n", cntLines("C:/c/file.txt")); _getch(); )

Ru-Cyrl 18-tutoriel Sypachev S.S. 1989-04-14 [email protégé] Stépan Sypachevétudiants

Ce n'est toujours pas clair ? – écrire des questions dans la boîte aux lettres

Auparavant, lors de la saisie et de la sortie de données, nous travaillions avec des flux standard - le clavier et le moniteur. Voyons maintenant comment le langage C implémente la réception de données à partir de fichiers et leur écriture là-bas. Avant de pouvoir effectuer ces opérations, vous devez ouvrir le fichier et y accéder.

Dans le langage de programmation C, un pointeur vers un fichier est de type FILE et sa déclaration ressemble à ceci :
FICHIER *monfichier ;

D'autre part, la fonction fopen() ouvre un fichier à l'adresse spécifiée comme premier argument en mode lecture ("r"), en mode écriture ("w") ou en mode ajout ("a") et renvoie un pointeur au programme. Par conséquent, le processus d'ouverture d'un fichier et de connexion au programme ressemble à ceci :
monfichier = fopen("hello.txt", "r");

Lors de la lecture ou de l'écriture de données dans un fichier, celui-ci est accessible via un pointeur de fichier (dans ce cas, monfichier).

Si pour une raison ou une autre (il n'y a pas de fichier à l'adresse spécifiée, l'accès à celui-ci est refusé) la fonction fopen() ne peut pas ouvrir le fichier, alors elle renvoie NULL. Dans les programmes réels, ils gèrent presque toujours une erreur d'ouverture de fichier dans la branche if, mais nous l'omettrons davantage.

La déclaration de la fonction fopen() est contenue dans le fichier d'en-tête stdio.h, elle doit donc être incluse. Également dans stdio.h, le type de structure FILE est déclaré.

Une fois le travail terminé avec un fichier, il est d'usage de le fermer pour libérer le tampon des données et pour d'autres raisons. Ceci est particulièrement important si le programme continue de s'exécuter après avoir travaillé avec le fichier. La rupture de la connexion entre un fichier externe et un pointeur vers celui-ci à partir du programme se fait à l'aide de la fonction fclose(). Un pointeur vers le fichier lui est passé en paramètre :
fclose(monfichier);

Plus d'un fichier peut être ouvert dans le programme. Dans ce cas, chaque fichier doit être associé à son propre pointeur de fichier. Cependant, si le programme travaille d'abord avec un fichier puis le ferme, le pointeur peut être utilisé pour ouvrir un deuxième fichier.

Lire et écrire dans un fichier texte

fscanf()

La fonction fscanf() a une signification similaire à la fonction scanf(), mais contrairement à elle, elle fournit une entrée formatée à partir d'un fichier plutôt qu'une entrée standard. La fonction fscanf() prend en paramètres : pointeur de fichier, chaîne de format, adresses des zones mémoire pour l'écriture des données :
fscanf(monfichier, "%s%d", str, &a);

Renvoie le nombre de données lues avec succès ou EOF. Les espaces et les caractères de nouvelle ligne sont comptés comme délimiteurs de données.

Disons que nous avons un fichier contenant la description suivante des objets :

Pommes 10 23,4 bananes 5 25,0 pain 1 10,3

#inclure main () ( FILE * fichier; struct food ( char name[ 20 ] ; quantité non signée; float price; ) ; struct food shop[ 10 ] ; char i= 0 ; file = fopen ( "fscanf.txt", "r" ) ; while (fscanf (file, "%s%u%f" , shop[ i].name , & (shop[ i].qty ) , & (shop[ i].price ) ) != EOF) ( printf ("%s %u %.2f \n", boutique[i].nom, boutique[i].qté, boutique[i].prix) ; je++; ) )

Dans ce cas, une structure et un tableau de structures sont déclarés. Chaque ligne du fichier correspond à un élément du tableau ; un élément de tableau est une structure contenant une chaîne et deux champs numériques. La boucle lit une ligne par itération. Lorsque la fin du fichier est rencontrée, fscanf() renvoie EOF et la boucle se termine.

fgets()

La fonction fgets() est similaire à la fonction gets() et effectue une saisie ligne par ligne à partir d'un fichier. Un appel à fgets() lira une ligne. Dans ce cas, vous ne pouvez pas lire la ligne entière, mais seulement une partie depuis le début. Les paramètres fgets() ressemblent à ceci :
fgets (character_array, number_of_characters_read, pointer_to_file)

Par exemple:
fgets(str, 50, monfichier)

Cet appel de fonction lira dans le fichier associé au pointeur monfichier une ligne complète de texte si sa longueur est inférieure à 50 caractères, y compris le caractère "\n", que la fonction stockera également dans un tableau. Le dernier (50ème) élément du tableau str sera le caractère "\0" ajouté par fgets() . Si la chaîne est plus longue, la fonction lira 49 caractères et écrira "\0" à la fin. Dans ce cas, "\n" ne sera pas contenu dans la ligne de lecture.

#inclure #define N 80 main () ( FILE * file; char arr[ N] ; file = fopen ( "fscanf.txt" , "r" ) ; while (fgets (arr, N, file) != NULL) printf (" %s" , arr) ; printf (" \n") ; fclose(fichier); )

Dans ce programme, contrairement au précédent, les données sont lues ligne par ligne dans le tableau arr. A la lecture de la ligne suivante, la précédente est perdue. La fonction fgets() renvoie NULL si elle ne parvient pas à lire la ligne suivante.

getc() ou fgetc()

La fonction getc() ou fgetc() (les deux fonctionnent) vous permet d'obtenir le caractère suivant d'un fichier.

while ((arr[ i] = fgetc (file) ) != EOF) ( if (arr[ i] == " \n") (arr[je] = " \0 " ; printf("%s \n", arr) ; je = 0 ; ) sinon je++; )arr[i] = " \0 " ; printf("%s \n", arr) ;

L'exemple de code affiche les données d'un fichier à l'écran.

Écrire dans un fichier texte

Tout comme l'entrée, la sortie vers un fichier peut être différente.

  • Sortie formatée. Fonction fprintf (file_index, format_string, variables) .
  • Sortie post-par-ligne. Fonction fputs(string, file_pointer) .
  • Sortie caractère par caractère. Fonction fputc() ou putc(symbol, file_pointer) .

Vous trouverez ci-dessous des exemples de code qui utilisent trois méthodes de sortie de données dans un fichier.

Écriture des champs d'une structure sur chaque ligne du fichier :

fichier = fopen ("fprintf.txt" , "w" ) ; while (scanf ("%s%u%f" , shop[ i].name , & (shop[ i].qty ) , & (shop[ i].price ) ) != EOF) ( fprintf (fichier, " %s %u %.2f \n", boutique[i].nom, boutique[i].qté, boutique[i].prix) ; je++; )

Sortie ligne par ligne dans un fichier (fputs(), contrairement à puts() lui-même, ne place pas « \n » à la fin de la ligne) :

while (obtient (arr) != NULL) ( fputs (arr, fichier); fputs (" \n", déposer); )

Exemple de sortie caractère par caractère :

while ((i = getchar () ) != EOF) putc (i, file) ;

Lire et écrire dans un fichier binaire

Vous pouvez travailler avec un fichier non pas comme une séquence de caractères, mais comme une séquence d'octets. En principe, il n'est pas possible de travailler autrement avec des fichiers non texte. Cependant, vous pouvez lire et écrire dans des fichiers texte de cette façon. L'avantage de cette méthode d'accès à un fichier est la vitesse de lecture-écriture : un bloc d'information important peut être lu/écrit en un seul accès.

Lors de l'ouverture d'un fichier pour un accès binaire, le deuxième paramètre de fopen() est la chaîne "rb" ou "wb".

Le sujet du travail avec des fichiers binaires est assez complexe et nécessite une leçon distincte pour l'étudier. Ici, seules les caractéristiques des fonctions de lecture et d'écriture dans un fichier, considéré comme un flux d'octets, seront notées.

Les fonctions fread() et fwrite() prennent en paramètres :

  1. adresse de la zone mémoire dans laquelle les données sont écrites ou lues,
  2. la taille d'un modèle donné, quel que soit son type,
  3. la quantité de données lues de la taille spécifiée,
  4. index des fichiers.

Ces fonctions renvoient le nombre de données lues ou écrites avec succès. Ceux. vous pouvez « commander » la lecture de 50 données, mais n’en recevoir que 10. Il n’y aura pas d’erreur.

Un exemple d'utilisation des fonctions fread() et fwrite() :

#inclure #inclure main () ( FILE * fichier; char Shelf1[ 50 ], Shelf2[ 100 ] ; int n, m; file = fopen ("shelf1.txt" , "rb" ) ; n= fread (shelf1, sizeof (char ) , 50 , fichier) ; fclose (fichier) ; fichier = fopen ("shelf2.txt" , "rb" ) ; m= fread (shelf2, sizeof (char ) , 50 , fichier) ; fclose (fichier) ; étagère1[ n] = " \0 " ; étagère2[m] = " \n"; étagère2[ m+ 1 ] = " \0 " ; fichier = fopen ("shop.txt" , "wb" ) ; fwrite (strcat (étagère2, étagère1) , sizeof (char ) , n+ m, fichier) ; fclose(fichier); )

Ici, une tentative est faite pour lire 50 caractères du premier fichier. n stocke le nombre de caractères réellement lus. La valeur de n peut être inférieure ou égale à 50. Les données sont placées dans une ligne. La même chose se produit avec le deuxième fichier. Ensuite, la première ligne est ajoutée à la seconde et les données sont transférées dans le troisième fichier.

Résolution de problème

  1. Écrivez un programme qui demande à l'utilisateur le nom (adresse) d'un fichier texte, puis l'ouvre et compte le nombre de caractères et de lignes qu'il contient.
  2. Écrivez un programme qui écrit dans un fichier les données reçues d'un autre fichier et modifiées d'une manière ou d'une autre avant l'écriture. Chaque ligne de données obtenue à partir d'un fichier doit s'inscrire dans une structure.

La plupart des programmes informatiques fonctionnent avec des fichiers et il est donc nécessaire de créer, supprimer, écrire, lire et ouvrir des fichiers. Qu'est-ce qu'un fichier ? Un fichier est un ensemble nommé d'octets qui peuvent être stockés sur un périphérique de stockage. Eh bien, il est maintenant clair qu'un fichier désigne une certaine séquence d'octets qui a son propre nom unique, par exemple file.txt. Les fichiers portant les mêmes noms ne peuvent pas se trouver dans le même répertoire. Le nom du fichier fait référence non seulement à son nom, mais aussi à son extension, par exemple : fichier.txt et fichier.dat fichiers différents, bien qu'ils portent les mêmes noms. Il existe un nom de fichier complet - il s'agit de l'adresse complète du répertoire de fichiers indiquant le nom du fichier, par exemple : D:\docs\file.txt. Il est important de comprendre ces concepts de base, sinon il sera difficile de travailler avec des fichiers.

Pour travailler avec des fichiers, vous devez inclure un fichier d'en-tête . DANS plusieurs classes sont définies et les fichiers d'en-tête sont inclus entrée de fichier et sortie de fichier.

Les E/S de fichier sont similaires aux E/S standard, la seule différence est que les E/S sont effectuées vers un fichier plutôt que vers l'écran. Si les E/S vers les périphériques standard sont effectuées à l'aide des objets cin et cout, alors pour organiser les E/S sur les fichiers, il suffit de créer vos propres objets qui peuvent être utilisés de la même manière que les opérateurs cin et cout.

Par exemple, vous devez créer un fichier texte et y écrire la ligne Travailler avec des fichiers en C++. Pour ce faire, vous devez suivre les étapes suivantes :

  1. créer un objet de classe ofstream ;
  2. associer un objet de classe au fichier dans lequel écrire ;
  3. écrire une ligne dans un fichier ;
  4. fermez le fichier.

Pourquoi est-il nécessaire de créer un objet ofstream plutôt qu'un objet ifstream ? Parce que vous devez écrire dans un fichier et si vous devez lire des données à partir d'un fichier, un objet de classe ifstream sera créé.

// crée un objet pour écrire dans le fichier ofstream /*nom de l'objet*/; // objet de la classe ofstream

Appelons l'objet fout. Voici ce que nous obtenons :

Ofstream fout;

Pourquoi avons-nous besoin d’un objet ? L'objet doit pouvoir écrire dans un fichier. L'objet a déjà été créé, mais n'est pas associé au fichier dans lequel la chaîne doit être écrite.

Fout.open("cppstudio.txt"); // associe l'objet au fichier

Grâce à l'opération point, nous accédons à la méthode de classe open(), dans laquelle nous indiquons le nom du fichier entre parenthèses. Le fichier spécifié sera créé dans le répertoire courant avec le programme. Si un fichier du même nom existe, le fichier existant sera remplacé par le nouveau. Ainsi, le fichier est ouvert, il ne reste plus qu'à y écrire la ligne souhaitée. Cela se fait comme ceci :

Fout<< "Работа с файлами в С++"; // запись строки в файл

En utilisant l'opération stream en conjonction avec l'objet fout, la chaîne Working with files in C++ est écrite dans un fichier. Puisqu'il n'est plus nécessaire de modifier le contenu du fichier, celui-ci doit être fermé, c'est-à-dire que l'objet doit être séparé du fichier.

Fout.close(); // ferme le fichier

Résultat - un fichier a été créé avec la ligne Working with files in C++.

Les étapes 1 et 2 peuvent être combinées, c'est-à-dire sur une seule ligne, créer un objet et l'associer à un fichier. Cela se fait comme ceci :

Ofstream fout("cppstudio.txt"); // crée un objet de la classe ofstream et l'associe au fichier cppstudio.txt

Combinons tout le code et obtenons le programme suivant.

// file.cpp : Définit le point d'entrée de l'application console. #include "stdafx.h" #include en utilisant l'espace de noms std ; int main(int argc, char* argv) ( ofstream fout("cppstudio.txt"); // crée un objet de la classe ofstream pour l'enregistrement et l'associe au fichier cppstudio.txt fout<< "Работа с файлами в С++"; // запись строки в файл fout.close(); // закрываем файл system("pause"); return 0; }

Reste à vérifier que le programme fonctionne correctement, et pour cela, ouvrez le fichier cppstudio.txt et regardez son contenu, ça devrait être - Travailler avec des fichiers en C++.

  1. créer un objet de la classe ifstream et l'associer au fichier à partir duquel la lecture sera effectuée ;
  2. lire le fichier ;
  3. fermez le fichier.
// file_read.cpp : Définit le point d'entrée de l'application console. #include "stdafx.h" #include #inclure en utilisant l'espace de noms std ; int main(int argc, char* argv) ( setlocale(LC_ALL, "rus"); // affichage correct du caractère cyrillique buff; // tampon de stockage intermédiaire du texte lu dans un fichier ifstream fin("cppstudio.txt") ; // fichier ouvert pour lire fin >><< buff << endl; // напечатали это слово fin.getline(buff, 50); // считали строку из файла fin.close(); // закрываем файл cout << buff << endl; // напечатали эту строку system("pause"); return 0; }

Le programme montre deux façons de lire à partir d'un fichier, la première utilise l'opération de transfert vers un flux, la seconde utilise la fonction obtenir la ligne() . Dans le premier cas, seul le premier mot est lu, et dans le second cas, une chaîne de 50 caractères est lue. Mais comme il reste moins de 50 caractères dans le fichier, les caractères jusqu'au dernier inclus sont lus. Veuillez noter que lire une deuxième fois (ligne 17) a continué après le premier mot, et non depuis le début, puisque le premier mot a été lu dansligne 14. Le résultat du programme est présenté dans la figure 1.

Travailler avec des fichiers en C++ Pour continuer, appuyez sur n'importe quelle touche. . .

Figure 1 - Utilisation de fichiers en C++

Le programme a fonctionné correctement, mais cela n'arrive pas toujours, même si tout est en ordre avec le code. Par exemple, le nom d'un fichier inexistant a été transmis au programme ou il y a eu une erreur dans le nom. Et alors ? Dans ce cas, il ne se passera rien du tout. Le fichier ne sera pas trouvé, ce qui signifie qu'il ne sera pas possible de le lire. Par conséquent, le compilateur ignorera les lignes où le travail est effectué sur le fichier. En conséquence, le programme se fermera correctement, mais rien ne s'affichera à l'écran. Il semblerait que ce soit une réaction tout à fait normale face à une telle situation. Mais un simple utilisateur ne comprendra pas ce qui se passe et pourquoi la ligne du fichier n'apparaît pas à l'écran. Donc, pour que tout soit très clair, C++ fournit une telle fonction - is_open(), qui renvoie des valeurs entières : 1 - si le fichier a été ouvert avec succès, 0 - si le fichier n'a pas été ouvert. Modifions le programme en ouvrant un fichier, de sorte que si le fichier n'est pas ouvert, un message correspondant s'affiche.

// file_read.cpp : Définit le point d'entrée de l'application console. #include "stdafx.h" #include #inclure en utilisant l'espace de noms std ; int main(int argc, char* argv) ( setlocale(LC_ALL, "rus"); // affichage correct du caractère cyrillique buff; // tampon de stockage intermédiaire du texte lu dans un fichier ifstream fin("cppstudio.doc") ; // ( VOUS AVEZ ENTRÉ UN NOM DE FICHIER INVALIDE) if (!fin.is_open()) // si le fichier n'est pas ouvert cout<< "Файл не может быть открыт!\n"; // сообщить об этом else { fin >> chamois ; // compte le premier mot du fichier cout<< buff << endl; // напечатали это слово fin.getline(buff, 50); // считали строку из файла fin.close(); // закрываем файл cout << buff << endl; // напечатали эту строку } system("pause"); return 0; }

Le résultat du programme est présenté dans la figure 2.

Le fichier ne peut pas être ouvert ! Pour continuer, appuyez sur n'importe quelle touche. . .

Figure 2 - Travailler avec des fichiers en C++

Comme le montre la figure 2, le programme a signalé qu'il était impossible d'ouvrir le fichier. Par conséquent, si le programme fonctionne avec des fichiers, il est recommandé d'utiliser cette fonction, is_open(), même si vous êtes sûr que le fichier existe.

Modes d'ouverture de fichiers

Les modes d'ouverture de fichiers déterminent la manière dont les fichiers sont utilisés. Pour définir le mode, la classe ios_base fournit des constantes qui déterminent le mode d'ouverture du fichier (voir Tableau 1).

Les modes d'ouverture de fichiers peuvent être définis directement lors de la création d'un objet ou lors de l'appel de la fonction open() .

Ofstream fout("cppstudio.txt", ios_base::app); // ouvre le fichier pour ajouter des informations à la fin du fichier fout.open("cppstudio.txt", ios_base::app); // ouvre le fichier pour ajouter des informations à la fin du fichier

Les modes d'ouverture de fichiers peuvent être combinés à l'aide d'une opération logique au niveau du bit ou| , par exemple : ios_base::out | ios_base::trunc - ouvre un fichier en écriture après l'avoir effacé.

Les objets de la classe ofstream, lorsqu'ils sont associés à des fichiers, contiennent par défaut des modes d'ouverture de fichiers ios_base::out | ios_base ::trunc . Autrement dit, le fichier sera créé s'il n'existe pas. Si le fichier existe, son contenu sera supprimé et le fichier lui-même sera prêt à être écrit. Les objets de la classe ifstream, lorsqu'ils sont associés à un fichier, ont le mode d'ouverture de fichier par défaut ios_base::in - le fichier est ouvert en lecture seule. Le mode d'ouverture du fichier est également appelé drapeau ; pour des raisons de lisibilité, nous utiliserons ce terme à l'avenir. Le tableau 1 ne répertorie pas tous les indicateurs, mais ceux-ci devraient suffire pour vous aider à démarrer.

Notez que les indicateurs ate et app ont une description très similaire, ils déplacent tous deux le pointeur vers la fin du fichier, mais l'indicateur app permet uniquement d'écrire jusqu'à la fin du fichier, et l'indicateur ate déplace simplement le drapeau vers la fin. du fichier et ne limite pas où écrire.

Développons un programme qui, à l'aide de l'opération sizeof(), calculera les caractéristiques des principaux types de données en C++ et les écrira dans un fichier. Caractéristiques:

  1. nombre d'octets alloués au type de données
  2. la valeur maximale qu'un type de données particulier peut stocker.

Le fichier doit être écrit au format suivant :

/* type de données octet valeur maximale bool = 1 255,00 char = 1 255,00 short int = 2 32767,00 unsigned short int = 2 65535,00 int = 4 2147483647,00 unsigned int = 4 4294967295,00 long int = 4 2147483647. 00 non signé long int = 4 4294967295.00 float = 4 2147483647.00 flotteur long = 8 9223372036854775800.00 double = 8 9223372036854775800.00 */

Un tel programme a déjà été développé plus tôt dans la section, mais là, toutes les informations sur les types de données ont été sorties sur le périphérique de sortie standard, et nous devons refaire le programme pour que les informations soient écrites dans un fichier. Pour ce faire, vous devez ouvrir le fichier en mode écriture, avec troncature préalable des informations du fichier actuel ( ligne 14). Une fois le fichier créé et ouvert avec succès (lignes 16 à 20), au lieu de l'instruction cout, dans ligne 22 nous utilisons l'objet fout. ainsi, au lieu de l'écran, les informations sur les types de données seront écrites dans un fichier.

// write_file.cpp : Définit le point d'entrée de l'application console. #include "stdafx.h" #include #inclure // travailler avec des fichiers #include // manipulateurs d'entrée/sortie utilisant l'espace de noms std ; int main(int argc, char* argv) ( setlocale(LC_ALL, "rus"); // associe l'objet au fichier et ouvre le fichier en mode écriture, en supprimant d'abord toutes les données ofstream fout("data_types.txt ", ios_base::out | ios_base::trunc); if (!fout.is_open()) // si le fichier n'a pas été ouvert ( cout<< "Файл не может быть открыт или создан\n"; // напечатать соответствующее сообщение return 1; // выполнить выход из программы } fout << " data type " << "byte" << " " << " max value "<< endl // en-têtes de colonnes <<"bool = " << sizeof(bool) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных bool*/ << (pow(2,sizeof(bool) * 8.0) - 1) << endl << "char = " << sizeof(char) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных char*/ << (pow(2,sizeof(char) * 8.0) - 1) << endl << "short int = " << sizeof(short int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных short int*/ << (pow(2,sizeof(short int) * 8.0 - 1) - 1) << endl << "unsigned short int = " << sizeof(unsigned short int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных unsigned short int*/ << (pow(2,sizeof(unsigned short int) * 8.0) - 1) << endl << "int = " << sizeof(int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных int*/ << (pow(2,sizeof(int) * 8.0 - 1) - 1) << endl << "unsigned int = " << sizeof(unsigned int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных unsigned int*/ << (pow(2,sizeof(unsigned int) * 8.0) - 1) << endl << "long int = " << sizeof(long int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных long int*/ << (pow(2,sizeof(long int) * 8.0 - 1) - 1) << endl << "unsigned long int = " << sizeof(unsigned long int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных undigned long int*/ << (pow(2,sizeof(unsigned long int) * 8.0) - 1) << endl << "float = " << sizeof(float) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных float*/ << (pow(2,sizeof(float) * 8.0 - 1) - 1) << endl << "long float = " << sizeof(long float) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных long float*/ << (pow(2,sizeof(long float) * 8.0 - 1) - 1) << endl << "double = " << sizeof(double) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных double*/ << (pow(2,sizeof(double) * 8.0 - 1) - 1) << endl; fout.close(); // программа больше не использует файл, поэтому его нужно закрыть cout << "Данные успешно записаны в файл data_types.txt\n"; system("pause"); return 0; }

Il est impossible de ne pas remarquer que les changements dans le programme sont minimes, et tout cela grâce au fait que les entrées/sorties standard et les entrées/sorties de fichiers sont utilisées exactement de la même manière. A la fin du programme, àligne 45Nous avons explicitement fermé le fichier, bien que cela ne soit pas nécessaire, mais que cela soit considéré comme une bonne pratique de programmation. Il convient de noter que toutes les fonctions et manipulateurs utilisés pour formater les entrées/sorties standard sont également pertinents pour les entrées/sorties de fichiers. Par conséquent, aucune erreur ne s'est produite lorsque l'instruction cout a été remplacé par un objet fout.