C++中的二进制到十进制转换:在10个值之后不工作[关闭]

xsuvu9jc  于 11个月前  发布在  其他
关注(0)|答案(1)|浏览(82)

**已关闭。**此问题需要debugging details。目前不接受回答。

编辑问题以包括desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem。这将帮助其他人回答问题。
7天前关闭
Improve this question
我正在尝试用C++为hack汇编语言创建一个反汇编程序。现在我的问题在于将16位二进制转换回A指令。在我检查opCode之后,(第一位)为0,我必须将它后面的其他15位转换回前缀为“@"的十进制。转换工作一直到00000111111111并输出”@“1023 ',但00001111111111和更高版本仅输出'@2559 '。

#include <iostream>
#include <string>
#include <cmath>

using namespace std;

int BtoA (int n)
{
    int num = n;
    int decimal = 0;
    int base = 0;
    int tmp = num;

    while (tmp != 0)
    {
        int last_dig = tmp % 10;
        tmp /= 10;

        decimal += last_dig * pow(2, base);

        base++;
    }

    return decimal;
}

int main()
{
    cout << "Welcome to the Hack Disassembler!\n";
    int opCode;
    int aIns;

    cout << "\nIs the OP-Code 1 or 0? ";

    cin >> opCode;

    if (opCode == 0)
    {
        cout << "\nWhat are the other 15 bits? ";
        cin >> aIns;
        cout << "\nThat A Instruction is @" << BtoA(aIns) << "!\n";
    }
}

字符串

sulc1iza

sulc1iza1#

尝试将变量aIns更改为类型std::string。如果它是类型int,则当您超过std::numeric_limits<int>::max()时会溢出,对于32位整数,这是2'147'483'647。这是一个10位数。当您添加第11位时,您会得到11'111'111'111,溢出。

// main.cpp
#include <iostream>
#include <stdexcept>
#include <string>

int bitstring_to_int(std::string const& s)
{
    if (s.empty())
        throw std::invalid_argument(
            '"' + s + "\" is empty. "
            "Instructions must have at least 1 bit.");
    if (s.length() > 15)
        throw std::invalid_argument(
            '"' + s + "\" is too wide. "
            "Instructions can have at most 15 bits.");
    for (auto const& c : s)
        if (c != '0' && c != '1')
            throw std::invalid_argument(
                '"' + s + "\" contains invalid character(s). "
                "It should be composed entirely of '0`s and '1's.");
    int n{};
    int bit{ 1 };
    for (auto i{ s.length() }; i--; bit <<= 1u)
        if (s[i] == '1')
            n |= bit;
    return n;
}

int main()
{
    std::cout << "Welcome to the Hack Disassembler!\n";
    int opCode;
    std::string aIns;

    std::cout << "\nIs the OP-Code 1 or 0? ";

    std::cin >> opCode;

    if (opCode == 0)
    {
        std::cout << "\nWhat are the other 15 bits? ";
        std::cin >> aIns;
        std::cout << "\nThat A Instruction is @" << bitstring_to_int(aIns) << "!\n";
    }
}
// end file: main.cpp

个字符

关于std::cin的惊喜

您的原始程序揭示了一个关于流输入的棘手事实:
假设你正在从流中提取一个类型为IntType的整数。它可以是int,或者任何其他整数类型。当你从流中提取的值溢出类型IntType时,值std::numeric_limits<IntType>::max()将被静默替换。
它并不是完全静默的,因为流也被置于失败状态。
如果不检查流是否失败,则可能无法捕捉流提取返回了“意外”值的事实。
在CppReference中,查找Stage 3: conversion and storage,您将在其中阅读以下内容:
如果v的类型是有符号整数类型,并且转换函数产生的正值或负值太大而无法容纳它,则最正或最负的可表示值分别存储在v中。
下面是一个演示:

// main.cpp
#include <cstdint>
#include <iostream>
#include <limits>
#include <sstream>
int main()
{
    std::int32_t const max32{ std::numeric_limits<std::int32_t>::max() };
    std::int64_t big_value{ max32 };
    ++big_value;  // fits in `int64_t`, but overflows `int32_t`

    // Output `big_value` to a stringstream, so that we can see 
    // what happens when it is subsequently extracted.
    std::stringstream sst;
    sst << big_value << '\n';
    std::int32_t value;
    sst >> value;

    std::cout
        << std::boolalpha
        << "Experiment: read `big_value` into `value`."
        << "\n  sst.fail() : " << sst.fail()
        << "\n  max32      : " << max32
        << "\n  big_value  : " << big_value
        << "\n  value      : " << value
        << "\n\n";
}
// end file: main.cpp


当我们将big_value写入流,然后将其读入变量value时,它会从2147483648悄悄地更改为2147483647

Experiment: read `big_value` into `value`.
  sst.fail() : true
  max32      : 2147483647
  big_value  : 2147483648
  value      : 2147483647


这正是OP所发生的事情,当他试图输入超过10位数的值时。

相关问题