Aide C++ : Structure & Fichier

Fermé
Louise - 13 avril 2006 à 18:28
 10fer - 16 nov. 2008 à 16:36
Bonjour tout le monde! Je suis une débutante en programmation C++ et j'ai un exercice à faire qui est assez difficile pour moi. Voici l'énoncé de cela:
Concevoir un programme en C++ qui lit le fichier dinfo.txt , réalise un tri en ordre alphabétique sur le champ nom et sauvegarde le résultat dans un autre fichier appelé dinfo_apres_tri.txt . On suppose que le contenu du fichier dinfo.txt ne dépasse jamais 10 000 lignes.
En fait, le fichier dinfo.txt est une structure qui comporte une colonne de Nom, de Prénom, de Type, de Type d'appareil, de #extension téléphonique, de Bureau, de #prise, de #inventaire, d'adresse physique et d'adresse IP. Chaque colonne est séparée par un espace ou une tabulation, tous les champs sont remplis et ce fichier est sous format texte.

Voici ce que j'ai fait jusqu'à maintentant, mais je suis bloquée et je n'arrive pas à poursuivre... :

#include <iostream>
#include <fstream>

using std::cout;
using std::ifstream;


struct Info {
char Nom [30] ;
} ;


Lire_element (ifstream Fichier) {
Info Etudiant ;

Fichier >> Etudiant.Nom ;
Return Etudiant ;
}


main () {

ifstream Lecture ;
Info Membre ;

Lecture.open("dinfo.txt") ;
Membre = Lire_element (Lecture) ;

while ( ! Lecture.eof() ) {
for (i=0 ; i<strlen(Nom) ; i++) {



J'espère tellement que vous pourriez m'aider à me débloquer. Merci beaucoup!

44 réponses

mamiemando Messages postés 33446 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 20 décembre 2024 7 812
14 avril 2006 à 09:43
Alors je ne sais plus si c'est toi ou pas qui m'avais déjà fourni la réponse : on l'a pas vu à l'école donc non... MAIS :)

1) Il faut bien comprendre qu'en informatique, le nombre de fonctions est tellement important que tu ne verras jamais toutes les fonctions
2) L'utilisation de la STL en l'occurrence des map est vraiment TRES classique
3) On pourrait s'en sortir en recodant un algo de tri (tri fusion, tri à bulle, tri par insertion) mais c'est un peu du masochisme si on ne te l'a pas demandé expressement
4) Le rôle des librairies est d'éviter de réinventer la roue à chaque fois.

A ta place je demanderai a ton/ta prof si ça pose un problème, sachant qu'en C++ la démarche des map est clairement la plus naturelle. Si tu n'y a pas le droit regarde comment s'implémente un tri par exemple pour une liste chainée, sachant que ce sera moins rapide en terme d'implémentation et d'éxecution.

Bonne chance
1
Bon...J'ai essayé de faire du mieux que je peux avec ce que je connais jusqu'à maintenant. Cependant, dans mon main(){ je veux que le tri se fait là, mais comment puis-je passer d'un nom à un autre afin de les comparer pour les placer en ordre alphabétique?...

#include <iostream>
#include <fstream>
#include <string>

using std::cout;
using std::ifstream;
using std::ofstream;


struct Utilisateur {
char Nom[20] , Prenom[20] , Type_appareil[10] , Extension_telephonique[5] ;
char Bureau[10] , Prise[20] , Inventaire[10] , Adresse_physique[20] ;
char Adresse_Ip[20] ;
};


Lire_Element (ifstream Fichier) {
Utilisateur Un_utilisateur;

Fichier >> Un_utilisateur.Nom ;
Fichier >> Un_utilisateur.Prenom ;
Fichier >> Un_utilisateur.Type_appareil ;
Fichier >> Un_utilisateur.Extension_telephonique ;
Fichier >> Un_utilisateur.Bureau ;
Fichier >> Un_utilisateur.Prise ;
Fichier >> Un_utilisateur.Inventaire ;
Fichier >> Un_utilisateur.Adresse_physique ;
Fichier >> Un_utilisateur.Adresse_Ip ;
return Un_utilisateur;
}


main () {

ifstream Infos ;
Utilisateur User ;
ofstream Nouveau ;

Infos.open("dinfo.txt") ;
Nouveau.open("dinfo_apres_tri.txt");

while ( ! Infos.eof()) {
for (i=0 ; i<20 ; i++) {
strncmp ( ?????????????
??????????????????????????
??????????????????????????
Nouveau << ????? ;
}}

Infos.close();
Nouveau.close(),
}
1
mamiemando Messages postés 33446 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 20 décembre 2024 7 812
20 avril 2006 à 12:34
Tu peux utiliser les fonctions strcmp et qsort par exemple. la fonction qsort prend en paramètre un pointeur sur une fonction définissant ta relation d'ordre.

http://www.linux-kheops.com/doc/man/manfr/man-html-0.9/man3/qsort.3.html
http://www.manpagez.com/missing.php

Exemple d'utilisation
http://www.lri.fr/~aze/page_c/aide_c/qsort.html

Note au passage quesi tu utilisais des std::string pour tes champs tu pourrais :
- t'abstraire de la taille des champ, puisque une stdd:string est virtuellement de longueur infinie
- utiliser l'opérateur < pour comparer tes chaînes

Bonne chance
1
mamiemando Messages postés 33446 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 20 décembre 2024 7 812
21 avril 2006 à 21:53
Une fonction doit toujours avoir un type de retour, que tu as oublié de précisé :
Utilisateur Lire_Element (ifstream Fichier) {
  Utilisateur Un_utilisateur;

  Fichier >> Un_utilisateur.Nom ;
  ...
  Fichier >> Un_utilisateur.Adresse_Ip ;
  return Un_utilisateur;
} 

Si la fonction ne retourne rien, son type de retour est void
void plop(){
  printf("plop\n");
}

Ensuite les messages d'erreurs te disent qu'ils ne connaissent pas strcmp, et pour cause, cette fonction attend en paramètre deux char*, et tu lui passes un char* et un std::string.

Il faut donc convertir tes strings avec les méthodes c_str(). Par ailleurs tu peux utiliser :
- l'opérateur = si à gauche de l'opérateur c'est un std::string pour faire une recopie de chaîne, à la place du strcpy.
- l'opérateur == si à gauche de l'opérateur c'est un std::string pour faire une comparaison de chaîne, à la place du strcmp.
if (Infos) {
  std::string Ligne1;
  std::string Ligne2;
  std::getline (Infos , Ligne1) ;
  while ( ! Infos.eof() ){
    while ( strcmp (User.Nom , Ligne1.c_str()) < 0) {
      Ligne2=Ligne1;
      Ligne1=User.Nom;
    }
    Nouveau << Ligne1 << endl;
  }
}

Je t'invite à prendre le temps de lire les docs :
https://community.hpe.com/t5/custom/page/page-id/HPPSocialUserSignonPage?redirectreason=permissiondenied&referer=https%3A%2F%2Fcommunity.hpe.com%2Ft5%2FServers-Systems-The-Right%2FSGI-com-Tech-Archive-Resources-now-retired%2Fba-p%2F6992583
http://www.manpagez.com/missing.php
http://www.linux-kheops.com/doc/man/manfr/man-html-0.9/man3/strcpy.3.html

Bonne chance
1

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
mamiemando Messages postés 33446 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 20 décembre 2024 7 812
13 avril 2006 à 20:23
Il manque la fin du programme. En fait c'est vraiment très simple à faire si tu utilises la structure map<> de la STL :
https://community.hpe.com/t5/custom/page/page-id/HPPSocialUserSignonPage?redirectreason=permissiondenied&referer=https%3A%2F%2Fcommunity.hpe.com%2Ft5%2FServers-Systems-The-Right%2FSGI-com-Tech-Archive-Resources-now-retired%2Fba-p%2F6992583

L'exemple donné sur la page parle de lui-même en ce qui concerne l'insertion d'élément dans une map (opérateur []). Or l'opérateur ordonnant les std::string est par défaut (la vie est bien faite !) l'ordre alphabétique ;-)
#include <fstream>
#include <iostream>
#include <string>
#include <map>

// Une structure contenant les infos
struct infos{
  std::string nom;
  std::string prenom;
  std::string appareil;  
  std::string prise;  
  std::string inventaire;  
  std::string adresse_ip;  
};

// Parser une ligne d'info
bool read_line_infos(
  const std::string & f_in,
  struct infos & data
){
  //Lit une chaine et met infos dans data
  //return true si tout va bien, false sinon
}

// Lire le fichier d'info et le mettre dans un dico
bool read_file_infos(
  std::string & filename_in,
  std::map<std::string,struct infos> & dico
){
  std::ifstream f_in(filename_in);
  if (f_in){
    std::string ligne; // variable contenant chaque ligne lue

    // cette boucle s'arrête dès qu'une erreur de lecture survient
    for(unsigned int no_line=1;std::getline(fichier, ligne);++no_line){
       // afficher la ligne à l'écran
       struct infos data;
       if( !read_line_infos(ligne,data) ){
         std::cerr << "La ligne " << no_line 
             << "["<< ligne << "]" << std::endl;     
      }else{
         dico[data.nom]=data;
      }
    }
    return true;
  }
  std::cerr << "Le fichier " << filename 
        << "n'a pu être ouvert" << std::endl;
  return false;
}


bool read_file_infos(
  std::string & filename_out,
  const std::map<std::string,struct infos> & dico
){
  std::ofstream f_out(filename_out);
  if(f_out){
    std::map<std::string,struct infos>::const_iterator
      dit(dico.begin()),
      dend(dico.end());
    for(;dit!=dend;++dit){
      const struct_info & data=dit->second;
      f_out << data.nom << "\t" << data.prenom << std::endl;
    }
    return true;
  }
  return false;
}

int main(){
  const std::string filename_in="plop.txt";
  const std::string filename_out="plop2.txt";
  std::map<std::string,struct infos> dico;

  // Lire le fichier
  read_file_infos(filename_in,dico);

  // Ecrire les datas
  read_sorted_file_infos(filename_out,dico);
  return 0;
}


Ou quelque chose dans l'idée ;-)

Bonne chance
0
Bonjour!
Premièrement, merci de m'avoir aidé!
Deuxièmement, je voudrais souligner que je ne pourrais pas utiliser des notions inconnues (que je n'ai pas encore vues à l'école), comme la bibliothèque <map> ... =(
Je me suis renseignée et je sais qu'il faut :
1) lire le fichier diinfo.txt ;
2) le mettre dans un tableau de structures ;
3) faire le tri en ordre alphabétique (de la colonne Nom) ;
4) enfin, mettre le tout dans le fichier dinfo_apres_tri.txt .
Comment pourrais-je écrire cela en C++?
Je vous remercie en avance!
0
Bon, c'est la vie...Vous ne me comprenez peut-être pas pour ce qui est de l'école et je ne sais pas trop de quoi vous parlez si c'était moi ou pas... En tout cas, je vais essayer de travailler cet exercice un peu plus selon ma petite connaissance et je vais le poster ici bientôt, s'il y a des erreurs, et on verra qu'est-ce que ça donne!
0
?????
0
Quelqu'un, s'il vous plaît!!!
0
J'suis allée voir ce que vous m'aviez donné sur le qsort. Mais il y a une chose que je ne comprends pas. C'est que dans mon fichier dinfo.txt, je ne peux pas savoir c'est quoi le nombre de Nom qu'il y a de-dans, donc comment pourrais-je comparer nom par nom si je ne sais pas quand ça termine?!
Je comprends que chaque Nom est formé sous forme de tableau et qu'il est possible de pouvoir comparer lettre par lettre pour les placer en ordre alphabétique, mais pour sauter d'un Nom à un autre dans une structure, je ne vois pas comment on pourrait faire ça si c'est de longueur indéfinie.
(désolé si j'suis un peu nulle dans tout ça...)
0
C'est surement plus simple avec les map et les string... Mais j'aimerais vraiment faire avec les structures et les fichiers de la façon que je fais, parce que j'aimerais bien maîtriser les notions de base en premier et après je pourrais faire avec des notions un peu plus complexes. Cependant, je n'arrive même pas à faire correctement mon programme... Bon voici ce que j'ai fait jusqu'à date (j'ai essayé de comprendre la fonction getline que vous m'aviez donné, en fait, ce qui est en gras ne me semble pas vraiment exact), pourriez-vous me débogger svp :

#include <iostream>
#include <fstream>
#include <string>

using std::cout;
using std::ifstream;
using std::ofstream;


struct Utilisateur {
char Nom[20] , Prenom[20] , Type_appareil[10] , Extension_telephonique[5] ;
char Bureau[10] , Prise[20] , Inventaire[10] , Adresse_physique[20] ;
char Adresse_Ip[20] ;
};


Lire_Element (ifstream Fichier) {
Utilisateur Un_utilisateur;

Fichier >> Un_utilisateur.Nom ;
Fichier >> Un_utilisateur.Prenom ;
Fichier >> Un_utilisateur.Type_appareil ;
Fichier >> Un_utilisateur.Extension_telephonique ;
Fichier >> Un_utilisateur.Bureau ;
Fichier >> Un_utilisateur.Prise ;
Fichier >> Un_utilisateur.Inventaire ;
Fichier >> Un_utilisateur.Adresse_physique ;
Fichier >> Un_utilisateur.Adresse_Ip ;
return Un_utilisateur;
}


main () {

ifstream Infos ;
Utilisateur User ;
ofstream Nouveau ;

Infos.open("dinfo.txt") ;
Nouveau.open("dinfo_apres_tri.txt");

if (Infos) {
std::string Ligne1;
std::string Ligne2
std::getline (Infos , Ligne1) ;
while ( ! Infos.eof() ){
while ( strcmp (Un_utilisateur.Nom , Ligne1) < 0) {
strcpy (Ligne2 , Ligne1);
strcpy (Ligne1 , Un_utilisateur.Nom);
}
Nouveau << Ligne1 << endl;
}}

Infos.close();
Nouveau.close(),
return 0;
}


Les erreurs qui se sont apparues lors de la compilation sont:
tp3.cpp: In function `int main()':
tp3.cpp:52: error: `Ligne2' does not name a type
tp3.cpp:54: error: `Un_utilisateur' undeclared (first use this function)
tp3.cpp:54: error: (Each undeclared identifier is reported only once for each function it appears in.)
tp3.cpp:55: error: `Ligne2' undeclared (first use this function)
0
...
0
Bon...J'ai corrigé ce que Kiruasam m'a dit de corriger...MAIS ça ne fonctionne toujours pas...

#include <iostream>
#include <fstream>
#include <string>

using std::cout;
using std::ifstream;
using std::ofstream;


struct Utilisateur {
char Nom[20] , Prenom[20] , Type_appareil[10] , Extension_telephonique[5] ;
char Bureau[10] , Prise[20] , Inventaire[10] , Adresse_physique[20] ;
char Adresse_Ip[20] ;
};


Lire_Element (ifstream Fichier) {
Utilisateur Un_utilisateur;

Fichier >> Un_utilisateur.Nom ;
Fichier >> Un_utilisateur.Prenom ;
Fichier >> Un_utilisateur.Type_appareil ;
Fichier >> Un_utilisateur.Extension_telephonique ;
Fichier >> Un_utilisateur.Bureau ;
Fichier >> Un_utilisateur.Prise ;
Fichier >> Un_utilisateur.Inventaire ;
Fichier >> Un_utilisateur.Adresse_physique ;
Fichier >> Un_utilisateur.Adresse_Ip ;
return Un_utilisateur;
}


main () {

ifstream Infos ;
Utilisateur User ;
ofstream Nouveau ;

Infos.open("dinfo.txt") ;
Nouveau.open("dinfo_apres_tri.txt");

if (Infos) {
std::string Ligne1;
std::string Ligne2;
std::getline (Infos , Ligne1) ;
while ( ! Infos.eof() ){
while ( strcmp (User.Nom , Ligne1) < 0) {
strcpy (Ligne2 , Ligne1);
strcpy (Ligne1 , User.Nom);
}
Nouveau << Ligne1 << endl;
}}
Infos.close();
Nouveau.close(),
return 0;
}


Voici les erreurs de compilation cette fois-ci:
tp3.cpp: In function `std::ifstream Lire_Element(std::ifstream)':
tp3.cpp:36: error: conversion from `Utilisateur' to non-scalar type `std::ifstream' requested
tp3.cpp: In function `int main()':
tp3.cpp:54: error: no matching function for call to `strcmp(char[20], std::string&)'
/usr/include/iso/string_iso.h:65: note: candidates are: int strcmp(const char*, const char*)
tp3.cpp:55: error: no matching function for call to `strcpy(std::string&, std::string&)'
/usr/include/iso/string_iso.h:66: note: candidates are: char* strcpy(char*, const char*)
tp3.cpp:56: error: no matching function for call to `strcpy(std::string&, char[20])'
/usr/include/iso/string_iso.h:66: note: candidates are: char* strcpy(char*, const char*)
0
Merci pour votre support! Je pense que le programme fonctionne bien car il n'y a plus d'erreurs lors de la compilation. J'ai aussi ajouté :
Infos.close();
Nouveau.close() ;
avant return 0; pour fermer les 2 fichiers.
Cependant, pour voir si le programme a réellement fait le tri en ordre alphabétique voulu, comment fait-on pour voir le contenu du fichier dinfo_apres_tri.txt ?
0
Bon j'ai essayé de créer un programme qui va lire mon nouveau fichier dinfo_apres_tri.txt pour vérifier si mon premier programme a bien fait son travail de triage. Il n'y a pas eu d'erreurs de compilation, cependant, quand je l'exécute, il ne fait absolument rien. Que puis-je faire pour corriger tout ça?

#include <iostream>
#include <fstream>
#include <string>

using std::cout;
using std::endl;
using std::ifstream;


struct Utilisateur {
char Nom[20] , Prenom[20] , Type_appareil[10] , Extension_telephonique[5] ;
char Bureau[10] , Prise[20] , Inventaire[10] , Adresse_physique[20] ;
char Adresse_Ip[20] ;
};


main () {

ifstream Infos ;
Infos.open("dinfo_apres_tri.txt") ;

if (Infos) {
std::string Ligne;
std::getline (Infos , Ligne) ;
while ( ! Infos.eof() ){
cout << Ligne << endl;
}}
Infos.close();
return 0;
}
0
mamiemando Messages postés 33446 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 20 décembre 2024 7 812
22 avril 2006 à 22:33
Tu as écrit :
std::getline (Infos , Ligne) ;
while ( ! Infos.eof() ){
  cout << Ligne << endl;
}

Or dans ta boucle while, tu n'avances jamais dans la lecture du fichier, donc tu boucle indéfiniment et il ne se passe ... rien ;)

Quand tu bloques, il faut que tu prennes le reflexe de chercher sur google :
https://www.google.fr/search?hs=jf3&hl=fr&client=firefox-a&rls=org.mozilla%3Afr%3Aofficial&q=c%2B%2B+lire+fichier+ligne+par+ligne&btnG=Rechercher&meta=&gws_rd=ssl
http://c.developpez.com/faq/cpp/?page=fichiers#FICHIERS_lecture_par_ligne

Bonne chance
0
Bon, j'ai essayé quelque chose d'autre avec les sites web que vous m'aviez donné. Mon programme de vérification ne se passe rien quand je l'exécute... Écoutez, je ne veux pas faire de presssion, mais je voulais seulement vous dire que ce programme de vérification n'est pas le but de mon travail. Je veux seulement faire un programme de tri en ordre alphabétique correctement, c'est pour cela que je voulais le vérifier. J'aimerais ne pas trop perdre de temps sur mon programme de vérification mais plutôt de bien faire mon premier programme de tri...Alors, svp, veuillez avoir la gentillesse de me corriger je vous en prie!...

#include <iostream>
#include <fstream>
#include <string>

using std::cout;
using std::endl;
using std::ifstream;


struct Utilisateur {
char Nom[20] , Prenom[20] , Type_appareil[10] , Extension_telephonique[5] ;
char Bureau[10] , Prise[20] , Inventaire[10] , Adresse_physique[20] ;
char Adresse_Ip[20] ;
};


main () {

ifstream Infos ;
Infos.open("dinfo_apres_tri.txt") ;

if (Infos) {
std::string Ligne;
while ( std::getline( Infos , Ligne ) ){
cout << Ligne << endl;
}}
Infos.close();
return 0;
}
0
mamiemando Messages postés 33446 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 20 décembre 2024 7 812
23 avril 2006 à 23:47
Ok on corrige déjà les fautes de bases : main retourne un int donc on écrit :
int main(){
  //...
  return 0;
}

Il peut être intéressant de passer en paramètre le nom du fichier à lire à l'éxécution (sinon à chaque fois que le nom changera, il faudra recompiler le programme). Ensuite si ton programme ne fais rien c'est sans doute parce que le fichier que tu veux lire n'est pas dans le même répertoire.

Chez moi j'ai écrit dans plop.cpp :
#include <iostream>
#include <fstream>
#include <string>

using std::cout;
using std::endl;
using std::ifstream;


struct Utilisateur {
    char Nom[20] , Prenom[20] , Type_appareil[10] , Extension_telephonique[5] ;
    char Bureau[10] , Prise[20] , Inventaire[10] , Adresse_physique[20] ;
    char Adresse_Ip[20] ;
};


int main(int argc,char **argv) {

    if(argc<2){
        std::cerr << "usage : " << argv[0] << " filename " <<std::endl;
        return 1;
    }
    std::ifstream Infos;
    Infos.open(argv[1]);

    if (Infos) {
        std::string Ligne;
        while ( std::getline( Infos , Ligne ) ){
            cout << Ligne << endl;
        }
    }
    Infos.close();
    return 0;
}

Et ensuite tout marche bien (je mets dans le fichier plop les lignes aaa bbb....) :
(mando@silk) (~) $ cat plop
aaa
bbb
ccccc
ddd

Je compile et je lance :
(mando@silk) (~) $ g++ -Wall -W plop.cpp
(mando@silk) (~) $ ./a.out plop
aaa
bbb
ccccc
ddd

Peut-être es-tu sous windows, et ta fenêtre disparaît sans que tu aies le temps de voir le résultat. Auquel cas, il suffit de rajouter une pause à la fin du programme. Avant chaque return du main, rajoute un getchar() :
int main(int argc,char **argv){
  //...
  getchar();
  return 0;
}

Bonne chance
0
Merci pour tout ça. Toutefois, il n'y a rien qui se passe (et j'ai essayé de mettre getchar(); comme vous m'aviez dit)...Est-ce que je suis supposée de voir le contenu du fichier dinfo_apres_tri.txt sur l'écran? Parce que c'est ça que je veux...Ummm... Est-ce qu'il y a un moyen d'inclure une fonction qui permet cette aparition du contenu à l'écran dans mon premier programme de tri alphabétique?
0
mamiemando Messages postés 33446 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 20 décembre 2024 7 812
24 avril 2006 à 01:00
Peux-tu me dire si tu es sous windows ou linux, l'endroit ou tu as mis ton fichier texte, l'endroit ou tu as mis ton programme, et comment tu l'exécutes ?

Parce que ton programme marche, je l'ai testé, et il n'y a aucun soucis. C'est peut être que chez toi le fichier n'est pas dans le même répertoire que ton éxecutable.
Normalement tu dois taper dans une console (démarrer, exécuter, cmd sous windows) :
cd le_repertoire_de_monprogramme
le_nom_de_mon_programme le_nom_de_mon_fichier

Et dans cette même fenêtre les résultats s'afficheront....

Bonne chance
0