2012-12-20 17 views
12

freopen()を使用してテキストファイルと画面に印刷しようとしていますが、ファイルへの印刷のみを行っています。freopen()を使用してファイルと画面に印刷する

プログラムの出力をファイルに保存して画面に印刷するのが簡単かどうか疑問に思っていましたか?なぜなら、これは別の方法で動作していたからですが、すべてのステートメントを2回印刷する必要がありました。 1つはファイルのためのもので、もう1つは出力のためのものです。

注:私はC++を初めてお持ちで、次の学期に向けて学びたいと思っています。既にオンラインで見ていて直接ソリューションが必要です。ここで

は、私がこれまで持っているものです。

#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よく形成された質問です。 –

+1

あなたはまだすべてを2回書く必要があります。 freopen(...、stdout)は、stdoutの現在のデスティネーションをfreopen()の最初の引数のファイル(ハンドル)に置き換えます。C/C++のファイル(またはストリーム)は1つの場所にしか移動できません。 初心者として、2つの場所に出力するコードを簡単に書く方法があるかどうかはわかりません。私がやる方法は、ostreamの独自の変種を実装して、一度に2つの場所に書き込むことです。しかし、初心者コーディングはほとんどありません。 –

答えて

6

これを達成する簡単な方法はわかりませんが、私は何とかこれを解決することができました。

fstreamを使用すると、コンソールに書き込むのと同じ方法でファイルに出力できます。

#include <fstream> 

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

ここで始めることができる点があります。コンソールとファイルに同時に出力する方法はありますか?

私は最近、その問題に対処するためのストリームデマルチプレクサを書いた:

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

あなたはこのようにそれを使用することができます:

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

私のアプローチはマニピュレータと未フォーマットの出力が正常に動作する利点があります。

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

ありがとうございました。悪いことに、より単純な方法ではありません。 – Bob

4

UNIXライクな環境での簡単な方法は、シェルコマンドtee使用することです:

$ my-program | tee output.txt 

を端末に標準出力にコピーされます、ファイルoutput.txtにも送信されます。


あなたはコードでそれをしなければならない場合は、あなたがostreams 2つ(またはそれ以上)にすべてのoperator<<を転送する代わりにcoutの独自の出力ストリームを、使用することができます。これは、C++のostream coutの根底にあるC出力ファイルを使ってみるよりも、(私にとっては)より良い感じです。あなたとあなたのfreopenはラインを交換する場合

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

次に、:

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

あなただけtee <<の代わりcout <<使用することができます。

teeを関数に渡すか、関数をグローバルにする必要があります。

+0

また、 'tee << endl;できないことに注意してください。そうすれば' '\ n' 'を使用し、 'Tee.flush()'を実装する必要があります。 – feetwet

関連する問題