次の (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;
}
}
}