126 votes

En C, comment dois-je lire un fichier texte et imprimer toutes les chaînes de caractères

J'ai un fichier texte nommé test.txt

Je veux écrire un programme C qui peut lire ce fichier et afficher le contenu dans la console (en supposant que le fichier contient uniquement du texte ASCII).

Je ne sais pas comment obtenir la taille de ma variable de chaîne. Comme ceci:

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 de 999 ne fonctionne pas car la chaîne retournée par fscanf peut être plus grande que cela. Comment puis-je résoudre cela?

2voto

RBerteig Points 23331

Deux approches viennent à l'esprit.

Premièrement, n'utilisez pas scanf. Utilisez fgets() qui prend un paramètre pour spécifier la taille du tampon, et qui laisse les caractères de saut de 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 commun en C avec fgetc(). Cela traite le fichier par morceaux de taille fixe ou un caractère à la fois.

Si vous devez traiter le fichier sur des chaînes délimitées par des espaces blancs, alors utilisez soit fgets soit fread pour lire le fichier, et quelque chose comme strtok pour diviser le tampon aux espaces blancs. N'oubliez pas de gérer la transition d'un tampon à l'autre, car vos chaînes cibles sont susceptibles de traverser la limite du tampon.

S'il existe une exigence externe d'utiliser scanf pour la lecture, limitez la longueur de la chaîne qu'il pourrait 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); ce qui écrira au plus 998 caractères dans le tampon laissant de la place pour le terminateur nul. Si des chaînes uniques plus longues que votre tampon sont autorisées, vous devriez les traiter en deux morceaux. Sinon, vous avez l'opportunité d'informer poliment l'utilisateur d'une erreur sans créer de faille de sécurité de débordement de 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.

1voto

Zakk Points 196

Vous pouvez utiliser getline() pour lire votre fichier texte sans vous soucier des lignes longues :

getline() lit une ligne entière depuis stream, en stockant l'adresse du tampon contenant le texte dans *lineptr. Le tampon est terminé par un caractère nul et inclut le caractère de saut de ligne, s'il a été trouvé.

Si *lineptr est défini sur NULL avant l'appel, alors getline() allouera un tampon pour stocker la ligne. Ce tampon doit être libéré par le programme utilisateur même si getline() a échoué.

bool read_file(const char *filename)
{
    FILE *file = fopen(filename, "r");
    if (!file)
        return false;

    char *line = NULL;
    size_t linesize = 0;

    while (getline(&line, &linesize, file) != -1) {
        printf("%s", line);
        free(line);
    }

    free(line);
    fclose(file);

    return true;
}

Vous pouvez l'utiliser de cette façon :

int main(void)
{
    if (!read_file("test.txt")) {
        printf("Erreur de lecture du fichier\n");
        exit(EXIT_FAILURE);
    }
}

1voto

Marco Ciaramella Points 129

Je utilise cette version

char* read(const char* filename){
    FILE* f = fopen(filename, "rb");
    if (f == NULL){
        exit(1);
    }
    fseek(f, 0L, SEEK_END);
    long size = ftell(f)+1;
    fclose(f);
    f = fopen(filename, "r");
    void* content = memset(malloc(size), '\0', size);
    fread(content, 1, size-1, f);
    fclose(f);
    return (char*) content;
}

0voto

Ricardo Points 162

Vous pourriez lire l'intégralité du fichier avec 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 est donc préférable de lire de petites parties du fichier et de les afficher.

#include 
#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;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X