2012-12-20 22 views
12

Sto cercando di usare freopen() per stampare su un file di testo e sullo schermo, ma sto solo ottenendo la stampa su un file.Uso di freopen() per stampare su file e schermo

Mi chiedevo se fosse facile salvare i programmi in uscita su un file e stamparlo sullo schermo? Perché l'ho fatto funzionare in un altro modo, ma alla fine ho dovuto stampare ogni dichiarazione due volte. Uno è per il file l'altro solo per l'output.

Nota: sono nuovo di C++ e sto cercando di apprenderlo per un corso nel prossimo semestre in modo tale che siano necessarie risposte dirette visto che ho già cercato online e non sono riuscito a trovare risposte semplici a questa soluzione.

Ecco quello che ho finora:

#include<iostream> 
#include<time.h> 
#include<stdlib.h> 
#include<fstream> 

using namespace std; 

void menu(){ 
    cout << "\t********************************************************\n" 
     << "\t* Welcome to slot machine.        *\n" 
     << "\t* Would you like to play? (1 to play, 2 not to play) *\n" 
     << "\t********************************************************\n\n"; 
    return; 
} 

void update(int arr[], int &token) { 
    if (arr[0]==arr[1] && arr[1]==arr[2]) { 
     token+=4; 
     cout << "You win\n\n"; 
    } else if (arr[0]==arr[1] || arr[1]==arr[2] || arr[0]==arr[2]) { 
     token+=1; 
     cout << "You got two out of three\n\n"; 
    } else { 
     token-=1; 
     cout << "You lose\n\n"; 
    } 
} 

int main() { 
    freopen("file.txt", "w", stdout); 
    int x, arr[3], token=4; 
    srand(time(0)); 
    menu(); 
    cin >> x; 
    while(token!=0) { 
     cout << "You have " << token << " tokens\n\n" 
      << "Pull? (1 to pull, 2 not to pull)\n\n"; 
     cin>>x; 
     if(x==1) { 
      for(int i=0; i<3; i++) { 
       arr[i]=1+rand()%10; 
      } 
      cout << "\t\t"; 
      for(int j=0; j<3; j++) { 
       cout << arr[j] << " "; 
      } 
      cout << "\n\n"; 
      update(arr,token); 
     } 
     else{ 
      cout << "OK\n"; 
     } 
    } 
    cin.get(); 
    return 0; 
} 
+0

+1 per una domanda ben formata. –

+1

Dovrai ancora scrivere tutto due volte. freopen (..., stdout) SOSTITUISCE la destinazione corrente di stdout con il file (handle) del primo argomento di freopen().Un file (o flusso) in C/C++ può andare solo in un posto. Come principiante, non sono sicuro che ci sia un modo FACILE di scrivere codice che produca in due posizioni. Il modo in cui lo farei è implementando la mia variante di ostream che scrive in due posti contemporaneamente. Ma non è quasi una codifica per principianti. –

risposta

6

Non conosco un modo semplice per raggiungere questo obiettivo, ma in qualche modo sono riuscito a risolverlo.

Utilizzando i flussi è possibile eseguire l'output su file allo stesso modo in cui è possibile scrivere sulla console. C'è un modo siamo in grado di uscita per la console e file contemporaneamente:

#include <fstream> 

int main() 
{ 
    std::ofstream f("file.txt"); 
    f << "something"; 
} 

Ora c'è un punto possiamo cominciare?

Ho recentemente scritto flusso demultiplatore per affrontare questo problema:

#include <vector> 
#include <ostream> 
class stream_demultiplexer 
{ 
private: 
    typedef std::vector<std::ostream*> str_cont; 
    str_cont d; 
public: 
    stream_demultiplexer& put(std::ostream::char_type ch) 
    { 
     for(str_cont::iterator it = d.begin(); it != d.end(); ++it) 
      (*it)->put(ch); 
     return *this; 
    } 

    stream_demultiplexer& write(const std::ostream::char_type* s, std::streamsize count) 
    { 
     for(str_cont::iterator it = d.begin(); it != d.end(); ++it) 
      (*it)->write(s, count); 
     return *this; 
    } 

    stream_demultiplexer& flush() 
    { 
     for(str_cont::iterator it = d.begin(); it != d.end(); ++it) 
      (*it)->flush(); 
     return *this; 
    } 


    template<typename T> 
    stream_demultiplexer& operator<<(const T& obj) 
    { 
     for(str_cont::iterator it = d.begin(); it != d.end(); ++it) 
      (**it) << obj; 
     return *this; 
    } 

    stream_demultiplexer& operator<<(std::ios_base& (*func)(std::ios_base&)) 
    { 
     for(str_cont::iterator it = d.begin(); it != d.end(); ++it) 
      (**it) << func; 
     return *this; 
    } 

    template<typename CharT, typename Traits> 
    stream_demultiplexer& operator<<(std::basic_ios<CharT,Traits>& (*func)(std::basic_ios<CharT,Traits>&)) 
    { 
     for(str_cont::iterator it = d.begin(); it != d.end(); ++it) 
      (**it) << func; 
     return *this; 
    } 

    stream_demultiplexer& operator<<(std::ostream& (*func)(std::ostream&)) 
    { 
     for(str_cont::iterator it = d.begin(); it != d.end(); ++it) 
      (**it) << func; 
     return *this; 
    } 

    void add_stream(std::ostream& ss) 
    { 
     d.push_back(&ss); 
    } 
}; 

è possibile utilizzarlo in questo modo:

stream_demultiplexer spl; 
std::ofstream f("file.txt"); 
spl.add_stream(f); 
spl.add_stream(std::cout); 
spl << 55 << " HELLO WORLD"; 

mio approccio ha un vantaggio che manipolatori e di uscita non formattato funziona correttamente:

spl << 76 << " " << std::hex << 76 << std::endl; 
spl.put('a'); 
spl.write("ABCDE", 5); 
+1

Grazie mille per l'aiuto. Per il male non c'è un modo più semplice però. – Bob

4

Il modo più semplice in un ambiente UNIX consiste nell'utilizzare il comando shell tee:

$ my-program | tee output.txt 

copierà stdout al terminale, e anche al file output.txt.


Se dovete farlo in codice, è possibile utilizzare il proprio flusso di uscita, invece di cout, che inoltra ogni operator<< a due (o più) ostreams. Ciò mi sembra più piacevole (rispetto a me) che aggirarmi con il file di output C alla base del ostream C++ cout.

#include <ostream> 

class Tee { 
    std::ostream &first, &second; 

    template<typename T> friend Tee& operator<< (Tee&, T); 

public: 
    Tee(std::ostream &f, std::ostream &s) : first(f), second(s) {} 
}; 

template <typename T> 
Tee& operator<< (Tee &t, T val) 
{ 
    t.first << val; 
    t.second << val; 
    return t; 
} 

Quindi, se si sostituisce la vostra linea freopen con:

std::ofstream outfile("file.txt"); 
Tee tee(std::cout, outfile); 

si può semplicemente utilizzare tee << invece di cout <<.

Si noti che sarà necessario passare tee nelle proprie funzioni o renderlo globale affinché funzioni.

+0

Nota anche che non puoi 'tee << endl;' quindi dovrai usare ''\ n'' e implementare un' Tee.flush() 'se vuoi questa funzionalità. – feetwet

Problemi correlati