要将我的版本合并到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'之后的部分?
答案 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()
个字符时停止打印。