#include #include #include "btree.h" /* * Fußnotensortierprogramm optimiert auf die Aufgabe aus dem Linux-Magazin * Ausgabe 10/08 Seite 30ff * * Beschränkungen: max. 2^32 Fußnoten, größte max. Nummerierung: 2^32. * Je nach Vorsortierung max. 2^32 bytes Fußnoten oder mehr, * bzw. beschränkt durch RAM. * * Funktionsweise: * Gelesen wird von stdin, ausgegeben auf stdout. Es gibt keine Hilfe oder * sonstige sinnvolle Ausgaben. * * Ich bin kein Programmierer und daher... öhm, sieht der Code * etwas Grauenhaft aus?? k.A. * Nach fast einem Tag Arbeit (ich wollte halt nur mal ein wenig C lernen, da * war mir das ganze hier Recht) hab ich jetzt auch keine Lust mehr, nochmal * drüberzugucken und noch Teile in Funktionen auszulagern etc. * * Meinen Teil hab ich mal (denke ich) auf geringen Speicherverbrauch * optimiert. Daher Langsamer durch häufiges freigeben * auch kleiner nicht benötigter Speicherbereiche(?). Speicherverbrauch ohne * b-Baum(*altzuneu) im ungünstigsten Fall etwas mehr als der untere Teil der * Eingabedatei, oder? * Die Verwendete btree Implementierung ist nicht von mir und daher u.U. * deutlich Speicherintensiver. k.A., hab keine Lust mehr noch selber was zu * implementieren ;-) * * Lizenz dieser Datei: Public Domain * Lizenz btree.c und btree.h: GPL v2. * * BUGs: Ich nutze eine btree-implementierung, die ich auf der LKML gefunden * habe. Diese steht unter der GPL v2. Ich musste eine Zeile hinzufügen, * da diese sonst nachvollziehbar Segfaults bei btree_search() lieferte. * * Wenn im Text irgendwo ein [XXX] auftaucht, wo XXX eine beliebige Zahl * ist, aber [XXX] keinen Verweis auf eine Fußnote darstellt, wird dafür * ein Verweis angelegt (die Zahl XXX also geändert), und in der * Fußnotenliste dafür die originale Zahl wieder angegeben. */ //globale Variablen int alloziierterspeicher = 0; int *neuzualt; //flacher speicher für mapping neu->alt int laufendenummer = 0; btree *altzuneu; //btree für mapping alt->neu char **fussnoten; //funktionen für die btree-lib unsigned int value(void * key) { return *(int *)key; } unsigned int keysize(void * key) { return sizeof(int); } unsigned int datasize(void * data) { return sizeof(int); } /* * fehler ausgeben und programm beenden */ fehler(char * fehlermeldung) { printf(fehlermeldung); exit(1); } /* * Es wurde eine Fußnote im Text gefunden. Diese sollte eine neue Nummer * bekommen und in die Korrespondenztabelle der alten eingefügt werden. */ int fn_einfuegen(char* altenummer_s) { int altenummer,i,neuenummer; bt_key_val * kv = NULL; //falls Speicher knapp wird, neuen alloziieren. if (alloziierterspeicher<(laufendenummer+1)) { if (alloziierterspeicher==0) { neuzualt=(int *)malloc(64*sizeof(int)); if (neuzualt==NULL) fehler("malloc: zu wenig speicher"); alloziierterspeicher=64; } else { alloziierterspeicher=alloziierterspeicher+(alloziierterspeicher); neuzualt=(int *) realloc(neuzualt,alloziierterspeicher*sizeof(int)); if (neuzualt==NULL) fehler("realloc: zu wenig speicher"); } } altenummer = atoi(altenummer_s); //alte nummer schon aufgetreten? if (laufendenummer>0) { kv = btree_search(altzuneu, &altenummer); } if (kv!=NULL) { //schon da -> vorhandene neue ausgeben return *(int *) kv->val; } else { //noch nicht da -> anfügen neuenummer = ++laufendenummer; kv = (bt_key_val*)malloc(sizeof(*kv)); kv->key = malloc(sizeof(int)); *(int *)kv->key = altenummer; kv->val = malloc(sizeof(int)); *(int *)kv->val = neuenummer; btree_insert_key(altzuneu,kv); neuzualt[neuenummer]=altenummer; return neuenummer; //TODO: neuenummer->laufendenummer } //return 100; unreachable } /* * Eine Klammer wurde im Text erkannt. Nun wird geprüft, ob dies auch eine * Fußnote ist und diese ggf. aufgenommen. */ void klammer_im_text() { char fussnotennummer[10]; int i = 0, neuenummer; char c; c=getchar(); while (c>=48 && c<=57 && i<10) { fussnotennummer[i]=c; i++; c=getchar(); } fussnotennummer[i]=0; if (c==93 && i>0) { neuenummer = fn_einfuegen(fussnotennummer); printf("[%i]",neuenummer); return; //neue Nummer eingefügt und ausgegeben. } // ist keine Fußnote, der hier eingelesene Text wird ausgegeben printf("[%s",fussnotennummer); putchar(c); } int fussnoten_folgen() { char trenntext[10] = "footnotes:"; char c; int i,j; for (i=0; i<10; i++) { c=getchar(); if (c!=trenntext[i]) { putchar('@'); for (j=0; jvalue = value; altzuneu->key_size = keysize; altzuneu->data_size = datasize; //ab hier der obere Teil (Textmodus) while ((c=getchar())!=EOF) { if (c==91) klammer_im_text(); else if (c==64) {if (fussnoten_folgen()) break;} else putchar(c); } //neuzualt-Speicher aufs nötigte schrumpfen neuzualt=(int *)realloc(neuzualt,laufendenummer*sizeof(int)); //Speicher für die Zeiger auf die Fußnoten alloziieren. fussnoten=(char **)malloc(laufendenummer*sizeof(char*)); //TODO:hier wird 1*sizeof(int) verschenkt, da fussnoten[0] nie vorkommen wird //ab hier der untere Teil (Fußnotenmodus) printf("@footnotes:"); alloziierterspeicher = 0; while ((c=getchar())!=EOF) { if (c==91) { i=0; c=getchar(); while (c>=48 && c<=57 && i<10) { fussnotennummer[i]=c; i++; c=getchar(); } fussnotennummer[i]=0; if (c==93 && i>0) //fussnotenanfang gefunden { if (aktuellefussnote) //string beenden fussnoten[aktuellefussnote][aktuellefussnotenlaenge++]=0; if (aktuellefussnotenmaxlaenge>aktuellefussnotenlaenge && aktuellefussnote) //TODO: schrumpfen könnte man auch nach ausg. { //platz für alte fußnote zurechtschrumpfen fussnoten[aktuellefussnote]=(char *)realloc( fussnoten[aktuellefussnote],aktuellefussnotenlaenge*sizeof(char)); } //prüfen, ob vor dieser fn schon alle anderen ausgegeben wurden if (maxausgegebenefn==aktuellefussnote-1) { //ja, es können weitere fussnoten ausgegeben werden while (fussnoten[aktuellefussnote]) { printf("[%i]%s",aktuellefussnote,fussnoten[aktuellefussnote]); free(fussnoten[aktuellefussnote]); fussnoten[aktuellefussnote]=NULL; maxausgegebenefn++; aktuellefussnote++; } } aktuellefussnotenlaenge=0; aktuellefussnotenmaxlaenge=0; altenummer = atoi(fussnotennummer); kv = btree_search(altzuneu, &altenummer); if (kv==NULL) { printf("[unreferenziert]"); aktuellefussnote = 0; } else //kv!=NULL { aktuellefussnote = *(int *) kv->val; } } else { //TODO: schon gelesene nicht-fußnoten-nummer wieder ausgeben printf("TODO"); } } else if (aktuellefussnote) { //in fussnote: gelesenes zeichen laden if (aktuellefussnotenmaxlaenge==0) { aktuellefussnotenmaxlaenge=256; fussnoten[aktuellefussnote]=(char *) malloc(aktuellefussnotenmaxlaenge*sizeof(char)); } else if (aktuellefussnotenmaxlaenge