How can I save text files in a container using C++?

I'm having a problem with my program. I want to save a text file in my custom container, but I don't know what the problem is.

 #include <iostream> #include <filesystem> #include <vector> #include <string> #include <fstream> #include <algorithm> using namespace std; template <typename Template> class Container { private: Template* Eigenschaft1; size_t Größe; size_t Speichergröße; public: Container(size_t ContainerGröße = 10000) : Größe(0), Speichergröße(ContainerGröße) { Eigenschaft1 = new Template[Speichergröße]; } void Speichern(const Template& Wert) { for (int i = 0; i < Größe; i++) { Eigenschaft1[Größe++] = Wert; } } }; class Personal { private: string Name; string Position; int Alter; double Gehalt; public: Personal(); void Speicherung(string Name, string Position, int Alter, double Gehalt, Container<ofstream>& Container); void Ausgabe(); void Hinzufügen(Container<ofstream>& Container); }; Personal::Personal() { Name = Name; Position = Position; Alter = Alter; Gehalt = Gehalt; } void Personal::Speicherung(string Name, string Position, int Alter, double Gehalt, Container<ofstream>& Container) { string Entscheidung; ofstream Datei1("Datei.csv"); Datei1 << "Name: " << Name << endl; Datei1 << "Position" << Position << endl; Datei1 << "Alter: " << Alter << endl; Datei1 << "Gehalt: " << Gehalt << endl; cout << "M\u00F6chten sie die Person speichern: "; if (Entscheidung == "Ja") { Container.Speichern(Datei1); } else if (Entscheidung == "Nein") { } } void Personal::Ausgabe() { ifstream Datei1("Datei.csv"); getline(Datei1, Name); Datei1 >> Position; Datei1 >> Alter; Datei1 >> Gehalt; cout << "Name: " << Name << endl; cout << "Alter: " << Alter << endl; cout << "Beruf: " << Position << endl; cout << "Gehalt: " << Gehalt << endl; } void Personal::Hinzufügen(Container<ofstream>& Container) { Personal P; cout << "Bitte geben side den Namen ein: "; cin >> P.Name; cout << "Bitte geben sie den Beruf an: "; cin >> P.Position; cout << "Bitte geben sie das Alter der Person an: "; cin >> P.Alter; cout << "Bitte geben sie das Gehalt der Person an: "; cin >> P.Gehalt; Speicherung(P.Name, P.Position, P.Alter, P.Gehalt, Container); } template <typename T> int main() { string Passwort1 { "Erfolg1234" }; string Passwort2; Container<ofstream> Container; Personal P; int Entscheidung; cout << "Geben sie das Passwort ein: "; cin >> Passwort2; if (Passwort2 == Passwort1) { cout << "Wollen sie eine neue Position hinzufügen (1)" << endl; cout << "Wollen sie auf eine Position zugreifen (2)" << endl; cin >> Entscheidung; if (Entscheidung == 1) { P.Hinzufügen(Container); } else if (Entscheidung == 2) { P.Ausgabe(); } } else { cout << "Falsches Passwort" << endl; } }
(1 votes)
Loading...

Similar Posts

Subscribe
Notify of
1 Answer
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
regex9
1 year ago

In my opinion, there are several points in your code that are either measurable or in which the meaning must be questioned.

(1) In general, it would first be good to follow conventional conventions:

  • Variable and method names start with a small letter. In this way, they (in particular variables) can later be more easily distinguished from type names.
  • Special characters (such as ö, ü, ß) in identifiers should be avoided. Not every compiler accepts this directly. A reluctance like ö therefore usually against o exchanged, one ü against u a ß against S .
  • Some of your variables do not have a well selected name (eg Property1 – the field should represent an array where the name does not indicate.
  • When defining interface and implementation, I would choose a uniform solution, because that makes a project more manageable. Either you participate consistently in header and implementation file (Container.h, Container.cpp, Personal.h, Personal.cpp, main.cpp) or you always connect interface and implementation as you do with the Containers – Class did.

2) A few specific code lines I would like to address:

(a) The assignments in your Staff – Constructors don't make sense.

 Personal::Personal() { Name = Name; Position = Position; /* etc. */ }

On the left and right you have the same variable. So you overwrite each field with yourself.

It would make more sense if you had a construct that fills your fields with parameters.

Example:

 class Personal { private: string _name; int _alter; public: Personal(const string& name, const int alter) : _name(name), _alter(alter) { } }; // invocation example: Personal person("Lena", 22);

The underscores before the field names are just a common convention to identify private fields. The values ​​are set via an initialization list. Alternatively, such a design definition would also be possible:

 Personal(const string& name, const int alter) { _alter = alter; _name = name; }

(b) In Add to cart -Method does not need new Staff -Instance to be created. Instead, you can use the instance to which the method is already bound.

 void Personal::hinzufuegen(Container & container) { cout << "Bitte geben Sie den Namen ein: "; cin >> _name; cout << "Bitte geben Sie das Alter der Person an: "; cin >> _alter; /* etc. */ speichern(container); }

Consequently, the data do not need to be explicitly Save because this method is bound to the same object and can therefore access the same states.

 void Personal::speichern(Container & container) { ofstream datei("Datei.csv"); datei << "Name: " << _name << endl; datei << "Alter: " << _alter << endl; /* etc. */ }

(c) It is better to declare variables only in the access area where they are actually used. In your main -Method, for example, introduce several variables, although they would only be required if certain conditions occur.

 int main() { string passwort { "Erfolg1234" }; string passwortEingabe; cout << "Geben Sie das Passwort ein: "; cin >> passwortEingabe; if (passwort == passwortEingabe) { cout << "Wollen sie eine neue Position hinzufügen (1)" << endl; cout << "Wollen sie auf eine Position zugreifen (2)" << endl; int entscheidung; cin >> entscheidung; Personal person; if (entscheidung == 1) { Container container; person.hinzufuegen(container); } else if (entscheidung == 2) { person.ausgabe(); } /* etc. */

In this way, your program code can also become clearer. On the one hand, it is possible to combine (initialization) one line from time to time with declaration and definition, and it is faster when unused variables are declared. On the other hand, variables can be assigned to their respective context more quickly: if you want to see where eg Decision the search area is reduced. In my above snippet only the if – To be considered hull. For your code, it should be assumed first that the variable in the whole main -Function is intended.

(d) In C++ there are own container classes for arrays or lists. There is no reason to work with C arrays or pointers instead.

Example:

 #include #include #include class Dog { public: std::string name; Dog() {} Dog(const std::string& name) : name(name) {} }; // main: std::array dogs; Dog pongo("Pongo"); dogs[0] = pongo; std::cout << dogs[0].name << std::endl; std::vector dogList(10); Dog perdita("Perdita"); dogList[0] = perdita; std::cout << dogList[0].name << std::endl;

As usual, arrays have a statically fixed size. In contrast, the std::vector -Type a dynamic list. In the example, the latter has been assigned an initial size. For the annexing of new elements (outside the reserved space), push-back method used.

(e) The main -Function cannot be a template.

There is also a lack of specific return. C++ can also handle this implicitly, safer (in terms of functionality on different target platforms) is however an explicit return.

 return 0;

In stdlib as an alternative own macros .

(f) With your loop, you compare values ​​with different data types.

 for (int i = 0; i < Größe; i++) {

The field has the type size_t while i is an int . Better use only one type ( size_t ).

 for (size_t i = 0; i < groesse; ++i) {

3) You obviously want to image personal data that can be stored in a file and read out again via your program. There is therefore a model class ( Staff ) and a serializer ( Containers ). Last class I would name differently (more clearly) (eg Staff Administrator ) and it would be good to equip both classes only with the respective properties/methods that are actually relevant to them.

The model class only serves for pure data storage. So she only holds the fields for name, age, etc.

 class Personal { private: string _name; string _position; int _alter; double _gehalt; public: Personal() { } Personal(const string& name, const string& position, const int alter, const double gehalt) : _name(name), _position(position), _alter(alter), _gehalt(gehalt) { } const string& gibName() const { return _name; } int gibAlter() const { return _alter; } void setzeName(const string& name) { _name = name; } void setzeAlter(const int alter) { _alter = alter; } /* etc. ... */ };

All about administration (storing and reading) is, on the other hand, exclusively part of the administrator class.

 class PersonalVerwalter { private: string _dateiname; public: PersonalVerwalter() { _dateiname = "Datei.text"; } Personal* liesPersonaldaten() { ifstream datei(_dateiname); if (!datei.is_open()) { return nullptr; } Personal* person = new Personal(); /* read lines into Personal object ... */ datei.close(); return person; } void speicherePersonaldaten(const Personal& person) { ofstream datei(_dateiname); if (!datei.is_open()) { return; } /* append data to stream ... */ datei.close(); } };

With regard to the data format, I would think again. On the one hand, I would only save the pure data (without labeling), otherwise you need to see that when you read it, you will cut the label back from the value. If each property is written in a separate line, you do not need a CSV format. This would be more worthwhile if you really structured accordingly, for example:

 Name,Position,Alter,Gehalt Timon,Manager,38,50000

Such a format would also be well suited if you want to save several people in the file (each line reflects the data of a personal entity).

When reading the file, you would have to ignore the first line (header) and separate the other lines using the comma (eg via sstream ).

All that concerns the reading of the data from the console and the output would be better saved in a separate function, which is main is called later.

 void speicherePersonal(PersonalVerwalter& verwalter) { string sollSpeichern; cout << "M\u00F6chten sie die Person speichern: " << endl; if (sollSpeichern == "Ja") { string name; cout << "Bitte geben Sie den Namen ein: "; cin >> name; /* etc. ... */ Personal person(name, position, alter, gehalt); verwalter.speicherePersonaldaten(person); } /* etc. ... */ } void gibPersonalDatenAus(PersonalVerwalter& verwalter) { Personal* person = verwalter.liesPersonaldaten(); if (!person) { return; } cout << "Name: " << person->gibName() << endl; /* etc. ... */ }

This clear functional separation ensures more flexibility (the model class could still be used for other cases without having a dependency on any stream) and overview (the code is logically structured).