Modification dans un fichier texte en c++ [Résolu/Fermé]

Messages postés
67
Date d'inscription
jeudi 10 mai 2007
Statut
Membre
Dernière intervention
10 mai 2010
- - Dernière réponse : yannboensit2007
Messages postés
67
Date d'inscription
jeudi 10 mai 2007
Statut
Membre
Dernière intervention
10 mai 2010
- 15 mai 2007 à 16:34
bonsoir a tous je travail ,mon application effectue des enregistrements dans un fichier texte(le matricule,le non et le prenom)en c++.j'arrive a rechercher les informations a partir du matricule ,mais je n'arrive a modifier et a supprimer un enregistrement .voici mon code
void rechercher(FILE*ptr)
{
int num_ligne1=0, num_ligne=0,div_ligne,nbre_car,nbre_enreg=0;
lignefich ligne;
char matricule[10];
cout<<"\n"<<"ENTREZ LE MATRICULE:";
cin>>matricule;
nbre_car=strlen(matricule);
rewind (ptr);

while(fgets(ligne, Maxi+2,ptr) !=NULL)
{
debut: num_ligne+=1;
div_ligne=fmod(num_ligne,3);
if ( div_ligne==1)
{
if (strnicmp(ligne,matricule,nbre_car)==0)
{
rewind(ptr);
num_ligne1=0;
cout<<"\n";
while(fgets(ligne,Maxi+2,ptr) !=NULL)
{
num_ligne1+=1 ;
if( (num_ligne1>=num_ligne)&&(num_ligne1<=num_ligne+2))
{
cout<<ligne;
nbre_enreg+=1;
}
}
}
}
}
rewind(ptr);
num_ligne1=0;
do
{
fgets(ligne,Maxi+2,ptr);
num_ligne1+=1;
} while(num_ligne1<num_ligne+2);
num_ligne=num_ligne1;

if (feof(ptr)!=0)
{
if ((nbre_enreg/3)==0)
{
cout<<" \n CE MATRICULE NE CORRESPOND A AUCUN ENREGISTREMENT";
}
else
{
// cout<<"\n "<<nbre_enreg/5<<" ETUDIANT(S) ";
}
cout<<"\n\n\n";
//cout<<"\n"<<"------------------------Fin de fichier------------------";
}
else
{
fgets(ligne, Maxi+2,ptr);
goto debut;
}

}
Afficher la suite 

5 réponses

Meilleure réponse
Messages postés
29064
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
17 novembre 2019
6698
1
Merci
En fait je pense que c'est une mauvaise approche (enfin c'est moins point de vue). Globalement l'accès à un fichier est lent, donc il vaut mieux charger le fichier dans une structure de donnée, manipuler cette structure, et réécrire le fichier si nécessaire.
#include <map>
#include <iostream>
#include <fstream>
#include <set>
#include <string>

typedef std::string matricule_t;
typedef std::string nom_t;
typedef std::string prenom_t;

class datas_etudiant_t{
    protected:
    typedef std::map<matricule_t,std::pair<nom_t,prenom_t> > map_matricule_t;
    typedef std::map<nom_t,std::set<matricule_t> > map_nom_t;
    typedef std::map<prenom_t,std::set<matricule_t> > map_prenom_t;

    map_matricule_t map_matricule;
    map_nom_t map_nom;
    map_prenom_t map_prenom;

    public:

    // Le constructeur
    datas_etudiant_t(){}

    // Ajouter un étudiant
    void ajouter_etudiant(
        const matricule_t & matricule,
        const nom_t & nom,
        const prenom_t & prenom
    ){
        map_matricule[matricule] = std::make_pair(nom,prenom);
        map_nom[nom].insert(matricule);
        map_prenom[prenom].insert(matricule);
    }
    // Recherche sur le matricule
    bool trouver_matricule(
        const matricule_t & matricule,
        nom_t & nom,
        prenom_t & prenom
    ){
        map_matricule_t::const_iterator fit(map_matricule.find(matricule));
        if (fit == map_matricule.end()) return false;
        nom = (fit->second).first;
        prenom = (fit->second).second;
        return true;
    }

    // Recherche sur le prenom
    bool trouver_prenom(
        const prenom_t & prenom,
        std::set<matricule_t> & matricules
    ){
        map_prenom_t::const_iterator fit(map_prenom.find(prenom));
        if(fit == map_prenom.end()) return false;
        matricules = fit->second;
        return true;
    }

    // Recherche sur le nom
    bool trouver_nom(
        const nom_t & nom,
        std::set<matricule_t> & matricules
    ){
        map_nom_t::const_iterator fit(map_nom.find(nom));
        if(fit == map_nom.end()) return false;
        matricules = fit->second;
        return true;
    }

    template <typename Tstream>
    void write(Tstream & out) const{
        map_matricule_t::const_iterator mit(map_matricule.begin()),mend(map_matricule.end());
        for(;mit!=mend;++mit){
            const matricule_t & matricule = mit->first;
            const nom_t & nom = (mit->second).first;
            const prenom_t & prenom = (mit->second).second;
            out << matricule << '\t' << nom << '\t' << prenom << std::endl;
        }
    }
};


int main(){
    datas_etudiant_t datas;
    datas.ajouter_etudiant("AP123","Poulain","Amélie");
    datas.ajouter_etudiant("AP124","Mauresmo","Amélie");
    datas.ajouter_etudiant("SP69","Poulain","Super");
    datas.ajouter_etudiant("PP99","Parker","Peter");

    {
        const std::string prenom_cherche = "Amélie";
        std::cout << "rechercher " << prenom_cherche << std::endl;
        std::set<matricule_t> matricules;
        if(datas.trouver_prenom(prenom_cherche,matricules)){
            std::set<matricule_t>::const_iterator sit(matricules.begin()),send(matricules.end());
            for(;sit!=send;++sit) std::cout << *sit << std::endl;
        }else std::cout << "Pas de personne dont le prénom est " << prenom_cherche << std::endl;
    }

    {
        const std::string nom_cherche = "Poulain";
        std::cout << "rechercher " << nom_cherche << std::endl;
        std::set<matricule_t> matricules;
        if(datas.trouver_nom(nom_cherche,matricules)){
            std::set<matricule_t>::const_iterator sit(matricules.begin()),send(matricules.end());
            for(;sit!=send;++sit) std::cout << *sit << std::endl;
        }else std::cout << "Pas de personne dont le nom est " << nom_cherche << std::endl;
    }

    // Ecrire dans la console
    datas.write(std::cout);

    // Ecrire dans un fichier
    std::ofstream ofs("plop.txt");
    if(ofs){
        datas.write(ofs);
        ofs.close();
    }else std::cerr << "fichier invalide" << std::endl;
    return 0;
}

Si tu veux faire une fonction de modification en fonction du matricule, pense à corriger en conséquence les 3 maps de datas_etudiant_t. En toute rigueur la fonction ajouter_etudiant doit vérifier que personne n'a déjà cet identifiant.

Bonne chance

Dire « Merci » 1

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

CCM 70689 internautes nous ont dit merci ce mois-ci

yannboensit2007
Messages postés
67
Date d'inscription
jeudi 10 mai 2007
Statut
Membre
Dernière intervention
10 mai 2010
-
bonsoir mamiemando merci pour le code comme je suis novice en programmation je vais prendre un peu de temps pour le lire et le comprendre
Messages postés
67
Date d'inscription
jeudi 10 mai 2007
Statut
Membre
Dernière intervention
10 mai 2010
0
Merci
j'aimerais savoir comment créer une fonction de modification et de suppression en utilisant maps datas_etudiant_t
Messages postés
29064
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
17 novembre 2019
6698
0
Merci
Je pense qu'il te manque un pré-requis important : la STl, en particulier les std::map et les std::set ! Donc voici un peu de lecture :
http://www.sgi.com/tech/stl/Map.html
http://www.sgi.com/tech/stl/set.html

Pour la suppression :
- dans map_matricule : il suffit d'écraser l'ancienne valeur
- pour les deux autres : rechercher le prénom (nom) avec un find, s'il est trouvé, supprimer le matricule du std::set correspondant. Je te laisse manipuler un peu tout ça pour ta familiariser avec la stl mais concrètement c'est moins de 20 lignes de code... Si tu comprends bien le code que je t'ai donné tu devrais y arriver, il suffit de prendre le temps de lire les deux liens que je t'ai donné. Voilà le début à rajouter dans la classe datas_etudiant_t
bool supprimer_etudiant(const matricule_t & matricule){
  map_matricule_t::iterator fit = map_matricule.find(matricule);
  if (fit ==  map_matricule.end()) return false; // pas trouvé
  const nom_t & nom = fit->first;
  const prenom_t & prenom = fit->second;
  //... supprimer de map_nom (A compléter)
  //... supprimer de map_prenom (A compléter)
  // supprimer de map_matricule
  map_matricule.erase(fit);
  return true;
}


Pour une modification il suffit de faire une suppression suivie d'un ajout. Dans la classe datas_etudiant_t :
void modifier_etudiant(
  const matricule_t & matricule,
  const nom_t & nouveau_nom,
  const prenom_t & nouveau_prenom
){
  supprimer_etudiant(matricule);
  ajouter_etudiant(matricule,nouveau_nom,nouveau_prenom);
}

En cas de soucis n'hésite pas à repasser.

Bonne chance
yannboensit2007
Messages postés
67
Date d'inscription
jeudi 10 mai 2007
Statut
Membre
Dernière intervention
10 mai 2010
-
Merci mamiemando,je penses qu'il me faut encore beaucoup de lecture
Messages postés
29064
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
17 novembre 2019
6698
0
Merci
Yep, je te conseille de regarder un tutoriel sur la STL. Ca vaut vraiment le coup de prendre un peu de temps pour voir comment ça marche car quand tu sais l'utiliser tu gagnes un temps fou, et les "seg fault" deviennent beaucoup moins fréquentes. En effet, tu n'as plus besoin de te poser de question en terme d'allocation mémoire, il se débrouille tout seul (cf code que je t'ai donné).

Quelques rappels de C++ (j'ai l'impression que tu as surtout fait du C jusqu'ici) :

- les classes sont des structures ou certains "membres" ne sont pas accessibles partout dans le programme (private, protected, public).

- à chaque structure et classe peut être rattaché des méthodes (c'est à dire une fonction qui s'applique à un objet de cette classe). Par exemple ajouter_etudiant et une méthode de data_etudiants_t

- en C++ tu as la notion de référence (const plop & p). Syntaxiquement tout se passe comme si tu manipulais directement un objet plop, mais algorithmiquement parlant tout se passe comme si tu manipulais un pointeur sur cet objet. Sauf que contrairement à un pointeur, une référence doit toujours être initialisée.

- tu peux accéder aux typedef publics d'une classe avec l'opérateur ::. Par exemple les types iterator et const_iterator sont des types définis dans chaque classe de la STL. L'opérateur :: sert aussi à accéder aux classes, fonctions, et structure d'un "namespace". Par exemple les classes de la STL sont toutes dans le namespace std, et c'est pourquoi on écrit par exemple std::set, std::map etc... Il faut voir un namespace comme une sorte de répertoire dans le code. Les namespaces servent essentiellement à éviter des conflits sur les noms de fonctions et à organiser le code.

- en C++ plutôt que d'utiliser des printf on utilise des streams (flux) sur lesquels ont lit/écrit avec les opérateurs << (l'équivalent du scanf) et >> (l'équivalent du printf). Les sorties et entrées standards stdin, stdout, stderr ont leurs homologue flux std::cin, std::cerr, std::cout.

Bon courage
Messages postés
67
Date d'inscription
jeudi 10 mai 2007
Statut
Membre
Dernière intervention
10 mai 2010
0
Merci
ok merci encore pour tous les conseils