为什么std :: ends导致字符串比较失败?

And*_*pov 0 c++ boost stl

我昨天花了大约4个小时试图在我的代码中解决这个问题.我将问题简化为下面的示例.

我们的想法是将字符串存储在以std :: ends结尾的字符串流中,然后将其检索并将其与原始字符串进行比较.

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

int main( int argc, char** argv )
{
    const std::string HELLO( "hello" );

    std::stringstream testStream;

    testStream << HELLO << std::ends;

    std::string hi = testStream.str();

    if( HELLO == hi )
    {
        std::cout << HELLO << "==" << hi << std::endl;
    }

    return 0;
}

正如您可能猜到的,上面的代码在执行时不会打印出任何内容.

虽然,如果打印出来,或者在调试器(VS2005)中查看,HELLO和hi看起来相同,它们的.length()实际上相差1.这就是我猜测导致"=="运算符失败的原因.

我的问题是为什么.我不明白为什么std :: ends是一个不可见的字符添加到字符串hi,使hi和HELLO的长度不同,即使它们具有相同的内容.此外,这个看不见的角色不会被增强修剪修剪.但是,如果使用strcmp比较两个字符串的.c_str(),则比较正常.

我首先使用std :: ends的原因是因为我在过去遇到了一些问题,因为stringstream在流的末尾保留了垃圾数据.std :: ends为我解决了这个问题.

Joh*_*itb 12

std::ends在流中插入空字符.将内容作为std::string将保留该空字符并在相应位置创建具有该空字符的字符串.

所以std :: string确实可以包含嵌入的空字符.下面的std :: string的内容不同的:

ABC
ABC\0
Run Code Online (Sandbox Code Playgroud)

二进制零不是空格.但它也不能打印,所以你不会看到它(除非你的终端专门显示它).

比较使用strcmpstd::string在传递时将a 的内容解释为C字符串.c_str().它会说

嗯,第一个\0(终止空字符)之前的字符是ABC,所以我认为字符串是ABC

因此,上述两者之间不会有任何区别.您可能遇到此问题:

std::stringstream s;
s << "hello";
s.seekp(0);
s << "b";
assert(s.str() == "b"); // will fail!
Run Code Online (Sandbox Code Playgroud)

断言将失败,因为stringstream使用的序列仍然是包含"hello"的旧序列.你做的只是覆盖第一个角色.你想这样做:

std::stringstream s;
s << "hello";
s.str(""); // reset the sequence
s << "b";
assert(s.str() == "b"); // will succeed!
Run Code Online (Sandbox Code Playgroud)

另请阅读此答案:如何重用ostringstream