2012-12-20 15 views
12

Próbuję użyć funkcji freopen() w celu wydrukowania pliku tekstowego i ekranu, ale ja tylko osiągam drukowanie do pliku.Używanie funkcji freopen() do drukowania do pliku i ekranu

Zastanawiam się, czy można łatwo zapisać programy do pliku i wydrukować na ekranie? Ponieważ działałem w inny sposób, ale musiałem wydrukować każde stwierdzenie dwukrotnie. Jeden jest dla pliku drugi tylko dla wyjścia.

Uwaga: Jestem nowy w C++ i staram się go nauczyć dla klasy w następnym semestrze, więc potrzebna jest bezpośrednia odpowiedź, ponieważ już patrzę online i nie mogłem znaleźć żadnych prostych odpowiedzi na to rozwiązanie.

Oto co mam do tej pory:

#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 za dobrze uformowane pytanie. –

+1

Będziesz musiał napisać wszystko dwa razy. freopen (..., stdout) zamieni bieżące miejsce docelowe stdout na plik (uchwyt) pierwszego argumentu freopen().Plik (lub strumień) w C/C++ może przejść tylko do jednego miejsca. Jako początkujący, nie jestem pewien, czy istnieje ŁATWY sposób napisania kodu, który wyprowadza do dwóch miejsc. Sposób, w jaki to zrobię, polega na wprowadzeniu własnego wariantu ostream, który zapisuje się jednocześnie w dwóch miejscach. Ale to nie jest kodowanie dla początkujących. –

Odpowiedz

6

Nie znam prostego sposobu, aby to osiągnąć, ale udało mi się jakoś to rozwiązać.

Korzystając z funkcji fstreams, możesz wysyłać do pliku w ten sam sposób, w jaki możesz pisać na konsoli. Jest sposób możemy wyjściowe do konsoli i złożyć jednocześnie:

#include <fstream> 

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

Teraz istnieje punkt możemy zacząć?

I niedawno napisany strumienia demultiplekser w celu rozwiązania tego problemu:

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

można go używać tak:

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

Moje podejście ma tę zaletę, że manipulatory i wyjście niesformatowany działa poprawnie:

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

Dziękuję bardzo za pomoc. Zły nie jest jednak prostszy. – Bob

4

Prosty sposób na UNIXopodobnych środowiska jest użycie polecenia powłoki tee:

$ my-program | tee output.txt 

skopiuje stdout do terminalu, a także do pliku output.txt.


Jeśli masz to zrobić w kodzie, można użyć własnego strumienia wyjściowego zamiast cout, który przekazuje każdy operator<< do dwóch (lub więcej) ostreams. Wydaje mi się, że jest to ładniejsze (niż dla mnie), ponieważ zawiera plik wyjściowy C leżący pod C++ ostream 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; 
} 

Następnie, jeśli zastąpi freopen linii z:

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

można po prostu użyć tee << zamiast cout <<.

Pamiętaj, że musisz przekazać tee do swoich funkcji lub sprawić, że stanie się globalny, aby działał.

+0

Zwróć też uwagę, że nie możesz "tee << endl;' więc musisz użyć '\ n'' i zaimplementować' Tee.flush() 'jeśli chcesz tę funkcjonalność. – feetwet

Powiązane problemy