我正在尝试在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;
答案 0 :(得分:2)
问题1:
argv[0]
不是第一个用户提供的参数。 arg[0]
保留供实现使用。通常,它是用于执行程序的命令。在这种情况下“./a.out”。 “./a.out”未转换为整数,导致行为不良,因为strtol
未检查其有效性。
解决方案:从argv[1]
开始并相应地增加for循环。
附录:不要忽略strtol
的第二个参数。采摘非常方便
关闭无效输入。用户可以输入“fubar”,你会错过它。
问题2:
部分由罗宾约翰逊回答。 hex_pref
不足以保存“0x”和输入用户参数。幸运的是,没有必要。 strtol
的第三个参数指定输入为十六进制。
解决方案:移除strcat
和hex_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;
}