C 言語における条件付きループ

CCBeginner
今すぐ練習

💡 このチュートリアルは英語版からAIによって翻訳されています。原文を確認するには、 ここをクリックしてください

はじめに

この実験では、C プログラミングにおける条件付きループの実装方法を学びます。まず、while ループの基本を理解し、break と continue の指示子を使ってループの実行を制御する方法を探ります。また、条件文を使って配列要素をフィルタリングし、さまざまな指示子を使ってループの効率を最適化する方法も学びます。この実験が終わるとき、C プログラミングにおける条件付きループとその実際の応用について十分な理解を得ることができます。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL c(("C")) -.-> c/FunctionsGroup(["Functions"]) c(("C")) -.-> c/BasicsGroup(["Basics"]) c(("C")) -.-> c/CompoundTypesGroup(["Compound Types"]) c(("C")) -.-> c/ControlFlowGroup(["Control Flow"]) c(("C")) -.-> c/UserInteractionGroup(["User Interaction"]) c/BasicsGroup -.-> c/operators("Operators") c/ControlFlowGroup -.-> c/if_else("If...Else") c/ControlFlowGroup -.-> c/for_loop("For Loop") c/ControlFlowGroup -.-> c/while_loop("While Loop") c/ControlFlowGroup -.-> c/break_continue("Break/Continue") c/CompoundTypesGroup -.-> c/arrays("Arrays") c/FunctionsGroup -.-> c/math_functions("Math Functions") c/UserInteractionGroup -.-> c/user_input("User Input") c/UserInteractionGroup -.-> c/output("Output") subgraph Lab Skills c/operators -.-> lab-438260{{"C 言語における条件付きループ"}} c/if_else -.-> lab-438260{{"C 言語における条件付きループ"}} c/for_loop -.-> lab-438260{{"C 言語における条件付きループ"}} c/while_loop -.-> lab-438260{{"C 言語における条件付きループ"}} c/break_continue -.-> lab-438260{{"C 言語における条件付きループ"}} c/arrays -.-> lab-438260{{"C 言語における条件付きループ"}} c/math_functions -.-> lab-438260{{"C 言語における条件付きループ"}} c/user_input -.-> lab-438260{{"C 言語における条件付きループ"}} c/output -.-> lab-438260{{"C 言語における条件付きループ"}} end

while ループを理解する

このステップでは、C プログラミングにおける while ループの基本を学びます。while ループは、特定の条件が真のままである限り、コードのブロックを繰り返すことができる強力な制御構造です。

while ループの基本構文を示す簡単な C プログラムを作成しましょう。VSCode エディタを開き、~/project ディレクトリに while_loop_example.c という名前の新しいファイルを作成します。

cd ~/project
touch while_loop_example.c
#include <stdio.h>

int main() {
    int count = 1;

    while (count <= 5) {
        printf("Current count: %d\n", count);
        count++;
    }

    return 0;
}

コードを分解してみましょう。

  • int count = 1; は、カウンタ変数を初期化します。
  • while (count <= 5) は、count が 5 以下の間、ループを続けるループを作成します。
  • printf() は、count の現在の値を表示します。
  • count++ は、各反復でカウンタをインクリメントします。

プログラムをコンパイルして実行します。

gcc while_loop_example.c -o while_loop_example
./while_loop_example

実行結果の例:

Current count: 1
Current count: 2
Current count: 3
Current count: 4
Current count: 5

ここでは、ユーザー入力を伴う while ループの例を示します。

#include <stdio.h>

int main() {
    int number;

    printf("Enter numbers (enter 0 to stop):\n");

    number = 1;  // ゼロ以外の値で初期化
    while (number!= 0) {
        printf("Enter a number: ");
        scanf("%d", &number);

        if (number!= 0) {
            printf("You entered: %d\n", number);
        }
    }

    printf("Loop ended. Goodbye!\n");

    return 0;
}

この例は、while ループが特定の条件 (0 を入力すること) が満たされるまで続く、対話型入力にどのように使用できるかを示しています。

while ループにおける break 指示子の適用

このステップでは、C プログラミングにおける break 指示子について学びます。これは、特定の条件が満たされたときにループを早期に終了させることができます。break 文は、現在のループを即座に終了させ、ループの次の文から実行を続ける方法を提供します。

break の使用方法を示すために、~/project ディレクトリに break_loop_example.c という名前の新しいファイルを作成しましょう。

cd ~/project
touch break_loop_example.c
#include <stdio.h>

int main() {
    int number;

    printf("Enter numbers to find the first multiple of 10:\n");

    while (1) {  // 無限ループ
        printf("Enter a number: ");
        scanf("%d", &number);

        if (number % 10 == 0) {
            printf("Found a multiple of 10: %d\n", number);
            break;  // 10 の倍数が見つかったときにループを終了
        }

        printf("Not a multiple of 10. Try again.\n");
    }

    printf("Loop terminated after finding a multiple of 10.\n");

    return 0;
}

コードを分解してみましょう。

  • while (1) は、break 文が見つかるまで続く無限ループを作成します。
  • ユーザーが 10 で割り切れる数を入力すると、break 文が即座にループを終了します。
  • 数が 10 で割り切れない場合、ループは入力を促すまま続きます。

もう 1 つの例を見てみましょう。これは、より複雑なシナリオでの break を示しています。

#include <stdio.h>

int main() {
    int sum = 0;
    int count = 0;
    int input;

    printf("Enter numbers (enter a negative number to stop):\n");

    while (1) {
        printf("Enter a number: ");
        scanf("%d", &input);

        if (input < 0) {
            break;  // 負の数が入力されたときにループを終了
        }

        sum += input;
        count++;
    }

    if (count > 0) {
        printf("Average of entered numbers: %.2f\n", (float)sum / count);
    } else {
        printf("No numbers were entered.\n");
    }

    return 0;
}

この例は、break をどのように使用できるかを示しています。

  • 特定の条件が満たされたときに入力の収集を停止する
  • 入力された数の平均を計算する
  • ループ終了に柔軟性を提供する

プログラムをコンパイルして実行して、break 指示子がどのように機能するかを確認しましょう。

gcc break_loop_example.c -o break_loop_example
./break_loop_example

while ループにおける continue 指示子の利用

このステップでは、C プログラミングにおける continue 指示子について学びます。これは、ループの現在の反復をスキップし、次の反復に移動することができます。continue 文は、特定の条件に基づいてループの一部を選択的に実行またはスキップする方法を提供します。

continue の使用方法を示すために、~/project ディレクトリに continue_loop_example.c という名前の新しいファイルを作成しましょう。

cd ~/project
touch continue_loop_example.c
#include <stdio.h>

int main() {
    int number;
    int sum_even = 0;
    int count_even = 0;

    printf("Enter 10 numbers to calculate the sum and count of even numbers:\n");

    int i = 0;
    while (i < 10) {
        printf("Enter number %d: ", i + 1);
        scanf("%d", &number);

        // 奇数をスキップ
        if (number % 2!= 0) {
            printf("Skipping odd number: %d\n", number);
            continue;  // 次の反復に移動
        }

        sum_even += number;
        count_even++;

        i++;
    }

    if (count_even > 0) {
        printf("Sum of even numbers: %d\n", sum_even);
        printf("Count of even numbers: %d\n", count_even);
        printf("Average of even numbers: %.2f\n", (float)sum_even / count_even);
    } else {
        printf("No even numbers were entered.\n");
    }

    return 0;
}

コードを分解してみましょう。

  • プログラムはユーザーに 10 個の数を入力するように求めます。
  • if (number % 2!= 0) は、数が奇数であるかどうかをチェックします。
  • continue は、奇数の場合、現在の反復の残りをスキップします。
  • 偶数のみが合計に加算され、カウントされます。

もう 1 つの例を見てみましょう。これは、より複雑な条件での continue を示しています。

#include <stdio.h>

int main() {
    int number;
    int positive_count = 0;
    int negative_count = 0;

    printf("Enter numbers (enter 0 to stop):\n");

    while (1) {
        printf("Enter a number: ");
        scanf("%d", &number);

        // 0 が入力されたらループを終了
        if (number == 0) {
            break;
        }

        // ゼロをスキップ
        if (number == 0) {
            continue;
        }

        // 正の数と負の数をカウント
        if (number > 0) {
            positive_count++;
        } else {
            negative_count++;
        }
    }

    printf("Positive numbers count: %d\n", positive_count);
    printf("Negative numbers count: %d\n", negative_count);

    return 0;
}

この例は、continue をどのように使用できるかを示しています。

  • 特定の値をスキップする
  • 条件に基づいて数を選択的に処理する
  • より柔軟なループ制御を提供する

プログラムをコンパイルして実行して、continue 指示子がどのように機能するかを確認しましょう。

gcc continue_loop_example.c -o continue_loop_example
./continue_loop_example

条件文を使って配列要素をフィルタリングする

このステップでは、C プログラミングにおいて条件文とループを使って配列要素をフィルタリングする方法を学びます。フィルタリングにより、特定の条件に基づいて配列から特定の要素を選択することができます。

配列要素のフィルタリングを示すために、~/project ディレクトリに array_filtering.c という名前の新しいファイルを作成しましょう。

cd ~/project
touch array_filtering.c
#include <stdio.h>

#define MAX_SIZE 10

int main() {
    int numbers[MAX_SIZE];
    int filtered_even[MAX_SIZE];
    int filtered_count = 0;

    // 配列要素を入力
    printf("Enter %d numbers:\n", MAX_SIZE);
    for (int i = 0; i < MAX_SIZE; i++) {
        printf("Enter number %d: ", i + 1);
        scanf("%d", &numbers[i]);
    }

    // 偶数をフィルタリング
    printf("\nFiltered Even Numbers:\n");
    for (int i = 0; i < MAX_SIZE; i++) {
        if (numbers[i] % 2 == 0) {
            filtered_even[filtered_count] = numbers[i];
            filtered_count++;
            printf("%d ", numbers[i]);
        }
    }

    printf("\n\nTotal even numbers: %d\n", filtered_count);

    return 0;
}

フィルタリングのプロセスを分解してみましょう。

  • 入力を格納する numbers と、フィルタリングされた要素を格納する filtered_even の 2 つの配列を作成します。
  • 最初のループはユーザーから 10 個の数を読み取ります。
  • 2 番目のループは条件文を使って偶数をフィルタリングします。
  • if (numbers[i] % 2 == 0) は数が偶数であるかどうかをチェックします。
  • 一致する要素は filtered_even 配列に格納されます。

複数のフィルタリング条件を持つもっと複雑な例を見てみましょう。

#include <stdio.h>

#define MAX_SIZE 10

int main() {
    int numbers[MAX_SIZE];
    int prime_numbers[MAX_SIZE];
    int prime_count = 0;

    // 配列要素を入力
    printf("Enter %d numbers:\n", MAX_SIZE);
    for (int i = 0; i < MAX_SIZE; i++) {
        printf("Enter number %d: ", i + 1);
        scanf("%d", &numbers[i]);
    }

    // 素数をフィルタリング
    printf("\nFiltered Prime Numbers:\n");
    for (int i = 0; i < MAX_SIZE; i++) {
        // 2 未満の数はスキップ
        if (numbers[i] < 2) continue;

        int is_prime = 1;
        for (int j = 2; j * j <= numbers[i]; j++) {
            if (numbers[i] % j == 0) {
                is_prime = 0;
                break;
            }
        }

        // 素数をフィルタリングされた配列に追加
        if (is_prime) {
            prime_numbers[prime_count] = numbers[i];
            prime_count++;
            printf("%d ", numbers[i]);
        }
    }

    printf("\n\nTotal prime numbers: %d\n", prime_count);

    return 0;
}

この例は以下を示しています。

  • 入力配列から素数をフィルタリングする
  • 素数判定を行うためのネストしたループ
  • フィルタリングされた要素を別の配列に格納する

プログラムをコンパイルして実行します。

gcc array_filtering.c -o array_filtering
./array_filtering

入力と出力の例:

Enter 10 numbers:
Enter number 1: 5
Enter number 2: 12
Enter number 3: 7
Enter number 4: 15
...

Filtered Prime Numbers:
5 7

Total prime numbers: 2

指示子を使ってループの効率を最適化する

このステップでは、C プログラミングにおいて様々な指示子と戦略を使ってループの効率を最適化する技術を学びます。ループのパフォーマンスと読みやすさを向上させるためのさまざまなアプローチを探ります。

最適化技術を示すために、~/project ディレクトリに loop_optimization.c という名前のファイルを作成しましょう。

cd ~/project
touch loop_optimization.c
#include <stdio.h>
#include <time.h>

#define ARRAY_SIZE 10000

// 従来のループを使って合計を計算する関数
int traditional_sum(int arr[], int size) {
    int sum = 0;
    for (int i = 0; i < size; i++) {
        sum += arr[i];
    }
    return sum;
}

// 最適化されたループを使って合計を計算する関数
int optimized_sum(int arr[], int size) {
    int sum1 = 0, sum2 = 0, sum3 = 0, sum4 = 0;

    // ループ展開技術
    int i;
    for (i = 0; i + 4 < size; i += 4) {
        sum1 += arr[i];
        sum2 += arr[i + 1];
        sum3 += arr[i + 2];
        sum4 += arr[i + 3];
    }

    // 残りの要素を処理する
    for (; i < size; i++) {
        sum1 += arr[i];
    }

    return sum1 + sum2 + sum3 + sum4;
}

int main() {
    int arr[ARRAY_SIZE];
    clock_t start, end;
    double cpu_time_used;

    // 配列を初期化する
    for (int i = 0; i < ARRAY_SIZE; i++) {
        arr[i] = i + 1;
    }

    // 従来の合計
    start = clock();
    int traditional_result = traditional_sum(arr, ARRAY_SIZE);
    end = clock();
    cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
    printf("Traditional Sum: %d\n", traditional_result);
    printf("Traditional Loop Time: %f seconds\n", cpu_time_used);

    // 最適化された合計
    start = clock();
    int optimized_result = optimized_sum(arr, ARRAY_SIZE);
    end = clock();
    cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
    printf("Optimized Sum: %d\n", optimized_result);
    printf("Optimized Loop Time: %f seconds\n", cpu_time_used);

    return 0;
}

もう 1 つの例を見てみましょう。これは複数の最適化技術を示しています。

#include <stdio.h>

#define MAX_SIZE 1000

int main() {
    int numbers[MAX_SIZE];
    int even_sum = 0, odd_sum = 0;

    // 効率的な初期化と合計
    for (int i = 0; i < MAX_SIZE; i++) {
        numbers[i] = i + 1;

        // 分岐を最小限に抑えた条件付き合計
        even_sum += (numbers[i] % 2 == 0) * numbers[i];
        odd_sum += (numbers[i] % 2!= 0) * numbers[i];
    }

    printf("Sum of Even Numbers: %d\n", even_sum);
    printf("Sum of Odd Numbers: %d\n", odd_sum);

    return 0;
}

示された重要な最適化技術:

  1. ループ展開によるループオーバーヘッドの削減
  2. 分岐予測の最小化
  3. 初期化と処理の結合
  4. 条件付き合計に乗算を使う

最適化フラグ付きでプログラムをコンパイルして実行します。

## 基本的な最適化でコンパイル
gcc -O2 loop_optimization.c -o loop_optimization
./loop_optimization

## 高度な最適化でコンパイル
gcc -O3 loop_optimization.c -o loop_optimization
./loop_optimization

追加の最適化ヒント:

  • -O2 または -O3 コンパイラフラグを使用する
  • ループ内の関数呼び出しを最小限に抑える
  • 適切なデータ型を使用する
  • 不要な計算を避ける
  • ループ不変コードの移動を検討する

まとめ

この実験では、C プログラミングにおける while ループの基本を学びます。それには、ループのフローを制御するための breakcontinue 指示子の使い方も含まれます。また、条件文を使って配列要素をフィルタリングする技術や、様々な指示子を使ってループの効率を最適化する方法も探ります。この実験が終了するまでに、C 言語で条件付きループを実装してさまざまなプログラミング問題を解決する方法をしっかりと理解するようになります。