Frage zum Auslesen/Verarbeiten einer Text-Datei
-
Hallo, ich bin E-Technikstudent und habe die Aufgabe bekommen, in C eine Spieleverwaltungssoftware zu schreiben.
Diese soll in der Lage sein, die installierten Spiele aus eine Datei einzulesen, dabei selbstständig erkennen, für wieviel Spieler das Spiel geeignet ist, und nur diejenigen Spiele anzeigen, die für die angegebene Anzahl Spieler verfügbar ist.Dazu sollen die Spieledaten in einer Datei "spiele.dat" gespeichert werden. Diese Daten sollen aus Spielenamen, Minimums-, Maximumspieleranzahl und Dateiname der ausführbaren exe-Datei bestehen. Dies soll pro installiertem Spiel zeilenweise in der Datei "spiele.dat" gespeichert sein/werden, wenn neue Programme installiert werden, denn das soll mein kleines Programm so ganz nebenbei auch noch können.
Um die einzelnen Spieledaten im Programm verarbeiten zu können, habe ich schonmal folgendes struct angelegt, woraus dann die Spieleliste werden soll:
struct sSpiele {
char Spielname[20] = {}, Dateiname[200] = {};
int min, max;
struct sSpiele *naechster;
};Könnt Ihr mir jetzt dabei helfen, wie ich es hinbekomme, die Datei "spiele.dat" auszulesen und in meine Liste zu speichern. Dazu wäre es echt hilfreich, wenn ihr mir auch sagen würdet, wie man diese Datei am besten aufbaut, also Trennung zwischen den einzelnen Datenteilen, damit das Unterscheiden zwischen den chars und den ints möglichst einfach zu bewerksteligen ist. Solltet ihr vorschläge bzl. der Liste haben, bin ich euch auch dankbar.
Aber bitte bedenkt: Ich bin absoluter C-Anfänger, ich fühle mich durch dieses Projekt absolut überfordert, versucht mir liebend gerne alles zu erklären, was ich noch lernen kann/muss, aber seit mir nicht böse, wenn ich es nicht auf Anhieb verstehe und doof nachfrage.
Für eure hoffentlich schnelle Hilfe (es soll ja erst in 4 tagen fertig sein
) bedanke ich mich schonmal recht herzlich
-
guckst du mal hier nach. Ein c und c++ Tutorial für Unix, DOS, Win31, Win98, Winnt.
Ich glaube Kapitel acht ist ungefähr das, was du suchst. Les den Rest auch ;). Wenn was unklar ist, nochmal fragen.
-
Ich hab mir das Kapitel 8 jetzt mal aufmerksam durchgelesen. Darin geht es leider nur darum, wie man ein Directoylisting hinbekommt, was dann auch noch für 3 verschiedene Plattformen erklärt wird.
Ich hätte vielleicht in der ersten Bitte um Hilfe darauf hinweisen sollen, dass wir strikt nach ANSI 90, also absolut plattformunabhängig programmieren sollen. Deswegen ist es auch nicht möglich mit Directorylistings zu arbeiten, denn dass war auch meine erste Idee, man definiert einen Pfad, in den alle Spiele.exen einfach nur hineinkopeirt werden müssen, diese haben eine bestimmte Formatierung (Spielname.Mindestspieleranzahl.Maxiumspieleranzahl.exe) und schon hätte ich auf das Einlesen und Erstellen einer eigenen Spieleliste in Dateiform verzichten können, aber da soetwas nicht platformunabhängig zu realisieren ist, muss ich darauf zurückgreifen, dass ich eine Eigene Datei habe, in die diese ganzen Informationen eingetragen werden (und das bei Instalation von Spielen durch meine Spielverwaltungssoftware, ich muss also in meinem Programm eine Stelle haben, in der ich dem Programm sage, "ich will ein neues Programm installieren, es heißt xyz, es ist für 2-4 Spieler und du findest es in Zukunft unter dem Namen 'C:\spiele\xyz.exe').Und genau das ist mein Problem, wie erstelle ich jetzt so eine Datei, wie lese ich sie, wie unterscheide ich, ob ich gerade den Spielenamen oder die Mindestspieleanzahl oder dergleichen gelesen hab, und wie bekomme ich diese Einzeldaten aus der Datei in eine programminterne Liste??
Über weitere Hilfe wäre ich äußerst dankbar...
-
Ich hab das als Beispiel angegeben, was auch auf Dateien angewendet werden kann,
anstatt auf Verzeichnisse. C ist es eigentlich egal, ob das ein Verzeichnis oder
eine Datei ist. Der Zugriff ist Grundsätzlich gleich.Bei Verzeichnissen ist schon eine Struktur (stat) vordefiniert die Du hier
selbst schreibst (struct sSpiele). Und so wie ich das sehe, ist das ebenfalls eine
einfach verkettete Liste (struct sSpiele *naechster).Was Du Dir überlegen musst ist, wie organisiere, bzw lege, ich die Daten in der
Datei (ab). Danach richtet sich dann die weitere Verarbeitung.Z.B:
1. Datensatz
xyz,C:\spiele\xyz.exe,2,4
2. Datensatz
abc,C:\spiele\abc.exe,2,12
usw.Die Kommas als Trenner benutzen und mit fscanf in die Struktur einlesen.
Beispiel aus C in a Nutshell mit deinen Angaben:struct sSpiele{ char Spielname[20]; char Dateiname[200]; unsigned int min; unsigned int max; struct sSpiele *naechster; }; .... FILE * fp; int results = 0; struct sSpiele *spiele, *sp_neu, *sp_root; /* ... (extra Funktion) Speicher für Struktur allokieren und naechster auf NULL setzen ...*/ /* ... Datei öffnen usw ... */ /* gehe davon aus, dass Komma der Trenner ist siehe oben und alles natürlich in einer Schleife - fscanf gibt EOF zurück, wenn die Datei zu Ende ist. */ results = fscanf(fp, "%20[^,],%200[^,],%u,%u", sp_neu->Spielname, sp_neu->Dateiname, &sp_neu->min, &sp_neu->max); /* Der Rest ist ganz normale Verarbeitung in einer einfach verketteten Liste, mit sp_neu immer den naechsten Datensatz auslesen, sp_root und spiele auf den ersten Datensatz(in der Struktur) setzen, spiele->naechster auf den naechsten Datensatz(Struktur) usw. setzten und mit spiele = spiele->naechster weiter wandern */
Nichts anderes steht auch in diesem Kapitel drin, halt nur mit Verzeichnissen.
Wenn Du in die Datei reinschreibst, dann halt mit fseek den Dateizeiger ans Ende
setzen und Datensatz reinschreiben. Bei Anzahl der Spieler min und max abfragen.
Du mußt das ja nicht wie in dem Tutorial rekursiv machen, gibt aber bestimmt
Extrapunkte :). Profs stehen auf sowas.
-
Ich hab das einfach mal so versucht, wie du es mir geschrieben hast, nur leider list er die ganze Zeile aus der Datei, und packt die in das Array Dateiname, ohne auf die Kommata zu achten.
Mein struct sieht folgendermaßen aus:
struct sInstalliert {
char Spielname[20];
char Dateiname[NAME_MAX+1];
char Dateiverzeichnis[PATH_MAX+1];
unsigned int min;
unsigned int max;
struct sInstalliert *naechster;
} *pInst_erster, *pInst_aktuell;Die Funktion zum Einlesen sieht folgendermaßen aus:
/* Liest die Datei mit den Spielen ein und schreibt die Spiele in eine Liste */
int spiele_einlesen () {
FILE *pDatei;
int Ergebnis = 1;
i = 0;
pDatei = fopen("c:\\spiele.dat", "r");
if (pDatei == NULL) {
fehlermeldung (38);
}
else {
pInst_erster = malloc(sizeof(struct sSpiele));
pInst_aktuell = pInst_erster;
while (Ergebnis > 0) {
Ergebnis = fscanf(pDatei,"%20[,],%(NAME_MAX+1)[,],%(PATH_MAX+1)[^,],%u,%u", &pInst_aktuell -> Spielname, &pInst_aktuell -> Dateiname, &pInst_aktuell -> Dateiverzeichnis, &pInst_aktuell -> min, &pInst_aktuell -> max);
printf("%s", pInst_aktuell -> Spielname);
pInst_aktuell -> naechster = malloc(sizeof(struct sSpiele));
pInst_aktuell = pInst_aktuell -> naechster;
i++;
}
free (pInst_aktuell);
}
return i;
}Der Einzige Eintag in der Spieledatei sieht wie folgt aus:
Memory,Memory.exe,,2,2,und zu guter letzt, die Ausgabe des printf-Befehls, welchen ich extra auf Fett gesetzt habe, um ihn hier beser anzuzeigen:
MemoryMemory.exex=
-
Für die Formatkennungen kannst du keine Berechnungen einbauen - %(NAME_MAX+1)[^,] ist keine legale scanf-Kennung. Außerdem wird bei der Größenangabe nicht das abschließend nötige Stringende-Zeichen berücksichtigt.
-
Auch wenn ich dort 256 für NAME_MAX+1 und 1025 für PATH_MAX+1 nehme, funktioniert es immernoch nicht, das +1 ist übrigens genau dafür da das \0 als Stringende-Zeichen zu speichern
-
flowalder schrieb:
Auch wenn ich dort 256 für NAME_MAX+1 und 1025 für PATH_MAX+1 nehme, funktioniert es immernoch nicht, das +1 ist übrigens genau dafür da das \0 als Stringende-Zeichen zu speichern
Schreib die Zahlen ohne das +1 hin.
Wenn du nur 4 Werte in der Datei drin hast und 5 auslesen willst, bekommst natürlich Datensalat. Dann mußt Du einen Dummy einführen:Memory,Memory.exe, ,2,2
Einfach ein Space-Zeichen wie hier hinter dem Komma von Memory.exe genügt schon und hinter dem letzten Eintrag (der 2) kein Komma mehr. Wenn Du die spiele.dat von Hand erstellst,
hinter dem letzten Datensatz nicht mehr auf [ENTER] oder [RETURN] drücken.
Sonst meint der Dateizeiger da ist noch ein Datensatz drin und liest den letzten
ein zweitesmal aus. Ach ja noch ein Fehler:
bei den Strings wie pInst_aktuell->Spielname kein & vor den Namen setzen, nur bei
den Zahlenwerten.Bei der Abfrage würde ich mal EOF versuchen:
while(fscanf(pDatei,"%20[^,],%255[^,],%1024[^,],%u,%u", pInst_aktuell -> Spielname, pInst_aktuell -> Dateiname, pInst_aktuell -> Dateiverzeichnis, &pInst_aktuell -> min, &pInst_aktuell -> max) != EOF) { ...
Das wärs fürs erste
Nur Mut
-
Möglicherweise mußt Du pInst_aktuell noch initialisieren damit
kein Speichzugriffsfehler auftritt:*pInst_aktuell = (struct sInstalliert){"", "", "", NAME_MAX, PATH_MAX};
Anstatt den beiden MAX-Werten geht auch 255 und 1024.