※上記の広告は60日以上更新のないWIKIに表示されています。更新することで広告が下部へ移動します。

<もくじ>

<更新履歴>
※2007/06/24 深夜 作成
※2007/06/25 午後 閲覧権限設定を変更(ログインしないと見れない設定だった)
※2007/06/26 午前 マクロを使わない例を追加
※2007/06/26 午後 サブルーチンを使った例を追加
※2007/06/26 午後 ページのデザインを変更 (Pukiwiki風に)
※2007/06/26 午後 いろいろ変更した例を追加

(1) 名前をひとつの変数に累積保存する例

  • 利点 -- 名前の保存がラク
  • 欠点 -- 名前の表示形式を変える場合がメンドウ
#include <stdio.h>

int main() {
  char buf[100];
  int x;
  int maxval;
  char maxname[1000];
  int minval;
  char minname[1000];

  if ( scanf("%s %d", buf, &x) == EOF ) {
    printf("NO INPUT...\n");
    return 0;
  }

  maxval = minval = x;
  strcpy(maxname, buf);
  strcpy(minname, buf);

  while ( scanf("%s %d", buf, &x) != EOF ) {
    if ( x > maxval ) {
      maxval = x;
      strcpy(maxname, buf);
    } else if ( x == maxval ) {
      strcat(maxname, " ");
      strcat(maxname, buf);
    }

    if ( x < minval ) {
      minval = x;
      strcpy(minname, buf);
    } else if ( x == minval ) {
      strcat(minname, " ");
      strcat(minname, buf);
    }
  } 

  printf("MAX is %d (%s)\n", maxval, maxname);
  printf("MIN is %d (%s)\n", minval, minname);

  return 0;
}

(2) 名前を複数の変数に1つづつ保存する例(ここでは最大3つ)

  • 利点 -- (1) に比べると、名前の表示形式を変えるのがラク
  • 欠点 -- (1) に比べると、名前の保存がメンドウ
#include <stdio.h>

int main() {
  char buf[100];
  int x;
  int maxval;
  int maxnum;
  char maxname1[100];
  char maxname2[100];
  char maxname3[100];
  int minval;
  int minnum;
  char minname1[100];
  char minname2[100];
  char minname3[100];

  if ( scanf("%s %d", buf, &x) == EOF ) {
    printf("NO INPUT...\n");
    return 0;
  }

  maxval = minval = x;
  strcpy(maxname1, buf);
  strcpy(minname1, buf);
  maxnum = minnum = 1;

  while ( scanf("%s %d", buf, &x) != EOF ) {
    if ( x > maxval ) {
      maxval = x;
      strcpy(maxname1, buf);
      maxnum = 1;
    } else if ( x == maxval ) {
      if ( maxnum == 1 ) {
        strcpy(maxname2, buf);
        maxnum = 2;
      } else if ( maxnum == 2 ) {
        strcpy(maxname3, buf);
        maxnum = 3;
      }
      /* 4つ以上は記録しない */
    }

    if ( x < minval ) {
      minval = x;
      strcpy(minname, buf);
      minnum = 1;
    } else if ( x == minval ) {
      if ( minnum == 1 ) {
        strcpy(minname2, buf);
        minnum = 2;
      } else if ( minnum == 2 ) {
        strcpy(minname3, buf);
        minnum = 3;
      }
      /* 4つ以上は記録しない */
    }
  }

  printf("MAX is %d (%s", maxval, maxname1);
  if ( maxnum > 1 ) {
    printf(" %s", maxname2);
  }
  if ( maxnum > 2 ) {
    printf(" %s", maxname3);
  }
  printf(")\n");

  printf("MIN is %d (%s", minval, minname1);
  if ( minnum > 1 ) {
    printf(" %s", minname2);
  }
  if ( minnum > 2 ) {
    printf(" %s", minname3);
  }
  printf(")\n");

  return 0;
}

(3) 上記を配列(変数)を使って書き直した例

  • 利点 -- (2) より少し短く書ける
  • 欠点 -- 配列の知識が必要
#include <stdio.h>

int main() {
  char buf[100];
  int x;
  int maxval;
  int maxnum;
  char maxname[3][100];   /* 配列で定義する */
  int minval;
  int minnum;
  char minname[3][100];   /* 配列で定義する */
  int i;

  if ( scanf("%s %d", buf, &x) == EOF ) {
    printf("NO INPUT...\n");
    return 0;
  }

  maxval = minval = x;
  strcpy(maxname[0], buf);
  strcpy(minname[0], buf);
  maxnum = minnum = 1;

  while ( scanf("%s %d", buf, &x) != EOF ) {
    if ( x > maxval ) {
      maxval = x;
      strcpy(maxname[0], buf);
      maxnum = 1;
    } else if ( x == maxval ) {
      if ( maxnum < 3 ) {
        strcpy(maxname[maxnum], buf);
        maxnum++;
      }
    }

    if ( x < minval ) {
      minval = x;
      strcpy(minname[0], buf);
      minnum = 1;
    } else if ( x == minval ) {
      if ( minnum < 3 ) {
        strcpy(minname[minnum], buf);
        minnum++;
      }
    }
  }

  printf("MAX is %d (", maxval);
  for ( i=0; i<maxnum; i++ ) {
    printf(" %s", maxname[i]);
  }
  printf(" )\n");

  printf("MIN is %d (", minval);
  for ( i=0; i<minnum; i++ ) {
    printf(" %s", minname[i]);
  }
  printf(" )\n");

  return 0;
}

(4) 上記をマクロを使って書き直した例

  • 利点 -- 保存する名前の個数を変更する時に修正がラク
  • 欠点 -- マクロの知識が必要
#include <stdio.h>

/* ↓これを修正すれば「3個まで」という制限を変えられる */
#define LIMIT 3
/* ↑これは「マクロ」と呼ばれるもので、変数とは違う */

int main() {
  char buf[100];
  int x;
  int maxval;
  int maxnum;
  char maxname[LIMIT][100];   /* 配列で定義する */
  int minval;
  int minnum;
  char minname[LIMIT][100];   /* 配列で定義する */
  int i;

  if ( scanf("%s %d", buf, &x) == EOF ) {
    printf("NO INPUT...\n");
    return 0;
  }

  maxval = minval = x;
  strcpy(maxname[0], buf);
  strcpy(minname[0], buf);
  maxnum = minnum = 1;

  while ( scanf("%s %d", buf, &x) != EOF ) {
    if ( x > maxval ) {
      maxval = x;
      strcpy(maxname[0], buf);
      maxnum = 1;
    } else if ( x == maxval ) {
      if ( maxnum < LIMIT ) {
        strcpy(maxname[maxnum], buf);
        maxnum++;
      }
    }

    if ( x < minval ) {
      minval = x;
      strcpy(minname[0], buf);
      minnum = 1;
    } else if ( x == minval ) {
      if ( minnum < LIMIT ) {
        strcpy(minname[minnum], buf);
        minnum++;
      }
    }
  }

  printf("MAX is %d (", maxval);
  for ( i=0; i<maxnum; i++ ) {
    printf(" %s", maxname[i]);
  }
  printf(" )\n");

  printf("MIN is %d (", minval);
  for ( i=0; i<minnum; i++ ) {
    printf(" %s", minname[i]);
  }
  printf(" )\n");

  return 0;
}

(5) 上記をサブルーチン使って書き直した例

  • 利点 -- (4) より少し短くなる
  • 欠点 -- うまく使わないと、全体の処理の流れが分かりにくくなる
#include <stdio.h>

#define LIMIT 3        /* 同値の場合に名前を保存する数 */
#define BUFSIZE 100    /* 文字列を入れる変数のサイズ */

/* ユーザ定義関数(サブルーチン) */
void disp(char title[], int val, int num, char names[][BUFSIZE]) {
  int j;

  printf("%s is %d (", title, val);
  for ( j=0; j<num; j++ ) {
    printf(" %s", names[j]);
  }
  printf(" )\n");
}

/* メイン関数 */
int main() {
  char buf[BUFSIZE];
  int x;
  int maxval;
  int maxnum;
  char maxname[LIMIT][BUFSIZE];
  int minval;
  int minnum;
  char minname[LIMIT][BUFSIZE];
  int i;

  if ( scanf("%s %d", buf, &x) == EOF ) {
    printf("NO INPUT...\n");
    return 0;
  }

  maxval = minval = x;
  strcpy(maxname[0], buf);
  strcpy(minname[0], buf);
  maxnum = minnum = 1;

  while ( scanf("%s %d", buf, &x) != EOF ) {
    if ( x > maxval ) {
      maxval = x;
      strcpy(maxname[0], buf);
      maxnum = 1;
    } else if ( x == maxval ) {
      if ( maxnum < LIMIT ) {
        strcpy(maxname[maxnum], buf);
        maxnum++;
      }
    }

    if ( x < minval ) {
      minval = x;
      strcpy(minname[0], buf);
      minnum = 1;
    } else if ( x == minval ) {
      if ( minnum < LIMIT ) {
        strcpy(minname[minnum], buf);
        minnum++;
      }
    }
  }

  disp("MAX", maxval, maxnum, maxname);    /* 最大を表示 */
  disp("MIN", minval, minnum, minname);    /* 最小を表示 */

  return 0;
}

(6) その他いろいろ変更してみた

  • ポイントは「グローバル変数」を使ったこと
    • グローバル変数は、関数の外で定義した変数のこと
    • ファイル内のどの関数からでも参照/更新ができる
  • 一方、関数内で定義したものを「ローカル変数」と呼ぶ
    • 関数の中でしか参照/更新できない (例外はあるけど説明は省略)
    • なので、別の関数で同じ名前の変数を定義しても、別物として扱われる
  • 入力される点数は 0~100 を想定している
    • できれば入力された点数の範囲チェックはした方がいいけど、ここでは省略
#include <stdio.h>

#define LIMIT 3        /* 同値の場合に名前を保存する数 */
#define BUFSIZE 100    /* 文字列を入れる変数のサイズ */

/* グローバル変数 */
int maxval;
int maxnum;
char maxname[LIMIT][BUFSIZE];
int minval;
int minnum;
char minname[LIMIT][BUFSIZE];

/* 最大値を求める */
void max_proc(char nam[], int val) {
  if ( val < maxval ) return;

  if ( val > maxval ) {
    maxval = val;
    strcpy(maxname[0], nam);
    maxnum = 1;
    return;
  }

  if ( maxnum >= LIMIT ) return;

  strcpy(maxname[maxnum], nam);
  maxnum++;
}

/* 最小値を求める */
void min_proc(char nam[], int val) {
  if ( val > minval ) return;

  if ( val < minval ) {
    minval = val;
    strcpy(minname[0], nam);
    minnum = 1;
    return;
  }

  if ( minnum >= LIMIT ) return;

  strcpy(minname[minnum], nam);
  minnum++;
}

/* 点数と名前を表示する */
void disp(char title[], int val, int num, char names[][BUFSIZE]) {
  int i;

  printf("%s is %d (", title, val);
  for ( i=0; i<num; i++ ) {
    printf(" %s", names[i]);
  }
  printf(" )\n");
}

/* 主処理 */
int main() {
  char buf[BUFSIZE];
  int x;

  maxval = -1;      /* 点数は最小 0点とする */
  minval = 101;     /* 点数は最大 100点とする */

  while ( scanf("%s %d", buf, &x) != EOF ) {
    max_proc(buf, x);
    min_proc(buf, x);
  }

  if ( maxval == -1 ) {
    printf("NO INPUT...\n");
    return 0;
  }

  disp("MAX", maxval, maxnum, maxname);    /* 最大を表示 */
  disp("MIN", minval, minnum, minname);    /* 最小を表示 */

  return 0;
}