Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

T-VIRUS

Alter Hase

  • »T-VIRUS« ist der Autor dieses Themas

Beiträge: 548

Wohnort: Göttingen(West)/Nordhausen(Ost)

Beruf: Schüler

  • Private Nachricht senden

1

19.09.2008, 22:38

Kleiner Parser sucht Feedback :)

Hallo,
ich habe schon seit einigen Wochen an meinem kleinen freien Parser gearbeitet.
Diesen nutze ich auch, noch in einer alten Version, in meinem 2D Spiel um es nicht Programmierern möglich zu machen sämtliche Grafiken sowie Sounds und einige Werte umzustellen.

Da ich die aktuelle Version für brauchbar, aber eben noch nicht perfekt halten, suche ich Feedback.
Ich plane bereits eine kleine .dll und das ganze noch für Unicode, da die STL String Klasse doch nur ANSI ist oder?, einbinden.

Der Download des Codes gibst hier:
http://mm.dedenet.de/gINI.rar

Da ich trotz meiner 3 1/2 Jahre C++ und jetzt auch 10 Monate C# noch immer einige Problem beim Klassen Design habe, bitte nicht zu streng mit dem Aufbau der Klassen sein :(

Auch ist die Frage, ob es mögliche Einfallstore gibt.
Leider kenne ich keine Regular Expression Klasse, sonst könnte ich bestimmt die CConvert Klasse ausbauen.
Aber für den Augenblick reicht es.

Leider scheite ich beim einbauen des Codes in einer .dll.
Diese wollte ich für Windows anbieten, während ich für Linux, Debian Lenny, eine .so anbieten wollte.
Aktuell gibt es nur ein SVN Repository als Konsolenanwendung zur Demonstration.

Ich danke schon jetzt für das Feedback und Tipps.

MFG T-Virus
Meine Blog:)

Wer Bugs im Text findet kann sie melden, fix erscheint irgendwann :D

MFG T-VIRUS

2

20.09.2008, 00:44

Für 3.5a hast du dann aber noch nicht viel gelernt ;) Regular Expressions sind in tr1 enthalten (demnach auch in boost).

Nja was verstehst du denn unter STL String Klasse? Ich kenn da z.B. die Klasse std::basic_string, dann noch das typedef std::string u. std::wstring, die nichts anderes sind als std::basic_string<char> u. std::basic_string<wchar_t>. Von d.h. ist das kein Problem, auch mit UNICODE zu arbeiten. Und nja guck dir mal <local> an ... usw.
Devil Entertainment :: Your education is our inspiration
Der Spieleprogrammierer :: Community Magazin
Merlin - A Legend awakes :: You are a dedicated C++ (DirectX) programmer and you have ability to work in a team? Contact us!
Siedler II.5 RttR :: The old settlers-style is comming back!

Also known as (D)Evil

T-VIRUS

Alter Hase

  • »T-VIRUS« ist der Autor dieses Themas

Beiträge: 548

Wohnort: Göttingen(West)/Nordhausen(Ost)

Beruf: Schüler

  • Private Nachricht senden

3

20.09.2008, 08:43

Guten Morgen,
danke für die Infos.

Ich nutze als string Klasse std::string.
Dies werde ich nun aber durch wstring ersetzen.
Da kann ich ja auch die Methoden weitestgehend so lassen, muss aber nur die ganzen Typen ändern.

Damit kann ich aber leben ;)

Was boost angeht, wollte ich eigentlich auf solch eine Sondersache verzichten.
Zwar ist boost an sich klasse, wie ich gehört habe, aber ich möchte es anderen entwicklern so einfach wie möglich machen und möchte auch die .dll/.so am ende so klein wie möglich haben.

Ich werde mal schauen wie ich mit RegEx arbeiten kann.
Was ich ja nur mit RegEx machen will, ist eine Prüfung des Strings, damit ich auch weiß ob der String eint int, double etc. ist.

Auch local werde ich mir mal zu gemüte ziehen :)

EDIT
Ich habe mal per Google was über locale gefunden.

http://de.nntp2http.com/comp/os/unix/programming/2004/10/95f9f586e3bb30cb07d3c70599fbf2d3.html

Sieht sehr interessant aus :)
Wenn dieses Beispiel stimmt, müsste ich also nur mit test<type>(string) das ganze mit if abfragen.
Das wäre klasse.

Aber wenn ich dazu locale brauche, wie kann ich dann von dem Rechner, auf dem ein Programm mit dem Parser ausgeführt wird, die Daten bekommen.
Im Beispiel wirde ja mit einem festen ISO Code gearbeitet.

MFG T-Virus
Meine Blog:)

Wer Bugs im Text findet kann sie melden, fix erscheint irgendwann :D

MFG T-VIRUS

Anonymous

unregistriert

4

20.09.2008, 10:36

1/ Ich hasse es wenn keine Kommentare im Quelltext drin sind. Ich als außenstehender empfinde es als Zumutung einen Quelltext durchzugucken, ohne das Kommentare enthalten sind und ich mir alles selbst zusammen dichten "darf".

2/ Darüber bekomme ich das Grauen! Im Header niemals using oder using namespace benutzen! Irgendwann wirst du auf Mehrdeutigkeiten stoßen und dann kann man sich nicht gerade köstlich in den Hintern beißen, weil man so dusselig war. Wenn dann ordne diese usings der Klasse zu, aber niemals global im Header - am Besten man benutzt sie erst gar nicht.

3/ Wegen deinem "Unicode- und ANSI-Problem": Les dir mein Tutorial über Lokalisierung durch: https://www.spieleprogrammierer.de/phpBB2/viewtopic.php?t=10196

4/ Ich finde deine Schreibweise grauenvoll. Vorallem bei sowas tut es mir richtig im Auge weh:

C-/C++-Quelltext

1
virtual string GetValueFromLine(string strLine);


4.1/ const correctness fehlt (überall).
4.2/ warum keine konstante Referenz? Performance adé
4.3/ GetValueFromLine ist wäh, schöner finde ich: "value_from_line".
4.4/ Wenn es nach mir geht:

C-/C++-Quelltext

1
2
    // Wiedergabe des Wertes einer Zeile.

virtual string_type value_from_line (const string_type& line) const;

In der STL findest du z. B. keine "GetFPSDingesKirchenMitScheissUpperUndLowerName".

5/ Du zeigst wieder sehr gut warum die Ungarische Notation in C++ nichts zu suchen hat:

C-/C++-Quelltext

1
2
string m_strSectionName;
map<string, string> m_Keys;
Tja, was hätte jetzt nach Ungarischer Notation map<string, string> für ein Kürzel? Wie du siehst: Gar keines. Die Ungarische Notation ist aus tiefen C-Zeiten, wo es keine modernen IDEs wie heute gab. Ein

C-/C++-Quelltext

1
2
3
    // postfix _ sagt aus das es ein Attribut ist.

string_type name_; // section_name ist sowieso nonsens, da wir schon in der Sektion sind.

std::map<string_type, string_type> data_; // Du sicherst hier Daten in Form von Schlüssel:Wert und nicht Schlüssel:Schlüssel. Daher ist "Keys" falsch.


6/ Lass die STL für dich arbeiten und deren cc'tors. Deine Abfrage ob entwas enthalten ist, ist unsinn:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
    CSection::CSection(string strSection, map<string, string> keys)
    {
        if(strSection.empty() == false)
        {
            m_strSectionName = strSection;
        }

        if(keys.empty() == false)
        {
            m_Keys = keys;
        }
    }

daraus wird besser:

C-/C++-Quelltext

1
2
3
4
5
section::section (const string_type& name, const std::map<string_type, string_type>& data) :
    name_ (name),
    data_ (data)
{
}

Kleiner, schlanker, schöner, schneller.

7/ cc'tor und assignment-operator fehlen komplett!

8/ Das (und viele andere Passagen) könnte man viel schöner Optimieren:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
bool CSection::KeyExists(string strKey)
{
    bool bKeyExists = false;

    int count = m_Keys.count(strKey);

    if(count > 0)
    {
        bKeyExists = true;
    }

    return bKeyExists;
}


durch

C-/C++-Quelltext

1
2
3
4
bool section::key_exists (const string_type& key) const
{
    return (data_.count (key) > 0);
}


9/ CSection::AddKey ist nonsens, da du keine Schlüssel hinzufügst, sondern Schlüssel:Wert-Paare. Logisch wäre hier:

C-/C++-Quelltext

1
void section::add_value (const string_type& key, const string_type& value = _T (""));


10/

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
    void CSection::RemoveKey(pair<string, string> pair)
    {
        bool bKeyExists = KeyExists(pair.first);

        if(bKeyExists == false)
        {
            return;
        }

        map<string, string>::iterator it = m_Keys.find(pair.first);
        m_Keys.erase(it);

        return;
    }
Was macht da unten das return??

11/ Dein ganzer Converter-Namespace ist überflüssig. Such hier im Forum mal nach "lexical_cast" oder bei google nach boost::lexical_cast.

12/ In vielen Klassen gibst du als Seperator den Datentyp "char" an. Nimm "string_type", das erleichtert die Handhabung.

13/ Bei einigen Funktionen gibt es den Parameter "strDefaultValue" (unschöne Schreibweise - but anyway), dieser hat jedoch gar keinen "default-value", dazu ist er nicht const und keine referenz.

So ich hab mir nicht alles durchgesehen, doch ich empfehle dir: Überarbeite den Code, er ist sehr wirr und unleserlich und vorallem: KOMMENTIER IHN!

so long!
- unsigned long

T-VIRUS

Alter Hase

  • »T-VIRUS« ist der Autor dieses Themas

Beiträge: 548

Wohnort: Göttingen(West)/Nordhausen(Ost)

Beruf: Schüler

  • Private Nachricht senden

5

20.09.2008, 10:47

Hallo unsigned long,
ich danke für das Feedback.

Ich werde mal schauen, wie ich das alles richten kann.
Auch Kommentare werde ich hinzufügen.

EDIT:
Ich habe mal was zu lexical_cast gefunden:
https://www.spieleprogrammierer.de/phpBB2/viewtopic.php?t=7928&highlight=lexicalcast

Das Problem ist, dass ich aber das ganze noch in eine .dll/.so packen will.
Nachdem was ich über .dlls weiß, was nicht sehr viel ist, kann man doch Templates selbst nicht in eine .dll packen, da diese doch erst zur Laufzeit in die entsprechenden Typen umgewandelt werden.

Aber der Ansatz ist schon ganz gut.

MFG T-Virus
Meine Blog:)

Wer Bugs im Text findet kann sie melden, fix erscheint irgendwann :D

MFG T-VIRUS

Anonymous

unregistriert

6

20.09.2008, 10:54

Da es sich sowieso um ein Template handelt, musst du es natürlich in einen Header bringen. Ich sehe da kein "DLL-Problem".

Steven77

Alter Hase

Beiträge: 515

Wohnort: Münster - Gievenbeach

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

7

20.09.2008, 11:07

Zitat von »"T-VIRUS"«

Das Problem ist, dass ich aber das ganze noch in eine .dll/.so packen will.
Nachdem was ich über .dlls weiß, was nicht sehr viel ist, kann man doch Templates selbst nicht in eine .dll packen, da diese doch erst zur Laufzeit in die entsprechenden Typen umgewandelt werden.


C++-Templates werden zur Compile-Zeit aufgelöst (nicht zur Laufzeit). Aber genau das ist ja auch das "Problem mit DLLs", weil während des Kompilierens der DLL nicht alle etwaig relevanten konkreten Typen bekannt sind, für die entsprechender Code generiert werden könnte.

Bei C# ist es z.B. anders. Generische Klassen (Pendants zu C++-Templates) werden erst zur Laufzeit aufgelöst und daher kann sich der "generische" Code solcher Klassen bereits in DLLs befinden.

Das sind technisch natürlich zwei komplett andere Ansätze, insofern hinkt ein solcher Verlgeich von C++-Templates und C#-Generics immer ein wenig.
Kommen Sie nie mit einem Schwert zu einer Schießerei.

T-VIRUS

Alter Hase

  • »T-VIRUS« ist der Autor dieses Themas

Beiträge: 548

Wohnort: Göttingen(West)/Nordhausen(Ost)

Beruf: Schüler

  • Private Nachricht senden

8

20.09.2008, 11:09

Hallo,
ich habe mal grade wegen TCHAR gegooglet.
Ist TCHAR nicht ein Windows typedef?

Wäre es vielleicht nicht besser direkt auf std::wstring auszuweichen?

Den das ganze ist nicht nur für Windows gedacht.
Ich habe eine ältere Version, von der du noch mehr Kopfschmerzen bekommen würdest, unter Debian in ein kleines 2D Spiel eingebunden.

Und ich möchte den Parser auch deshalb mit möglichst Platformunabhängigen Datentypen nutzen.

Auf solche Sachen wie

Quellcode

1
#ifdef WIN32


Möchte ich weitestgehend verzichten, da ich meinen Code möglichst simpel halten möchte.

EDIT
@Post über mir:
Also kann ich die Template Version vergesen oder wie?
Also müsste ich doch die Methoden ausbauen, die breits vorhanden sind?

MFG T-Virus
Meine Blog:)

Wer Bugs im Text findet kann sie melden, fix erscheint irgendwann :D

MFG T-VIRUS

9

20.09.2008, 11:10

Und by the way:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void CSection::RemoveKey(pair<string, string> pair)
    {
        bool bKeyExists = KeyExists(pair.first);

        if(bKeyExists == false)
        {
            return;
        }

        map<string, string>::iterator it = m_Keys.find(pair.first);
        m_Keys.erase(it);

        return;
    }
hat noch mehr Schwachstellen. KeyExists wird wahrscheinlich die Funktion m_keys.find schon aufrufen, oder? Dann suchst du 2mal nach dem selben key ... ist das nicht etwas arg unperformant, vorallem bei std::map?

Dann übergibst du das pair by value. Das da zwei Strings kopiert werden u. zusätzlich noch das pair, scheint dir egal zu sein ;)

C-/C++-Quelltext

1
2
3
4
5
6
7
typedef std::pair<std::string, std::string> value_t;

void CSection::RemoveKey(value_t const& pair)
{
    std::map<std::string, std::string>::iterator it(m_data.find(pair.first));
    if (it = m_data.end()) m_data.erase(it);
}
schneller, kürzer, besser!
Devil Entertainment :: Your education is our inspiration
Der Spieleprogrammierer :: Community Magazin
Merlin - A Legend awakes :: You are a dedicated C++ (DirectX) programmer and you have ability to work in a team? Contact us!
Siedler II.5 RttR :: The old settlers-style is comming back!

Also known as (D)Evil

T-VIRUS

Alter Hase

  • »T-VIRUS« ist der Autor dieses Themas

Beiträge: 548

Wohnort: Göttingen(West)/Nordhausen(Ost)

Beruf: Schüler

  • Private Nachricht senden

10

20.09.2008, 11:14

Hallo,
danke für den Hiwneis.
Ich werde diese Methode so oder so streichen.
Es würde dort reichen, eine kosntante referenz eines Strigs zu übergeben.
Der schmeisst dann einfach das pair raus.

Ich arbeite bei FoundKey eigentlich mit count.
Dies müsste ich vielleicht mal umstellen.

MFG T-Virus
Meine Blog:)

Wer Bugs im Text findet kann sie melden, fix erscheint irgendwann :D

MFG T-VIRUS

Werbeanzeige