Htoi的10位输出不正确

Htoi incorrect output at 10 digits

本文关键字:不正确 输出 10位 Htoi      更新时间:2023-10-16

当我输入0x123456789我得到了不正确的输出,我不知道为什么。起初我认为这是一个最大可能的int值问题,但我把变量改为unsigned long,问题仍然存在。

#include <iostream>
using namespace std;
long htoi(char s[]);
int main()
{
    cout << "Enter Hex n";
    char hexstring[20];
    cin >> hexstring;
    cout << htoi(hexstring) << "n";
}
//Converts string to hex
long htoi(char s[])
{
    int charsize = 0;
    while (s[charsize] != '')
    {
        charsize++;
    }
    int base = 1;
    unsigned long total = 0;
    unsigned long multiplier = 1;
    for (int i = charsize; i >= 0; i--)
    {
        if (s[i] == '0' || s[i] == 'x' || s[i] == 'X' || s[i] == '')
        {
            continue;
        }
        if ( (s[i] >= '0') && (s[i] <= '9') )
        {
            total = total + ((s[i] - '0') * multiplier);
            multiplier = multiplier * 16UL;
            continue;
        }
        if ((s[i] >= 'A') && (s[i] <= 'F'))
        {
            total = total + ((s[i] - '7') * multiplier); //'7' equals 55 in decimal, while 'A' equals 65
            multiplier = multiplier * 16UL;
            continue;
        }
        if ((s[i] >= 'a') && (s[i] <= 'f'))
        {
            total = total + ((s[i] - 'W') * multiplier); //W equals 87 in decimal, while 'a' equals 97
            multiplier = multiplier * 16UL;
            continue;
        }
    }
    return total;
}

long在您的计算机上可能也是32位。尝试long long

存储该数字需要超过32位。您的长类型很可能小到32位。

请改用std::uint64_t。这始终是一个64位无符号类型。如果编译器不支持,请使用long-long。必须至少为64位。

这个想法遵循了数字的多项式性质。123与相同

1*102+2*101+3*100

换句话说,我必须将第一个数字乘以10两次。我不得不把2乘以10一次。我把最后一个数字乘以一。再次,从左到右读取:

  • 将0乘以10,再加1→0*10+1=1
  • 乘以10,再加上2→1*10+2=12
  • 乘以10,再加上3→12*10+3=123

我们会做同样的事情:

#include <cctype>
#include <ciso646>
#include <iostream>
using namespace std;
unsigned long long hextodec( const std::string& s )
{
  unsigned long long result = 0;
  for (char c : s)
  {
    result *= 16;
    if (isdigit( c )) result |= c - '0';
    else              result |= toupper( c ) - 'A' + 10;
  }
  return result;
}
int main( int argc, char** argv )
{
  cout << hextodec( argv[1] ) << "n";
}

您可能会注意到,函数不止三行。我这么做是为了清楚起见。C++习惯用法可以使循环成为一行:

for (char c : s)
  result = (result << 4) | (isdigit( c ) ? (c - '0') : (toupper( c ) - 'A' + 10));

如果您愿意,也可以进行验证。我介绍的并不是进行数字到值转换的唯一方法。还有其他同样好的方法(还有一些更好的方法)。

我希望这能有所帮助。

我发现发生了什么,当我输入"1234567890"时,它会跳过"0",所以我必须修改代码。另一个问题是long实际上是32位,所以我按照@Bathsheba的建议将其更改为uint64_t。这是最后的工作代码。

#include <iostream>
using namespace std;
uint64_t htoi(char s[]);
int main()
{
    char hexstring[20];
    cin >> hexstring;
    cout << htoi(hexstring) << "n";
}
//Converts string to hex
uint64_t htoi(char s[])
{
    int charsize = 0;
    while (s[charsize] != '')
    {
        charsize++;
    }
    int base = 1;
    uint64_t total = 0;
    uint64_t multiplier = 1;
    for (int i = charsize; i >= 0; i--)
    {
        if (s[i] == 'x' || s[i] == 'X' || s[i] == '')
        {
            continue;
        }
        if ( (s[i] >= '0') && (s[i] <= '9') )
        {
            total = total + ((uint64_t)(s[i] - '0') * multiplier);
            multiplier = multiplier * 16;
            continue;
        }
        if ((s[i] >= 'A') && (s[i] <= 'F'))
        {
            total = total + ((uint64_t)(s[i] - '7') * multiplier); //'7' equals 55 in decimal, while 'A' equals 65
            multiplier = multiplier * 16;
            continue;
        }
        if ((s[i] >= 'a') && (s[i] <= 'f'))
        {
            total = total + ((uint64_t)(s[i] - 'W') * multiplier); //W equals 87 in decimal, while 'a' equals 97
            multiplier = multiplier * 16;
            continue;
        }
    }
    return total;
}