Computer Hardware Forum - TweakPC

Computer Hardware Forum - TweakPC (https://www.tweakpc.de/forum/)
-   Programmiersprachen (https://www.tweakpc.de/forum/programmiersprachen/)
-   -   [C++]Komplexe Datenstrukturen Speichern/laden (https://www.tweakpc.de/forum/programmiersprachen/74617-c-komplexe-datenstrukturen-speichern-laden.html)

Soman_X 18.01.2010 14:24

[C++]Komplexe Datenstrukturen Speichern/laden
 
Hallo zusammen!
Ich hoffe, hier an diese Stelle bin ich richtig mit meinem problem.... na ja ihc versuchs einfach mal :mrgreen:

Folgendes: Ich habe zu übungszwecken eine kleine Konsolenanwendung geschrieben, um beliebige Passwörter nach bestimmten kriterien (groß/Kleinschreibung, Ziffern) erstellen zu lassen.
Zum abspeichern dieser Passswörter nebst Namen habe ich eine eigene Klasse erstellt und diese in einen header gepackt:
[code]
#ifndef _password_h
#define _password_h

//-------------Klassendeklaration--------
class password
{
private:
string name;
string value;
unsigned int position;
static unsigned int ctr;

public:
password();
password(string name, string value);
~password();

void setName(string name);
void setValue(string value);
string getName(void);
string getValue(void);
unsigned int getPosition(void);
static unsigned int getCounter(void);

void print(void);
void killPw(void);
void changePw(void);

};
#endif
[/code]Die nähere Funktion des ganzen programms ist nicht weiter relevant.
Wichtig ist nur, dass im hauptprogramm ein Array aus Passwörtern als globale variable erstellt wird. Soweit funktioniert alles, ich kann Passwörter eingeben, auslesen, ändern etc.

jetzt möchte ich aber, quasi als I-Tüpfelchen die engegeben Passwörter in eine Datei speichern, die auch beim programmstart ausgelesen wird. Denn nur so macht das programm auch sinn :inflames:

ich habe schon diverse versuche hinter mir, aber ncihts hat bisher funktioniert. Kann mir jemand sagen, wie ich das sinnvoll in C++ löse?

Feanor 18.01.2010 21:47

AW: [C++]Komplexe Datenstrukturen Speichern/laden
 
Du könntest z.B. deine Klasse mit Methoden zum serialisieren/deserialisieren erweitern, z.B.:

[code]
password & deserialize(std::istream & stream);
std::ostream & serialize();
[/code]

Die Referenzen werden zwecks chaining zurückgegeben. Kannst natürlich auch nichts zurückgeben, bzw. bei der Deserialisierung einen Pointer, wenn dir das lieber ist.

Beim Serialisieren schreibste dann Variable für Variable in die Datei (bei den Datentypen aufpassen!). Am besten jeden Datentypen auf (char *) casten und mit der write/read-Methode von std::stream schreiben/lesen (nicht mit "<<" und ">>"). Als Größe "sizeof(<Datentyp>)" angeben:
[code]
out.write((char*)&password1, sizeof(password1));
[/code]
Beim Deserialisieren das ganze Spiel anders herum (new password().deserialize(stream)).
Alternativ bietet boost auch Methoden zur Serialisierung.

Das Deserialisieren kannste dann vor dem Schließen des Programms machen, das Serialisieren beim Starten des Programms.

Falls ich das Ganze etwas ausführlicher schildern soll oder ich etwas näher erklären soll, gib einfach Bescheid.

Soman_X 19.01.2010 08:08

AW: [C++]Komplexe Datenstrukturen Speichern/laden
 
Danke erstmal für die schnelle und kompetente antwort!:-D

Ich muss zu meiner schande gestehen, dass ich von serialize() und deserialize() noch nie gehört habe 8-O

Demzufolge wäre eine genauere erklärung sehr fein =)

Feanor 19.01.2010 17:02

AW: [C++]Komplexe Datenstrukturen Speichern/laden
 
Ist nichts kompliziertes. Eigentlich nur die Begrifflichkeit für das Persistieren von Objekten, sei es in Datenbanken, übers Netzwerk oder - wie in deinem Fall - in Dateien. Die Methodendefinition, solltest du eigentlich einfach so übernehmen können. Die Methoden musst du dann noch mit Leben füllen.
In "serialize" schreibst du deine Objekte (also die Membervariablen) in eine Datei (std::ostream, siehe [url=http://cplusplus.com/reference/iostream/ostream/]ostream - C++ Reference[/url]) mittels "write"-Funktion von "std::ostream" (wie in meinem ersten Beitrag beschrieben).
In "deserialize" liest du dann die Variablen wieder aus dem Stream (in der gleichen Reihenfolge), also:
[code]
(new password())->deserialize(in);
[/code]
Oder du gibst deiner password-Klasse eine statische deserialize-Funktion, die neue passwort-Objekte erstellt, quasi eine Factory.
Da neue Objekte auf dem Heap angelegt wurde, musst du diese auch wieder löschen, wenn du sie nicht mehr brauchst.
Wenn du Arrays oder Vektoren oder ähnliches auf diese Art persistieren willst, musst du dir natürlich was einfallen lassen, z.B. zuerst die Anzahl der Elemente in den Stream schreiben und danach die Elemente. Beim Auslesen kannst du dann die Anzahl rauslesen und in einer Schleife die Elemente wieder deserialisieren.

Du kannst auch statische "readValueFromStream(std::istream & in, T const & val)" und "writeValueToStream(std::ostream & out, T const & val)" Methoden in einer Helper-Klasse erstellen und diese templaten. Das spart dir einiges an Arbeit, solltest du an mehreren Stellen serialisieren.

Falls das soetwas wie eine Passwortverwaltung werden soll, dann sei gewarnt, denn die Werte werden nur binär in eine Datei geschrieben und sind nicht verschlüsselt. Darum müsstest du dich separat kümmern.

Probiers doch einfach mal aus und sobald du auf Probleme stößt, kannst du ja deinen Quelltext hier reinkopieren und ich/wir kann dir weiterhelfen.

Alternativ kannste das wie gesagt auch mit boost machen ([url=http://www.boost.org/]Boost C++ Libraries[/url]) oder natürlich mit xml (Stichwort Xerces), wenn du drauf stehst und gern mit Kanonen auf Spatzen schießt.

edit: Lass dich von den "const"s nicht durcheinanderbringen. Kann auch gut sein, dass ich sie falsch gemacht habe. Im Zweifelsfall kannst du sie einfach weglassen.

tele 19.01.2010 18:17

AW: [C++]Komplexe Datenstrukturen Speichern/laden
 
Serialisierung hat halt nur das Problem, dass bei einer Änderung am Code der zu serialisiernden Klasse, eventuell bereits serialisierte Klassen nicht mehr deserialisiert werden können.
Einfach ausgedrückt: Änderst du was am Code, kannst du eventuell gespeicherte Sachen net mehr laden.

Also macht man, wenn man davon nicht abhängig sein möchte entsprechende Speicher/Lademethoden.

d.h. die Klasse braucht eine Methode, welche ihre gesammten zu speichernden Attribute in das Zielformat (z.b. properties-file oder XML oder was eigenes oder ...) bringt.
Im Hauptprogramm ruft man dann eine Methode auf, welche
- den Kopf/Fuß des speicherformates erstellt (Datenbankverbindung, Datei erstellen, XML Document anlegen oder was auch immer)
- für alle Einträge in dem Array die jeweilige Speichermethode des Objektes aufruft
- das alles in das Zielformat schreibt.

Beim Laden wiederum musst du natürlich im Hauptprogramm die jeweiligen Teile für jedes Objekt auseinanderstückeln und jedes objekt sich selbst erstellen lassen (mit geeignetem Konstruktor oder entsprechenden Methoden)

Ich hab keine Ahnung von C++, aber in Java-Pseudo-Code würde das so aussehen:

fall: speichere als properties-file (Plain text im format "Name = Wert"

Zu Speichernde Klasse
[code]

class Container {
private String attribut1;
private String attribut2;

public String getSaveData(){
String ret = "#####\n attribut1 = "+attribut1+"\n attribut2 = "+attribut2";
return ret;
}

public static Container load(String LoadData){
Container self = new Container();

String[] splits = LoadData.split(" ")

self.attribut1 = splits[3];
self.attribut2 = splits[6];
return self;
}
}
[/code]

Hauptprogramm
[code]
public class MyPasswordProgramm{

public static Container[] passwords;

public static void main(String[] args){
if(args[0].equals("load")){
String fileContent = pseudoCodeToLoadStringFromFile("MyFile.txt");
String[] fileContentSplits = fileContent.split("#####");
passwords = new Container[fileContentSplits.length];
for(int i=0; i<fileContentSplits.length; i++){
Container currentPassword = Container.load(fileContentSplits[i]);
passwords[i] = currentPassword;
}
} else if(args[0].equals("save")) {
String content = "";
for(int i=0; i<passwords.length; i++){
content = content + password[i].getSaveData();
}
pseudoCodeToWritetoFile(content, "MyFile.txt");
}
}
}
[/code]

Soman_X 20.01.2010 08:04

AW: [C++]Komplexe Datenstrukturen Speichern/laden
 
@Feanor
Ja es soll ne Passwortverwaltung werden.
Dass der ganze Kram lesbar ist (fast) wie ein offenes Buch, das ist mir klar. Deswegen ist es ja auch nicht bzw nur bedingt für den praktischen gebrauch gedacht ;)
Es ist lediglich eine Art übungsaufgabe, die ich mir selbst gestellt habe, einfach um zu sehen a)wie weit meine C++ kenntnisse wirklich sind und b)wie sehr ich sie anhand von Praxis und Internethilfe noch erweitern kann.

Man hätte vllt dazusagen sollen, dass ich nur n kleiner doofer Azubi im ersten Lehrjahr bin und meine C++ Kenntnisse bisher nur in Eigenregie erhalten habe... bis auf den Billigkram, den ich aufm Informatonstechnischen BK gelernt habe... aber die Lehrer haben zum Teil schon die Backen aufgeblasen und hilflos mit den Schultern gezuckt, wenn ich ne technische Frage hatte... waren also nicht sehr hilfreich xD

Was die Kanonen und SPatzen angeht... mit XML hatte ich vor, mich im Frühjahr mal näher zu beschäftigen, wenns mein Ausbildungsplan auhc vorsieht^^

@tele
Dein pseudocode sagt mir jetzt so gar nichts. Das problem ist, es gibt in C++ keine container. Dazu braucht man die STL. und genau die hab ihc mir jetz mal besorgt^^

____
Im Moment bin ich grade dran, das ganze Ding nochmal neu anzufangen. Durch meine etwas Planlose herangehensweise sieht das Projekt mittlerweiel so aus wie mein Kleiderschrank...chaotisch:inflames:
Ich erstele jetzt 2 Klassen. wie bisher die (leciht abgewandelte) Passwortklasse und eine Organisationsklasse, die die Passwörter verwaltet. Statt Strings nutze ich jetzt char-arrays, um die größe im Speicher zu kennen. und n Anlehnung an tele's Code werde ich den ganzen Kram jetzt in ner Map bzw Hashmap speichern, um den Zugriff zu erleichtern... mal sehen was dabei rauskommt.

Das Abspeichern der Daten hat mittlerweile ganz gut über einfach read und writes funktioniert. probleme gab es nur mit den teils recht unterschiedlich langen Strings, aber das sollte in der neuen version mit den char[] umgangen werden :-D

Feanor 20.01.2010 08:24

AW: [C++]Komplexe Datenstrukturen Speichern/laden
 
Du kannst auch weiterhin Strings benutzen. Speichere wie schon beschrieben einfach zuerst die Länge in eine Datei und dann die Daten. Mit den Arrays haste dann das Größere Problem, da du die erst initialisieren musst (und das find ich immer ganz schön stressig, wenns nicht unbedingt sein muss). Außerdem speicherst du mehr Daten als wirklich nötig, z.B. wenn du dein char * mit Länge 20 anlegst, aber ein Passwort z.B. nur 8 Zeichen lang ist. Dabei speicherst du dann 12 unnötige Zeichen (zumindest mit meiner Methode).
Im Grunde genommen unterscheiden sich teles und meine Methode nur darin, dass bei mir die Attribute in Binärform in eine Datei geschrieben werden und bei ihm als Text. Wenns um offene Standards geht, dann ist binär natürlich böse, aber es ist um einiges performanter. Wenn man dann noch beachtet, dass es in Java schon vorgefertigte Methoden zum Arbeiten mit Property-Files u.ä. gibt und in C++ nicht, ist es einfacher die Daten binär zu persistieren. In Java würde ich definitiv teles Methode favorisieren.

tele 21.01.2010 21:37

AW: [C++]Komplexe Datenstrukturen Speichern/laden
 
"Container" war ein von mir frei erdachter Namen für die Klasse. du kannst das genausogut "Bumsfallera" nennen.

Es ist im Endeffekt eine Klasse mit Attributen/daten und methoden/funktionen.

Was ist daran nicht zu verstehen? Der Inhalt der attribute1 und attribute2 werden in einen String gespeichert, alle Strings aller dieser instanzierter Klasse in eine Datei.

ach ja, mit [URL="http://lmgtfy.com/?q=c%2B%2B+save+class+to+file"]ein wenig suchen[/URL] gibt es auch massenhaft beispiele dazu

DonSchado 28.01.2010 22:01

AW: [C++]Komplexe Datenstrukturen Speichern/laden
 
[quote=tele;660292]mit [URL="http://lmgtfy.com/?q=c%2B%2B+save+class+to+file"]ein wenig suchen[/URL][/quote]

Wie geil ist das denn?! :mrgreen:

Hab den Thread nicht genau verfolgt, aber reicht es dir nicht wenn du einfach nur ne Textdatei verwendest?
Okay, für ein Passwort vielleicht generell nicht sehr zu empfehlen, aber ich glaub darum geht es dir doch gar nicht oder?

Grüße

Soman_X 29.01.2010 07:25

AW: [C++]Komplexe Datenstrukturen Speichern/laden
 
Es wird auch in ne textdatei gespeichert. Das problem ist ja mittlerweile gelöst ;)

Es ging vielmehr darum, wie ich die Daten aus der Klasse in die textdatei und zurück bekomme ;)


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:22 Uhr.

Powered by vBulletin® Version 3.8.10 (Deutsch)
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
SEO by vBSEO 3.5.2 ©2010, Crawlability, Inc.