LoginSignup
0
0

Cのdowhileの使い道

Last updated at Posted at 2023-06-05

はじめに

こんにちは。
順次、分岐、反復。プログラミングの3種の神器の一つの反復を実現してくれるwhileにはきょうだい?のdowhileがあります。しかし、使い道が分からないままになっていませんか?(そもそもforしか使っていないとか?)
今回はdowhileの使い道を紹介したいと思います。

dowhileとは

一応、知識を整理するためにまとめます

while

whileはまず( )の中の条件式を比較し、結果が真の場合は{ }の中の処理をします
次に( )の中の条件式を比較し...というのを繰り返します
そのため、条件式によっては処理が一回もされません

while (/* 条件式 */) {
    /* 条件が真のときに行う処理 */
}

dowhile

dowhileはまず{ }の中の処理をし、次に( )の中の条件式を比較します
その結果が真の場合はまた{ }の中の処理をし...というのを繰り返します
そのため、条件式にかかわらず、必ず一回は処理がされます

またwhileと違い、( )の後ろに「;」が必要です

do {
    /* 条件が真のときに行う処理 */
} while (/* 条件式 */);
#include <stdio.h>

int main(void) {
    int i = 0;

    // while_A
    while (i < 3) {
        printf("while_A_%d, ", i);
        i ++;
    }
    // >> while_A_0, while_A_1, while_A_2

    // while_B
    while (i < 3) {
        printf("while_B");
        i ++;
    }
    // >> (何も出力されない)

    i = 0;

    // dowhile_A
    do {
        printf("dowhile_A_%d, ", i);
        i ++;
    } while (i < 3);
    // >> dowhile_A_0, dowhile_A_1, dowhile_A_2

    // dowhile_B
    do {
        printf("dowhile_B");
        i ++;
    } while (i < 3);
    // >> dowhile_B

    return 0;
}

dowhileの使い道

一回は処理がされる特徴を活用できる例を紹介します

ユーザからの入力を検証する場合

whileで書いた場合

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    int inputedNum;    

    system("cls");
    printf("あなたの誕生月を入力してください");
    scanf("%d", &inputedNum);
    while (inputedNum < 0 || inputedNum > 12) {
        system("cls");
        printf("あなたの誕生月を入力してください");
        scanf("%d", &inputedNum);
    }

    // ...

    return 0;
}

間違いではないですが、system("cls"); ~ scanf("%d", &inputedNum);が重複しているのが気になります。今回は重複しているコードが少ないですが、もっと多くなると見にくくなります。

また、int inputedNum = 0;など、わざとwhileの条件式の結果が真になるようにしてもいいですが、プログラムの意味合いから考えるといまいちです。今回は「ユーザの入力を検証して、誕生月でない場合はもう一度入力を要求する」という意味合いのコードを書きたいからです。

dowhileで書いた場合

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    int inputedNum;    
    do {
        system("cls");
        printf("あなたの年齢を入力してください");
        scanf("%d", &inputedNum);
    } while (inputedNum < 0 || inputedNum > 12);

    // ...

    return 0;
}

whileで書いた場合の問題を解決できています

一つの#defineに複数の行を定義したい場合

(#defineの詳細な解説は省略します)
これはwhileとの比較ではなく、dowhileだからこそできることです

ここでは引数に渡された2つの値を入れ替えるアルゴリズムであるSWAPをマクロで定義するとします

dowhileを使わない場合

#define SWAP(x, y) \
tmp = x; \
x = y; \
y = tmp;

もしこれをifの中で呼び出すと

int main (void) {
    int x = 2, y = 3, z = 1;

    if (z)
        SWAP (x, y);

    return 0;
}

int main (void) {
    int x = 2, y = 3, z = 1;

    if (z)
        tmp = x;
    x = y;
    y = tmp;

    return 0;
}

と解釈されるため、エラーやバグになります。

dowhileを使う場合

dowhiledo {/* 複数の文 */} while (0);とすることで一つのブロックとなります
また条件式を0とすることで{ }の中を一回だけ処理をさせることができます

#define SWAP(x, y) \
do { \
    tmp = x; \
    x = y; \
    y = tmp; \
} while (0)

もしこれをifの中で呼び出しても

int main (void) {
    int x = 2, y = 3, z = 1;

    if (z)
        SWAP (x, y);

    return 0;
}

int main (void) {
    int x = 2, y = 3, z = 1;

    if (z)
        do {
            tmp = x;
            x = y;
            y = tmp;
        } while (0);

    return 0;
}

と解釈され、正常に動きます。(引数が2回解釈されているため完璧なコードではありませんが、ここではdowhileの使い道を紹介したいので詳細な説明は割愛します)

さいごに

いかがでしたでしょうか?
少しでも参考に、そして使うきっかけになれば幸いです。

  • 間違いや分かりにくいところがありましたら、遠慮なくコメントしてください。ただし筆者はCの上級者ではないので、その点はご容赦ください。
0
0
7

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0