2009-04-14 8 views
2

J'ai récemment découvert le mot-clé friend classes C++ et les utilisations en sérialisation et maintenant j'ai besoin d'aide pour le faire fonctionner.Sérialisation de classe C++

Je n'ai aucun problème à sérialiser ma classe dans un fichier, ça marche très bien, mais j'ai du mal à essayer de lire ce fichier dans un conteneur de vecteurs. Je suis sûr que j'ai besoin d'une boucle dans mon code qui lit ligne par ligne, mais comme la classe a des types différents je suppose que je ne peux pas utiliser std :: getline() et peut-être que cette approche n'utiliserait pas la méthode istream mis en œuvre? Un fichier de sortie de l'échantillon serait:

Person 1 
2009 
1 

Person 2 
2001 
0 

Mon code:

class SalesPeople { 
    friend ostream &operator<<(ostream &stream, SalesPeople salesppl); 
    friend istream &operator>>(istream &stream, SalesPeople &salesppl); 

    private: 
     string fullname; 
     int employeeID; 
     int startYear; 
     bool status; 
}; 

ostream &operator<<(ostream &stream, SalesPeople salesppl) 
{ 
    stream << salesppl.fullname << endl; 
    stream << salesppl.startYear << endl; 
    stream << salesppl.status << endl; 
    stream << endl; 
    return stream; 
} 

istream &operator>>(istream &stream, SalesPeople &salesppl) 
{ 
    stream >> salesppl.fullname; 
    stream >> salesppl.startYear; 
    stream >> salesppl.status; 
    // not sure how to read that empty extra line here ? 
    return stream; 
} 

// need some help here trying to read the file into a vector<SalesPeople> 
SalesPeople employee; 
vector<SalesPeople> employees; 

ifstream read("employees.dat", ios::in); 
if (!read) { 
    cerr << "Unable to open input file.\n"; 
    return 1; 
} 

// i am pretty sure i need a loop here and should go line by line 
// to read all the records, however the class has different 
// types and im not sure how to use the istream method here. 

read >> employee; 
employees.push_back(employee); 

D'ailleurs, je sais que la bibliothèque Boost a une grande classe de sérialisation, mais je suis en train d'apprendre comment sérialisation fonctionnerait en utilisant la bibliothèque STL pour le moment. Merci beaucoup d'avance pour toute aide que vous pouvez me donner et pour me mettre dans la bonne voie!

Répondre

2

Il semble que vous ayez déjà tout le code dont vous avez besoin! J'ai copié votre code et l'ai compilé avec quelques modifications pour lire le SalesPeople d'un fichier dans une boucle. Je vais inclure les changements ci-dessous, mais puisque c'est pour vos devoirs, vous voudrez peut-être juste lire et réfléchir sur les conseils suivants avant de regarder le code.

  • Pour lire la dans une boucle VENDEURS À , je vous recommande de prendre un coup d'oeil à ce FAQ. Il a un exemple de presque exactement ce dont vous avez besoin. FAQ 15.4 aidera également vous, je crois.

  • Pour votre question sur la façon de traiter la ligne supplémentaire vide lors de la lecture à partir du fichier, consultez cette link. Vous pouvez très simplement extraire les espaces blancs de cette façon.

  • Comme jfclavette suggéré, je serais recommande la recherche dans std::getline pour la lecture au nom de SalesPerson complète, puisque vous besoin de tout sur cette ligne en une seule chaîne .

J'ai une question à vous poser, cependant: qu'en est-il de l'ID employé? Je remarque qu'il est ignoré dans votre exemple de code. Est-ce exprès?

Et maintenant, si vous avez encore besoin d'aide, vous pouvez vérifier le code que j'ai écrit pour obtenir ce travail:

istream &operator>>(istream &stream, SalesPeople &salesppl) 
{ 
    //stream >> salesppl.fullname; 
    getline(stream, salesppl.fullname); 
    stream >> salesppl.startYear; 
    stream >> salesppl.status; 
    // not sure how to read that empty extra line here ? 
    stream >> ws; 
    return stream; 
} 

while(read >> employee) 
{ 
    // cout << employee; // to verify the input, uncomment this line 
    employees.push_back(employee); 
} 

En outre, comme jfclavette a suggéré, il ne peut pas être une mauvaise idée d'ajouter un peu validation de l'entrée (vérifiez l'état du flux après en avoir lu le contenu et vérifiez qu'il est toujours bon). Bien que je recommanderais d'utiliser la boucle while() pour les raisons indiquées dans FAQ 15.5.

+0

Merci beaucoup! Ça a beaucoup aidé! Maintenant, je comprends mieux ce que je faisais de mal. En outre, je n'avais aucune idée de ws, je me demandais comment faire cela depuis longtemps! Merci beaucoup! – nmuntz

+0

Pas de problème, content de pouvoir aider! – Venesectrix

1

Vous ne savez pas quel est votre problème. Qu'est-ce que tu ne comprends pas exactement? Le fait que vos noms soient composés de plusieurs jetons? Il n'y a pas de moyen magique de le faire, vous pourriez vouloir obtenir le nom getline(). Vous pouvez également spécifier le nombre de jetons lors de la sérialisation et lire le nombre de jetons approprié. Par exemple, votre fichier pourrait ressembler.

2 Personne 1

Je suppose que personne était le prénom et le nom de famille 1 ici. Vous pouvez également appliquer l'idée qu'il y a un prénom et un nom de famille et que vous lisez chacun séparément.

Vous effectuerez généralement une boucle while (! Ifstream.eof()) et lira. Bien sûr, vous devriez toujours valider les entrées.

En outre, pourquoi ajoutez-vous un endl supplémentaire entre chaque enregistrement? Les données sérialisées n'ont pas besoin d'être jolies. :)

Questions connexes