十六进制转换在CPP中非常错误

时间:2016-09-30 21:43:59

标签: c++ cmd hex

我正在尝试在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;
再试一次失败的尝试。现在正如一位用户所说,key [i]即使使用std :: hex

也会打印垃圾
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;

3 个答案:

答案 0 :(得分:2)

问题1:

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

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

附录:不要忽略strtol的第二个参数。采摘非常方便 关闭无效输入。用户可以输入“fubar”,你会错过它。

问题2:

部分由罗宾约翰逊回答。 hex_pref不足以保存“0x”和输入用户参数。幸运的是,没有必要。 strtol的第三个参数指定输入为十六进制。

解决方案:移除strcathex_pref

问题3:

您正在输出无符号字符。这些将被<<解释为您输入的任何数字的ASCII值。这将为您提供令人讨厌的垃圾字符输出,哔哔声以及其他任何恰好由该数字表示的内容,而不是漂亮,干净的十六进制值。

打印时,

解决方案:unsigned int key或将key[i]投射到unsigned int

半问题4:

您没有以十六进制输出结果。

解决方案:使用std::hex

答案 1 :(得分:1)

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:\Users\rjohnson\Desktop\Workspaces\TestHex\Debug>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);

答案 2 :(得分:-1)

可能有效的代码版本如下。 无论如何,我会考虑考虑更好的设计。 非常确定以下代码可能会出现很多可能的问题。

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;

}