処理の流れを制御する 解答ページ | Programming Place Plus C言語編 第17章

トップページC言語編第17章

問題①

問題① 次の do文を、同じ結果になるように、無限ループを使ったかたちに書き換えてください。

#include <stdio.h>

int main(void)
{
    int value = 0;
    do {
        puts("Please enter the integer.");
        char input_string[32];
        fgets(input_string, sizeof(input_string), stdin);
        sscanf(input_string, "%d", &value);

        if (value > 0) {
            printf("%d is positive number.\n", value);
        }
        else if (value < 0) {
            printf("%d is negative number.\n", value);
        }
    } while (value != 0);
}


整数の入力を受け取り、0 より大きいか、0 より小さいかによってメッセージを出力し、ループを続行します。0 だったときには何も出力せずに終了します。

Please enter the integer.
3  <-- 入力した整数
3 is positive number.
Please enter the integer.
-3  <-- 入力した整数
-3 is negative number.
Please enter the integer.
0  <-- 入力した整数

do文で実現すると、変数 value がループの外側に出てしまうことがやや気になるところです。while文や for文で書くと、変数 value をループの内側に入れられます。

#include <stdio.h>

int main(void)
{
    while (1) {
        puts("Please enter the integer.");
        char input_string[32];
        fgets(input_string, sizeof(input_string), stdin);
        int value;
        sscanf(input_string, "%d", &value);

        if (value > 0) {
            printf("%d is positive number.\n", value);
        }
        else if (value < 0) {
            printf("%d is negative number.\n", value);
        }
        else {
            break;
        }
    };
}

while文に変更し、条件式を 1 にしました。これで必ずループに入りますから、do文の「最低でも1回はループする」という動作をマネできます。あとは、適切なタイミングで break文を使って脱出すればいいです。

入力された値が 0 のときにはループを抜け、そうでなければ続行しなければなりませんから、value == 0 のときに break文を実行するようにします。value == 0 というのは、value > 0 でも value < 0 でもないときなので、ここでは else を最後に付け足して実現しています。

問題②

問題② 次のプログラムは何をしているのでしょうか?

#include <stdio.h>

int main(void)
{
    int i;

    i = 0;
loop:
    printf("%d\n", i);
    ++i;
    if (i < 10) { goto loop; }
}


goto文のラベル名が「loop」となっていることからも推測できますが、これは goto文を利用したループ構造です。変数i でループ回数を数え、printf関数を 10回呼び出しています。実行結果はこうなります。

実行結果:

0
1
2
3
4
5
6
7
8
9

明らかに for文などで作るループよりも分かりづらいでしょう。C言語も含めて、大半のプログラミング言語では、ループ構造を作るために専用の構文が用意されており、それを使うべきです。goto文による表現は非常に原始的なもので、読むのも書くのも苦痛になるでしょう。

【上級】この原始的な形は、プログラムの実際の動作をより的確に表しています。for文などのループ専用の構文は、プログラムの実際の動作の形を隠して、プログラマーが記述しやすい形に直したものと言えます。コンパイルを行った後には、あたかも goto文で書いたかのようなプログラムに変換されています。

問題③

問題③ 問題②のプログラムを、goto文をなくし、for文だけで書き変えてください。


次のように書けます。

#include <stdio.h>

int main(void)
{
    for (int i = 0; i < 10; ++i) {
        printf("%d\n", i);
    }
}

実行結果:

0
1
2
3
4
5
6
7
8
9

問題④

問題④ 問題③で書き変えたプログラムをさらに、無限ループを使うように書き変えてください。


次のように書けます。

#include <stdio.h>

int main(void)
{
    int i = 0;

    while (1) {
        if (i >= 10) {
            break;
        }
        printf("%d\n", i);
        ++i;
    }
}

実行結果:

0
1
2
3
4
5
6
7
8
9

無限ループを作ったら、決して抜け出すことがないループでない限り、恐らくは break文が必要になります(break文の代わりに、return文や goto文を使う可能性はあります)。

ループの内部で、条件判定を行う場所や、インクリメントを行う場所を少し変えただけで、動作は大きく変わってしまいます。for文の実行順序(初期化→条件判定→内部の処理→インクリメント)を思い浮かべながら、それと同じ順序になるように書き変えていきましょう。


参考リンク


更新履歴

’2018/6/5 第18章から練習問題⑬を移動してきて、練習問題⑤とした。

’2018/2/9 全面的に文章を見直し、修正を行った。

’2015/8/22 ソースコード内のキーワードの色が変わっていない箇所があったので、修正。

’2009/5/4 新規作成。



第17章のメインページへ

C言語編のトップページへ

Programming Place Plus のトップページへ



はてなブックマーク に保存 Pocket に保存 Facebook でシェア
X で ポストフォロー LINE で送る noteで書く
rss1.0 取得ボタン RSS 管理者情報 プライバシーポリシー
先頭へ戻る