2012-11-26 22 views
12

Considerare:Differenza tra inizializzazioni stringstream.str (a_value) e stringstream << a_value

std::string  s_a, s_b; 

std::stringstream ss_1, ss_2; 

// at this stage: 
//  ss_1 and ss_2 have been used and are now in some strange state 
//  s_a and s_b contain non-white space words 

ss_1.str(std::string()); 
ss_1.clear(); 

ss_1 << s_a; 
ss_1 << s_b; 

// ss_1.str().c_str() is now the concatenation of s_a and s_b, 
//     <strike>with</strike> without space between them 

ss_2.str(s_a); 
ss_2.clear(); 

// ss_2.str().c_str() is now s_a 

ss_2 << s_b; // line *** 

// ss_2.str().c_str() the value of s_a is over-written by s_b 
// 
// Replacing line *** above with "ss_2 << ss_2.str() << " " << s_b;" 
//     results in ss_2 having the same content as ss_1. 

Domande:

  1. Qual è la differenza tra stringstream.str (a_value); e stringstream < < a_valore; e, in particolare, perché il primo non consente concatenazione tramite < < ma il secondo fa?

  2. Perché hanno ottenuto ss_1 automaticamente bianco-spazio tra s_a e S_B, ma abbiamo bisogno di aggiungere in modo esplicito lo spazio vuoto nella linea che potrebbe sostituire linea ***: ss_2 << ss_2.str() << " " << s_b;?

+0

In te Ad esempio, le stringhe sono vuote. Cosa intendi per 'ottenere automaticamente uno spazio bianco tra s_a e s_b'? –

+0

@JesseGood '// s_a e s_b contengono parole di spazio non-bianco' –

risposta

4

Il problema riscontrato è perché std::stringstream è costruito di default con ios_base::openmode mode = ios_base::in|ios_base::out che è una modalità non aggiungendo.

Sei interessato alla modalità di uscita qui (vale a dire: ios_base::openmode mode = ios_base::out)

std::basic_stringbuf::str(const std::basic_string<CharT, Traits, Allocator>& s) opera in due modi diversi, a seconda del openmode:

  1. mode & ios_base::ate == false: (es: non accodamento Flussi di uscita):

    str imposta pptr() == pbase(), in modo che l'output successivo sia sovrascrivere i caratteri copiati da s

  2. mode & ios_base::ate == true: (es: aggiungendo flussi di uscita):

    str imposterà pptr() == pbase() + s.size(), in modo che la successiva uscita sarà allegato all'ultimo carattere copiato da s

(si noti che questo aggiungendo modalità è nuovo in quanto C++ 11)

Maggiori dettagli possono essere trovati here.

Se si desidera che il aggiungendo problema, creare la tua stringstream con ios_base::ate:

std::stringstream ss(std::ios_base::out | std::ios_base::ate) 

Esempio semplice applicazione qui:

#include <iostream> 
#include <sstream> 

void non_appending() 
{ 
    std::stringstream ss; 
    std::string s = "hello world"; 

    ss.str(s); 
    std::cout << ss.str() << std::endl; 

    ss << "how are you?"; 
    std::cout << ss.str() << std::endl; 
} 

void appending() 
{ 
    std::stringstream ss(std::ios_base::out | std::ios_base::ate); 
    std::string s = "hello world"; 

    ss.str(s); 
    std::cout << ss.str() << std::endl; 

    ss << "how are you?"; 
    std::cout << ss.str() << std::endl; 
} 

int main() 
{ 
    non_appending(); 
    appending(); 

    exit(0); 
} 

Questa uscita sarà in 2 modi diversi, come spiegato in precedenza:

hello world 
how are you? 
hello world 
hello worldhow are you? 
+2

Un altro modo per farlo, senza modificare 'openmode', è cercare fino alla fine del flusso prima dell'inserimento. 'Ss.str (s); ss.seekp (0, std :: ios_base :: end); ss << "come stai?"; ' – Praetorian

+0

Grazie; tweak minore: In non_appending(), se la prima inizializzazione è più lunga, ad esempio, std::string s = "A very long hello world!";, la seconda riga di output sarà: "come stai? ciao mondo!" – user1823664

+1

@ user1823664 - per capire cosa sta succedendo qui è necessario capire che lo 'streambuffer' di' stringstream' usa i puntatori interni per memorizzare le posizioni nel buffer. 'str()' usa questi puntatori per creare un nuovo 'std :: string' - e, a seconda di dove' egptr' o 'pptr', otterrai una stringa creata da questi. –

4

consiglio di leggere di riferimento stringstream: http://en.cppreference.com/w/cpp/io/basic_stringstream

std::stringstream::str() sostituisce il contenuto della stringa sottostante

operator<< inserisce i dati nel flusso.

+0

Ancora non spiega perché' str() 'seguito da' << 'ha un comportamento simile, a meno che io non fraintenda qualcosa –

+2

L'altra cosa è che dopo aver usato' str() ', le cose vanno fuori sincrono. Ad esempio, usando 'str()' su una nuova istanza, seguito da 'operator <<' inseriremo la seconda parte all'inizio, sovrascrivendo la prima parte. http://ideone.com/OPR9Ps – chris

+1

Chiede perché chiamare l'operatore "<<" ** dopo ** usando 'str' per sostituire il contenuto non ** aggiunge ** alla fine - e la risposta è perché' openmode' non ha 'mangiato' set –

Problemi correlati