Я могу сделать это:
int main(int argc, char** argv) {
unsigned char cTest = 0xff;
return 0;
}
Но что правильный путь состоит в том, чтобы получить шестнадцатеричное число в программу через командную строку?
unsigned char cTest = argv[1];
не добивается цели. Это производит инициализацию, делает целое число из указателя без предупреждения броска.
Как указывает тип 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, воспользуйтесь преимуществами ANSI-C Quiting , чтобы оболочка выполняла преобразование, а затем ваша программа просто печатает значения из командной строки.
#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 , который будет проходить через символы в строке и преобразует их, с учетом Radix (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
, и у вас есть только Unsive Char
Это в?
, например, с SSCANF
:
int val;
sscanf(argv[1], &val)
printf("%d\n", val);
Традиционный способ сделать этот вид вещей в C - это с Scanf () . Это именно обратный отпечаток печати (), чтение данного формата из файла (или терминала) и в список переменных, а не написать их в него.
В вашем случае вы используете SSCANF
, так как вы уже получили его в строке, а не по потоку.
unsigned char cTest = argv[1];
неправильно, потому что argv[1]
имеет тип char *
. Если argv[1]
содержит нечто подобное "0xff"
и вы хотите присвоить целое значение, соответствующее этому, неподписанному символу char -
, самым простым способом, вероятно, было бы использовать strtoul()
, чтобы сначала преобразовать его в беззнаковый длинный
, а затем проверить, является ли преобразованное значение меньше или равно UCHAR_MAX
. Если да, то можно просто присвоить cTest
. Третий параметр
strtoul()
является базовым, который может быть равен 0 для обозначения разбора числа в стиле C (разрешены восьмеричные и шестнадцатеричные литералы). Если вы хотите разрешить только базу 16, передайте ее в качестве третьего аргумента в strtoul()
. Если вы хотите разрешить любую базу (чтобы можно было разобрать 0xff
, 0377
, 255
и т.д.), используйте 0.
UCHAR_MAX
определено в <лимиты.h>
.