【问题标题】:Why the part after '\0' of a string can be printed after calling istream::getline为什么调用 istream::getline 后可以打印字符串 '\0' 之后的部分
【发布时间】:2018-07-03 00:39:03
【问题描述】:

为了巩固我对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] 分别指代 cpluscpluss1[1] 之后的字符保持不变,因为一旦到达终止符,提取就会停止。但是让我意想不到的一点是s1可以打印出来。控制台打印

s1:abcdefgh
new s1:  cdefgh

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

【问题讨论】:

标签: c++ string iostream getline


【解决方案1】:

C++ 字符串和使用它们的 I/O 工具并不真正关心 NUL 字节。他们知道自己的长度,如果他们的数据是 N 字节长,那么其中一些字节是否为 NULiostreams 将继续运行直到它们达到记录的长度(当您使用 @ 阅读时设置) 987654325@)。

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

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

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

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

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-12-17
      • 1970-01-01
      • 2014-02-06
      • 2016-05-31
      • 2016-01-31
      • 2017-10-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多