テスト点数構造体処理:学籍番号と成績をコードで管理

SCORE: 1480
プライベート

/
構造化を用いてテスト点数を処理して出力
作成者:寺田凱斗
学生番号:251205120
作成日:12月3日
/

include

struct SEISEKI_DATA {
int japanese;
int math;
int science;
int society;
int gaksueki_number;
} seiseki[5] =
{
{90,60,80,60,1},
{100,25,80,60,2},
{65,55,80,80,3},
{45,80,60,100,4},
{100,100,100,100,5}
};

int main(void) {

int i,j,keep_sum,keep_id;
int sum[5];;
int ID[5];
FILE* fp;

for (i = 0; i < 5; i++) {
    sum[i] = seiseki[i].japanese + seiseki[i].math + seiseki[i].science + seiseki[i].society;
    ID[i] = seiseki[i].gaksueki_number;
}

for (i = 0; i < 5; i++) {
    for (j = 0; j < 5; j++) {
        if (sum[j] > sum[ j + 1]) {
            keep_sum = sum[ j ];     //
            sum[j] = sum[ j + 1];
            sum[j + 1] = keep_sum;

            keep_id = ID[j];
            ID[j] = ID[j + 1];
            ID[j + 1] = keep_id;
        }
    }
}
fp = fopen("5-4-result.txt", "w");

for (i = 0; i < 5; i++) {
    if (fp != NULL) {
        fprintf(fp, "学籍番号%d=%d\n",seiseki[i].gaksueki_number, sum[i]);
    }
}

}

2025/12/06 12:31

おっ、テストの点数を構造体で処理して、ファイルに出力するプログラムですね! 寺田凱斗さんの作成日12月3日のコード、拝見しました!😊

このコードでは、5人の学生の成績データを構造体 SEISEKI_DATA に格納し、それぞれの合計点を計算しています。その後、合計点の高い順に並べ替えて、学籍番号と合計点を "5-4-result.txt" というファイルに出力しようとしているんですね。

いくつか、より分かりやすく、または意図通りに動作させるためのポイントを共有させてください!

  • 合計点の計算と並べ替えについて:

    • 合計点を計算する部分は sum[i] に格納されていますが、並べ替えのループで sum[j] > sum[j + 1] という条件で比較しています。このままだと、配列のインデックスが j+1 までしか存在しないため、j が配列の最後の要素(この場合は4)になったときに sum[5] にアクセスしようとしてしまい、プログラムがエラーを起こしてしまう可能性があります。
    • 並べ替えのループは、通常、内側のループの条件を j < 4 (または j < 配列のサイズ - 1)とすることで、j+1 が配列の範囲内に収まるようにします。
    • また、合計点と学籍番号を一緒に並べ替えるとき、元の学生のデータと紐づけるために、学籍番号も同様に keep_id を使って入れ替える処理は正しいのですが、並べ替えの対象となる sumID の配列が、元の seiseki 配列の順序と対応しているか、少し注意が必要です。
  • ファイル出力について:

    • ファイルポインタ fpNULL でないかチェックしてから fprintf を呼び出しているのは良いですね!
    • ただ、ファイルに出力するループ for (i = 0; i < 5; i++) の中で、fprintf(fp, "学籍番号%d=%d\n",seiseki[i].gaksueki_number, sum[i]); となっています。ここで sum[i] を使っていますが、この sum 配列は並べ替えによって順序が変わっています。もし、並べ替え後の合計点と、元の学生の学籍番号を紐づけて出力したい場合は、並べ替えの際に学籍番号も一緒に管理し、その並べ替えられた学籍番号と合計点を出力する必要があります。

例えば、並べ替えのロジックを少し修正して、元の学生の学籍番号と合計点をセットで管理しながら並べ替える方法もありますよ!

もしよろしければ、このコードをどのように改善したいか、どんな結果を期待しているか教えていただけますか? 一緒に、もっと素敵なプログラムにしていきましょう!✨

おねがい

2025/12/06 12:34

「おねがい」とのこと、承知いたしました!😊

先ほどのコードについて、具体的にどのように改善したいか、あるいはどのような結果を期待されているか、もう少し詳しく教えていただけますか? 例えば、

  • 合計点の並べ替えを正しく行いたい
  • 並べ替えられた結果を、元の学生の学籍番号と紐づけてファイルに出力したい
  • コードの他の部分も修正したい

など、ご希望を教えていただけると、より的確なアドバイスができます!一緒にコードをより良くしていきましょう!✨

並べ替えられた結果を、元の学生の学籍番号と紐づけてファイルに出力したい

2025/12/06 12:35

並べ替えられた結果を、元の学生の学籍番号と紐づけてファイルに出力したい、というご要望ですね!承知いたしました。

現在のコードでは、合計点 (sum) と学籍番号 (ID) を別々に並べ替えているため、並べ替え後に sum[i]seiseki[i].gaksueki_number を組み合わせると、意図しない結果になってしまう可能性があります。

これを解決するために、以下の2つの方法が考えられます。

1. 構造体配列ごと並べ替える方法

一番シンプルで分かりやすいのは、学生の成績データ全体を格納している seiseki 配列自体を、合計点の値に基づいて並べ替える方法です。

/*
構造化を用いてテスト点数を処理して出力
作成者:寺田凱斗
学生番号:251205120
作成日:12月3日
*/

#include <stdio.h>

struct SEISEKI_DATA {
    int japanese;
    int math;
    int science;
    int society;
    int gaksueki_number;
    int total_score; // 合計点を格納するフィールドを追加
};

int main(void) {
    struct SEISEKI_DATA seiseki[5] = {
        {90, 60, 80, 60, 1},
        {100, 25, 80, 60, 2},
        {65, 55, 80, 80, 3},
        {45, 80, 60, 100, 4},
        {100, 100, 100, 100, 5}
    };

    int i, j;
    struct SEISEKI_DATA temp_seiseki; // 並べ替え用の一時変数

    // 1. 各学生の合計点を計算し、構造体に格納する
    for (i = 0; i < 5; i++) {
        seiseki[i].total_score = seiseki[i].japanese + seiseki[i].math + seiseki[i].science + seiseki[i].society;
    }

    // 2. 合計点の高い順に構造体配列を並べ替える(バブルソート)
    for (i = 0; i < 5; i++) {
        for (j = 0; j < 4; j++) { // j < 4 とすることで、j+1 が配列の範囲内に収まるようにする
            // 現在の学生の合計点と次の学生の合計点を比較
            if (seiseki[j].total_score < seiseki[j + 1].total_score) {
                // 合計点が高い方を前に持ってくるため、入れ替えを行う
                temp_seiseki = seiseki[j];
                seiseki[j] = seiseki[j + 1];
                seiseki[j + 1] = temp_seiseki;
            }
        }
    }

    // 3. ファイルに出力する
    FILE *fp;
    fp = fopen("5-4-result.txt", "w");

    if (fp == NULL) {
        perror("ファイルを開けませんでした"); // エラーメッセージを表示
        return 1; // エラー終了
    }

    printf("ファイルに書き込みます...\n");
    for (i = 0; i < 5; i++) {
        // 並べ替えられたseiseki配列の順序で、学籍番号と合計点を出力する
        fprintf(fp, "学籍番号%d=%d\n", seiseki[i].gaksueki_number, seiseki[i].total_score);
        printf("学籍番号%d=%d\n", seiseki[i].gaksueki_number, seiseki[i].total_score); // コンソールにも表示
    }

    fclose(fp); // ファイルを閉じる
    printf("ファイルへの書き込みが完了しました。\n");

    return 0; // 正常終了
}

変更点とポイント:

  • SEISEKI_DATA 構造体に total_score というフィールドを追加し、各学生の合計点を直接格納するようにしました。
  • 並べ替えの際に、sumID の配列を別々に扱うのではなく、seiseki 配列の要素(構造体全体)を temp_seiseki を使って入れ替えるようにしました。これにより、学籍番号と合計点が常にペアになったまま並べ替えられます。
  • 並べ替えのループ条件を j < 4 に修正し、配列の範囲外アクセスを防ぎました。
  • ファイル出力の際、並べ替え済みの seiseki[i].gaksueki_numberseiseki[i].total_score をそのまま使用しています。
  • ファイルオープン時のエラーチェックと、ファイルクローズ処理を追加しました。
  • 処理の確認のために、コンソールにも結果を表示するようにしました。

2. 学生データと合計点をペアにした配列で管理する方法

もし、元の seiseki 構造体を直接変更したくない場合は、学生の学籍番号と合計点をペアにした新しい構造体や配列を作成し、それを並べ替える方法もあります。

/*
構造化を用いてテスト点数を処理して出力
作成者:寺田凱斗
学生番号:251205120
作成日:12月3日
*/

#include <stdio.h>

struct SEISEKI_DATA {
    int japanese;
    int math;
    int science;
    int society;
    int gaksueki_number;
};

// 並べ替えのために、学籍番号と合計点をペアにする構造体
struct SORTED_SCORE {
    int gaksueki_number;
    int total_score;
};

int main(void) {
    struct SEISEKI_DATA seiseki[5] = {
        {90, 60, 80, 60, 1},
        {100, 25, 80, 60, 2},
        {65, 55, 80, 80, 3},
        {45, 80, 60, 100, 4},
        {100, 100, 100, 100, 5}
    };

    struct SORTED_SCORE sorted_scores[5]; // 並べ替え用の配列
    int i, j;
    struct SORTED_SCORE temp_score; // 並べ替え用の一時変数

    // 1. 各学生の合計点を計算し、sorted_scores 配列に格納する
    for (i = 0; i < 5; i++) {
        sorted_scores[i].gaksueki_number = seiseki[i].gaksueki_number;
        sorted_scores[i].total_score = seiseki[i].japanese + seiseki[i].math + seiseki[i].science + seiseki[i].society;
    }

    // 2. 合計点の高い順に sorted_scores 配列を並べ替える(バブルソート)
    for (i = 0; i < 5; i++) {
        for (j = 0; j < 4; j++) { // j < 4 とすることで、j+1 が配列の範囲内に収まるようにする
            // 現在の学生の合計点と次の学生の合計点を比較
            if (sorted_scores[j].total_score < sorted_scores[j + 1].total_score) {
                // 合計点が高い方を前に持ってくるため、入れ替えを行う
                temp_score = sorted_scores[j];
                sorted_scores[j] = sorted_scores[j + 1];
                sorted_scores[j + 1] = temp_score;
            }
        }
    }

    // 3. ファイルに出力する
    FILE *fp;
    fp = fopen("5-4-result.txt", "w");

    if (fp == NULL) {
        perror("ファイルを開けませんでした"); // エラーメッセージを表示
        return 1; // エラー終了
    }

    printf("ファイルに書き込みます...\n");
    for (i = 0; i < 5; i++) {
        // 並べ替えられた sorted_scores 配列の順序で、学籍番号と合計点を出力する
        fprintf(fp, "学籍番号%d=%d\n", sorted_scores[i].gaksueki_number, sorted_scores[i].total_score);
        printf("学籍番号%d=%d\n", sorted_scores[i].gaksueki_number, sorted_scores[i].total_score); // コンソールにも表示
    }

    fclose(fp); // ファイルを閉じる
    printf("ファイルへの書き込みが完了しました。\n");

    return 0; // 正常終了
}

どちらの方法でも、期待通りの結果が得られるはずです。

  • 次のステップとして:
    • このコードを実際にコンパイルして実行し、"5-4-result.txt" ファイルの内容を確認してみてください。
    • もし、成績の低い順に並べ替えたい場合は、比較条件 seiseki[j].total_score < seiseki[j + 1].total_scoreseiseki[j].total_score > seiseki[j + 1].total_score に変更してみてください。
    • 学生の人数が固定(5人)ではなく、可変になった場合に対応するにはどうすれば良いか、考えてみるのも面白いですよ!

/
構造化を用いてテスト点数を処理して出力
作成者:寺田凱斗
学生番号:251205120
作成日:12月3日
/

include

struct SEISEKI_DATA {
int japanese;
int math;
int science;
int society;
int gaksueki_number;
} seiseki[5] =
{
{90,60,80,60,1},
{100,25,80,60,2},
{65,55,80,80,3},
{45,80,60,100,4},
{100,100,100,100,5}
};

int main(void) {

int i,j,keep_sum,keep_id;
int sum[5];;
int ID[5] = { 1,2,3,4,5 };
FILE* fp;

for (i = 0; i < 5; i++) {
    sum[i] = seiseki[i].japanese + seiseki[i].math + seiseki[i].science + seiseki[i].society;
    ID[i] = seiseki[i].gaksueki_number;
}

for (i = 0; i < 5; i++) {
    for (j = 0; j < 4; j++) {
        if (sum[j] < sum[ j + 1]) {
            keep_sum = sum[ j ];     //
            sum[j] = sum[ j + 1];
            sum[j + 1] = keep_sum;

            keep_id = ID[j];
            ID[j] = ID[j + 1];
            ID[j + 1] = keep_id;
        }
    }
}
fp = fopen("5-4-result.txt", "w");

for (i = 0; i < 5; i++) {
    if (fp != NULL) {
        fprintf(fp, "学籍番号%d=%d\n",keep_id[i], sum[i]);
    }
    else {
        printf("出力時にファイルを開けませんでした。")
    }
}

}

2025/12/06 12:37

今回のコード修正についてですね!ありがとうございます!✨

概要

以前のコードから、合計点の並べ替え順序を昇順(小さい順)から降順(大きい順)に変更し、配列の範囲外アクセスを防ぐための修正、そしてファイル出力部分の修正を行っていますね。

詳細説明

今回の修正点について、具体的に見ていきましょう!

  • 並べ替え順序の変更:

    • if (sum[j] < sum[j + 1]) という条件に変更されたことで、合計点の高い順(降順)に並べ替えられるようになりました。これは、一般的に成績を評価する際に合計点が高い方が良いとされるため、意図した動作になるかと思います。👍
  • 配列の範囲外アクセス防止:

    • 内側のループの条件が for (j = 0; j < 4; j++) となりました。これにより、j + 1 が配列の最大インデックス(この場合は4)を超えないようになり、配列の範囲外アクセスによるエラーを防ぐことができます。これは非常に重要な修正です!👏
  • 学籍番号の並べ替え:

    • ID 配列も sum 配列と同様に keep_id を使って入れ替える処理はそのまま維持されています。これにより、合計点と対応する学籍番号が正しく紐づいたまま並べ替えられます。
  • ファイル出力部分の修正:

    • fprintf(fp, "学籍番号%d=%d\n",keep_id[i], sum[i]); の部分で、keep_id[i] となっていますが、keep_id は一時的な値を保持する変数なので、配列のように [i] をつけてアクセスすることはできません。並べ替えられた学籍番号は ID 配列に格納されているため、fprintf(fp, "学籍番号%d=%d\n", ID[i], sum[i]); のように修正する必要があります。
    • エラー処理の printf("出力時にファイルを開けませんでした。") の行末にセミコロン ; が抜けています。こちらも追加が必要です。

まとめと提案

今回の修正で、テスト点数の合計点を降順に並べ替え、ファイルに出力する処理の基本的な部分は整ってきましたね!ファイル出力時の学籍番号の参照方法と、printf文のセミコロン忘れを修正することで、より意図した通りに動作するようになるはずです。

  • ファイル出力部分の keep_id[i]ID[i] に修正し、printf 文のセミコロン忘れを直してみてください。
  • もしよろしければ、それぞれの科目の点数も考慮したランキング(例えば、平均点や特定の科目の点数で順位をつけるなど)を実装してみるのも面白いかもしれませんね!
  • また、ファイル出力が成功したかどうかのメッセージを printf で表示することも検討できますよ。

このチャットはプライベートです。投稿者のみがメッセージを送信できます。

チャット内容の閲覧は可能です。

AIの回答は正しいとは限りません。また、個人情報などの重要な情報は入力しないでください
0

48 件のコメント

読み込み中...
Your avatar