C语言 通过命令行将十六进制数输入到程序中

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2162831/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 04:19:51  来源:igfitidea点击:

Getting a hexadecimal number into a program via the command line

cbase-conversionstrtol

提问by Pieter

I can do this:

我可以做这个:

int main(int argc, char** argv) {
  unsigned char cTest = 0xff;
  return 0;
}

But what's the right way to get a hexadecimal number into the program via the command line?

但是通过命令行将十六进制数输入程序的正确方法是什么?

unsigned char cTest = argv[1];

unsigned char cTest = argv[1];

doesn't do the trick. That produces a initialization makes integer from pointer without a castwarning.

没有用。这会产生一个初始化,使指针变成整数,而没有强制转换警告。

采纳答案by Greg Bacon

As the type of mainindicates, arguments from the command line are strings and will require conversion to different representations.

正如类型所main指示的,命令行中的参数是字符串,需要转换为不同的表示形式。

Converting a single hexadecimal command-line argument to decimal looks like

将单个十六进制命令行参数转换为十进制看起来像

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
  printf("%ld\n", strtol(argv[1], NULL, 16));

  return 0;
}

Example usage:

用法示例:

$ ./hex ff
255

Using strtoland changing the final argument from 16 to 0 as in

使用strtol并将最终参数从 16 更改为 0,如

printf("%ld\n", strtol(argv[1], NULL, 0));

makes the program accept decimal, hexadecimal (indicated by leading 0x, and octal (indicated by leading 0) values:

使程序接受十进制、十六进制(由前导0x指示0)和八进制(由前导指示)值:

$ ./num 0x70
112
$ ./num 070
56
$ ./num 70
70

Using the bash command shell, take advantage of ANSI-C Quotingto have the shell perform the conversion, and then your program just prints the values from the command line.

使用 bash 命令外壳,利用ANSI-C 引用让外壳执行转换,然后您的程序只需打印命令行中的值。

#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 supports many formats of the form $'...', but $'\xHH'appears to be the closest match to your question. For example:

Bash 支持 form 的多种格式$'...',但$'\xHH'似乎与您的问题最接近。例如:

$ ./print-byte $'\xFF' $'\x20' $'\x32'
255 32 50

Maybe you pack the values from the command line into a string and print it.

也许您将命令行中的值打包成一个字符串并打印出来。

#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] = '
$ ./pack-string 48 65 6c 6c 6f 21
Hello!
'; printf("%s\n", s); free(s); } return 0; }

In action:

在行动:

$ echo $'\x48\x65\x6c\x6c\x6f\x21'
Hello!

All of the above is reinventing wheels that bash and the operating system already provide for you.

以上所有内容都是重新发明 bash 和操作系统已经为您提供的轮子。

$ echo $(perl -e 'print "\x50\x65\x72\x6c"')
Perl
$ echo `python -c 'print "\x50\x79\x74\x68\x6f\x6e"'`
Python

The echoprogram prints its command-line arguments on the standard output, which you can think of as a forloop over the arguments and a printffor each.

echo程序在标准输出上打印其命令行参数,您可以将其视为for对参数的循环和printf每个参数的循环。

If you have another program that performs the decoding for you, use Command Substitutionthat replaces a command surrounded by backticks or $()with its output. See examples below, which again use echoas a placeholder.

如果您有另一个程序为您执行解码,请使用命令替换来替换由反引号括起来的命令$()或其输出。请参阅下面的示例,它们再次echo用作占位符。

$ ./prog `python -c 'print "\x41\x42\x43"'`
$ ./prog `perl -e 'print "\x41\x42\x43"'`
$ ./prog `ruby -e 'print "\x41\x42\x43"'`

回答by Peter Le Bek

I think some people arriving here might just be looking for:

我认为有些人到达这里可能只是在寻找:

char *terminatedAt;
if (argc != 2)
    return 1;

unsigned long value = strtoul( argv[1], &terminatedAt, 16);

if (*terminatedAt != '
int val;
sscanf(argv[1], &val)
printf("%d\n", val); 
') return 2; if (value > UCHAR_MAX) return 3; unsigned char byte = (unsigned char)value; printf( "value entered was: %d", byte);

回答by Ruben Bartelink

You could use strtoulwhich would walk through the characters in the string and convert them, taking into account the radix (16 in this context) that you pass in:-

您可以使用strtoul来遍历字符串中的字符并转换它们,同时考虑到您传入的基数(在此上下文中为 16):-

unsigned char cTest = argv[1];

As covered in the other examples, there are shorter ways, but none of them allow you to cleanly error check the processing (what happens if someone passes FFFand you've only got an unsiged charto put it into?

正如其他示例中所述,有更短的方法,但它们都不允许您彻底检查处理过程中的错误(如果有人通过FFF并且您只有一个unsiged char将其放入会发生什么?

e.g. with sscanf:

例如sscanf

##代码##

回答by Alok Singhal

##代码##

is wrong, because argv[1]is of type char *. If argv[1]contains something like "0xff"and you want to assign the integer value corresponding to that to an unsigned char, the easiest way would be probably to use strtoul()to first convert it to an unsigned long, and then check to see if the converted value is less than or equal to UCHAR_MAX. If yes, you can just assign to cTest.

是错误的,因为argv[1]是 类型char *。如果argv[1]包含类似的内容"0xff"并且您想将与该值对应的整数值分配给 an unsigned char,最简单的方法可能是strtoul()先将其转换为 an unsigned long,然后检查转换后的值是否小于或等于UCHAR_MAX。如果是,您可以只分配给cTest.

strtoul()'s third parameter is a base, which can be 0 to denote C-style number parsing (octal and hexadecimal literals are allowed). If you only want to allow base 16, pass that as the third argument to strtoul(). If you want to allow any base (so you can parse 0xff, 0377, 255, etc.), use 0.

strtoul()的第三个参数是一个基数,可以为 0 表示 C 风格的数字解析(允许八进制和十六进制文字)。如果您只想允许基数为 16,请将其作为第三个参数传递给strtoul(). 如果你想允许任何基地(这样你就可以解析0xff0377255等),使用0。

UCHAR_MAXis defined in <limits.h>.

UCHAR_MAX中定义<limits.h>

回答by T.E.D.

The traditional way to do this kind of thing in C is with scanf(). It's exactly the inverse of printf(), reading the given format outof the file (or terminal) and into the variables you list, rather than writing them into it.

在 C 中做这种事情的传统方法是使用scanf()。它与 printf() 完全相反,文件(或终端)中读取给定格式读取到您列出的变量中,而不是将它们写入其中。

In your case, you'd use sscanfas you've already got it in a string rather than a stream.

在您的情况下,您将使用sscanf它,因为您已经将它放在字符串中而不是流中。

回答by Pod

atoi, atol, strtoi, strtol

atoi, atol, strtoi,strtol

all in stdlib.h

全在 stdlib.h