【问题标题】:Converting char in string to unsigned long long in C++在 C++ 中将字符串中的 char 转换为 unsigned long long
【发布时间】:2017-12-11 12:26:34
【问题描述】:

好的,所以我正在构建一个 Base64 编码器/解码器,可以将十六进制转换为 base64 并返回,但我发现了一个我正在尝试理解的奇怪问题,代码如下:

string b64_encode(string str)
{
    string newStr = "";
    string ref = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

    unsigned long long h = 0;

    for(int i=0; i<str.size(); i+=3)
    {
        //Get every 3 chars
        char a = str[i];
        char b = str[i+1];
        char c = str[i+2];

        //Now, convert each hex character (base 16) to it's equivalent decimal number
        //and merge them into one variable
        h = strtoull(&a, nullptr, 16) << 8; //shift left by 8 bits
        h |= strtoull(&b, nullptr, 16) << 4; //shift left by 4 bits
        h |= strtoull(&c, nullptr, 16); //no shift required only the first 2 characters need

        cout << h << endl; //for testing purposes only
    }

    return newStr;
}

当我在 Mac OSX 上运行此代码时,我得到以下结果,这是不正确的:

4052
3959
1570
4091
3814
...

但是,我在 Windows 8 的 Visual Studio 2013 上编写了相同的代码,它给了我正确的值:

1170
1901
518
2921
1734
...

我使用的十六进制字符串:

string str = "49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d";

所以我的问题是,有没有办法在 Mac OSX 上也显示正确的数字?我在网上查了一下,但没有太大帮助。

【问题讨论】:

  • &amp;a 不是以 0 结尾的字符串,因此您会调用未定义的行为。
  • @mch 如果是这样的话,它在 Windows 上是如何工作的?
  • 似乎与mac字节序有关
  • 您可以修复未定义的行为,因此它不再靠运气起作用:ideone.com/LxmwW3 或您的示例输入:ideone.com/2GMMJX
  • @MegaColorBoy 就我个人而言,我不会使用 strtoull 将单个十六进制数字转换为数字。我会使用(ch &gt; '9' ? ( 10 + (ch - 'a')) : (ch - '0')) 之类的东西,假设我知道输入已被检查。

标签: c++ hex


【解决方案1】:

所以根据@mch,问题是字符不是以 0 结尾的,这会引发未定义的行为,多亏了他,这个问题得到了解决:

string b64_encode(string str)
{
    string newStr = "";
    string ref = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

    unsigned long long h = 0;

    for(int i=0; i<str.size(); i+=3)
    {
        //Get every 3 chars
        char a[2] = {str[i], 0};
        char b[2] = {str[i+1], 0};
        char c[2] = {str[i+2], 0};

        //Now, convert each hex character (base 16) to it's equivalent decimal number
        //and merge them into one variable
        h = strtoull(a, nullptr, 16) << 8; //shift left by 8 bits
        h |= strtoull(b, nullptr, 16) << 4; //shift left by 4 bits
        h |= strtoull(c, nullptr, 16); //no shift required only the first 2 characters need

        cout << h << endl;
    }

    return newStr;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-22
    • 2016-04-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多