|
JLI Spieleprogrammierung
|
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen |
Autor |
Nachricht |
mrxcptn Mini JLI'ler
Alter: 49 Anmeldedatum: 02.06.2008 Beiträge: 12
Medaillen: Keine
|
Verfasst am: 22.12.2008, 22:08 Titel: Dateiverarbeitung und STL Versuche |
|
|
Hallo an alle,
Ich hab mich mit dem Beginn der Weihnachtsferien mal wieder an den PC gesetzt, und nachdem ich nun endlich ein laufendes System habe, auch meine Programmierbücher hervorgekramt.
Mein erstes Projekt war zum lernen, wiederholen, vertiefen usw. vom Arbeiten mit Dateien gedacht, doch so weit muss man erst einmal kommen.
Ich habe angefangen mit einer header-Datei mit der Klassendefinition für eine Art Personenverzeichnis:
CPP: | #include <string>
using namespace std;
class cPerson //Erstellung der Klasse cPerson(Personenverzeichnis)
{
public:
cPerson()//<-standardkonstruktur v_v weitere Konstruktoren
{
bWeiblich = false;
sVorname = "Linus";
sNachname = "Torvalds"; //Kleines Easteregg..
sVorwahl = "01234";
sNummer="56789";
sWohnort="Finnland";
sGeburtsdatum="28121969";
}
cPerson(bool Weiblich, string Vorname, string Nachname, string Vorwahl, string Nummer, string Wohnort, string Geburtsdatum)
{
bWeiblich = Weiblich;
sVorname = Vorname;
sNachname = Nachname;
sVorwahl = Vorwahl;
sNummer = Nummer;
sWohnort = Wohnort;
sGeburtsdatum = Geburtsdatum;
}
cPerson(bool Weiblich, string Vorname, string Nachname)
{
bWeiblich = Weiblich;
sVorname = Vorname;
sNachname = Nachname;
}
cPerson(bool Weiblich, string Vorname, string Nachname, string Vorwahl, string Nummer)
{
bWeiblich = Weiblich;
sVorname = Vorname;
sNachname = Nachname;
sVorwahl = Vorwahl;
sNummer = Nummer;
}
protected:
bool bWeiblich;
string sVorname;
string sNachname;
string sVorwahl;//Erstellung der Notwendigen Werte
string sNummer;
string sWohnort;
string sGeburtsdatum;
}; |
Die Daten dieser Klasse wollte ich dann in eine Binärdatei speichern.
Beim Blättern durch meine Bücher ist mir dann die Idee gekommen, was ich mache wenn ich mich vertippt habe und einen speziellen Wert eines Objekts dieser Klasse ändern will.
Da ich keine komplette verkettete Liste handschreiben wollte, hab ich testweise ein neues Projekt mit etwa dem gleichen Aufbau erstellt und wollte dort einzelne Objekte in einer "list" aus der STL einfügen.
Die Header-datei:
CPP: | #include <string>
using namespace std;
class Mensch
{
public:
Mensch()
{
sName = "Standard";
iAlter = 99;
}
Mensch(string Name, int Alter)
{
sName = Name;
iAlter = Alter;
cout << "Der Mensch " << sName.c_str() << " ist " << iAlter << " Jahre alt.\n";
}
string sName;
int iAlter;
} |
Ich Schlaumeier bin während ich das hier getippt habe draufgekommen, dass ich für push_back() als Wert ja ein Objekt der Klasse nennen muss, weil das ja nicht den Konstruktor aufruft:
Zitat: | Und die Main-Datei:
CPP: | #include <iostream>
#include "Klassen.h"
#include <list>
#include <string>
using namespace std;
list<Mensch> MenschListe;
int main()
{
MenschListe.push_back("Horst",25);
MenschListe.push_front("Georg",32);
MenschListe.push_back("Karl",34);
MenschListe.push_back("Hans",21);
MenschListe.push_back("Fred",18);
} |
Beim Build-Vorgang kommt folgender Fehler:
Zitat: | ..\main.cpp|12|error: no matching function for call to `std::list<Mensch, std::allocator<Mensch> >::push_back(const char[6], int)' |
Der fehler taucht 5 Mal auf, für jeden "Menschen" den ich in die Liste einfügen will. |
Aber aus diesem Fehler lerne ich hoffentlich...
Trotzdem kommt noch ein Fehler: Zitat: |
..\functexcept.h|36|error: expected unqualified-id before "namespace"| |
Ich verwende CodeBlocks mit MinGW auf Windows XP SP2.
Zuletzt bearbeitet von mrxcptn am 23.12.2008, 22:58, insgesamt 3-mal bearbeitet |
|
Nach oben |
|
|
mrxcptn Mini JLI'ler
Alter: 49 Anmeldedatum: 02.06.2008 Beiträge: 12
Medaillen: Keine
|
Verfasst am: 22.12.2008, 22:14 Titel: |
|
|
Und der zweite Fehler ist auch gefunden... ein fehlendes Semikolon nach der Klassendefinition in der Headerdatei:
CPP: | #include <string>
using namespace std;
class Mensch
{
public:
Mensch()
{
sName = "Standard";
iAlter = 99;
}
Mensch(string Name, int Alter)
{
sName = Name;
iAlter = Alter;
cout << "Der Mensch " << sName.c_str() << " ist " << iAlter << " Jahre alt.\n";
}
string sName;
int iAlter;
};//Kleines Biest!! |
Da ich aber sicher noch einige Fehler machen werde hats nicht geschadet den Thread aufzumachen.
Für ein bisschen Kritik an meinem Programmierstil und Verbesserungsvorschläge wäre ich dankbar.
Edit: Damit hier nicht gleich 15 Posts von mir sind editiere ich jetzt hier rein.
Ich bin eindeutig übermüdet, war wohl doch ne lange Nacht gestern..
Ich hab eine lokale Variable initialisiert und ausgegeben, anstatt die bereits vorhandene zu ändern. Warum der Compiler sich da nicht wegen Doppelbenutzung oder sowas aufregt ist mir zwar schleierhaft, aber ich hab das Problem gefunden.
Zitat: | Also:
Main-Funktion: CPP: | #include <iostream>
#include "Klassen.h"
#include <list>
#include <string>
using namespace std;
list<Mensch> MenschListe;
list<Mensch>::iterator MenschIndex;
int main()
{
MenschListe.push_back(Mensch("Horst",25));
MenschListe.push_front(Mensch("Georg",32));
MenschListe.push_back(Mensch("Karl",34));
MenschListe.push_back(Mensch("Hans",21));
MenschListe.push_back(Mensch("Fred",18));
MenschListe.push_back(Mensch());
MenschIndex=MenschListe.begin();
MenschIndex++;
MenschIndex->Nameaendern("Unbekannt");
(*MenschIndex).Wieheisstdu();
return 0;
} |
Klassen.h:
CPP: | #include <string>
using namespace std;
class Mensch
{
public:
Mensch()
{
sName = "Standard";
iAlter = 99;
}
Mensch(string Name, int Alter)
{
sName = Name;
iAlter = Alter;
cout << "Der Mensch " << sName.c_str() << " ist " << iAlter << " Jahre alt.\n";
}
void Nameaendern(string Name)
{
cout << sName << " heisst jetzt ";
/*string */sName = Name; //Da war der Fehler
cout << sName << '\n';
}
void Wieheisstdu()
{
cout << "Die ausgesuchte Person ist " << sName << '\n';
}
string sName;
int iAlter;
};
|
Der Fehler passiert bei der Ausführung von "MenschIndex->Nameaendern("Unbekannt");"
weil im Ausgabefenster nach "MenschIndex->Wieheisstdu();"
Immer noch der alte Name und nicht Unbekannt ausgegeben wird.
Kann ich in einer Liste nicht einzelne Werte einzelner Listenelemente anpassen oder hab ich nur irgendeinen Fehler bei der Funktion Nameaendern eingebaut?
Bitte um Hilfe. Danke. |
Edit2:
So, nach reiflicher Überlegung wollte ich diese list direkt in der Header-Datei erstellen.
Geht leider nicht, , ich kann nicht einfach unter der Klassendefinition oder auch in der Klasse eine list mit der Klasse Mensch erstellen, der Compiler meldet, dass laut ISO C++ eine list nicht ohne Typ erstellt werden darf.
Wenn jemand mir das erklären kann, bitte ich darum. Und was anderes:
Wäre es sinnvoll ein Template für diese Klasse Mensch zu erstellen und darin eine list UND einen vector mit Menschen zu haben, um das ganze auf zwei Arten ansprechen zu können oder wäre das unnötiger Code?
P.S.: Langsam wird das peinlich mit mir.. :oops:
Zuletzt bearbeitet von mrxcptn am 23.12.2008, 17:32, insgesamt einmal bearbeitet |
|
Nach oben |
|
|
Jonathan_Klein Living Legend
Alter: 37 Anmeldedatum: 17.02.2003 Beiträge: 3433 Wohnort: Siegerland Medaillen: Keine
|
Verfasst am: 22.12.2008, 23:53 Titel: |
|
|
Erstens: CPP Tags verwenden
Zweitens: Das mit den Überdecken ist normal, wenn du in einem {} Block eine Variable nochmal deklarierst, wird immer diese Angesprochen und nicht die aus einen eventuell Übergeordneten Block.
Drittens: Vielleicht kennt er "Mensch" an dieser Stelle noch gar nicht, zeig mal Quellcode.
Viertens: Zwei Container, die das selbe speichern sind eigentlich eine dumme Idee. Doppelter Speicherverbrauch und beim ändern müssen immer beide geändert werden, das ist sehr schlecht. Einer der beiden könnte natürlich Zeiger enthalten, dann hättest du nur noch Probleme, wenn ein Element gelöscht oder hinzugefügt werden soll.
Überleg dir lieber, was es für Container gibt, und was ihre stärken/schwächen sind und nehme dann den besten. _________________ https://jonathank.de/games/ |
|
Nach oben |
|
|
mrxcptn Mini JLI'ler
Alter: 49 Anmeldedatum: 02.06.2008 Beiträge: 12
Medaillen: Keine
|
Verfasst am: 23.12.2008, 22:54 Titel: |
|
|
Danke erstmal für deine Hilfe, ich hab in der Zwischenzeit schon ein wenig weitergebastelt und mir stellen sich schon wieder neue Fragen.
Hier erst einmal mein Code:
Main.cpp
CPP: | #include <iostream>
#include "Klassen.h"
#include <list>
#include <string>
#include <fstream>
using namespace std;
string Dateiverzeichnis = "d:\\textfile.txt";
int main()
{
cout << i << '\n';
Mensch a;
Mensch f("Fred",18);
Mensch g("Georg",32);
Mensch h("Horst",25);
Mensch j("Johann",21);
Mensch k("Karl",34);
MenschVektor.reserve(5);
MenschVektor[0] = &f;
MenschVektor[0]->Nameausgeben();
MenschVektor[1] = &g;
MenschVektor[1]->Nameausgeben();
MenschVektor[2] = &h;
MenschVektor[2]->Nameausgeben();
MenschVektor[3] = &j;
MenschVektor[3]->Nameausgeben();
MenschVektor[4] = &k;
MenschVektor[4]->Nameausgeben();
MenschVektor[3]->Menschspeichern(Dateiverzeichnis);
cout << Dateiverzeichnis.c_str() << '\n';
system("PAUSE");
return 0;
} |
Klassen.h
CPP: | #include <string>
#include <list>
#include <vector>
#include <fstream>
using namespace std;
class Mensch
{
public:
Mensch()
{
sName = "Standard";
iAlter = 99;
cout << "Ein Standardmensch mit dem Alter 99 wurde erschaffen." << '\n';
}
Mensch(string Name, int Alter)
{
sName = Name;
iAlter = Alter;
cout << "Der Mensch " << sName.c_str() << " ist " << iAlter << " Jahre alt.\n";
}
void Nameaendern(string Name)
{
cout << sName << " heisst jetzt ";
sName = Name;
cout << sName << ".\n";
}
void Nameausgeben()
{
cout << "Die ausgesuchte Person ist " << sName << ".\n";
}
void Menschspeichern(string Dateiname)
{
fstream Datei(Dateiname.c_str(), ios::out | ios::ate);
if(Datei.good())
{
int Namenlaenge = sName.length();
Datei << Namenlaenge << ";" << sName << ";" << iAlter << ";\n";
}
else
{
cout << "Datei konnte nicht geoeffnet werden\n";
Datei.clear();
}
Datei.close();
}
protected:
string sName;
int iAlter;
};
int i = 124;
vector<Mensch*> MenschVektor; |
Und jetzt meine Fragen.
1. Wie kann ich eine relative Pfadangabe geben, z.B. zur .exe Datei, geht das überhaupt?
2. Wie kann ich Leerzeichen in Pfadnamen verwenden, das hat bei einem meiner Versuche immer nur dazu geführt, dass er den else Zweig aufruft, weil der die Datei scheinbar nicht öffnen kann. Ich habs auch schon mit Pfadangaben wie "\"h:\\\\Programmieren\\\\Eigene Projekte\\\\textdatei.txt\"" versucht, aber ohne Erfolg.
3. Wie bringe ich ihn dazu, an eine Textdatei anzuhängen oder sie zu erstellen falls sie noch nicht existiert?
P.S.: Ich habe deinen Rat befolgt und bin zu dem Ergebnis gekommen, dass in meinem Fall ein Vektor besser passt.
Und das mit der in der Headerdatei erstellten Liste funktioniert plötzlich ohne Probleme..
Ich werd jetzt einmal so weiterbasteln ohne am Pfad rumzupfuschen und wenn sich neue Fragen aufwerfen, kommen die auch direkt per Edit hier dazu. |
|
Nach oben |
|
|
xardias JLI Master
Alter: 38 Anmeldedatum: 28.12.2003 Beiträge: 804 Wohnort: Palo Alto, CA Medaillen: Keine
|
Verfasst am: 23.12.2008, 23:20 Titel: |
|
|
zu 1: Die Pfade sind immer relativ zum Arbeitsverzeichnis. Das ist in Visual Studio meist der Projektordner glaube ich. Und sonst der Ordner in dem die xe aufgerufen wurde.
zu 2: "\"Mein Ordner\\Mit Leerzeichen.txt\"" sollte es eigentlich tun.
zu 3: ios::app statt ios::out |
|
Nach oben |
|
|
mrxcptn Mini JLI'ler
Alter: 49 Anmeldedatum: 02.06.2008 Beiträge: 12
Medaillen: Keine
|
Verfasst am: 24.12.2008, 00:08 Titel: |
|
|
Okay, ich hab das jetzt alles probiert. Relative Pfade funktionieren, auch mit Leerzeichen, sogar ohne \" davor und danach.
Edit: Funktioniert mit fstream file(Dateiname.c_str(), ios::out|ios::app);
Danke!
Jetzt gehts mit Binärdateien weiter.. |
|
Nach oben |
|
|
|
|
Du kannst keine Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum nicht antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen.
|
Powered by phpBB © 2001, 2005 phpBB Group Deutsche Übersetzung von phpBB.de
|