Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden.
Du solltest ein Upgrade durchführen oder einen alternativen Browser verwenden.
Du solltest ein Upgrade durchführen oder einen alternativen Browser verwenden.
[C++] Problem mit überladener Member-Funktion
- Ersteller daemon777
- Erstellt am
delete[] feld1;
Ausserdem folgender Vorschlag:
Ausserdem stelle ich mal die Frage, ob es notwendig ist auf einen Schlag soviel Speicher zu reservieren? Ressourcensparender wäre es nur dann Speicher zu reservieren wenn er auch benötigt wird.
MfG
Arnd
Ausserdem folgender Vorschlag:
Code:
#ifndef _karte_
#define _karte_
#include <string>
#define SIZE_OF_KARTE 1000
class karte
{
private:
std::string dateiname;
std::string levelname;
char** feld1;
public:
inline karte();
inline ~karte();
};
inline karte::karte()
{
feld1 = new char* [SIZE_OF_KARTE];
if( feld1 )
for (int i=0; i<SIZE_OF_KARTE; i++)
feld1[i] = new char [SIZE_OF_KARTE];
};
inline karte::~karte()
{
if( feld1)
for (int i=0; i<SIZE_OF_KARTE; i++)
delete[] feld1[i]
delete[] feld1;
feld1 = NULL;
};
#endif
Ausserdem stelle ich mal die Frage, ob es notwendig ist auf einen Schlag soviel Speicher zu reservieren? Ressourcensparender wäre es nur dann Speicher zu reservieren wenn er auch benötigt wird.
MfG
Arnd
Zuletzt bearbeitet:
- Registriert
- Dez. 2003
- Beiträge
- 1.371
Danke an euch alle. Ich wüsst nicht wie ich das ohne euch hätte lösen können.
Das mit dem Speicher muss glaub ich so sein. Jedenfalls fällt mir keine andere vernünftige Lösung ein. Einzige alternative währe dass ich während der Laufzeit immer wieder auf eine Datei auf der festplatte öffnen würde, zur richigen Stelle springen, auslesen usw. Da denke ich ist das so doch praktischer.
Das mit dem Speicher muss glaub ich so sein. Jedenfalls fällt mir keine andere vernünftige Lösung ein. Einzige alternative währe dass ich während der Laufzeit immer wieder auf eine Datei auf der festplatte öffnen würde, zur richigen Stelle springen, auslesen usw. Da denke ich ist das so doch praktischer.
Das das so praktischer ist, ist schon klar. Solange Du genügend Speicher hast, keine Rücksicht auf andere Anwendungen nehmen musst, etc .. kann man so auch programmieren. Bei diesem Ansatz muss man einfach weniger denken und planen :-).
Ich weiss ja nicht wieviele Dateien Du hast und kenne auch deren Inhalt nicht.
Ich halte es aber für ziemlich unwahrscheinlich das diese Datei oder Dateien immer genau 1000 Bytes lang sind?
Wenn es eine Datei ist, und Du jetzt pro Zeile einen new mit 1000 Bytes machst, dann ist das ziemlicher Overkill.
Mal abgesehen davon das eine Zeile ja auch mal länger als 1000 Bytes einkann.
Ebenso ist es doch auch unwahrscheinlöich das es 1000 Dateien sind deren Inhalt immer genau 1000 Bytes beträgt.
Die Grösse einer Datei kann man bestimmen und dann einfach das new daran anpassen.
MfG
Arnd
Ich weiss ja nicht wieviele Dateien Du hast und kenne auch deren Inhalt nicht.
Ich halte es aber für ziemlich unwahrscheinlich das diese Datei oder Dateien immer genau 1000 Bytes lang sind?
Wenn es eine Datei ist, und Du jetzt pro Zeile einen new mit 1000 Bytes machst, dann ist das ziemlicher Overkill.
Mal abgesehen davon das eine Zeile ja auch mal länger als 1000 Bytes einkann.
Ebenso ist es doch auch unwahrscheinlöich das es 1000 Dateien sind deren Inhalt immer genau 1000 Bytes beträgt.
Die Grösse einer Datei kann man bestimmen und dann einfach das new daran anpassen.
MfG
Arnd
Zuletzt bearbeitet:
7H3 N4C3R
Lt. Commander
- Registriert
- Feb. 2002
- Beiträge
- 1.816
Arnd schrieb:Ausserdem folgender Vorschlag: [...]
Folgender Gegenvorschlag von mir
Das #define würde ich unbedingt durch eine Konstante ersetzen.
Code:
const std::size_t SIZE_OF_KARTE 1000;
Genau deshalb gibt es Konstanten, die man auch entsprechend einsetzen sollte. Der Typ std::size_t sollte immer grundsätzlich dann eingesetzt werden, wenn es z.B. um Speicherallokierung geht. Er ist von Natur aus vorzeichenlos und minimiert so die Gefahr, dass man negative Werte an den Operator new übergibt. Er hat auch bereits die richtige Größe und wird vor dem Aufruf von new nicht nochmal implizit umgewandelt.
Eine Prüfung auf 0 nach Aufruf des operator new überflüssig. Der Standard garantiert, dass new einen gültigen Zeiger zurückgibt oder eine Exception wirft. Will man das unbedingt nicht, muss man ein new (std::no_throw) ... aufrufen.
Die Verwendung von NULL anstatt 0 ist in C++ nach seinem Erfinder Bjarne Stroustrup unschön. Es verschleiert nur, dass NULL einfach nur ein int mit dem Wert 0 ist und erweckt den Eindruck, ein 0-Zeiger wäre irgendeine magische Konstante. Außerdem trifft die oben beschriebene Problematik zu.
Und das 0-setzen von Werten im Destruktor wird allgemeinhin als überflüssig angesehen (im Gegensatz zum 0-setzen in Methoden in Funktionen und Methoden, was gut ist), weil es eh die letzen Atemzüge des Objektes sind und die Zuweisung schlichweg überflüssig.
Hallo 7H3 N4C3R,
bei dem define kein Widerspruch.
Bzgl. der Abfrage auf 0 lasse ich mich so schnell nicht von abbringen, aber die Diskussion hatte wir hier schon mal.
Fakt ist doch trotzdem, das es üblich ist normalerweise überhaupt keine Pointer abzufragen und schon gar nicht ein funktionierendes Exceptionhandling aufzubauen.
Das die Abfrage an sich an der Stelle etwas überflüssig ist mag sein, sollte wirklich 0 zurückkommen ist mit Sicherheit etwas oberfaul und der Rest des Programms wird dann sicher auch nicht laufen.
Aber: Zum einen halte ich es für sinnvoll das ein Programm fehlerresistent ist und auch bei unsinnigen Eingabewerte nicht einfach abstürzt. Dazu gehört eine korrekte Fehlerbehandlung (das können ifs oder exceptions sein).
Der Vorteil ist aber das ich an jeder Stelle meines Programms, z.B zu Debugzwecken oder Fehlersuche oder im Zuge von Testszenarien einfach einen Pointer auf 0 setzen kann ohne noch weiter Code an anderen Stellen ändern zu müssen und das Programm läuft ohne
Absturz weiter. Nur die Funktionalität wird eben nicht ausgeführt.
Wenn das if fehlt muss ich es im Zuge von Testszenarien hinzzufügen um einen Absturz zu vermeiden.
Ich halte es einfach für sinnvoll diesen Ansatz prinzipiell ohne Ausnahmen zu machen. Das minimiert die Fehlermöglichkeiten. Nimm mal als Beispiel die Formulierung "if( 0 == lVar )", das ist genauso eine Formulierung um Schreibfehler zu minimieren.
Mein Ansatz oder eben Anspruch ist einfach das ich eine beliebige Methode aus meinem Programm herausnehmen kann und diese mit allen möglichen Eingabewerten füttern kann, ohne das dann das Programm abstürzt.
Das ich in Destruktoren die Variablenwerte auch auf 0 setze, hat auch seinen Grund. Es kann eine gute Hilfestellung bei der Fehlersuche sein. Es gibt Fälle in denen ich dann entscheiden kann ob auf einem Pointer schon der Destruktor aufgerufen wurde, oder ob der Pointer einfach nur in die Pampa zeigt. Durch die Zuweisung wird schliesslich trotzdem der benutzte Speicher auf 0 gesetzt, was sonst nicht der Fall wäre und das kann manchmal helfen.
Und bzgl. Standard, wer garantiert denn das der Compiler auf dem ich gerade arbeite sich an den Standard hält? Und was glaubst Du was der Kunde sagt, wenn ich dem sage das mein Compiler sich nicht an den Standard hält und mich daher leider keine Schuld trifft?
Ich arbeite z.B. mit dem Microtec C++ Compiler und habe keine Ahnung ob der sich an Standards hält. Er verhält sich in Teilen auf jeden anders als der MS Compiler.
Daher ist mein Grundsatz einfach, verwende keinen Pointer ohne ihn vorher nicht auch auf 0abgefragt zu haben.
Sollte es auf Geschwindigkeit ankommen und jede Codezeile zählen, rücke ich davon vielleicht auch mal ab in dem ich bestimmte implizite Annahmen treffe.
D.h. vieles von dem was ich mache basiert auf meiner persönlichen Erfahrung. Und unter Windows ist die Fehlersuche leider oft genug die Hälfte der Arbeit.
MfG
Arnd
bei dem define kein Widerspruch.
Bzgl. der Abfrage auf 0 lasse ich mich so schnell nicht von abbringen, aber die Diskussion hatte wir hier schon mal.
Fakt ist doch trotzdem, das es üblich ist normalerweise überhaupt keine Pointer abzufragen und schon gar nicht ein funktionierendes Exceptionhandling aufzubauen.
Das die Abfrage an sich an der Stelle etwas überflüssig ist mag sein, sollte wirklich 0 zurückkommen ist mit Sicherheit etwas oberfaul und der Rest des Programms wird dann sicher auch nicht laufen.
Aber: Zum einen halte ich es für sinnvoll das ein Programm fehlerresistent ist und auch bei unsinnigen Eingabewerte nicht einfach abstürzt. Dazu gehört eine korrekte Fehlerbehandlung (das können ifs oder exceptions sein).
Der Vorteil ist aber das ich an jeder Stelle meines Programms, z.B zu Debugzwecken oder Fehlersuche oder im Zuge von Testszenarien einfach einen Pointer auf 0 setzen kann ohne noch weiter Code an anderen Stellen ändern zu müssen und das Programm läuft ohne
Absturz weiter. Nur die Funktionalität wird eben nicht ausgeführt.
Wenn das if fehlt muss ich es im Zuge von Testszenarien hinzzufügen um einen Absturz zu vermeiden.
Ich halte es einfach für sinnvoll diesen Ansatz prinzipiell ohne Ausnahmen zu machen. Das minimiert die Fehlermöglichkeiten. Nimm mal als Beispiel die Formulierung "if( 0 == lVar )", das ist genauso eine Formulierung um Schreibfehler zu minimieren.
Mein Ansatz oder eben Anspruch ist einfach das ich eine beliebige Methode aus meinem Programm herausnehmen kann und diese mit allen möglichen Eingabewerten füttern kann, ohne das dann das Programm abstürzt.
Das ich in Destruktoren die Variablenwerte auch auf 0 setze, hat auch seinen Grund. Es kann eine gute Hilfestellung bei der Fehlersuche sein. Es gibt Fälle in denen ich dann entscheiden kann ob auf einem Pointer schon der Destruktor aufgerufen wurde, oder ob der Pointer einfach nur in die Pampa zeigt. Durch die Zuweisung wird schliesslich trotzdem der benutzte Speicher auf 0 gesetzt, was sonst nicht der Fall wäre und das kann manchmal helfen.
Und bzgl. Standard, wer garantiert denn das der Compiler auf dem ich gerade arbeite sich an den Standard hält? Und was glaubst Du was der Kunde sagt, wenn ich dem sage das mein Compiler sich nicht an den Standard hält und mich daher leider keine Schuld trifft?
Ich arbeite z.B. mit dem Microtec C++ Compiler und habe keine Ahnung ob der sich an Standards hält. Er verhält sich in Teilen auf jeden anders als der MS Compiler.
Daher ist mein Grundsatz einfach, verwende keinen Pointer ohne ihn vorher nicht auch auf 0abgefragt zu haben.
Sollte es auf Geschwindigkeit ankommen und jede Codezeile zählen, rücke ich davon vielleicht auch mal ab in dem ich bestimmte implizite Annahmen treffe.
D.h. vieles von dem was ich mache basiert auf meiner persönlichen Erfahrung. Und unter Windows ist die Fehlersuche leider oft genug die Hälfte der Arbeit.
MfG
Arnd
Zuletzt bearbeitet:
7H3 N4C3R
Lt. Commander
- Registriert
- Feb. 2002
- Beiträge
- 1.816
Ja, das Thema hatten wir schonmal
Naja ich finde es gut, wenn ein Programm (während der Entwicklung) abstürzt, weil man es dann punktgenau im Debugger hat.
Sicher, man hat nie eine Garantie, dass ein Compiler dem Standard folgt. Allerdings sieht man es ja z.B. anhand von MS, dass sich aber alle darum mühen. VS8.0 in zumindest hinsichtlich Standard-Kompatibilität die erste richtig brauchbare Version.
Und spezielle Compiler für Minimalplattformen bieten natürlich wiederum nicht alles, z.B. Exceptions. Für sollte Ausnahme-Fälle sollte aber nicht immer jedes Programm gewappnet sein, ist meine Meinung.
Und den Einsatz von Pointern minimiere ich sowieso, da man mit automatischen Objekten viele Sachen viel einfacher und schöner machen kann. In einem Artikel meinte Stroustrup mal, dass Pointer eigentlich nur noch aus Kompatibilitätsgründen dringeblieben sind. Dafür wurden Referenzen eingeführt.
Sicher, man hat nie eine Garantie, dass ein Compiler dem Standard folgt. Allerdings sieht man es ja z.B. anhand von MS, dass sich aber alle darum mühen. VS8.0 in zumindest hinsichtlich Standard-Kompatibilität die erste richtig brauchbare Version.
Und spezielle Compiler für Minimalplattformen bieten natürlich wiederum nicht alles, z.B. Exceptions. Für sollte Ausnahme-Fälle sollte aber nicht immer jedes Programm gewappnet sein, ist meine Meinung.
Und den Einsatz von Pointern minimiere ich sowieso, da man mit automatischen Objekten viele Sachen viel einfacher und schöner machen kann. In einem Artikel meinte Stroustrup mal, dass Pointer eigentlich nur noch aus Kompatibilitätsgründen dringeblieben sind. Dafür wurden Referenzen eingeführt.
Und wie ist dann sichergestellt das in der Entwicklungsphase auch alle Code Pfade durchlaufen worden sind? Das heisst ein Absturz während der Entwicklung ist sicher zu begrüssen, weil er auf einen Fehler hindeutet. Aber es fehlt eben die Sicherheit das dann beim Kunden nichts passiert.
Und wenn es um grössere Systeme geht, findes ich es besser das vielleicht eine Funktionalität nicht geht, anstatt das das System abstürzt. Zumindest beim Kunden lässt sich das dann einfacher verkaufen.
Aber ich sage ja auch nicht das mein Ansatz der beste ist. Nur lieber eine Sicherheitsabfrage zuviel als zu wenig. Vor allem in so einem Forum kann man nicht oft genug darauf hinweisen.
Was meinst Du wieviel Code ich schon bekommen habe der einfach davon ausgeht das keine Fehler auftreten.
MfG
Arnd
Und wenn es um grössere Systeme geht, findes ich es besser das vielleicht eine Funktionalität nicht geht, anstatt das das System abstürzt. Zumindest beim Kunden lässt sich das dann einfacher verkaufen.
Aber ich sage ja auch nicht das mein Ansatz der beste ist. Nur lieber eine Sicherheitsabfrage zuviel als zu wenig. Vor allem in so einem Forum kann man nicht oft genug darauf hinweisen.
Was meinst Du wieviel Code ich schon bekommen habe der einfach davon ausgeht das keine Fehler auftreten.
MfG
Arnd
- Registriert
- Dez. 2003
- Beiträge
- 1.371
Tut mir Leid dass ich euch noch mal belästigen muss 
Der Code macht mal wieder nicht das was ich von ihm will
Es geht mal wieder um die Datei karte.h
Der Compiler behauptet allen Ernstes dass levelname ein nicht deklarierter bezeichner ist.
--------------------Konfiguration: maps - Win32 Release--------------------
Kompilierung läuft...
main.cpp
D:\SPIELE PROGGEN\TEST\DATEIEN\MAPS\karte.h(37) : error C2065: 'levelname' : nichtdeklarierter Bezeichner
D:\SPIELE PROGGEN\TEST\DATEIEN\MAPS\karte.h(37) : error C2679: Binaerer Operator '=' : Kein Operator definiert, der einen rechtsseitigen Operator vom Typ 'class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >' akzep
tiert (oder keine geeignete Konvertierung moeglich)
D:\SPIELE PROGGEN\TEST\DATEIEN\MAPS\karte.h(42) : error C2065: 'dateiname' : nichtdeklarierter Bezeichner
D:\SPIELE PROGGEN\TEST\DATEIEN\MAPS\karte.h(42) : error C2679: Binaerer Operator '=' : Kein Operator definiert, der einen rechtsseitigen Operator vom Typ 'class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >' akzep
tiert (oder keine geeignete Konvertierung moeglich)
Fehler beim Ausführen von cl.exe.
maps.exe - 4 Fehler, 0 Warnung(en)
Warum nervt der Compiler mich denn eigentlich immer mit solchen "Fehlern" ?
Der Code macht mal wieder nicht das was ich von ihm will
Es geht mal wieder um die Datei karte.h
Code:
#ifndef _karte_
#define _karte_
#include <string>
class karte
{
private:
std::string dateiname;
std::string levelname;
char** feld1;
public:
inline setlevelname(std::string name);
inline setdateiname(std::string name);
inline karte();
inline ~karte();
};
inline karte::karte()
{
feld1 = new char* [1000];
for (int i=0; i<1000; i++)
feld1[i] = new char [1000];
};
inline karte::~karte()
{
delete[] feld1 ;
};
inline setlevelname(std::string name)
{
levelname=name;
};
inline setdateiname(std::string name)
{
dateiname=name;
};
#endif
Der Compiler behauptet allen Ernstes dass levelname ein nicht deklarierter bezeichner ist.
--------------------Konfiguration: maps - Win32 Release--------------------
Kompilierung läuft...
main.cpp
D:\SPIELE PROGGEN\TEST\DATEIEN\MAPS\karte.h(37) : error C2065: 'levelname' : nichtdeklarierter Bezeichner
D:\SPIELE PROGGEN\TEST\DATEIEN\MAPS\karte.h(37) : error C2679: Binaerer Operator '=' : Kein Operator definiert, der einen rechtsseitigen Operator vom Typ 'class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >' akzep
tiert (oder keine geeignete Konvertierung moeglich)
D:\SPIELE PROGGEN\TEST\DATEIEN\MAPS\karte.h(42) : error C2065: 'dateiname' : nichtdeklarierter Bezeichner
D:\SPIELE PROGGEN\TEST\DATEIEN\MAPS\karte.h(42) : error C2679: Binaerer Operator '=' : Kein Operator definiert, der einen rechtsseitigen Operator vom Typ 'class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >' akzep
tiert (oder keine geeignete Konvertierung moeglich)
Fehler beim Ausführen von cl.exe.
maps.exe - 4 Fehler, 0 Warnung(en)
Warum nervt der Compiler mich denn eigentlich immer mit solchen "Fehlern" ?
G
Green Mamba
Gast
Weil du ihm immer versteckte Fehler einbaust.Warum nervt der Compiler mich denn eigentlich immer mit solchen "Fehlern" ?![]()
Versuchs mal so:
Code:
inline [COLOR="Red"]karte::[/COLOR]setlevelname(std::string name)
{
levelname=name;
};
inline [COLOR="Red"]karte::[/COLOR]setdateiname(std::string name)
{
dateiname=name;
};
Ohne diese vorgestellten Klassennamen gehören die Funktionen nicht zur Klasse, und kennen daher die Membervariablen nicht.
Übrigens schreibt man Klassennamen groß (Karte), und stellt der Übersicht den Membervariablen ein m vor. Also statt levelname m_levelname.
- Registriert
- Dez. 2003
- Beiträge
- 1.371
Ach verdammt warum muss der Compiler auch immer so pingelig sein ?
Fehlermdeldun bekomme ich jetzt keine mehr aber trotzdem macht das Programm nciht was ich will. Hab in der zwischenzeit mal die Namen angepasst damit ihr keinen Augenkrebs bekommt
Und zwar geht es bei den Dateien eigentlich darum aus einer Datei auszulesen und dann in die Datenstrukturen zu schreiben. Bisher war das noch nicht implementiert. die dread Methode der datei.h sieht nun so aus:
Ist natürlich noch nicht fertig.
Als Test habe ich eine Datei genommen die so aus sieht:
levelname Mein_Testlevel
Begin_feld1
:field 5 4 1
END_feld1
Dann müsste ja eigentlich genau das (jedenfalls bis zur zweiten Zeile ausgegeben werden. Es wird statdessen aber gar nichts ausgegeben
Vielleicht könnt ihr mir ja noch einmal weiterhelfen.
Fehlermdeldun bekomme ich jetzt keine mehr aber trotzdem macht das Programm nciht was ich will. Hab in der zwischenzeit mal die Namen angepasst damit ihr keinen Augenkrebs bekommt
Und zwar geht es bei den Dateien eigentlich darum aus einer Datei auszulesen und dann in die Datenstrukturen zu schreiben. Bisher war das noch nicht implementiert. die dread Methode der datei.h sieht nun so aus:
Code:
inline int Datei::dread(std::string datei,Karte &mkarte)
{
FILE* pFile = fopen(datei.c_str(),"rb");
if(!pFile)
return 0;
ZeroMemory(m_buffer,30);
ZeroMemory(m_buffer2,30);
sscanf(m_buffer2,"%s",m_buffer);
std::cout<<m_buffer2<<" "<<m_buffer<<endl;
scanf(m_buffer);
mkarte.setlevelname(m_buffer);
std::cout<<m_buffer<<endl;
return 1;
};
Ist natürlich noch nicht fertig.
Als Test habe ich eine Datei genommen die so aus sieht:
levelname Mein_Testlevel
Begin_feld1
:field 5 4 1
END_feld1
Dann müsste ja eigentlich genau das (jedenfalls bis zur zweiten Zeile ausgegeben werden. Es wird statdessen aber gar nichts ausgegeben
Vielleicht könnt ihr mir ja noch einmal weiterhelfen.
Hallo daemon777,
du liest ja auch nichts aus der Datei aus :-).
- Der Puffer für die Zeile sollte grösser sein, ich würde da eher 1024 Bytes nehmen.
- "rb" beim fopen ist bei ASCII Files eigentlich nicht nötig.
Und jetzt wird es ja interessant, jetzt kommen doch diese Buffer mit 1000 Bytes Länge ins Spiel, oder? D.h. Du musst hier aufpassen das du keine Arraygrenzen verletzt, falls eine Datei mal länger als 1000 Bytes ist.
Ausserdem sollte der Code robuster gegen falsch formatierte Dateien sein.
D.h. führende Leerzeilen sollten egal sein.
Kommentarzeilen wären schön (z.B. mit "#") . Das hält die Leveldateien lesbarer.
Ebenso sollte man führende Leerstellen in einer Zeile ignorieren können.
....
Alles nice to have :-).
Und bzgl. Programmierstil. Ich empfinde es nicht besonders schön alles als inline zu deklarieren und in das Headerfile zu packen. Was für Code kommt den bei Dir in das CPP File?
MfG
Arnd
du liest ja auch nichts aus der Datei aus :-).
Code:
inline int Datei::dread(std::string datei,Karte &mkarte)
{
int lRet = 0;
FILE* pFile = fopen(datei.c_str(),"r");
if(pFile)
{
LONG lLine = 0;
lRet = 1;
ZeroMemory(m_buffer2,sizeof m_buffer2);
ZeroMemory(m_levelName,sizeof m_levelName);
while( !feof( pFile ) )
{
ZeroMemory(m_buffer,sizeof m_buffer);
fgets( m_buffer, sizeof m_buffer-1, pFile );
if( !feof( pFile ) ) // EDIT: Diese Stelle bitte streichen, da unnötig! Siehe Post unten.
{
if( lLine == 0 )
{
sscanf( "%s %s", m_buffer2, m_levelName );
}
std::cout << m_buffer <<endl;
lLine++;
}
}
fclose( pFile );
mkarte.setlevelname(m_levelName);
}
return lRet;
};
- Der Puffer für die Zeile sollte grösser sein, ich würde da eher 1024 Bytes nehmen.
- "rb" beim fopen ist bei ASCII Files eigentlich nicht nötig.
Und jetzt wird es ja interessant, jetzt kommen doch diese Buffer mit 1000 Bytes Länge ins Spiel, oder? D.h. Du musst hier aufpassen das du keine Arraygrenzen verletzt, falls eine Datei mal länger als 1000 Bytes ist.
Ausserdem sollte der Code robuster gegen falsch formatierte Dateien sein.
D.h. führende Leerzeilen sollten egal sein.
Kommentarzeilen wären schön (z.B. mit "#") . Das hält die Leveldateien lesbarer.
Ebenso sollte man führende Leerstellen in einer Zeile ignorieren können.
....
Alles nice to have :-).
Und bzgl. Programmierstil. Ich empfinde es nicht besonders schön alles als inline zu deklarieren und in das Headerfile zu packen. Was für Code kommt den bei Dir in das CPP File?
MfG
Arnd
Zuletzt bearbeitet:
7H3 N4C3R
Lt. Commander
- Registriert
- Feb. 2002
- Beiträge
- 1.816
Mal davon abgesehen, dass ich diese C-Einleseroutinen absolut grauselig finde (will jetzt mal nicht meckern
), enthält dein Code einen Bug.
Die Prüfung auf eof ist so falsch. Wenn man letzte Zeile eingelesen hat, steht was sinnvolles im Puffer. Trotzdem ist das eof-Flag gesetzt, weil man bis zum Ende der Datei gelesen hat. An dieser Stelle darf man also so nicht auf eof prüfen, weil man sonst die letzte Zeile einfach überliest.
Die Prüfung auf eof ist so falsch. Wenn man letzte Zeile eingelesen hat, steht was sinnvolles im Puffer. Trotzdem ist das eof-Flag gesetzt, weil man bis zum Ende der Datei gelesen hat. An dieser Stelle darf man also so nicht auf eof prüfen, weil man sonst die letzte Zeile einfach überliest.
- Registriert
- Dez. 2003
- Beiträge
- 1.371
7H3 N4C3R schrieb:Mal davon abgesehen, dass ich diese C-Einleseroutinen absolut grauselig finde (will jetzt mal nicht meckern)
Was schlägst du vor ?
Wenn du fstream für sinnvoller hällst poste mal bitte Code weil das hab ich auch schon versucht. Ohne Erfolg natürlich.
@Arnd: Dein Code hat einen Fehler. m_levelname ist ein privates element einer anderen Klasse. Der Compiler beschwert sich darüber.
Hallo,
es wird niemand gezwungen das zu übernehmen.
Ausserdem habe ich das nur aus dem Kopf runtergeschrieben und nicht kompiliert.
Schliesslich war die Vorgabe durch das fopen bereits gegeben.
Ich habe das nur vervollständigt.
Das mit dem zweiten feof ist korrekt. Sorry. Habe den Code oben editiert.
Und das mit dem grauslich halte ich mal für starke Geschmackssache.
Ich mische C und C++ eben. Das kann jeder halten wie er will.
Aus ästhetischen Gesichtspunkten ist es sicher schöner wenn alles in C++ geschrieben ist.
@daemon777
Das m_levelName ein privates Element ist, war mir nicht klar da ich deine Headerdateien nicht im Kopf habe.
Ich wollte nur eine neue Variable benutzen und habe diese eben so genannt.
Der Name ergibt sich einfach aus der Bedeutung. Benenne Sie um und es geht.
Ausserdem wenn es ein Element einer anderen Klasse ist, dann sollte der Name doch wohl auch nicht stören?
Es kann höchstens sein, das Du in der selben Klasse den Namen bereits verwendest aber diese einen anderen Typ hat?
MfG
Arnd
es wird niemand gezwungen das zu übernehmen.
Ausserdem habe ich das nur aus dem Kopf runtergeschrieben und nicht kompiliert.
Schliesslich war die Vorgabe durch das fopen bereits gegeben.
Ich habe das nur vervollständigt.
Das mit dem zweiten feof ist korrekt. Sorry. Habe den Code oben editiert.
Und das mit dem grauslich halte ich mal für starke Geschmackssache.
Ich mische C und C++ eben. Das kann jeder halten wie er will.
Aus ästhetischen Gesichtspunkten ist es sicher schöner wenn alles in C++ geschrieben ist.
@daemon777
Das m_levelName ein privates Element ist, war mir nicht klar da ich deine Headerdateien nicht im Kopf habe.
Ich wollte nur eine neue Variable benutzen und habe diese eben so genannt.
Der Name ergibt sich einfach aus der Bedeutung. Benenne Sie um und es geht.
Ausserdem wenn es ein Element einer anderen Klasse ist, dann sollte der Name doch wohl auch nicht stören?
Es kann höchstens sein, das Du in der selben Klasse den Namen bereits verwendest aber diese einen anderen Typ hat?
MfG
Arnd
Zuletzt bearbeitet:
7H3 N4C3R
Lt. Commander
- Registriert
- Feb. 2002
- Beiträge
- 1.816
Ja natürlich. Nur nicht beschwerenArnd schrieb:Und das mit dem grauslich halte ich mal für starke Geschmackssache.
Ich mische C und C++ eben. Das kann jeder halten wie er will.
Eine Lösung mit fstreams kann ich auch noch posten. Heut wohl aber net mehr. =)
Zuletzt bearbeitet:
7H3 N4C3R
Lt. Commander
- Registriert
- Feb. 2002
- Beiträge
- 1.816
So hier mal die versprochene Version mit fstreams
Code:
#include <iostream>
#include <fstream>
#include <string>
.....
bool dread( const std::string& fileName, Karte& karte)
{
std::ifstream in (fileName.c_str(), std::ios::in);
bool ret = false;
if( in) {
bool firstLine = true;
std::string line;
while( !std::getline( in, line).fail()) {
if( firstLine) {
firstLine = false;
karte.setLevelName( line);
}
else {
std::cout << line << '\n';
}
}
std::cout.flush();
ret = true;
}
else {
std::cerr << "Datei nicht gefunden oder keine Leserechte.\n";
}
return ret;
}
- Registriert
- Dez. 2003
- Beiträge
- 1.371
OK danke dass du dir noch die Mühe gemacht hast 
Ich denke ich werde das so abändern schon weil es moderner Programmierstil ist.
Das ganze hat nur ( bis jetzt ) einen Nachteil. Und zwar wird das zwar mit der ersten Zeile so funktionieren aber ich weiß nicht wie viele Befehle noch vor feld1 und danach stehen. Die müsste ich auch noch irgendwie auslesen können.
Also ich habe mir das so ähnlich wie eine Scipt Sprache gedacht ( natürlich nicht so kompliziert
) Ich habe ein paar Befehle + Parameter, die in einer Datei stehen und mein Code soll jetzt dazu dienen diesen Code einzulesen und auszuwerten.
Der Einfachheit halber habe ich mir gedacht einfach den string bis zum ersten Leerzeichen zu durchsuchen und dann einen Substring bis zu dieser Stelle herrzustellen um wiederrum den mit einer Konstanten zu vergleichen
zB strcmp(msbstring, KeyWords);
Und das ganze kommt dann in ne Schleife. So kann ich dann rausfinden welche Funktion aufgeruffen werden soll.
Jetzt meine Frage: Ist das ein brauchbarer und durchführbarer Ansatz oder eher unpraktisch ?
Ich denke ich werde das so abändern schon weil es moderner Programmierstil ist.
Das ganze hat nur ( bis jetzt ) einen Nachteil. Und zwar wird das zwar mit der ersten Zeile so funktionieren aber ich weiß nicht wie viele Befehle noch vor feld1 und danach stehen. Die müsste ich auch noch irgendwie auslesen können.
Also ich habe mir das so ähnlich wie eine Scipt Sprache gedacht ( natürlich nicht so kompliziert
Der Einfachheit halber habe ich mir gedacht einfach den string bis zum ersten Leerzeichen zu durchsuchen und dann einen Substring bis zu dieser Stelle herrzustellen um wiederrum den mit einer Konstanten zu vergleichen
Und das ganze kommt dann in ne Schleife. So kann ich dann rausfinden welche Funktion aufgeruffen werden soll.
Jetzt meine Frage: Ist das ein brauchbarer und durchführbarer Ansatz oder eher unpraktisch ?
Ähnliche Themen
- Antworten
- 5
- Aufrufe
- 1.977
- Antworten
- 3
- Aufrufe
- 1.598
- Antworten
- 1
- Aufrufe
- 1.198