我可以做这个:
int main(int argc, char** argv) {
unsigned char cTest = 0xff;
return 0;
}
但是通过命令行将十六进制数输入程序的正确方法是什么?
unsigned char cTest = argv[1];
不成功。这会产生一个初始化,从指针生成整数而没有强制转换警告。
我可以做这个:
int main(int argc, char** argv) {
unsigned char cTest = 0xff;
return 0;
}
但是通过命令行将十六进制数输入程序的正确方法是什么?
unsigned char cTest = argv[1];
不成功。这会产生一个初始化,从指针生成整数而没有强制转换警告。
我想有些到达这里的人可能只是在寻找:
$ ./prog `python -c 'print "\x41\x42\x43"'`
$ ./prog `perl -e 'print "\x41\x42\x43"'`
$ ./prog `ruby -e 'print "\x41\x42\x43"'`
如类型main
所示,命令行中的参数是字符串,需要转换为不同的表示形式。
将单个十六进制命令行参数转换为十进制看起来像
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
printf("%ld\n", strtol(argv[1], NULL, 16));
return 0;
}
示例用法:
$ ./hex ff
255
使用strtol
最后一个参数并将其从 16 更改为 0,如
printf("%ld\n", strtol(argv[1], NULL, 0));
使程序接受十进制、十六进制(由前导表示)0x
和八进制(由前导表示0
)值:
$ ./num 0x70
112
$ ./num 070
56
$ ./num 70
70
使用 bash 命令 shell,利用ANSI-C 引用让 shell 执行转换,然后您的程序只需从命令行打印值。
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
int i;
for (i = 1; i < argc; i++) {
unsigned char value = argv[i][0];
if (strlen(argv[i]) > 1)
fprintf(stderr, "%s: '%s' is longer than one byte\n", argv[0], argv[i]);
printf(i + 1 < argc ? "%u " : "%u\n", value);
}
return 0;
}
Bash 支持多种格式的表单$'...'
,但$'\xHH'
似乎与您的问题最接近。例如:
$ ./print-byte $'\xFF' $'\x20' $'\x32'
255 32 50
也许您将命令行中的值打包成一个字符串并打印出来。
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
int i;
if (argc > 1) {
char *s = malloc(argc);
if (!s) {
fprintf(stderr, "%s: malloc: %s\n", argv[0], strerror(errno));
return 1;
}
for (i = 1; i < argc; i++)
s[i - 1] = strtol(argv[i], NULL, 16) & 0xff;
s[argc - 1] = '\0';
printf("%s\n", s);
free(s);
}
return 0;
}
在行动:
$ ./pack-string 48 65 6c 6c 6f 21
Hello!
以上所有内容都在重新发明 bash 和操作系统已经为您提供的轮子。
$ echo $'\x48\x65\x6c\x6c\x6f\x21'
Hello!
该echo
程序在标准输出上打印其命令行参数,您可以将其视为for
参数的循环和printf
每个循环。
如果您有另一个程序为您执行解码,请使用命令替换来替换被反引号包围的命令$()
或其输出。请参阅下面的示例,这些示例再次echo
用作占位符。
$ echo $(perl -e 'print "\x50\x65\x72\x6c"')
Perl
$ echo `python -c 'print "\x50\x79\x74\x68\x6f\x6e"'`
Python
您可以使用strtoul遍历字符串中的字符并转换它们,同时考虑到您传入的基数(在此上下文中为 16):-
char *terminatedAt;
if (argc != 2)
return 1;
unsigned long value = strtoul( argv[1], &terminatedAt, 16);
if (*terminatedAt != '\0')
return 2;
if (value > UCHAR_MAX)
return 3;
unsigned char byte = (unsigned char)value;
printf( "value entered was: %d", byte);
正如其他示例中所述,有一些更短的方法,但是它们都不允许您彻底检查处理过程(如果有人通过FFF
并且您只有一个输入会发生unsiged char
什么?
例如sscanf
:
int val;
sscanf(argv[1], &val)
printf("%d\n", val);
unsigned char cTest = argv[1];
是错误的,因为argv[1]
是 type char *
。如果argv[1]
包含类似的东西,"0xff"
并且您想将与之对应的整数值分配给 a unsigned char
,最简单的方法可能是strtoul()
先将其转换为 a unsigned long
,然后检查转换后的值是否小于或等于UCHAR_MAX
。如果是,您可以分配给cTest
.
strtoul()
的第三个参数是一个基数,可以为 0 表示 C 风格的数字解析(允许使用八进制和十六进制字面量)。如果您只想允许以 16 为基数,请将其作为第三个参数传递给strtoul()
. 如果您想允许任何基数(以便您可以解析0xff
、0377
、255
等),请使用 0。
UCHAR_MAX
中定义<limits.h>
。
在 C 中做这种事情的传统方法是使用scanf()。它与 printf() 完全相反,将给定的格式从文件(或终端)中读取并写入您列出的变量中,而不是将它们写入其中。
在您的情况下,您将使用sscanf
它,因为您已经将它放在字符串而不是流中。
atoi
, atol
, strtoi
,strtol
全部在stdlib.h