IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

[Améliorations] Programme de manipulations de fichier


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    36
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 36
    Par défaut [Améliorations] Programme de manipulations de fichier
    Bonjour,

    Je viens vous présenter un programme permettant à l'utilisateur de manipuler (basiquement) ses fichiers.

    Voici le code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    #define MAX_LEN 	1000 	/* Taille de chaîne maximale */
    #define BASE		10	/* Base décimale */
     
     
    #define FAIL		0	
    #define SUCCESS		1 	/* Constantes pour les retours de fonction */
     
    typedef struct File
    {
        FILE* ptr;
        char* path;
    } File;
     
    int menu(long*);
    void readFile(File*);
    void createFile(File*);
    void writeFile(File*);
     
    void clean(void);
    int read_string(char*, const int);
    long read_long(long**);
    void error(void);
     
    int main(void)
    {
    	long ret, retMenu;		
    	File my_file;
     
    	my_file.ptr = NULL;
    	my_file.path = NULL;
     
    	printf("\n\n          zReader - Manipulez vos fichiers");
     
    	do
    	{
    		if((ret = menu(&retMenu)) == FAIL) 
    			error();
     
    		if(retMenu == 1) 
    			readFile(&my_file);
     
    		else if(retMenu == 2) 
    			createFile(&my_file);
     
    		else if(retMenu == 3) 
    			writeFile(&my_file);
     
    		else if(retMenu == 4) 
    			break;
     
    		else 
    			printf("\n Mauvaise saisie, recommencez !\n\n");
     
    	} while(1);
     
    	return EXIT_SUCCESS;
    }
     
    int menu(long* ret)
    {
    	printf( "\n\n\n   MENU\n"
    		" 1 - Lire un fichier\n"
    		" 2 - Créer un fichier\n"
    		" 3 - Ecrire dans un fichier\n"
    		" 4 - Quitter le programme\n\n"	
    		" Votre choix ? ");
    	if((read_long(&ret)) == FAIL)
    		return FAIL;
     
    	else
    		return SUCCESS;
    }
     
    void readFile(File* my_file)
    {
    	int retPath;
    	char str[MAX_LEN] = "";
     
    	my_file->path = malloc(MAX_LEN * sizeof(my_file->path));
     
    	while(1)
    	{	
    		printf("\n\n Entrez le chemin du fichier que vous souhaitez lire : ");
    		if((retPath = read_string(my_file->path, MAX_LEN)) == FAIL) 
    			error();
     
    		if((my_file->ptr = fopen(my_file->path, "r")) != NULL) 
    			break;
     
    		else 
    			printf("\n Mauvaise saisie : le fichier n'existe pas, recommencez !\n");
    	}
     
    	printf("\n Contenu du fichier : \n\n");
     
    	if(fgetc(my_file->ptr) != EOF) 	
    	{
    		fseek(my_file->ptr, 0, SEEK_SET);
     
    		while(fgets(str, MAX_LEN, my_file->ptr) != NULL) 
            		printf("%s", str);
    	}
     
    	else printf(" Désolé, le fichier est vide !");
     
    	fclose(my_file->ptr);
    	free(my_file->path);
    }
     
    void createFile(File* my_file)
    {
    	int retPath;
     
    	my_file->path = malloc(MAX_LEN * sizeof(my_file->path));
     
    	while(1)
    	{	
    		printf("\n\n Entrez le chemin du fichier que vous souhaitez créer : ");
    		if((retPath = read_string(my_file->path, MAX_LEN)) == FAIL) 
    			error();
     
    		if((my_file->ptr = fopen(my_file->path, "w")) != NULL) 
    			break;
     
    		else 	
    			printf("\n Mauvaise saisie : le chemin du fichier n'existe pas, recommencez !\n");
    	}
     
    	printf("\n Le fichier a bien été créé !");
     
    	fclose(my_file->ptr);
    	free(my_file->path);
    }
     
    void writeFile(File* my_file)
    {
    	int retPath, c;
    	char str[MAX_LEN * 5] = "";
     
    	my_file->path = malloc(MAX_LEN * sizeof(my_file->path));
     
    	while(1)
    	{	
    		printf("\n\n Entrez le chemin du fichier que vous souhaitez lire : ");
    		if((retPath = read_string(my_file->path, MAX_LEN)) == FAIL) 
    			error();
     
    		if((my_file->ptr = fopen(my_file->path, "w")) != NULL) 
    			break;
     
    		else 
    			printf("\n Mauvaise saisie : le fichier n'existe pas, recommencez !\n");
    	}
     
    	printf("\n Saisissez le texte à mettre dans le fichier (pour fermer, tapez \"close_file\") : \n\n");
     
    	while(c = read_string(str, sizeof(str)))
        	{
            	if(strstr(str, "close_file")) 
    			break;
     
            	fputs(str, my_file->ptr);
        	}
     
    	if(c == FAIL) 
    		error();
     
    	fclose(my_file->ptr);
    	free(my_file->path);
    }
     
    void clean(void)
    {
        	int c = 0;
        	while ((c = getchar()) != '\n' && c != EOF);
    }
     
    int read_string(char *str, const int length)
    {
        	char *ptr = NULL;
     
        	if(fgets(str, length, stdin) != NULL)
        	{
            	ptr = strchr(str, '\n');
     
            	if(ptr != NULL) 
    			*ptr = '\0';
     
            	else 
    			clean();
     
            	return SUCCESS;
        	}
     
        	else
        	{
            	clean();
     
            	return FAIL;
        	}
    }
     
    long read_long(long** ret)
    {
        	char str[MAX_LEN] = {0}; 
     
        	if(read_string(str, 100)) 
    	{
    		**ret = strtol(str, NULL, BASE);
    		return SUCCESS;
    	}
     
        	else 
    		return FAIL;
    }
     
     
    void error(void)
    {
    	fprintf(stderr, "Erreur fatale lors de la saisie");
    	exit(EXIT_FAILURE);
    }
    Comme vous pouvez le voir, le code est (hélas) assez loin d'être parfait, et j'aimerais avoir vos critiques et vos améliorations à propos de celui-ci.

    Merci d'avance,
    Lucas-84.

  2. #2
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    déjà une petite factorisation de la saisie d'un nom de fichier:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    	while(1)
    	{	
    		printf("\n\n Entrez le chemin du fichier que vous souhaitez lire : ");
    		if((retPath = read_string(my_file->path, MAX_LEN)) == FAIL) 
    			error();
     
    		if((my_file->ptr = fopen(my_file->path, "w")) != NULL) 
    			break;
     
    		else 
    			printf("\n Mauvaise saisie : le fichier n'existe pas, recommencez !\n");
    	}
    qui est 2 fois dans le code..

  3. #3
    Membre expérimenté Avatar de brachior
    Homme Profil pro
    Doctorant
    Inscrit en
    Mai 2011
    Messages
    190
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Doctorant
    Secteur : Enseignement

    Informations forums :
    Inscription : Mai 2011
    Messages : 190
    Par défaut
    Pourquoi prendre en paramètre un double étoile ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    long read_long(long*);
    Ça suffit amplement ^^

    Par contre,
    Quel est l'intérêt de transmettre une structure si c'est pour l'allouer et la libérer dans la fonction ?
    C'est à se demander l'intérêt du pointeur dans la structure ^^

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    my_file->path = malloc(MAX_LEN * sizeof(my_file->path));
    /* [...] */
    free(my_file->path);
    De plus, si le tableau path à toujours la longueur constante du define MAX_LEN,
    Pourquoi ne pas laisser l'allocation statique ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    typedef struct File
    {
        FILE* ptr;
        char[MAX_LEN] path;
    } File;
    Ta fonction read_string remplace les retour chariot par des NULL.
    C'est pratique pour ta récupération de nombre, mais pour l'écriture dans un fichier,
    Ça veut dire qu'on ne peut pas revenir à la ligne =/

    Tes appels à error ne libèrent pas la mémoire.
    Bon certes, le programme quittant c'est l'OS qui se chargera de la libération ...
    Mais c'est bien parce que tes structures sont simples et qu'il est plutôt intelligent ...
    Parce que ne pas fermer un fichier, normalement c'est un coup à planter ce fichier ...

    Manque une fonction de libération de ta structure ^^

    Sinon, l'idée est sympa et fonctionne plutôt bien ^^
    Reste plus qu'à intégrer readline et les options en ligne de commandes

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    36
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 36
    Par défaut
    Merci beaucoup pour vos réponses !
    Je vais les prendre en compte, et je vous donne des nouvelles dès que cela est fait.

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2010
    Messages
    36
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 36
    Par défaut
    Voilà, j'ai corrigé quasiment toutes les erreurs indiquées.
    @souviron34, j'ai créé une nouvelle fonction :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void keyed_file(File* my_file, const char* mode)
    Elle permet la saisie d'un nom de fichier, et remplace ainsi les trois occurrences du code cité :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    void keyed_file(File* my_file, const char* mode)
    {
    	int retPath;
     
    	while(1)
    	{	
    		printf("\n\n Entrez le chemin du fichier concerné : ");
    		if((retPath = read_string(my_file->path, MAX_LEN)) == FAIL) 
    			error();
     
    		if((my_file->ptr = fopen(my_file->path, mode)) != NULL) 
    			break;
     
    		else 
    			printf("\n Mauvaise saisie : le fichier n'existe pas, recommencez !\n");
    	}
    }
    Le deuxième paramètre mode est envoyé directement par les fonctions de manipulations de fichiers (create_file, write_file, read_file). Il permet de spécifier le mode d'ouverture du fichier concerné.

    @brachior, merci pour ce long message.
    La plupart des erreurs notées ont été corrigées.
    J'ai supprimé les allocations dynamiques grâce à l'idée de l'allocation statique.
    Pour la saisie dans les fichiers, j'ai utilisé directement la fonction fgets.
    A la suite de la remarque sur la fonction error, pleine de bon sens (), j'ai modifié en créant une fonction free_struct, avant de me rendre compte qu'à priori cette fonction était appelée avant l'ouverture des fichiers. Je demande tout de même une confirmation.

    En résumé, voici mon nouveau code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    #define MAX_LEN 	1000 	/* Taille de chaîne maximale */
    #define BASE		10	/* Base décimale */
     
     
    #define FAIL		0	
    #define SUCCESS		1 	/* Constantes pour les retours de fonction */
     
    typedef struct File
    {
        FILE* ptr;
        char path[MAX_LEN];
    } File;
     
    int menu(long*);
    void read_file(File*);
    void create_file(File*);
    void write_file(File*);
    void keyed_file(File*, const char*);
     
    void clean(void);
    int read_string(char*, const int);
    long read_long(long*);
    void error(void);
     
    int main(void)
    {
    	long ret, retMenu;		
    	File my_file;
     
    	printf("\n\n          zReader - Manipulez vos fichiers");
     
    	do
    	{
    		if((ret = menu(&retMenu)) == FAIL) 
    			error();
     
    		if(retMenu == 1) 
    			read_file(&my_file);
     
    		else if(retMenu == 2) 
    			create_file(&my_file);
     
    		else if(retMenu == 3) 
    			write_file(&my_file);
     
    		else if(retMenu == 4) 
    			break;
     
    		else 
    			printf("\n Mauvaise saisie, recommencez !\n\n");
     
    	} while(1);
     
    	return EXIT_SUCCESS;
    }
     
    int menu(long* ret)
    {
    	printf( "\n\n\n   MENU\n"
    		" 1 - Lire un fichier\n"
    		" 2 - Créer un fichier\n"
    		" 3 - Ecrire dans un fichier\n"
    		" 4 - Quitter le programme\n\n"	
    		" Votre choix ? ");
    	if((read_long(ret)) == FAIL)
    		return FAIL;
     
    	else
    		return SUCCESS;
    }
     
    void read_file(File* my_file)
    {
    	char str[MAX_LEN] = "";
     
    	keyed_file(my_file, "r");
     
    	printf("\n Contenu du fichier : \n\n");
     
    	if(fgetc(my_file->ptr) != EOF) 	
    	{
    		fseek(my_file->ptr, 0, SEEK_SET);
     
    		while(fgets(str, sizeof(str), my_file->ptr) != NULL) 
            		printf("%s", str);
    	}
     
    	else 
    		printf(" Désolé, le fichier est vide !");
     
    	fclose(my_file->ptr);
    }
     
    void create_file(File* my_file)
    {
    	keyed_file(my_file, "w");
     
    	printf("\n Le fichier a bien été créé !");
     
    	fclose(my_file->ptr);
    }
     
    void write_file(File* my_file)
    {
    	char str[MAX_LEN * 5] = "";
     
    	keyed_file(my_file, "w");
     
    	printf("\n Saisissez le texte à mettre dans le fichier (pour fermer, tapez \"close_file\") : \n\n");
     
    	while(fgets(str, sizeof(str), stdin) != NULL)
        	{
            	if (strstr(str,"close_file"))
                		break;
     
            	fputs(str, my_file->ptr);
        	}
     
    	fclose(my_file->ptr);
    }
     
    void keyed_file(File* my_file, const char* mode)
    {
    	int retPath;
     
    	while(1)
    	{	
    		printf("\n\n Entrez le chemin du fichier concerné : ");
    		if((retPath = read_string(my_file->path, MAX_LEN)) == FAIL) 
    			error();
     
    		if((my_file->ptr = fopen(my_file->path, mode)) != NULL) 
    			break;
     
    		else 
    			printf("\n Mauvaise saisie : le fichier n'existe pas, recommencez !\n");
    	}
    }
     
    void clean(void)
    {
        	int c = 0;
        	while ((c = getchar()) != '\n' && c != EOF);
    }
     
    int read_string(char *str, const int length)
    {
        	char *ptr = NULL;
     
        	if(fgets(str, length, stdin) != NULL)
        	{
            	ptr = strchr(str, '\n');
     
            	if(ptr != NULL) 
    			*ptr = '\0';
     
            	else 
    			clean();
     
            	return SUCCESS;
        	}
     
        	else
        	{
            	clean();
     
            	return FAIL;
        	}
    }
     
    long read_long(long* ret)
    {
        	char str[MAX_LEN] = {0}; 
     
        	if(read_string(str, 100)) 
    	{
    		*ret = strtol(str, NULL, BASE);
    		return SUCCESS;
    	}
     
        	else 
    		return FAIL;
    }
     
     
    void error(void)
    {
    	fprintf(stderr, "Erreur fatale lors de la saisie");
    	exit(EXIT_FAILURE);
    }
    Pour les options en ligne de commande et readline, je verrai un peu plus tard...

  6. #6
    Membre expérimenté Avatar de brachior
    Homme Profil pro
    Doctorant
    Inscrit en
    Mai 2011
    Messages
    190
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Doctorant
    Secteur : Enseignement

    Informations forums :
    Inscription : Mai 2011
    Messages : 190
    Par défaut
    En fait, je ne comprend pas l'intérêt de ta structure.
    Enfin, je ne comprends pas pourquoi les fonctions l'initialisent et la libèrent ...
    C'est pas leur rôle normalement Oo

    Enfin, peut être que je n'arrive pas a voir l'utilisation globale que tu veux en faire ^^
    Mais dans ton code actuel, je ne comprends pas trop =/

Discussions similaires

  1. pb avec un programme de manipulation des fichiers
    Par El Mou dans le forum Débuter
    Réponses: 8
    Dernier message: 27/12/2011, 09h30
  2. Programmation pour manipuler des fichiers XML
    Par anolo40 dans le forum Débuter
    Réponses: 8
    Dernier message: 09/08/2011, 22h29
  3. Réponses: 5
    Dernier message: 18/10/2009, 13h42
  4. Réponses: 2
    Dernier message: 18/01/2003, 17h06

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo