Remplissage d'un tableau par des donne d'un fichier

Fermé
saskioutchiha_5955 Messages postés 4 Date d'inscription dimanche 22 mai 2022 Statut Membre Dernière intervention 25 mai 2022 - Modifié le 24 mai 2022 à 11:00
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 - 25 mai 2022 à 01:29
je veux remplire un tableau de structure par des donne d'un fichier mais cette partie de code générale ne sa marche pas et he ne sais pas pourquoi



le code de remplissage de tableau adher (de types pointeur )


le code :


adh=fopen("adher.txt","r");
if(adh == NULL){
    printf("fichier introuvable");
}
else{
if(!feof(adh)){
    
    while (fscanf(adh,"%d %s %s",&ad.codeadh,ad.nom,ad.prenom)==3)
    {
       adher=realloc(adher,b*sizeof(struct adherons));
        adherons1->codeadh = ad.codeadh;
        strcpy(adherons1->nom,ad.nom);
        strcpy(adherons1->prenom,ad.prenom);
        adherons1++;
        b++;
    }
}
fclose(adh);
}
A voir également:

2 réponses

[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083
Modifié le 23 mai 2022 à 12:58
Bonjour saskioutchiha_5955,

Bienvenue sur le forum. Tu as le droit de dire bonjour et d'utiliser d'autres types de formules de politesse, car tu écris à des êtres humains lorsque tu postes un message sur un forum :-)

Aussi, pour poster du code sur le forum, il faut cliquer sur le bouton code
<>▼ 
(cliquer sur la flèche pointant vers le bas, et choisir le langage c) pour poster le code entre les balises de code c. De cette façon il s'affiche correctement (comme ci-après).

Sur ta question.

En supposant que le fichier adher.txt contient des données comme ceci, avec des noms sans espaces et ne dépassant pas 254 char :

1889 Chaplin Charlie
1905 Garbo Greta
1892 Hardy Oliver
1895 Keaton Buster
1890 Laurel Stan


alors le code suivant ouvre correctement le fichier et affiche les données en question :

#include <stdio.h>
  
int main(void) {
        FILE * adh=fopen("adher.txt","r");
        if (adh == NULL){
                printf("fichier introuvable\n");
        } else{
                int code;
                char nom[255];
                char prenom[255];
                while (fscanf(adh,"%d %s %s",&code, nom, prenom) == 3) {
                        printf("code : %d - nom : %s - prénom : %s\n",
                                        code, nom, prenom);
                }
                fclose(adh);
        }
        return 0;
}


Note que le
if(!feof(adh))
rajoute un test inutile, qui est exécuté une fois et avant toute tentative de lecture (ce qui n'a aucun sens), et que je l'ai supprimé de l'exemple simplifié ci-dessus.

Le problème vient donc de ce que tu fais dans la boucle :
                        // On ne connaît pas la valeur initiale de b
                        // je suppose que c'est 1 (0 poserait problème).
                        // Cependant, ce n'est pas comme cela qu'on utilise
                        // realloc() en principe. Ici, à chaque itération, 
                        // tu fais un realloc().
                        // Normalement, on fait plutôt comme cela : on
                        // réserve une capacité initiale et on la double
                        // si on approche de la saturation.
                        // De plus, il faut contrôler le retour de realloc()
                        // dans une variable temporaire, pour vérifier qu'il 
                        // n'est pas NULL avant d'écraser le pointeur.
                        // Enfin, si c'est ton premier appel à malloc ou
                        // realloc sur adher, il faut que celui-ci contienne
                        // NULL avant le premier appel à realloc() pour que
                        // ce premier appel se comporte comme un malloc
                        // initial.
                        adher=realloc(adher,b*sizeof(struct adherons));
                        // ensuite tu affectes ce que tu as récupéré à une
                        // struct accédée via un pointeur "adherons1" et tu
                        // ne fais rien de ton espace mémoire "adher"
                        // pourquoi n'utilises tu pas cet espace ?
                        adherons1->codeadh = ad.codeadh;
                        strcpy(adherons1->nom,ad.nom);
                        strcpy(adherons1->prenom,ad.prenom);
                        // tu passes au pointeur suivant, ce qui signifie
                        // que tu dois avoir un tableau de pointeurs sur
                        // struct lesquels doivent pointer vers un espace
                        // suffisant permettant de stocker les données de
                        // la struct ... est-ce le cas ?
                        adherons1++;
                        // tu incrémentes b (mais on ne sait pas que vaut b
                        // à l'entrée de la boucle dans ce que tu as posté et
                        // j'ai supposé qu'il valait 1 à l'entrée)
                        b++;


Comme suggéré dans les commentaires, au lieu de faire cela, ne devrais-tu pas utiliser l'espace alloué pour
adher
?

Cela te permettrait d'accéder aux données avec la notation crochets
[]
, comme si c'était un tableau de struct par exemple
adher[b-1].code = code;
(si
b
commence à 1) car avec
realloc()
tu réserves une zone de mémoire contiguë qui te permet d'accéder aux emplacements mémoire, car ils sont situés les uns à la suite des autres à partir de l'adresse unique contenue dans le pointeur
adher
.

Enfin, il ne faudra pas oublier de libérer la mémoire vers laquelle pointe
adher
.

Dal
2
saskioutchiha_5955 Messages postés 4 Date d'inscription dimanche 22 mai 2022 Statut Membre Dernière intervention 25 mai 2022
23 mai 2022 à 15:47
merci pour ton effort et je suis désolé pour la salutation car c'est ma première question dans ce forum
premièrement j'ai réserve une quantité de la mémoire au début par la fonction malloc() et j'ai initialise b par 2 donc le pointeur adher a de type (struct adherons ) et dans chaque itération il vas réserve une case mémoire pour stoque les informations par les donne de fichier par le pointeur adherons1 qui vas remplir case par case
je vais te envoyée tous les partie de code pour bien comprendre tous que j'ai fais parce que cas c'est un projet et je peux pas t'envoyer tout le code car il contient 600 ligne
0
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083 > saskioutchiha_5955 Messages postés 4 Date d'inscription dimanche 22 mai 2022 Statut Membre Dernière intervention 25 mai 2022
Modifié le 23 mai 2022 à 17:58
dans chaque itération il vas réserve une case mémoire

Comme expliqué dans le code commenté ci-dessus, normalement on ne fait pas cela. On réserve une quantité de mémoire par exemple pour stocker 2 struct, ou 16 struct, et quand tu arrives à saturation, tu fais un
realloc()
pour doubler.

Augmenter la capacité de 1 struct à chaque tour de boucle marchera aussi (ce n'est pas ce qui fera que ton code plantera), mais ce n'est pas une bonne pratique car cela signifie de multiples appels à
realloc()
, qui est un appel système (ce n'est pas optimisé, c'est lent).

Si tu veux augmenter de 1 à chaque tour, tu peux le faire, mais que tu augmentes de 1 ou que tu doubles, n'écrase pas le pointeur avec ce qui est retourné par
realloc()
avant d'avoir vérifié que la réallocation a fonctionné, car tu auras un problème s'il retourne NULL (tu auras écrasé ton pointeur valide et rendu la mémoire inaccessible).

                        struct adherent * temp = realloc(adher, b * sizeof(struct adherent));
                        if (temp == NULL) {
                                printf("Erreur : impossible d'allouer la "
                                                "mémoire\n");
                                // gérer l'erreur, demander à l'utilisateur de libérer de 
                                // la mémoire, permettre au programme de poursuivre
                                // en faisant autre chose, ou sortir du programme
                                exit(EXIT_FAILURE);
                        }
                        adher = temp;


pour stoque les informations par les donne de fichier par le pointeur adherons1 qui vas remplir case par case

Je pense que ton erreur est là.

Tu n'as pas à utiliser un autre pointeur sur struct pour remplir les "cases".

realloc()
réserve un bloc de mémoire où les struct sont stockées les unes à la suite des autres à partir de l'adresse mémoire contenue dans le pointeur sur struct
adher
. Tu n'as besoin de rien d'autre pour accéder aux "cases" comme tu dis.

adher[0]
te permet d'accéder au premier struct,
adher[1]
au deuxième, etc., et comme la notation crochets déréférence le pointeur
adher
, tu peux utiliser le point pour accéder aux champs :
adher[0].code = 1889;
par exemple.
1
saskioutchiha_5955 Messages postés 4 Date d'inscription dimanche 22 mai 2022 Statut Membre Dernière intervention 25 mai 2022 > [Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024
24 mai 2022 à 03:21
merci beaucoup j'ai résolve ce problème de remplissage de tableau mais j'ai rencontrer un autre problème c'est quand je remplis le tableau avec des nouveaux donne (ce n'est pas par le fichier) il me permet de remplire que une seul case et après le programme se bloque et il sort et je sais pas ou est le problème .
DUEXIEME QUESTION :
et j'ai une autre questions quant je affiche les donne que j'ai stoque parmi le fichier comme ca :
printf("%d",adher[ 0].code) il me donne la valeur exacte.
mais quant je affiche avec le pointeur qui point sur la case comme ca :
printf("%d",adherons1->code) il me donne une valeur fausse .
et merci beaucoup .
0
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083 > saskioutchiha_5955 Messages postés 4 Date d'inscription dimanche 22 mai 2022 Statut Membre Dernière intervention 25 mai 2022
Modifié le 24 mai 2022 à 10:20
Déjà, bravo d'avoir résolu ton problème initial !

Pour tes autres problèmes.

Si lorsque ton programme tente d'écrire des données en mémoire il "se bloque et il sort" c'est que, probablement, tu essayes d'écrire dans une zone mémoire qui n'est pas allouée au programme.

Si tu es sous Linux, compile avec l'option
-g
et lance ton programme avec valgrind. Cet outil t'aidera à déterminer les lignes qui causent ton plantage. Le fait de compiler avec les warnings peut aussi t'aider à corriger des incohérences dans ton code (options
-Wall -Wextra
).

Pour ta 2ème question, c'est difficile de te dire ce qui ne va pas sans le code.

Tu n'indiques pas de quel type est "adherons1".

Si "adherons1" est un pointeur sur struct qui est exactement du même type que adher et que tu as fait
adherons1 = adher;
juste avant alors
printf("%d", adher[0].code);
devrait afficher la même chose que
printf("%d", adherons1->code);
.

Note que le résultat de
realloc()
peut éventuellement aboutir à modifier l'adresse mémoire à partir de laquelle sont stockées les données stockée dans adher. Tu devrais donc mettre à jour "adherons1" avec la même valeur affectée à "adher" avant de faire une quelconque manipulation ou opération avec ce pointeur.

En bref, si tu veux vraiment accéder à tes données en incrémentant un autre pointeur sur struct au lieu d'utiliser la notation crochets sur adher (pourquoi ?) tu dois t'assurer que ton autre pointeur pointe bien sur les données appropriées.
0
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083 > [Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024
Modifié le 24 mai 2022 à 14:12
Si tu n'as pas valgrind ou que tu n'est pas sous Linux, mais que tu as une version récente de gcc (à partir de la version 10), tu peux aussi utiliser son analyseur statique de code avec l'option
-fanalyzer
qui peut t'aider à trouver des erreurs.
0
saskioutchiha_5955 Messages postés 4 Date d'inscription dimanche 22 mai 2022 Statut Membre Dernière intervention 25 mai 2022
25 mai 2022 à 00:18
merci beaucoup j'ai résolve tous les probleme j'ai seulement une petite question sur comment on peu lire un fichier sound dans mon programme c car c'est une tache que je veux l'ajouter dans mon projet pour montrer a mon prof que je suis créative
hhhhhh si tu as l'idee tu peut me aide et merci une autre fois
0
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083
Modifié le 25 mai 2022 à 01:35
La bibliothèque standard définie par le langage C n'est pas capable de lire un fichier son.

Il y a des solutions.

1.

Une première solution est d'utiliser une API de ton système d'exploitation, par exemple, sous Windows :

https://docs.microsoft.com/fr-FR/previous-versions//dd743680(v=vs.85)

PlaySound(TEXT("recycle.wav"), NULL, SND_FILENAME);


Fais un
#include <windows.h>
dans ton source pour utiliser cette fonction.

Comme indiqué par la documentation de Microsoft, cette fonction est accessible avec une bibliothèque du système Windows qui s'appelle "Winmm".

Pour créer un exécutable fonctionnant avec elle, il faudra donc aussi modifier le paramétrage de tes options de compilation, dans les options passées à l'éditeur de liaison en ajoutant
winmm
.

Si tu compiles avec gcc, à la fin de ta ligne de commande de compilation, rajoute
-lwinmm
.

Si tu compiles pour Windows et que ton enseignant est sous Windows, tu peux fournir l'exécutable ainsi généré, car la bibliothèque système "Winmm" existe sous Windows depuis Windows 2000. Si tu veux que ton enseignant soit en mesure de compiler ton code avec la liaison de cette bibliothèque, tu devrais lui fournir la ligne de commande de compilation complète.

Ce type de solution est limité au système d'exploitation qui propose cette 'API (Windows dans cet exemple) et ne fonctionnera pas si ton enseignant utilise un autre système.

2.

Un autre type de solutions est d'utiliser une bibliothèque externe te permettant de jouer un son.

Par exemple :

C'est plus compliqué à installer et utiliser, mais ces bibliothèques permettent d'écrire un code portable sur les différents systèmes d'exploitation qu'ils supportent : Linux et Unix (POSIX), MacOS, Windows,... une fois la bibliothèque installée pour le système en question.

C'est certainement une solution peu commode pour ton enseignant s'il doit compiler ton code, car elle suppose qu'il installe la bibliothèque en question.
0