Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/145.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么stringstream>&燃气轮机;在失败时更改目标的值?_C++_State_Stringstream_Cin - Fatal编程技术网

C++ 为什么stringstream>&燃气轮机;在失败时更改目标的值?

C++ 为什么stringstream>&燃气轮机;在失败时更改目标的值?,c++,state,stringstream,cin,C++,State,Stringstream,Cin,来自Stroustrup的TC++PL,第三版,第21.3.3节: 如果我们试图读入变量v,但操作失败,那么v的值应该保持不变(如果v是istream或ostream成员函数处理的类型之一,则v的值保持不变) 下面的例子似乎与上面的引文相矛盾。根据上面的引文,我希望v的值保持不变,但它被归零。这种明显矛盾的行为有什么解释 #include <iostream> #include <sstream> int main( ) { std::stringstream

来自Stroustrup的TC++PL,第三版,第21.3.3节:

如果我们试图读入变量v,但操作失败,那么v的值应该保持不变(如果v是istream或ostream成员函数处理的类型之一,则v的值保持不变)

下面的例子似乎与上面的引文相矛盾。根据上面的引文,我希望v的值保持不变,但它被归零。这种明显矛盾的行为有什么解释

#include <iostream>
#include <sstream>

int main( )
{
    std::stringstream  ss;

    ss  << "The quick brown fox.";

    int  v = 123;

    std::cout << "Before: " << v << "\n";

    if( ss >> v )
    {
        std::cout << "Strange -- was successful at reading a word into an int!\n";
    }

    std::cout << "After: " << v << "\n";

    if( ss.rdstate() & std::stringstream::eofbit  ) std::cout << "state: eofbit\n";
    if( ss.rdstate() & std::stringstream::failbit ) std::cout << "state: failbit\n";
    if( ss.rdstate() & std::stringstream::badbit  ) std::cout << "state: badbit\n";

    return 1;
}
谢谢。

发件人:

如果提取失败(例如,如果在需要数字的地方输入了字母),则值保持不变,并设置failbit(,直到C++11

若提取失败,则将零写入值并设置failbit。如果提取导致值太大或太小而无法装入值,则会写入std::numeric_limits::max()或std::numeric_limits::min(),并设置failbit标志。(自C++11以来)

您的编译器似乎是在C++11模式下编译的,这改变了行为



输入操作符使用其
get
函数调用的locale方面。对于C++11,指定使用等类型的函数。在C++11之前,它显然使用了样式解析(参考文献,我没有访问C++03规范)来提取数字。行为的变化是由于分析输入时的这种变化。

运算符>>是格式化的输入运算符。
因此,从流中读取输入的方式取决于区域设置:

[istream.格式化.算术] 与插入器一样,这些提取器依赖于区域设置的num_get(22.4.2.1)对象来解析输入流数据。这些提取器作为格式化输入函数(如27.7.2.2.1所述)。构造sentry对象后,转换就像由以下代码片段执行一样进行:

typedef num_getnumget;
iostate err=iostate::goodbit;
使用_facet(loc).get(*this,0,*this,err,val);
设置状态(err);
正如我们在上面看到的,该值实际上是由嵌入到流中的区域设置的
numget
方面设置的

num\u获取虚拟函数[facet.num.get.virtuals] 第三阶段: 要存储的数值可以是以下值之一:

  • 零,如果转换函数无法转换整个字段。ios_base::failbit已分配给err
  • 如果该字段表示的值太大,无法在val中表示,则为可表示的最大正值。ios_base::failbit被分配给err
  • 对于无符号整数类型,如果字段表示的值太大而无法在val中表示,则为最负的可表示值或零。ios_base::failbit被分配给err
阶段3的定义在n2723->n2798之间发生了巨大变化

num\u获取虚拟函数[facet.num.get.virtuals] 第3阶段:第2阶段处理的结果可以是:

  • 在第2阶段积累了一系列字符,这些字符被转换(根据scanf的规则)为val类型的值。该值存储在val中,ios_base::goodbit存储在err中
  • 阶段2中累积的字符序列会导致scanf报告输入故障。ios_base::failbit已分配给err

有趣的变化,我从来不知道。我总是将提取失败后读取变量视为未定义的行为……有人知道这一变化背后的基本原理吗?@Alex:这听起来更符合strtod等的做法(它总是返回一个确定的值),我想它会给你一些关于提取失败方式的信息。我想,超出范围和不可解析是不同的。@Alex:可能是为了使字符串转换函数的实现更容易()。但是,我们无法准确地找到这一措辞变化的提出地点。这个答案并不能说明全部情况:如果构建sentry对象失败,那么我们就不会得出“如果提取失败,零将写入值”的结论。如果流已经设置了错误条件,或者只包含空格,则可能发生这种情况。(哨兵跳过空格)。根据Joachim Pileborg的解释,在这种情况下原始值将被保留,最好在此类问题中提及编译器标志;我使用的标志是:
-Wall-Wextra-Werror-static-std=c++11
Before: 123
After: 0
state: failbit
   typedef num_get< charT,istreambuf_iterator<charT,traits> > numget;
   iostate err = iostate::goodbit;
   use_facet< numget >(loc).get(*this, 0, *this, err, val);
   setstate(err);