Zeichenweises Lesen einer .txt datei

tischn

Grünschnabel
Hallo,
Ich programmiere an einem kleinen Konsolen spiel Snake (c++ compiler, windows). Dazu habe ich einen Map-Editor geschrieben, mit dem man eingene Maps erstellen kann, und diese abspeichern. Abgespeichert werden sie in einer .txt datei in einer Zeile. Nun will ich diese .txt Datei lesen und jedes Zeichen in eine eigene Variabel setzen (2-dimensionaler Array). Hier steht der Code (sehr stark vereinfacht):
Code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
#include <conio.h>

int main()
{
    int timer0;
    int timer1;
	int timer2;
    char xy[30][20];
    char mapdir[]=".\\maps\\";
    char name[64];
	FILE *datei;
	char c;


    for(timer1=0; timer1<20; timer1++)
    {
        for(timer0=0; timer0<30; timer0++)
        xy[timer0][timer1]=' ';
    }
    system("cls")";
    printf("Bittte geben sie den Namen der Map ein:\n");
    chdir(mapdir);
    scanf("%s",&name);
    strcat(name, ".txt");
    fopen(datei, "r");
    timer0=0;
    timer1=0;
    timer2=0;
    while(timer1!=20)
    {
        while(timer0!=30)
        {
            while( (c=fgetc(datei)) != EOF)
            xy[timer0][timer1]=c;
            timer0=timer0++;
            printf("%c", xy[timer0][timer1]);
        }
        timer1++;
        timer0=0;
        printf("\n);
    }
    fclose(datei);
    system("PAUSE");
}
Der Output sollte folgendes sein:
Code:
 ______________________________
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|                              |
|______________________________|
So sieht er allerdings aus;
Code:
                             t
                             e
                             s
                             t
                             .
                             t
                             x
                             t

                             )
                             Ö
                             u




                             á
                             ?
                             (
Das einzige, was ich darüber herausgefunden habe, ist das dieses test.txt immer der Dateiname der .txt datei ist
Kann jemand helfen?
 
Hi und Willkommen bei tutorials.de,

"c++ compiler"
Meinst du vllt. Visual Studio?
C++-Compiler gibts mehrere.

Das Problem:
Du liest die gesamte Datei in [0][0] vom Array ein.
Weil ein neues Zeichen das Letzte immer überschreibt
hast du am Schluss nur das letzte Zeichen drin.
Der Rest vom Array ist mit irgendwas Unvorhersehbarem gefüllt.
Mach die Einleseschleife vor der doppelten while.

Paar Tipps zum Code:

Ist es Absicht, die Datei spaltenweise zu nehmen?
123
456
789
in der Datei wird in deinem zweidim. Array zu
147
258
369

".\\" bei ".\\maps\\" ist für Windows normalerweise nicht nötig.

Wenn du den Dateinamen ja schon mit strcat ein ".txt" dazumachst
kannst du den Pfad "maps\\" ja auch mit Stringfunktionen dazumachen (strcpy/strcat),
statt chdir zu verwenden.

Statt einem scanf %s wäre bei Dateipfaden gets (oder fgets) angebrachter.
%s hat nämlich ein (gewolltes) Problem mit Leerzeichen etc.,
die in einem Dateinamen aber sein dürfen.

Statt den while-Schleifen wären für den Fall
(bekannte Anzahl zum Durchzählen) for-Schleifen "schöner":
C++:
for(timer0 = 0; timer0 < 20; timer0++)
...
Dann erspart man sich das ++ im Schleifenblock auch.

C++:
timer0=timer0++;
kann auch einfach
C++:
timer0++;
sein.

Warum nennst du die Zählvariablen eigentlich Timer?
Bei Timer denkt man an irgendwas Zeitbezogenes.
 
Danke für die schnelle Antwort und die vielen Tipps


"c++ compiler"
Meinst du vllt. Visual Studio?
C++-Compiler gibts mehrere.
Ja es ist der Visual Studio 2005/2008 compiler


Du liest die gesamte Datei in [0][0] vom Array ein.
Weil ein neues Zeichen das Letzte immer überschreibt
hast du am Schluss nur das letzte Zeichen drin.
Der Rest vom Array ist mit irgendwas Unvorhersehbarem gefüllt.
Mach die Einleseschleife vor der doppelten while.
Das sollte so sein, weil in der Datei eigentlich alle Felder (bzw. Variablen) stehen und ich jedes einzelne so überschreibe


Warum nennst du die Zählvariablen eigentlich Timer?
Bei Timer denkt man an irgendwas Zeitbezogenes.
Das ist mein erstes c-Programm. Als ich damit angefangen habe, wusste ich nicht was for-schlaufen bewirken. Ich habe alle timer genannt, weil ich die Variabeln im Programm für alle vorübergehenden Variabeln verwende. Manchmal hat das etwas mit zeit zu tun


Weshalb steht aber beim Output die der Dateiname und so komische Zeichen anstatt der richtigen Map, wie sie in der Datei steht?
 
Angenommen, das ist dein Dateiinhalt:
123
456
789
Und das ist am Anfang im Array (wobei x für "Leer" steht):
xxx
xxx
xxx

Dein Einlesen beginnt so:
123 1xx
456 xxx
789 xxx

123 2xx
456 xxx
789 xxx

123 3xx
456 xxx
789 xxx

123 4xx
456 xxx
789 xxx

...

123 9xx
456 xxx
789 xxx

Du liest schon beim ersten Arrayelement alles ein.

Dann, wenns zum nächsten Arrayelement kommt, wird aus der Datei
gar nichts mehr eingelesen, weil sie schon am Ende (EOF) ist.
Also bleibt es im Array auf x / Leer.
Usw...

Am Schluss hast du dann eben
9xx
xxx
xxx
statt
123
456
789
und gibts das immer mit printf aus.

Und das x (also "Leer") ist in C/C++ kein unsichtbares Leerzeichen oder so
(das müsste man extra reinschreiben, wenn man will),
sondern irgendein zufälliges Zeug.
In deinem Fall steht in den ungefüllten Bereichen uA. der Dateiname.


Werde gleich einen verbesserten Code schreiben...

edit:
Also, statt:
C++:
while(timer1!=20)
{
    while(timer0!=30)
    {
        while( (c=fgetc(datei)) != EOF)
        xy[timer0][timer1]=c;
        timer0=timer0++;
        printf("%c", xy[timer0][timer1]);
    }
    timer1++;
    timer0=0;
    printf("\n);
}
das:
C++:
for(timer0 = 0; timer0 < 30; timer0++)
{
    for(timer1 = 0; timer1 < 20; timer1++)
        xy[timer0][timer1] = fgetc(datei);
}
for(timer0 = 0; timer0 < 30; timer0++)
{
    for(timer1 = 0; timer1 < 20; timer1++)
        printf("%c", xy[timer0][timer1]);
    printf("\n");
}
Hab die Fehlerprüfung weggelassen, damit einfacher verständlich.
 
Zuletzt bearbeitet:
@deepthroat:
Du kennst den Standard ja besser, aber rein logisch
wird zuerst der gleiche Wert zugewiesen -> sinnlos
und dann ++.

C++:
timer0 = timer1++
geht doch auch, also versteh ich das Undefiniert nicht wirklich.

Und wenn es undefiniert ist, sollte es erst recht geändert werden.
tischn wird wohl ein einfaches ++ gemeint haben.

Der Code oben hat keine Fehlerprüfung, ich weiß.

@tischn: Hab den Code oben dazueditiert.
 
Danke

Leider funktioniert es immer noch nicht. Jetst ist einfach alles mit
Code:
' '
überschrieben. Und wegen der Fehlerüberprüfung:

Code:
if(datei != NULL)
{
    // Datei lesen
}
else
{
    printf("Die Datei konnte nicht geöffnet werden")
}

ist das richtig?

C++:
for(timer0 = 0; timer0 < 30; timer0++)
{
    for(timer1 = 0; timer0 < 20; timer0++)
        xy[timer0][timer1] = fgetc(datei);
}
for(timer0 = 0; timer0 < 30; timer0++)
{
    for(timer1 = 0; timer0 < 20; timer0++)
        printf("%c", xy[timer0][timer1]);
    printf("\n");
}
Hab die Fehlerprüfung weggelassen, damit einfacher verständlich.

Ich denke dass du bei der 2. und 4. For-Schlaufe einen Fehler gemacht hast. Heisst es nicht:
C++:
for(timer1 = 0; timer1 < 20; timer1++)
//...
anstatt:
C++:
for(timer1 = 0; timer0 < 20; timer0++)
//...
und braucht man nicht noch eine Klammer ({}) bei der 2. und 4. For-schleife?
 
Zuletzt bearbeitet von einem Moderator:
@Code: Hatte Fehler drin (statt timer1 versehentlich timer0 genommen, mehrfach).
Kopier ihn nocheinmal raus.

@Fehlerprüfung: Ja, das ist richtig (zumÜberprüfen, ob die fopen funktioniert hat).
fopen ist aber nicht das Einzige.
Mein Code verlässt sich zB. darauf, dass genug in der Datei steht.
Wenn die Datei zu kurz ist, gibts keine Fehlermeldung etc.
(dafür wieder die EOF-Sache oder Dateilänge ermitteln oder...).

edit zum neuen Beitrag:
Genau, du hast meinen Fehler gefunden.

Zu den fehlenden {}:
Wenn der "Inhalt" aus nur einem Befehl besteht
(egal wie lang, aber nur ein ; als Ende)
braucht man die {} nicht unbedingt.
Gilt auch für if, while...
 
Danke aber nun ist die Karte einfach lehr...

Inhalt der .txt-datei
Code:
 |||||||||||||||||||_                  __  |||||||||||     __ _          _     __ _          _     __ _          _     __ _          _     __ _          _     __ _          _     __ _          _     __ _          _     __ _          _     __ _          _     __ _          _     __ _          _     __ _          _     __ _          _     __ _          _     __ _          _     __ _          _     __ _          _     __ _          _     __ _            *00 __ _          _     __ _          _     __ _          _     __ _          _     __  |||||||||||     __                  _ |||||||||||||||||||

(das *00 ist die Schlange :D)
 
@deepthroat:
Du kennst den Standard ja besser, aber rein logisch
wird zuerst der gleiche Wert zugewiesen -> sinnlos
und dann ++.
Es gibt in diesem Ausdruck keinen Sequenzpunkt. Trotzdem wird zweifach verändernd auf den Wert der Variablen zugegriffen.

Es ist nicht definiert in welcher Reihenfolge das passiert, da der C & C++ Standard nur erlaubt den Wert von Variablen zwischen zwei Sequenzpunkten max. einmal zu verändern.

Es könnte also zuerst timer0++ ausgeführt werden (was den Wert von timer0 um 1 erhöhen würde, aber den alten Wert zurückgibt), dann die Zuweisung timer0 = <alter Wert von timer0>.

Es könnte auch so sein, wie du vermutet hast.

Es könnte auch einfach etwas ganz anderes passieren. Es ist einfach undefiniert / kein standard konformer Code.

Gruß
 
Zurück