cyberkate
Messages postés13Date d'inscriptionjeudi 21 avril 2005StatutMembreDernière intervention25 avril 2005
-
21 avril 2005 à 15:43
cyberkate
Messages postés13Date d'inscriptionjeudi 21 avril 2005StatutMembreDernière intervention25 avril 2005
-
24 avril 2005 à 21:05
Bonjour !
Je développe une application en mode console en C++.
Voici le thème : je veux gérer des clients qui réalisent plusieurs abonnements à un magazine.
J'ai donc créé une classe C_client et une classe C_abonnement. Je sauvegarde mes données dans un fichier lorsque l'utilisateur saisit le sous menu 5 pour sortir de l'application.
Or, la sauvegarde d'un client sans abonnements ne pose aucun problème. Seulement lorsque je lui ajoute un abonnement (chaque client possède un tableau d'abonnements), l'enregistrement des données quant à cet abonnement se trouvent erronées.
Voici ma procédure d'enregistrement de fichiers :
#include <string>
#include
#include <fstream>
void enregFichier()
{
int i;
// si le fichier est lisible...
if ( is_readable( "abonnements.txt" ) )
{ // ...alors on écrit dedans en effacant tout
std::ofstream file( "abonnements.txt" );
for (i=0;i<MAXIMUM;i++)
{
&tabClient[i],
ca c'est l'adresse en mémoire de ton client, mais pas l'objet lui meme.
DOnc au mieux ce que tu écris c'est l'adresse, qu'on se fou absolument.
Donc j'utilise ma version qui est plus lisible: ton code donnerait:
steve_clamage
Messages postés475Date d'inscriptiondimanche 3 octobre 2004StatutMembreDernière intervention11 août 20065 21 avril 2005 à 21:12
Le fwrite enregistre l'objet en binaire et non son adresse, en C++ on utiliserais plutot std::ostream::write.
cyberkate, pour faire propre il faudrait que ce soit tes classes qui
fournissent une methode de serialisation (= sauvegarde d'une instance
dans un fichier) car la façon d'enregistré une instance dépends des
attributs (si pointeur sur tableau dynamique par exemple).
cyberkate
Messages postés13Date d'inscriptionjeudi 21 avril 2005StatutMembreDernière intervention25 avril 2005 22 avril 2005 à 11:36
Pour la méthode de steve_clamage, j'ai le problème suivant : tous mes champs qui ne sont pas de type chaine ne peuvent être convertis en chaine... Voici ce que j'ai mis comme code :
Quant à la méthode de luhtor, j'ai essayé avec ce code dans la procédure enregFichier :
int i;
// si le fichier est lisible...
if ( is_readable( "abonnements.txt" ) )
{
std::ofstream file("abonnements.txt");
for (int i=0; i<MAXIMUM; i++)
{
file << tabClient[i].getNumClient() << tabClient[i].getNom() << tabClient[i].getPrenom() << tabClient[i].getAdresse() << tabClient[i].getCp() << tabClient[i].getVille() << tabClient[i].getTelephone() << tabClient[i].afficheLesAbonnements() << endl;
};
};
J'ai l'erreur suivant à la ligne débutant par "file" : error C2679: binary '<<' : no operator defined which takes a right-hand operand of type 'void' (or there is no acceptable conversion)
Ne peut-on pas enregistrer dans le fichier directement un objet ? J'aimerais conserver le type de chaque élément.
Je précise que pour récupérer un donnée de type chaine, je ne sais pas trop comment faire :
void getPrenom()
{
cout << prenom;
};
ou
char *getTelephone()
{
return telephone;
};
??
De plus, pour inscrire dans le fichier l'ensemble du tableau tabAbonnements de chaque client, je ne sais pas comment m'y prendre. Faut-il refaire une autre boucle pour inscrire chaque donnée de chaque objet du tableau ?
cyberkate
Messages postés13Date d'inscriptionjeudi 21 avril 2005StatutMembreDernière intervention25 avril 2005 22 avril 2005 à 14:14
Je pense que cela doit se voir que je débute vraiment en C++ ! lol
J'arrive pas du tout à faire ce que tu me dis alors que je fais du copier coller en essayant d'adapter le code. J'obtiens une bonne dizaine d'erreurs...
J'ai du mal à comprendre comment faire pour enregistrer donnée par donnée dans mon fichier afin de les relire lors du prochain lancement de l'application.
J'ai mis mes fichiers en ligne si ça vous aide à comprendre mon problème : ils ne contienent aucune modification par rapport à mon post initial.
Fichiers .cpp et .h
Je continue à chercher en attendant votre aide, car je suis vraiment perdue et que je dois présenter ce projet en examen...
cyberkate
Messages postés13Date d'inscriptionjeudi 21 avril 2005StatutMembreDernière intervention25 avril 2005 22 avril 2005 à 20:27
J'ai rajouté ce code dans le public de ma classe C_client (si je le mets en dessous, il y a une erreur demandant de mettre la fonction friend à l'intérieur d'une classe) :
Ensuite, voici le contenu de ma fonction enregFichier :
if ( is_readable( "abonnements.txt" ) )
{ // ...alors on écrit dedans en effacant tout
std::ofstream file("abonnements.txt");
for (int i=0; i<MAXIMUM; i++)
{
file << tabClient[i] << endl;
};
file.close();
};
Voici le nouveau problème : il n'y a pas "d'erreur" lors de l'écriture mais lorsque je réouvre l'application, les données sont affichées avec plein de fois 0040119F0 entre et après....
Voici le code qui charge les données dans mon tableau à l'ouverture de l'application :
void chargeClient()
{
monFichier = fopen("abonnements.txt", "r+"); //ouverture du fichier en lecture
if (monFichier == NULL)
{
cout << "Erreur d'ouverture du fichier Abonnements." << endl;
}
else
{
int i;
for (i=0;i<MAXIMUM;i++)
{
tmp = fread(&clientEnCours, sizeof(clientEnCours), 1, monFichier); // on lit une ligne par une ligne
if (!tmp) // si la ligne est vide
{
cout << "Erreur de lecture." << endl;
}
else
{
tabClient[i] = clientEnCours;
};
};
cyberkate
Messages postés13Date d'inscriptionjeudi 21 avril 2005StatutMembreDernière intervention25 avril 2005 22 avril 2005 à 20:51
Pour ce qui est des char *, je ne pense pas que ce soit une obligation, mais c'est qu'on a appris que comme ça. Donc j'ai repris le "cours" et ce que j'avais à peu près compris.
En laissant les fonctions de mon dernier post et en changeant les char * en std::string, je n'ai pas d'erreurs dans le débuggueur, mais les données dans le fichier ne sont pas correctes.
J'utilise cette fonction comme ceci : tabClient[i].getNom(); pour afficher le nom...
J'ai mes données et plein de 0040119F0 0040119F0 0040119F0...
Donc je ne comprends pas... peut-être que je les lis mal...
Merci de ton aide.
luhtor
Messages postés2023Date d'inscriptionmardi 24 septembre 2002StatutMembreDernière intervention28 juillet 20086 22 avril 2005 à 22:52
:)
Poste ta fonction qui enregistre dans un fichier, car ce que tu as ce
sont des adresses mémoires donc quelque part tu écris un pointeur et
nom un string.
cyberkate
Messages postés13Date d'inscriptionjeudi 21 avril 2005StatutMembreDernière intervention25 avril 2005 23 avril 2005 à 11:10
Voici ma fonction qui enregistre dans un fichier :
void enregFichier()
{
int i;
// si le fichier est lisible...
if ( is_readable( "abonnements.txt" ) )
{ // ...alors on écrit dedans en effacant tout
std::ofstream file("abonnements.txt");
for (int i=0; i<MAXIMUM; i++)
{
file << tabClient[i] << endl;
};
file.close();
};
};
Ce qui est bizarre, c'est que ça enregistre mes données ainsi que les adresses mémoires.
cyberkate
Messages postés13Date d'inscriptionjeudi 21 avril 2005StatutMembreDernière intervention25 avril 2005 23 avril 2005 à 13:26
Si je fais cout << tabClient[i].getNom() << endl; dans ma fonction afficheInfo(), j'ai l'erreur suivante de compilation :
error C2678: binary '<<' : no operator defined which takes a left-hand operand of type 'class ostream_withassign' (or there is
no acceptable conversion)
Et getNom() retourne un string :
std::string getNom()
{
return std::string(this->nom);
};
Et si je mets la fonction :
friend inline std::ostream & operator << (std::ostream & chaine, const C_client & client)
{
chaine << client.num_client << " " << client.nom << " " << client.prenom << " " << client.adresse << " " << client.cp << " " << client.ville << " " << client.telephone; // tu ajoutes ce que tu veux après
celà me fait 2 erreurs de même type :
- error C2228: left of '.getNumAb' must have class/struct/union type
- error C2228: left of '.getLibelle' must have class/struct/union type
Je ne peux "accéder" aux données privées relatives aux abonnements que par l'intermédiaire de fonctions :
cyberkate
Messages postés13Date d'inscriptionjeudi 21 avril 2005StatutMembreDernière intervention25 avril 2005 23 avril 2005 à 15:40
J'ai bien mis les bibliothèques iostream, string, ftream en en-tête.
Par contre, pour ce qui est du using namespace std; , si je le mets en en-tête, j'ai 59 erreurs car, apparemment, le cout et le cin ne sont pas acceptés :
error C2872: 'cout' : ambiguous symbol
error C2872: 'cin' : ambiguous symbol
Comment faire pour mettre le using namespace std; sans avoir les erreurs concernant le cout et le cin
cyberkate
Messages postés13Date d'inscriptionjeudi 21 avril 2005StatutMembreDernière intervention25 avril 2005 24 avril 2005 à 11:30
Oh je ne le prends pas mal. Cela me semblait bizarre de mettre autant de bibliothèques avec les mêmes noms, mais bon... lol
J'ai corrigé ce que tu m'as dit.
Je ne savais pas que c'était des pointeurs qui accédaient aux données (d'ailleurs, on le voit comment ??)
Sinon j'ai testé l'application : l'inscription dans le fichier se fait bien... par contre je n'arrive pas à relire les informations...
Y-a-t-il quelquechose qui ne va pas dans ma fonction chargeClient ??
Je ne sais pas si je remplis bien mon tableau tabClient et si je le lis bien...
Peux tu m'aider sur ce point ??
Merci beaucoup
Je te re-poste ma fonction chargeClient() au cas où...
monFichier = fopen("abonnements.txt", "r+"); //ouverture du fichier en lecture
if (monFichier == NULL)
{
cout << "Erreur d'ouverture du fichier Abonnements." << endl;
}
else
{
int i;
for (i=0;i<MAXIMUM;i++)
{
tmp = fread(&clientEnCours, sizeof(clientEnCours), 1, monFichier); // on lit une ligne par une ligne
if (!tmp) // si la ligne est vide
{
cout << "Erreur de lecture." << endl;
}
else
{
tabClient[i] = clientEnCours;
};
};
luhtor
Messages postés2023Date d'inscriptionmardi 24 septembre 2002StatutMembreDernière intervention28 juillet 20086 24 avril 2005 à 19:00
Est ce que tu peux reposter :) car la ca devient pénible d'accéder à ce post ^^
De mémoire pour ta question: c'est des pointeurs on le voit comment ?
Et bien c'est toi qui a définit ca comme ca:
un truc du genre:
Abonnements *abonnement[MAX] <===== ca c'est un tableau de pointeur.
Donc il contient que des pointeurs et quand tu y fais référence, c'est
un pointeur.