Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 20 von 23

Thema: C(++) - Lesen und Schreiben von Dateien

  1. #1

    Pik Gast

    C(++) - Lesen und Schreiben von Dateien

    Für einen Beleg müssen wir uns unter anderem mit dem Lesen und Schreiben von (vorrangig) Textdateien auseinandersetzen. Beim Testen des Übungsbeispiels kommt es aber schon zum ersten Fehler:

    Code:
    #include <stdafx.h>
    #include <stdio.h>
    
    int main()
    {
    	
    	FILE *datei;
    	char *name = "test.txt";
    
    	datei = fopen (name, "a+"); 
    
    	if (datei == NULL)
    	{
    		printf("Fehler beim Oeffnen");
    		return -1;
    	}
    
    	else
    	{
    		fprintf ("Hat geklappt");
    		fclose (datei);
    	}
    	
    	return 0;
    }
    Als Fehlermeldung erhalte ich error C2660: 'fprintf' : function does not take 1 parameters. Ich habe keine Ahnung, von welchen Parameter die Rede ist.

    Dann hätte ich noch eine Frage zum Befehl fgets. Da wird ja aus einer Datei eine Zeichenfolge mit n Zeichen oder bis \n eingelesen. Wenn man die Länge der Zeichenfolge nicht weiß muß man ja auf \n zurückgreifen, aber muß das dann auch direkt im Text der Datei stehen? (z.B. Textdatei mir dem Inhalt" Hallo \n")

    Edit: Ersteres Problem ist gelöst.

    Geändert von Pik (10.01.2006 um 16:40 Uhr)

  2. #2
    Erste Lösung (ja, auch wenn dus schon gelöst hast ^^): fprintf soll ja wie der Name schon sagt was an einen Filehandle printfen. Daher sollte man auch den Filehandle angeben Also im Endeffekt:
    Code:
    fprintf(datei, "Hat geklappt");
    Zu der zweiten Sache: \n ist nur das Escape-Zeichen für einen Zeilenumbruch. ^^ Also das bedeutet effektiv, dass fgets bis zum Zeilenende (oder halt Dateiende) liest. Es reicht also wenn die Datei einfach nur "Hallo" beinhält.

  3. #3

    Pik Gast
    Ah, ok danke.

    Si, ich möchte jetzt aus einer Datei die erste Zeile einlesen und einer Variablen zuordnen. Die Syntax ist ja:
    Code:
    char *fgets( char *str, int num, FILE *stream );
    Bei dem obigen Beispiel wäre das:
    Code:
    char *fgets( char *str, int \n, FILE *datei);
    Kann ich nun statt *str eine (schon deklarierte) Variable einsetzen (z.B. *string1), die dann als Wert den eingelesenen String bekommt?

    Und wie kann man dann überhaupt die Strings aus den folgenden Zeilen einlesen? Man gibt ja keinen Anfang an.

  4. #4
    Code:
    FILE *datei;
    char buffer[1024]; // Ich mach einfach mal einen String
                       // (Also eigentlich ein char-Array)
                       // mit der Länge 1024.
    
    ... file öffnen und alles ..
    
    fgets(buffer, 1024, datei); // Hier wieder 1024, da der buffer so groß ist.
                                // Ich gehe hier einfach mal davon aus, 
                                // dass eine Zeile nicht mehr
                                // als 1024 Zeichen beinhalten wird.
    
    ... jetzt sollte die erste zeile in der variable 'buffer' enthalten sein ...
    Vor das buffer muss kein & (der Referenzierungsoperator, macht aus einer Variable einen Pointer), da Arrays automatisch Pointer sind.

    Alles komplex, ich weiß. String Behandlung in C ist eh so eine heikle Sache. >_>

  5. #5
    Das, was du gerade tust, ist Filehandling in C.
    Die meisten Probleme kannst du dir aber sparen, wenn du das Filehandling ueber C++ machst, ueber filestreams, z.B. fstream.

  6. #6

    Pik Gast
    Danke Dingsi, hat geklappt.
    Und ist es nun überhaupt möglich die weiteren Zeilen ebenfalls auszulesen? Die Richtung, in die ich denken muß würde ja schon reichen ^^

    Zitat Zitat von Ineluki
    Das, was du gerade tust, ist Filehandling in C.
    Die meisten Probleme kannst du dir aber sparen, wenn du das Filehandling ueber C++ machst, ueber filestreams, z.B. fstream.
    Naja, sämtliche Vorlesungen/Übungen, Anleitungen und das gegebene Material basieren auf C, weshalb ich nicht unbedingt großartig neue Dinge (die auch wieder Zeit benötigen) in den Beleg mit einbringen möchte.

  7. #7
    Zitat Zitat von Pik
    Danke Dingsi, hat geklappt.
    Und ist es nun überhaupt möglich die weiteren Zeilen ebenfalls auszulesen? Die Richtung, in die ich denken muß würde ja schon reichen ^^
    Ach, das hab ich ganz vergessen. Ist nicht allzu komplex. Einfach nochmal fgets aufrufen. Filehandles haben intern eine Art Zeiger, der angibt wo sie sich gerade in der Datei befinden. Wenn du fgets (oder andere Funktionen à la fread, fwrite usw.) aufrust wird dieser Zeiger erhöht bis zum letzten gelesenen Zeichen. Weitere Aufrufe, die diesen Filehandle betreffen, werden dort dann weitergeführt (Mal von rewind und fseek oder wie sie heißen abgesehen).

  8. #8

    Pik Gast
    Ah, praktisch ^^

    Gut, das reicht erstmal um bisschen weiterzuarbeiten. Ich das Schreiben wird dann wohl etwas einfacher. Nuja, ich melde mich wieder bei Problemen. Also bis Freitag

  9. #9

    Pik Gast
    Wieder ein Problem. Bei der Erstellung einer Textdatei möchte ich dieser einen namen geben, welcher in einer Vaariablen gespeichert ist.

    Also ich lege eine Datei an:
    Code:
    FILE *datei; 
    char *name = "liste.txt";
    datei = fopen(name, "a+");
    Kann man nun die Textdatei statt dem gegebenen "liste.txt" so benennen, daß man den Inhalt einer Variablen als Name für die Textdatei nutzen kann?

  10. #10
    natuerlich. Eigentlich machst du das ja. mit

    char* name = "liste.txt";

    deklarierst du ja nur einen Zeiger auf ein Nullterminiertes Array of Char, laesst den Compiler eines mit vorgegebenem Inhalt erstellen und laesst dessen Addresse den Compiler dem Zeiger zuweisen.

    Natuerlich kannst du auch selber einen Textbuffer einladen, ihn als nullterminiertes Zeichenarray speichern und die Addresse des ersten Zeichens statt name uebergeben.

    eine einfache Moeglichkeit waere z.B. sowas ...

    Code:
    #include <stdio.h>
    #include <iostream>
    #include <string>
    using namespace std;
    
    ...
    
    FILE *datei; 
    string namestr;
    
    cout<<"Geben Sie einen Dateinamen an: ";
    cin>>namestr;
    datei = fopen(namestr.c_str(), "a+");
    
    ...

  11. #11
    Das ist aber alles ganz schön gemischt. Die Streams und Strings aus C++, die Datei-Zugriffsmethode aus C. Ob das alles so schön ist?

  12. #12
    hey, Pik wollte doch den Dateizugriff in C haben, auch wenn im Threadtitel C++ steht.
    Natuerlich haette ich auch ne C Funktion schreiben koennen, die den Speicher entsprechend alloziiert, aber darum gings ja nicht. Die C++ String Klasse kapselt ja auch nur die C Basisfunktionen ...

    Ich sehe keinen Grund, warum man nicht C++ mit C Funktionen mischen sollte (Was anderes bleibt einem ja auch gar nicht uebrig, da die meisten Funktionen ohnehin C spezifisch sind). Auch in Zeiten von Cout verwende ich doch sehr oft noch printf bzw sprintf, ganz einfach aus dem einfachen Grund, weil die Formatierungsmoeglichkeiten damit systaktisch wesentlich griffiger sind, als mit cout ...

  13. #13
    War auch kein Vorwurf dir gegenüber.

  14. #14

    Pik Gast
    Danke, nachdem ich mir dein Beispiel angesehen habe, hab ich nochmal meine Aufzeichnungen durchblättert und etwas Ähnliches (mir begreiflicheres) gefunden.

    Code:
    FILE *datei;
    char filename[100];
    
    printf("Dateiname zum Speichern eingeben:");
    scanf("%s", filename);
    
    datei = fopen(filename, "a+");
    Ich nehme an, daß es das gleiche bewirkt oder?

    Wobei es dennoch interessant zu wissen wäre, was die Befehle cout und cin bei deinem Beispiel genau bewirken.

  15. #15
    Jup, sollte den selben Effekt haben.

    cin und cout sind Standard-Objekte (Keine Befehle!) in C++, die einem den einfachen Zugriff auf In- und Output erlauben.

    << und >> sind die beiden Methoden (bzw. überladenen Operatoren dieser Objekte, ich weiß >_>) über die halt dieser Zugriff genau abläuft.

    Mit cout << "Hello World"; wird also einfach "Hello World" ausgegeben.
    Mit cin >> name; wird einfach eine Zeile der Eingabe in die Variable "name" geschrieben.

    Die >>/<< Operatoren sind übrigens sehr sehr nett auf alle möglichen Typen überladen, d.h. man kann sie sehr nett mit allen möglichen Datentypen ansprechen.

    int foo;
    cin >> foo;


    erkennt von selbst, dass es ne Zahl einlesen soll.

    Geändert von Dingsi (14.01.2006 um 19:26 Uhr)

  16. #16
    Das Problem mit den Standard C Eingabefunktionen, wie z.B. scanf ist, dass es keinen wirklichen Schutz vor Bufferueberlauf gibt (ausser man macht verdammt viel Aufwand), das heisst, wenn der User in dem Fall mehr als 99 Zeichen (=100 incl Nullterminator) eingibt, kann alles moegliche passieren, von unberechenbarem Verhalten ueber Programmabstuerze bis hin zu Computerabstuerzen.

    Da ist die cin >> name; Methode wesentlich sicherer, da es den Puffer selbststaendig verwaltet.

  17. #17

    Pik Gast
    Die Zeichenanzahl kann man ja erweitern und im Vordergrund steht die Funktionalität (*hust*).

    Wie dem auch sei habe ich ein neues Problem. Wenn ich mit fgets die Strings einlese werden die Zeilenumbrüche ebenfals mit eingelesen, was problematisch ist, wenn ich die Strings aneinanderhängen will. Zwar kann ich die Zeichenanzahl so auf die eingelesenen Strings abstimmen, daß der Zeilenumbruch wegfällt, aber die Flexibilität geht verloren.
    Kann man einen String zufällig um ein Zeichen kürzen oder muß man dann auf eine Schleife zurückgreifen, die immer prüft, was gerade für ein Zeichen eingelesen wird (wenn sowas überhauüt geht)? Oder gibt's sogar noch eine einfachere Variante?

  18. #18
    Och, da gibt es etliche Möglichkeiten. Mir fällt jetzt auf die Schnelle ein..
    Code:
    char* buffer = "Hallo Welt.\n";
    
    for(int i=0;i<strlen(buffer);i++)
    {
      if(buffer[i] == '\n' || buffer[i] == '\r') buffer[i] = 0; // Oder auch ' ' von mir aus.
                                                             // 0 kennzeichnet jedenfalls das Ende das strings,
    }
    Einfach durch den ganzen String gehen und alle Zeilenumbrüche (\n) und Wagenrückläufe (\r) ersetzen.

    Geht sicher auch auf andere Art und Weise einfacher, aber das fällt mir dazu so ein. ^^

    Ja, klar, man könnte mithilfe von strchr die Position von \n bzw. \r bestimmen und dann überschreiben. o.o Ich weiß nicht, das könnte ein wenig Rechenaufwand sparen.

  19. #19

    Pik Gast
    Hab's mit strchr gemacht, ist die einfachere Lösung ^^

  20. #20

    Pik Gast
    Hab gerade wieder ein Problem. Ich will den Inhalt eines vorhandenen Strings umschreiben:
    Code:
    char test[100];
    *test='test';
    printf("%s", test);
    Einerseits wird nur der letzte Buchtabe gespeichert, andererseits bekomme ich foglgende Fehlermeldung, wenn der String länger als 4 Zeichen ist:
    Zitat Zitat
    too many characters in constant

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •