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

02.03.2009, 10:57

[Erledigt] Abspeichern und auslesen einer CHAR_INFO Struktur

Hallo!

Ich will ein CHAR_INFO Array vom Ausmaß z.B. [10][10] binär in eine Textdatei speichern und später wieder auslesen. Meine bisherigen Versuche mit #include <fstream> sind leider gescheitert.

Folgendes funktioniert ja leider nicht:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
CHAR_INFO Inhalt[10][10];

// Hier würde das Array gefüllt...


ofstream Output("Dateiname.dat", ios::binary);

Output.write ((CHAR_INFO*) &Inhalt[0][0], sizeof(Inhalt));

Output.close ();
"Der Wald wäre sehr leise, wenn nur die begabtesten Vögel singen würden."

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

2

02.03.2009, 11:36

Warum soll das nicht funktionieren?

Einzige Änderung:

C-/C++-Quelltext

1
Output.write ((char*) &Inhalt[0][0], sizeof(Inhalt)); 

3

02.03.2009, 18:03

Bei folgendem Quelltext handelt es sich um einen kleinen Mapeditor für mein geplantes Pacmanspiel. Dabei soll mit der Funktion saveMap die aktuelle Map gespeichert werden...

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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
#include <windows.h> 
#include <conio.h> // für _getch()

#include <fstream>

using namespace std; // Namensraum in fstream


// Höhe und Breite des Spielfedes

#define HEIGHT 10
#define WIDTH 20

// Prototypen

//


// Cursor sichtbar|unsichtbar machen bzw. Größe einstellen

void setCursorInfo(bool bVisible, DWORD CursorSize); 
// Cursorposition bestimmen

void gotoxy(int x, int y);
// Gibt nach eingabe von w,a,s,d die aktuelle Cursorposition zurück

COORD aktCursorPos(char chAuswahl, COORD CursorPos);
// Schreibt je nach Auswahl an der aktuellen Cursorposition das bestimmte Zeichen

// in das CHAR_INFO Array

CHAR_INFO setGround(char chAuswahl, COORD CursorPos, CHAR_INFO Ground[HEIGHT][WIDTH]);
// Zeichnet das CHAR_INFO Array in den ConsoleScreenBuffer und setzt die Cursorposition

// dahin wo zuletzt gezeichnet wurde

void zeichneGround(CHAR_INFO Ground[HEIGHT][WIDTH], COORD CursorPos);
// Schreibt einen Text aus einem char Array mit der angegebenen Satzlänge an die 

// Position xy

void writeText(unsigned short int x, unsigned short int y, const char* lpBuffer, DWORD nNumberOfChars );
// zeichneInfo fasst die writeText Funktionen für die Ausgabe der Auswahlmöglichkeiten 

// zusammen

void zeichneInfo();
// saveMap speichert das CHAR_INFO Array in eine Datei mit dem Dateinamen aDateiname

int saveMap( CHAR_INFO Ground[HEIGHT][WIDTH], char aDateiname[] );

// Das Hauptprogramm

//

int main ()
{
    setCursorInfo(TRUE, 100);   

    // Deklarierung des CHAR_INFO Arrays für das Spielfeld

    CHAR_INFO Ground[HEIGHT][WIDTH];
    
    // Diese for-Schleife füllt das Spielfeld damit eine einheitliche

    // blaue Fläche angezeigt wird

    for(int i=0; i<HEIGHT; i++)
    {
        for(int j=0; j<WIDTH; j++)
        {
            Ground[i][j].Attributes = BACKGROUND_BLUE;
            Ground[i][j].Char.AsciiChar = ' ';
        }
    }
    
    // Deklaration und Zuweisung der Variablen CursorPos und chAuswahl

    COORD CursorPos = {0,0}; // Die Cursor Position

    char chAuswahl = 0; // Eine Variable für die Auswahl


    // Diese do-while Schleife läuft solange bis 6 für beenden gedrückt wurde

    // und verzweigt je nach Auswahl auf die einzelnen Funktionen

    do
    {
        if( chAuswahl == 'w' || chAuswahl == 'a' ||
            chAuswahl == 's' || chAuswahl == 'd' )
        {
            // Cursorposition aktuallisieren

            CursorPos = aktCursorPos(chAuswahl, CursorPos);
        }
        else if( chAuswahl == '1' || chAuswahl == '2' ||
                 chAuswahl == '3' || chAuswahl == '4' )
        {
            // Spielfeld besetzen

            Ground[CursorPos.Y][CursorPos.X] = setGround(chAuswahl, CursorPos, Ground);
        } 
        else if( chAuswahl == '5' )
        {
            // Map speichern

            saveMap(Ground, "PacmanMap");
        }

        // Die Auswahlmöglichkeiten ausgeben

        zeichneInfo();
        // Das Spielfeld ausgeben

        zeichneGround(Ground, CursorPos);
        
        // Abfrage der Auswahlmöglichkeiten

        chAuswahl = _getch();
    } while (chAuswahl != '6');
    
    setCursorInfo(FALSE, 1);
    gotoxy(0,HEIGHT+2);
    
    return 0;
} // ENDE von main


// Beschreibung s.o.

void setCursorInfo(bool bVisible, DWORD CursorSize)
{
    HANDLE hConOut = GetStdHandle( STD_OUTPUT_HANDLE );
    CONSOLE_CURSOR_INFO CursorInfo;
    CursorInfo.bVisible = bVisible;
    CursorInfo.dwSize = CursorSize;
    SetConsoleCursorInfo( hConOut, &CursorInfo ); 
}

// Beschreibung s.o.

void gotoxy(int x, int y)
{
    HANDLE hConsoleOutput = GetStdHandle( STD_OUTPUT_HANDLE );
    COORD CursorPos = {x,y};
    SetConsoleCursorPosition ( hConsoleOutput, CursorPos );
}

// Beschreibung s.o.

COORD aktCursorPos(char chAuswahl, COORD CursorPos)
{
    switch(chAuswahl)
    {
    case 'w': // hoch

        if(CursorPos.Y > 0)
            CursorPos.Y--;
        break;
    case 'a': // links

        if(CursorPos.X > 0)
        CursorPos.X--;
        break;
    case 's': // runter

        if(CursorPos.Y < HEIGHT-1)
        CursorPos.Y++;
        break;
    case 'd': // rechts

        if(CursorPos.X < WIDTH-1)
        CursorPos.X++;
        break;
    }
    return CursorPos;
}

// Beschreibung s.o.

CHAR_INFO setGround(char chAuswahl, COORD CursorPos, CHAR_INFO Ground[HEIGHT][WIDTH])
{
    switch(chAuswahl)
    {
    case '1': // Wand

        Ground[CursorPos.Y][CursorPos.X].Char.AsciiChar = ' ';
        Ground[CursorPos.Y][CursorPos.X].Attributes = BACKGROUND_BLUE | BACKGROUND_INTENSITY;
        // Erkennungstöne für Wand

        Beep(50,50);
        Beep(70,50);
        break;
    case '2': // Punkt

        Ground[CursorPos.Y][CursorPos.X].Char.AsciiChar = 7;
        Ground[CursorPos.Y][CursorPos.X].Attributes = FOREGROUND_GREEN | FOREGROUND_INTENSITY;
        // Erkennungstöne für Punkt

        Beep(250,50);
        Beep(300,50);
        break;
    case '3': // Diamant

        Ground[CursorPos.Y][CursorPos.X].Char.AsciiChar = 4;
        Ground[CursorPos.Y][CursorPos.X].Attributes = FOREGROUND_GREEN | FOREGROUND_INTENSITY;
        // Erkennungstöne für Diamant

        Beep(550,50);
        Beep(500,50);
        Beep(550,50);
        Beep(500,50);
        break;
    case '4': // Leer

        Ground[CursorPos.Y][CursorPos.X].Char.AsciiChar = ' ';
        Ground[CursorPos.Y][CursorPos.X].Attributes = 0;
        break;
    }

    // Gibt das aktuallisierte Feld zurück

    return Ground[CursorPos.Y][CursorPos.X];
}

// Beschreibung s.o.

void zeichneGround(CHAR_INFO Ground[HEIGHT][WIDTH], COORD CursorPos)
{
    HANDLE hConOut = GetStdHandle( STD_OUTPUT_HANDLE );
    COORD GroundSize = {WIDTH,HEIGHT};
    COORD upperLeft = {0,0};
    SMALL_RECT rect = {0,0,80,24};
    
    WriteConsoleOutputA( hConOut, &Ground[0][0], GroundSize, upperLeft, &rect );
    SetConsoleCursorPosition( hConOut, CursorPos );
}

// Beschreibung s.o.

void writeText(unsigned short int x, unsigned short int y, const char* lpBuffer,
               DWORD nNumberOfChars )
{
    HANDLE hConsoleOutput = GetStdHandle( STD_OUTPUT_HANDLE );

    SetConsoleTextAttribute( hConsoleOutput, FOREGROUND_GREEN | FOREGROUND_INTENSITY );

    COORD CursorPos = {x,y};

    SetConsoleCursorPosition ( hConsoleOutput, CursorPos );

    WriteConsoleA( hConsoleOutput, lpBuffer, nNumberOfChars, NULL, NULL );
}

// Beschreibung s.o.

void zeichneInfo()
{
    const char Text1[] = "1 - Mauer";
    const char Text2[] = "2 - Punkt";
    const char Text3[] = "3 - Diamant";
    const char Text4[] = "4 - Leer";
    const char Text5[] = "5 - Map speichern";
    const char Text6[] = "6 - Beenden";

    writeText(WIDTH+1,0,&Text1[0],sizeof(Text1));
    writeText(WIDTH+1,2,&Text2[0],sizeof(Text2));
    writeText(WIDTH+1,4,&Text3[0],sizeof(Text3));
    writeText(WIDTH+1,6,&Text4[0],sizeof(Text4));
    writeText(WIDTH+1,8,&Text5[0],sizeof(Text5));
    writeText(WIDTH+1,10,&Text6[0],sizeof(Text6));
}

// Beschreibung s.o.

int saveMap( CHAR_INFO Ground[HEIGHT][WIDTH], char aDateiname[] )
{
    // Öffnen einer Datei zum schreiben im Binärmodus

    ofstream Output (aDateiname,ios::binary);
    if (Output == NULL)
    {
        // Fehlermeldung wenn die Datei nicht geöffnet werden konnte

       const char Text[] = "Fehler! Datei konnte nicht geoeffnet werden.";
       writeText(0,HEIGHT+1,&Text[0],sizeof(Text));
       return 3;
    }

    // Diese for-Schleife schreibt die einzelnen Zeichen in die PacmanMap Datei

    for(int i=0; i<HEIGHT; i++)
    {
        for(int j=0; j<WIDTH; j++)
        {
            Output.write ((char*) &Ground[i][j], sizeof(Ground[i][j]));
        }
    }
    
    const char Text[] = "Datei wurde gespeichert!";
    writeText(0,HEIGHT+1,&Text[0],sizeof(Text));

    // kurz warten...

    DWORD Zeit = GetTickCount()/1000+2;
    while(GetTickCount()/1000<=Zeit){}

    // Die Nachricht "Datei wurde gespeichert!" wieder vom Screen entfernen

    const char Text1[] = "                        ";
    writeText(0,HEIGHT+1,&Text1[0],sizeof(Text1));

    // Schließen der Datei

    Output.close ();
    return 0;
}
... wenn ich dann aber mit folgendem Quelltext versuche die Map auszulesen funktioniert das leider nicht und ich verstehe irgendwie nicht warum.

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
#include <fstream>
#include <windows.h>
#include <iostream>

using namespace std;

#define HEIGHT 10
#define WIDTH 20

void zeichneGround(CHAR_INFO Ground[HEIGHT][WIDTH]);

int main ()
{
    CHAR_INFO Ground[HEIGHT][WIDTH];

    ifstream Input ("PacmanMap", ios::binary);
    if (Input == NULL)
    {
        cout << "Datei konnte nicht geoeffnet werden." << endl;
        system("PAUSE");
        return 3;
    }
    Input.read ((char*) &Ground[0][0], sizeof(Ground));

    zeichneGround(Ground);

    return 0;
}

void zeichneGround(CHAR_INFO Ground[HEIGHT][WIDTH])
{
    HANDLE hConOut = GetStdHandle( STD_OUTPUT_HANDLE );
    COORD GroundSize = {WIDTH,HEIGHT};
    COORD upperLeft = {0,0};
    SMALL_RECT rect = {1,1,80,24};
    
    WriteConsoleOutputA( hConOut, &Ground[0][0], GroundSize, upperLeft, &rect );
}
"Der Wald wäre sehr leise, wenn nur die begabtesten Vögel singen würden."

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

4

02.03.2009, 18:23

Und was funktioniert nicht?

5

02.03.2009, 18:39

Äh entweder das abspeichern oder das auslesen ... beim abspeichern müsste eigentlich alles funktionieren aber beim auslesen wird nicht die Map angezeigt die ich erstellt habe.
"Der Wald wäre sehr leise, wenn nur die begabtesten Vögel singen würden."

K-Bal

Alter Hase

Beiträge: 703

Wohnort: Aachen

Beruf: Student (Elektrotechnik, Technische Informatik)

  • Private Nachricht senden

6

02.03.2009, 18:41

1. Leg lieber ein eindimensionales Array an, auf welches du zweidimensional zugreifst.

2. Geh mal mitm Debugger durch ;-)

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

7

02.03.2009, 18:49

Zitat von »"Andreas2"«

Äh entweder das abspeichern oder das auslesen ... beim abspeichern müsste eigentlich alles funktionieren aber beim auslesen wird nicht die Map angezeigt die ich erstellt habe.


Schau dir die Daten doch mal im Hexeditor an, dann weißt du ob das Speichern funktioniert. Das lesen sieht, auf den ersten Blick, ok aus.

8

02.03.2009, 19:05

Ok ich begeb mich dann mal auf Fehlersuche!

Gibt es eigentlich einen HexEditor der in Visual C++ 2008 integriert ist und wo finde ich den?
"Der Wald wäre sehr leise, wenn nur die begabtesten Vögel singen würden."

9

02.03.2009, 19:38

Zitat

binär in eine Textdatei

Was willst du? Soll jetzt Text abgespeichert werden oder dann doch binaer? Gegenfrage: Warum speicherst du nicht erstmal alles als Text, dann reicht auch Notepad um das Ergebnis zu bestaunen. Erhoffst du dir irgendwas, wenn du binaer das ganze speicherst?

PS: Ich finde ja so 'ne Verweise auf dem Debugger, ohne mal ueber Sinn und Unsinn des Problems nachgedacht zu haben, fast genauso bloed.
If it were not for laughter, there would be no Tao.

10

02.03.2009, 19:59

Zitat von »"knivil"«

Zitat

binär in eine Textdatei

Was willst du? Soll jetzt Text abgespeichert werden oder dann doch binaer? Gegenfrage: Warum speicherst du nicht erstmal alles als Text, dann reicht auch Notepad um das Ergebnis zu bestaunen. Erhoffst du dir irgendwas, wenn du binaer das ganze speicherst?

1. nun, du kannst auch in einer .txt binärdaten speichern, nicht? Ich hoffe nur, das er nicht versucht, das mim Texteditor zu schreiben und binär zu lesen, oder umgekehrt
2. Speichervorteil: 65535 (word unter Win32) braucht binär 2 Bytes, als text schon 5; zum debuggen ist text aber wiklich besser

Werbeanzeige