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 :

Fonction invisible :(


Sujet :

C

  1. #1
    Membre du Club
    Homme Profil pro
    Etudiant
    Inscrit en
    Mai 2020
    Messages
    42
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 22
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Etudiant

    Informations forums :
    Inscription : Mai 2020
    Messages : 42
    Points : 42
    Points
    42
    Par défaut Fonction invisible :(
    Bonjour c'est encore moi ,
    J'ai un autre problème,
    J'ai créer 3 fonctions :
    - la premiere permet de compter le nombre de ligne dans un fichier
    - la 2eme permet d'afficher le contenue de mon fichier
    -le 3eme permet d'ajouter un contenue dans le fichier s'il n'est pas présent
    Voici mon 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
     #include <stdlib.h>
     #include <stdio.h>
     #include <string.h>
     
     
    int compte_ligne(FILE *fichier){
     
    	int count = 0;
    	int nLignes = 0;
     
    	while((count=fgetc(fichier)) != EOF)
    	{
    		if(count=='\n'){
    			nLignes++;
            }    
    	}
        //nLignes = nLignes + 1;
        count = 1;
        fclose(fichier);
     
     
    	return nLignes;
    }
     
    void afficher_lieu (int nLignes) {
     
        FILE *fichier;
        char* chaine;
        int i=0;
     
        fichier = fopen("Fichier/Lieu.txt", "r"); //Ouvre le fichier que en read 
     
    /* A voir apres
        if (fichier == NULL ){ //Au cas ou il y aurait une erreur lors de l'ouverture du fichier
            fprintf(stderr, "Erreur ouverture fichier - Abandon\n"); 
    		return -1; // Return -1 pour erreur
        }
    */
     
        while(i < nLignes){
            fgets(chaine, 80, fichier); 
            printf("test : %s", chaine); 
            i = i + 1;
        }
        fclose(fichier); //Ferme le fichier
     
    }
     
    void afficher_participants (int nLignes) {
     
        FILE *fichier;
        char* chaine;
        int i=0;
     
        fichier = fopen("Fichier/Participant.txt", "r"); //Ouvre le fichier que en read 
     
    /* A voir apres
        if (fichier == NULL ){ //Au cas ou il y aurait une erreur lors de l'ouverture du fichier
            fprintf(stderr, "Erreur ouverture fichier - Abandon\n"); 
    		return -1; // Return -1 pour erreur
        }
    */
     
        while(i < nLignes){
            fgets(chaine, 80, fichier); 
            printf("\nParticipant : %s", chaine); 
            i = i + 1;
        }
     
        fclose(fichier); //Ferme le fichier
     
    }
     
    void ajouter_lieu (){
     
     
        FILE *fichier;
     
        char Lieu_Dans_Fichier[30], Lieu_entree[30];
        int trouve = 0;
        fichier = fopen("Fichier/test.txt", "r"); //Ouvre le fichier que en read 
     
    /* A voir apres
        if (fichier == NULL ){ //Au cas ou il y aurait une erreur lors de l'ouverture du fichier
            fprintf(stderr, "Erreur ouverture fichier - Abandon\n"); 
    		return -1; // Return -1 pour erreur
        }
    */
     
        printf("Lieu a ajouter : ");  //Pour savoir le mot cherche
        scanf("%s",Lieu_entree);
     
        while (fgets(Lieu_Dans_Fichier,30,fichier) != NULL) // Le 30 correspond a max 30 caracteres
        {   
          if (strstr(Lieu_Dans_Fichier, Lieu_entree) != NULL){  // Si mot cherche == mot dans le fichier 
                trouve = 1;
            }
        }
        fclose(fichier); //Ferme le fichier
     
        fichier = fopen("Fichier/Lieu.txt", "a"); //Ouvre le fichier en mode écriture
     
        if (trouve == 1){
            printf("Le lieu existe deja :)");
        }
        else{
            printf("OK, Ajout du lieu");
            fprintf(fichier, "%s\n", Lieu_entree);  //Ecrit le mot recherche a la fin du fichier 
        }
        fclose(fichier); //Ferme le fichier
    }
     
    int main () {
     
        FILE *fichier_lieu = fopen("Fichier/Lieu.txt", "r");
        FILE *fichier_participant = fopen("Fichier/Participant.txt", "r");
       afficher_participants(compte_ligne(fichier_participant));
        afficher_lieu(compte_ligne(fichier_lieu));
        ajouter_lieu();
     
     
        fclose(fichier_lieu); fclose(fichier_participant);
        return 0;
     
    }
    Le problème est : Quand j'exécute le programme la fonction ajouter_lieu() n'est pas exécuter. Par contre quand je retire l'appel : afficher_lieu(compte_ligne(fichier)); , la fonction ajouter_lieu() est exécutée. Je ne comprends vraiment pas pourquoi ...
    Si vous pouvez m'aider
    @+
    Bapth

  2. #2
    Membre du Club
    Homme Profil pro
    Etudiant
    Inscrit en
    Mai 2020
    Messages
    42
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 22
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Etudiant

    Informations forums :
    Inscription : Mai 2020
    Messages : 42
    Points : 42
    Points
    42
    Par défaut
    J'ai enfin résolu mon problème !!
    J'ai juste changé à la ligne 28 et 52 char *chaine; par char chaine[80];
    Je n'ai pas vraiment compris pourquoi ce changement rendait mon programme fonctionnel. (Peut-être on passe d'une taille dynamique à une taille fixe ...)
    Je vous mets quand même 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
     #include <stdlib.h>
     #include <stdio.h>
     #include <string.h>
     
     
    int compte_ligne(FILE *fichier){
     
    	int count = 0;
    	int nLignes = 0;
     
    	while((count=fgetc(fichier)) != EOF)
    	{
    		if(count=='\n'){
    			nLignes++;
            }    
    	}
        //nLignes = nLignes + 1;
        count = 1;
        fclose(fichier);
     
     
    	return nLignes;
    }
     
    void afficher_lieu (int nLignes) {
     
        FILE *fichier;
        char chaine[80];
        int i=0;
     
        fichier = fopen("Fichier/Lieu.txt", "r"); //Ouvre le fichier que en read 
     
    /* A voir apres
        if (fichier == NULL ){ //Au cas ou il y aurait une erreur lors de l'ouverture du fichier
            fprintf(stderr, "Erreur ouverture fichier - Abandon\n"); 
    		return -1; // Return -1 pour erreur
        }
    */
     
        while(i < nLignes){
            fgets(chaine, 80, fichier); 
            printf("test : %s", chaine); 
            i = i + 1;
        }
        fclose(fichier); //Ferme le fichier
     
    }
     
    void afficher_participants (int nLignes) {
     
        FILE *fichier;
        char chaine[80];
        int i=0;
     
        fichier = fopen("Fichier/Participant.txt", "r"); //Ouvre le fichier que en read 
     
    /* A voir apres
        if (fichier == NULL ){ //Au cas ou il y aurait une erreur lors de l'ouverture du fichier
            fprintf(stderr, "Erreur ouverture fichier - Abandon\n"); 
    		return -1; // Return -1 pour erreur
        }
    */
     
        while(i < nLignes){
            fgets(chaine, 80, fichier); 
            printf("\nParticipant : %s", chaine); 
            i = i + 1;
        }
     
        fclose(fichier); //Ferme le fichier
     
    }
     
    void ajouter_lieu (){
     
     
        FILE *fichier;
     
        char Lieu_Dans_Fichier[30], Lieu_entree[30];
        int trouve = 0;
        fichier = fopen("Fichier/test.txt", "r"); //Ouvre le fichier que en read 
     
    /* A voir apres
        if (fichier == NULL ){ //Au cas ou il y aurait une erreur lors de l'ouverture du fichier
            fprintf(stderr, "Erreur ouverture fichier - Abandon\n"); 
    		return -1; // Return -1 pour erreur
        }
    */
     
        printf("Lieu a ajouter : ");  //Pour savoir le mot cherche
        scanf("%s",Lieu_entree);
     
        while (fgets(Lieu_Dans_Fichier,30,fichier) != NULL) // Le 30 correspond a max 30 caracteres
        {   
          if (strstr(Lieu_Dans_Fichier, Lieu_entree) != NULL){  // Si mot cherche == mot dans le fichier 
                trouve = 1;
            }
        }
        fclose(fichier); //Ferme le fichier
     
        fichier = fopen("Fichier/Lieu.txt", "a"); //Ouvre le fichier en mode écriture
     
        if (trouve == 1){
            printf("Le lieu existe deja :)");
        }
        else{
            printf("OK, Ajout du lieu");
            fprintf(fichier, "%s\n", Lieu_entree);  //Ecrit le mot recherche a la fin du fichier 
        }
        fclose(fichier); //Ferme le fichier
    }
     
    int main () {
     
    //Ouverture fichiers //
    	FILE *fichier_lieu = fopen("Fichier/Lieu.txt", "r");
        FILE *fichier_participant = fopen("Fichier/Participant.txt", "r");
     
       // afficher_lieu(compte_ligne(fichier));
        ajouter_lieu();
     
        afficher_lieu(compte_ligne(fichier_lieu));
        afficher_participants(compte_ligne(fichier_participant));
     
     
    //Fermeture fichiers //
        fclose(fichier_lieu); fclose(fichier_participant);
        return 0;
    }
    Voila
    @+
    Bapth

  3. #3
    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 bapth Voir le message
    Je n'ai pas vraiment compris pourquoi ce changement rendait mon programme fonctionnel
    Pourtant la réponse est simple : ton programme plantait

    Tu utilisais des tableaux mais ils n'étaient pas initialisés.

    La solution la + simple est 1 tableau constant, comme tu l'as fait : char chaine[80];.

    Sinon, il faut l'allouer, l'initialiser si nécessaire et le désallouer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
        char* chaine;
     
        chaine = malloc(80 /* * sizeof(char) */);
     
        if (chaine != NULL) {
            memset(chaine, '\0', 80); // if needed
     
    //      ...
     
            free(chaine);
            chaine = NULL;
        }

  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 bapth Voir le message
    Bonjour c'est encore moi ,
    Hey, salut

    Citation Envoyé par bapth Voir le message
    J'ai un autre problème,
    A mon avis ce n'est pas le dernier. Quand je débutais en prog C, je faisais tellement chier mon collègue à lui poser plein de questions qu'il avait découpé un carton de jus de fruit "Joker" et m'avait donné l'étiquette. Et je n'avais eu ensuite le droit qu'à un "Joker" par jour. Si je lui posais une question, je lui donnais le carton qu'il me rendait le lendemain.

    Citation Envoyé par bapth Voir le message
    J'ai juste changé à la ligne 28 et 52 char *chaine; par char chaine[80];
    Je n'ai pas vraiment compris pourquoi ce changement rendait mon programme fonctionnel. (Peut-être on passe d'une taille dynamique à une taille fixe ...)
    C'est un peu de ça. Tu as au départ une taille effectivement dynamique mais encore non allouée (aucun espace de prévu pour y stocker quoi que ce soit). Tu as effectivement une taille qui peut-être dynamique mais qui est pour l'instant nulle. Et quand tu tentes d'y mettre des caractères (fgets()) => plantage (en réalité c'est plus subtil car c'est un comportement indéterminé donc imprévisible donc on ne peut même pas prédire qu'il y aura plantage).

    Prenons du départ: quand tu déclares un pointeur char *chaine (ou n'importe quel truc *chaine), tu ne déclares qu'un pointeur inutile. Il te faut ensuite positionner ce pointeur, c'est à dire lui donner une adresse. Pour simplifier, tu es obligé d'écrire à un moment donné chaine=quelque_chose et si tu n'écris pas cette instruction, alors tu es certain que ton programme est incorrect. C'est une certitude absolue. Ton travail est de trouver ce "quelque_chose" à mettre (mais en général ce n'est pas une difficulté car le codeur qui a l'habitude sait pourquoi il crée son pointeur et donc sait ce qu'il va y mettre).
    Si tu n'écris pas ce chaine=quelque_chose, tu n'as fait que créer en ram un pointeur (une variable) contenant une valeur (toute variable contient toujours une valeur) mais valeur indéterminée. En effet, pourquoi le compilateur s'embêterait-il à y mettre quoi que ce soit vu que tu es censé toi y mettre quelque chose de valide => un des prédicats de base du C est que pour être le plus rapide possible, il ne fait que ce qui est écrit et à toi de t'assurer que tu fais ce qu'il faut pour que ça ne soit pas invalidant du point de vue logique car il ne vérifie rien.
    Donc tu as en main un pointeur (adresse mémoire) contenant n'importe quelle valeur (n'importe quelle adresse) et là, à cette adresse, tu vas y stocker (fgets()) de la data ??? As-tu le droit d'écrire à cette adresse ? Cette adresse n'est-elle pas celle d'une autre variable ?? Fait-elle seulement partie de l'espace mémoire de ton programme ??? C'est ce qu'on nomme donc un UB (Undefined Behaviour = comportement indéterminé). Ton programme peut marcher, peut ne pas marcher, peut marcher les jours pairs et planter les jours impair, peut marcher 5 ans puis tu rajoutes un compteur et ça plante (et tu te creuses le citron à essayer de comprendre en quoi ton compteur fait planter le truc), peut te rebooter ta machine ou reformater ton disque dur (nan je déconne, il y a quand-même la barrière de l'OS qui protège mais c'est pour illustrer).

    foetus, lui, utilise aussi le pointeur mais ensuite demande au C de réserver une zone mémoire (malloc=memory allocation) et récupère cette zone alloué (chaine=malloc(...)). Il a respecté la règle du chaine=quelque_chose, son programme est correct (ce qui ne veut pas dire qu'il ne faillira pas ailleurs, un programme en C c'est une attention de tous les instants). Par exemple il faudra veiller à ne pas dépasser et surtout il faudra ensuite penser à libérer la zone free(chaine) car le C ne le fera pas automatiquement. Bon en réalité les OS modernes le font automatiquement quand le programme se termine mais déjà ce n'a pas toujours été le cas (XP par exemple ne le faisait pas) et quoi qu'il en soit, en C vaut mieux toujours faire les choses soi-même, au-moins on est sûr qu'elles sont faites, plutôt que de compter sur l'esclave de service sans être certain qu'il sera au rendez-vous (il y a des programmes en C qui tournent sur des trucs exotiques, comme par exemple le contrôle de pilotage automatique, et bon si tu as envie de voler dans un avion où le programmeur a pensé "je m'en fouts de libérer de la RAM dont je ne me sers plus, le truc doit probablement le faire automatiquement"...)

    Il y a l'autre solution du tableau réservé à la compilation, le fameux char chaine[80], ce que tu as fait. Là tu définis une zone de 80 caractères qui t'es immédiatement réservée. Tu as la garantie que rien ne pourra la pourrir ("rien" dans le cas d'un programme bien écrit évidemment, car si tu provoques un UB, il peut alors venir justement pourrir ta zone) et tu peux y mettre ce que tu veux (dans la limite de 80 caractères, sans oublier le '\0' si ce que tu y mets doit être une string). Pas de souci de réservation/libération, pas de souci de pointeur inconnu, bref la solution la plus simple chaque fois que tu devras prévoir une zone de taille fixe. A toi simplement de veiller à ne pas dépasser car le C n'y veillera pas à ta place.
    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 du Club
    Homme Profil pro
    Etudiant
    Inscrit en
    Mai 2020
    Messages
    42
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 22
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Etudiant

    Informations forums :
    Inscription : Mai 2020
    Messages : 42
    Points : 42
    Points
    42
    Par défaut
    Merci pour toutes tes indications.
    Si je comprends bien, il faut être constamment vigilent car une fonction créer peut se mettre à bugger lors de l'ajout de la dernière ligne de notre programme . Il faut donc être tout le temps vigilent lors de la création de nos variables
    @+ et merci encore !
    Bapth

  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 bapth Voir le message
    Il faut donc être tout le temps vigilent lors de la création de nos variables
    Et aussi dans leur utilisation !!!
    Une erreur facile à faire
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    int n[10];
    for (i=0; i <= 10; i++) n[i]=0;		// Dépassement de capacité, un tableau de 10 va de 0 à 9 => écrire "i < 10" !!!

    Et c'est encore pire avec les strings (sur un char tab[10], tu ne peux aller que de 0 inclus à 8 inclus car il faut au minimum tab[9] de libre pour y stocker le '\0'). Il existe toutefois pour ça un consensus permettant de limiter les risques: rajouter systématiquement "+1" =>char tab[10 + 1] signifiant "ma chaine aura 10 caractères réels et j'ai bien pensé au '\0'" et si on veut boucler, on peut alors écrire for (i=0; i < 10; i++) ....
    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]

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

Discussions similaires

  1. [AC-2003] Bouton invisible dans sa fonction
    Par Jojo____ dans le forum IHM
    Réponses: 6
    Dernier message: 26/04/2012, 08h12
  2. rendre invisible un bout de code en fonction d une radio box
    Par florianjoy54 dans le forum Général JavaScript
    Réponses: 7
    Dernier message: 13/02/2011, 14h14
  3. [AC-2003] Rendre partie de form invisible en fonction case à option
    Par mouktar dans le forum IHM
    Réponses: 3
    Dernier message: 18/05/2009, 10h21
  4. Réponses: 3
    Dernier message: 09/02/2009, 15h01
  5. rendre invisible les partie d'une form en fonction de leur couleur?
    Par Jayceblaster dans le forum Windows Forms
    Réponses: 1
    Dernier message: 09/07/2007, 14h41

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