プログラミング演習1
― 課題4の付録 ―
破局のbreak文、未練のcontinue文
case文のときにbreak文が出てきたが、break文のもう一つの使い方に ループ(反復)からの脱出がある。break文に出会うと、プログラムは その文を含む最小のループ(for, while, do〜while)から抜け出す。 if文と組み合わせることで、ループ内の任意の場所から条件付きで 抜け出すことができる。
do { n++; …(1)… if (n > N) { printf("*** 反復回数が%d回を超えました。 ***\n", N); break; } …(2)… } while (err >= eps);break文とよく似たものにcontinue文がある。 continue文はループの中でのみ用いられ、この文以降の文を省略してループの最後までジャンプする。 ループの外には出ないことがbreak文との違いである。
continue文が出てくるシチュエーションでは、if文を使えば代用できる。 また、break文が出てくるシチュエーションでは、continue文とループでの条件文の追加で 代用できないことはないが、同種の条件式を2か所で使うことになる。
do { n++; …(1)… if (n > N) { printf("*** 反復回数が%d回を超えました。 ***\n", N); } else { …(2)… } } while ((err >= eps) && (n <= N));多重ループを一気に抜けるにはgoto文が便利である。 また、関数(メイン関数の場合にはプログラム)を強制終了させるには return文、 サブルーチン内からプログラムを強制終了させるにはexit関数を用いる。
scanf関数は好かん、とです…
scanf関数はいろいろと問題が多いので、代わりにgets関数とsscanf関数の組み合わせをお薦めする。 通常は
main() { double x1, x2, eps; … printf(" x1, x2, eps = "); scanf("%lf%lf%lf", &x1, &x2, &eps); … }と書くところをgets関数とsscanf関数で置き換えると…
main() { double x1, x2, eps; char s[128]; … printf(" x1, x2, eps = "); gets(s); sscanf(s, "%lf%lf%lf", &x1, &x2, &eps); … }デリミタ(数字の区切り)としてSpace, Tab以外にコンマも許すようにし、 ついでにエラー処理したいときは、
main() { double x1, x2, eps; char s[128]; … printf(" x1, x2, eps = "); gets(s); if (sscanf(s, "%lf%lf%lf", &x1, &x2, &eps) != 3) // スペース、タブ if (sscanf(s, "%lf,%lf,%lf", &x1, &x2, &eps) != 3) { // コンマ printf("*** 入力形式が異常です。 ***\n"); return 1; } … }main関数の型と戻り値
main関数は、プログラム内では戻る先がないので、型は決めなくても プログラムの動作自体にはまったく影響がない。 大昔は void (不完全型) としているソースが多かった。
1: #include <stdio.h> 2: 3: void main() 4: { 5: printf("hello, world!\n"); 6: }しかし、ANSI準拠のCコンパイラでは、デフォルトでint型となっており、 厳しめのコンパイラチェックをかけると、警告として戻り値を要求される。 実は、main関数の戻り値はOSに引き渡されるので、OS側で正常終了か異常終了かを 調べるのに利用されることが多い。 したがって、積極的に戻り値を返す癖をつけるようにしてほしい。 終了状態を返す整数型関数の戻り値としては、正常終了時に 0、異常終了時に 0 以外を返すのが慣例である。
1: #include <stdio.h> 2: 3: main() 4: { 5: printf("hello, world!\n"); 6: return 0; 7: }ちなみに、stdlib.h をインクルードしているときには、 戻り値用の定数マクロとして EXIT_SUCCESS, EXIT_FAILURE が使用できる。
1: #include <stdio.h> 2: #include <stdlib.h> 3: 4: main() 5: { 6: printf("hello, world!\n"); 7: return EXIT_SUCCESS; 8: }ごく短いプログラムでは野暮な感じがするが、 可搬性が良くなるので、プロのプログラマを めざすなら知っていて損はない。
デバッグに便利な定数マクロ
Cでは、標準で __FILE__, __LINE__ などの定数マクロが用意されている。 これは、printf と共に使えば有用なデバッグツールになる。
__LINE__ にはソース内の行番号が入る。 __FILE__ にはソースのファイル名が入る。 文字列定数なので、printf 内では他の文字列と連結できる。 ソースのはじめに #define でマクロ定義しておくと便利である。1: #include <stdio.h> 2: #define CLINE printf(__FILE__":%d\n", __LINE__) 3: 4: main() 5: { 6: printf("hello, world!\n"); CLINE; 7: return 0; 8: }2行目は、
2: #define CLINE printf("%s:%d\n", __FILE__, __LINE__)としてもよい。 たとえば、上記のプログラム hello.c の実行結果は
hello, world! hello.c:6となる。途中でフリーズするようなソースをデバッグする際に CLINE; をブレークポイント代わりにあちこち入れておくと、 どこまで実行しているかがデバッガを使わなくても追跡できる。
【目次】 | 【1.】 | 【2.】 | 【3.】 | 【付録2】