![](/img/trans.png)
[英]C++ Unexpected behavior with istream, getline, binary file, regex and strings
[英]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.