我在 C++ 中尝试了 noskipws 操纵器,并编写了以下代码。
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int main()
{
string first, middle, last;
istringstream("G B Shaw") >> first >> middle >> last;
cout << "Default behavior: First Name = " << first << ", Middle Name = " << middle << ", Last Name = " << last << '\n';
istringstream("G B Shaw") >> noskipws >> first >> middle >> last;
cout << "noskipws behavior: First Name = " << first << ", Middle Name = " << middle << ", Last Name = " << last << '\n';
}
Run Code Online (Sandbox Code Playgroud)
我期望以下输出:
预期产出
Default behavior: First Name = G, Middle Name = B, Last Name = Shaw
noskipws behavior: First Name = G, Middle Name = , Last Name = B
Run Code Online (Sandbox Code Playgroud)
输出
Default behavior: First Name = G, Middle Name = B, Last Name = Shaw
noskipws behavior: First Name = G, Middle Name = , Last Name = Shaw
Run Code Online (Sandbox Code Playgroud)
我修改了这段代码,使其适用于这样的字符,并且效果很好。
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int main()
{
char first, middle, last;
istringstream("G B S") >> first >> middle >> last;
cout << "Default behavior: First Name = " << first << ", Middle Name = " << middle << ", Last Name = " << last << '\n';
istringstream("G B S") >> noskipws >> first >> middle >> last;
cout << "noskipws behavior: First Name = " << first << ", Middle Name = " << middle << ", Last Name = " << last << '\n';
}
Run Code Online (Sandbox Code Playgroud)
我知道 cin 是如何工作的,但我无法弄清楚为什么它在string.
Run Code Online (Sandbox Code Playgroud)std::istringstream("G B S") >> std::noskipws >> first >> middle >> last;
对字符串执行提取时,首先清除字符串并将字符插入其缓冲区。
21.4.8.9 插入器和提取器
Run Code Online (Sandbox Code Playgroud)template<class charT, class traits, class Allocator> basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, basic_string<charT, traits, Allocator>& str);效果:表现为格式化输入函数 (27.7.2.2.1)。构造哨兵对象后,如果哨兵转换为
true,则调用str.erase()然后从中提取字符is并将其附加到str,就像通过调用str.append(1, c).[...]
第一次读取会将字符串提取"G"到first. 对于第二次提取,将不会提取任何内容,因为std::noskipws设置了格式标志,禁用了前导空格的清除。因此,字符串被清除,然后提取失败,因为没有放入任何字符。 以下是上述子句的延续:
21.4.8.9 插入器和提取器(续)
[...] 字符被提取并附加,直到发生以下任何一种情况:
n字符被存储;文件结束出现在输入序列上;
isspace(c, is.getloc())对于下一个可用的输入字符为真c。
当流确定提取失败时,std::ios_base::failbit将在流状态中设置指示错误。
从此时起,除非清除流状态,否则任何和所有 I/O 尝试都将失败。提取器变得不可操作,如果流状态未清除其所有错误,它将无法运行。这意味着提取到last不会做任何事情,它保留了它在前一次提取(没有std::noskipws)时的值,因为流没有清除字符串。
至于为什么使用char有效:字符在C或C++中没有格式要求。任何和所有字符都可以提取到 type 的对象中char,这就是为什么尽管std::noskipws设置了但仍能看到正确输出的原因:
27.7.2.2.3/1 [istream::提取器]
Run Code Online (Sandbox Code Playgroud)template<class charT, class traits> basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& in, charT& c);效果:表现得像 in 的格式化输入成员(如 27.7.2.2.1 中所述)。构造哨兵对象后,从 中提取一个字符(
in如果有),并将其存储在 中c。否则,函数调用in.setstate(failbit).
如果一个字符可用,提取器的语义会将一个字符存储到其操作数中。它不以空格(甚至 EOF 字符!)为界。它会像普通字符一样提取它。
| 归档时间: |
|
| 查看次数: |
4887 次 |
| 最近记录: |