【问题标题】:istringstream decimal integer input to 8-bit typeistringstream 十进制整数输入到 8 位类型
【发布时间】:2014-08-10 16:05:50
【问题描述】:

这个:

#include <iostream>
#include <sstream>
#include <inttypes.h>

using namespace std;

int main (void) {
    istringstream iss("123 42");
    int8_t x;
    while (iss >> x) {
        cout << x << endl;
    }
    return 0;
}  

生产:

1
2
3
4
2

但我想要:

123
42

强制转换 iss &gt;&gt; (int)x(我最初用 char 尝试过)给了我“错误:二进制表达式的无效操作数('istringstream'(又名'basic_istringstream')和'int') " (clang) 或 "error: 'operator>>' 的重载不明确" (g++)。

有没有办法将值作为数字直接读入 8 位 类型,还是必须使用中间存储?

【问题讨论】:

  • 请注意,这个输出1 2 3 4 2 2 仍然是错误的,因为2 被打印了两次最后。这是因为错误的循环。你应该使用像while(stream &gt;&gt; item){ ... }这样的循环。
  • @Nawaz 点采取,更正。

标签: c++ stringstream


【解决方案1】:

没有内置的 8 位类型;您正在使用 signed char 的别名,当您对任何类型的 char 进行格式化输入时,IOStreams 将始终提取单个 ASCII 字母。

所以,是的,使用中间存储,或者将 int8_t 包装在一个新类中,该类为格式化 I/O 提供自己的重载(除非您有严格的内存和/或性能要求,否则我认为这有点过头了)。

(您对iss &gt;&gt; (int)x 的尝试非常混乱;转换用于您将要为其取值的表达式,而不是用于命名您要为其设置值的对象的左值。)

【讨论】:

    【解决方案2】:

    您必须使用中间类型或自己进行解析。所有 char 类型(char、signed char 和 unsigned char)都被视为文本元素,而不是整数。 int8_t 可能只是其中一个的 typedef,这就是您的代码失败的原因。

    注意:

    • 输出也会遇到同样的问题。
    • 不要使用 C 风格的强制转换,它们几乎只会导致错误。
    • 在输入操作之前检查 EOF 是没有用的,您需要在之后检查失败。

    【讨论】:

    • The output will suffer from the same issues. 是的,但有一个非常简洁的解决方法:cout &lt;&lt; +x &lt;&lt; endlx 提升为int。这几乎是一元加号唯一的好处。
    • 有趣。考虑到这一点,我更喜欢使用 static_cast,因为它更清楚地表明这里正在进行转换。
    【解决方案3】:

    根本问题是int8_t 通常(显然包括您的情况)类似于:typedef char int8_t;。无论好坏,iostream 为 char 提供重载,假设内容是字符而不是数字。

    可以通过定义自己的类来避免这种情况,例如:

    class my_int8_t {
        // ...
    };
    

    在这种情况下,您可以为该类型提供自己的 operator&gt;&gt;operator&lt;&lt; 重载(将内容视为数字而不是字符)。

    一旦你有了它,将数据从输入复制到输出(每行一个数字)可能会更好地执行以下操作:

    std::copy(std::istream_iterator<my_int8_t>(std::cin), 
              std::istream_iterator<my_int8_t>(),
              std::ostream_iterator<my_int8_t>(std::cout, "\n"));
    

    其中,这避免了当前代码中正确检测文件结尾的问题。

    【讨论】:

      【解决方案4】:
      #include <iostream>
      #include <string>
      #include <sstream>
      using namespace std;
      
      typedef unsigned char uint8_t;
      class exstringstream : public stringstream
      {
      public:
          exstringstream(const string& s)
              :stringstream(s)
          {
      
          }
          friend exstringstream& operator >> (exstringstream&, uint8_t& t); 
      };
      
      exstringstream& operator >> (exstringstream& ss, uint8_t& t)
      {
          unsigned int val;
          stringstream& s = ss;
          s >> val;
      
          t = static_cast<uint8_t>(val);
      
          return ss;
      }
      
      int main()
      {
          string str("123 45");
          exstringstream ss(str);
      
          uint8_t a, b;
          ss >> a >> b;
          cout << a << " " << b << endl;
          return 0;
      }
      

      【讨论】:

        【解决方案5】:

        运算符无法区分字符类型和 8 位有符号/无符号整数类型,因为它们与从语言中看到的相同(如其他答案中所述),这意味着您也无法实现支持两者的类/运算符.

        如果两者都需要,则必须使用scanf/printf 格式为"hhu",或PRIu8 来自&lt;cinttypes&gt;

        https://www.cplusplus.com/reference/cinttypes/

        https://www.cplusplus.com/reference/cstdio/printf/

        【讨论】:

          猜你喜欢
          • 2014-10-19
          • 2017-01-27
          • 2018-11-30
          • 1970-01-01
          • 2016-09-21
          • 2021-08-13
          • 2019-08-13
          • 2019-06-30
          • 1970-01-01
          相关资源
          最近更新 更多