第15回:復習

 今週は,1年間かけて学習してきたC言語によるプログラミングの総復習を行います.


前期に学習した内容をまとめると

これらについて,復習をかねて,もう一度前期の期末試験の問題を,何も見ないで解いてみよう.


後期に学習した内容をまとめると


【演習のこたえ】

偏差値を求めるプログラム

#include <stdio.h>
#include <math.h>

void main()
{
    int i;
    int data[100];
    float sum, sum2, ave, sigma;
    FILE *fp;

    fp = fopen("testdata.txt", "r");
    if(fp == NULL) return;

    sum = 0;
    sum2 = 0;

    for(i = 0; i<100; i++){
        fscanf(fp, "%d", &(data[i]));
        sum += data[i];
        sum2 += data[i] * data[i];
    }

    fclose(fp);

    ave = sum / 100.0;
    sigma = sqrt((100*sum2 - (sum*sum))/100/(100-1));

    printf("平均値=%f\n", ave);
    printf("標準偏差=%f\n", sigma);

    for(i =0; i<100; i++){
        printf("%d, %f\n", i, (data[i] - ave)/sigma*10+50;
    }
}

成績順に並べ替えるプログラム

#include <stdio.h>
#include <math.h>

void swap(float *a, float *b)
{
     float t;

     t = *a;
     *a = *b;
     *b = t;
}

void sort(int n, float *s)
{
     int i, j;

    for(i=0; i < n-1; i++){
        for(j=i+1; j < n; j++){
            if(s[i] > s[j]){
                  swap(&(s[i]), &(s[j]));
            }
        }
    }
}

void main()
{
    int i, j;
    int data[100]
    float dev[100];
    float sum, sum2, ave, sigma;
    FILE *fp;

    fp = fopen("testdata.txt", "r");
    if(fp == NULL) return;

    sum = 0;
    sum2 = 0;

    for(i = 0; i<100; i++){
        fscanf(fp, "%d", &(data[i]));
        sum += data[i];
        sum2 += data[i] * data[i];
    }

    fclose(fp);

    ave = sum / 100.0;
    sigma = sqrt((100*sum2 - (sum*sum))/100/(100-1));

    printf("平均値=%f\n", ave);
    printf("標準偏差=%f\n", sigma);

    for(i =0; i<100; i++){
        dev[i] = (data[i] - ave)/sigma*10+50;
    }

    sort(100, dev);

    for(i=0; i<100; i++){
        printf("%d, %f\n", i, dev[i]);
    }
}

データ数のわからない場合のプログラム

この場合は,上のプログラムのうちファイルを読み込む部分を下のように変える.

void main() 
{
    int i, j, n;

    fp = fopen("testdata.txt", "r");
    if(fp == NULL) return;


    for(i = 0; !(feof(fp)); i++){
        fscanf(fp, "%d", &(data[i]));
    }

    n = i;

    fclose(fp);  


構造体の演習の復習

 下記の成績データをファイルから読み込んで,各学生の2回のテストの平均点を計算し,成績を判定するプログラムを,構造体を用いて作成せよ.

2 1 1 アベ 50 60
2 1 2 イトウ 70 45
2 1 3 ウエダ 90 53
2 1 4 エンドウ 75 65
2 1 5 オカダ 30 15
2 1 6 カトウ 90 76
2 1 7 キダ 80 56
2 1 8 クリタ 86 95

成績対応表
A
80点以上
B
60点以上
C
50点以上
F
50点未満
ステップ1
まずは,構造体を使わずに,データを読み込んで画面に表示するだけのプログラムを作ってみる.
ステップ2
変数を構造体を用いるように変更する.
ステップ3
構造体の配列を用いる
ステップ4
平均点を求める部分を関数にし,メイン関数から引数として構造体ポインタを用いて渡し,平均点を計算して構造体の平均に代入するようにする.

まずは,構造体を使わないでやってみると...

#include <stdio.h>

float ave(int ten_1, int ten_2)
{
    return((ten_1 + ten_2 )/2.0);  
}

void main()
{
    int i, n=8;
    int gakunen;
    int kumi;
    int bangou;
    char simei[25];
    int ten_1;
    int ten_2;
    float heikin;
    char hantei;

    FILE *fp;

    fp = fopen("seiseki.txt", "r");
    if(fp == NULL) return;

   for(i=0; i<n; i++){
        fscanf(fp, "%d %d %d %s %d %d", &gakunen, 
                                        &kumi,
                                        &bangou,
                                        simei,
                                        &ten_1,
                                        &ten_2);
        heikin = ave(ten_1, ten_2);

        if(heikin>=80){
            hantei = 'A';
        }else if(heikin>=60){
            hantei = 'B';
        }else if(heikin>=50){
            hantei = 'C';
        }else{
            hantei = 'F';
        }

        printf("%d %d %d %8s %d %d %.1f %c\n", gakunen,
                                              kumi,
                                              bangou,
                                              simei,
                                              ten_1,
                                              ten_2,
                                              heikin,
                                              hantei);
    }

    fclose(fp);
}

では,構造体を使ってみると...

#include <stdio.h>

struct seiseki{
    int gakunen;
    int kumi;
    int bangou;
    char simei[25];
    int ten_1;
    int ten_2;
    float heikin;
    char hantei;
};

void ave(struct seiseki *list)
{
    list->heikin = (list->ten_1 + list->ten_2 )/2.0;  
}

void main()
{
    int i, n=8;
    struct seiseki list2;
    FILE *fp;

    fp = fopen("seiseki.txt", "r");
    if(fp == NULL) return;

   for(i=0; i<n; i++){
        fscanf(fp, "%d %d %d %s %d %d", &list2.gakunen, 
                                        &list2.kumi,
                                        &list2.bangou,
                                        list2.simei,
                                        &list2.ten_1,
                                        &list2.ten_2);
        ave(&list2);

        if(list2.heikin>=80){
            list2.hantei = 'A';
        }else if(list2.heikin>=60){
            list2.hantei = 'B';
        }else if(list2.heikin>=50){
            list2.hantei = 'C';
        }else{
            list2.hantei = 'F';
        }

        printf("%d %d %d %s %d %d %.1f %c\n", list2.gakunen,
                                              list2.kumi,
                                              list2.bangou,
                                              list2.simei,
                                              list2.ten_1,
                                              list2.ten_2,
                                              list2.heikin,
                                              list2.hantei);
    }

    fclose(fp);
}

次に,構造体の配列を使ってデータをいっぺんに読み込んでから処理してみよう.

#include <stdio.h>

struct seiseki{
    int gakunen;
    int kumi;
    int bangou;
    char simei[25];
    int ten_1;
    int ten_2;
    float heikin;
    char hantei;
};

void hantei(struct seiseki *list)
{
    if(list2->heikin>=80){
        list2->hantei = 'A';
    }else if(list2->heikin>=60){
        list2->hantei = 'B';
    }else if(list2->heikin>=50){
        list2->hantei = 'C';
    }else{
        list2->hantei = 'F';
    }  
}

void ave(struct seiseki *list)
{
        list->heikin = (list->ten_1 + list->ten_2 )/2.0;  
}

void main()
{
    int i, n;
    struct seiseki list2[10];
    FILE *fp;

    fp = fopen("seiseki.txt", "r");
    if(fp == NULL) return;

   for(i=0; !feof(fp); i++){
        fscanf(fp, "%d %d %d %s %d %d", &list2[i].gakunen, 
                                        &list2[i].kumi,
                                        &list2[i].bangou,
                                        list2[i].simei,
                                        &list2[i].ten_1,
                                        &list2[i].ten_2);
        ave(&list2[i]);
        hantei(&list2[i]);

        printf("%d %d %d %s %d %d %.1f %c\n",
                                        list2[i].gakunen,
                                        list2[i].kumi,
                                        list2[i].bangou,
                                        list2[i].simei,
                                        list2[i].ten_1,
                                        list2[i].ten_2,
                                        list2[i].heikin,
                                        list2[i].hantei);
    } 

    fclose(fp);

}

期末試験について

時間割り

1月28日(水) 2時限 0406教室

持ち込みは,一切不可です.

試験範囲は,前後期合わせて情報処理・演習で取り上げた内容すべてです.

これらの点を中心に,これまで演習で作ったプログラムをよく復習しておいてください.


【参考】去年の期末試験の問題です.

問題1 1から100までの間の,奇数の和を求めるプログラムを作成せよ.

問題2 100人の試験結果のデータ(100点満点で正の整数)を読み込んで,順位をつけるプログラムを作りたい.この作業を次のステップで進めていこう.

 ファイル名”test.dat"

 データの例:

  58
  96
  43

まず,全体の流れに基づき,メイン関数を用意した.

#include <stdio.h>
void main()
{
    int n=100; /*データの数*/
    int point[100]; /*試験結果のデータを格納する配列*/
    int order[100]; /*順位を格納する配列*/
    yomikomi(n, point);
    juni(n, point, order);
    kakidashi(n, order);
}

[1] test.datファイルの内容を配列に読み込む関数yomikomiを作成せよ.関数への引数は,データの数nと,データを読み込む配列point[]のアドレスとする.

[2] 読み込んだデータから,順位を求める関数juniを作成しよう.

 (1) 順位を求めるアルゴリズムを考え,文章またはフローチャートを用いて説明せよ.

データの例:

要素の番号 0 1 2 3 4 5 6 7 8 9
成績(point) 58 96 43 85 62 38 75 62 73 0
順位(order)

 (2) アルゴリズムに基づき,順位を求める関数juniを作成せよ.関数への引数は,データの数n,点数の配列point[]のアドレス,順位を記入する配列order[]のアドレスとする.

[2’] ([2]が難しくてわからない人へ)読み込んだ成績を成績のよい順に並べ替える関数sortを作成せよ.関数への引数は,データの数n,点数の配列point[]のアドレスとする.