J'ai un fichier texte nommé test.txt
Je souhaite écrire un programme C capable de lire ce fichier et d’en imprimer le contenu sur la console (en supposant que le fichier ne contienne que le texte ASCII.).
Je ne sais pas comment obtenir la taille de ma variable 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?
Le moyen le plus simple est de lire un caractère et de l'imprimer juste après avoir lu:
int c;
FILE *file;
file = fopen("test.txt", "r");
if (file) {
while ((c = getc(file)) != EOF)
putchar(c);
fclose(file);
}
c
est int
ci-dessus, puisque EOF
est un nombre négatif et qu'un simple char
peut être unsigned
.
Si vous voulez lire le fichier en morceaux, mais sans allocation de mémoire dynamique, vous pouvez faire:
#define CHUNK 1024 /* read 1024 bytes at a time */
char buf[CHUNK];
FILE *file;
size_t nread;
file = fopen("test.txt", "r");
if (file) {
while ((nread = fread(buf, 1, sizeof buf, file)) > 0)
fwrite(buf, 1, nread, stdout);
if (ferror(file)) {
/* deal with error */
}
fclose(file);
}
La deuxième méthode ci-dessus consiste essentiellement à lire un fichier avec un tableau alloué dynamiquement:
char *buf = malloc(chunk);
if (buf == NULL) {
/* deal with malloc() failure */
}
/* otherwise do this. Note 'chunk' instead of 'sizeof buf' */
while ((nread = fread(buf, 1, chunk, file)) > 0) {
/* as above */
}
Votre méthode de fscanf()
avec %s
en tant que format perd les informations sur les espaces dans le fichier. Il ne s'agit donc pas de copier un fichier dans stdout
.
Il y a beaucoup de bonnes réponses ici pour le lire en morceaux, je vais juste vous montrer un petit truc qui lit tout le contenu en même temps dans un tampon et l'imprime.
Je ne dis pas que c'est mieux. Ce n'est pas le cas, et comme Ricardo, cela peut parfois être mauvais, mais je trouve que c'est une solution intéressante pour les cas simples.
Je l'ai saupoudré de commentaires parce qu'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 pouviez en apprendre quelque chose :)
Au lieu de cela, imprimez directement les caractères sur la console car le fichier texte est peut-être très volumineux et vous risquez de nécessiter 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;
}
Utilisez "read ()" à la place de fscanf:
ssize_t read(int fildes, void *buf, size_t nbyte);
LA DESCRIPTION
La fonction read () doit tenter de lire
nbyte
octets du fichier associé au descripteur de fichier ouvert,fildes
, dans la mémoire tampon désignée parbuf
.
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.html
Vous pouvez utiliser fgets
et limiter la taille de la chaîne de lecture.
char *fgets(char *str, int num, FILE *stream);
Vous pouvez remplacer le while
dans votre code par:
while (fgets(str, 100, file)) /* printf("%s", str) */;
Deux approches me viennent à l’esprit.
Tout d'abord, n'utilisez pas scanf
. Utilisez fgets()
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 de la mémoire tampon devrait naturellement copier le fichier intact.
Deuxièmement, utilisez fread()
ou le langage C commun avec fgetc()
. Ceux-ci traiteraient le fichier en morceaux de taille fixe ou en un seul caractère à la fois.
Si vous devez traiter le fichier sur des chaînes délimitées par des espaces, utilisez soit fgets
ou fread
pour lire le fichier, et quelque chose comme strtok
pour diviser le tampon à des espaces. N'oubliez pas de gérer la transition d'une mémoire tampon à l'autre, car vos chaînes cible risquent de s'étendre sur la limite de la mémoire tampon.
S'il existe une exigence externe d'utiliser scanf
pour effectuer la lecture, limitez la longueur de la chaîne qu'il est possible de lire avec un champ de précision dans le spécificateur de format. Dans votre cas avec un tampon de 999 octets, dites alors scanf("%998s", str);
qui écrira au maximum 998 caractères dans le tampon en laissant de la place au terminateur nul. Si des chaînes uniques plus longues que votre mémoire tampon sont autorisées, vous devrez les traiter en deux parties. Si ce n'est pas le cas, vous avez la possibilité de signaler poliment une erreur à l'utilisateur sans créer de faille de sécurité liée au débordement de la mémoire tampon.
Quoi qu'il en soit, validez toujours les valeurs de retour et réfléchissez à la façon de gérer les entrées mauvaises, malveillantes ou simplement mal formées.
#include <stdio.h>
#include <stdlib.h>
int main() {
int num;
FILE *fptr;
if ((fptr = fopen("/root/Desktop/my_pass.txt","r")) == NULL) { // checks if file exists
puts("File not exists");
exit(1); // for exit(1) is required #include <stdlib.h>
} else
fscanf(fptr,"%d", &num);
printf("My pass is: %d\n", num);
fclose(fptr);
return 0;
}
Vous pouvez lire le fichier entier avec l'allocation de mémoire dynamique, mais ce n'est pas une bonne idée car si le fichier est trop volumineux, vous pourriez avoir des problèmes de mémoire.
Il est donc préférable de lire de courtes parties du fichier et de 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;
}