【C言語】ファイルから数値を読み込んで平均値を求める

この記事では、C言語を使ってファイルから数値を読み込み、その平均値を計算する方法について解説します。

具体的には、数値を読み込むためのfscanf関数の使い方や、ループを使ったデータの処理方法、平均値の計算方法、そしてエラーが発生したときの対処法について学びます。

初心者の方でもわかりやすく説明しているので、ぜひ最後まで読んでみてください。

目次から探す

数値の読み込み

C言語では、ファイルからデータを読み込むためにいくつかの関数が用意されています。

その中でも、fscanf関数は特に便利で、フォーマットに従ってデータを読み込むことができます。

ここでは、fscanf関数の基本的な使い方と、ループを使った数値の読み込み方法について解説します。

fscanf関数の基本

fscanf関数は、指定したファイルからデータを読み込み、指定した変数に格納するための関数です。

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

int fscanf(FILE *stream, const char *format, ...);
引数説明
stream読み込むファイルのポインタ
format読み込むデータの形式を指定する文字列
読み込んだデータを格納するための変数のアドレス

書式指定子の使い方

fscanf関数では、書式指定子を使って読み込むデータの型を指定します。

例えば、整数を読み込む場合は%d、浮動小数点数を読み込む場合は%fを使用します。

以下は、整数を読み込む例です。

int number;
fscanf(file, "%d", &number);

この例では、fileというファイルポインタから整数を読み込み、numberという変数に格納しています。

読み込むデータの型

fscanf関数は、さまざまなデータ型に対応しています。

主な書式指定子は以下の通りです。

フォーマット指定子説明
%d整数
%f浮動小数点数
%s文字列
%c文字

これらの書式指定子を使うことで、異なる型のデータをファイルから読み込むことができます。

ループを使った数値の読み込み

ファイルから複数の数値を読み込む場合、ループを使用することが一般的です。

これにより、ファイルの終わりまでデータを読み込むことができます。

whileループの活用

whileループを使って、ファイルから数値を読み込む方法を見てみましょう。

以下のコードは、ファイルから整数を読み込み続ける例です。

FILE *file = fopen("numbers.txt", "r"); // ファイルを開く
int number;
if (file != NULL) {
    while (fscanf(file, "%d", &number) == 1) { // 整数が読み込まれる限りループ
        printf("%d\n", number); // 読み込んだ数値を表示
    }
    fclose(file); // ファイルを閉じる
} else {
    printf("ファイルを開けませんでした。\n");
}

このコードでは、fscanfが成功した場合(戻り値が1の場合)にループが続き、読み込んだ数値を表示します。

EOF(End Of File)の扱い

ファイルの終わりを示す特別な値がEOF(End Of File)です。

fscanf関数は、ファイルの終わりに達するとEOFを返します。

これを利用して、ループを終了させることができます。

上記の例では、fscanfが1を返さなくなった時点でループが終了します。

このように、fscanf関数とループを組み合わせることで、ファイルから数値を効率的に読み込むことができます。

次のセクションでは、読み込んだ数値を使って平均値を計算する方法について解説します。

平均値の計算

ファイルから読み込んだ数値の平均値を求めるためには、まず合計値とカウントを管理する必要があります。

これにより、全ての数値を合計し、その数を数えることで平均を計算することができます。

合計値とカウントの管理

合計値を保持する変数

合計値を保持するためには、int型またはfloat型の変数を用意します。

整数の平均を求める場合はint型、浮動小数点数の平均を求める場合はfloat型を使用します。

以下のように変数を宣言します。

int sum = 0; // 合計値を保持する変数
int count = 0; // 読み込んだ数値のカウント

このように、sumには読み込んだ数値の合計を、countには読み込んだ数値の個数を格納します。

読み込んだ数値のカウント方法

数値をファイルから読み込む際に、各数値を読み込むたびにcountをインクリメントします。

これにより、読み込んだ数値の個数を正確に把握することができます。

以下は、数値を読み込む際の例です。

while (fscanf(file, "%d", &number) != EOF) {
    sum += number; // 合計値に加算
    count++; // カウントを増やす
}

このコードでは、fscanf関数を使ってファイルから数値を読み込み、sumにその数値を加算し、countを1増やしています。

平均値の算出

合計値とカウントが揃ったら、次は平均値を計算します。

平均値の計算式

平均値は、合計値をカウントで割ることで求められます。

以下のように計算します。

float average = (float)sum / count; // 平均値の計算

ここで、(float)sumとすることで、整数の割り算ではなく浮動小数点数の割り算を行うことができます。

これにより、より正確な平均値を得ることができます。

ゼロ除算の防止

カウントがゼロの場合、つまりファイルに数値が含まれていなかった場合にゼロ除算が発生します。

これを防ぐために、カウントがゼロでないことを確認してから平均値を計算する必要があります。

以下のように条件分岐を使います。

if (count > 0) {
    float average = (float)sum / count; // 平均値の計算
    printf("平均値: %.2f\n", average); // 平均値を表示
} else {
    printf("数値が読み込まれませんでした。\n");
}

このようにすることで、数値が読み込まれなかった場合には適切なメッセージを表示し、プログラムがエラーを起こさないようにします。

これで、ファイルから数値を読み込んで平均値を求める処理が完了します。

完成したコード

#include <stdio.h>

int main() {
    FILE *file;
    int number;
    int sum = 0;  // 合計値を保持する変数
    int count = 0; // 読み込んだ数値のカウント
    
    file = fopen("numbers.txt", "r");
    if (file == NULL) {
        printf("ファイルを開くことができませんでした。\\n");
        return 1;
    }

    while (fscanf(file, "%d", &number) != EOF) {
        sum += number; // 合計値に加算
        count++;       // カウントを増やす
    }

    fclose(file);

    if (count > 0) {
        float average = (float)sum / count; // 平均値の計算
        printf("平均値: %.2f\\n", average); // 平均値を表示
    } else {
        printf("数値が読み込まれませんでした。\\n");
    }

    return 0;
}

エラーハンドリング

プログラムを作成する際には、エラーハンドリングが非常に重要です。

特にファイル操作を行う場合、ファイルが存在しない、または読み込みに失敗することがあります。

ここでは、ファイルオープン時と読み込み時のエラー処理について詳しく解説します。

ファイルオープン時のエラー

ファイルを開く際には、fopen関数を使用しますが、ファイルが存在しない場合や、アクセス権がない場合にはエラーが発生します。

このエラーを適切に処理することが重要です。

エラーメッセージの表示

ファイルが正常にオープンできなかった場合、エラーメッセージを表示することで、ユーザーに問題を知らせることができます。

以下は、ファイルオープン時のエラーメッセージを表示するサンプルコードです。

#include <stdio.h>
int main() {
    FILE *file;
    file = fopen("data.txt", "r"); // 読み込みモードでファイルをオープン
    // ファイルオープンの成功を確認
    if (file == NULL) {
        // エラーメッセージを表示
        perror("ファイルを開くことができませんでした");
        return 1; // エラーコードを返してプログラムを終了
    }
    // ファイル操作のコード...
    fclose(file); // ファイルを閉じる
    return 0;
}

このコードでは、fopenがNULLを返した場合にperror関数を使ってエラーメッセージを表示しています。

プログラムの安全な終了

エラーが発生した場合は、プログラムを安全に終了させることが重要です。

上記の例では、エラーが発生した場合にreturn 1;でプログラムを終了しています。

これにより、後続の処理が実行されることを防ぎます。

読み込み時のエラー

ファイルが正常にオープンできた場合でも、データの読み込み中にエラーが発生することがあります。

たとえば、ファイル内に不正なデータが含まれている場合などです。

不正なデータの処理

fscanf関数を使用してデータを読み込む際、読み込みに失敗した場合にはエラー処理を行う必要があります。

以下は、不正なデータを処理するサンプルコードです。

#include <stdio.h>
int main() {
    FILE *file;
    int number;
    file = fopen("data.txt", "r");
    if (file == NULL) {
        perror("ファイルを開くことができませんでした");
        return 1;
    }
    while (fscanf(file, "%d", &number) == 1) { // 整数が正常に読み込まれた場合
        printf("読み込んだ数値: %d\n", number);
    }
    if (!feof(file)) { // EOF以外の理由でループを抜けた場合
        printf("不正なデータが含まれています。\n");
    }
    fclose(file);
    return 0;
}

このコードでは、fscanfが1を返す限り数値を読み込み続け、EOF以外の理由でループを抜けた場合には不正なデータが含まれていることを通知します。

エラー発生時の対処法

エラーが発生した場合には、適切な対処を行うことが重要です。

たとえば、エラーが発生した場合にプログラムを終了するのではなく、エラーメッセージを表示して次の処理に進むことも考えられます。

以下はその一例です。

#include <stdio.h>
int main() {
    FILE *file;
    int number;
    file = fopen("data.txt", "r");
    if (file == NULL) {
        perror("ファイルを開くことができませんでした");
        return 1;
    }
    while (1) {
        if (fscanf(file, "%d", &number) != 1) { // 読み込みに失敗した場合
            if (feof(file)) {
                break; // EOFに達した場合はループを抜ける
            } else {
                printf("不正なデータが含まれています。次のデータをスキップします。\n");
                fscanf(file, "%*s"); // 不正なデータをスキップ
                continue; // 次のループへ
            }
        }
        printf("読み込んだ数値: %d\n", number);
    }
    fclose(file);
    return 0;
}

このコードでは、不正なデータが見つかった場合にそのデータをスキップし、プログラムが続行できるようにしています。

これにより、プログラムが途中で停止することなく、可能な限りデータを処理することができます。

目次から探す