Dateigröße auslesen und Inhalt ausgeben
-
mahlzeit!
folgender code und dazugehörige frage:
FILE *fpointer; fpointer = fopen("C:/.../Desktop/hallo.txt", "r"); char string[80]; for (int i = 0; i < 10; i++) { fscanf(fpointer, "%s", string); printf("%s \n", string); } fclose(fpointer);
in der textdatei "hallo.txt" steht folgendes drin:
Hallo Welt! Wie geht es dir?
die aufgabe besteht darin, eine datei vom desktop zu öffnen und den inhalt zeilenweise auszugeben. man geht von 80 zeichen pro zeile aus.
erste ideen:
erst einmal die anzahl der zeichen oder anzahl der zeilen in der datei bestimmen.
hätte ich die anzahl der zeichen z.b. mit fgetc(fpointer) oder anzahl der zeilen vor dem auslesen , könnte ich schon mal die for-schleife effizienter gestalten. diese läuft jetzt ja 10 mal. habe ich nur 5 zeilen text in meiner datei, sind 5 durchgänge verschenkt. so war mein gedanke zumindest.ich habe jetzt mit vielen funktionen herumgespielt. die anzahl an bytes in der datei beim auslesen habe ich irgendwie nicht hinbekommen. da hat er nur ganz konfuse zahlen als ergebnis gebracht.
allerdings habe ich das auslesen zeilen mit:int cnt = 1; //1 wegen erster zeile for (int i = 0; i < 10; i++) { if(fgetc(fpointer) == EOF) cnt++; } printf("%d", cnt);
hinbekommen. wenn auch nicht ganz korrekt (siehe unten --> problem mit der formatierung), da in der datei 2 zeilen sind und mein "cnt" 5 irgendwie anzeigt. vielleicht lieg ich auch völlig daneben.
man müsste ja theoretisch vor dem auslesen der datei, die größe bestimmen können um der for-schleife effiziente parameter zu geben. theoretisch!
geht ja aber scheinbar erst, wenn man diese ausliest mit z.b. einer for-schleife eben.
ich hoffe ihr wisst was ich in etwa meine.mir kamen auch ideen dieses problem mit malloc() oder einer zweiten schleife zu händeln. aber eine extra schleife zum zählen der größe um mit dieser größe dann effizient den inhalt mittels zweiter schleife auszulesen is ja völliger nonsens.
desweiteren funktionen w.z.b. fseek(), ftell(), st_size gelesen. aber das sagt mir gleich mal gar nix. bin dahingehend kein pro!
vielleicht habt ihr einen guten gedanken.zweites problem, was auf dem ersten aufbaut:
wenn ich die schleife jetzt 10 mal durchlaufen lasse und ich habe in meiner textdatei nur 2 zeilen (wie im bsp. oben), dann gibt er mir folgendes aus:Hallo Welt! Wie geht es dir? dir? dir? dir? dir?
erstens: wie verhindere ich das er mit das wort "dir?" 5 mal ausgibt (siehe problem 10 schleifendurchläufe)? jetzt bitte nicht mit 6 statt 10 schleifendurchläufe kommen. darauf wär ich auch gekommen. die anzahl der zeilen kann sich ja in der datei ändern.
und
zweitens: wie ändere ich die formatierung? das jedes wort jetzt einzeln auf einer zeile steht, liegt mit sicherheit an der printf-funktion + \n. allerdings würde ohne return alles in einer zeile stehen, was ja auch logisch aber eben nicht ganz das ist, was ich will.
wie händel ich es also, dass er mir die zwei zeilen aus der datei auch als 2 zeilen in der console ausgibt und eben nicht so wie das jetzt der fall ist?besten dank und gruß
norbert
-
Viel zu umständlich! Und im Ansatz auch schon vermurkst, wie du selber merkst. Die Aufgabe ist ziemlich trivial auf eine der folgenden Arten und Weisen zu lösen:
-Einfach alles einlesen und ausgeben, schließlich sind die Zeilenumbrüche schon in der Datei
-fgets benutzen
-scanf mit negated scanset auf Zeilenumbruch benutzen (%[^\n]
)
-Bestimmt noch viele andereDenk dran, dass es auch so etwas wie Rückgabewerte von Lesefunktionen gibt. So kann man einfach so lange einlesen, bis man das Ende erreicht hat, ohne dieses im Voraus zu kennen.
Damit ist die Aufgabe ein Dreizeiler. Fünf Zeilen, wenn man sehr großzügig ist.
-
Lange Fassung, etwas erklärender:
#include <stdio.h> // fopen, ftell, fseek, rewind, puts, fgets, fputs, fclose, printf // Program entry main(){ // Declarations FILE* file; long file_size; char line[255]; // Open file (in read mode) file = fopen("input.txt", "r"); if(file){ // file != NULL ->file handle is valid and can be used // Get file length file_size = ftell(file); // Get current file position which is the start fseek(file, 0, SEEK_END); // Set file position to the end file_size = ftell(file) - file_size; // Calculate file size by <end - start> // Output file size printf("File size in bytes: %ld\n", file_size); // Set file pointer back to start rewind(file); // Output file line-per-line puts("File content:"); while(fgets(line, sizeof(line), file)) // fgets(...) != NULL ->read line successfully fputs(line, stdout); // Close file fclose(file); }else puts("Couldn't open file!"); }
Oder kurz, als Zweizeiler:
#include <stdio.h> main(){FILE* file = fopen("input.txt", "r"); char line[255]; while(fgets(line, sizeof(line), file)) fputs(line, stdout);}
-
Das
printf(line)
ist gefährlich und daher zu vermeiden.Das line ist in diesem Fall der Formatstring.
Wenn in der Datei ein ein gültiger Formatspecifier steht, willprintf
auch den Paramter dazu haben und nimmst sich den auch.%s%s%s%s Hallo Welt! %s%s%s%s
Daher
printf("%s", line);
-
Oder gleich
puts(line);
(bei der Fehlermeldung hat Youka ja auch schon diese Funktion benutzt
-
Th69 schrieb:
Oder gleich
puts(line);
(bei der Fehlermeldung hat Youka ja auch schon diese Funktion benutzt
Ne, so einfach ist das nicht.
puts
hängt automatisch ein '\n' an. Das steht aber noch in line vomfgets
Dann wird es immer eine Leerzeile dazwischen geben.Daher dann als Gegenpart von fgets:
fputs(line, stdout);
(welches ich auch lieber nehme, da es dir richtige Funktion dafür ist)
Allerdings optimiert der Compiler (wenn er darf) das
printf("%s",
von alleine durch einfputs(
(Und printf("%s\n", von alleine durch einputs(
Diese Optimierung kann er bei einem printf(line) auch nicht machen, da er den Inhalt von line nicht kennt)
-
Upps, du hast Recht. Immer diese Inkonsistenzen zwischen den verschiedenen Funktionen.