C 通过命令行将十六进制数输入程序
我可以这样做:C 通过命令行将十六进制数输入程序,c,base-conversion,strtol,C,Base Conversion,Strtol,我可以这样做: int main(int argc, char** argv) { unsigned char cTest = 0xff; return 0; } 但是,通过命令行将十六进制数输入程序的正确方法是什么 unsigned char cTest=argv[1] 这没用。它从指针生成一个初始化整数,不带强制转换警告。您可以使用它遍历字符串中的字符并转换它们,同时考虑传入的基数(在本上下文中为16):- char *terminatedAt; if (argc != 2)
int main(int argc, char** argv) {
unsigned char cTest = 0xff;
return 0;
}
但是,通过命令行将十六进制数输入程序的正确方法是什么
unsigned char cTest=argv[1]代码>
这没用。它从指针生成一个初始化整数,不带强制转换警告。您可以使用它遍历字符串中的字符并转换它们,同时考虑传入的基数(在本上下文中为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
来放入,会发生什么情况
e、 g.使用sscanf
:
int val;
sscanf(argv[1], &val)
printf("%d\n", val);
正如main
的类型所示,来自命令行的参数是字符串,需要转换为不同的表示形式
将单个十六进制命令行参数转换为十进制
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
printf("%ld\n", strtol(argv[1], NULL, 16));
return 0;
}
使用strtol
并将最终参数从16更改为0,如中所示
printf("%ld\n", strtol(argv[1], NULL, 0));
使程序接受十进制、十六进制(由前导0x
表示)和八进制(由前导0
表示)值:
使用bash命令shell,利用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;
}
也许可以将命令行中的值打包成字符串并打印出来
#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;
}
所有这些都是对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
atoi
,atol
,strtoi
,strtol
全功能stdlib.h
unsigned char cTest = argv[1];
是错误的,因为argv[1]
属于char*
类型。如果argv[1]
包含类似“0xff”
的内容,并且您希望将与之对应的整数值分配给无符号char
,最简单的方法可能是使用strtoul()
首先将其转换为无符号长型
,然后检查转换后的值是否小于或等于UCHAR_MAX
。如果是,您可以只分配给cTest
strtoul()
的第三个参数是一个base,可以是0来表示C风格的数字解析(允许使用八进制和十六进制文字)。如果只允许base 16,则将其作为第三个参数传递给strtoul()
。如果要允许任何base(因此您可以解析0xff
,0377
,255
,等等),使用0
UCHAR\u MAX
是在
中定义的。在C中进行此类操作的传统方法是使用。它与printf()完全相反,从文件(或终端)中读取给定格式并将其写入所列变量,而不是将它们写入其中
在您的情况下,您应该使用sscanf
,因为您已经将其放入字符串而不是流中。我认为一些来到这里的人可能只是在寻找:
$ ./prog `python -c 'print "\x41\x42\x43"'`
$ ./prog `perl -e 'print "\x41\x42\x43"'`
$ ./prog `ruby -e 'print "\x41\x42\x43"'`
命令行参数始终是字符串。某些平台可能将其设置为Unicode,在这种情况下,简单的strtol
将不起作用。@直接:在这种情况下,mbstol
或任何多字节或宽字符(或TCHAR)变体将涵盖这一点?(我也怀疑这是一个关键问题,因为question@dirkgently:在这种情况下,是main()的第二个参数
不是类型char**
?这不符合标准。@Alok:它们可能仍然是多字节的,在这种情况下,mbstoul最好,但在问题的上下文中,这太花哨了。我认为+1很好的解释,考虑到我在代码中试图展示的大多数观点背后的推理都在3分钟前指出(另请参见链接的手册页)但这并不能帮助提问者理解为什么有必要这样做或给出一个示例。当帖子没有添加时,最好将其删除以保持干燥UCHAR\u MAX
可能大于LONG\u MAX
,因此您应该使用strtoul()和 Value> 255 > <代码>应该是“代码>值> UCHAROXMAX 。最后, StistalyCase是C++,这里不需要强制转换因为隐式转换规则。Ta,我在初版中有一个<代码> CUT//CUT>:P我考虑使用U,但是考虑到这个问题会使问题变得过于复杂。oner主要是想理解一个对他们来说不太明显的概念。我同意有时一个人必须让事情对初学者来说不完全是学究式的正确,但在这种情况下,我认为学究式的学习对初学者来说也不难。这将阻止许多人假设UCHAR\u MAX==255
或LONG\u MAX>UCHAR_MAX
,等等。谢谢你的编辑和一个好的答案!@Alok:总是很高兴学究,谢谢!我认为演员阵容很好,因为它解释了读者发生了什么,并且避免了关于缩短转换的警告。我将忽略mbs问题(以及wchar_t问题,因为问题排除了它们).一遍又一遍!我是。非常感谢!非常感谢-非常非常有帮助
$ echo $'\x48\x65\x6c\x6c\x6f\x21'
Hello!
$ echo $(perl -e 'print "\x50\x65\x72\x6c"')
Perl
$ echo `python -c 'print "\x50\x79\x74\x68\x6f\x6e"'`
Python
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"'`