Wie leite ich cin und cout in Dateien um?

Antworten:

219

Hier ist ein funktionierendes Beispiel dafür, was Sie tun möchten. Lesen Sie die Kommentare, um zu erfahren, was jede Zeile im Code bewirkt. Ich habe es auf meinem PC mit gcc 4.6.1 getestet; es funktioniert gut.

#include <iostream>
#include <fstream>
#include <string>

void f()
{
    std::string line;
    while(std::getline(std::cin, line))  //input from the file in.txt
    {
        std::cout << line << "\n";   //output to the file out.txt
    }
}
int main()
{
    std::ifstream in("in.txt");
    std::streambuf *cinbuf = std::cin.rdbuf(); //save old buf
    std::cin.rdbuf(in.rdbuf()); //redirect std::cin to in.txt!

    std::ofstream out("out.txt");
    std::streambuf *coutbuf = std::cout.rdbuf(); //save old buf
    std::cout.rdbuf(out.rdbuf()); //redirect std::cout to out.txt!

    std::string word;
    std::cin >> word;           //input from the file in.txt
    std::cout << word << "  ";  //output to the file out.txt

    f(); //call function


    std::cin.rdbuf(cinbuf);   //reset to standard input again
    std::cout.rdbuf(coutbuf); //reset to standard output again

    std::cin >> word;   //input from the standard input
    std::cout << word;  //output to the standard input
}

Sie können in nur einer Zeile speichern und umleiten als:

auto cinbuf = std::cin.rdbuf(in.rdbuf()); //save and redirect

Hier std::cin.rdbuf(in.rdbuf())setzt std::cin'sPuffer auf in.rdbuf()und gibt dann den alten Puffer zurück, der zugeordnet ist std::cin. Das gleiche kann mit std::cout- oder jedem Stream für diese Angelegenheit gemacht werden.

Hoffentlich hilft das.

Nawaz
quelle
4
Muss ich die Dateien schließen, bevor ich cin und cout auf Standard-E / A zurücksetze?
updogliu
3
@updogliu: Nein . Wenn Sie möchten, können Sie verwenden , inund outvon und Schreiben auf, zu lesen in.txtund out.txtjeweils. Außerdem werden die Dateien automatisch geschlossen , wenn inund outgehen out of scope.
Nawaz
Ich mag diese Lösung gegenüber der freopen, weil ich meinen stdoutRücken nicht mehr bekommen kann, wenn ich sie benutze freopen. stackoverflow.com/questions/26699524/…
xxks-kkk
88

Einfach schreiben

#include <cstdio>
#include <iostream>
using namespace std;

int main()
{
    freopen("output.txt","w",stdout);
    cout<<"write in file";
    return 0;
}
Tsotne Tabidze
quelle
14
Das leitet stdoutnicht um cout.
updogliu
5
Dadurch wird auch printf umgeleitet, was in einigen Fällen eine gute Sache sein kann.
JDiMatteo
5
@AkshayLAradhya Nicht beim Festlegen std::sync_with_studio(false);, obwohl es standardmäßig auf eingestellt ist true.
vsoftco
2
@ PřemyslŠťastný warum?
Reggaeguitar
4
Wenn die Antworten in der Funktionalität gleich wären, wäre das C ++ - Äquivalent dazu ofstream out("out.txt"); cout.rdbuf(out.rdbuf());- nur eine zusätzliche Zeile, und es ist portabel. Nicht soooo viel einfacher :)
Nevelis
19

Hier ist ein Kurzcode-Snippet zum Abschatten von cin / cout, das für die Programmierung von Wettbewerben nützlich ist:

#include <bits/stdc++.h>

using namespace std;

int main() {
    ifstream cin("input.txt");
    ofstream cout("output.txt");

    int a, b;   
    cin >> a >> b;
    cout << a + b << endl;
}

Dies bietet den zusätzlichen Vorteil, dass einfache Fstreams schneller sind als synchronisierte Standard-Streams. Dies funktioniert jedoch nur für den Bereich der Einzelfunktion.

Die globale cin / cout-Umleitung kann wie folgt geschrieben werden:

#include <bits/stdc++.h>

using namespace std;

void func() {
    int a, b;
    std::cin >> a >> b;
    std::cout << a + b << endl;
}

int main() {
    ifstream cin("input.txt");
    ofstream cout("output.txt");

    // optional performance optimizations    
    ios_base::sync_with_stdio(false);
    std::cin.tie(0);

    std::cin.rdbuf(cin.rdbuf());
    std::cout.rdbuf(cout.rdbuf());

    func();
}

Beachten Sie, dass ios_base::sync_with_stdioauch zurückgesetzt wird std::cin.rdbuf. Die Reihenfolge ist also wichtig.

Siehe auch Bedeutung von ios_base :: sync_with_stdio (false); cin.tie (NULL);

Standard-Streams können auch leicht für den Umfang einer einzelnen Datei abgeschattet werden, was für die wettbewerbsfähige Programmierung nützlich ist:

#include <bits/stdc++.h>

using std::endl;

std::ifstream cin("input.txt");
std::ofstream cout("output.txt");

int a, b;

void read() {
    cin >> a >> b;
}

void write() {
    cout << a + b << endl;
}

int main() {
    read();
    write();
}

In diesem Fall müssen wir jedoch die stdDeklarationen einzeln auswählen und vermeiden, using namespace std;da dies zu Mehrdeutigkeitsfehlern führen würde:

error: reference to 'cin' is ambiguous
     cin >> a >> b;
     ^
note: candidates are: 
std::ifstream cin
    ifstream cin("input.txt");
             ^
    In file test.cpp
std::istream std::cin
    extern istream cin;  /// Linked to standard input
                   ^

Siehe auch Wie werden Namespaces in C ++ richtig verwendet? , Warum wird "using namespace std" als schlechte Praxis angesehen? und Wie löse ich eine Namenskollision zwischen einem C ++ - Namespace und einer globalen Funktion?

Vadzim
quelle
15

Angenommen, der Name Ihres Kompilierungsprogramms lautet x.exe und $ ist die System-Shell oder Eingabeaufforderung

$ x <infile >outfile 

nimmt Eingaben von infile entgegen und gibt sie in outfile aus.

Ahmed Eid
quelle
Dies hat nichts mit C ++ zu tun und schlägt in keinem nicht trivialen Beispiel fehl, beispielsweise wenn Ihr Programm untergeordnete Prozesse erzeugt, die in die Konsole schreiben. Zumindest ist das das Problem, auf das ich gestoßen bin, als ich eine solche Umleitung versucht habe, weshalb ich hier bin.
Ashrasmun
5

Versuchen Sie dies, um cout in eine Datei umzuleiten .

#include <iostream>
#include <fstream>

int main()
{
    /** backup cout buffer and redirect to out.txt **/
    std::ofstream out("out.txt");

    auto *coutbuf = std::cout.rdbuf();
    std::cout.rdbuf(out.rdbuf());

    std::cout << "This will be redirected to file out.txt" << std::endl;

    /** reset cout buffer **/
    std::cout.rdbuf(coutbuf);

    std::cout << "This will be printed on console" << std::endl;

    return 0;
}

Vollständigen Artikel lesen Verwenden Sie std :: rdbuf, um cin und cout umzuleiten

HaseeB Mir
quelle
1
Die Frage wurde vor fast 6 Jahren (2012) beantwortet, aber Sie haben jetzt 2018 eine Antwort hinzugefügt. Ihre Antwort entspricht der akzeptierten Antwort. Ich frage mich also, warum Sie dies gepostet haben, als Sie nichts Neues hinzuzufügen hatten.
Nawaz
Meine Antwort hebt nur die Cout-Version speziell hervor und die detaillierte Antwort finden Sie unter dem folgenden Link.
HaseeB Mir
Was ist neu in Ihrer Antwort, das in der akzeptierten Antwort nicht vorhanden ist ?
Nawaz
2
Meine Antwort mischt nicht die Umleitung von cout und cin, meine Version wird getrennt, um sie besser lesbar zu machen
HaseeB Mir