Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » stringstream rdbuf()

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 < [ 2 ]
000
26.09.2005, 10:25 Uhr
~nakaa11
Gast


warum kann ich den buffer eines stringstreams nicht mehr an eine variable übergeben nachdm ich den stringstream mit rdbuf() aufgerufen habe?
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
26.09.2005, 16:01 Uhr
Spacelord
Hoffnungsloser Fall


Was willst du denn da übergeben? Der alte streambuffer ist der Rückgabewert von rdbuf.
Den Pointer musst du dann speichern und kannst ihn dann später wieder herstellen.
So ganz hab ich dein Problem allerdings nicht verstanden.....

MfG Spacelord
--
.....Ich mach jetzt nämlich mein Jodeldiplom.Dann hab ich endlich was Eigenes.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
26.09.2005, 17:49 Uhr
~nakaa11
Gast


also folgendes:

in meinem istringstream is steht eine zeichenfolge.
ich gebe sie aus mit

Code:
cout << is.rdbuf();


und dann versuche ich dieselbe zeichenfolge in einer variablen zu speichern.
bsp:


Code:
double zahl:
is >> zahl;



dann steht nix in der zahl.

danke für die bemühungen!

mod edit: clase tags mit / statt \

Dieser Post wurde am 26.09.2005 um 17:51 Uhr von Pablo editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
26.09.2005, 22:42 Uhr
virtual
Sexiest Bit alive
(Operator)


Das geht nicht, weil wenn Du mit dem cout den entsprechenden Teil aus dem Stringbuffer bereits liest.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
27.09.2005, 09:16 Uhr
~nakaa11
Gast


naja gut, aber der buffer wird ja nicht gelöscht. heißt das dass der zeiger auf den buffer ne adresse weitergeschoben wird und könnte ich ihn zurücksetzen? also mich würd mal interessieren wie das intern funktioniert. nakaa*
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
27.09.2005, 09:51 Uhr
virtual
Sexiest Bit alive
(Operator)


Im Prinzip hast Du, wenn Du mit Streams arbeitest zwei wichtige Klassen vor Dir: Zum einen der Stream selbst, zum anderen den Streambuffer. Die Aufgabe des Streambuffers ist ist, die Daten ide der Stream im liefert zu speichern, bzw. die Daten bereitzustellen. Die Aufgabe des Streams selbst liegt einfach nur darin, die Daten zu formatieren.

Wie Du schon richtig bemerkt hast, kann man mittels rdbuf() den Buffer eines Streams ermitteln bzw. ihn auch neu setzen.

Ein Streambuffer hat zwei "Areas": eine Put-Area (für Schreibzugriffe) und eine (Get-Area) (für lese zugriffe). Beide Areas können nahezu unabh. voneinander angesteuert werden. Insbesondere kann man für die Areas den Schreib/Lese/Zeiger setzen, etwa über die methode seekg oder seekp


Dein Problem liesse sich ggf. wie folgt lösen:

C++:
#include <iostream>
#include <sstream>

int main() {
        std::stringstream s;

        s<<4711;

        std::cout<<s.rdbuf()<<std::endl;

        int i;
        s.seekg(0, std::ios::beg);
        s>>i;

        std::cout<<i<<std::endl;
}


Zu beachten ist das seekg. Allerdings gibt es eben streams, welche nicht mehr zurückspulen können. Ausserdem bekommst Du Probleme, wenn Du statt

C++:
        std::cout<<s.rdbuf()<<std::endl;


folgendes Schreiben würdest:

C++:
        int j;
        s>>j;
        std::cout<<j<<std::endl;


In diesem Fall wird nämlich das eof Flag bit des s - Streams beeinflusst, welches Du vor dem seekg mittels clear zurücksetzen müsstest.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
29.09.2005, 17:35 Uhr
~nakaa11
Gast



Zitat von Benutzer:

In diesem Fall wird nämlich das eof Flag bit des s - Streams beeinflusst, welches Du vor dem seekg mittels clear zurücksetzen müsstest.



schon wieder nicht verstanden. j ist doch als variable ganz normal auf meinem stack gespeichert.
wieso kann ich sie plötzlich nicht mehr mit dem std::cout ausgeben? was hat das mit dem stringstream zu tun. is das nicht wurscht ob der ein eof am ende hat oder nicht?
ansonsten schon mal vielen dank für die erklärungen!
viele grüße,
nakaa
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
29.09.2005, 22:20 Uhr
virtual
Sexiest Bit alive
(Operator)


Nicht das j ist das Problem, sondern das s:
Ein Stream (also auch s) hat Status bits:
good: Alles in ordnung
fail: Die letzte Aktion ging schief, aber man kann mit dem Stream noch arbeiten
bad: Die letzte Aktion ging schief, der Inhalt des Streams ist korrupt
eof: Ende des Streams wurde erreicht

Solange ein andere Bit ausser dem good Bit gesetzt ist, ist der Stream nicht nutzbar. Dh insbesondere, daß jeder Befehl zum Lesen ignoriert wird. Dies ändert sich erst, indem man die Flags mittels der method clear() löscht.

Zu beachtzen ist, daß diese Flag bestandteil des STreams, nicht des Streambuffers sind. Daher werden also, wenn du direkt mit dem Streambuffer arbeitest, logischerweise keine Flags gesetzt, bei der Aktion mit Streams jedoch schon.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
008
30.09.2005, 09:01 Uhr
~nakaa11
Gast


morgen!
hmmhmmmm.
das bedeutet ja, dass ich daselbe problem habe wenn ich folgendes mache:

Code:

char * filename;
ostringstream merr_name;
filename=(char*)merr_name.str().c_str();


, oder?
denn in meinem code hat filename an einer anderen stelle plötzlich einen anderen wert als den den ich mit dem c_string pointer übergeben habe...
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
009
30.09.2005, 10:15 Uhr
virtual
Sexiest Bit alive
(Operator)


Also prinzipiell scheint es Dir doch darum zu gehen, etwas einmal in einen stream zu schreiben und es zweimal auszulesen?

Dazu habe ich mal einen Speziellen Stream geschrieben, welchen ich grade überarbeite. Der nchstehende Stream ist noch nicht komplett, funktioniert aber:

C++:
#ifndef OTEESTREAM_H_INCLUDED_
#define OTEESTREAM_H_INCLUDED_

#include <ostream>

namespace strm {


namespace intern {

template< class Ch, class Tr= std::char_traits<Ch> >
class basic_teestreambuf : public std::basic_streambuf< Ch, Tr > {

// === TYPES ======================================================================================
public:
    /** Type of a stream. */
    typedef std::basic_ostream<Ch,Tr> stream_type;

    /** Type of a pointer to the stream. */
    typedef std::basic_ostream<Ch,Tr>* stream_pointer;

    /** Character type. */
    typedef Ch char_type;

    /** Character pointer type. */
    typedef Ch* char_pointer;

    /** Character traits type. */
    typedef Tr traits_type;

    /** Integer type from character traits. */
    typedef typename traits_type::int_type int_type;

// === CONSTANTS ==================================================================================
private:
    /** Size of the internal buffer. */
    static const std::streamsize BUFFERSIZE = 8192;

// === ATTRIBUTES =================================================================================
private:
    /** First output streamn or <code>null</code>. */
    stream_pointer m_first;

    /** Second output streamn or <code>null</code>. */
    stream_pointer m_second;

    /** Default buffer. */
    char_type m_default_buffer[BUFFERSIZE];

// === PRIVATE INTERFCE ===========================================================================
private:

    /**
     * Assigment is forbidden.
     */

    basic_teestreambuf& operator = (
        const basic_teestreambuf&);

    /**
     * Copy is forbidden.
     */

    basic_teestreambuf(
        const basic_teestreambuf&);

// === PROTECTED INTERFACE ========================================================================
protected:

    /**
     * Flushes the buffer.
     * Flushing means that the internal bu´ffer is flushed and then the both attachted streams
     * as well.
     *
     * @return 0 on success.
     */

    virtual int sync() {
        int_type c;
        // First write to the subordinated streams
        if (NULL != pbase() && pbase()!=pptr()) {
            c = traits_type::to_int_type(overflow());
            if (traits_type::eq_int_type(c, traits_type::eof())) {
                return c;
            }
        }
        // new sync on the subordinated streams
        if (NULL != m_first) {
            c = m_first->rdbuf()->pubsync();
            if (traits_type::eq_int_type(c, traits_type::eof())) {
                return c;
            }
        }
        if (NULL != m_second) {
            c = m_second->rdbuf()->pubsync();
            if (traits_type::eq_int_type(c, traits_type::eof())) {
                return c;
            }
        }
        return 0;
    }

    /**
     * Sets the buffer.
     * Initial, this method is called by the constructor in order to set the buffer to an area
     * of {@link #BUFFERSIZE} bytes. But this method might be also called after construction to
     * assign a new buffer. By default <code>setbuf(0,0)</code> means "unbuffered" and buffering
     * is turned off.
     * <p>
     * Before changing the buffer, any data in the old buffer is flushed.
     *
     * @param buffer        Pointer to the new buffer.
     * @param size            Size of the new buffer.
     *
     * @return                This instance.
     */

    virtual std::basic_streambuf<char_type,traits_type>*  setbuf(
        char_pointer buffer,
        std::streamsize size) {
    
        sync(); // TODO: how to handle an error here?
        setp(buffer, buffer+size);
        return this;
    }

    virtual int_type overflow(
        int_type c = traits_type::eof()) {

        char_pointer base = pbase();

        // Check, if buffered IO
        if (NULL!=base) {
            // This is buffered IO
            char_pointer ptr = pptr();

            // Write to subordinated streams
            if (NULL!=m_first) {
                if (m_first->rdbuf()->sputn(base, ptr-base) != ptr-base) {
                    return traits_type::to_int_type(traits_type::eof());
                }
            }
            if (NULL!=m_second) {
                if (m_second->rdbuf()->sputn(base, ptr-base) != ptr-base) {
                    return traits_type::to_int_type(traits_type::eof());
                }
            }

            // Mark buffer as empty
            setp(base, epptr());

            // If not eof, write to buffer
            if (!traits_type::eq_int_type(c, traits_type::eof())) {
                return sputc(c);
            }
        }
        else {
            // This is unbuffered IO

            // Write to subordinated streams
            int r;
            if (NULL!=m_first) {
                r = m_first->rdbuf()->sputc(c);
                if (traits_type::eq_int_type(r, traits_type::eof())) {
                    return traits_type::to_int_type(traits_type::eof());
                }
            }
            if (NULL!=m_second) {
                r = m_second->rdbuf()->sputc(c);
                if (traits_type::eq_int_type(r, traits_type::eof())) {
                    return traits_type::to_int_type(traits_type::eof());
                }
            }
        }

        return traits_type::to_int_type(c);
    }

// === PUBLIC INTERFACE ===========================================================================
public:
    /**
     * Sole constructor.
     * Creates a new instance with the specified target streams. The buffer is initial set to the
     * default buffer.
     *
     * @param first        Pointer to the first stream.
     * @param second    Pointer to the second stream
     */

    basic_teestreambuf(stream_pointer first=NULL, stream_pointer second=NULL)
        : m_first(first), m_second(second) {

        setbuf(m_default_buffer, BUFFERSIZE);
    }

    /**
     * Destructor.
     * Ensures that any cached data is flushed.
     */

    virtual ~basic_teestreambuf() {
        try {
            sync();
        }
        catch(...) {
        }
    }

};

} // namespace intern


template< class Ch, class Tr=std::char_traits<Ch> >
class basic_oteestream : public std::basic_ostream< Ch, Tr > {

// === TYPES ======================================================================================
public:
    /** Type of a stream. */
    typedef std::basic_ostream<Ch,Tr> stream_type;

    /** Character type. */
    typedef Ch char_type;

    /** Character traits type. */
    typedef Tr traits_type;

    typedef intern::basic_teestreambuf<Ch,Tr> teestreambuf_type;
    
public:
    

    basic_oteestream()
        : stream_type(new teestreambuf_type()) {
    }
    basic_oteestream(std::ostream& first)
        : stream_type(new teestreambuf_type(&first)) {
    }
    basic_oteestream(std::ostream& first, std::ostream& second)
        : stream_type(new teestreambuf_type(&first, &second)) {
    }
};


typedef basic_oteestream<char> oteestream;
typedef basic_oteestream<wchar_t> woteestream;

}

#endif



Im Prinzip ist ein oteestream - welcher dort ja definiert wird - ein Streamduplizierer. Das folgende Beispiel deomnstriert die ungefähre Arbeitsweise:

C++:
int main() {
    std::stringstream ein_stream;
    strm::oteestream tee(ein_stream, std::cout);

    tee<<"Ausgabe nach tee"<<std::endl;

    std::string ausgabe = ein_stream.str();
}


oteestream erwartet also zwei untergeordnete (bieliebige) Streams als parameter bei der Construction. Alles, was man in den oteestream reintut, kommt zweimal raus, nämlich bei beiden Streams, die man bei der Konstruktion angegeben hat.
Im obige Beispiel wird also "Ausgabe nach tee" zum einen zur Standardausgabe ausgegeben, zum anderen auch in den Stringstream ein_stream. Daher kannst Du dann den Inhalt von ein_stream noch in eine Variable kopieren...

Die Klasse ist zwar funktionstüchtig, aber eben noch nicht fertig: ich bin mir noch nicht ganz sicher, ob es sinn macht, oteestream eine Seek-Method zu schenken, ausserdem fehlen noch methoden, die untergeordneten Streams im nachhinein zu verändern.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 < [ 2 ]     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: