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

1

22.06.2008, 20:00

Dateien einlesen / parsern

Hallo zusammen

Ursprünglich wollte ich gleich eine x.Datei parsern, merke jetzt aber, dass es mir generell bisschen an Grundlagen bezüglich dieses Themas mangelt :>
Nun will ich erstmal ein einfacheres File parsern.
Ich hoffe ich könnt mir kurz ein paar Tipps geben.

Welche Methode würdet ihr empfehlen. ifstream zum lesen?

Ich habe früher mal ein einfaches bmp-file geparsert. Beim Bmp-File kann man im Header (sofern ich mich jetzt richtig erinnere) auslesen, an welcher stelle im Filfe die eigentlichen rgb Farbinformationen beginnen und dann zu dieser Stelle springen.
Wie ich sehe benutzen aber viele Formate eine art Schlüsselwort um anzugeben, das jetzt die eigentlichen Informationen folgen. Demanch kann man auch nicht einfach an einen bestimmten Punkt in der Datei springen und dann mit dem auslesen beginnen.

Lädt man nun einfach Informationen aus dem File und "sucht" nach diesen Schlüsselwörtern?

Habt ihr ein Link, wo das ganze Thema bisschen genauer beschrieben wird?

Danke

gruss neptun

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

2

22.06.2008, 20:08

Es kommt hier auch stark auf das Format an, das du laden willst. :)
@D13_Dreinig

Toa

Alter Hase

Beiträge: 944

Beruf: Research associate

  • Private Nachricht senden

3

22.06.2008, 20:10

Du könntest Zeilenweise durch die Datei gehen und die C++ Strings bieten dir dann eine Vielzahl an Möglichkeiten zu manipulieren..

Databyte

Alter Hase

Beiträge: 1 040

Wohnort: Na zu Hause

Beruf: Student (KIT)

  • Private Nachricht senden

4

22.06.2008, 20:34

Kommt natürlich auf das Format an... wenn du sowas wie ne
Programmier-sprache machen willst is Toa´s Idee nicht schlecht ( @Toa: wie kommste nur darauf ??? ;))

Wenn du aber sowas wie x.Daetein paresen willst, dann sind das wahrscheilnich keine Zeilen-Befehele^^

Vieleicht wäre das konvertieren von Pointern hier noch sehr interessant...

ifstream würd ich jedenfalls in jedem Fall nehmen :p

5

22.06.2008, 20:35

Hm es kommt stark auf den Aufbau des Formates an.
Generell ließt es sich mit std::ifstream unter C++ ganz gut ;)
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

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

6

22.06.2008, 20:38

Zitat von »"Databyte"«


ifstream würd ich jedenfalls in jedem Fall nehmen :p


Und wieso würdest du das in jedem Fall verwenden?
@D13_Dreinig

7

22.06.2008, 20:56

Was spricht denn gegen fopen? :P Oder was spricht gegen die Betriebssystem-API eigenen Funktionen, wenn man eh nur für Windows programmiert? Tjo
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

8

22.06.2008, 21:07

Also gehen wir mal vom x.Format aus. Ich weiss das dies komplex sein kann. Mir geht es aber erstmal nur um die wirklich einfachen Dinge.
Mir ist einfach nicht ganz klar, wie ich an die nötigen Informationen kommen kann.
Ich habe z.b eine Datei im ASCII Format. Nun will ich erstmal die Zahl der Vertecies auslesen.
Wie soll ich da vorgehen? Zeichen für Zeichen lesen, bis ich auf den Buchstaben M (für Mesh) treffe und dann checken ob das nächste Zeichen ein e ist, und dann weiter zu s und h?
Dann kanns doch sein, das nach dem { Zeichen noch Leerzeichen folgen. Wie komme ich als 100% zuverlässig an diese Zahl ran?

9

22.06.2008, 22:18

auch wenn ich DirectX zum Glück nicht benutze und daher keine Ahnung davon habe, würde ich dir empfehlen, auf einen existierenden Parser zurückzugreifen. Bestimmt hat jemand das Rad bereits erfunden und mehr Zeit, Arbeit und Sorgfalt investiert, als Du es tun wirst.

Wenn Du trotzdem einen eigenen Parser haben willst, würde ich erst einmal einen Lexer schreiben, der das Script in Token zerlegt, also (am Beispiel von C) aus:

C-/C++-Quelltext

1
int myInt = 29;

eine Liste aller enthaltenen Elemente (Token) anfertigt:

C-/C++-Quelltext

1
2
3
4
5
int
myInt
=
29
;


Anschließend kann der Parser herausfinden, um welche Typen es sich bei den Token handelt. int bezeichnet einen eingebauten Variablentyp, myInt ist ein Bezeichner, = ein Operator und 29 eine (natürliche/Dezimal-)Zahl.

Token zu erkennen kann schwierig sein. In obigem Beispiel wird fast jedes Token durch ein Leerzeichen von den anderen getrennt. Das Semikolon jedoch kann nur als Token erkannt werden, weil der Lexer weiß, dass Zahlen nur aus einer oder mehreren Ziffern, gefolgt von einem Dezimalpunkt, gefolgt von einer oder mehreren Ziffern bestehen kann (google mal nach EBNF); eine Zahl darf also kein Semikolon enthalten, folglich ist das Semikolon ein neues Token und/oder ein Fehler.

Wenn Du nun eine Liste aller vorkommenden Token in einem array oder besser einem SL container vorliegen hast, musst Du noch die Syntax prüfen. Wenn das erste Token einer Zeile zum Beispiel "Vector" ist, könntest Du prüfen, ob die folgenden n Token vom Typ "{", float, float, float "}" sind und falls ja, die drei Floats in einem Vektor speichern.

Na ja, ich bin kein Crack aber vielleicht hilft das als kleine Übersicht.
Es gibt übrigens auch Parser-Generatoren, die Du mit EBNF-Statements fütterst und dir dann einen c++ Parser erzeugen, zum Beispiel Flex.

Ba'el

Alter Hase

Beiträge: 409

Wohnort: Erfurt

Beruf: Student (6 FS angew. Info. - Richtung Medieninformatik)

  • Private Nachricht senden

10

22.06.2008, 23:25

also für was einfaches, hätt' ich hier 'n Beispiel
in diesem Fall, um .obj-dateien einzulesen (ganz einfach)

natürlich muss man es an das Format anpassen, .obj is' da einigermaßen Standardisiert deswegen geht das so einfach ...

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# cube.obj

v -0.500000 -0.500000 1.00000
v 0.500000 -0.500000 1.00000
v 0.500000 0.500000 1.00000
v -0.500000 0.500000 1.00000
v 0.500000 -0.500000 0.000000
v -0.500000 -0.500000 0.000000
v -0.500000 0.500000 0.000000
v 0.500000 0.500000 0.000000
 
f 1 2 3
f 1 3 4
f 5 6 7
f 5 7 8
f 6 1 4
f 6 4 7
f 2 5 8
f 2 8 3
f 6 5 2
f 6 2 1
f 4 3 8
f 4 8 7


C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
[...]

typedef struct
{
    float m_iX;
    float m_iY;
    float m_iZ;
}SVertex;

std::vector<SVertex> vertices;

[...]

int load(char* pcFile)
{
    FILE* pFile;
    char line[255], comment[255];
    float x,y,z;
    int v[3];

    for(int i=0;i<3;i++) v[i]=0;

    pFile = fopen(pcFile, "r" );

    int iCountV = 0;
    
    while ( fgets( line, sizeof(line), pFile ) != NULL )
    {
        if (sscanf( line, "#%s", comment ) )
            printf( "valid: comment %s\n", comment );
        if (sscanf( line, "v %f %f %f", &x, &y, &z ))
        {
            vertices.push_back(SVertex());
            vertices.at(iCountV).m_iX = x;
            vertices.at(iCountV).m_iY = y;
            vertices.at(iCountV).m_iZ = z;
            
            iCountV++;
        }
        if (sscanf(line, "f %i %i %i", &v[0],&v[1],&v[2]))
        {       
            printf( "valid: f %i %i %i\n", v[0],v[1],v[2]);
            glBegin(GL_TRIANGLES);
                glVertex3f(vertices.at(v[0]-1).m_iX, vertices.at(v[0]-1).m_iY, vertices.at(v[0]-1).m_iZ);
                glVertex3f(vertices.at(v[1]-1).m_iX, vertices.at(v[1]-1).m_iY, vertices.at(v[1]-1).m_iZ);
                glVertex3f(vertices.at(v[2]-1).m_iX, vertices.at(v[2]-1).m_iY, vertices.at(v[2]-1).m_iZ);
            glEnd();
        }
    }
    return 0;
}


hier ganz einfach, nur Vertices und Faces und auch nur Dreiecke, kann man natürlich auch erweitern und bestimmt auch eleganter manchen ... ist ja nur 'n Beispiel
aktuelle Projekte:
Ruby on Rails
XNA &amp; Touchless
Progr. mobiler Endgeräte (GPS Trekking)

Werbeanzeige