J'ai un fichier texte nommé test.txt
Je veux écrire un programme C qui peut lire ce fichier et imprimer le contenu sur la console (supposons que le fichier ne contienne que du texte ASCII).
Je ne sais pas comment obtenir la taille de ma variable de chaîne. Comme ça:
char str[999];
FILE * file;
file = fopen( "test.txt" , "r");
if (file) {
while (fscanf(file, "%s", str)!=EOF)
printf("%s",str);
fclose(file);
}
La taille 999
ne fonctionne pas car la chaîne renvoyée par fscanf
peut être plus grande que cela. Comment puis-je résoudre ça?
la source
stdout
.c
c'est int, et C garantira qu'ilEOF
n'est égal à aucun caractère valide.Il y a beaucoup de bonnes réponses ici sur la lecture en morceaux, je vais juste vous montrer une petite astuce qui lit tout le contenu à la fois dans un tampon et l'imprime.
Je ne dis pas que c'est mieux. Ce n'est pas le cas, et comme Ricardo parfois ça peut être mauvais, mais je trouve que c'est une bonne solution pour les cas simples.
Je l'ai parsemé de commentaires car il se passe beaucoup de choses.
#include <stdio.h> #include <stdlib.h> char* ReadFile(char *filename) { char *buffer = NULL; int string_size, read_size; FILE *handler = fopen(filename, "r"); if (handler) { // Seek the last byte of the file fseek(handler, 0, SEEK_END); // Offset from the first to the last byte, or in other words, filesize string_size = ftell(handler); // go back to the start of the file rewind(handler); // Allocate a string that can hold it all buffer = (char*) malloc(sizeof(char) * (string_size + 1) ); // Read it all in one operation read_size = fread(buffer, sizeof(char), string_size, handler); // fread doesn't set it so put a \0 in the last position // and buffer is now officially a string buffer[string_size] = '\0'; if (string_size != read_size) { // Something went wrong, throw away the memory and set // the buffer to NULL free(buffer); buffer = NULL; } // Always remember to close the file. fclose(handler); } return buffer; } int main() { char *string = ReadFile("yourfile.txt"); if (string) { puts(string); free(string); } return 0; }
Faites-moi savoir si c'est utile ou si vous pourriez en apprendre quelque chose :)
la source
buffer[string_size] = '\0';
au lieu destring_size+1
? Afaik la chaîne réelle va de0
àstring_size-1
et le\0
caractère doit donc être àstring_size
, non?ftell
etfseek
pour trouver la taille d'un fichier n'est pas sûr: securecoding.cert.org/confluence/display/seccode/…fclose(handle)
calloc(2)
plutôt que de nemalloc(1)
pas avoir à définir le terminateur nul.Au lieu de cela, imprimez directement les caractères sur la console car le fichier texte peut être très volumineux et vous pouvez avoir besoin de beaucoup de mémoire.
#include <stdio.h> #include <stdlib.h> int main() { FILE *f; char c; f=fopen("test.txt","rt"); while((c=fgetc(f))!=EOF){ printf("%c",c); } fclose(f); return 0; }
la source
Utilisez "read ()" à la place de fscanf:
ssize_t read(int fildes, void *buf, size_t nbyte);
Voici un exemple:
http://cmagical.blogspot.com/2010/01/c-programming-on-unix-implementing-cat.html
Partie de travail de cet exemple:
f=open(argv[1],O_RDONLY); while ((n=read(f,l,80)) > 0) write(1,l,n);
Une autre approche consiste à utiliser
getc
/putc
pour lire / écrire 1 caractère à la fois. Beaucoup moins efficace. Un bon exemple: http://www.eskimo.com/~scs/cclass/notes/sx13.htmlla source
read
vous permettra de lire un certain nombre de caractères. Lisez suffisamment pour remplir votre tampon, puis videz votre tampon sur l'écran, effacez-le et répétez jusqu'à ce que vous arriviez à la fin du fichier.Deux approches me viennent à l'esprit.
Tout d'abord, ne l'utilisez pas
scanf
. Utilisezfgets()
qui prend un paramètre pour spécifier la taille de la mémoire tampon, et qui laisse les caractères de nouvelle ligne intacts. Une simple boucle sur le fichier qui imprime le contenu du tampon devrait naturellement copier le fichier intact.Deuxièmement, utilisez
fread()
ou l'idiome C commun avecfgetc()
. Ceux-ci traiteraient le fichier en morceaux de taille fixe ou un seul caractère à la fois.Si vous devez traiter le fichier sur des chaînes délimitées par des espaces, utilisez l'un
fgets
ou l' autrefread
pour lire le fichier, et quelque chose commestrtok
pour diviser le tampon en espace blanc. N'oubliez pas de gérer la transition d'un tampon à l'autre, car vos chaînes cibles sont susceptibles de couvrir la limite du tampon.S'il existe une exigence externe à utiliser
scanf
pour effectuer la lecture, limitez la longueur de la chaîne qu'il peut lire avec un champ de précision dans le spécificateur de format. Dans votre cas avec un tampon de 999 octets, ditesscanf("%998s", str);
qui écrira au plus 998 caractères dans le tampon en laissant de la place pour le terminateur nul. Si des chaînes simples plus longues que votre tampon sont autorisées, vous devrez les traiter en deux parties. Sinon, vous avez la possibilité d'informer poliment l'utilisateur d'une erreur sans créer de trou de sécurité de dépassement de la mémoire tampon.Quoi qu'il en soit, validez toujours les valeurs de retour et réfléchissez à la manière de gérer les entrées incorrectes, malveillantes ou simplement mal formées.
la source
Vous pouvez utiliser
fgets
et limiter la taille de la chaîne de lecture.char *fgets(char *str, int num, FILE *stream);
Vous pouvez modifier le
while
dans votre code en:while (fgets(str, 100, file)) /* printf("%s", str) */;
la source
Vous pouvez lire le fichier entier avec une allocation de mémoire dynamique, mais ce n'est pas une bonne idée car si le fichier est trop gros, vous pourriez avoir des problèmes de mémoire.
Il vaut donc mieux lire de courtes parties du fichier et l'imprimer.
#include <stdio.h> #define BLOCK 1000 int main() { FILE *f=fopen("teste.txt","r"); int size; char buffer[BLOCK]; // ... while((size=fread(buffer,BLOCK,sizeof(char),f)>0) fwrite(buffer,size,sizeof(char),stdout); fclose(f); // ... return 0; }
la source