【C言語】正しい値が入力されるまでscanfを繰り返す方法

C言語でプログラムを作成する際、ユーザーからの入力を正しく受け取ることは非常に重要です。

しかし、ユーザーが誤った値を入力することもあります。

この記事では、正しい値が入力されるまで繰り返し入力を求める方法や、入力エラーの処理方法について解説します。

目次から探す

正しい値が入力されるまで繰り返す方法

C言語でユーザーからの入力を受け取る際、正しい値が入力されるまで繰り返し入力を求めることがよくあります。

ここでは、whileループとdo-whileループを使ってその方法を解説します。

whileループを使った方法

whileループの基本構造

whileループは、条件が真である限り繰り返し処理を行う制御構造です。

基本的な構造は以下の通りです。

while (条件) {
    // 繰り返し実行する処理
}

条件が真である限り、ループ内の処理が繰り返されます。

条件が偽になるとループを抜けます。

scanfの戻り値を利用したループ制御

scanf関数は、入力が成功した場合に読み取った項目の数を返します。

これを利用して、正しい値が入力されるまでループを続けることができます。

以下に具体的な例を示します。

#include <stdio.h>
int main() {
    int num;
    int result;
    printf("整数を入力してください: ");
    result = scanf("%d", &num);
    while (result != 1) {
        // 入力が正しくない場合の処理
        printf("無効な入力です。再度整数を入力してください: ");
        
        // 入力バッファをクリア
        while (getchar() != '\n');
        // 再度入力を受け取る
        result = scanf("%d", &num);
    }
    printf("入力された整数は %d です。\n", num);
    return 0;
}

この例では、scanfの戻り値が1でない場合(つまり、整数が入力されなかった場合)にループが続きます。

入力バッファをクリアするために、getchar関数を使って改行文字まで読み飛ばしています。

do-whileループを使った方法

do-whileループの基本構造

do-whileループは、少なくとも一度はループ内の処理を実行する制御構造です。

基本的な構造は以下の通りです。

do {
    // 繰り返し実行する処理
} while (条件);

ループ内の処理が一度実行された後、条件が真である限りループが続きます。

初回入力を必ず実行する利点

do-whileループを使うと、初回の入力を必ず実行することができます。

これにより、初回の入力を別途処理する必要がなくなります。

以下に具体的な例を示します。

#include <stdio.h>
int main() {
    int num;
    int result;
    do {
        printf("整数を入力してください: ");
        result = scanf("%d", &num);
        if (result != 1) {
            // 入力が正しくない場合の処理
            printf("無効な入力です。再度整数を入力してください。\n");
            
            // 入力バッファをクリア
            while (getchar() != '\n');
        }
    } while (result != 1);
    printf("入力された整数は %d です。\n", num);
    return 0;
}

この例では、do-whileループを使って初回の入力を必ず実行し、入力が正しくない場合に再度入力を求めるようにしています。

これにより、コードがシンプルで読みやすくなります。

以上が、whileループとdo-whileループを使って正しい値が入力されるまで繰り返す方法です。

どちらの方法も、ユーザーからの入力を確実に受け取るために非常に有効です。

入力エラーの処理方法

C言語でユーザーからの入力を受け取る際、正しい値が入力されるまで繰り返し入力を求めることがよくあります。

しかし、入力エラーが発生した場合、そのエラーを適切に処理しないと無限ループに陥る可能性があります。

ここでは、入力エラーの処理方法について詳しく解説します。

入力バッファのクリア

入力バッファとは

入力バッファとは、ユーザーが入力したデータが一時的に保存されるメモリ領域のことです。

scanf関数を使用して入力を受け取る際、ユーザーが入力したデータはまず入力バッファに格納され、その後プログラムに渡されます。

例えば、ユーザーが数値を入力する際に誤って文字を入力した場合、その文字は入力バッファに残ったままになります。

この状態で再度scanfを呼び出すと、入力バッファに残っているデータが再び読み取られ、エラーが繰り返されることになります。

バッファクリアの方法

入力バッファをクリアするためには、fflush関数getchar関数を使用する方法があります。

以下に具体的な方法を示します。

  1. fflush(stdin)を使用する方法
#include <stdio.h>
int main() {
    int num;
    while (1) {
        printf("整数を入力してください: ");
        if (scanf("%d", &num) == 1) {
            break; // 正しい入力があった場合、ループを抜ける
        } else {
            printf("無効な入力です。再度入力してください。\n");
            fflush(stdin); // 入力バッファをクリア
        }
    }
    printf("入力された整数: %d\n", num);
    return 0;
}
  1. getcharを使用する方法
#include <stdio.h>
int main() {
    int num;
    while (1) {
        printf("整数を入力してください: ");
        if (scanf("%d", &num) == 1) {
            break; // 正しい入力があった場合、ループを抜ける
        } else {
            printf("無効な入力です。再度入力してください。\n");
            while (getchar() != '\n'); // 入力バッファをクリア
        }
    }
    printf("入力された整数: %d\n", num);
    return 0;
}

エラーメッセージの表示

ユーザーに対するフィードバック

入力エラーが発生した場合、ユーザーに対して適切なフィードバックを提供することが重要です。

エラーメッセージを表示することで、ユーザーは何が間違っているのかを理解し、正しい入力を行うことができます。

エラーメッセージの具体例

以下に、エラーメッセージを表示する具体的な例を示します。

#include <stdio.h>
int main() {
    int num;
    while (1) {
        printf("整数を入力してください: ");
        if (scanf("%d", &num) == 1) {
            break; // 正しい入力があった場合、ループを抜ける
        } else {
            printf("無効な入力です。整数を入力してください。\n");
            while (getchar() != '\n'); // 入力バッファをクリア
        }
    }
    printf("入力された整数: %d\n", num);
    return 0;
}

この例では、ユーザーが無効な入力を行った場合に「無効な入力です。整数を入力してください。」というエラーメッセージを表示しています。

これにより、ユーザーは何が間違っているのかを理解し、正しい入力を行うことができます。

以上の方法を用いることで、C言語で正しい値が入力されるまでscanfを繰り返す際の入力エラー処理を適切に行うことができます。

応用例

複数の入力を検証する場合

複数のscanfを使った入力検証

C言語で複数の入力を検証する場合、各入力に対して個別にscanfを使用し、正しい値が入力されるまで繰り返し処理を行うことが一般的です。

以下に、整数と浮動小数点数の入力を検証する例を示します。

#include <stdio.h>
int main() {
    int integerInput;
    float floatInput;
    int result;
    // 整数の入力を検証
    printf("整数を入力してください: ");
    while ((result = scanf("%d", &integerInput)) != 1) {
        // 入力エラー処理
        printf("無効な入力です。再度整数を入力してください: ");
        while (getchar() != '\n'); // 入力バッファをクリア
    }
    // 浮動小数点数の入力を検証
    printf("浮動小数点数を入力してください: ");
    while ((result = scanf("%f", &floatInput)) != 1) {
        // 入力エラー処理
        printf("無効な入力です。再度浮動小数点数を入力してください: ");
        while (getchar() != '\n'); // 入力バッファをクリア
    }
    printf("入力された整数: %d\n", integerInput);
    printf("入力された浮動小数点数: %f\n", floatInput);
    return 0;
}

この例では、整数と浮動小数点数の入力がそれぞれ正しい形式であるかを確認し、無効な入力があった場合には再度入力を促すようにしています。

入力エラー処理の統一

複数の入力に対して同じエラー処理を行う場合、エラー処理のコードが重複してしまうことがあります。

これを避けるために、エラー処理を関数としてまとめることができます。

以下に、エラー処理を関数化した例を示します。

#include <stdio.h>
// 入力エラー処理関数
void clearInputBuffer() {
    while (getchar() != '\n');
}
int main() {
    int integerInput;
    float floatInput;
    int result;
    // 整数の入力を検証
    printf("整数を入力してください: ");
    while ((result = scanf("%d", &integerInput)) != 1) {
        // 入力エラー処理
        printf("無効な入力です。再度整数を入力してください: ");
        clearInputBuffer(); // 入力バッファをクリア
    }
    // 浮動小数点数の入力を検証
    printf("浮動小数点数を入力してください: ");
    while ((result = scanf("%f", &floatInput)) != 1) {
        // 入力エラー処理
        printf("無効な入力です。再度浮動小数点数を入力してください: ");
        clearInputBuffer(); // 入力バッファをクリア
    }
    printf("入力された整数: %d\n", integerInput);
    printf("入力された浮動小数点数: %f\n", floatInput);
    return 0;
}

このようにすることで、エラー処理のコードが簡潔になり、再利用性が向上します。

カスタム入力関数の作成

カスタム関数の設計

複数の入力検証を行う場合、カスタム入力関数を作成することでコードの再利用性と可読性を向上させることができます。

カスタム関数は、特定のデータ型の入力を検証し、正しい値が入力されるまで繰り返す処理を行います。

以下に、整数と浮動小数点数の入力を検証するカスタム関数の設計例を示します。

#include <stdio.h>
// 入力エラー処理関数
void clearInputBuffer() {
    while (getchar() != '\n');
}
// 整数入力を検証するカスタム関数
int getValidInteger() {
    int value;
    int result;
    printf("整数を入力してください: ");
    while ((result = scanf("%d", &value)) != 1) {
        printf("無効な入力です。再度整数を入力してください: ");
        clearInputBuffer(); // 入力バッファをクリア
    }
    return value;
}
// 浮動小数点数入力を検証するカスタム関数
float getValidFloat() {
    float value;
    int result;
    printf("浮動小数点数を入力してください: ");
    while ((result = scanf("%f", &value)) != 1) {
        printf("無効な入力です。再度浮動小数点数を入力してください: ");
        clearInputBuffer(); // 入力バッファをクリア
    }
    return value;
}
int main() {
    int integerInput = getValidInteger();
    float floatInput = getValidFloat();
    printf("入力された整数: %d\n", integerInput);
    printf("入力された浮動小数点数: %f\n", floatInput);
    return 0;
}

再利用可能な入力関数の実装

上記のカスタム関数を使用することで、入力検証のコードが簡潔になり、再利用性が向上します。

これにより、同じ入力検証の処理を複数の場所で使用することが容易になります。

例えば、他のデータ型や入力形式に対しても同様のカスタム関数を作成することで、コードの一貫性と可読性を保つことができます。

#include <stdio.h>
// 入力エラー処理関数
void clearInputBuffer() {
    while (getchar() != '\n');
}
// 整数入力を検証するカスタム関数
int getValidInteger() {
    int value;
    int result;
    printf("整数を入力してください: ");
    while ((result = scanf("%d", &value)) != 1) {
        printf("無効な入力です。再度整数を入力してください: ");
        clearInputBuffer(); // 入力バッファをクリア
    }
    return value;
}
// 浮動小数点数入力を検証するカスタム関数
float getValidFloat() {
    float value;
    int result;
    printf("浮動小数点数を入力してください: ");
    while ((result = scanf("%f", &value)) != 1) {
        printf("無効な入力です。再度浮動小数点数を入力してください: ");
        clearInputBuffer(); // 入力バッファをクリア
    }
    return value;
}
int main() {
    int integerInput = getValidInteger();
    float floatInput = getValidFloat();
    printf("入力された整数: %d\n", integerInput);
    printf("入力された浮動小数点数: %f\n", floatInput);
    return 0;
}

このように、カスタム関数を作成することで、入力検証の処理を簡潔かつ再利用可能にすることができます。

これにより、プログラム全体の品質と保守性が向上します。

目次から探す