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 :

Créer ses fonctions


Sujet :

C

  1. #1
    Membre confirmé Avatar de nl.smart
    Homme Profil pro
    ouvrier
    Inscrit en
    Avril 2019
    Messages
    155
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : ouvrier
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2019
    Messages : 155
    Points : 534
    Points
    534
    Par défaut Créer ses fonctions
    Bonjour,

    Jusqu'à présent j'ai créé des programmes manipulant des chiffres pour en faire parfois des fonctions, maintenant j'en viens à créer des programmes manipulant des lettres.

    Dans l'exemple ci-dessous le code lit le texte contenu dans un fichier texte, comment créer une fonction à partir de ce 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
    #include <stdio.h>   // lecture du contenu d'un fichier texte avec une extension .txt
    #include <stdlib.h>  // ok linux et windows
    #include <time.h>    //
    #include <string.h>  //
     
    int main()
    {
        FILE *ptr_ouverture_fichier;
        char fichier_a_ouvrir[30];
        char texte;
     
        printf("\n Liste des fichiers .txt : \n");
     
        system ("dir *.txt"); // affiche les fichiers .txt se trouvant dans le dossier courant
     
        printf("\n Entre le nom du fichier que tu souhaites ouvrir : ");
        scanf("%s", fichier_a_ouvrir);
     
        ptr_ouverture_fichier = fopen (fichier_a_ouvrir, "r");
     
        if (ptr_ouverture_fichier == NULL)
        {
            printf(" Erreur lors de l'ouverture du fichier ! ");
            return EXIT_FAILURE;
        }
     
        printf("\n Le contenu du fichier %s est : \n", fichier_a_ouvrir);
        texte = fgetc(ptr_ouverture_fichier);
     
        while (texte != EOF)
            {
                printf ("%c", texte);
                texte = fgetc(ptr_ouverture_fichier);
            }
     
        fclose(ptr_ouverture_fichier);
     
        return EXIT_SUCCESS;
    }
    La première question que je me pose est, de quel type doit être le prototype de cette fonction ?

    Est-ce que le seul paramètre du prototype est bien le nom du fichier à ouvrir ? char fichier_a_ouvrir[30];

    Est-ce que la fonction renvoie une valeur? Je pense que non, la fonction ouvrira un fichier dont elle lira le contenu.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    type? ouvrir_fichier_texte(char fichier_a_ouvrir[30]);
    Merci à vous pour vos lumières.

  2. #2
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 684
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 684
    Points : 30 973
    Points
    30 973
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par nl.smart Voir le message
    Dans l'exemple ci-dessous le code lit le texte contenu dans un fichier texte, comment créer une fonction à partir de ce code ?
    Il faut penser "une fonction c'est un mini travail que je dois pouvoir réutililser plusiers fois si besoin". A ce titre, elle en doit pas "trop en faire" car ce sera alors trop ciblé pour "une action précise" et tu ne pourras pas la réutiliser si tu as un autre besoin "presque" pareil (exemple une fonction qui convertit un fichier en majuscules => tu ne pourras pas l'utiliser pour convertir une simple phrase saisie en majuscules ; alors que si tu fais une fonction qui convertit une simple string en majuscules tu pourras l'appeler pour un texte chargé depuis le clavier ou depuis un fichier ou depuis un flux réseau)
    Elle ne doit pas non plus être "trop limitée" car la plus value disparait (à quoi sert une fonction qui ouvre un fichier alors qu'il existe déjà fopen() qui le fait)

    Donc voilà. Là c'est un peu la "touche personnelle" qui y fait...

    Citation Envoyé par nl.smart Voir le message
    La première question que je me pose est, de quel type doit être le prototype de cette fonction ?
    De quoi a-t-elle besoin pour travailler ? Et que renvoie-t-elle ?

    Citation Envoyé par nl.smart Voir le message
    Est-ce que le seul paramètre du prototype est bien le nom du fichier à ouvrir ? char fichier_a_ouvrir[30];
    A-t-elle besoin d'autre chose ? Ne veux-tu pas lui donner aussi le mode d'ouverture ("r", "w", "a", ...) pour pouvoir éventuellement l'utiliser dans d'autres circonstances futures que tu ne connais pas encore ?
    Accessoirement il vaut mieux écrire ici char *fichier_a_ouvrir. En effet, une string étant terminée par un '\0', tu n'as pas besoin d'y copier les 30 caractères du nom (30 copies de 1 octet). La fonction peut se contenter de l'adresse de cette string (une copie de 4 octets) et de là elle pourra lire la zone jusqu'à trouver le '\0' => elle aura alors tout le nom

    Citation Envoyé par nl.smart Voir le message
    Est-ce que la fonction renvoie une valeur? Je pense que non, la fonction ouvrira un fichier dont elle lira le contenu.
    Et que fera-t-elle de ce contenu ? Et même si elle traite le contenu, ne veux-tu pas quand-même lui faire renvoyer un truc signifiant "ok ça c'est bien passé" ou "j'ai eu un souci" ce qui permettrait à l'appelant de gérer en conséquence ?

    Voillà, plein de sujets de réflexion à se poser quand on veut créer une fonction...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  3. #3
    Membre confirmé Avatar de nl.smart
    Homme Profil pro
    ouvrier
    Inscrit en
    Avril 2019
    Messages
    155
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : ouvrier
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2019
    Messages : 155
    Points : 534
    Points
    534
    Par défaut
    Merci pour toutes vos explications, je prends soin de conserver les échanges, il arrive de m'y référer ultérieurement.

    La fonction souhaitée est créée, elle soulagera le main.

    Merci par avance pour vos remarques concernant le code ci-dessous.

    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
     
    #include <stdio.h>   // lecture du contenu d'un fichier texte avec une extension .txt
    #include <stdlib.h>  // ok linux et windows
    #include <time.h>    //
    #include <string.h>  //
     
    FILE *ouvrir_fichier_texte(void);
     
    int main()
    {
     
        ouvrir_fichier_texte();
     
        return EXIT_SUCCESS;
    }
     
    FILE *ouvrir_fichier_texte(void)
    {
        FILE *ptr_ouverture_fichier = NULL;
        char fichier_a_ouvrir[30];
        char texte;
     
        printf("\n Liste des fichiers .txt : \n");
     
        system ("dir *.txt"); // affiche les fichiers .txt se trouvant dans le dossier courant
     
        printf("\n Entre le nom du fichier que tu souhaites ouvrir : ");
        scanf("%s", fichier_a_ouvrir);
     
        ptr_ouverture_fichier = fopen (fichier_a_ouvrir, "r");
     
        if (ptr_ouverture_fichier == NULL)
        {
            printf(" Erreur lors de l'ouverture du fichier ! ");
            exit(0);
        }
     
        printf("\n Le contenu du fichier %s est : \n", fichier_a_ouvrir);
        texte = fgetc(ptr_ouverture_fichier);
     
        while (texte != EOF)
            {
                printf ("%c", texte);
                texte = fgetc(ptr_ouverture_fichier);
            }
     
        fclose(ptr_ouverture_fichier);
     
        return EXIT_SUCCESS;
    }

  4. #4
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 684
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 684
    Points : 30 973
    Points
    30 973
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par nl.smart Voir le message
    Merci par avance pour vos remarques concernant le code ci-dessous.
    Ben voilà. ta fonction fait tout ce qu'il ne faut pas faire.
    1. elle se charge de demander le nom du fichier à ouvrir => tu ne peux plus t'en servir en automatique.
      Pour essayer de trouver comment bien séparer les actions des différentes fonctions, tu peux penser "MVC". Le "M" c'est le Modèle, c'est l'organisation des données et les méthodes de récupération et/ou de sauvegarde de ces données. Le "V" c'est la Vue, c'est tout ce qui concerne l'affichage des informations ou les questions posées à l'utilisateur. Le "C" c'est le Controleur, c'est tout ce qui concerne le traitement des datas et le calcul de nouvelles valeurs en fonctions des valeurs connues. C'est une façon de programmer qui permet un découpage "propre" et qui permet d'attribuer les actions à différentes technos (aujourd'hui le modèle c'est du fichier texte mais demain c'est de la bdd, aujourd'hui la vue c'est du printf() mais demain ce sera une IHM, etc.
    2. elle quitte le programme si elle n'arrive pas à ouvrir le fichier => on ne fait jamais quitter un programme. Le programme commence au main() et finit au main(). Si la fonction ne peut pas faire son travail, elle retourne une valeur spéciale et l'appelant gère en conséquence


    Soulager le main c'est louable. Mais si tu te contentes de remplacer "main()" par "ouvrir_fichier()" et que tu rajoutes juste un int main() {ouvrir_fichier()} la plus-value reste très mitigée...

    Citation Envoyé par nl.smart Voir le message
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    texte = fgetc(ptr_ouverture_fichier);
    while (texte != EOF)
    	{
    		printf ("%c", texte);
    		texte = fgetc(ptr_ouverture_fichier);
    	}
    Attention à l'indentation. Tu n'as pas besoin de décaler les accolades (tu gagnes un niveau => quand tu écriras à droite de l'écran tu comprendras). Et surtout tu peux éviter cette répétition de lecture si typiquement scolaire (j'ai l'impression de lire du Warnier)...

    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    while ((texte=fgetc(ptr_ouverture_fichier)) != EOF) {
    	printf ("%c", texte);
    }

    Citation Envoyé par nl.smart Voir le message
    char texte;
    int texte; !!!
    Ce qui permet à ton programme de ne pas confondre EOF (-1 ou 0xFFFF) avec le caractère 'ÿ' (code ascii 255 ou 0x00FF)...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  5. #5
    Membre confirmé Avatar de nl.smart
    Homme Profil pro
    ouvrier
    Inscrit en
    Avril 2019
    Messages
    155
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : ouvrier
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2019
    Messages : 155
    Points : 534
    Points
    534
    Par défaut
    #include "Politesse.h"

    Merci pour votre dernier poste détaillé.

    Mon code ci-dessous tient compte de vos remarques :
    _ la fonction ne se charge plus de demander le nom du fichier à ouvrir, ça se passe dans le main
    _ ai bien lu la façon de procéder MVC
    _ la fonction ne quitte plus le programme si le fichier ne s'ouvre pas, une boucle relance le programme, de plus le fichier ainsi que la ligne incriminés seront rapportés
    _ il y en a peu dans le main, en effet, cette fonction est un exemple simple pour la pédagogie et aussi simplifier les échanges

    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
    #include <stdio.h>   // créer un fichier texte avec une extension .txt
    #include <stdlib.h>  // ok linux et windows
    #include <time.h>    // 2019.11.17
    #include <string.h>  //
    
    FILE *ouvrir_fichier_texte(char fichier_a_ouvrir[]);
    
    int main()
    {
        int relancer = 1;
    
        while(relancer == 1) // boucle permettant de relancer le programme 
        {
        char fichier_a_ouvrir[30];
    
        printf("\n Liste des fichiers .txt du répertoire courant : \n");
    
        system ("dir *.txt"); // affiche les fichiers .txt se trouvant dans le dossier courant
    
        printf("\n Entre le nom du fichier que tu souhaites ouvrir : ");
        scanf("%s", fichier_a_ouvrir);
    
        ouvrir_fichier_texte(fichier_a_ouvrir);
    
        } // while relancer
    }
    
    FILE *ouvrir_fichier_texte(char fichier_a_ouvrir[])
    {
        FILE *ptr_ouverture_fichier = NULL;
        int texte = 0;
    
        ptr_ouverture_fichier = fopen (fichier_a_ouvrir, "r");
    
        if (ptr_ouverture_fichier == NULL)
        {
            printf("\n Erreur lors de l'ouverture du fichier %s ligne %d \n", __FILE__, __LINE__);
    // si erreur, le code renverra le nom du fichier ainsi que de la ligne, puis relancera la boucle
            return 0;
        }
    
        printf("\n Le contenu du fichier %s est : \n", fichier_a_ouvrir);
        
        while ((texte=fgetc(ptr_ouverture_fichier)) != EOF) {
            printf ("%c", texte);
        }
    
        fclose(ptr_ouverture_fichier);
    
        return ptr_ouverture_fichier; // ainsi écrites, est-ce que ces 2 dernières lignes sont correctes ? 
    }
    Merci pour vos remarques et suggestions.

  6. #6
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 684
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 684
    Points : 30 973
    Points
    30 973
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par nl.smart Voir le message
    Mon code ci-dessous tient compte de vos remarques :
    C'est pas mal Il y a bien entendu quelques erreurs de débutant mais ça commence à avoir une allure plus professionnelle

    Les quelques imperfections
    • la fonction affiche un message d'erreur si souci => en MVC ce n'est pas son rôle. Si elle a un rôle de traitement, alors elle traite. L'affichage se fera dans les fonctions "Vue". D'autant plus que j'ai présenté le MVC comme quelque chose de triangulaire alors que c'est plutôt hiérarchique (la Vue appelant tantôt les fonctions du Modèle et tantôt les fonctions du Contrôle et se chargeant de superviser le tout par rapport à l'utilisateur).
    • la fonction retourne un pointeur et retourne 0 en cas d'échec. Même si c'est pareil, on a plus l'habitude de voir "NULL". C'est plutôt une question de conventions mais ça aide à la relecture
    • la fonction retourne un pointeur or l'appelant n'en a que faire (le fichier a été ouvert, lu et refermé). Là ça devient plutôt un souci de conception. Tant qu'à lui faire renvoyer un truc, autant lui faire renvoyer un truc potentiellement utile (le nombre d'octets lus par exemple)
    • les commentaires sur "stdio.h" et "stdlib.h" c'est pas encore trop ça. stdio (STanDard Input Output) concerne tout ce qui a trait aux IO (fichier, affichage). stdlib (STanDard LIBrairie) c'est un peu le "fourre-tout" de tout ce qu'on n'a pas pu mettre ailleurs. Il contiendra les fonctions d'allocations mémoire, génération de random, gestion des signaux de comm. string c'est tout ce qui concerne la manipulation de strings (compter, chercher, copier, comparer) et time contient les fonctions de manipulation des unités temporelles (Linux travaille en secondes tandis que nous lisons le temps découpé en hh:mm:ss)
    • attention à l'indentation => c'est vrai que je t'ai dit qu'il ne fallait pas décaler les accolades mais faut quand-même décaler les lignes des blocs pour bien les faire ressortir par rapport aux lignes du bloc du dessus
    • attention au noms trop long => à taper c'est galère (ça m'a gonflé dès la 3° ligne)

    Sinon c'est un truc qui a déjà pas mal de classe . Maintenant est-ce que tu veux ma version ?

    Citation Envoyé par nl.smart Voir le message
    _ il y en a peu dans le main, en effet, cette fonction est un exemple simple pour la pédagogie et aussi simplifier les échanges
    Bien évidemment
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  7. #7
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 629
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 629
    Points : 10 554
    Points
    10 554
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    la Vue appelant tantôt les fonctions du Modèle et tantôt les fonctions du Contrôle et se chargeant de superviser le tout par rapport à l'utilisateur
    Dans un vrai MVC, les entrées sont sur le contrôleur. C'est avec un MVP (model-view-presenter) que les entrées se font sur la vue (mais tu n'as plus de lien entre la vue et le modèle)

    La difficulté, c'est que tous les UIs (boutons, entrées, listes, ...) mélangent une vue et un contrôleur.

  8. #8
    Membre confirmé Avatar de nl.smart
    Homme Profil pro
    ouvrier
    Inscrit en
    Avril 2019
    Messages
    155
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : ouvrier
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2019
    Messages : 155
    Points : 534
    Points
    534
    Par défaut
    #include "Politesse.h"

    foetus, merci pour vos précisions apportées quant au mvc et la distinction à faire avec le mvp.

    sve@r, merci pour vos encouragements et les suggestions jointes.

    Le code ci-après tient compte de vos dernières remarques :
    _ si erreur lors de l'ouverture du fichier un message en informe l'utilisateur, possibilité d'en étoffer le contenu, création de logfile...
    _ NULL et non 0, ptr_ouverture_fichier étant un pointeur
    _ suppression des commentaires aux côtés des librairies, merci pour les explications jointes à ces dernières
    _ pour l'indentation j'ai réécrit le code en laissant faire l'ide et en continuant à "airer" le code ici et là, question de lisibilité
    _ pour ce qui est des noms de variables trop longs, écrits en anglais ils sont plus courts, les noms de variables devant rester compréhensibles de n'importe qui, comme les commentaires inclus dans le code

    Question :
    _ return EXIT_SUCCESS; est-ce correct à la fin de cette fonction ?

    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
    /* lecture du contenu d'un fichier texte avec une extension .txt
     * ok linux et windows
     * 2019.11.22
    */
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include <string.h>
     
    FILE *open_txt_file(char file_to_open[]);
     
    int main()
    {
        int reload = 1;
     
        while (reload == 1)
        {
            char file_to_open[30];
     
            printf("\n Liste des fichiers .txt du répertoire courant : \n");
     
            system("dir *.txt"); // affiche les fichiers .txt se trouvant dans le dossier courant
     
            printf("\n Entrez le nom du fichier que vous souhaitez ouvrir : ");
            scanf("%s", file_to_open);
     
            open_txt_file(file_to_open);
     
        } // while relancer
    }
     
    FILE *open_txt_file(char file_to_open[])
    {
        FILE *ptr_open_txt = NULL;
        int texte = 0;
     
        ptr_open_txt = fopen(file_to_open, "r");
     
        if (ptr_open_txt == NULL)
        {
            printf("\n!!! Une erreur est survenue lors de l'ouverture du fichier %s \n", file_to_open);
            return 0; // si erreur, le code relancera la boucle
        }
     
        printf("\n Le contenu du fichier %s est : \n", file_to_open);
     
        while ((texte=fgetc(ptr_open_txt)) != EOF) {
            printf("%c", texte);
        }
     
        fclose(ptr_open_txt);
     
        return EXIT_SUCCESS;
    }
    Dilemme cornélien, dois-je voir votre version du code ?
    Mon penchant va vers non, votre code n'aura plus grand chose à voir avec celui du débutant que je suis, j'ai encore du chemin à parcourir pour en arriver à celui que vous proposerez, donc autant que j'accomplisse encore ce bout de chemin en suivant vos idées et suggestions pour y parvenir.

    Merci pour vos remarques et suggestions.

  9. #9
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 684
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 684
    Points : 30 973
    Points
    30 973
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par nl.smart Voir le message
    Le code ci-après tient compte de vos dernières remarques :
    _ si erreur lors de l'ouverture du fichier un message en informe l'utilisateur, possibilité d'en étoffer le contenu, création de logfile...
    Ok. C'est pas forcément dans cette fonction que ça doit se faire mais c'est probablement plus pratique. Maintenant (nouvelle info), les librairies C offrent un canal dédié aux messaes d'erreur => stderr. Ce canal est à la base le même que celui des messages normaux (stdout) mais il peut si besoin être détourné par l'utilisateur du programme (si celui-ci désire par exemple logguer les erreurs ou autre truc de ce genre).
    De plus il existe une variable globale "errno" qui est mise à jour systématiquement chaque fois qu'une opération système n'a pas pu se faire. Cette variable est elle-même reliée à la fonction strerror() (déclarée dans "errno.h") qui retourne une chaine littérale explicative du souci rencontré.
    En associant les deux, le traitement d'ouverture fichier peut alors devenir
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
        if ((ptr_open_txt=fopen(file_to_open, "r")) == NULL)
        {
            fprintf(stderr, "\n!!! Une erreur est survenue lors de l'ouverture du fichier %s - Message système %s\n", file_to_open, strerror(errno));
            return 0; // si erreur, le code relancera la boucle
        }
    (l'association de l'évaluation de fopen() et de l'affectation de son résultat dans if ((ptr_open_txt=fopen(file_to_open, "r")) == NULL] étant devenue assez classique pour être facilement comprise par tous les progs C)

    Citation Envoyé par nl.smart Voir le message
    _ NULL et non 0, ptr_ouverture_fichier étant un pointeur
    Euh je crois qu'il y a incompréhension. Le NULL c'est la valeur retournée par la fonction (valeur qui va avec le type "FILE *" de la fonction et non le type "FILE * de fopen()). Or elle continue à retourner 0 tout en étant de type "FILE *"...
    Cependant ce n'est plus vraiment une erreur car son type "FILE *" n'a plus rien à voir avec la nature des valeurs qu'elle retourne qui sont maintenant de simples états réussite/echec. Donc effectivement la fonction n'ayant plus lieu d'être "FILE *" mais "int" (détail à ne pas oublier quand on change la nature d'une fonction => vérifier si son type est toujours correct), peut alors retourner 0. Toutefois dans ce dernier cas, un autre consensus car le standard utilisé par les fonctions systèmes veut qu'une fonction de type "int" retourne alors -1 en cas de souci (les valeurs positives pouvant alors servir à de vrais informations comme par exemple un compteur ou autre)
    Donc (résumé) une fonction pointeur renverra NULL en cas d'échec et un pointeur valide en cas de réussite, une fonction int renverra -1 en cas d'échec et 0 ou autre en cas de réussite. Mais bien évidemment ça reste une convention.

    Citation Envoyé par nl.smart Voir le message
    _ pour ce qui est des noms de variables trop longs, écrits en anglais ils sont plus courts, les noms de variables devant rester compréhensibles de n'importe qui, comme les commentaires inclus dans le code
    Tu es plein de bonnes volonté. Avec l'habitude tu verras que "file_to_open" ça va te gonfler
    Le souci étant évidemment de trouver un juste milieu entre un nom explicite mais trop long ou simple mais trop court. Déjà il y a quelques astuces
    • un consensus implicite est généralement admis pour les pointeurs de fichiers => fp => fp=fopen(...) tout comme "i" et "j" pour les indices de boucles. Et si tu dois gérer plusieurs fichiers alors fp_fic1, fp_fic2 etc
    • l'emploi de la notation "CamelCase" peut aussi aider => fileToOpen au lieu de file_to_open (10 car au lieu de 12). Et l'habitude vient assez rapidement
    • ne pas avoir le même réflexe pour une courte fonction que pour une grosse fonction. Dans une courte fonction (donc rapidement lisible) tu peux simplifier les noms. Ainsi dans mon exemple n'utilisant que des courtes fonctions (la plus grosse fait 20 lignes en incluant les commentaires et les lignes vides d'aération), je nomme le nom de fichier "fic" et le pointeur "fp".

    Ensuite c'est le goût de chacun qui fait le reste.

    Citation Envoyé par nl.smart Voir le message
    _ return EXIT_SUCCESS; est-ce correct à la fin de cette fonction ?
    Malheureusement non. Cette macro est associée à la fonction exit() destinée à renvoyer un code à l'environnement ayant appelé le programme. Si tu travailles sous Unix/Linux, cet environnement c'est le shell. Or en shell la convention c'est qu'un programme ayant bien fonctionné retourne 0 (toute autre valeur permettant ainsi d'affiner les différentes causes d'un échec éventuel).
    Donc EXIT_SUCCESS vaut 0. Donc ta fonction retourne 0 en cas d'échec et 0 en cas de réussite...

    Citation Envoyé par nl.smart Voir le message
    dois-je voir votre version du code ? Dilemme cornélien...
    ...comme disait Chimène (de Gormas et non Badi). C'est comme tu le sens

    Citation Envoyé par nl.smart Voir le message
    votre code n'aura plus grand chose à voir avec celui du débutant que je suis
    Je l'ai quand-même écrite à destination des débutants
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  10. #10
    Membre confirmé Avatar de nl.smart
    Homme Profil pro
    ouvrier
    Inscrit en
    Avril 2019
    Messages
    155
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : ouvrier
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2019
    Messages : 155
    Points : 534
    Points
    534
    Par défaut
    #include "Politesse.h"

    Quel cour ! Formidable ! Un grand merci pour vos explications.

    _ strerror() : n'ayant pas déposé tout le code de ma fonction, je m'aperçois que ce que j'avais fait, et pas publié, est très proche de votre solution, bien entendu je prends note de l'idée :-)
    _ (ptr_open_txt == NULL) : effectivement, après lecture de vos explications il y avait une incompréhension de mon coté, respectons les conventions
    _ pour ce qui est du CamelCase, franchement, j'ai jamais accroché cette notation, camel_case me convient plus lors de la lecture du code, avec le temps et rien n'étant figé les choses peuvent encore changer

    Le poste passe en résolu.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 2
    Dernier message: 14/04/2015, 15h44
  2. [E-00][VBA] Créer une fonction et ses arguments
    Par tiyolx dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 05/07/2013, 09h43
  3. [MySQL] créer ses propres fonctions
    Par essono dans le forum PHP & Base de données
    Réponses: 3
    Dernier message: 18/11/2006, 15h09
  4. Programme permettant de créer ses propres paquets TCP/UDP
    Par mat087 dans le forum Développement
    Réponses: 6
    Dernier message: 21/05/2004, 21h42
  5. Créer des fonctions au sein d'un script
    Par mat.M dans le forum MS SQL Server
    Réponses: 3
    Dernier message: 31/03/2004, 15h25

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