Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Databyte

Alter Hase

  • »Databyte« ist der Autor dieses Themas

Beiträge: 1 040

Wohnort: Na zu Hause

Beruf: Student (KIT)

  • Private Nachricht senden

1

01.04.2010, 14:20

cout zusätzlich in Console ausgeben

Hi

Wie der Titel schon sagt, möchte ich alles das was über cout in die Console geschrieben wird, zusätzlich in eine
Datei ausgeben. Mit std::cout.rdbuf() kann man ja den stream zozusagen umleiten. Das Problem ist, dass
wenn man dort den streambuffer von einem ofstream übergibt, das genze nicht mehr in die Console geschrieben
wird ( was ja auch irgendwie logisch ist )... nur wie kann ich jetzt den output sowohl in die Console als auch in
die Datei lenken ?

Ich habe es schon mit einem eigenen Streambuffer nach folgendem musster versucht ( hier noch ohne Datei):

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class StreamInterceptor
    : public std::streambuf
{
public:
    StreamInterceptor(std::ostream& _stream)
    {
        _stream.rdbuf(this);
    }

    std::streamsize xsputn ( const char * s, std::streamsize n )
    {
        String str(s, n);
        printf(str.c_str());
        return (n);
    }

private:
    std::streambuf* m_OldStreamBuffer;
};

// Und dann der aufruf irgendwie so:
new StreamInterceptor(std::cout);


Das Problem dabei ist, dass bei folgendem Aufruf

C-/C++-Quelltext

1
std::cout << "Hallo" << 1 << String("Cool");


nur das "Hallo" geschrieben wird... wie krieg ich die anderen Variablentypen auch noch ?

2

01.04.2010, 14:24

Ich denke ich würde einfach eine eigene Streamklasse machen, die den << Operator überlädt und dann einmal den << Operator von der Konsolenausgabe aufruft und einmal den von dem Dateistream.
D.h. den Stream auf den cout zeigt speichern, cout auf deine Klasse setzen und in der Klasse einen Dateistream haben.

Im groben sollte es so gehen, aber ich habe mich damit schon ein Weilchen nicht mehr beschäftigt.
Lieber dumm fragen, als dumm bleiben!

Databyte

Alter Hase

  • »Databyte« ist der Autor dieses Themas

Beiträge: 1 040

Wohnort: Na zu Hause

Beruf: Student (KIT)

  • Private Nachricht senden

3

01.04.2010, 16:05

Habs jetzt hieraus genommen: http://www.c-plusplus.de/forum/viewtopic…769.html#842769
Und so umgesetzt:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
class StreamLogger
    : public std::streambuf
{
public:
    typedef std::streambuf base_type;
    typedef base_type::traits_type traits_type;

    StreamLogger(   std::ostream& _outStream)
        :   m_OldSB( _outStream.rdbuf()) ,
            m_OutStream( _outStream )
    {
        // hänge mich selbst bei 'out' als Streambuf ein.
        m_OutStream.rdbuf( this );
    }

    ~StreamLogger()
    {
        // Stellt die Ausgangssituation wieder her
        m_OutStream.rdbuf( m_OldSB );
    }

    static void OpenLogFile(const String& _fileName)
    {
        // Logfile öffnen, wenn nicht schon offen !
        if(!FileStream.is_open())
        {
            FileStream.open(_fileName.c_str());

            // Aus irgendeinem grund muss der Stream erstmal geflushed werden
            FileStream.flush();

            // Ist er wirklich offen ?
            if(!FileStream.is_open())
                throw LogStreamException();
        }
    }

    static void CloseLogFile()
    {
        // Logfile schließen
        FileStream.close();
    }

protected:
    virtual int_type overflow( int_type c = traits_type::eof() )
    {
        // jedes Zeichen an BEIDE Streambufs sb1 & sb2 weitergeben
        if( m_OldSB && FileStream.rdbuf()
            && !traits_type::eq_int_type( m_OldSB->sputc( c ),              traits_type::eof() )
            && !traits_type::eq_int_type( FileStream.rdbuf()->sputc( c ), traits_type::eof() )
            )
            return traits_type::not_eof( c );
        return traits_type::eof();  // einer der Streambufs tut nicht
    }

private:
    // Kopieren verhindern
    StreamLogger( const StreamLogger& );
    StreamLogger& operator=( const StreamLogger& );

    // Den FileStream soll es nur einmal geben
    static std::ofstream    FileStream;

    std::streambuf* m_OldSB;
    std::ostream&   m_OutStream;
}; 

std::ofstream StreamLogger::FileStream;



// Ein paar StreamLogger
StreamLogger*   StreamLogger_cout = NULL;
StreamLogger*   StreamLogger_cerr = NULL;
StreamLogger*   StreamLogger_clog = NULL;




void InitLog(const String& _fileName)
{
    StreamLogger::OpenLogFile(_fileName);

    StreamLogger_cout = new StreamLogger(std::cout);
    StreamLogger_cerr = new StreamLogger(std::cerr);
    StreamLogger_clog = new StreamLogger(std::clog);
}

void UnInitLog()
{
    SafeDelete(StreamLogger_cout);
    SafeDelete(StreamLogger_cerr);
    SafeDelete(StreamLogger_clog);

    StreamLogger::CloseLogFile();
}


Nur steht da, dass das nicht die Performanteste lösung ist... jetzt frage ich mich wiso ?

Werbeanzeige