繁体   English   中英

istream :: getline()的令人困惑的行为

[英]Puzzling behavior of istream::getline()

我测试了以下代码以阐明对istream::getline()理解:

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

然后控制台打印:

abcd
 efg
ijklmnopqrst

但在我看来

abcd
efgh
ijklmnopqrst

此外,我发现调用ss.getline()之后的s1大小与调用ss>>之后的大小相同,但是再次调用ss>>之后大小会改变。 谁能帮我解析?

两件事情。

首先, >>不会占用空格,因此getline将检索它。

其次,这一行是不正确的:

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

由于getline需要一个std::basic_string ,只需传入字符串即可:

ss.getline(s1, 250, '\n');

在您的代码中, &s1[0]可以访问写入的底层缓冲区,但是字符串的长度是分开存储的,并且仍然是前一次读取的长度(这就是为什么h被丢弃的原因)。 但是,由于缓冲区溢出,此时您已经调用了未定义的行为。

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

getline()调用的第一个参数是char * 对于这个char缓冲区实际上来自std::string及其实际上是其内部缓冲区的事实, ss完全一无所知。

使整个事务复杂化的事实是,此std::string包含四个字符,给人以印象。 因为这就是它的全部。

绝对没有任何东西可能导致此std::string改变主意。 仅仅因为指向其内部字符缓冲区的指针被传递到getline() ,该指针开始对其进行粗鲁的乱写(导致未定义的行为,我将在稍后推断),因此std::string仍然相信它仅包含四个字符。

与此同时,最初的格式化输入操作, >>提取的首字母,但并未提取下面的空间,所以,当这流,随后,有这个getline()调用,它开始时提取的字符其工作开始这个空格字符,直到下一个换行符-五个字符(如果我靠手指指望),但是将其转储到std::string保证可以容纳四个字符的缓冲区中(因为保持请注意,最初格式化的提取运算符>>仅在其中转储了四个字符)。

我忽略了一些细节,例如std::string会自动在结尾的'\\0' ,但最重要的是这是未定义的行为。 getline调用提取更多的字符,以确保该缓冲区可以保留给定的字符。 未定义的行为。 一大堆未定义的行为。 这不仅仅是输出的第二行中的四个字符,也不是您期望看到的四个字符,只是getline()实际上最终提取了更多的字符,但是这里打印的std::string拥有一切权利根据宪法,它仍然只有四个字符,只是内部缓冲区被重踩。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM