次の (1), (2), (3) に指定されたとおりにプログラムを作れ.
(1) 国語,数学,英語の3科目の成績を一人分だけまとめた構造体(整数型メンバ kokugo, sugaku, eigo を持つ)を作り,それをseiseki_t という名前の型として定義せよ.
(2) seiseki_t 型の引数を1つとり,その3科目の平均点を返す関数
double heikinten(seiseki_t s) を作れ.
(3) 3科目の成績を5人分キーボードから入力し,それを seiseki_t s[5] という配列に入れる.それらの中で,平均点が60点以上の人の3科目の成績を表示する.以上のことをするプログラムを作れ.
実行例
50 50 70 20 80 90 80 70 50 60 60 70 30 80 50
20 80 90
80 70 50
60 60 70
#include <stdio.h> #define NUM 5 typedef struct { int kokugo; int sugaku; int eigo; } seiseki_t; double heikinten(seiseki_t s) { return (s.kokugo + s.sugaku + s.eigo) / 3.0; } int main() { seiseki_t s[NUM]; int i; for ( i = 0; i < NUM; i++ ) { scanf("%d%d%d", &s[i].kokugo, &s[i].sugaku, &s[i].eigo); } for ( i = 0; i < NUM; i++ ) { if ( heikinten(s[i]) >= 60 ) { printf("%d %d %d\n", s[i].kokugo, s[i].sugaku, s[i].eigo); } } return 0; }
注意する点は、関数 heikinten 中の部分を (s.kokugo + s.sugaku + s.eigo) / 3 という式にすると 整数/整数となり、結果が整数値(小数点以下切り捨て)になってしまうことである.浮動小数点で計算を 行わせるため、 / 3.0 とする必要がある.
次の (1), (2), (3) に指定されたとおりにプログラムを作れ.
(1) 3次元ベクトルを表す構造体(3つの成分を表す double 型のメンバ x, y, z をもっている)を作り、それを vector_t という型名として定義せよ。
(2) vector_t 型の引数を1つとり,それが表すベクトルの長さ(大きさ)を返す関数
double vector_length(vector_t v)
を作れ。(ベクトルの長さは成分の2乗の和の平方根)
(3) 3次元ベクトル5個分の成分(15個の実数値)をキーボードから入力し,それらを vector_t v[5] という配列に入れる.それらの中で,長さが 10 を超えるものだけを表示する.以上のことをするプログラムを作れ.(ヒント: scanf を用いて double 型の数値を読み込むための書式文字列は "%lf" である.)
実行例
5.0 -4.0 7.0 -3.0 7.0 8.0 2.0 7.0 3.0 4.0 0.0 -4.0 9.0 -3.0 6.0
-3.0 7.0 8.0
9.0 -3.0 6.0
#include <stdio.h> #include <math.h> #define NUM 5 typedef struct { double x; double y; double z; } vector_t; double vector_length(vector_t v) { return sqrt( v.x * v.x + v.y * v.y + v.z * v.z ); } int main() { vector_t v[NUM]; int i; for ( i = 0 ; i < NUM; i++ ) { scanf("%lf%lf%lf", &v[i].x, &v[i].y, &v[i].z); } for ( i = 0; i < NUM; i++ ) { if ( vector_length(v[i]) > 10 ) { printf("%f %f %f\n", v[i].x, v[i].y, v[i].z); } } return 0; }
数学関数 sqrt を用いているので,プログラム先頭でヘッダファイル math.h を読み込み, さらに,コンパイル時に -lm のリンクオプションを付けてコンパイルする必要がある.
文字列 s 中の文字 c の個数を返す関数
int count_char(char s[], char c)
を作り,それを用いたプログラムを一つ作成せよ.
例: count_char(“abcdeabc”, 'b') の返す値は 2
#include <stdio.h> int count_char(char s[], char c) { int i, n = 0; for (i = 0; s[i] != '\0'; i++) { if (s[i] == c) { n++; } } return n; } int main() { int n; n = count_char("abcdeabc", 'b'); printf("%d\n", n); }
文字列 s 中にある文字 c の場所をその添字で返す関数
int position(char s[], char c)
を作り,それを用いたプログラムを一つ作成せよ.ただし,s 中に c が複数個あるときには最初のもの(添字が一番小さいもの)の添字を,また c がないときには -1 を返すものとする.
例 position(“abcdabc”, 'b') が返す値は 1
#include <stdio.h> int position(char s[], char c) { int i, n = 0; for (i = 0; s[i] != '\0'; i++) { if (s[i] == c) { return i; } } return -1; } int main() { int p; p = position("abcdeabc", 'b'); printf("%d\n", p); }
cos(1.0), cos(2.0), ..., cos(10.0) の10個の数値の中で最大の値のものを表示するプログラムを作れ.
#include <stdio.h> #include <math.h> int main() { double x, max; max = cos(1.0); for ( x = 2.0; x <= 10.0; x += 1.0) { if ( max < cos(x) ) max = cos(x); } printf("%f\n", max); return 0; }
sin(1.0), sin(2.0), ..., sin(10.0) の10個の数値の中で最大の値のものを表示するプログラムを作れ.
#include <stdio.h> #include <math.h> int main() { double x, max; max = sin(1.0); for ( x = 2.0; x <= 10.0; x += 1.0) { if ( max < sin(x) ) max = sin(x); } printf("%f\n", max); return 0; }
1以上13以下の整数値を5個キーボードから読み込み,それがポーカーのどの役にあたっているかを判別して,”no pair”, "one pair”, “two pair”, “three card”, “four card”, “full house”, “straight” のいずれかを表示する.これを繰り返すプログラムを作れ.ただし,範囲外の数値が入力されると終了するものとする.(注意: 10, 11, 12, 13, 1 はストレートであるが, 11, 12, 13, 1, 2 や 12, 13, 1, 2, 3 や 13, 1, 2, 3, 4はストレートではない.フルハウスはワンペアとスリーカードとが合わさったものである.)
実行例
7 4 3 1 10
no pair
3 5 8 5 11
one pair
4 8 6 4 8
two pair
8 7 5 7 7
three card
7 2 7 7 7
four card
4 9 4 9 9
full house
7 4 8 5 6
straight
0 0 0 0 0
問題に不備があったので次の一文を追加する.入力された 5 個の整数値がすべて同じ数値であるときには,そのまま終了する.(ファイブカードはない)
次のプログラムは,読み込んだ数値 card[0], ..., card[4] の値の中に,j という値が何個あるかを数えて cnt[j] に入れることから始める.
この配列を用いることで,役の判断が簡単になる.たとえば,読み込んだ値が 6, 3, 6, 6, 7 の場合, cnt[] の値は次のようになり,その役がスリーカードであることが分かる.
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
0 | 0 | 0 | 1 | 0 | 0 | 3 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
#include <stdio.h> int main() { int card[5]; /* 読み込んだ値が入る */ int cnt[14]; /* 読み込んだ値で 1, 2, 3, ..., 13 に等しいものの個数が入る */ int i; /* card[i] の添字 */ int j; /* cnt[j] の添字 */ int max1, max2; /* cnt[] の要素の値の最大値と2番目の最大値 */ int p; /* cnt[13], cnt[12], ... の中で値 1 であるものの最初(最大)の添字 */ int q; /* cnt[p-1], cnt[p-2], ... の中で値が 0 であるものの最初(最大)の添字 */ while (1) { for (i = 0; i < 5; i++) { scanf("%d", &card[i]); /* 整数値の読み込み */ } for (i = 0; i < 5; i++) { if (card[i] < 1 || 13 < card[i]) return 0; /* 値が範囲外のときは終了 */ } for (j = 0; j <= 13; j++) { cnt[j] = 0; /* cnt[] をすべて 0 に初期化( cnt[0] は q を求めるときの番兵となる) */ } for (i = 0; i < 5; i++) { cnt[card[i]] ++; /* card[0], ..., card[4] の値の中に,j という値が何個あるかを数えて cnt[j] に入れる */ } max1 = max2 = 0; for (j = 1; j <= 13; j++) { if (max1 < cnt[j]) { /* cnt[j] が最大値よりも大きいときは */ max2 = max1; /* 最大値が2番目の最大値になる */ max1 = cnt[j]; /* 最大値がcnt[j] になる */ } else if (max2 < cnt[j]) { /* そうじゃなくて,2番目の最大値よりも大きいときは */ max2 = cnt[j]; /* 2番目の最大値がcnt[j]になる */ } } /* max1には同じカードの最大枚数,max2にはその次の最大枚数が入る. */ switch (max1) { /* 同一カードの最大枚数が */ case 5: /* 5のときには */ return 0; /* 終了(ファイブカードは考慮しない)*/ case 4: /* 4のときには */ printf("four card\n"); /* フォーカード */ break; case 3: /* 3のときには */ if (max2 == 2) { /* 2番目の最大枚数が 2 ならば */ printf("full house\n"); /* フルハウス */ } else { /* そうでなければ */ printf("three card\n"); /* スリーカード */ } break; case 2: /* 2のときには */ if (max2 == 2) { /* 2番目の最大枚数が 2 ならば */ printf("two pair\n"); /* ツーペア */ } else { /* そうでなければ */ printf("one pair\n"); /* ワンペア */ } break; case 1: /* 1のときには */ for (p = 13; cnt[p] == 0; p--) ; /* cnt[13], cnt[12], ... の中で最初に 1 であるものを探す */ for (q = p; cnt[q] == 1; q--) ; /* cnt[p], cnt[p-1], ... の中で最初に 0 であるものを探す(cnt[0] == 0 であるから,これが番兵となってこの for 文は必ず止まる */ if (p - q == 5 || (p == 13 && q == 9 && cnt[1] == 1)) { /* ストレートである条件 */ printf("straight\n"); } else { printf("no pair\n"); } break; } } }