- Registriert
- 3 Aug. 2014
- Beiträge
- 28.573
Hallo,
mal eine grundlegende Frage zu C, vielleicht steht ich dabei auch nur etwas auf dem Schlauch:
Wie kann man sinnvoll den folgenden Inhalt aus einer Textdatei auslesen und die Werte aufsplitten?
Hier der Beispielinhalt:
[src=text]2 // Anzahl der Testcases (immer nur die erste Zeile)
100 // Credit
3 // Item count
5 75 25 // Products
200 // C
7 // I
150 24 79 50 88 345 3 // P
// und so weiter[/src]
Momentan mache ich es wie folgt.
Kurze Anmerkung, da der Code nicht wirklich kommentiert ist - mittels "fgetc" ein Zeichen (readIn) auslesen und auf einen char Array (readData) auf Position (writePos) schreiben - kommt ein Space oder Newline, wird an writePos ein Null-Terminiert gesetzt und mittels "atoi" bzw. "strtoul" (für vorzeichenlose Integer) die Werte als Zahl aus (readData) aus- bzw. eingelesen. (mode) dient dazu zwischen (C)redit, (I)tem count oder (P)roducts umzuschalten.
Das funktioniert auch, nur Frage ich mich ob ich es nicht unnötig komplex anstelle wenn ich Zeichenweise vorgehen.
Ich hatte schon mal "fscanf" versucht zu verwenden, aber da die Zeilen unterschiedlich viele Attribute haben, weiß ich nicht wie ich es damit parsen kann. Geht das überhaupt damit?
Oder wäre "fgets" die bessere Alternative um X Zeichen einzulesen ? Wenn man die Position eines Spaces kennt bei einer Aufzählung von Produkt-Preisen?
Hier mal mein Code dazu*:
* so etwas wie storeData kann ignoriert werden, das ist nur der Speicherort für die Werte.
[src=c] FILE* inputFile = fopen(inputFilePath, "r");
char readIn = '\0';
char readData[32] = "\0";
int writePos = 0;
int mode = 0;
unsigned int lines = 0;
unsigned int index = 0;
unsigned int position = 0;
storeData *current = NULL;
storeData *previous = NULL;
storeData *first = NULL;
char *end; // used for strtoul for unsigned product prices
while (!feof(inputFile)) {
readIn = fgetc(inputFile);
if (readIn == ' ') {
readData[writePos] = '\0';
if (mode == 2) {
current->products[index] = strtoul(readData, &end, 10);
//printf("index: %d, %d\n", (index+1), current->products[index]);
++index;
}
readData[0] = '\0';
writePos = 0;
} else if (readIn == '\n') {
if (lines == 0) {
// Ignore the first line
readData[writePos] = '\0';
writePos = 0;
++lines;
continue;
}
readData[writePos] = '\0';
writePos = 0;
if (mode == 2) {
current->products[index] = strtoul(readData, &end, 10);
//printf("index: %d, %d\n", (index+1), current->products[index]);
}
++mode;
if (mode >= 4) {
mode = 1;
}
if (mode == 1) {
if (current != NULL) {
previous = current;
}
current = (storeData*) calloc(1, sizeof(storeData));
if (first == NULL) {
first = current;
}
current->first = first;
current->previous = previous;
current->next = NULL;
current->credit = 0;
current->items = 0;
current->index = position;
if (previous != NULL) {
previous->next = current;
}
++position;
}
switch (mode) {
case 1:
// [C]redit
current->credit = atoi(readData);
break;
case 2:
// tem count and product storage
current->items = atoi(readData);
current->products = (unsigned int*) calloc(current->items, sizeof(unsigned int));
index = 0;
break;
default:
break;
}
++lines;
} else {
readData[writePos] = readIn;
++writePos;
}
}[/src]
mal eine grundlegende Frage zu C, vielleicht steht ich dabei auch nur etwas auf dem Schlauch:
Wie kann man sinnvoll den folgenden Inhalt aus einer Textdatei auslesen und die Werte aufsplitten?
Hier der Beispielinhalt:
[src=text]2 // Anzahl der Testcases (immer nur die erste Zeile)
100 // Credit
3 // Item count
5 75 25 // Products
200 // C
7 // I
150 24 79 50 88 345 3 // P
// und so weiter[/src]
Momentan mache ich es wie folgt.
Kurze Anmerkung, da der Code nicht wirklich kommentiert ist - mittels "fgetc" ein Zeichen (readIn) auslesen und auf einen char Array (readData) auf Position (writePos) schreiben - kommt ein Space oder Newline, wird an writePos ein Null-Terminiert gesetzt und mittels "atoi" bzw. "strtoul" (für vorzeichenlose Integer) die Werte als Zahl aus (readData) aus- bzw. eingelesen. (mode) dient dazu zwischen (C)redit, (I)tem count oder (P)roducts umzuschalten.
Das funktioniert auch, nur Frage ich mich ob ich es nicht unnötig komplex anstelle wenn ich Zeichenweise vorgehen.
Ich hatte schon mal "fscanf" versucht zu verwenden, aber da die Zeilen unterschiedlich viele Attribute haben, weiß ich nicht wie ich es damit parsen kann. Geht das überhaupt damit?
Oder wäre "fgets" die bessere Alternative um X Zeichen einzulesen ? Wenn man die Position eines Spaces kennt bei einer Aufzählung von Produkt-Preisen?
Hier mal mein Code dazu*:
* so etwas wie storeData kann ignoriert werden, das ist nur der Speicherort für die Werte.
[src=c] FILE* inputFile = fopen(inputFilePath, "r");
char readIn = '\0';
char readData[32] = "\0";
int writePos = 0;
int mode = 0;
unsigned int lines = 0;
unsigned int index = 0;
unsigned int position = 0;
storeData *current = NULL;
storeData *previous = NULL;
storeData *first = NULL;
char *end; // used for strtoul for unsigned product prices
while (!feof(inputFile)) {
readIn = fgetc(inputFile);
if (readIn == ' ') {
readData[writePos] = '\0';
if (mode == 2) {
current->products[index] = strtoul(readData, &end, 10);
//printf("index: %d, %d\n", (index+1), current->products[index]);
++index;
}
readData[0] = '\0';
writePos = 0;
} else if (readIn == '\n') {
if (lines == 0) {
// Ignore the first line
readData[writePos] = '\0';
writePos = 0;
++lines;
continue;
}
readData[writePos] = '\0';
writePos = 0;
if (mode == 2) {
current->products[index] = strtoul(readData, &end, 10);
//printf("index: %d, %d\n", (index+1), current->products[index]);
}
++mode;
if (mode >= 4) {
mode = 1;
}
if (mode == 1) {
if (current != NULL) {
previous = current;
}
current = (storeData*) calloc(1, sizeof(storeData));
if (first == NULL) {
first = current;
}
current->first = first;
current->previous = previous;
current->next = NULL;
current->credit = 0;
current->items = 0;
current->index = position;
if (previous != NULL) {
previous->next = current;
}
++position;
}
switch (mode) {
case 1:
// [C]redit
current->credit = atoi(readData);
break;
case 2:
// tem count and product storage
current->items = atoi(readData);
current->products = (unsigned int*) calloc(current->items, sizeof(unsigned int));
index = 0;
break;
default:
break;
}
++lines;
} else {
readData[writePos] = readIn;
++writePos;
}
}[/src]
Zuletzt bearbeitet: