[gelöst] Wie kann ich ein FILE als Parameter einer Funktion übergeben?



  • Hallo,

    ich möchte gern im Hauptprogramm eine Datei öffnen und dann in einer Funktion etwas in die Datei schreiben. (Die Funktion will ich später öfter aufrufen; deswegen möchte ich eben nicht den Dateinamen übergeben und jedes Mal in der Funktion die Datei öffnen und wieder schließen.)

    Ich stelle mir das mehr oder weniger so vor:

    #include <stdio.h>
    
    void speichern(FILE datei) {
    	fputc('A', &datei);
    }
    
    int main() {
    	FILE *datei = new FILE;
    	datei = fopen ("test.txt","w");
    	speichern(*datei);
    	fclose(datei);
    }
    

    Dieser Code wird auch kompiliert, aber wenn ich das Programm starte, passiert ein Segmentation fault . Ich vermute mal, weil fputc nicht in die datei schreibt, sondern versucht an die Adresse des Zeigers auf datei zu schreiben.

    Kann mir jemand sagen, was ich korrigieren muss?

    Vielen Dank im Voraus!



  • Wieso übergibst du nicht einfach den Zeiger den du ja schon in der main Funktion hast?



  • tda schrieb:

    Hallo,

    ich möchte gern im Hauptprogramm eine Datei öffnen und dann in einer Funktion etwas in die Datei schreiben. (Die Funktion will ich später öfter aufrufen; deswegen möchte ich eben nicht den Dateinamen übergeben und jedes Mal in der Funktion die Datei öffnen und wieder schließen.)

    Ich stelle mir das mehr oder weniger so vor:

    #include <stdio.h>
    
    void speichern(FILE datei) {
    	fputc('A', &datei);
    }
    
    int main() {
    	FILE *datei = new FILE;
    	datei = fopen ("test.txt","w");
    	speichern(*datei);
    	fclose(datei);
    }
    

    Dieser Code wird auch kompiliert, aber wenn ich das Programm starte, passiert ein Segmentation fault . Ich vermute mal, weil fputc nicht in die datei schreibt, sondern versucht an die Adresse des Zeigers auf datei zu schreiben.

    Kann mir jemand sagen, was ich korrigieren muss?

    Vielen Dank im Voraus!

    #include <stdio.h>
    
    void speichern(FILE* datei) {
    	fputc('A', datei);
    }
    
    int main() {
    	FILE *datei = new FILE;
    	datei = fopen ("test.txt","w");
    	speichern(datei);
    	fclose(datei);
    }
    


  • @Zeigerübergabe: An sowas hatte ich auch gedacht, wusste dann aber nicht so recht, wie ich in der Funktion damit umgehen muss.

    @FileZeiger: Ja, das ist genau, was ich wollte. (Wann etwas Zeiger oder Referenz oder was auch immer ist, ist bei mir noch größtenteils geschicktes Raten und Rumprobieren. 😉 )

    Vielen Dank für die schnelle Hilfe!



  • FILE *datei = new FILE; 
    datei = fopen ("test.txt","w");
    

    Hier hast du ein schönes Memory Leak. Schreib lieber

    FILE* datei = fopen("test.txt", "w");
    

    Wenn du tatsächlich C++ programmierst (was wegen new anzunehmen ist), kannst du dir sonst auch mal die IO-Streams ( std::fstream ) anschauen. Die schliessen sich zum Beispiel auch selbst.



  • Nexus schrieb:

    Schreib lieber

    FILE* datei = fopen("test.txt", "w");
    

    Das habe ich inzwischen gemacht. Das mit dem new war nur beim Rumprobieren entstanden...

    Nexus schrieb:

    kannst du dir sonst auch mal die IO-Streams ( std::fstream ) anschauen. Die schliessen sich zum Beispiel auch selbst.

    Haben die sonst noch irgendwelche Vorteile?

    Ich war auch schon auf die gestoßen, ürsprünglich aber zunächst nur auf ostream::write und istream::read , was mir unnötig kompliziert schien. Da ich meine Daten binär und daher durchaus byte-weise schreiben und lesen kann, schien mir fputc angemessener. Aber ostream::put und istream::get dürften ja etwa das gleiche tun wie fputc und fgetc , oder?



  • Vorteil von std::fstream ist, dass einem mehr Sicherheit durch Exceptions gewährleistet wird. Für byteweises (, binäres) einlesen gibt es std::stringstream(>>).



  • Exceptionsicherheit: Ja. Stringstreams für binäres Einlesen: Nein.
    stringstream bietet (bis auf das fehlende open() und close() ) genau die gleichen Operationen wie fstream , denn beide sind von iostream abgeleitet. Siehe http://www.cplusplus.com/reference/iostream/. Ihre wahren Stärken könnnen die iostreams zwar nur beim formatierter Ein-/Ausgabe mit den << und >> Operatoren ausspielen, dennoch sind sie den Sachen aus <cstdio> ( <stdio.h> ist veraltet!) vorzuziehen. Übrigens: Wenn du byteweise (==> binär) schreibst solltest du statt "w" "wb", bzw. bei fstream ios::binary benutzen.



  • Danke für die Antworten!

    Oberon_0 schrieb:

    Übrigens: Wenn du byteweise (==> binär) schreibst solltest du statt "w" "wb", bzw. bei fstream ios::binary benutzen.

    Das ist mir auch schonmal über den Weg gelaufen. Was macht das eigentlich für einen Unterschied?

    Oberon_0 schrieb:

    Ihre wahren Stärken könnnen die iostreams zwar nur beim formatierter Ein-/Ausgabe mit den << und >> Operatoren ausspielen, dennoch sind sie den Sachen aus <cstdio> ( <stdio.h> ist veraltet!) vorzuziehen.

    OK. Ich habe inzwischen mein Projekt komplett auf fstream umgestellt. Falls das noch jemand anderes interessiert, hier nochmal die Kurzfassung (mit einer zusätzlichen Zwischen-Funktion):

    #include <iostream>
    #include <fstream>
    using namespace std;
    
    void speichern(ofstream &datei) {
    	datei.put('B');
    }
    
    void mehrere_speichern(ofstream &datei) {
    	speichern(datei);
    	speichern(datei);
    }
    
    int main() {
    	ofstream datei("test.txt", ios::out | ios::binary);
    	speichern(datei);
    	mehrere_speichern(datei);
    }
    


  • Die Parameter w und wb sind ja zunächst nur Abkürzüngen, welche angeben, mit welchen "Anforderungen" eine Datei geöffnet werden soll.

    Dabei steht das w für Schreibzugriff (write) und das b für binären Zugriff (binary).

    In Kombination heißt wb dann natürlich: Binär schreiben.

    Binär liest und schreibt man immer dann, wenn man eine Datei exakt kopieren will. Andernfalls würden Terminierungszeichen und andere Steuerzeichen Probleme machen und die Datei unbrauchbar machen.

    Oder man schreibt binär, wenn man eigene Strukturen speichern möchte. Auch hier wären Steuerzeichen hinderlich und es muss entsprechedn binär geschrieben werden
    Aber das Thema wird umso komplizierter, umso mehr man an Plattformunabhängigkeit interessiert ist.

    Will man reinen Text speichern, so ist ein binärer Zugriff in der Regel nicht notwendig und bereitet nur Probleme. Einfach mal experimentieren 🙂



  • Für meinen Fall brauche ich auf jeden Fall binäre Dateien. Meine Frage war nur, was es für einen Unterschied macht, ob ich eine Datei mit " w " oder " wb " (bzw. mit oder ohne ios::binary ) öffne, aber inzwischen habe ich eine Antwort gefunden: inhaltlich offenbar keinen, aber benutzen sollte ich " wb " bzw. ios::binary dennoch.

    <a href= schrieb:

    cplusplus.com">In many environments, such as most UNIX-based systems, it makes no difference to open a file as a text file or a binary file; Both are treated exactly the same way, but differentiation is recommended for a better portability.

    Vielen Dank für all die Hilfe! 🙂



  • noch als kleiner nachtrag: unter windows gibts sehr wohl nen unterschied - hab hier schon mehrfach gehört, dass jmd nen \r\n beim "normalen" auslesen bekommen hat, obwohl eigtl nur ein \n in der datei stand - beim binären lesen hatte das dann auch geklappt ^^
    also wenn du binär willst, nimm binär - verlass dich nicht drauf, dass es keinen unterschied macht.

    bb


Anmelden zum Antworten