Come reindirizzare cin e cout ai file?


Risposte:


219

Ecco un esempio funzionante di ciò che vuoi fare. Leggi i commenti per sapere cosa fa ogni riga del codice. L'ho provato sul mio pc con gcc 4.6.1; funziona benissimo.

#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
}

È possibile salvare e reindirizzare in una sola riga come:

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

Qui std::cin.rdbuf(in.rdbuf())imposta il std::cin'sbuffer su in.rdbuf()e quindi restituisce il vecchio buffer associato std::cin. Lo stesso può essere fatto con std::cout- o qualsiasi flusso per quella materia.

Spero che aiuti.


4
Devo chiudere i file prima di ripristinare cin e passare a IO standard?
updogliu,

3
@updogliu: No. Se vuoi, puoi usare ine outleggere e scrivere da, in.txte out.txtrispettivamente. Inoltre, i file verranno chiusi automaticamente quando ine outusciranno dall'ambito.
Nawaz,

Mi piace questa soluzione rispetto a freopenquella perché non posso più riavere la stdoutschiena se uso freopen. stackoverflow.com/questions/26699524/...
xxks-KKK

88

Scrivi e basta

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

int main()
{
    freopen("output.txt","w",stdout);
    cout<<"write in file";
    return 0;
}

14
Questo è il reindirizzamento stdout, no cout.
Aggiornamento

5
Questo reindirizzerà anche printf, che in alcuni casi potrebbe essere una buona cosa.
JDiMatteo,

5
@AkshayLAradhya Non quando lo si imposta std::sync_with_studio(false);, sebbene per impostazione predefinita sia impostato su true.
vsoftco,

2
@ PřemyslŠťastný perché?
reggaeguitar,

4
Se le risposte fossero uguali in termini di funzionalità, l'equivalente in C ++ di questo sarebbe ofstream out("out.txt"); cout.rdbuf(out.rdbuf());: solo una riga in più, ed è portatile. Non molto più semplice :)
nevelis,

19

Ecco uno snippet di codice breve per lo shadowing cin / cout utile per i concorsi di programmazione:

#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;
}

Questo offre un ulteriore vantaggio del fatto che gli stream semplici sono più veloci dei flussi stdio sincronizzati. Ma questo funziona solo per lo scopo di singola funzione.

Il reindirizzamento globale cin / cout può essere scritto come:

#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();
}

Si noti che ios_base::sync_with_stdioripristina anche std::cin.rdbuf. Quindi l'ordine conta.

Vedi anche Significato di ios_base :: sync_with_stdio (false); cin.tie (NULL);

I flussi std io possono anche essere facilmente ombreggiati per l'ambito di un singolo file, che è utile per la programmazione competitiva:

#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();
}

Ma in questo caso dobbiamo scegliere le stddichiarazioni una per una ed evitarle using namespace std;poiché darebbe un errore di ambiguità:

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
                   ^

Vedi anche Come usi correttamente gli spazi dei nomi in C ++? , Perché "utilizzare lo spazio dei nomi std" è considerato una cattiva pratica? e come risolvere una collisione di nomi tra uno spazio dei nomi C ++ e una funzione globale?


15

supponendo che il nome del programma di compilazione sia x.exe e $ sia la shell di sistema o il prompt

$ x <infile >outfile 

prenderà l'input dall'infile e uscirà all'outfile.


Ciò non è correlato al C ++ e non riesce in alcun esempio non banale, ad esempio quando il programma genera processi figlio che scrivono sulla console. Almeno questo è il problema che ho riscontrato quando ho provato un reindirizzamento, quindi perché sono qui.
ashrasmun,

5

Prova questo per reindirizzare cout al file.

#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;
}

Leggi l'articolo completo Usa std :: rdbuf per reindirizzare cin e cout


1
Alla domanda era stata data risposta circa 6 anni fa (nel 2012), ma hai aggiunto una risposta ora nel 2018. La tua risposta è uguale alla risposta accettata. Quindi mi chiedo perché l'hai pubblicato quando non avevi nulla di nuovo da aggiungere?
Nawaz,

La mia risposta evidenzia solo la versione speciale e la risposta dettagliata è fornita nel link sottostante.
HaseeB Mir,

Cosa c'è di nuovo nella tua risposta che non è presente nella risposta accettata ?
Nawaz,

2
La mia risposta non mescola il reindirizzamento di Cout e Cin, la mia versione si separa per renderla più leggibile
HaseeB Mir
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.