为什么在调用istream :: getline之后可以打印字符串'\ 0'之后的部分

时间:2018-01-24 03:44:09

标签: c++ string iostream getline

要将我的版本合并到istream::getline,我测试了以下代码:

#include <iostream>
#include <sstream>
using namespace std;
int main()
{
    string s("abcdefgh \nijklmnopqrst");        
    string s1;
    stringstream ss(s);
    ss >> s1;
    cout <<"s1:"<< s1 << endl;
    ss.getline(&s1[0], 250, '\n');
    if(s1[0]==' '&&s1[1]=='\0')
      cout << "new s1:"<<s1 << endl;
    getchar();
    return 1;
}

据我了解,ss.getline调用将提取空格,终结符'\n'然后将空格和'\0'分配到s1[0]s1[1]分别引用{{ 3}},s1[1]之后的字符保持不变,因为一旦终结符到达,提取就会停止。但令我困惑的是,s1可以打印出来。控制台打印

s1:abcdefgh
new s1:  cdefgh

为什么在这种情况下可以打印字符串'\ 0'之后的部分?

2 个答案:

答案 0 :(得分:2)

C ++字符串和使用它们的I / O工具并不真正关心server个字节。他们知道自己的长度,如果他们的数据长度为N个字节,那么这些字节中的一些是client并不重要,NUL s将一直持续到达到记录的长度(设置为你用NUL)阅读。

当你这样做时,你明确地误用了你的字符串:

iostream

因为ss >> s1;绕过了ss.getline(&s1[0], 250, '\n'); 的安全访问者来获取原始&s1[0](更糟糕的是,你告诉std::string它可能最多可以提取250个字符缓冲区可能要小得多),并保持长度/容量信息不变(因此它仍然认为它包含许多字符char*读取)。

你真的想要std::getline,面向getline,并且能够正常工作(包括根据需要为您调整输出大小,调整已知字符串长度,确保现有数据不会留在原位) :

ss >> s1;

答案 1 :(得分:1)

std::string允许包含空字符。与传统的c-string不同,null字符不用于确定其长度(尽管在其末尾存储了一个空字符,以便允许它与c-string接受函数一起使用)。它的长度是单独存储的,可以使用size()length()成员函数进行检索。因此,当您使用operator<<打印出来时,操作员在找到空值时不会停止打印,而是在打印出s1.size()个字符时停止打印。