Neo-=IuE=-
Here to stay
|
Ich wollte eine Textdatei auslesen, aber ich wollte die Zeilen immer komplett haben, also zb mit fgets() kann ich ja nur "n-1" zeichen auslesen und brauch dafür aber auch wenn die zeile doch nur 5 zeichen lang ist ein "n" zeichenlanges char array ich hab jetzt eine funktion geschrieben um das zu verwirklichen, dass es eben in ein dynamisch erstelltes array kommt... nur kommt mir das a bissi umständlich vor. Wenn jemand a bessere methode weiß, dann bitte postets es // Zeilenweises Auslesen einer Textdatei und speichern der Zeile in ein dynamisch erstelltes Array
#include <stdio.h>
#include <stdlib.h>
int len(const char* string)
{
int length = 0; // Zählvariable für Zeichenkettenlänge
while(string[length]) // Bis Abschluss 0
length++; // Position erhöhen
return length; // Länge zurückgeben
}
int main(void)
{
char *buf; // Pointer auf ausgelesene Zeile
FILE *f; // Filepointer
int length=0; // Zählvariable
f = fopen("test.txt", "r"); // Öffnen der Testdatei
if (!f) // Wenn File not found abbrechen
return 1;
while(!feof(f)) // Bis Fileende erreicht:
{
buf = (char*)malloc(sizeof(char*)); // Speicherplatz für erstes Zeichen reservieren
buf[length] = fgetc(f); // Erstes Zeichen der Zeile auslesen
while(!((buf[length]=='\n')||(!buf[length]))) // Bis Zeichen \n oder \0 ist:
{
length++; // Anzahl der Zeichen pro Zeile erhöhen
buf = (char*)realloc(buf, sizeof(char*)*length); // Speicherplatz um 1 Zeichen verlängern
buf[length] = fgetc(f); // Nächstes Zeichen auslesen
if(feof(f)) // Bei Fileende Abbruchbedingung von Schleife setzen
buf[length] = 0;
if(buf[length-1] == EOF) //Wenn Zeichen für EOF ausgelesen wurde, dieses löschen
buf[length-1] = 0;
}
if (buf[length] == '\n') // Wenn letztes Zeichen \n:
{
buf = (char*)realloc(buf, sizeof(char*)*(length+1)); // Speicherplatz um 1 Zeichen verlängern
buf[length+1] = 0; // \0 für Zeilenende hinzufügen
}
printf("%s", buf); // Testausgabe der Zeile
length = 0; // Länge rücksetzen
free(buf); // Speicher wieder freigeben
}
fclose(f); // File schließen
scanf("%c", &length); // Zeichen einlesen für warten vor Programmende
return 0;
}
Bearbeitet von Neo-=IuE=- am 30.11.2004, 23:02
|
mat
AdministratorLegends never die
|
*) file 1x komplett mit einem fread auslesen.. es sei denn, dein textfile ist wirklich groß (> 100mb? O_o), dann lies es in größeren blöcken ein. allgemein gesagt: umso mehr du auf einmal liest, desto schneller *) strchr das nach dem zeilenende sucht (entweder \r\n oder nur \n.. je nach os - brauchst aber eh nur nach \n suchen und dann jeweils ) und die zeile in eine linked list aufnimmt (braucht keine double ll sein, forwärts reicht ja). ich hab zwar von realloc nichts schlechtes gehört, persönlich würd ichs aber meiden. kA, vl weiss wer andrer mehr dazu. oder willst dus wirklich in einem char** haben? edit: btw, es gibt strlen()
|
that
ModeratorHoffnungsloser Optimist
|
Ein realloc für jedes Zeichen = quadratisches Zeitverhalten der Funktion = schlecht.
|
mat
AdministratorLegends never die
|
für jedes zeichen so genau hab ich gar nicht geschaut, hab nur realloc gesehen und gedacht es wird pro zeile vergrößert
|
Neo-=IuE=-
Here to stay
|
na ich habs zeilenweise ausgelesen, zeile verarbeitet, dann erst nächste zeile des mit strlen() is ma scho klar, des kommt aber noch daher, dass in der fh bei dem bsp wo wir grad sind wir die string.h net einbinden sollen, weil wir zb strstr() selba schreiben sollen nur mir is des zfad, deshalb mach i mir halt selba aufgabenstellenungen und schau ob ich die sinnvoll lösen kann ja des mim realloc gfällt ma ja eh net, nur wie sonst: wie bei fgets() brauch auch fread ein char array des scho besteht um n zeichen reinzulesen... nur ich will eben keinen unnötign speicher reservieren naja dann muss ichs doch so machen, dass ich imma in einen buffer einlese mit bestimmter anzahl von zeichen und dann aber in ein dynamisch erstelltes array verknüpfe für die zeile
|
Ringding
Pilot
|
*) file 1x komplett mit einem fread auslesen.. es sei denn, dein textfile ist wirklich groß (> 100mb? O_o), dann lies es in größeren blöcken ein. allgemein gesagt: umso mehr du auf einmal liest, desto schneller Allerdings ist fgetc auch recht schnell, und wenn er noch getc statt fgetc verwenden würde, wär's sogar fast gleich schnell wie ein größeres fread. Ich würde es so machen: Zuerst einmal mit einem kleinen Array anfangen (1kb oder so). Wenn das reicht, realloc auf die richtige Größe und fertig. Wenn nicht, gehst du in eine Schleife, in der du dir eine Liste aus Arrays zusammenhängst, in die du immer das nächste Stück hineinliest, bis nichts mehr kommt. Dann weißt du die Gesamtgröße, kannst das Ergebnisarray anlegen, stückweise alles zusammenkopieren und die kleinen Arrays freigeben. Braucht zwar kurzzeitig die doppelte Menge an Speicher, aber das ist nicht unüblich - außerdem könnte dir das bei realloc ebenso passieren.
|
gue
Addicted
|
wie bei fgets() brauch auch fread ein char array des scho besteht um n zeichen reinzulesen... nur ich will eben keinen unnötign speicher reservieren Hast du das probiert? Das stimmt nämlich nicht. fgets und fread reservieren den Speicher und geben einen Zeiger darauf zurück. Du brauchst da gar nichts allozieren Du kannst also durchaus fgets benutzen. Edit: pro forma dein Programm #include <stdio.h>
#include <stdlib.h>
int main(void) {
char *string;
FILE *file;
file = fopen("text.c", "r");
while (!feof(file)) {
if (fgets(string, 0xffff, file)) printf("%s", string);
}
fclose(file);
}
|
Ringding
Pilot
|
fgets und fread reservieren den Speicher und geben einen Zeiger darauf zurück. Unsinn.
|
Rektal
Here to stay
|
-> Slide Card & Swap Magic Set
man fgets char *fgets(char *s, int size, FILE *stream);
fgets() reads in at most one less than size characters from stream and stores them into the buffer pointed to by s. "pointed to by s" == selber buffer anlegen
|
Neo-=IuE=-
Here to stay
|
eben gue bei deiner variante hast glück, dass du nix wichtiges überschrieben hast beim einlesen sicha is a pointer auf char gleichwertig, nur wenn du den pointer nicht auf ein array legst bzw. auf ein mit malloc erstelltes array zeigen lässt, dann kannst du genauso irgendwas im ram überschreiben ich habs jetzt so gmacht, dass ich einfach ein array dynmisch erstellt hab mit einer bestimmten größe zb 100 und dann einfach imma um 100 vergrößert hab und immer mit fgets() einglesen und dann zamghängt natürlich hab ich dann zwar a bissi unsinnig benützten speicherplatz, max. halt knapp 100byte
|
gue
Addicted
|
Unsinn. Stimmt Sorry für Misinfo @ Neo (war wohl doch 1 Bier zu viel gestern )
|
SYSMATRIX
Legend Legend
|
und warum nicht per mmap?
mmap dürfte locker 1.5x so schnell sein wie die methode per syscalls.
speichersparender dürfte es auch sein.
|
Ringding
Pilot
|
Weil der Thread "ANSI C" heißt.
|
mat
AdministratorLegends never die
|
und warum nicht per mmap?
mmap dürfte locker 1.5x so schnell sein wie die methode per syscalls.
speichersparender dürfte es auch sein. mach lieber perl, webjunge
|
SYSMATRIX
Legend Legend
|
edit: sorry, my bad :/ @mat: fu!
|