paedubucher hat geschrieben:Ich habe jetzt
eine Version komplett ohne Puffer geschrieben. Es geht zwar schon in die Richtung Spaghetticode, aber es hält sich noch im Rahmen. Jetzt brauche ich nur noch das Filehandling zu schreiben.
Das neue Programm scheint auch ca. 10% schneller zu laufen als das alte, wobei solche amateurhaften Messungen immer mit Vorsicht zu geniessen sind. Die Performancesteigerung ist aber durchaus nachvollziehbar.
Das Programm funktioniert leider nicht korrekt. Wenn nach einem Punkt ein Schlusszeichen kommt, darf das nicht einfach ausgegeben werden, es muss durch die gleiche Logik laufen. Darum habe ich den Ansatz wieder verworfen.
Darum jetzt zu meillos lookahead-Ansatz und etwas Programmier-Pädagogik
Ich habe einen kleinen Puffer, der immer einige Zeichen aufnehmen kann.
buf_i ist immer der aktuelle Index, wo als nächstes geschrieben werden kann. Gelesen soll nur von der Stelle 0 werden. Nun habe ich drei Funktionen:
Code: Alles auswählen
int buf_getchar();
void buf_discard(int n);
char *buf_next(int n);
Die erste ist ein getchar, das mit einem Puffer arbeitet, dazu gleich. Die zweite schiebt den Puffer um n Stellen nach links, rechts wird mit 0 aufgefüllt.
Code: Alles auswählen
void buf_discard(int n)
{
int i;
while (n--) {
for (i = 0; i < LOOKAHEAD - 1; i++) {
buf[i] = buf[i + 1];
}
buf[i] = 0;
buf_i--;
}
}
Die dritte Funktion gibt die nächsten n Zeichen des Puffers zurück. Wenn zu wenig da ist, enthält der String eben den Wert 0 für die übrigen Stellen.
Code: Alles auswählen
char *buf_next(int n)
{
int i;
char *str = (char*)malloc(sizeof(char) * n);
for (i = 0; i < n; i++) {
str[i] = (i < buf_i) ? buf[i] : 0;
}
return str;
}
Nun kommt das Hauptproblem: buf_getchar():
Code: Alles auswählen
int buf_getchar()
{
int c;
if (buf_i > 0) {
c = buf[0];
buf_discard(1);
return c;
} else {
do {
c = getchar();
buf[buf_i++] = c;
} while (c != '\n' && c != EOF && buf_i < LOOKAHEAD);
}
c = buf[0];
buf_discard(1);
return c;
}
Wenn der Buffer nicht leer ist (buf_i > 0), wird das Zeichen links vom Puffer unter c abgespeichert, der Puffer einmal nach links durchgeschoben, und c zurückgegeben. Wenn hingegen noch nichts im Puffer ist, wird soviel eingelesen, wie möglich (bis zu EOF, \n oder halt, bis der Puffer voll ist). Nach dem erfolgten Einlesen wird nun wiederum das Zeichen ganz links zurückgegeben und der Puffer nach links durchgeschoben.
Nun stehe ich vor einem Henne-Ei-Problem: Wenn der Puffer etwas drin hat, aber noch nicht voll ist, sollte ich ja zunächst probieren, noch etwas hineinzulesen, bevor ich ihn aufbrauche. Der Puffer soll ja immer soviel laden, wie möglich. Ob etwas zu lesen ist weiss ich aber erst, wenn ich getchar() aufrufe. Und wenn ich das tue, aber nichts zu lesen ist, bleibt das ganze dort hängen.
Ich müsste ja irgendwie herausfinden können, ob da noch was zu lesen ist. Soll ich mir merken, warum das puffern abgebrochen wurde? Wenn es durch \n bzw. EOF war, dann ist halt nichts mehr zu lesen, wenn es aber durch Erreichen der Pufferlänge war, soll ich versuchen weiterzulesen? Das könnte ein Ansatz sein...
Oder sollte ich einfach einen input-Buffer bauen, der sich laufend vergrössert, sodass er immer die ganze Zeile halten kann?