#include <stdio.h> /* 標準入出力 */
#include <stdlib.h> /* 標準ライブラリー */
#include <math.h> /* 数学的関数 */
#include <string.h> /* 文字列関数 */
#define SEN "--------------------\n" /* マクロ定義 */
#define KEISEN "=====================\n"

/* サブルーチンの宣言 */
void data_write(void); /* データの書き込み */
void data_read(void); /* データの読み込み */
void data_disp(void); /* 成績一覧表の表示 */
void data_kensk(void); /* 検索処理 */
void data_input(void); /* 入力処理 */
void the_end(void); /* プログラムの終了処理 */

/* 変数, 構造体の宣言 */
struct seiseki {
  char simei[20]; /* 氏名 */
  int bango, kokugo, eigo, suugaku; /* 番号, 国語, 英語, 数学 */
};
struct seiseki a[100]; /* 登録数は100名まで */
int n, i, goukei; /* 変数の定義 */

double heikin, std;
FILE *fp;
char filename[] = "student.dat";

int main()
{
  int k; /* switch-case用の処理番号 */
  do { /* 繰り返し処理do-while */
    /* 初期メニュー画面 */
    printf("\n");
    printf("☆☆　成績処理メニュー　☆☆\n");
    printf(SEN);
    printf("データの書き込み・・・・・・・・・【1】\n");
    printf("データの読み込み・・・・・・・・・【2】\n");
    printf("成績一覧表・・・・・・・・・・・・【3】\n");
    printf("検索処理・・・・・・・・・・・・・【4】\n");
    printf("入力処理・・・・・・・・・・・・・【5】\n");
    printf("終わり・・・・・・・・・・・・・・【9】\n");
    printf(SEN);
    printf("処理番号を入力してください：");
    scanf("%d", &k);
    printf("\n");

    /* 関数の呼び出し */
    switch (k) {
    case 1:
      data_write();
      break;
    case 2:
      data_read();
      break;
    case 3:
      data_disp();
      break;
    case 4:
      data_kensk();
      break;
    case 5:
      data_input();
      break;
    case 9:
      the_end();
      break;
    default:
      printf("該当番号なし\n");
      break;
    }
  } while (k < 10);
  return 0;
}
/* データの書き込み */
void data_write(void)
{
  fp = fopen(filename, "w");
  for ( i = 0; i < n; ++i) {
    fprintf(fp, "%s %d %d %d %d\n", a[i].simei, a[i].bango, a[i].kokugo, a[i].eigo, a[i].suugaku);
  }
  fclose(fp);
}

/* データの読み込み */
void data_read(void)
{
  char buf[100];
  int i;
  fp = fopen(filename, "r");
  n = 0;
  for (i = 0; fgets(buf, 100, fp) != NULL; ++i) {
    sscanf(buf, "%s %d %d %d %d", a[i].simei, &a[i].bango, &a[i].kokugo, &a[i].eigo, &a[i].suugaku);
    ++n;
  }
}

/* 成績一覧表の表示 */
void data_disp(void)
{
  int goukei_k = 0, goukei_e = 0, goukei_s = 0;
  double heikin_k = 0.0, heikin_e = 0.0, heikin_s = 0.0;
  double std_k = 0.0, std_e = 0.0, std_s = 0.0;
  printf("☆☆☆　成績一覧表　☆☆☆\n");
  printf(KEISEN);
  printf("番号　名前　　　　　国語　英語　数学　合計　平均\n");
  for (i = 0; a[i].bango; i++) {
    printf("%5d %-10s %5d %5d %5d", a[i].bango, a[i].simei, a[i].kokugo, a[i].eigo, a[i].suugaku);
    /* 3科目の合計計算 */
    goukei = (a[i].kokugo + a[i].eigo + a[i].suugaku);
    printf("%7d", goukei);
    /* キャスト：3科目の平均計算 */
    heikin = (double)goukei / 3;
    printf("%6.1f\n", heikin);
    /* 各科目の合計計算 */
    goukei_k += a[i].kokugo;
    goukei_e += a[i].eigo;
    goukei_s += a[i].suugaku;
  }
  printf("\n");

  /* 各科目の平均計算 */
  heikin_k = (double)goukei_k / n;
  heikin_e = (double)goukei_e / n;
  heikin_s = (double)goukei_s / n;
  printf("平均               %5.1f %5.1f %5.1f\n", heikin_k, heikin_e, heikin_s);

  /* 偏差の二乗和の計算 */
  for (i = 0; i < n; i++) {
    std_k += pow((a[i].kokugo - heikin_k), 2);
    std_e += pow((a[i].eigo - heikin_e), 2);
    std_s += pow((a[i].suugaku - heikin_s), 2);
  }

  /* 標準偏差の計算 */
  std_k = sqrt(std_k / n);
  std_e = sqrt(std_e / n);
  std_s = sqrt(std_s / n);
  printf("標準偏差           %5.1f %5.1f %5.1f\n", std_k, std_e, std_s);
}

/* 検索処理 */
void data_kensk(void)
{
  char s[100];
  printf("検索する氏名 = ");
  scanf("%s", s);
  printf("番号　名前　　　　　国語　英語　数学　合計　平均\n");
  for ( i = 0; a[i].bango; ++i)
    if (strstr(a[i].simei, s)) {
      printf("%5d %-10s %5d %5d %5d", a[i].bango, a[i].simei, a[i].kokugo, a[i].eigo, a[i].suugaku);
      /* 3科目の合計計算 */
      goukei = (a[i].kokugo + a[i].eigo + a[i].suugaku);
      printf("%7d", goukei);
      /* キャスト：3科目の平均計算 */
      heikin = (double)goukei / 3;
      printf("%6.1f\n", heikin);
    }
  printf("\n");
}

/* 入力処理 */
void data_input(void)
{
  struct seiseki *p;
  for (p = a; p->bango; ++p);
  printf("番号 = " );
  scanf("%d", &p->bango);
  printf("氏名 = ");
  scanf("%s", p->simei);
  printf(" 国語 = ");
  scanf("%d", &p->kokugo);
  printf(" 英語 = ");
  scanf("%d", &p->eigo);
  printf(" 数学 = ");
  scanf("%d", &p->suugaku);
  ++n;
}

/* プログラムの終了処理 */
void the_end(void)
{
  exit(0);
}
