提问人:Finley 提问时间:1/24/2018 最后编辑:Finley 更新时间:1/24/2018 访问量:54
为什么调用 istream::getline 后可以打印字符串的“\0”后面的部分
Why the part after '\0' of a string can be printed after calling istream::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;
}
据我了解,调用将提取空格,然后终止符分配空格和 into 并单独引用 cpluscplus,字符后保持不变,因为一旦终止符到达,提取就会停止。但一个意想不到的点让我感到困惑的是,它可以打印出来。控制台打印ss.getline
'\n'
'\0'
s1[0]
s1[1]
s1[1]
s1
s1:abcdefgh
new s1: cdefgh
为什么在这种情况下可以打印字符串的“\0”后面的部分?
答:
std::string
允许包含 null 字符。与传统的 c 字符串不同,null 字符不用于确定其长度(尽管 null 字符存储在其末尾,以便允许它与 c 字符串接受函数一起使用)。它的长度是单独存储的,可以使用 or 成员函数进行检索。因此,当您使用 打印出来时,运算符在找到 null 时不会停止打印,而是在打印字符时停止打印。size()
length()
operator<<
s1.size()
C++ 字符串和用于处理它们的 I/O 工具并不真正关心字节。他们知道自己的长度,如果他们的数据是 N 个字节长,那么其中一些字节是否长并不重要,s 将继续运行,直到它们达到记录的长度(在读取时设置)。NUL
NUL
iostream
ss >> s1;
当你这样做时,你在这里明确地滥用了你的字符串:
ss.getline(&s1[0], 250, '\n');
因为绕过 的安全访问器来获取原始数据(更糟糕的是,您告诉它可以拉取多达 250 个字符,而底层缓冲区可能要小得多),并且保持长度/容量信息不变(因此它仍然认为它包含读取的字符数)。&s1[0]
std::string
char*
getline
ss >> s1;
你真的想要 std::getline
,它是面向的,并且可以正常工作(包括根据需要为你调整输出大小,调整已知的字符串长度,确保现有数据不会留在原位):std::string
std::getline(ss, s1, '\n');
评论
ss.getline(s1, 250, '\n')