【问题标题】:Can I tell if a std::string represents a number using stringstream?我可以判断一个 std::string 是否使用 stringstream 表示一个数字吗?
【发布时间】:2011-02-07 00:38:19
【问题描述】:

显然,这应该用于显示字符串是否为数字,例如“12.5”== yes,“abc”== no。然而,我得到了一个不顾一切的输入。

std::stringstream ss("2");
double d; ss >> d;
if(ss.good()) {std::cout<<"number"<<std::endl;}
else {std::cout<<"other"<<std::endl;}

【问题讨论】:

  • “12.5 abc”是否符合“字符串是数字”的条件?如果“否”,则到目前为止没有任何答案适用。

标签: c++ numbers stringstream words


【解决方案1】:

不要使用 good()!测试流是否为failed or not

if (ss)

Good 告诉你是否设置了 eofbit、badbit 或 failbit,而 fail() 告诉你关于 badbit 和 failbit。除非您已经知道流失败了,否则您几乎从不关心 eofbit,因此您几乎从不想使用 good。

请注意,如上所述,直接测试流完全等同于:

if (!ss.fail())

相反,!ss 等价于 ss.fail()。


将提取合并到条件表达式中:

if (ss >> d) {/*...*/}

完全等价于:

ss >> d;
if (ss) {/*...*/}

但是,您可能想测试是否可以将完整的字符串转换为双精度字符串,这有点复杂。使用已经处理所有情况的 boost::lexical_cast。

【讨论】:

    【解决方案2】:

    如果您想检查 string 是否包含 一个数字而不包含其他任何内容(空格除外),请使用:

    #include <sstream>
    
    bool is_numeric (const std::string& str) {
        std::istringstream ss(str);
        double dbl;
        ss >> dbl;      // try to read the number
        ss >> std::ws;  // eat whitespace after number
    
        if (!ss.fail() && ss.eof()) {
            return true;  // is-a-number
        } else {
            return false; // not-a-number
        }
    }
    

    ss &gt;&gt; std::ws 对于接受带有尾随空格的数字(例如 "24 ")很重要。

    ss.eof() 检查对于拒绝像 "24 abc" 这样的字符串很重要。它确保我们在读取数字(和空格)后到达字符串的末尾。

    测试工具:

    #include <iostream>
    #include <iomanip>
    
    int main()
    {
        std::string tests[8] = {
                "", "XYZ", "a26", "3.3a", "42 a", "764", " 132.0", "930 "
        };
        std::string is_a[2] = { "not a number", "is a number" };
        for (size_t i = 0; i < sizeof(tests)/sizeof(std::string); ++i) {
            std::cout << std::setw(8) << "'" + tests[i] + "'" << ": ";
            std::cout << is_a [is_numeric (tests[i])] << std::endl;
        }
    }
    

    输出:

          '': not a number
       'XYZ': not a number
       'a26': not a number
      '3.3a': not a number
      '42 a': not a number
       '764': is a number
    ' 132.0': is a number
      '930 ': is a number
    

    【讨论】:

    • 我喜欢这个解决方案,但是在 OSX 上使用我的编译器时,如果没有要读取的空格,ss &lt;&lt; std::ws 会设置失败标志。我必须在刷新空白之前检查 eof。
    【解决方案3】:

    您应该使用istringstream 以便它知道它正在尝试解析输入。另外,直接查看提取结果即可,不用稍后再使用good

    #include <sstream>
    #include <iostream>
    
    int main()
    {
        std::istringstream ss("2");
        double d = 0.0;
        if(ss >> d) {std::cout<<"number"<<std::endl;}
        else {std::cout<<"other"<<std::endl;}
    }
    

    【讨论】:

    • “它知道它正在尝试解析输入”有什么关系呢?也许有利于代码清晰,但我认为没有技术原因。
    • 您没有检查额外的内容。例如,“2 abc”不是一个数字——它是一个嵌入了空格的字符串。 IIRC,解决方案是检查 {{ss.peek() == EOF}} (一切都被消耗)或者可能通过查看 {{ss.gcount()}}。
    【解决方案4】:
    int str2int (const string &str) {
      stringstream ss(str);
      int num;
      if((ss >> num).fail())
      { 
          //ERROR: not a number
      }
      return num;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-20
      • 2012-11-04
      • 2022-01-25
      • 2019-09-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-16
      • 2020-01-18
      相关资源
      最近更新 更多