オプション
第三弾はオプションです。
C++
#include <iostream>
#include <vector>
#include <unordered_map>
#include <regex>
using namespace std;
struct opt_info
{
bool f_term;
const int const_value;
const int default_value;
const char *help;
};
unordered_map<string, struct opt_info> option_lt = {
{"--help", {true, 0, 0, "help message"}}, // help message
{"--special", {false, 3, 1, "special option"}}, // const value = 3, default = 1
{"--hogen", {false, 4, 1, "hogen option"}}, // const value = 4, default = 1
};
int main(int argc, char **argv)
{
vector<string> lt;
if (argc > 1)
{
int n = argc - 1;
for (int i = 0; i < n; i++)
{
lt.push_back(argv[i + 1]);
}
}
else
{
return 0;
}
unordered_map<string, int> opt_val_lt;
unordered_map<string, bool> check_lt;
decltype(option_lt)::iterator it = option_lt.begin();
for (; it != option_lt.end(); ++it)
{
check_lt.insert(make_pair(it->first, false));
}
bool term = false;
decltype(lt)::iterator k = lt.begin();
for (; k != lt.end(); ++k)
{
decltype(option_lt)::iterator it = option_lt.find(*k);
if (it != option_lt.end())
{
if (it->second.f_term)
{
term = true;
}
check_lt[it->first] = true;
}
}
it = option_lt.begin();
for (; it != option_lt.end(); ++it)
{
string s = it->first;
regex reg{R"(--)"};
string ret = regex_replace(s, reg, "");
if (check_lt[it->first])
{
opt_val_lt.insert(make_pair(ret, it->second.const_value));
}
else
{
opt_val_lt.insert(make_pair(ret, it->second.default_value));
}
}
if (0 == opt_val_lt.size())
{
cerr << "unknown option" << endl;
return -1;
}
if (term)
{
it = option_lt.begin();
cerr << "Help:" << endl;
for (; it != option_lt.end(); ++it)
{
cerr << " " << it->first << " : " << it->second.help << endl;
}
return 0;
}
decltype(opt_val_lt)::iterator e = opt_val_lt.begin();
for (; e != opt_val_lt.end(); ++e)
{
cout << e->first << " : " << e->second << endl;
}
try
{
cout << opt_val_lt.at("special") << endl; // use value of special
cout << opt_val_lt.at("hogen") << endl; // use value of hogen
}
catch (std::out_of_range &)
{
cerr << "exception std::out_of_range" << endl;
}
return 0;
}
Python
import argparse
parser = argparse.ArgumentParser()
parser.add_argument(
"--special", type=int, nargs="?", const=3, default=1, help="special option"
)
parser.add_argument(
"--hogen", type=int, nargs="?", const=4, default=1, help="hogen option"
)
opt = parser.parse_args()
print(opt)
print(f"special = {opt.special}") # use value of special
print(f"hogen = {opt.hogen}") # use value of hogen
実行結果
$ ./a.out --help
Help:
--hogen : hogen option
--special : special option
--help : help message
$ ./a.out --hogen
help : 0
special : 1
hogen : 4
1
4
$ ./a.out --special
help : 0
special : 3
hogen : 1
3
1
$ python3 option.py --help
usage: option.py [-h] [--special [SPECIAL]] [--hogen [HOGEN]]
optional arguments:
-h, --help show this help message and exit
--special [SPECIAL] special option
--hogen [HOGEN] hogen option
$ python3 option.py --hogen
Namespace(hogen=4, special=1)
special = 1
hogen = 4
$ python3 option.py --special
Namespace(hogen=1, special=3)
special = 3
hogen = 1
講評
C++の方はだいぶコードが大きくなりました。
そして、オプションの引数て難しいというか面倒くさい。
そのようなC++ライブラリもありそうですが、そうするとまた呼び出し等々でコード量が増えます。
こうゆう機能的かつ実用的な部分になってくると、pythonとは圧倒的な差が付きますね。
C++のコードは継ぎ接ぎ状態になってしまい、正直しんどかったです。
私の場合、C++では作らないですね。
ライブラリ
pythonには標準ライブラリでオプション指定のような機能が提供されています。
本記事では以下を使いました。

Argparse チュートリアル
author, Tshepang Mbambo,. このチュートリアルでは、 argparse を丁寧に説明します。 argparse は、Python 標準ライブラリの一部であり、おすすめのコマンドライン引数の解析モジュールです。 コンセ...
コメント