2009-07-16 15 views
7

Wie erzwingen std :: stringstream operator >>, um eine ganze Zeichenfolge zu lesen, anstatt bei den ersten Leerzeichen zu stoppen?Wie erzwinge ich std :: stringstream operator >> um eine ganze Zeichenfolge zu lesen?

Ich habe ein Template-Klasse bekam, die einen Wert aus einer Textdatei lesen speichert:

template <typename T> 
class ValueContainer 
{ 
protected: 
    T m_value; 

public: 
    /* ... */ 
    virtual void fromString(std::string & str) 
    { 
    std::stringstream ss; 
    ss << str; 
    ss >> m_value; 
    } 
    /* ... */ 
}; 

I Scharf-/Unscharfschaltung Strom Flaggen versucht haben, aber es hat nicht geholfen.

Klärungs

Die Klasse ist eine Container-Vorlage mit automatischer Umwandlung zu/von Typ T. Strings ist nur eine Instanz der Vorlage, es muss auch als auch andere Typen unterstützen. Deshalb möchte ich Operator >> zwingen, das Verhalten von std :: getline nachzuahmen.

+2

Ich bin nicht klar, was das Problem ist. Wenn Sie '>>' mit der Klasse 'T' arbeiten wollen, müssen Sie' >> 'wie folgt überschreiben: ' stringstream & operator >> (T & receiver) '. Innerhalb dieser Funktion haben Sie Zugriff auf den 'stringstream' (über' this') und auf 'receiver' und Sie können aus '* this' beliebig viele Daten ausmisten. Können Sie das Problem bitte deutlicher erklären? – Ari

+0

Tut mir leid, es ist natürlich "stringstream & operator" (stringstream & ss, T & receiver) ', und Sie greifen' ss' direkt zu. – Ari

Antwort

6

Als Betreiber >> ist nicht unsere Anforderung erfüllt, wenn T = string, können wir eine bestimmte Funktion schreiben für [T = String] Fall. Dies ist möglicherweise nicht die richtige Lösung. Aber, wie ein Work around erwähnt hat.

Bitte korrigieren Sie mich, wenn Ihre Anforderung nicht erfüllt wird.

I wie unten ein Beispielcode geschrieben haben:

#include <iostream> 
#include <sstream> 
#include <string> 

using namespace std; 

template <class T> 
class Data 
{ 
    T m_value; 
    public: 
    void set(const T& val); 
    T& get(); 
}; 

template <class T> 
void Data<T>::set(const T& val) 
{ 
    stringstream ss; 
    ss << val; 
    ss >> m_value; 
} 

void Data<string>::set(const string& val) 
{ 
    m_value = val; 
} 

template <class T> 
T& Data<T>::get() 
{ 
    return m_value; 
} 

int main() 
{ 
    Data<int> d; 
    d.set(10); 
    cout << d.get() << endl; 

    Data<float> f; 
    f.set(10.33); 
    cout << f.get() << endl; 

    Data<string> s; 
    s.set(string("This is problem")); 
    cout << s.get() << endl; 
} 
+0

Ich habe tatsächlich das Problem auf diese Weise gelöst, mit spezialisierten Vorlage für Zeichenfolgen. Danke für die Antwort! –

1

Es gibt keine Möglichkeit mit dem Operator >>, dass ich davon achte, dass man seine eigene Facette schreibt (operator >> stop beim ersten Zeichen, für das isspace (c, getloc()) wahr ist). Aber es gibt eine getline-Funktion in <string>, die das gewünschte Verhalten hat.

+0

Ich bin mir dessen bewusst, aber es muss ich auch von String zu anderen Werten konvertieren und ich möchte keinen separaten Container für Strings erstellen. –

+0

Wie gesagt, die Alternative zur Verwendung von getline ist das Schreiben einer Facette. Ich weiß, was ich gebrauchen würde. Beachten Sie, dass die Verwendung von Merkmalen es Ihnen ermöglichen würde, nur das Verhalten von fromString und nicht den gesamten Container zu Sonderfällen zu machen. – AProgrammer

2

Wo soll es aufhören? Wenn Sie eine ganze Zeile lesen möchten, benötigen Sie wahrscheinlich getline Funktion, wenn Sie eine ganze Zeichenfolge im Streamstring-Objekt gespeichert haben, ist Ihre Wahl ostringstream::str Methode.

+0

Ich denke, ostringstream :: str() ist die beste Lösung hier. – p00ya

1

Ich gehe davon aus, dass Sie diese Vorlage mit T = std::string instanziieren. In diesem Fall könnten Sie getline verwenden:

getline(ss, m_value, '\0'); 

Dies setzt allerdings voraus Sie nul-Zeichen als gültige Teile der Zeichenfolge nicht akzeptieren.

Andernfalls können Sie Ihren eigenen Extraktor für `T 'schreiben. Hier

5

ist eine Lösung:

std::istream & ReadIntoString (std::istream & istr, std::string & str) 
{ 
    std::istreambuf_iterator<char> it(istr), end; 
    std::copy(it, end, std::inserter(str, str.begin())); 
    return istr; 
} 

(Dank der Original-Poster in C++ Newsgroup)

+1

Wenn der ursprüngliche Post irgendwo online ist, fügen Sie bitte einen Link hinzu! – lumbric