Подтвердить что ты не робот

Разница между инициализацией stringstream.str(a_value) и 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.

Вопросы:

  • В чем разница между stringstream.str(a_value); а также stringstream < ценность; и, в частности, почему первый не позволяют конкатенацию через < но второй делает?

  • Почему ss_1 автоматически получает пустое пространство между s_a и s_b, но нам нужно явно добавить пробел в строку, которая могла бы заменить строку ***: ss_2 << ss_2.str() << " " << s_b;?

4b9b3361

Ответ 1

Проблема, с которой вы столкнулись, заключается в том, что по умолчанию std::stringstream создается с помощью ios_base::openmode mode = ios_base::in|ios_base::out, который является неприемлемым.

Здесь вы интересуетесь режимом вывода (например: ios_base::openmode mode = ios_base::out)

std::basic_stringbuf::str(const std::basic_string<CharT, Traits, Allocator>& s) работает по-разному, в зависимости от openmode:

  • mode & ios_base::ate == false: (то есть: не добавляемые выходные потоки):

    str установит pptr() == pbase(), так что последующий вывод будет перезаписать символы, скопированные из s

  • mode & ios_base::ate == true: (то есть: добавить выходные потоки):

    str установит pptr() == pbase() + s.size(), так что последующий вывод будет добавлен к последнему символу, скопированному из s

(Обратите внимание, что этот добавочный режим новый, поскольку С++ 11)

Более подробную информацию можно найти здесь.

Если вы хотите добавить поведение, создайте stringstream с помощью ios_base::ate:

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

Простой пример приложения здесь:

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

Это будет выводиться двумя различными способами, как описано выше:

hello world
how are you?
hello world
hello worldhow are you?

Ответ 2

Предложите вам прочитать ссылку на строковый поток: http://en.cppreference.com/w/cpp/io/basic_stringstream

std::stringstream::str() Заменяет содержимое базовой строки

operator<< Вставляет данные в поток.