【问题标题】:num_get facet and stringstream conversion to boolean - fails with initialised boolean?num_get facet 和 stringstream 转换为布尔值 - 初始化布尔值失败?
【发布时间】:2010-10-07 20:18:14
【问题描述】:

我继承了一个将字符串转换为数值的模板,并希望将其应用于转换为 boolean。我对 stringstream 和 locale 类不是很有经验。我似乎确实有一些奇怪的行为,我想知道是否有人可以向我解释一下?

template<typename T> T convertFromString( const string& str ) const {

std::stringstream SStream( str );  
T num = 0; 
SStream >> num;

return num;  
}  

在我尝试布尔转换之前,这工作正常

string str1("1");
int val1 = convertFromString<int>(str1); // ok
string str2("true");
bool val2 = convertFromString<bool>(str2); // val2 is _false_

我花了一些时间来找出问题所在。我已确认语言环境的 truename() 返回“true”。

问题似乎与变量num 的初始化有关。我可以将模板更改为此,它可以工作:

template<typename T> T convertFromString( const string& str ) const {

std::stringstream SStream( str );  
T num;  // <----------------------- Changed here
SStream >> num;

return num;  
}  
string str2("true");
bool val2 = convertFromString<bool>(str2); // val2 is _true_

为什么有效?我接受用 '0' 初始化 bool 是错误的,但为什么这会导致 SStream&gt;&gt;numconversion 失败?

【问题讨论】:

    标签: c++ templates initialization std stringstream


    【解决方案1】:

    使用 0 初始化 bool 将可靠地将其设置为 false,这对流提取没有影响。

    导致您的问题的原因是默认情况下,流在处理布尔值时仅识别值 01。要让他们识别名称 truefalse,您需要使用 boolalpha 操纵器将其明确告知流。

    解决问题的最佳方法是专门为 bool 模板:

    template<> bool convertFromString<bool>( const string& str ) const {
      std::stringstream SStream( str );  
      bool val = false;
      SStream >> val;
      if( SStream.fail() )
      {
        SStream.clear(); 
        SStream >> boolalpha >> val; 
      }    
      return val;  
    }  
    

    请注意,您的更改没有使代码正常工作。对于您使用的单个测试用例,它似乎就是这样做的。 随着您的更改,该函数无法从流中读取并返回未初始化的值。由于任何非零值都将被解释为 true,因此该函数似乎可以工作,但是一旦您尝试提取 "false",您将看到它失败(该函数仍然返回 true)。

    编辑:调整代码以处理数字和字母布尔值。

    【讨论】:

    • 这是有道理的。自从发布以来,我已经从主存档中提取了代码以自行测试,它似乎可以工作。但是,正如您所说,不一致是统一的布尔值(在一种情况下主要是true,在另一种情况下主要是false)。
    • 感谢您提供解决方案(boolalpha)。
    • 要同时识别真/假和 1/0 字符串,尝试一个似乎很有用,如果失败则尝试另一个: if( `(SStream>>num).fail()) { SStream.clear(); SStream>>boolalpha>>num; }
    • 好收获。我已经调整了我的答案以包括这一点。
    【解决方案2】:

    这是因为从 'true' 的字符串流转换失败 - 您的函数模板应该在返回之前检查 SStream.fail(),这样您可以更轻松地发现类似的失败。

    当你初始化 bool 时,它的值为 false。当你不初始化它时(在你去掉= 0之后),它是随机垃圾(通常非零)并返回true。

    template<typename T> T convertFromString( const string& str ) {
    
    std::stringstream SStream( str );  
    T num = 0; 
    SStream >> num;
    
    if (SStream.fail())
    {
        // conversion failure - handle error
        bool error = true;
    }
    
    return num;  
    } 
    

    【讨论】:

      猜你喜欢
      • 2018-01-24
      • 1970-01-01
      • 1970-01-01
      • 2021-06-27
      • 1970-01-01
      • 1970-01-01
      • 2011-12-26
      • 1970-01-01
      • 2017-03-07
      相关资源
      最近更新 更多