十六进制转换在CPP中出现了严重的错误

Hex conversion going terribly wrong in CPP

本文关键字:错误 转换 CPP 十六进制      更新时间:2023-10-16

我正在尝试读取unsigned char数组中的命令行十六进制参数。我的代码:

    #include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <memory.h>
#include <cstring>
unsigned char key[16] ={0x00, 0x00, 0x00, 0x00,
                                0x00, 0x00, 0x00, 0x00,
                                0x00, 0x00, 0x00, 0x00,
                                0x00, 0x00, 0x00, 0x00};

int main(int argc, char** argv){
        char hex_pref[]="0x";
        for (int i = 0; i < 16; i++){
                key[i] = strtol(strcat(hex_pref, argv[i]), NULL, 16);
                std::cout << argv[i] << "t";
        }
        std::cout << std::endl;
        for (int i = 0; i < 16; i++)
                std::cout << key[i] << "t";
        std::cout << std::endl;
        return 0;
}

程序的输出是非常不可预测的。每次我改变参数都会得到奇怪的结果。

我像

那样运行它
./a.out ab 32 bf 00 0a 2e 4c 3d 25 db 66 22 84 fb 19 72

我试着调试,但没有答案。有什么建议吗?谢谢你。


执行了以下操作,但问题仍然存在,因为我无法验证密钥[I]是什么。

char hex_pref[4];
        strcpy(hex_pref, "0x");
        for (int i = 0; i < 16; i++){
                strcat(hex_pref, argv[i]);
                key[i] = strtol(hex_pref, NULL, 16);
                //std::cout << argv[i] << "t";
        }
        std::cout << std::endl;
        for (int i = 0; i < 16; i++)
                std::cout << std::hex << key[i] << "t";
        std::cout << std::endl;
        return 0;

又一次失败尝试。现在,正如一位用户所说,即使使用std::hex

, key[i]也会打印垃圾。
for (int i = 1; i < 17; i++){
                //strcat(hex_pref, argv[i]);
                key[i-1] = strtol(argv[i], NULL, 16);
                //std::cout << argv[i] << "t";
        }
        std::cout << std::endl;
        for (int i = 0; i < 16; i++)
                std::cout << std::hex << key[i] << "t";
        std::cout << std::endl;
        return 0;

问题一:

argv[0]不是第一个用户提供的参数。arg[0]保留给实现使用。通常它是用来执行程序的命令。在这种情况下"./a.out"。"。/。因为strtol没有被检查有效性,所以不会转换为导致不良行为的整数。

解决方案:从argv[1]开始,相应增加for循环。

附录:不要忽略strtol的第二个参数。采摘起来很方便关闭无效输入。用户可能会输入"fubar",而你会错过它。

问题2:

部分被Robin Johnson的回答覆盖。hex_pref不够长,不能容纳"0x"和输入user参数。幸运的是,这不是必须的。strtol的第三个参数指定输入是十六进制。

解决方案:删除strcathex_pref

问题3:

您正在输出无符号字符。这些将被<<解释为输入的任何数字的ASCII值。这将给你讨厌的垃圾字符输出,哔哔声和其他任何恰好由这个数字表示的东西,不是漂亮的,干净的十六进制值。

解决方案:打印时将unsigned int key或将key[i]转换为unsigned int

Semi-problem 4:

你没有输出十六进制的结果。

解决方案:使用std::hex

strcat()试图将结果放入未准备的hex_pref,因为它的大小为"2"。这是行不通的。

http://www.cplusplus.com/reference/cstring/strcat/

保持你原来的方法。以下代码是"正确的"。并产生良好的输出(见下面的代码)。

#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <memory.h>
#include <cstring>
unsigned char key[16] = { 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00 };

int main(int argc, char** argv)
    {
    char hex_pref[] = "0x";
    for (int i = 1; i < 17 && i < argc; ++i)
        {
        std::cout << argv[i] << "t";
        if ( strlen(argv[i]) < 3)
            {
            char result[5];
            result[0]= 0;
            strcat(result, hex_pref);
            strcat(result, argv[i]);
            key[i-1] = char(strtol(result, NULL, 16));
            }
        }
    std::cout << std::endl;
    for (int i = 0; i < 16; ++i)
        {
        std::cout << int(key[i]) << "t";
        }
    std::cout << std::endl;
    return 0;
    }

输出是:

C:UsersrjohnsonDesktopWorkspacesTestHexDebug>testhex  ab 32 bf 00 0a 2e 4c 3d 25 db 66 22 84 fb 19 72
ab      32      bf      00      0a      2e      4c      3d      25      db      66      22      84      fb      19      72
171     50      191     0       10      46      76      61      37      219     102     34      132     251     25      114

使用流和字符串的另一种方法是"真正的"方法。这里没有足够的空间提供完整的解释,但是有很多教程和成熟的例子。

string result;
result += "0x";
result += argv[i];
key[i]= strtol(result.c_str(), NULL, 16);

您的代码的可能版本如下:无论如何,我会考虑一个更好的设计。我很确定下面的代码也可能出现很多问题。

unsigned long long key[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

int main(int argc, char** argv) {

for (int i = 1; i < argc; i++) {
    sscanf(argv[i], "%x", &(key[i]));
    std::cout << argv[i] << "t";
}
std::cout << std::endl << std::endl;
for (int i = 0; i < argc; i++)
    std::cout << key[i] << "t";
std::cout << std::endl;
getchar();
return 0;

}