【问题标题】:How to detect negative numbers as parsing errors when reading unsigned integers?读取无符号整数时如何将负数检测为解析错误?
【发布时间】:2011-12-02 09:25:14
【问题描述】:

我想从 C++ iostream 中读取以 10 为底(十进制)表示的无符号整数,并至少进行基本的错误检测。在我看来,在这种情况下,减号显然是一个错误,因为无符号整数没有符号。但是,gcc 的看法不同:

#include <iostream>
#include <sstream>

int main() {
    std::stringstream a("5"), b("-0"), c("-4");
    unsigned int i;
    a >> i; if ( a ) std::cout << i << std::endl; else std::cout << "Conversion failure" << std::endl;
    b >> i; if ( b ) std::cout << i << std::endl; else std::cout << "Conversion failure" << std::endl;
    c >> i; if ( c ) std::cout << i << std::endl; else std::cout << "Conversion failure" << std::endl;
    return 0;
}

给我一​​个输出

4294967292

对于最后一行,就好像一个有符号整数 -4 已被读取并转换为无符号整数。

Apparently, the GCC people see this as a feature。是否有一些标准要求这种行为,是否有任何方法可以编写自己的解析器来摆脱它,即将“-4”(可能是“-0”)检测为转换错误?

【问题讨论】:

  • 您是否发布了正确的错误报告?那个被标记为“固定”,没有任何阻力。
  • @spraff:好像是这样,这个提到了负数行为。

标签: c++ iostream


【解决方案1】:

咨询 C++03, 22.2.2.1.2/11,格式继承自scanf 和朋友们,他们反过来都说转换后的字符序列是“可选签名的”,即使对于那些无符号的输出。 strtoul 也一样。

所以,我想你可以说强制行为的标准是 C89 用于 C++03,C99 用于 C++11。

由于 - 恰好只允许作为第一个字符,我想解决方法是在使用 operator&gt;&gt; 之前使用 peek 检查它。

【讨论】:

    【解决方案2】:

    如果我正确阅读了 22.2.2.1.2/table 5,它表明提取到无符号数相当于 scanf%u,这似乎 进行了负 -> 正转换.

    【讨论】:

      【解决方案3】:

      如果你这样做了,真的会有所不同吗?

      int i;
      unsigned int u;
      c >> i;
      u = i;
      std :: cout << u;
      

      operator&gt;&gt; 容忍符号不匹配并不重要,因为底层 C 规则在任何情况下都允许静默转换。您并没有通过“加强”输入操作符从根本上增加任何安全性。

      也就是说,my gcc(Solaris 上为 4.3.5)表示这是一个转换错误。

      【讨论】:

      • 使用 -Wconversion -Wsign-conversion -Werror 编译时会非常不同。我可以关闭静默转换,但不能关闭 iostream 符号处理。
      • 它可能决定以与处理文字相同的方式处理它,但我不知道标准对此有何规定。
      • 转换错误是件好事,而且似乎是因为您使用的是旧的 gcc 版本(根据 bug 是 4.4.1 之前的版本),这让我仍然想知道为什么 gcc 人试图解决任何问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-07
      • 2018-12-21
      • 2018-02-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多