C++でコンソールアプリケーションやツールを開発する際、プログラムの実行時に外部から設定値やファイル名を渡したい場面は頻繁に訪れます。
これを実現するのが 「コマンドライン引数」 です。
main 関数の引数にある argc や argv は何?」「
char* の配列ではなく、string として扱いたい」「
-o や --help のようなオプション機能を実装したい」このような疑問や要望に応えるために、この記事ではC++におけるコマンドライン引数の基本的な受け取り方から、std::string や数値への変換方法、そして簡易的なオプション解析(パーサー)の実装例まで、現在の開発現場で役立つテクニックをサンプルコード付きで徹底解説します。
![]() 執筆者:マヒロ |
|
コマンドライン引数の基本的な受け取り方 (argc, argv)
C++のプログラム開始点である main 関数は、引数を受け取れるように定義することができます。
これらがコマンドライン引数を格納する変数となります。
main関数の定義と引数の意味
コマンドライン引数を利用する場合、main 関数は通常以下のように定義します。
#include <iostream>
// int argc: 引数の数(Argument Count)
// char *argv[]: 引数の値の配列(Argument Vector)
int main(int argc, char *argv[]) {
// 引数の数を出力
std::cout << "引数の総数: " << argc << std::endl;
// すべての引数を出力
for (int i = 0; i < argc; ++i) {
std::cout << "argv[" << i << "]: " << argv[i] << std::endl;
}
return 0;
}
実行結果(コマンド:./app data.txt -mode fast)
引数の総数: 3
argv[0]: ./app
argv[1]: data.txt
argv[2]: -mode
argv[3]: fast
※実行環境によって argv[0] のパス形式は異なります。
ソースコードの解説
argc(Argument Count) プログラムに渡された引数の個数が入ります。 重要なのは、プログラム名自体(実行ファイル名)も1つとしてカウントされる点です。そのため、引数を何も渡さなくてもargcは最低でも1になります。argv(Argument Vector) 引数の文字列(char*)が格納された配列です。argv[0]にはプログラムの実行パスが入り、ユーザーが渡した最初の引数はargv[1]から始まります。
C++らしく扱う:stringやvectorへの変換
argv はC言語スタイルの文字列(char*)配列であるため、そのままでは文字列の結合や比較、検索といった操作が不便です。
C++で開発を行うなら、最初に std::string や std::vector に変換してしまうのがベストプラクティスです。
vector<string> に変換して扱いやすくする
#include <iostream>
#include <vector>
#include <string>
int main(int argc, char *argv[]) {
// char*配列を stringのvector に変換
// argv + 1 とすることで、プログラム名(argv[0])を除外して格納
std::vector<std::string> args(argv + 1, argv + argc);
// 範囲for文でスマートにアクセス
for (const auto& arg : args) {
std::cout << "引数: " << arg << std::endl;
}
// 文字列としての比較も簡単
if (!args.empty() && args[0] == "start") {
std::cout << "処理を開始します" << std::endl;
}
return 0;
}
実行結果(コマンド:./app start config.json)
引数: start
引数: config.json
処理を開始します
std::vector<std::string> args(argv + 1, argv + argc); という1行で、扱いづらいポインタ配列を、便利な string のリストに変換しています。
コンストラクタの第一引数を argv + 1 にすることで、不要なプログラム名(argv[0])をスキップし、実質的な引数だけを格納しています。
これにより、args[0] が「ユーザーが指定した最初の引数」となり、直感的に扱えるようになります。
数値として受け取る場合の変換方法 (int, double)
コマンドライン引数はすべて「文字列」として渡されます。
「回数」や「閾値」などの数値を渡したい場合は、プログラム側で型変換を行う必要があります。
std::stoi や std::stod を使う
#include <iostream>
#include <string>
#include <vector>
int main(int argc, char *argv[]) {
// 引数チェック(プログラム名以外に2つ必要)
if (argc < 3) {
std::cerr << "使用法: ./app <整数> <小数>" << std::endl;
return 1;
}
try {
// 文字列を整数に変換 (String TO Integer)
int num = std::stoi(argv[1]);
// 文字列を浮動小数点数に変換 (String TO Double)
double rate = std::stod(argv[2]);
std::cout << "整数: " << num << std::endl;
std::cout << "小数: " << rate << std::endl;
std::cout << "計算結果: " << num * rate << std::endl;
} catch (const std::exception& e) {
// 数値ではない文字が渡された場合などのエラー処理
std::cerr << "数値への変換に失敗しました: " << e.what() << std::endl;
return 1;
}
return 0;
}
実行結果(コマンド:./app 100 1.5)
整数: 100
小数: 1.5
計算結果: 150
ソースコードの解説
std::stoi: 文字列をint型に変換します。std::stod: 文字列をdouble型に変換します。- 例外処理: 変換できない文字列(例:”abc”)が渡されると例外(
std::invalid_argument等)を投げるため、try-catchブロックで囲むことで安全性を確保しています。
実践!オプション引数の解析(簡易パーサーの実装)
実用的なツールでは、command -o output.txt -v のように、順序に依存しない「オプション指定」が求められます。
本格的な解析にはライブラリ(getopt や CLI11、Boostなど)を使うこともありますが、標準機能だけで簡易的なパーサーを作ることも可能です。
自作クラスによるオプション解析の実装例
#include <iostream>
#include <vector>
#include <string>
#include <map>
class ArgParser {
public:
ArgParser(int argc, char *argv[]) {
for (int i = 1; i < argc; ++i) {
std::string arg = argv[i];
// オプション(-で始まる)の場合
if (arg[0] == '-') {
// 次の要素が値かどうかを確認
if (i + 1 < argc && argv[i + 1][0] != '-') {
options[arg] = argv[i + 1];
i++; // 値の分だけインデックスを進める
} else {
// 値がない場合はフラグとして扱い、"true"をセット
options[arg] = "true";
}
} else {
// オプション以外の引数(ファイル名など)
positionalArgs.push_back(arg);
}
}
}
// オプションの値を取得する(存在しない場合はデフォルト値を返す)
std::string getOption(const std::string& key, const std::string& defaultValue = "") {
if (options.count(key)) {
return options[key];
}
return defaultValue;
}
// オプション以外の引数を取得
const std::vector<std::string>& getPositionalArgs() const {
return positionalArgs;
}
private:
std::map<std::string, std::string> options;
std::vector<std::string> positionalArgs;
};
int main(int argc, char *argv[]) {
ArgParser parser(argc, argv);
// オプションの取得
std::string outputFile = parser.getOption("-o", "default.txt");
bool isVerbose = parser.getOption("-v") == "true";
std::cout << "出力ファイル: " << outputFile << std::endl;
if (isVerbose) {
std::cout << "詳細モード: ON" << std::endl;
}
// その他の引数の表示
std::cout << "処理対象ファイル:" << std::endl;
for (const auto& file : parser.getPositionalArgs()) {
std::cout << " - " << file << std::endl;
}
return 0;
}
実行結果(コマンド:./app input1.txt -o result.log input2.txt -v)
出力ファイル: result.log
詳細モード: ON
処理対象ファイル:
- input1.txt
- input2.txt
この簡易パーサーは、ハイフン - で始まる引数を「オプション」と見なし、その直後に値があればキーと値のペアとして std::map に保存します。
-v のように値が続かない、あるいは次もオプションである場合は、フラグ(スイッチ)として扱います。
これにより、引数の順番を気にせず、柔軟なコマンドライン操作が可能になります。
C++のスキルを活かして年収を上げる方法
以上、C++のコマンドライン引数の受け取り方について解説しました。
なお、C++のスキルがある場合には、「転職して年収をアップさせる」「副業で稼ぐ」といった方法を検討するのがおすすめです。
C++を扱えるエンジニアは希少価値が高いため、転職によって数十万円の年収アップはザラで、100万円以上年収が上がることも珍しくありません。
なお、転職によって年収を上げたい場合は、エンジニア専門の転職エージェントサービスを利用するのが最適です。
併せて、副業案件を獲得できるエージェントにも登録しておくと、空いている時間を活かして稼げるようなC++の案件を探しやすくなります。
転職エージェントも副業エージェントも、登録・利用は完全無料なので、どんな求人や副業案件があるのか気になる方は、気軽に利用してみるとよいでしょう。



