为什么调用 istream::getline 后可以打印字符串的“\0”后面的部分

Why the part after '\0' of a string can be printed after calling istream::getline

提问人:Finley 提问时间:1/24/2018 最后编辑:Finley 更新时间:1/24/2018 访问量:54

问:

为了巩固我的不稳定性,我测试了以下代码: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”后面的部分?

C++ 字符串 IOSTREAM getLine

评论

1赞 Zan Lynx 1/24/2018
为什么你还在使用糟糕的代码,而你另一个问题中的每个人都解释了为什么它是错误的?stackoverflow.com/questions/48413784/......
0赞 Finley 1/24/2018
@ZanLynx 我的编译器在使用时会报错,我的IDE是Visual Studioss.getline(s1, 250, '\n')
0赞 Finley 1/24/2018
@ZanLynx编译器说没有找到重载函数的实例,
0赞 Zan Lynx 1/24/2018
你需要使用这个:en.cppreference.com/w/cpp/string/basic_string/getline

答:

1赞 Benjamin Lindley 1/24/2018 #1

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

2赞 ShadowRanger 1/24/2018 #2

C++ 字符串和用于处理它们的 I/O 工具并不真正关心字节。他们知道自己的长度,如果他们的数据是 N 个字节长,那么其中一些字节是否长并不重要,s 将继续运行,直到它们达到记录的长度(在读取时设置)。NULNULiostreamss >> s1;

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

ss.getline(&s1[0], 250, '\n');

因为绕过 的安全访问器来获取原始数据(更糟糕的是,您告诉它可以拉取多达 250 个字符,而底层缓冲区可能要小得多),并且保持长度/容量信息不变(因此它仍然认为它包含读取的字符数)。&s1[0]std::stringchar*getliness >> s1;

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

std::getline(ss, s1, '\n');