moin,
lese eine Datei zeilenweise aus. jetzt will ich in einem array jeder
zeile gespeichert haben, z.B das ist dann über einen index i zeile[i]
den kompletten string angezeigt bekomme, weiss jemand en tipp. auslesen
der datei geht schon.
hab also ne while-Schleife(feof) { fgets(string,....)}; will dann
sozusagen irgendwie schreiben zeile[i]= string
danke schon ma
Eric schrieb:
> moin,>> lese eine Datei zeilenweise aus. jetzt will ich in einem array jeder> zeile gespeichert haben, z.B das ist dann über einen index i zeile[i]> den kompletten string angezeigt bekomme, weiss jemand en tipp. auslesen> der datei geht schon.>> hab also ne while-Schleife(feof)
schon falsch.
C schaut nicht in die Zukunft. feof dient dazu, nachdem dir die
Lesefunktion angezeigt hat, dass sie nicht mehr lesen konnte,
festzustellen ob das 'Nicht-lesen-können' daraus resultierte, dass die
Datei zu ende ist
{ fgets(string,....)}; will dann
> sozusagen irgendwie schreiben zeile[i]= string
Strings kann man so nicht umkopieren.
http://www.mikrocontroller.net/articles/FAQ#Wie_funktioniert_String-Verarbeitung_in_C.3F
Wie gross hast du zeile als 2-dimensionales Array dimensioniert?
1
charzeile[512][81];// Platz für 512 Zeilen zu je 80 Zeichen.
2
3
4
i=0;
5
while(fgets(string,...)){
6
strcpy(zeile[i++],string);
7
}
8
9
if(!feof(...))
10
printf("Fehler beim Lesen der Datei\n");
Wobei sich in diesem Fall allerdings die Frage erhebt, warum du da den
Umweg über eine Hilfsvariable string machst.
Peter Stegemann schrieb:
> Karl heinz Buchegger schrieb:>>> Wie gross hast du zeile als 2-dimensionales Array dimensioniert?>>>>
1
>>strcpy(zeile[i++],string);
2
>>
>> strncpy, bitte. Besser waere natuerlich noch strdup und nur ein> Pointerarray.
Besser wär eine dynamisch aufgebaute Datenstruktur (Liste von Strings).
Es ist immer unklug, sich auf eine Maximallänge einer Datei zu
verlassen.
strncpy hilft dir in dem Fall auch nichts, weil schon 'string' eine
maximale Länge vorgibt, die nach dem fgets richtig behandelt werden
will.
Karl heinz Buchegger schrieb:
> Peter Stegemann schrieb:>> strncpy, bitte. Besser waere natuerlich noch strdup und nur ein>> Pointerarray.> Besser wär eine dynamisch aufgebaute Datenstruktur (Liste von Strings).> Es ist immer unklug, sich auf eine Maximallänge einer Datei zu> verlassen.
"Besser" liesse sich hier sicherlich noch ein paar mal steigern :-)
> strncpy hilft dir in dem Fall auch nichts, weil schon 'string' eine> maximale Länge vorgibt, die nach dem fgets richtig behandelt werden> will.
Ich sehe hier keine deklaration von "string" und selbst wenn sie da
waere, ich wuerde mich nie darauf verlassen, dass die Quellgroesse
kleinergleich der Zielgroesse ist. Sowas aendert sich auch schnell
mal...
danke erst mal;
hab auch noch das Problem wie gesagt, das die Datei nicht immer gleich
groß. Nur sind meine c Kenntnisse auch nicht so fundamental, und bei
meinen pdf "c in 21 tagen" steht bei dateien ja das man für die zeile so
wie die länge immer schon vorher speicher reservieren muss, mich würde
interessieren, wie ich das, wie oben geschrieben, dynamisch machen kann.
1.bezog sich die Ftrage und damit auch die Antwort darauf, ohne
Pufferüberlauf Zeilen zu lesen, deren Länge man nicht vorher kennt.
2. Ist in dem von dir beschriebenen Fall halt die Liste leer, weil
bereits beim ersten Durchlauf der cast con std::istream nach bool
einfach false liefert.
Peter Stegemann schrieb:
> Wasserdicht? Was macht dein Programm, wenn das File nicht existiert?
OK. Eine Meldung wär schön.
Aber abgesehen davon passiert nichts weiter Schlimmes.
> In C ist das sehr mühsam, wenn man es effizient und wasserdicht> haben will.
Du kannst das 'effizient' ruhig weglassen :-)
Wasserdicht als Grundforderung alleine würde schon reichen.
naja, zu langsam soll es ja auch nicht werden.
Man könnte z.B. zeichenweise lesen und mit jedem Zeichen den Puffer
mit realloc() um eins verlängern.
So etwas würde ich als ineffizient bezeichnen und gleich ausschließen,
daher die Formulierung.
Klaus Wachtler schrieb:
> naja, zu langsam soll es ja auch nicht werden.> Man könnte z.B. zeichenweise lesen und mit jedem Zeichen den Puffer> mit realloc() um eins verlängern.
OK. mach aus der 1 eine 10 oder 20 und dann sieht diese Strategie gar
nicht mehr so schlecht aus. Das ist noch relativ simpel zu machen und
ist im Vergleich zu dem was sonst da noch so alles abläuft gar nicht
mehr so schlecht.
Aber darauf wollte ich eigentlich gar nicht so sehr hinaus. Mir wäre
schon lieb, wenn derartige Eingabesyssteme in C wenigstens wasserdicht
wären.
Sowas ist immer eine herrliche Diskussion in den comp.lang Foren. Da
wird hemmungslos C mit C++ Code verglichen und dass C++ dann sooooo
langsam wäre. Nur wenn man dann mal die Codes vergleicht kommt man
drauf, dass wieder mal Äpfel mit Birnen verglichen werden. Während C++
Code Bufferoverflows aus dem Stand heraus vermeidet, ist der angeblich
funktional gleichwertige C Code (der liest ja auch nur eine Datei ein)
hemmungslos anfällig für alle möglichen Overflows.
Fazit: Wenn es nicht korrekt sein muss, ist es leicht schnell zu sein
:-)
muss es aber in C programmieren, weil ich das dann in MatLab über
mex-file einbinden muss. Geht zwar auch in Matlab die datei einzulesen,
aber da brauchte ich 28s und in C nur 2s. C muss sein weil matlab als
standard nur einen c compiler hat. es werden zwar bestimmte c++ compiler
unterstützt aber die Kosten geld (borland c++). wäre wirklich nett, wenn
wie oben c++ code auch einer ein primitives c beispiel posten könnte
Eric schrieb:
> muss es aber in C programmieren, weil ich das dann in MatLab über> mex-file einbinden muss. Geht zwar auch in Matlab die datei einzulesen,> aber da brauchte ich 28s und in C nur 2s. C muss sein weil matlab als> standard nur einen c compiler hat. es werden zwar bestimmte c++ compiler> unterstützt aber die Kosten geld (borland c++). wäre wirklich nett, wenn> wie oben c++ code auch einer ein primitives c beispiel posten könnte
Wenn du es genauso dynamisch haben willst, musst du dir eine kleine
Liste schreiben. Wenn du es nicht kannst, wird es Zeit, das zu lernen.
Nein, ich schreibe dir jetzt keine, meine Zeit waechst auch nicht auf
Baeumen.
Alternativ kannst du dich mit einem Array von Strings durchschlagen, das
du mit realloc() vergroesserst. Nicht schoen, aber geht auch.
So in etwa könnte es in C aussehen, wenn man alles dynamisch haben will.
Verbessern könnte man insbesondere, daß in leseDateiZeilenweiseAlloc()
das Feld immer nur um 1 verlängert wird; effektiver wäre es ähnlich
wie in leseZeileAlloc() immer gleich etwas mehr zu nehmen, dafür dann
seltener verlängern zu müssen. Kann aber jeder selber machen...
Weiterhin habe ich nicht realloc() genommen, sondern hole mir mit
malloc() Speicher, kopiere mit memcpy und gebe den alten dann frei.
Grund: Ich glaube mich zu entsinnen, daß man in Matlab die malloc()
und free() durch Matlab-Funktionen ersetzen muss (bin mir da aber
nicht sicher), und ich nicht weiß, ob es da ein realloc() überhaupt
gibt. So kann man es im Zweifelsfall jedenfalls leichter umbauen.
Von der Funktionalität her entspricht es i.W. dem C++-Beispiel von oben,
leider etwas umständlicher.
Achtung!
Getestet ist nur soweit, daß es einmal eine Datei gelesen hat.
Vor allem die gesamte Fehlerbehandlung ist nie ausprobiert worden.
Klaus Wachtler schrieb:
> Verbessern könnte man insbesondere, daß in leseDateiZeilenweiseAlloc()> das Feld immer nur um 1 verlängert wird; effektiver wäre es ähnlich> wie in leseZeileAlloc() immer gleich etwas mehr zu nehmen, dafür dann> seltener verlängern zu müssen. Kann aber jeder selber machen...
Ich wuerde die Groesse nicht verdoppeln. Eher z.B. um 10% vergroessern.
> Weiterhin habe ich nicht realloc() genommen, sondern hole mir mit> malloc() Speicher, kopiere mit memcpy und gebe den alten dann frei.> Grund: Ich glaube mich zu entsinnen, daß man in Matlab die malloc()> und free() durch Matlab-Funktionen ersetzen muss (bin mir da aber> nicht sicher), und ich nicht weiß, ob es da ein realloc() überhaupt> gibt. So kann man es im Zweifelsfall jedenfalls leichter umbauen.
Ich wuerde trotzdem realloc() nehmen und im Zweifelsfall dann eben
realloc ueber malloc() und memcpy() implementieren. Ist praktisch
genauso einfach, im Fall der Existenz von realloc() aber wesentlich
effizienter.
Peter Stegemann schrieb:
> Klaus Wachtler schrieb:>>> Verbessern könnte man insbesondere, daß in leseDateiZeilenweiseAlloc()>> das Feld immer nur um 1 verlängert wird; effektiver wäre es ähnlich>> wie in leseZeileAlloc() immer gleich etwas mehr zu nehmen, dafür dann>> seltener verlängern zu müssen. Kann aber jeder selber machen...>> Ich wuerde die Groesse nicht verdoppeln. Eher z.B. um 10% vergroessern.
Naja, war nur als Vorschlag gedacht wie man es machen könnte.
Wenn man es vernünftig optimieren will, muß man ohnehin überlegen,
was malloc() intern macht.
Vermutlich wird es minimale Granularität geben, in der intern Blöcke
allokiert werden, und vermutlich wird auch nicht jedes beliebige
Vielfache davon allokiert werden.
Ich hatte mal eine einfache Speicherverwaltung gebaut und kam dabei
zu dem Ergebnis, daß es zu wesentlicher weniger Fragmentierung
führt, nur eine Mindestblockgröße und 2^n-fache davon wirklich
zu reservieren. Alle anderen angeforderten Größen werden einfach
entsprechend aufgerundet.
Ich denke, ähnlich wird das malloc() auch arbeiten.
Falls das so ist, ist weder mein Vorschlag noch deiner ideal,
sondern es wäre vielmehr am besten, genau solche Größen
zu belegen.
>>> Weiterhin habe ich nicht realloc() genommen, sondern hole mir mit>> malloc() Speicher, kopiere mit memcpy und gebe den alten dann frei.>> Grund: Ich glaube mich zu entsinnen, daß man in Matlab die malloc()>> und free() durch Matlab-Funktionen ersetzen muss (bin mir da aber>> nicht sicher), und ich nicht weiß, ob es da ein realloc() überhaupt>> gibt. So kann man es im Zweifelsfall jedenfalls leichter umbauen.>> Ich wuerde trotzdem realloc() nehmen und im Zweifelsfall dann eben> realloc ueber malloc() und memcpy() implementieren. Ist praktisch> genauso einfach, im Fall der Existenz von realloc() aber wesentlich> effizienter.
ICH würde es auch so machen, aber der OP liest sich für mich eher,
als ob eine solche Änderung nicht unbedingt problemlos wäre.
Deshalb dachte ich es wäre ein netter Service, soweit voraus zu
denken.
Meinen Vorschlag mit realloc() zu vereinfachen, ist wohl einfacher
als andersrum.
Aber egal, wie man es macht, macht man es halt falsch ;-)
Hängt halt davon ab, wie es nun in Matlab ist. Aber das
wollte ich nicht herausfinden, dazu war ich zu faul.
Klaus Wachtler schrieb:
> Peter Stegemann schrieb:>> Klaus Wachtler schrieb:>>>>> Verbessern könnte man insbesondere, daß in leseDateiZeilenweiseAlloc()>>> das Feld immer nur um 1 verlängert wird; effektiver wäre es ähnlich>>> wie in leseZeileAlloc() immer gleich etwas mehr zu nehmen, dafür dann>>> seltener verlängern zu müssen. Kann aber jeder selber machen...>>>> Ich wuerde die Groesse nicht verdoppeln. Eher z.B. um 10% vergroessern.>> Naja, war nur als Vorschlag gedacht wie man es machen könnte.>> Wenn man es vernünftig optimieren will, muß man ohnehin überlegen,> was malloc() intern macht.
Nicht nur das.
Ich würd mir auch mal typische Files ansehen (so das möglich ist).
Wenn sich da rausstellt, dass so über den Daumen die durchschnittliche
Zeilenlänge im File um die 60 Zeichen ist, dann würd ich das als
Default-Erst-Allokierung nehmen und erst ab dort vergrößern.
> Ich hatte mal eine einfache Speicherverwaltung gebaut und kam dabei> zu dem Ergebnis, daß es zu wesentlicher weniger Fragmentierung> führt, nur eine Mindestblockgröße und 2^n-fache davon wirklich> zu reservieren.
Kann mich noch erinnern, dass mir im Studium erzählt wurde, dass eine
gute Strategie auch darin besteht, die Fibonacci Folge als Blockgrößen
zu benutzen. Die Begründung weiß ich nicht mehr, aber das hab ich mir
gemerkt, weil es so ziemlich das einzige mal war, dass diese Folge für
irgendetwas gut war.
Aber wie heißt es so schön:
Machs erst korrekt, und erst dann machs schnell.
Optimization is the root of all evil
Optimization: Rule 1: Don't do it
Rule 2: Don't do it ... yet