C++ Vokabeltrainer mit Klassen

lolorollo

Ensign
Registriert
Juli 2013
Beiträge
141
Hallo
Ich habe angefangen einen Vokabeltrainer zu schreiben. Ich habe eine Klasse write_read geschrieben, um die Vokabeln in eine Text Datei zu lesen und zu schreiben (einmal Lektionenweise und einmal werden in dem Vector alle Vokabeln gespeichert).
Aber ich mach mir die letzte Zeit Gedanken über guten C++ Stil :D .
Ist es besser die Funktionen zur Abfrage der Vokabeln in eine neue Klasse zu machen und von der Klasse write_read zu erben? Oder sollte ich besser die Funktionen in der Klasse write_read als Memberfunktionen hinzufügen? Oder soll ich die Funktionen lieber global deklarieren?

So sieht die Klasse im Moment aus:

Code:
#include <vector> 
#include <string> 
#include <fstream> 
  
class Read_Write 
{ 
    public: 
        void write(std::string& f, std::string& d, int unit);//um in eine Datei zu schreiben (unit für die Lektion, zu der die Vokabel gehört 
        void read();//liest alle Vokabeln aus der Datei in die vectoren 
        void read_unit(int unit);//liest nur die angegebene Lektion in die vectoren 
  
  
    private: 
        //Darin werden die Vokabeln gespeichert: 
        std::vector<std::string> fremdsprache; 
        std::vector<std::string> sprache; 
  
        std::fstream file;//um die datei zu öffnen und zu lesen 
  
};
 
Was ist denn bei der Klasse das Objekt?

Das sollte eigentlich die Vokabel sein. Also solltest Du eine Klasse "Vokabel" haben und in der sollten die Methoden read und write erscheinen.
 
Also wenn du es objektorientiert machen willst, würde ich eine Klasse zum Laden/Speichern der Vokabeln schreiben. Eine Vokabelklasse, wo Bedeutung und Übersetzung schön gekapselt sind und eine Containerklasse, die die einzelnen Instanzen von Vokabel enthält.

Insgesamt sieht es so aus, als würde bei dir die Zuständigkeit verschwimmen. Die eine Klasse ist nicht nur für Lesen/Schreiben, sondern anscheinend auch zum Speichern der Vokabeln (und das ohne dokumentierten Zusammenhang (1. Objekt Fremdsprache zu 1. Objekt Sprache, ja? Lieber mit pair() die beiden Sachen zusammenkleben und in einen Vector packen. Das wäre nicht 100%ig OO, aber schönes C++, sofern es wirklich nur bei den beiden Werten bleibt.)
Den Filestream würde ich vllt. auch eher als lokales Objekt in die write- bzw. read-Funktionen reinpacken.
 
Zuletzt bearbeitet:
Fortatus schrieb:
Also wenn du es objektorientiert machen willst, würde ich eine Klasse zum Laden/Speichern der Vokabeln schreiben. Eine Vokabelklasse, wo Bedeutung und Übersetzung schön gekapselt sind und eine Containerklasse, die die einzelnen Instanzen von Vokabel enthält.

Insgesamt sieht es so aus, als würde bei dir die Zuständigkeit verschwimmen. Die eine Klasse ist nicht nur für Lesen/Schreiben, sondern anscheinend auch zum Speichern der Vokabeln (und das ohne dokumentierten Zusammenhang (1. Objekt Fremdsprache zu 1. Objekt Sprache, ja? Lieber mit pair() die beiden Sachen zusammenkleben und in einen Vector packen. Das wäre nicht 100%ig OO, aber schönes C++, sofern es wirklich nur bei den beiden Werten bleibt.)
Den Filestream würde ich vllt. auch eher als lokales Objekt in die write- bzw. read-Funktionen reinpacken.

Vielen Dank :)
Also schreib ich eine Klasse Vokabel, die die Methoden abfragen() und abfragen_unit() bekommt und als private member die zwei vectoren hat (pair versteh ich nicht ganz ^^)
Dann schreib ich noch eine Klasse mit den Funktionen aus der Klasse Read_Write nur mit anderen Private Membern :)
Aber ich versteh nicht ganz was du mit der Containerklasse für die Instanzen von Vokabeln meinst...
 
Ich finde, Du solltest es erst mal einfach halten. Ich weiß, eine Klasse aufzudröseln ist nicht schön und Fleißarbeit aber Du solltest erst die Grundprinzipien verstehen.

Da reicht eine Klasse "Vokabeln" auf der Du die Instanzen erzeugst. Eventuell zwei Unterklassen (local/foreign) für Sprachen, wenn Du das nicht mit einem Attribut unterscheiden willst (kann man aber später noch machen).

Trotzdem ändert das nicht am Lesen und Speichern. Das ist Methoden der Oberklasse.
 
Also alle Methoden in die Klasse Vokabel rein?

Code:
#include <vector>
#include <string>
#include <fstream>

class Vokabel
{
	public:
		void write(std::string& f, std::string& d, int unit);//um in eine Datei zu schreiben (unit für die Lektion, zu der die Vokabel gehört
		void read();//liest alle Vokabeln aus der Datei in die vectoren
		void read_unit(int unit);//liest nur die angegebene Lektion in die vectoren
		void Abfragen_unit(int unit);
		void Abfragen();


	private:
		//Darin werden die Vokabeln gespeichert:
		std::vector<std::string> fremdsprache;
		std::vector<std::string> sprache;


};
 
Ähhh nein. Du brauchst sowas wie einen Vokabelkasten, der ein std::vector<Vokabel> ist, bzw. enthält.

Modelliere die Wirklichkeit!
 
Danke :)
habs jetzt so gelöst

Code:
class Vokabel 
{ 
  
    public: 
        //get Methoden 
        std::string getDeutsch() const; 
        std::string getSprache() const; 
  
        //Um Instanzen zu ändern 
        void setDeutsch(std::string& d); 
        void setSprache(std::string& s); 
  
  
    private: 
        std::string Deutsch; 
        std::string Sprache; 
  
  
  
}; 
  
  
//globale Funktionen 
//lesen und schreiben 
void read(); 
void write(Vokabel& V, int unit); 
void read_unit(int unit);
Ergänzung ()

edit:
so hab ich aber das Problem das ich nicht weiß, wie ich die Funktion read/read_unit implementieren soll...
Die Funktionen müssen ja immer nur eine Vokabel lesen und die einer Vokabel zuordnen. Dann muss die Funktion wissen wo sie stehen geblieben ist und die nächste Vokabel lesen...
 
Du könntest da alternativ auch auf ein
Code:
struct
oder
Code:
std::pair<std::string, std::string>
zurückgreifen - dann sparst Du dir da ne eigene Klassendefinition.
 
so hab ich aber das Problem das ich nicht weiß, wie ich die Funktion read/read_unit implementieren soll...
Die Funktionen müssen ja immer nur eine Vokabel lesen und die einer Vokabel zuordnen. Dann muss die Funktion wissen wo sie stehen geblieben ist und die nächste Vokabel lesen...

Du musst dir überlegen, wie du deine Daten so repräsentierst, dass du sie möglichst einfach wieder lesen kannst. Falls du das nicht zu Forschungszwecken selbst machen möchtest, musst du das Rad hier nicht neu erfinden, sondern kannst bereits vorhandene Formate nutzen. An dieser Stelle würde ich zwei Varianten ins Spiel bringen. Entweder die protobufs von Google oder JSON. Da du noch nicht so erfahren mit der Sprache bzw. Programmieren allgemein zu sein scheinst würde ich dir JSON ans Herz legen. Das ist in meinen Augen einfacher zu handhaben und man kann die entstandenen Dateien auch noch selbst lesen und verstehen. Ich hab dafür bisher jsoncpp genommen und das konnte alle meine Anforderungen bewältigen. Über die entsprechenden De- und Encoder kannst du somit sehr leicht aus deinen Objekten einen speicherbaren String und umgekehrt erstellen.

Deine Datei könnte dann beispielsweise so aussehen:
Code:
{
    "unit1": [
        {"dt": "haus", "en": "house"},
        {"dt": "tisch", "en": "table"},
        {"dt": "kiste", "en": "box"},
        {"dt": "fenster", "en": "window"}
    ],

    "unit2": [
        {"dt": "rennen", "en": "run"},
        {"dt": "laufen", "en": "walk"},
        {"dt": "essen", "en": "eat"},
        {"dt": "schlafen", "en": "sleep"}
    ]
}

Die Datei brauchst du dann nur wieder einlesen und den erhaltenen String über den mitgelieferten Parser wieder in ein Objekt umwandeln, über das du dann bequem auf deine Daten zugreifen kannst.
 
Zurück
Oben