私がすることができます:
int main(int argc, char** argv) {
unsigned char cTest = 0xff;
return 0;
}
しかし、コマンドラインを介してプログラムに16進数を取り込む正しい方法は何ですか?
unsigned char cTest = argv[1];
トリックをしません。これにより、キャスト警告なしでポインタから整数になる初期化が生成されます。
私がすることができます:
int main(int argc, char** argv) {
unsigned char cTest = 0xff;
return 0;
}
しかし、コマンドラインを介してプログラムに16進数を取り込む正しい方法は何ですか?
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
示すように、コマンドラインからの引数は文字列であり、別の表現に変換する必要があります。
単一の16進コマンドライン引数を10進数に変換すると、次のようになります。
#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
プログラムが10進数、16進数(先頭で示される) 、および8進数(先頭で示される0
)の値を受け入れるようにします。
$ ./num 0x70
112
$ ./num 070
56
$ ./num 70
70
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はフォームの多くの形式をサポートしていますが、$'...'
あなた$'\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
渡す基数(このコンテキストでは16)を考慮して、文字列内の文字をウォークスルーして変換するstrtoulを使用できます。-
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]
タイプがであるため、間違っていchar *
ます。argv[1]
のようなものが含まれて"0xff"
いて、それに対応する整数値をに割り当てたい場合、unsigned char
最も簡単な方法は、strtoul()
最初にそれをに変換してから、unsigned long
変換された値が。以下であるかどうかを確認することですUCHAR_MAX
。はいの場合は、に割り当てることができますcTest
。
strtoul()
の3番目のパラメーターはベースであり、Cスタイルの数値解析を示すために0にすることができます(8進数および16進数のリテラルを使用できます)。16進数のみを許可する場合は、それを3番目の引数として。に渡しますstrtoul()
。0xff
任意のベースを許可する場合( 、、、など0377
を解析できるようにするため255
)、0を使用します。
UCHAR_MAX
で定義されてい<limits.h>
ます。
Cでこの種のことを行う従来の方法は、scanf()を使用することです。これはprintf()の逆であり、指定された形式をファイル(またはターミナル)からリストした変数に書き込むのではなく読み取ります。
あなたの場合、sscanf
ストリームではなく文字列ですでにそれを持っているので、あなたはそれを使うでしょう。
atoi
、、、、atol
_ strtoi
_strtol
オールインstdlib.h