2010-03-08 12 views
7

Hier ist wahrscheinlich eine sehr noobish Frage für Sie: Wie (wenn überhaupt möglich) kann ich einen ifstream von einer Funktion zurückgeben?Zurückgeben von ifstream in einer Funktion

Grundsätzlich muss ich den Dateinamen einer Datenbank vom Benutzer erhalten, und wenn die Datenbank mit diesem Dateinamen nicht existiert, dann muss ich diese Datei für den Benutzer erstellen. Ich weiß, wie man das macht, aber nur, indem man den Benutzer auffordert, das Programm nach dem Erstellen der Datei neu zu starten. Ich wollte, dass die Unannehmlichkeiten für den Benutzer, wenn möglich, vermeiden, aber die Funktion unten kompiliert nicht in gcc:

ifstream getFile() { 
    string fileName; 
    cout << "Please enter in the name of the file you'd like to open: "; 
    cin >> fileName; 
    ifstream first(fileName.c_str()); 
    if(first.fail()) { 
     cout << "File " << fileName << " not found.\n"; 
     first.close(); 
     ofstream second(fileName.c_str()); 
     cout << "File created.\n"; 
     second.close(); 
     ifstream third(fileName.c_str()); 
     return third; //compiler error here 
    } 
    else 
     return first; 
} 

EDIT: sorry, vergessen, Ihnen zu sagen, wo und was der Compiler Fehler war:

main.cpp:45: note: synthesized method ‘std::basic_ifstream<char, std::char_traits<char> >::basic_ifstream(const std::basic_ifstream<char, std::char_traits<char> >&)’ first required here 

EDIT: Ich änderte die Funktion, um einen Zeiger anstelle von Remus vorgeschlagen, und änderte die Zeile in main() in "Ifstream-Datenbank = * GetFile()"; Ich bekomme jetzt wieder diesen Fehler, aber diesmal in der Linie in main():

main.cpp:27: note: synthesized method ‘std::basic_ifstream<char, std::char_traits<char> >::basic_ifstream(const std::basic_ifstream<char, std::char_traits<char> >&)’ first required here 
+3

Was Sie aufgelistet haben, ist kein Compilerfehler, es ist eine "Notiz". Sehen Sie sich den tatsächlichen Fehler an. –

Antwort

5
bool checkFileExistence(const string& filename) 
{ 
    ifstream f(filename.c_str()); 
    return f.is_open(); 
} 

string getFileName() 
{ 
    string filename; 
    cout << "Please enter in the name of the file you'd like to open: "; 
    cin >> filename; 
    return filename; 
} 

void getFile(string filename, /*out*/ ifstream& file) 
{ 
    const bool file_exists = checkFileExistence(filename); 
    if (!file_exists) { 
     cout << "File " << filename << " not found." << endl; 
     filename = getFileName(); // poor style to reset input parameter though 
     ofstream dummy(filename.c_str(); 
     if (!dummy.is_open()) { 
      cerr << "Could not create file." << endl; 
      return; 
     } 
     cout << "File created." << endl; 
    } 
    file.open(filename.c_str()); 
} 

int main() 
{ 
    // ... 
    ifstream file; 
    getFile("filename.ext", file); 
    if (file.is_open()) { 
     // do any stuff with file 
    } 
    // ... 
}
+0

Danke !!! nach ein bisschen Basteln mit deinem Code habe ich endlich bekommen, was ich wollte. : D – wrongusername

+1

Während dieses Code-Snippet die Frage lösen kann, [hilft eine Erklärung] (http://meta.stackexchange.com/questions/114762/explaining-entirely-code-based-results) wirklich, um die Qualität zu verbessern von deinem Beitrag. Denken Sie daran, dass Sie die Frage für Leser in der Zukunft beantworten, und diese Leute könnten die Gründe für Ihren Codevorschlag nicht kennen. – NathanOliver

3

ifstream unterstützt Semantik nicht Kopie konstruieren (das, was die Fehlermeldung im Grunde sais), so dass Sie nicht eine ifstream zurückkehren können. Geben Sie stattdessen einen ifstream * zurück und übergeben Sie dem Aufrufer die Verantwortung, den Zuweisungszeiger zu löschen.

+0

Okay ... Ich gebe "Return & Third" ein und warnt mich nun, dass "die Adresse der lokalen Variablen 'Third' zurückgegeben wurde." was mache ich dann in main()? – wrongusername

+0

niemals zurück und stack_variable. Weisen Sie dem ifstream einen neuen Operator zu und geben Sie den Zeiger zurück. –

+0

Sie meinen, etwas wie "ifstream returnStream = &first; return returnStream;"? BTW, das funktioniert auch nicht. es gibt mir einen Fehler: "main.cpp: 56: Fehler: Konvertierung von 'Std :: Ifstream *' zu nicht-skalaren Typ 'Std :: Ifstream' angefordert Haupt.cpp: 57: error: Ungültige Konvertierung von 'void *' nach 'std :: ifstream *' " – wrongusername

14

Nein, nicht wirklich. ifstream hat keinen Kopierkonstruktor, und wenn Sie versuchen, einen zurückzugeben, bedeutet das, dass Sie die Instanz in Ihrer Funktion dorthin kopieren, wohin die Rückgabe gehen soll.

Die übliche Problemumgehung besteht darin, einen Verweis auf einen Verweis zu übergeben und diesen Verweis in Ihrer Funktion zu ändern.

Edit: Während dies Ihren Code funktioniert, wird es nicht das grundlegende Problem beheben. Im Moment mischen Sie zwei ziemlich unterschiedliche Zuständigkeiten in eine einzige Funktion: 1) Erlangen Sie einen Dateinamen, 2) Öffnen oder erstellen Sie diese Datei. Ich denke, wenn Sie diese trennen, wird der Code einfacher, und es wird viel einfacher, die Quelle des Problems, das Sie sehen, zu beseitigen.

Edit 2: Die Verwendung einer Referenz wie dieser funktioniert sehr gut ohne operator=. Die allgemeine Idee ist so etwas wie:

int open_file(char const *name, fstream &stream) { 
    stream.open(name); 
} 

Der Zuweisungsoperator weder notwendig noch sinnvoll ist in diesem Fall - wir einfach die vorhandene fstream über die Referenz. Ein operator= wäre notwendig wenn und nur wenn wir mussten das Argument an den ctor übergeben. Mit einem Stream können wir standardmäßig einen Stream erstellen, der keine Verbindung zu einer Datei herstellt, und anschließend nach der Tatsache die Verbindung zu der Datei herstellen.

+0

Danke! Ich habe das, aber leider funktioniert der Code immer noch nicht. Mit "ifstream database = * getFile(); "Ich bekomme einen Fehler in dieser Zeile von" main.cpp: 29: note: synthetisierte Methode 'std :: basic_ifstream > :: basic_ifstream (const std :: basic_ifstream > &) 'zuerst erforderlich hier " – wrongusername

+0

aber ich denke, es hat mich auf diesen einen Fehler, obwohl. – wrongusername

+0

Der" Trick "der Weitergabe einer Referenz, um die Rückgabe eines neuen Objekts zu vermeiden, wird nur arbeite für Typen, die eine Oper haben tor = '. std :: ifstream hat das auch nicht, also wird dieser Rat für Sie nicht funktionieren. – MSalters

Verwandte Themen