まずはどのように動くかという仕様を決めます。これだけのプログラムでも色々と考える必要があります。
- コマンドライン引数で階乗の数値を入力する。
- コマンドライン引数で入力した数値から階乗を計算する。
- 計算した結果をコンソールに表示する。
- 引数では数値を入力する。数値以外は0と見なす。
- 数値がマイナスの場合はエラーを表示し、2を返す。
- 小数点がついていた場合は、小数点以下を無視する。
- 引数の数が1つでない場合はエラーを表示し、1を返す。
- 値のオーバーフローは考慮しない。
コンパイルし、実行を行うと以下のようになります。
ソースコードの解説を簡単にします。
ソース | 説明 |
---|---|
main(int argc, char *argv[]) | 今回はmain()関数にint argc, char *argv[]という2つの引数がついています。argcは整数(int)で、引数の数を表します。argvは引数の文字列の配列を意味します。*や[]の意味はまた機会があれば説明します。とりあえずargv[1]などが一つ目の引数の文字列と解釈してください。 |
int value, fact, i; | valueと、factと、iという名前の整数のデータ領域を作成しています。 |
if (argc != 2) {...} | 引数の数(argc)のチェックを行っています。引数の数にはコマンド自身の数も含まれるので引数が1つのときには2となります。!=2はargcが2で無いかどうかという計算で、その結果により、{...}内の処理を行います。 |
value = atoi(argv[1]); | 引数の文字列argv[1]を整数値に変換して、valueに代入しています。文字列のままでは計算ができないためです。atoi()というのは文字列を整数値に変換するライブラリ関数です。stdlib.hに入っているのでstdlib.hを#includeしています。 |
if (value < 0) {...} | 引数を整数値に変換したvalueが0より小さい場合に{...}の処理をします。 |
fact = 1; | factというデータ領域に1を代入します。 |
for (i = 1; i <= value; i++) {...} | 繰り返し処理を行い、階乗を求めています。(1)iのデータ領域に1を代入します。(2)iがvalue以下の値か調べ、iがvalue以下の値であれば、{...}の処理を実行し、そうでなければ{...}の次の行の処理に移ります。(3){...}内の処理が終わったらi++を実行します。i++はiの値をi = i+1と同じ意味でiの値に1つ値を足します。 |
fact = fact * i; | アスタリスク(*)は掛け算の意味です。iが1つずつ加算するのを繰り返すことで、階乗を計算します。 |
printf("factorial = %d¥n", fact); | 階乗の値を出力します。printf()で表示する文字列の指定内のパーセント(%)には意味があり、%dは整数(int)の表示を行うことを意味します。文字列の後ろの引数に%dに表示するデータを列挙します。 |
複雑になりましたが、それは今回のプログラムがユーザーからのコマンドラインからの入力が増えたことが原因です。これでもオーバーフローを考慮しないなど、処理が少なくなるようにサボっています(17の階乗でなるはずの無いマイナス値となっているのはオーバーフローのためです)。
通常の場合、プログラムはユーザーの入力に対し、何かの処理を行います。ユーザーの入力は何があるか分からないので、入力を制限する処理を入れたり、どのような入力でもチェックによりエラーを返すなどの処理を入れなくてはいけません。そうしないと 想定外の問題が起こることになります。
この想定外の問題をいかにして少なくすることができるかが、プログラマの腕の見せ所の1つです。
それと、今回はCPUの処理(演算と制御)の部分とメモリ(データ領域の作成)の部分がHello Worldに比べて多く増えています。それらについてはまた次回。
0 件のコメント:
コメントを投稿