演習問題7解答例

問1 関数を使用
5-問1 大人と子供の判断
5-問2 正,負,及び,0 の判断
5-問3 成績の判断
5-問4 時間と分の変換
5-問5 閏年の判定
5-問8 条件付き和の計算
5-問9 個数のカウント
5-問10 直列及び並列の抵抗値
5-問14 複数人の成績の判定とその割合
5-問15 複数人の給与支払いに必要な紙幣の数(ファイル)
5-問17 数字の分離
5-問18 1 であるビット数のカウント
問2 関数を使用
6-問1 ベクトルの絶対値
6-問2 ベクトルの和
6-問3 内積
6-問4 データの入れ替え
6-問5 平均点の人数
6-問6 平面上の点の原点からの距離と点の数
6-問7 成分の割合(ファイル)
6-問10 売り上げの集計
6-問11 末尾の数のチェックとその割合
6-問13 平面上の点間の距離と最大
問3 関数を使用
5-問22 二分法
5-問23 台形則
問4 関数を使用
6-問16 n クラス(各クラス: m 人)の中の平均値と人数(メモリの動的確保)
問5 n 行 m 列の行列の和
問6 英文を構成する文字数と単語数の出力( main 関数の引数)

注:以下の問題において,基本的に,入出力を main 関数で行い,他の処理を別の関数で行うように作成すること.

[問1]演習問題 5 の問 1 から問 18 までを(問 6,7,11,12,13,及び,16 を除く),関数を利用して書け.

[5-問1]年齢を読み込み,20 歳以上なら「大人」,そうでなければ「子供」と出力するプログラムを書け.
/****************************/
/* 大人と子どもの識別       */
/*      coded by Y.Suganuma */
/****************************/
#include <stdio.h>

int handan(int);

int main()
{
	int nenrei, sw;
/*
     年齢の入力
*/
	printf("年齢を入力してください ");
	scanf("%d", &nenrei);
/*
     判断
*/
	sw = handan(nenrei);

	if (sw > 0)
		printf("   大人\n");
	else
		printf("   子供\n");

	return 0;
}

/***************************/
/* 大人か子供の判断        */
/*      nen : 年齢         */
/*      return : =0 : 子供 */
/*               =1 : 大人 */
/***************************/
int handan(int nen)
{
	int sw;
	sw = (nen >= 20) ? 1 : 0;
	return sw;
}
		
[5-問2]一つの整数データを読み込み,その値がゼロなら「 0 」,正なら「正」,それ以外なら「負」と出力するプログラムを,if 文を使用して書け.
/****************************/
/* 正,負,ゼロの識別       */
/*      coded by Y.Suganuma */
/****************************/
#include <stdio.h>

int handan(int);

int main()
{
	int kazu, sw;
/*
     年齢の入力
*/
	printf("数字を入力してください ");
	scanf("%d", &kazu);
/*
     判断
*/
	sw = handan(kazu);

	switch (sw) {
		case 0:
			printf("   0\n");
			break;
		case 1:
			printf("   正\n");
			break;
		default:
			printf("   負\n");
			break;
	}

	return 0;
}

/**************************/
/* 正,負,ゼロの識別     */
/*      kazu : 整数       */
/*      return : =0 : 0  */
/*               =-1 : 負 */
/*               =1 : 正  */
/**************************/
int handan(int kazu)
{
	int sw;

	if (kazu == 0)
		sw = 0;
	else {
		if (kazu > 0)
			sw = 1;
		else
			sw = -1;
	}

	return sw;
}
		
[5-問3]試験の点数を読み込み,その点数が
60 点未満なら「不可」
60 点以上で 70 点未満なら「可」
70 点以上で 80 点未満なら「良」
80 点以上なら「優」
と出力するプログラムを書け
/****************************/
/* 成績の判定               */
/*      coded by Y.Suganuma */
/****************************/
#include <stdio.h>

int handan(int);

int main()
{
	int ten, sw;
/*
      点数の入力
*/
	printf("点数は? ");
	scanf("%d", &ten);
/*
      判定
*/
	sw = handan(ten);

	switch (sw) {
		case 0:
			printf("   不可\n");
			break;
		case 1:
			printf("   可\n");
			break;
		case 2:
			printf("   良\n");
			break;
		default:
			printf("   優\n");
			break;
	}

	return 0;
}

/***************************/
/* 成績の判定              */
/*      ten : 点数         */
/*      return : =0 : 不可 */
/*               =1 : 可   */
/*               =2 : 良   */
/*               =3 : 優   */
/***************************/
int handan(int ten)
{
	int sw;

	if (ten < 60)
		sw = 0;
	else {
		if (ten < 70)
			sw = 1;
		else {
			if (ten < 80)
				sw = 2;
			else
				sw = 3;
		}
	}

	return sw;
}
		
[5-問4]時間と分の変換を行うプログラムを書け.つまり,1 時間 20 分なら 80 分,また,90 分なら 1 時間 30 分に変換する.
/****************************/
/* 時間の変換               */
/*      coded by Y.Suganuma */
/****************************/
#include <stdio.h>

void time_cv(int *, int *, int);

int main()
{
	int time, min, sw;
/*
      変換方法の入力
*/
	printf("変換方法は(0:時間→分, 1:分→時間)? ");
	scanf("%d", &sw);
/*
     データと変換
*/
	if (sw == 0) {
		printf("   時間と分は? ");
		scanf("%d %d", &time, &min);
		time_cv(&time, &min, sw);
		printf("      %d 分です\n", min);
	}
	else {
		printf("   分は? ");
		scanf("%d", &min);
		time_cv(&time, &min, sw);
		printf("      %d 時間 %d 分です\n", time, min);
	}

	return 0;
}

/*****************************/
/* 時間の変換                */
/*      time : 時間          */
/*      min : 分             */
/*      sw : =0 : 時間から分 */
/*           =1 : 分から時間 */
/*****************************/
void time_cv(int *time, int *min, int sw)
{
	if (sw == 0)
		*min = 60 * *time + *min;
	else {
		*time = *min / 60;
		*min  = *min % 60;
	}
}
		
[5-問5]閏年の判定を行うプログラムを書け.閏年は,年号が 4 で割り切れ,100 で割り切れない年である.ただし,400 で割り切れる年は含む.
/****************************/
/* 閏年の判定               */
/*      coded by Y.Suganuma */
/****************************/
#include <stdio.h>

int hantei(int);

int main()
{
	int year;
/*
     年の入力
*/
	printf("年を入力して下さい? ");
	scanf("%d", &year);
/*
     判定
*/
	if (hantei(year))
		printf("   閏年です\n");
	else
		printf("   閏年ではありません\n");

	return 0;
}

/******************/
/* 閏年の判定     */
/*      yean : 年 */
/******************/
int hantei(int year)
{
	int sw;

	if (((year%4 == 0) && (year%100 != 0)) || (year%400 == 0))
		sw = 1;
	else
		sw = 0;

	return sw;
}
		
[5-問8]n (入力)個のデータを読み込み,100 以上のデータ,及び,100 未満のデータの和をそれぞれ求めるプログラムを書け.
/**************************************/
/* 100以上,及び,100未満のデータの和 */
/*      coded by Y.Suganum            */
/**************************************/
#include <stdio.h>
#include <stdlib.h>

void sum100(double *, double *, double *, int);

int main()
{
	double sum1, sum2, *x;
	int i1, n;
/*
     データの入力
*/
	printf("データの数は? ");
	scanf("%d", &n);

	x = (double *)malloc(n*sizeof(double));

	for (i1 = 0; i1 < n; i1++) {
		printf("   データは? ");
		scanf("%lf", &x[i1]);
	}
/*
     計算
*/
	sum100(&sum1, &sum2, x, n);
/*
     出力
*/
	printf("100未満の和 %f  100以上の和 %f\n", sum1, sum2);

	return 0;
}

/**************************************/
/* 100以上,及び,100未満のデータの和 */
/*      sum1 : 100未満の和            */
/*      sum2 : 100以上の和            */
/*      x : データ                    */
/*      n : データの数                */
/**************************************/
void sum100(double *sum1, double *sum2, double *x, int n)
{
	int i1;
/*
     初期設定
*/
	*sum1 = 0.0;
	*sum2 = 0.0;
/*
     計算
*/
	for (i1 = 0; i1 < n; i1++) {
		if (x[i1] < 100.0)
			*sum1 += x[i1];
		else
			*sum2 += x[i1];
	}
}
		
[5-問9]与えられた n 個のデータ内にある正の数と負の数の個数を出力するプログラムを書け.
/***************************/
/* 正と負の数の個数        */
/*      coded by Y.Suganum */
/***************************/
#include <stdio.h>
#include <stdlib.h>

void kazu(int *, int *, int *, int);

int main()
{
	int i1, n, sei, hu, *x;
/*
     データの入力
*/
	printf("データの数は? ");
	scanf("%d", &n);

	x = (int *)malloc(n*sizeof(int));

	for (i1 = 0; i1 < n; i1++) {
		printf("   データは? ");
		scanf("%d", &x[i1]);
	}
/*
     数える
*/
	kazu(&sei, &hu, x, n);
/*
     出力
*/
	printf("正の数 %d  負の数 %d\n",sei,hu);

	return 0;
}

/*************************/
/* 正と負の数の個数      */
/*      sei : 正の数の数 */
/*      hu : 負の数の数  */
/*      x : データ       */
/*      n : データの数   */
/*************************/
void kazu(int *sei, int *hu, int *x, int n)
{
	int i1;
/*
     初期設定
*/
	*sei = 0;
	*hu  = 0;
/*
     数える
*/
	for (i1 = 0; i1 < n; i1++) {
		if (x[i1] != 0) {
			if (x[i1] > 0)
				(*sei)++;
			else
				(*hu)++;
		}
	}
}
		
[5-問10]n 個の抵抗(入力)を直列または並列に接続したときの抵抗を計算するプログラムを書け.
/***************************/
/* 抵抗の直列と並列        */
/*      coded by Y.Suganum */
/***************************/
#include <stdio.h>
#include <stdlib.h>

void teiko(double *, double *, double *, int);

int main()
{
	double cho, hei, *x;
	int i1, n;
/*
     データの入力
*/
	printf("抵抗の数は? ");
	scanf("%d", &n);

	x = (double *)malloc(n*sizeof(double));

	for (i1 = 0; i1 < n; i1++) {
		printf("   抵抗の値は? ");
		scanf("%lf", &x[i1]);
	}
/*
     抵抗の計算
*/
	teiko(&cho, &hei, x, n);
/*
     出力
*/
	printf("直列結合 %f  並列結合 %f\n", cho, hei);

	return 0;
}

/***********************/
/* 抵抗の直列と並列    */
/*      cho : 直列結合 */
/*      hei : 並列結合 */
/*      x : データ     */
/*      n : データの数 */
/***********************/
void teiko(double *cho, double *hei, double *x, int n)
{
	int i1;
/*
     初期設定
*/
	*cho = 0.0;
	*hei = 0.0;
/*
     抵抗の計算
*/
	for (i1 = 0; i1 < n; i1++) {
		*cho += x[i1];
		*hei += 1.0 / x[i1];
	}

	*hei = 1.0 / *hei;
}
		
[5-問14]n (入力)人の試験の点を入力した後,不可,可,良,及び,優の割合(%)を計算し,出力するプログラムを書け.ただし,
不可: 50 点未満
可 : 50 点から 60 点未満
良 : 60 点から 80 点未満
優 : 80 点以上
とする.
/****************************/
/* 優、良、可、不可の割合   */
/*      coded by Y.Suganuma */
/****************************/
#include <stdio.h>
#include <stdlib.h>

void seiseki(double *, int *, int);

int main()
{
	double a[4];
	int i1, *m, n;
/*
          入力
*/
	printf("人数は? ");
	scanf("%d", &n);

	m = (int *)malloc(n*sizeof(int));

	for (i1 = 0; i1 < n; i1++) {
		printf("   点数は ");
		scanf("%d", &m[i1]);
	}
/*
          計算
*/
	seiseki(a, m, n);
/*
          出力
*/
	printf("不可=%f%\n", a[0]);
	printf("  可=%f%\n", a[1]);
	printf("  良=%f%\n", a[2]);
	printf("  優=%f%\n", a[3]);

	return 0;
}

/*********************************/
/* 優、良、可、不可の割合        */
/*      a : 不可,可,良,優の% */
/*      m : データ(点数)       */
/*      n : 人数                 */
/*********************************/
void seiseki(double *a, int *m, int n)
{
	int i1;
/*
          初期設定
*/
	for (i1 = 0; i1 < 4; i1++)
		a[i1] = 0.0;
/*
          計算
*/
	for (i1 = 0; i1 < n; i1++) {
		if (m[i1] < 50)
			a[0] += 1.;
		else {
			if (m[i1] < 60)
				a[1] += 1.;
			else {
				if (m[i1] < 80)
					a[2] += 1.;
				else
					a[3] += 1.;
			}
		}
	}

/*
          計算と出力
*/
	for (i1 = 0; i1 < 4; i1++)
		a[i1] = a[i1] / n * 100.0;
}
		
[5-問15]n 人に給与を支払うものとする.n 及び各人の給与の額をファイルから読み込み,すべての人に給与を釣り銭がないように支払うために必要な 10,000 円札,5,000 円札,1,000 円札,500 円硬貨,及び,100 円硬貨の合計枚数を出力するプログラムを書け.ただし,給与の最小単位は 100 円であるものとする.
/****************************/
/* 給与の計算               */
/*      coded by Y.Suganuma */
/****************************/
#include <stdio.h>
#include <stdlib.h>

void maisu(int *, int *, int);

int main()
{
	int i1, *kyuyo, n, m[5];
	FILE *in;
/*
          ファイルのオープンとデータの読み込み
*/
	in = fopen("kyuyo", "r");

	fscanf(in, "%d", &n);

	kyuyo = (int *)malloc(n*sizeof(int));

	for (i1 = 0; i1 < n; i1++)
		fscanf(in, "%d", &kyuyo[i1]);

	fclose(in);
/*
          枚数の決定
*/
	maisu(m, kyuyo, n);
/*
          出力
*/
	printf("10000円札 %d 枚\n", m[0]);
	printf("5000円札 %d 枚\n", m[1]);
	printf("1000円札 %d 枚\n", m[2]);
	printf("500円硬貨 %d 枚\n", m[3]);
	printf("100円硬貨 %d 枚\n", m[4]);

	return 0;
}

/*****************************************/
/* 給与の計算                            */
/*      m : 各枚数                       */
/*      kyuyo : 各人の給与               */
/*              (給与の内容変化に注意) */
/*      n : 人数                         */
/*****************************************/
void maisu(int *m, int *kyuyo, int n)
{
	int i1, k1;
/*
          初期設定
*/
	for (i1 = 0; i1 < 5; i1++)
		m[i1] = 0;
/*
          計算
*/
	for (i1 = 0; i1 < n; i1++) {
		k1         = kyuyo[i1] / 10000;
		kyuyo[i1] -= k1 * 10000;
		m[0]      += k1;
		k1         = kyuyo[i1] / 5000;
		kyuyo[i1] -= k1 * 5000;
		m[1]      += k1;
		k1         = kyuyo[i1] / 1000;
		kyuyo[i1] -= k1 * 1000;
		m[2]      += k1;
		k1         = kyuyo[i1] / 500;
		kyuyo[i1] -= k1 * 500;
		m[3]      += k1;
		k1         = kyuyo[i1] / 100;
		m[4]      += k1;
	}
}
		
[5-問17]正の整数を入力し,それを各桁毎に分解し,それらの数字を正順及び逆順に,間に 1 つ以上の空白をあけて出力するプログラムを書け.例えば,12345 と入力したら,次のように出力することになる.ただし,整数の桁数は最大 9 桁であるとする.
1 2 3 4 5
5 4 3 2 1
/****************************/
/* 数字の分離               */
/*      coded by Y.Suganuma */
/****************************/
#include <stdio.h>

void sepa(int);

int main()
{
	int n;
					// データの入力
	printf("正の整数を入力してください ");
	scanf("%d", &n);
					// 分離
	sepa(n);

	return 0;
}

/***************************/
/* 数字の分離              */
/*      n : 対象となる数字 */
/***************************/
void sepa(int n)
{
	int m, k = 100000000, k1, sw = 0;
					// 正順
	m = n;
	while (k > 0) {
		k1  = m / k;
		m  %= k;
		k  /= 10;
		if (k1 > 0) {
			sw = 1;
			printf("%d ", k1);
		}
		else {
			if (sw > 0)
				printf("%d ", k1);
		}
	}
	printf("\n");
					// 逆順
	m = n;
	while (m > 0) {
		k1  = m % 10;
		m  /= 10;
		printf("%d ", k1);
	}
}
		
[5-問18]整数型データの中で 1 になっているビットの数を出力するプログラムを書け.
/****************************/
/* 1のビット数を数える     */
/*      coded by Y.Suganuma */
/****************************/
#include <stdio.h>

int bit(int);

int main()
{
	int n;
/*
     整数の入力
*/
	printf("整数を入力して下さい ");
	scanf("%d", &n);
/*
     数を数え,出力
*/
	printf("1のビット数は %d\n", bit(n));

	return 0;
}

/****************************/
/* 1のビット数を数える     */
/*      n : 整数            */
/****************************/
int bit(int n)
{
	int i1, kazu = 0;
	unsigned int mask = 0x80000000;
/*
     数を数える
*/
	for (i1 = 0; i1 < 32; i1++) {
		if ((mask & n) != 0)
			kazu++;
		mask >>= 1;
	}

	return kazu;
}
		
[問2]演習問題 6 の問 1 から問 13 まで(ただし,問 8,9,及び,12 を除く)を,関数を利用して書け.

[6-問1]n (入力)次元のベクトル a の各要素を配列変数の各要素に入力した後,その大きさ( | a | )を出力するプログラムを書け.
/***************************/
/* ベクトルの大きさの計算  */
/*      code by Y.Suganuma */
/***************************/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

double ook(int, double *);

int main()
{
	double *x;
	int i1, n;
/*
          データの入力
*/
	printf("ベクトルの次元は? ");
	scanf("%d", &n);

	x = (double *)calloc(n, sizeof(double));

	for (i1 = 0; i1 < n; i1++) {
		printf("   %d 番目の要素は? ",i1+1);
		scanf("%lf", &x[i1]);
	}
/*
          計算と出力
*/
	printf("結果は=%f\n", ook(n, x));

	return 0;
}

/***********************/
/* ベクトルの大きさ    */
/*      n : データの数 */
/*      x : データ     */
/***********************/
double ook(int n, double *x)
{
	double s = 0.0;
	int i1;
/*
          計算
*/
	for (i1 = 0; i1 < n; i1++)
		s += x[i1] * x[i1];
	s = sqrt(s);

	return s;
}
		
[6-問2]n (入力)次元のベクトル ab の各要素を配列変数の各要素に入力した後,ベクトル ab の和( c = a + b )を出力するプログラムを書け.
/****************************/
/* ベクトルの和の計算       */
/*      coded by Y.Suganuma */
/****************************/
#include <stdio.h>
#include <stdlib.h>

void add(int, double *, double *, double *);

int main()
{
	int i1, n;
	double *a, *b, *c;
/*
          入力
*/
	printf("ベクトルの次元は? ");
	scanf("%d", &n);

	a = (double *)malloc(n*sizeof(double));
	b = (double *)malloc(n*sizeof(double));
	c = (double *)malloc(n*sizeof(double));

	for (i1 = 0; i1 < n; i1=i1+1) {
		printf("ベクトルa,bの %d 番目の要素は? ",i1+1);
		scanf("%lf %lf", &a[i1], &b[i1]);
	}
/*
          実行
*/
	add(n, a, b, c);
/*
          出力
*/
	printf("和は\n");
	for (i1 = 0; i1 < n; i1=i1+1)
		printf(" %f", c[i1]);
	printf("\n");

	return 0;
}

/************************/
/* ベクトルa,bの和c */
/*      n : 次元        */
/************************/
void add(int n, double *a, double *b, double *c)
{
	int i1;
	for (i1 = 0; i1 < n; i1++)
		c[i1] = a[i1] + b[i1];
}
		
[6-問3]n 次元のベクトル ab の内積を計算し出力するプログラムを書け.なお,n,および,各ベクトルの要素の値はキーボードから入力するものとする(ベクトルに対しては,配列変数を利用するものとする).また,ベクトル ab の内積 x の定義は以下の通りである.
  x = a1b1 + a2b2 + ・・・ + anbn
/****************************/
/* 内積の計算               */
/*      coded by Y.Suganuma */
/****************************/
#include <stdio.h>
#include <stdlib.h>

double naiseki(int, double *, double *);

int main()
{
	double *a, *b;
	int n, i1;
/*
          データの入力
*/
	printf("次元は? ");
	scanf("%d", &n);

	a = (double *)malloc(n*sizeof(double));
	b = (double *)malloc(n*sizeof(double));

	for (i1 = 0; i1 < n; i1++) {
		printf("   ベクトルaの %d 番目の要素は? ",i1+1);
		scanf("%lf", &(a[i1]));
	}
	for (i1 = 0; i1 < n; i1++) {
		printf("   ベクトルbの %d 番目の要素は? ",i1+1);
		scanf("%lf", &(b[i1]));
	}
/*
          計算と出力
*/
	printf("内積=%f\n", naiseki(n, a, b));

	return 0;
}

/**********************/
/* aとbの内積       */
/*      n : 次元      */
/*      return : 内積 */
/**********************/
double naiseki(int n, double *a, double *b)
{
	double x = 0.0;
	int i1;

	for (i1 = 0; i1 < n; i1++)
		x += a[i1] * b[i1];

	return x;
}
		
[6-問4]配列 a に n (入力)個のデータ,また,配列 b に n 個のデータを入力した後,もし,a[i] が b[i] より大きければ,a[i] と b[i] を入れ換える操作を行うプログラムを書け.このとき,この操作を行った回数,及び,入れ換えを行った a[i],b[i] の値を出力するものとする.
/****************************/
/* データの交換             */
/*      coded by Y.Suganuma */
/****************************/
#include <stdio.h>
#include <stdlib.h>

int change(double *, double *, int, int *);

int main()
{
	double *a, *b;
	int i1, *k, n, m;
/*
          入力
*/
	printf("データの数は? ");
	scanf("%d", &n);

	a = (double *)malloc(n*sizeof(double));
	b = (double *)malloc(n*sizeof(double));

	k = (int *)calloc(n, sizeof(int));

	for (i1 = 0; i1 < n; i1++) {
		printf("a,bの %d 番目のデータは? ",i1+1);
		scanf("%lf %lf", &a[i1], &b[i1]);
	}
/*
          実行と出力
*/
	m = change(a, b, n, k);

	printf("操作回数=%d\n", m);
	for (i1 = 0; i1 < n; i1++) {
		if (k[i1] > 0)
			printf("   a,b %f %f\n", b[i1], a[i1]);
	}

	return 0;
}

/*********************************/
/* データの交換                  */
/*      a,b : データ             */
/*      n : データの数           */
/*      k : 交換したか否かを示す */
/*      return : 交換回数        */
/*********************************/
int change(double *a, double *b, int n, int *k)
{
	double x;
	int i1, m = 0;
/*
          実行
*/
	for (i1 = 0; i1 < n; i1++) {
		if (a[i1] > b[i1]) {
			x     = a[i1];
			a[i1] = b[i1];
			b[i1] = x;
			k[i1] = 1;
			m++;
		}
	}

	return m;
}
		
[6-問5]n (入力)人の英語,及び,数学の点を入力し,各科目の平均点を計算した後(平均点も出力),どちらかの科目が平均点以下の人の数を出力するプログラムを書け.
/************************************/
/* 平均値の計算(平均点以下の出力) */
/*      coded by Y.Suganuma         */
/************************************/
#include <stdio.h>
#include <stdlib.h>

int hei(int *, int *, int n);

int main()
{
	int n, i1, *x, *y;
/*
         データの読み込み
*/
	printf("人数は? ");
	scanf("%d", &n);

	x = (int *)malloc(n*sizeof(int));
	y = (int *)malloc(n*sizeof(int));

	for (i1 = 0; i1 < n; i1++) {
		printf("%d 番目の人の英語と数学の点は? ", i1+1);
		scanf("%d %d", &(x[i1]), &(y[i1]));
	}
/*
         結果の計算と出力
*/
	printf("   平均点以下の人数は %d 人\n", hei(x, y, n));

	return 0;
}

/********************************************/
/* 平均値の計算(平均点以下の出力)         */
/*      x : 英語の点                        */
/*      y : 数学の点                        */
/*      n : 人数                            */
/*      return : どちらかが平均点以下の人数 */
/********************************************/
int hei(int x[], int y[], int n)
{
	double mean1 = 0.0, mean2 = 0.0;
	int i1, kazu = 0;
/*
         平均値の計算力
*/
	for (i1 = 0; i1 < n; i1++) {
		mean1 += x[i1];
		mean2 += y[i1];
	}

	mean1 /= n;
	mean2 /= n;
/*
         数を数える
*/
   for (i1 = 0; i1 < n; i1++) {
		if (x[i1] <= mean1 || y[i1] <= mean2)
			kazu++;
	}

	return kazu;
}
		
[6-問6]平面上の n 個の点の座標 ( xi, yi ) を読み込み,原点 (0, 0) からの平均距離を計算した後,平均距離,原点から平均距離以上離れたすべての点の座標,及び,その数を出力するプログラムを書け.
/****************************/
/* 原点までの距離の計算     */
/*      coded by Y.Suganuma */
/****************************/
#include <stdio.h>
#include <math.h>
#include <stdlib.h>

int gen(int, double [], double [], int [], double *);

int main()
{
	double mean, *x, *y;
	int i1, k, n, *ten;
/*
         データの入力
*/
	printf("点の数は? ");
	scanf("%d", &n);

	x   = (double *)calloc(n,sizeof(double));
	y   = (double *)calloc(n,sizeof(double));
	ten = (int *)calloc(n,sizeof(int));

	for (i1 = 0; i1 < n; i1++) {
		printf("%d 番目の点の座標は? ", i1+1);
		scanf("%lf %lf", &x[i1], &y[i1]);
	}
/*
         計算
*/
	k = gen(n, x, y, ten, &mean);
/*
         出力
*/
	printf("平均距離は %f\n点の座標は\n", mean);
	for (i1 = 0; i1 < k; i1++)
		printf("%f %f\n", x[ten[i1]], y[ten[i1]]);
	printf("   点の数=%d\n", k);

	return 0;
}

/******************************/
/* 平均距離以上離れた点       */
/*      n : 点の数            */
/*      x,y : 座標            */
/*      ten : 離れた点の番号  */
/*      av : 平均距離         */
/*      return : 離れた点の数 */
/******************************/
int gen(int n, double x[], double y[], int ten[], double *av)
{
	double mean = 0.0, x1, *z;
	int i1, k = 0;
/*
         ワークエリア
*/
	z = (double *)calloc(n, sizeof(double));
/*
         距離の計算
*/
	for (i1 = 0; i1 < n; i1++) {
		x1     = x[i1] * x[i1] + y[i1] * y[i1];
		z[i1]  = sqrt(x1);
		mean  += z[i1];
	}
/*
         平均距離以上離れた点の数
*/
	mean /= n;
	for (i1 = 0; i1 < n; i1++) {
		if (z[i1] >= mean) {
			ten[k] = i1;
			k++;
		}
	}

	free(z);

	*av = mean;

	return k;
}
		
[6-問7]今,ある物質を構成する n (未知数)個の成分の各質量がファイルに保存されていたとする.これらの成分を入力した後,各成分の全体に対する%を別のファイルへ出力するプログラムを書け.
/****************************/
/* 成分の%の計算           */
/*      coded by Y.Suganuma */
/****************************/
#include <stdio.h>
#include <stdlib.h>

#define STEP 100

void per(double *, double *, int n);

int main()
{
	double *x, *y;
	int dim = STEP, n = 0, i1;
	FILE *in, *out;
/*
         データの読み込み
*/
	in = fopen("input", "r");

	x  = (double *)malloc(dim*sizeof(double));

	while (EOF != fscanf(in, "%lf", &x[n])) {
		n++;
		if (n >= dim) {
			dim += STEP;
			x    = (double *)realloc(x, dim*sizeof(double));
		}
	}

	fclose(in);
/*
          %の計算
*/
	y = (double *)malloc(n*sizeof(double));

	per(x, y, n);
/*
          出力
*/
	out = fopen("output", "w");

	for (i1 = 0; i1 < n; i1++)
		fprintf(out,"%d 番目の成分 %6.2f %\n", i1+1, y[i1]);

	fclose(out);

	return 0;
}

/*********************/
/* 成分の%の計算    */
/*      x : 成分     */
/*      y : 成分の% */
/*      n : 成分の数 */
/*********************/
void per(double *x, double *y, int n)
{
	double sum = 0.0;
	int i1;
/*
         成分の和を計算
*/
	for (i1 = 0; i1 < n; i1++)
		sum += x[i1];
/*
          %の計算
*/
	for (i1 = 0; i1 < n; i1++)
		y[i1] = x[i1] / sum * 100.0;
}
		
[6-問10]ある店舗の毎日の売上の記録 xi ( i = 1 ~ 30 )がある(入力データとして読み込む).ある与えられた日(入力データ)を基準にした前後 7 日間(例えば,5 日が与えられたときは,2 日から 8 日)の売上高の平均を計算し,出力するプログラムを書け.ただし,前後の日にちが 0 以下になったり 31 以上になった場合は,1 または 30 までの平均を計算する(例えば,2 日が与えられたときは,1 日から 5 日までの平均を計算)ものとする.また,0 以下または 31 以上の日にちが入力されたときは,再入力をうながすものとする( goto 文は使用しない).
/****************************/
/* 売上の計算               */
/*      coded by Y.Suganuma */
/****************************/
#include <stdio.h>

int heikin(int *, int);

int main()
{
	int i1, m = 0, x[30];
/*
          データの入力
*/
	for (i1 = 0; i1 < 30; i1++) {
		printf("   %d 日の売上は? ", i1+1);
		scanf("%d", &x[i1]);
	}

	while (m < 1 || m > 30) {
		printf("基準日(1から30)は? ");
		scanf("%d", &m);
	}
/*
          計算と出力
*/
	printf("平均=%d\n", heikin(x, m));

	return 0;
}

/************************/
/* 売上の計算           */
/*      x : データ      */
/*      m : 基準日      */
/*      return : 平均値 */
/************************/
int heikin(int *x, int m)
{
	int i1, k1, k2, mean = 0, n;

	k1 = m - 3;
	if (k1 < 1)
		k1 = 1;
	k2 = m + 3;
	if (k2 > 30)
		k2 = 30;
	n = k2 - k1 + 1;

	for (i1 = k1-1; i1 < k2; i1++)
		mean += x[i1];

	mean /= n;

	return mean;
}
		
[6-問11]n (入力)個の正の整数値を入力し,末尾の桁が 0,1,・・・,9 のものの個数とその割合(%)を出力するプログラムを書け.
/****************************/
/* 0、1、...              */
/*      coded by Y.Suganuma */
/****************************/
#include <stdio.h>
#include <stdlib.h>

void matu(int *, int *, int);

int main()
{
	int i1, k1, n, *m, kk[10];
/*
          初期設定
*/
	for (i1 = 0; i1 < 10; i1++)
		kk[i1] = 0;
/*
          入力
*/
	printf("データの数は? ");
	scanf("%d", &n);

	m = (int *)malloc(n*sizeof(int));

	for (i1 = 0; i1 < n; i1++) {
		printf("   正の整数? ");
		scanf("%d", &m[i1]);
	}
/*
          出力
*/
	matu(m, kk, n);

	for (i1 = 0; i1 < 10; i1++) {
		k1 = kk[i1] * 100 / n;
		printf("%d  %d 個  %d %\n", i1, kk[i1], k1);
	}

	return 0;
}

/************************/
/* 0、1、...          */
/*      m : データ      */
/*      kk : 各末尾の数 */
/*      n : データの数  */
/************************/
void matu(int *m, int *kk, int n)
{
	int i1, k1;

	for (i1 = 0; i1 < n; i1++) {
		k1 = m[i1] % 10;
		kk[k1]++;
	}
}
		
[6-問13]平面上の n (入力)個の点の座標を入力した後,すべての点の間の距離を計算し,その距離が最大になる点の組( 2 つの点の座標),及び,その距離を出力するプログラムを書け.
/****************************/
/* 点間の距離の計算         */
/*      coded by Y.Suganuma */
/****************************/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

double max(double *x, double *y, int, int *, int *);

int main()
{
	double max_r, *x, *y;
	int n, i1, k1, k2;
/*
          データの入力
*/
	printf("点の数は? ");
	scanf("%d", &n);

	x = (double *)malloc(n*sizeof(double));
	y = (double *)malloc(n*sizeof(double));

	for (i1 = 0; i1 < n; i1++) {
		printf("   %d 番目の点の座標は? ", i1+1);
		scanf("%lf %lf", &(x[i1]), &(y[i1]));
	}
/*
          計算と出力
*/
	max_r = max(x, y, n, &k1, &k2);

	printf("点(%f,%f)と(%f,%f)間で距離は %f\n",
           x[k1], y[k1], x[k2], y[k2], max_r);

	return 0;
}

/***********************************/
/* 点間の距離の計算                */
/*      x,y : 点の座標             */
/*      n : 点の数                 */
/*      k1,k2 : 最大距離を与える点 */
/*      return : 最大距離          */
/***********************************/
double max(double *x, double *y, int n, int *k1, int *k2)
{
	double max_r = 0.0, r, r1, r2;
	int i1, i2;

	for (i1 = 0; i1 < n-1; i1++) {
		for (i2 = i1+1; i2 < n; i2++) {
			r1 = x[i1] - x[i2];
			r2 = y[i1] - y[i2];
			r  = sqrt(r1 * r1 + r2 * r2);
			if (r > max_r) {
				max_r = r;
				*k1   = i1;
				*k2   = i2;
			}
		}
	}

	return max_r;
}
		
[問3]演習問題 5 の問 22 と問 23 を,関数を利用して書け.ただし,f(x) の計算を別の関数で行い,二分法及び台形則による積分を実行する関数にその名前を引数として受け渡せ.

[5-問22]二分法により次式の根を求めるためのプログラムを書け.
f(x) = ex - 3x = 0
ただし,二分法は,関数 f(x) が区間 [a, b] で連続で,かつ,根が 1 つだけ存在するとき利用できる方法である.従って,f(a)f(b) < 0となる.区間 [a, b] の中点 c を
c = 0.5 * (a + b)
で求め,f(c) の値を計算し,f(a)f(c) < 0なら
b = c,f(b) = f(c)
そうでなければ
a = c,f(a) = f(c)
と置き換え,根の存在区間を半分に縮小する.この操作を,
|b - a| < ε
が満足されるまで繰り返すことによって解を求める.

プログラム例 7.24 を参照してください.

[5-問23]台形則により次の関数の任意区間の積分値を計算するプログラムを書け.
f(x) = (2π)-0.5-x*x/2
ただし,台形則は,積分区間 [x1, x2] を n 個の,幅
h = (x2 - x1) / n
の小区間に分け,各区間の面積を右図のような台形で近似して,積分値を計算する方法である.従って,積分値 S は次のように書ける.
  S = 0.5h{f(x1) + 2(f(x1+h) + f(x1+2h) + ・・・ + f(x2-h)) + f(x2)}

プログラム例 7.25 を参照してください.

[問4]演習問題 6 の問 16 を,関数を利用して書け.

[6-問16]ある学年に n (入力)クラスあり,各クラスには m 人(入力,クラス毎に異なる)の生徒がいるものとする.全員に対しある試験を実施したとき,各人の名前,点数を動的確保した配列に保存した後,学年平均点以下の人の名前とその点数を出力するプログラムを書け.

(calloc)を使用した場合)
/**********************************/
/* 平均点と平均点以下の人(calloc) */
/*      coded by Y.Suganuma       */
/**********************************/
#include <stdio.h>
#include <stdlib.h>

void heikin(int **, int *, int);

int main()
{
	int i1, i2, **cl, n, *m;
	char ***name;
/*
     データの入力と平均点の計算
*/
	printf("クラスの数は? ");
	scanf("%d", &n);

	cl   = (int **)calloc(n, sizeof(int *));
	m    = (int *)calloc(n, sizeof(int));
	name = (char ***)calloc(n, sizeof(char **));

	for (i1 = 0; i1 < n; i1++) {

		printf("%d 番目のクラスの人数は ", i1+1);
		scanf("%d", &m[i1]);

		cl[i1]   = (int *)calloc(m[i1], sizeof(int));
		name[i1] = (char **)calloc(m[i1], sizeof(char *));

		for (i2 = 0; i2 < m[i1]; i2++) {
			name[i1][i2] = (char *)calloc(20, sizeof(char));
			printf("     %d 番目の人の名前は? ",i2+1);
			scanf("%s", name[i1][i2]);
			printf("        %d 番目の人の点は? ",i2+1);
			scanf("%d", &(cl[i1][i2]));
		}
	}
/*
     出力
*/
	heikin(cl, m, n);

	for (i1 = 0; i1 < n; i1++) {
		for (i2 = 0; i2 < m[i1]; i2++) {
			if (cl[i1][i2] <= 0)
				printf("   %3d 点  %s\n", -cl[i1][i2], name[i1][i2]);
			free(name[i1][i2]);
		}
		free(cl[i1]);
		free(name[i1]);
	}

	free(cl);
	free(name);

	return 0;
}

/*********************************************************/
/* 平均点と平均点以下の人(calloc)                        */
/*      cl[i][j] : i番目のクラスのj番目の人の点        */
/*                  (平均点以下の場合は,負にして返す) */
/*      m[i] : i番目のクラスの人数                      */
/*      n : クラスの数                                   */
/*********************************************************/
void heikin(int **cl, int *m, int n)
{
	int i1, i2, mean = 0, nin = 0;
/*
     平均点の計算
*/
	for (i1 = 0; i1 < n; i1++) {
		nin += m[i1];
		for (i2 = 0; i2 < m[i1]; i2++)
			mean += cl[i1][i2];
	}

	mean /= nin;
/*
     比較
*/
	for (i1 = 0; i1 < n; i1++) {
		for (i2 = 0; i2 < m[i1]; i2++) {
			if (cl[i1][i2] <= mean)
				cl[i1][i2] = -cl[i1][i2];
		}
	}
}
		
(new)を使用した場合)
/*******************************/
/* 平均点と平均点以下の人(new) */
/*      coded by Y.Suganuma    */
/*******************************/
#include <stdio.h>

void heikin(int **, int *, int);

int main()
{
	int i1, i2, **cl, n, *m;
	char ***name;
/*
     データの入力と平均点の計算
*/
	printf("クラスの数は? ");
	scanf("%d", &n);

	cl   = new int * [n];
	m    = new int [n];
	name = new char ** [n];

	for (i1 = 0; i1 < n; i1++) {

		printf("%d 番目のクラスの人数は ", i1+1);
		scanf("%d", &m[i1]);

		cl[i1]   = new int [m[i1]];
		name[i1] = new char * [m[i1]];

		for (i2 = 0; i2 < m[i1]; i2++) {
			name[i1][i2] = new char [20];
			printf("     %d 番目の人の名前は? ",i2+1);
			scanf("%s", name[i1][i2]);
			printf("        %d 番目の人の点は? ",i2+1);
			scanf("%d", &(cl[i1][i2]));
		}
	}
/*
     出力
*/
	heikin(cl, m, n);

	for (i1 = 0; i1 < n; i1++) {
		for (i2 = 0; i2 < m[i1]; i2++) {
			if (cl[i1][i2] <= 0)
				printf("   %3d 点  %s\n", -cl[i1][i2], name[i1][i2]);
			delete [] name[i1][i2];
		}
		delete [] cl[i1];
		delete [] name[i1];
	}

	delete [] cl;
	delete [] name;

	return 0;
}

/*********************************************************/
/* 平均点と平均点以下の人(calloc)                        */
/*      cl[i][j] : i番目のクラスのj番目の人の点        */
/*                  (平均点以下の場合は,負にして返す) */
/*      m[i] : i番目のクラスの人数                      */
/*      n : クラスの数                                   */
/*********************************************************/
void heikin(int **cl, int *m, int n)
{
	int i1, i2, mean = 0, nin = 0;
/*
     平均点の計算
*/
	for (i1 = 0; i1 < n; i1++) {
		nin += m[i1];
		for (i2 = 0; i2 < m[i1]; i2++)
			mean += cl[i1][i2];
	}

	mean /= nin;
/*
     比較
*/
	for (i1 = 0; i1 < n; i1++) {
		for (i2 = 0; i2 < m[i1]; i2++) {
			if (cl[i1][i2] <= mean)
				cl[i1][i2] = -cl[i1][i2];
		}
	}
}
		
[問5]n 行 m 列の行列の足し算を行うプログラムを,関数を利用して書け.なお,関数は,任意の n 及び m に対応できるようにせよ.

(calloc)を使用した場合)
/****************************/
/* 行列の足し算(calloc)     */
/*      coded by Y.Suganuma */
/****************************/
#include <stdio.h>
#include <stdlib.h>

void add(double **, double **, double **, int, int);

int main()
{
	double **a, **b, **c;
	int i1, i2, n, m;
/*
     データの入力
*/
	printf("行の数は? ");
	scanf("%d", &n);
	printf("列の数は? ");
	scanf("%d", &m);

	a = (double **)calloc(n, sizeof(double *));
	b = (double **)calloc(n, sizeof(double *));
	c = (double **)calloc(n, sizeof(double *));

	printf("行列a\n");
	for (i1 = 0; i1 < n; i1++) {
		a[i1] = (double *)calloc(m, sizeof(double));
		c[i1] = (double *)calloc(m, sizeof(double));
		printf("   %d行目\n", i1+1);
		for (i2 = 0; i2 < m; i2++) {
			printf("      %d列目のデータは? ", i2+1);
			scanf("%lf", &a[i1][i2]);
		}
	}

	printf("行列b\n");
	for (i1 = 0; i1 < n; i1++) {
		b[i1] = (double *)calloc(m, sizeof(double));
		printf("   %d行目\n", i1+1);
		for (i2 = 0; i2 < m; i2++) {
			printf("      %d列目のデータは? ", i2+1);
			scanf("%lf", &b[i1][i2]);
		}
	}
/*
     計算と出力
*/
	add(a, b, c, n, m);

	for (i1 = 0; i1 < n; i1++) {
		for (i2 = 0; i2 < m; i2++)
			printf("%f ", c[i1][i2]);
		printf("\n");
		free(a[i1]);
		free(b[i1]);
		free(c[i1]);
	}

	free(a);
	free(b);
	free(b);

	return 0;
}

/**********************************/
/* n行m列の行列の足し算(calloc) */
/*      c = a + b                 */
/**********************************/
void add(double **a, double **b, double **c, int n, int m)
{
	int i1, i2;

	for (i1 = 0; i1 < n; i1++) {
		for (i2 = 0; i2 < m; i2++)
			c[i1][i2] = a[i1][i2] + b[i1][i2];
	}
}
		
(new)を使用し,1次元配列を利用した場合)
/****************************/
/* 行列の足し算(new)        */
/*      coded by Y.Suganuma */
/****************************/
#include <stdio.h>

void add(double **, double **, double **, int, int);

int main()
{
	double **a, **b, **c;
	int i1, i2, n, m;
/*
     データの入力
*/
	printf("行の数は? ");
	scanf("%d", &n);
	printf("列の数は? ");
	scanf("%d", &m);

	a = new double * [n];
	b = new double * [n];
	c = new double * [n];

	printf("行列a\n");
	for (i1 = 0; i1 < n; i1++) {
		a[i1] = new double [m];
		c[i1] = new double [m];
		printf("   %d行目\n", i1+1);
		for (i2 = 0; i2 < m; i2++) {
			printf("      %d列目のデータは? ", i2+1);
			scanf("%lf", &a[i1][i2]);
		}
	}

	printf("行列b\n");
	for (i1 = 0; i1 < n; i1++) {
		b[i1] = new double [m];
		printf("   %d行目\n", i1+1);
		for (i2 = 0; i2 < m; i2++) {
			printf("      %d列目のデータは? ", i2+1);
			scanf("%lf", &b[i1][i2]);
		}
	}
/*
     計算と出力
*/
	add(a, b, c, n, m);

	for (i1 = 0; i1 < n; i1++) {
		for (i2 = 0; i2 < m; i2++)
			printf("%f ", c[i1][i2]);
		printf("\n");
		delete [] a[i1];
		delete [] b[i1];
		delete [] c[i1];
	}

	delete [] a;
	delete [] b;
	delete [] c;

	return 0;
}

/**********************************/
/* n行m列の行列の足し算(calloc) */
/*      c = a + b                 */
/**********************************/
void add(double **a, double **b, double **c, int n, int m)
{
	int i1, i2;

	for (i1 = 0; i1 < n; i1++) {
		for (i2 = 0; i2 < m; i2++)
			c[i1][i2] = a[i1][i2] + b[i1][i2];
	}
}
		
[問6]キーボードから,「 English This is a pen 」 のように English の後に英文を入力すると,英文を構成する単語数及びすべての文字数を出力するプログラムを main 関数の引数を利用して書け.
/******************************************/
/* 入力された単語と文字数を数えるコマンド */
/*      coded by Y.Suganuma               */
/******************************************/
#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[])
{
	int i1, num = 0;

	for (i1 = 1; i1 < argc; i1++)
		num += strlen(argv[i1]);

	printf("単語数は %d 文字数は %d\n", argc-1, num);

	return 0;
}
		

菅沼ホーム 演習解答例目次 本文目次 付録 索引