[C] Zahlen aus Datei lesen

n1smo

Mitglied
Hi, es gibt zwar schon etliche Beiträge zudem Thema hab aber leider nichts passendes gefunden was mir weiterhelfen könnte.

Ich hab folgendes Problem.
Ich hab ne Datei in der Zahlen wie folgt drin stehen könnten, als Beispiel:

2,394,34,95553,233949586
29,595,4353
3450,534,2,4,67,6,7,8,9

Also alles variabel, die Zahlen selber, die Zahlen pro Zeile als auch die Anzahl der Zeilen.

Ich such jetzt einen gescheiten weg diese Zahlen einzulesen.
Das Programm soll alle Zahlen durchgehen und die grösste in einer Variabel speichern.

Der einzige Weg der mir einfällt dies zu machen ist sich jedes Zeichen einzeln per fgetc zu holen, die vorher gespeicherte Zahl mit 10 zu multiplizieren und die aktuell eingelesene zu addieren. So ungefähr:

int nummer, c;
while( (c=fgetc(datei)) != EOF)
if (c>='0' && c<='9'){
nummer=nummer*10 + c;
}
Das ganze wird halt immer so lange gemacht bis ein komma bzw new line zeichen kommt.

Ist natürlich alles andere als elegant die Methode, daher wollt ich mich mal informieren wie eine bessere implementierung aussehen könnte.
 
Hallo,

nach deinem Beispiel sieht es so aus, dass in der Datei Integer-Zahlen stehen, die mit Komma getrennt sind.
Da könntest du folgendes machen:
- Zeile aus Datei einlesen
- mit "strtok" die Zeile zerlegen, so dass man die einzelnen Strings mit den Zahlen erhält
- mit "atoi" den String in einen Integer konvertieren

Gruß
MCoder
 
Hab noch nie mit strtok gearbeitet, das könnte evtl das Problem des einlesens lösen, müsste ich mir mal genau angucken. Werd das wenn ich Zeit finde mal probieren, sollte jemand irgendwelche Code schnipsel haben wäre ich auch dankbar.

Danke erstmal
 
Also hat alles gut geklappt, danke, nun hab ich aber noch eine Frage wenn ich die Zeilen mit fgets einlese, muss ich ja eine maximale zeilenlänge angeben. Kann ich das irgendwie umgehen, so dass die Zeile beliebig lang sein darf?
 
Hallo,

die Funktion "fgets()" liest bis einschließlich des Zeilenumbruch-Zeichens oder eben nur soviel, wie der bereitgestellte Speicher hergibt. Du könntest also schauen, ob das letzte eingelesene Zeichen ein Zeilenumbruch ist. Wenn ja, hast du die Zeile komplett eingelesen, ansonsten muss du solange weiter einlesen, bis der Zeilenumbruch kommt und dir dann die Zeile zusammenstückeln.

Muss es eigentlich unbedingt C sein? Mit C++ wäre es nämlich einfacher.

Gruß
MCoder
 
Jo muss leider C sein, und wie genau prüfe ich das letzte eingelesene Zeichen?
Und nehmen wir mal an der Speicher ist voll aber das war noch nicht das letzte Zeichen, was kann man dann machen?
 
Jo muss leider C sein, und wie genau prüfe ich das letzte eingelesene Zeichen?
Einfach testen, ob das letzte Zeichen ein '\n' ist:
C++:
char buffer[] = "abcdefg\n";

if( buffer[strlen(buffer) - 1] == '\n' )
{
    // Zeilenende erkannt
}
else
{
    // ...
}
Und nehmen wir mal an der Speicher ist voll aber das war noch nicht das letzte Zeichen, was kann man dann machen?
Genau das ist die Stelle, wo es bei C etwas umständlich wird. Du musst mit dynamisch alloziertem Speicher arbeiten, den du dem Bedarf entsprechend anpassen musst (Verwendung von malloc, realloc und Co.).

Gruß
MCoder
 
So wie dich verstanden habe, kommt es ja nicht so sehr darauf an, die Daten zeilenweise zu verabeiten, sondern wirklich nur die Zahlen aus der gesamten Datei herauszuziehen.
Falls das letzte Zeichen ein Zeilenumbruch oder ein Komma ist, ist die Sache erledigt. Ansonsten musst du dir nur die letzte (Teil)Zahl merken und die erste (Teil)Zahl des nächsten fgets()-Aufrufes da dranhängen.
Für diesen Fall entsprechend (statischen) Speicher vorzuhalten, sollte nicht das Problem sein.

Gruß
MCoder
 
Ja sry, das muss ich noch berichtigen ich dachte auch dass ich erst alles auslesen muss, aber hat sich herausgestellt dass ich doch jede Zeile einzeln einlesen muss, und sie dann erstmal zu verarbeiten.
Im moment steig ich aber echt nicht dahinter wie ich das genau mit der Speicherverwaltung machen soll damit er bei zu langen Zahlen keine Fehler ausspuckt, theoretisch könnte ich einfach die max laenge vom puffer enorm hoch stellen, aber kein plan wie sich das auf die performance ausschlägt, bestimmt nicht so gut...

Zudem ist mir noch eine Frage aufgekommen:

Wie kann ich die gleiche Zeile per strtok 2-mal durchlaufen ohne das Puffer Array vorher kopieren zu müssen, quasi den Lesezeiger wieder an den Anfang setzen.

Hier mal ein Beispiel dazu:
char* Token
char puffer[ZEILENLAENGE];

while(fgets(puffer, ZEILENLAENGE, datei)){

Token = strtok(puffer, ",\n");

while(Token != NULL) {

// mach irgendwas...

Token = strtok(NULL, ",\n");
}

// jetzt soll die gleiche Zeile nochmal durchlaufen werden

Token = strtok(puffer, ",\n");

while(Token != NULL) {

// mach irgendwas...

Token = strtok(NULL, ",\n");
}

// funktioniert so aber nicht...

}

So funktionierts leider nicht, da dann direkt am ende weitermacht wird wo er vorher aufgehört hat also quasi bei NULL...
Im moment umgehe ich das Problem indem ich dem Puffer vorher kopiere und den zweiten durchlauf dann mit dem kopierten Puffer starte, aber das geht doch bestimmt auch besser.
 

Neue Beiträge

Zurück