C言語でgetopt/getopt_long関数の使い方を教えて!
こういった悩みにお答えします.
本記事の信頼性
- リアルタイムシステムの研究歴12年.
- 東大教員の時に,英語でOS(Linuxカーネル)の授業.
- 2012年9月~2013年8月にアメリカのノースカロライナ大学チャペルヒル校(UNC)コンピュータサイエンス学部で客員研究員として勤務.C言語でリアルタイムLinuxの研究開発.
- プログラミング歴15年以上,習得している言語: C/C++,Python,Solidity/Vyper,Java,Ruby,Go,Rust,D,HTML/CSS/JS/PHP,MATLAB,Assembler (x64,ARM).
- 東大教員の時に,C++言語で開発した「LLVMコンパイラの拡張」,C言語で開発した独自のリアルタイムOS「Mcube Kernel」をGitHubにオープンソースとして公開.
- 2020年1月~現在はアメリカのノースカロライナ州チャペルヒルにあるGuarantee Happiness LLCのCTOとしてECサイト開発やWeb/SNSマーケティングの業務.2022年6月~現在はアメリカのノースカロライナ州チャペルヒルにあるJapanese Tar Heel, Inc.のCEO兼CTO.
- 最近は自然言語処理AIとイーサリアムに関する有益な情報発信に従事.
- (AI全般を含む)自然言語処理AIの論文の日本語訳や,AIチャットボット(ChatGPT,Auto-GPT,Gemini(旧Bard)など)の記事を50本以上執筆.アメリカのサンフランシスコ(広義のシリコンバレー)の会社でプロンプトエンジニア・マネージャー・Quality Assurance(QA)の業務委託の経験あり.
- (スマートコントラクトのプログラミングを含む)イーサリアムや仮想通貨全般の記事を200本以上執筆.イギリスのロンドンの会社で仮想通貨の英語の記事を日本語に翻訳する業務委託の経験あり.
こういった私から学べます.
C言語を独学で習得することは難しいです.
私にC言語の無料相談をしたいあなたは,公式LINE「ChishiroのC言語」の友だち追加をお願い致します.
私のキャパシティもあり,一定数に達したら終了しますので,今すぐ追加しましょう!
独学が難しいあなたは,元東大教員がおすすめするC言語を学べるオンラインプログラミングスクール5社で自分に合うスクールを見つけましょう.後悔はさせません!
目次
getopt関数
1 2 3 4 |
int getopt(int argc, char * const argv[], const char *optstring); extern char *optarg; extern int optind; |
getopt関数は,コマンドライン引数(オプション)を解釈する関数です.
getopt関数がとる引数argcとargvは,main関数に渡された引数の個数と配列です.
argvの要素の中で'-'で始まるもの(かつ "-" 単独や "--" 単独ではないもの)はオプション要素になります.
また,オプション要素から先頭の'-'を除いた文字(-aの場合はa)は,オプション文字になります.
getopt関数は,繰り返し呼び出される毎に次のオプション文字を返します.
変数optindは,argvの次に処理される要素の添字です.
プログラムの起動時にシステムがoptindを1に初期化します.
プログラム中にoptindを1にリセットすることで,同じargvのスキャンをやり直すことができます.
新たなオプション文字が見つかると,getopt関数はその文字を返し,外部変数optindと静的な変数nextcharを更新します.
これらの処理を行うことで,getopt関数は次の呼び出しの際に,以降のオプション文字やargvの要素のスキャンを継続できます.
オプション文字が見つからない場合,-1を返します.
optindは,argvの要素の中でオプションでない最初の要素を示します.
また,optstringは受け付けるオプション文字からなる文字列です.
文字の後にコロン(:)が置かれている場合は,そのオプションには引数が必要であることを示します.
現在注目しているargv要素で,オプション文字に引き続くテキストへのポインタか,あるいは次のargv要素のテキストへのポインタをoptargに代入します.
2個連続してコロンが置かれている場合(::)は,そのオプションは引数を取っても取らなくても良いです.
getopt関数のコード
getopt関数のコードは以下になります.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
/* * Author: Hiroyuki Chishiro * License: 2-Clause BSD */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #define OPTSTRING "ai:" int main(int argc, char *argv[]) { int a, i; int opt; while ((opt = getopt(argc, argv, OPTSTRING)) != -1) { switch (opt) { case 'a': a = 1; break; case 'i': i = atoi(optarg); break; default: fprintf(stderr, "Usage: %s [-a] [-i integer] str\n", argv[0]); exit(1); } } printf("a = %d, i = %d, optind = %d\n", a, i, optind); if (optind >= argc) { fprintf(stderr, "String is needed after options.\n"); exit(2); } printf("str = %s\n", argv[optind]); return 0; } |
実行結果は以下になります.
1 2 3 4 |
$ gcc getopt.c $ a.out -a -i 123 abc a = 1, i = 123, optind = 4 str = abc |
getopt_long関数
1 2 3 |
int getopt_long(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex); |
getopt_long関数は,長いオプション(2つのダッシュ"--"で始まるオプション)を受け入れること以外はgetopt関数と同様に動作します(プログラムに長いオプションだけが渡された場合,optstringはNULLではなく空文字列("")になります.).
長いオプションの名前は,定義されたオプションに正確にマッチする場合以外にも,他と重ならない範囲において短縮できます.
長いオプションは引数を取ることができ,「--arg=param」または「--arg param」と言う形式で指定します.
getopt_long関数固有の引数は以下になります.
- longopts:struct optionの要素からなる配列の先頭要素へのポインタ
- longindex:NULLでない場合,長いオプションの添字をlongoptsからの相対位置として保持している変数へのポインタ
struct option構造体の定義は以下になります.
1 2 3 4 5 6 |
struct option { const char *name; int has_arg; int *flag; int val; }; |
struct option構造体のフィールドの解説は以下になります.
- name:長いオプションの名前を設定します.
- has_arg:no_argument(または 0)の場合,オプションは引数を取りません.
required_argument(または1)の場合,オプションは引数を必要とします.
optional_argument(または2)の場合,オプションは引数を取っても取らなくても良いです. - flag:長いオプションに対する結果の返し方を指定します.
flagがNULLの場合,getopt_long関数はvalを返します(例:呼び出し元のプログラムは,valに等価なオプション文字を代入することができます.).
NULL以外の場合には,getopt_long関数は0を返します.オプションが見つかった場合,flagが指す変数にvalが代入されます.
見つからない場合,flagは変更されません. - val:返り値,またはflagが指す変数に代入される値を設定します.
ここで,has_argがoptional_argumentの場合は,「--arg param」と--argとparamの間が空白の場合は正常に動作しないので注意して下さい.
「--arg=param」と=を入れて書くと正常に動作します.
getopt_long関数のコード
getopt_long関数のコードは以下になります.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
/* * Author: Hiroyuki Chishiro * License: 2-Clause BSD */ #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include <getopt.h> #define OPTSTRING "a:b::df:" static int verbose_flag = 0; static struct option long_options[] = { {"add", required_argument, NULL, 'a'}, {"append", optional_argument, NULL, 'b'}, {"delete", no_argument, NULL, 'd'}, {"noverbose", no_argument, &verbose_flag, 0}, {"verbose", no_argument, &verbose_flag, 1}, {NULL, 0, NULL, 0} }; int main(int argc, char *argv[]) { int c, option_index; while (true) { option_index = 0; if ((c = getopt_long(argc, argv, OPTSTRING, long_options, &option_index)) == -1) { break; } switch (c) { case 0: /* for long options. */ printf("option %s", long_options[option_index].name); if (optarg) { printf(" with arg %s", optarg); } printf("\n"); break; case 'a': printf("option %c with value '%s'\n", c, optarg); break; case 'b': printf("option %c", c); if (optarg) { printf(" with arg %s", optarg); } printf("\n"); break; case 'd': printf("option %c\n", c); break; default: fprintf(stderr, "Error: Unknown character code %c\n", c); } } if (verbose_flag) { printf("verbose flag is set.\n"); } if (optind < argc) { printf("non-option elements of argv: "); while (optind < argc) { printf("%s ", argv[optind++]); } printf("\n"); } return 0; } |
まずはビルドしましょう.
1 |
$ gcc getopt_long.c |
addオプションの実行結果は以下になります.
1 2 3 4 5 6 7 8 9 |
$ a.out --add abc option a with value 'abc' $ a.out -a abc option a with value 'abc' $ a.out: option '--add' requires an argument Error: Unknown character code ? $ a.out -a a.out: option requires an argument -- 'a' Error: Unknown character code ? |
appendオプションの実行結果は以下になります.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
$ a.out --append=abc option b with arg abc $ a.out --append abc option b non-option elements of argv: abc $ a.out --append option b $ a.out -b abc option b with arg abc $ a.out -b a.out: option requires an argument -- 'b' Error: Unknown character code ? $ a.out --a a.out: option '--a' is ambiguous; possibilities: '--add' '--append' Error: Unknown character code ? |
deleteオプションの実行結果は以下になります.
1 2 3 4 5 6 7 8 9 |
$ a.out --delete option d $ a.out --d option d $ a.out -d option d $ a.out --da a.out: unrecognized option '--da' Error: Unknown character code ? |
noverboseオプションの実行結果は以下になります.
1 2 |
$ a.out --noverbose option noverbose |
verboseオプションの実行結果は以下になります.
1 2 3 |
$ a.out --verbose option verbose verbose flag is set. |
まとめ
C言語でgetopt/getopt_long関数の使い方を紹介しました.
getopt/getopt_long関数を使いこなすのは難しいですが,何度も読み直してきちんと理解しましょう!
C言語を独学で習得することは難しいです.
私にC言語の無料相談をしたいあなたは,公式LINE「ChishiroのC言語」の友だち追加をお願い致します.
私のキャパシティもあり,一定数に達したら終了しますので,今すぐ追加しましょう!
独学が難しいあなたは,元東大教員がおすすめするC言語を学べるオンラインプログラミングスクール5社で自分に合うスクールを見つけましょう.後悔はさせません!