エディタを作る-1の2 コマンド引数
コンソール・アプリケーションの(GUIと比べての) 利点は、
【コマンド引数】 を付けて実行することで、
手軽に色々な値を指定・変更できる点である。
具体的に言えば、今回作ろうとしている コマンドライン・エディタの場合、
>edit file1
のように(editが実行ファイルとし、file1がファイル名の指定となる)ファイル名をコマンド引数として 指定することで、それをファイル名として開くことができる。 file1という名前のファイルが存在しなければ 新規に作成される。
file1の部分は、実行する時に簡単に指定できるし、変更(違うファイル名を指定)することも簡単だ。 これをGUIのアプリで実行しようとすると、ここまで簡単にはできない。
コンソール アプリを作る際には、この「コマンド(ライン)引数」を、自由に取り込んで、間違えることなく扱えるようにならないといけない。 よって、今回のサンプル・プログラムも かなり試す価値のあるものだ。
Qiitaの元々のソースファイルは以下の通り。
(少しだけ 整形している: return 0; を追加する等)
またしても、これは「いかがなものか?」という部分があるし、足りない部分もあり、気になる。
例えば、argv[100] を文字列として表示させようとしているが、まず 100番目のコマンド引数は存在しないだろうから、実行したら暴走しても仕方ないようにも思える。 ま~これも、
~それを超える添字にアクセスするとランタイムエラーが起きる
という記述から、エラーになるのが分かって使っていて、エラーが出る事を期待して試しているのだろう。 (コンパイルの時に出てくれるとありがたいのだが それは無理で、実行時に ↓ こんなエラーが出た)
不要な所を削除し、確認したい値(argc)を表示させるように変更したコードが次の通り。
ただ、C言語の入門書などでは 至る所で コマンド引数の使い方サンプルが載っているだろうし、C言語の場合は その変数名まで含めて 典型的な使い方が固定化されているので この程度の確認で問題は無いだろう。
よく勘違いしやすいのは、引数無しで実行しても argcは 1 が入る点だろう。 argcは引数の数ではなく コマンド自身を含めた数だからだ。
>arg
と コマンド引数無し だと argc = 1 になる
>arg file1
と 引数を1個つけて実行すると、argc には2が入る。
もう1点、間違えやすいのは argv[] の先頭には、引数の文字列が入るのではなく、コマンドその物の文字列が入る。 つまり、
argv[0] には ”arg” が入っており、argv[1]に初めて 引数の1つ目の文字列が入るのだ。 ( この例では argv[1]= ”file1” )
argv[]がゼロから始まる点([1]からではなく)も C言語の基本だが、BASIC等から入ってきた人は 間違えやすいので注意が必要だ。
さて、コマンド引数を使ったプログラムをデバッグする際は、コマンドプロンプトから試していたのでは 効率が悪くていけない。
Visual Studioの 統合環境で使っている場合、特定の(確認用の)コマンド引数が指定できると デバッグが楽になる。
[デバッグ] → [???のプロパティ] を選択し、(画像はVisual Studio 2013の物)
???のプロパティのページを表示させ、
「構成プロパティ」→「デバッグ」の項目に
【コマンド引数】の入力枠がある。 ここに(この例では file1 を入力)引数の文字列を入力しておくと、あたかもコマンドライン引数のそれが指定されているように動き、デバッグできる。
もう一つ 注意しないといけないのが、
argv[0] に入る コマンド(自分自身)の文字列が入るのだが、コマンドプロンプトから実行する時と 統合環境から実行する時で 違いがある。
arg.exe を コマンドプロンプトから実行する時、
argv[0] は 単純に ”arg” なのに対し、
開発環境から実行すると、 (あまりにも長い)
フォルダ名まで含めて入っている点だ。
例えば、 ”D:\C\EditerConsole\01day\2_argument\Debag\” という フォルダ名まで含まれる。 長い!
コマンド名自体など、コード内で使わなければ良いだけの話ではあるが・・・
もう少し、例外的なテストをしてみたい。
>arg file1 file2
と コマンド引数を2つ指定した場合、
argc = 3
argv[1] = "file1", argv[2]="file2"
となるのは良いとして、全角(日本語のファイル名)は使えるのだろうか?
上の画像の通り、全角の文字列でも正しく使えそうだ。 ただし、”ファイル1” と ”ファイル2”の間を ちゃんと半角のスペースにしないと 正しく判別してくれないが・・・
全角の空白で 区切ろうとしても 空白として扱ってくれない ↓
”ファイル1 ファイル2” と くっ付いて、1つの文字列となってしまう。
ただこれは 海外由来のOSのサガで、仕方ない事なのだろう。
。