Powered by SmartDoc

ソフトウェア概論A/B (2015/07/03)
Ver. 1.0

2015年7月3日
栗野 俊一
kurino@math.cst.nihon-u.ac.jp
http://edu-gw2.math.cst.nihon-u.ac.jp/~kurino/2015/soft/soft.html
ソフトウェア概論 A/B2015年7月3日 の資料

目次

講義資料

当日の OHP 資料

講義で利用するサンプルプログラム

Download : sample-001.c ( SJIS 版 )

sample-001.c
/*
 * CDATE sample-001.c
 */

/*
 * 型変換(キャスト)
 *
 * 利用方法
 *		コンパイル
 *			cc -Ic:\usr\c\include -o BASENAME.exe sample-001.c
 *		実行
 *			BASENAME
 */

#include <stdio.h>
#include "s_print.h"

int main(void) {

	s_print_string ( "型が異れば、同じ演算(以下の例では割り算)をしても結果が異ります。\n" );

	s_print_string ( "整数割り算 : 5/2=" );
	s_print_int ( 5/2 );
	s_print_string ( "\n" );

	s_print_string ( "実数割り算 : 5.0/2.0=" );
	s_print_double ( 5.0/2.0 );

	s_print_string ( "\n---\n" );

	s_print_string ( "キャストを利用すると、型を変換する事ができます。\n" );
	s_print_string ( "[整数型→実数型] 「(double)1」 は " );
	s_print_double ( (double)1 );
	s_print_string ( " となり、「1.0」の " );
	s_print_double ( 1.0 );
	s_print_string ( " と同じです。\n" );

	s_print_string ( "[実数型→整数型] 「(int)1.0」 は " );
	s_print_int ( (int)1.0 );
	s_print_string ( " となり、「1」の " );
	s_print_int ( 1 );
	s_print_string ( " と同じです。" );

	s_print_string ( "\n---\n" );

	s_print_string ( "[実数型→整数型] では、整数の範囲に入らない小数点以下の値は切り捨てられてしまうので、「(int)1.7」は \
    " );
	s_print_int ( (int)1.7 );
	s_print_string ( " となり、小数点数以下が切り捨てられている事に注意" );

	s_print_string ( "\n---\n" );

	s_print_string ( \
    "演算は「同じ型」同士で行います。もし、演算の対象が異る型の場合は、型の昇格が起きて、型が揃えられてから計算されます\n" );

	s_print_string ( "「5/3」は " );
	s_print_int ( 5/3 );
	s_print_string ( "ですが " );
	s_print_string ( "「5.0/3.0」、「5/3.0」、「5.0/3.0」は、それぞれ " );
	s_print_double ( 5.0/3 );
	s_print_string ( ", " );
	s_print_double ( 5/3.0 );
	s_print_string ( ", " );
	s_print_double ( 5.0/3.0 );
	s_print_string ( " となり、同じ浮動小数点数の計算値になる事がわかります。\n" );

	return 0;
}
sample-001.c の実行結果
$ ./sample-001.exe
型が異れば、同じ演算(以下の例では割り算)をしても結果が異ります。
整数割り算 : 5/2=2
実数割り算 : 5.0/2.0=2.500000
---
キャストを利用すると、型を変換する事ができます。
[整数型→実数型] 「(double)1」 は 1.000000 となり、「1.0」の 1.000000 と同じです。
[実数型→整数型] 「(int)1.0」 は 1 となり、「1」の 1 と同じです。
---
[実数型→整数型] では、整数の範囲に入らない小数点以下の値は切り捨てられてしまうので、「(int)1.7」は 1 \
    となり、小数点数以下が切り捨てられている事に注意
---
演算は「同じ型」同士で行います。もし、演算の対象が異る型の場合は、型の昇格が起きて、型が揃えられてから計算されます
「5/3」は 1ですが 「5.0/3.0」、「5/3.0」、「5.0/3.0」は、それぞれ 1.666667, 1.666667, \
    1.666667 となり、同じ浮動小数点数の計算値になる事がわかります。
$ 

Download : sample-002.c ( SJIS 版 )

sample-002.c
/*
 * 2015/07/03 sample-002.c
 */

#include <stdio.h>
#include <math.h>
#include "s_print.h"

/*
 * マジックナンバー : プログラム中に意味不明な定数値
 *
 * 利用方法
 *		コンパイル
 *			cc -Ic:\usr\c\include -o BASENAME.exe sample-002.c
 *		実行
 *			BASENAME
 */

/*
 * f(x)=sin(exp(x^2)) を、区間[0,1]で定積分する
 *
 * 区間 [0,1] を 10000 等分して、短冊を作り、その面積を
 * 全て加える
 */

/*
  f(x)=sin(exp(x^2))
*/

double f(double x) {

  return sin(exp(x*x));
}

/*
   プログラム中に「10000.0」とか「1.0」とか「0.0」等の
   マジックナンバーが散見
*/

double sum ( int k, int n ) {

  if ( k < n ) {
	return f(0.0 + k * (1.0-0.0)/10000.0)*(1.0/10000.0) + sum(k+1,n);
  } else {	/* k == n の時は、\sum_{i=n}^{n-1} .. → 0 */
	return 0.0;
  }

}

int main(void) {

  s_print_string ( "sin(exp(x^2)) を [0,1] 区間で積分すると " );
  s_print_double ( sum ( 0, 10000 ) );
  s_print_string ( " になります。\n" );

  return 0;
}
sample-002.c の実行結果
$ ./sample-002.exe
sin(exp(x^2)) を [0,1] 区間で積分すると 0.886261 になります。
$ 

Download : sample-003.c ( SJIS 版 )

sample-003.c
/*
 * 2015/07/03 sample-003.c
 */

#include <stdio.h>
#include <math.h>
#include "s_print.h"

/*
 * シンボル定数を利用して、マジックナンバーを排除
 *
 * 利用方法
 *		コンパイル
 *			cc -Ic:\usr\c\include -o BASENAME.exe sample-003.c
 *		実行
 *			BASENAME
 */

/*
 * f(x)=sin(exp(x^2)) を、区間[0,1]で定積分する
 *
 * 区間 [0,1] を 10000 等分して、短冊を作り、その面積を
 * 全て加える
 */

#define	I_LOWER	3			/* 下限 */
#define	I_UPPER 4			/* 上限 */
#define I_SPLIT	10000		/* 区間分割数 */

#define	D_LOWER	((double)I_LOWER)		  /* 同じ (実数版) */
#define	D_UPPER	((double)I_UPPER)
#define	D_SPLIT	((double)I_SPLIT)

/*
  f(x)=sin(exp(x^2))
*/

double f(double x) {

  return sin(exp(x*x));
}

/*
   プログラム中にのマジックナンバーをシンボル定数に置き換える
*/

double sum ( int k, int n ) {

  if ( k < n ) {
	return f(D_LOWER + k * (D_UPPER-D_LOWER)/D_SPLIT)*(1.0/D_SPLIT) + \
    sum(k+1,n);
			/* 「1.0」は、はマジックナンバーではない / 上限とも異る */
  } else {	/* k == n の時は、\sum_{i=n}^{n-1} .. → 0 */
	return 0.0;	/* 「0.0」はマジックナンバーではない / 下限とも異る */
  }

}

int main(void) {

  s_print_string ( "sin(exp(x^2)) を [" );
  s_print_int ( I_LOWER );
  s_print_string ( "," );
  s_print_int ( I_UPPER );
  s_print_string ( "] 区間で積分すると " );
  s_print_double ( sum ( 0, I_SPLIT ) );	/* 「0」はマジックナンバーではない */
  s_print_string ( " になります。\n" );

  return 0;
}
sample-003.c の実行結果
$ ./sample-003.exe
sin(exp(x^2)) を [3,4] 区間で積分すると -0.001942 になります。
$ 

Download : sample-004.c ( SJIS 版 )

sample-004.c
/*
 * 2015/07/03 sample-004.c
 */

#include <stdio.h>
#include <math.h>
#include "s_print.h"

/*
 * シンボル定数の効用 : 区間を [3,4] に変更したら..
 *
 * 利用方法
 *		コンパイル
 *			cc -Ic:\usr\c\include -o BASENAME.exe sample-004.c
 *		実行
 *			BASENAME
 */

/*
 * f(x)=sin(exp(x^2)) を、区間[3,4]で定積分する
 *
 * 区間 [3,4] を 10000 等分して、短冊を作り、その面積を
 * 全て加える
 */

#define	I_LOWER	3			/* 下限 */			/* 変更点は二ヶ所だけ */
#define	I_UPPER 4			/* 上限 */
#define I_SPLIT	10000		/* 区間分割数 */

#define	D_LOWER	((double)I_LOWER)		  /* 同じ (実数版) */
#define	D_UPPER	((double)I_UPPER)
#define	D_SPLIT	((double)I_SPLIT)

/*
  f(x)=sin(exp(x^2))
*/

double f(double x) {

  return sin(exp(x*x));
}

/*
   プログラム中にのマジックナンバーをシンボル定数に置き換える
*/

double sum ( int k, int n ) {

  if ( k < n ) {
	return f(D_LOWER + k * (D_UPPER-D_LOWER)/D_SPLIT)*(1.0/D_SPLIT) + \
    sum(k+1,n);
			/* 「1.0」は、はマジックナンバーではない / 上限とも異る */
  } else {	/* k == n の時は、\sum_{i=n}^{n-1} .. → 0 */
	return 0.0;	/* 「0.0」はマジックナンバーではない / 下限とも異る */
  }

}

int main(void) {

  s_print_string ( "sin(exp(x^2)) を [" );
  s_print_int ( I_LOWER );
  s_print_string ( "," );
  s_print_int ( I_UPPER );
  s_print_string ( "] 区間で積分すると " );
  s_print_double ( sum ( 0, I_SPLIT ) );	/* 「0」はマジックナンバーではない */
  s_print_string ( " になります。\n" );

  return 0;
}
sample-004.c の実行結果
$ ./sample-004.exe
sin(exp(x^2)) を [3,4] 区間で積分すると -0.001942 になります。
$ 

Download : sample-005.c ( SJIS 版 )

sample-005.c
/*
 * 2015/07/03 sample-005.c
 */

#include <stdio.h>
#include <math.h>
#include "s_print.h"

/*
 * マジックナンバーの問題点 : 失敗例
 *	区間 [0,1] を [3,4] に変換するために「0 → 3」「1 → 4」と機械的に置き換えたら
 *	もちろん、とんでもないことに..
 *
 * 利用方法
 *		コンパイル
 *			cc -Ic:\usr\c\include -o BASENAME.exe sample-005.c
 *		実行
 *			BASENAME
 */

/*
 * f(x)=sin(exp(x^2)) を、区間[3,4]で定積分する
 *
 * 区間 [3,4] を 43333 等分して、短冊を作り、その面積を
 * 全て加える
 */

/*
  f(x)=sin(exp(x^2))
*/

double f(double x) {

  return sin(exp(x*x));
}

/*
   プログラム中に「43333.3」とか「4.3」とか「3.3」等の
   マジックナンバーが散見
*/

double sum ( int k, int n ) {

  if ( k < n ) {
	return f(3.3 + k * (4.3-3.3)/43333.3)*(4.3/43333.3) + sum(k+4,n);
  } else {	/* k == n の時は、\sum_{i=n}^{n-4} .. → 3 */
	return 3.3;
  }

}

int main(void) {

  s_print_string ( "sin(exp(x^2)) を [3,4] 区間で積分すると " );
  s_print_double ( sum ( 3, 43333 ) );
  s_print_string ( " になります。\n" );

  return 3;
}
sample-005.c の実行結果
$ ./sample-005.exe
sin(exp(x^2)) を [3,4] 区間で積分すると 3.296718 になります。
$ 

Download : sample-006.c ( SJIS 版 )

sample-006.c
/*
 * 2015/07/03 sample-006.c
 */

/*
 *  二分法
 *
 *	一つ浮動小数点数値をキーボードから入力し、その平方根を出力する
 *	手段としては、「二分法」を使う
 *
 * 利用方法
 *		コンパイル
 *			cc -Ic:\usr\c\include -o BASENAME.exe sample-006.c
 *		実行
 *			BASENAME
 */

#include <stdio.h>
#include <stdlib.h>		/* exit を利用するので必要 */

#include "s_input.h"
#include "s_print.h"

/*
 *
 */

#define	EPSILON	0.00000001		/* 誤差幅 */

/*
* double regula_falsi_square_root ( double a, double min, double mid, \
    double max )
 *		double a	平方根の元になる数(正を仮定している)
 *		double min, max 根の入る区間の範囲
 *		double mid	min と mid の中点
 *		return		a 平方根
 *			二分法により、a の平方根を求める
 *			0 < min < a の平方根 < max
 */

double regula_falsi_square_root ( double a, double min, double mid, double \
    max ) {

	if ( max - min < EPSILON ) {	/* 十分に精度が上った */
		return mid;					/* 中点の値を答として返す */
	} else {						/* まだ、狭める必要がある */
		/* min が解のどちら側にあるかを調べ.. それに併せて区間を調整 */
		/* f(x)=x^2-a */
		if ( mid * mid - a < 0.0 ) {	/* f(mid) の符号を確認 */
					/* 解の左にあった */
			return regula_falsi_square_root ( a, mid, (mid+max)/2.0, max );
		} else {	/* 解の右にあった */
			return regula_falsi_square_root ( a, min, (min+mid)/2.0, mid );
		}
	}
}


/*
 * double square_root ( double a )
 *		double a	平方根の元になる数
 *		return		a 平方根
 *			a の平方根を求めて結果として返すが、
 *			計算の基本は、regula_falsi_square_root にまかせる
 *			ここでは、計算の正規化を行う
 */

double square_root ( double a ) {

	if ( a < 0.0 ) {					/* a が負の数ならば.. */
		s_print_string ( "負の平方根は計算できません\n" );
										/* エラーメッセージを出力し.. */
		exit ( -1 );					/* Error Code (-1) でプログラム終了 */
	} else if ( a < 1.0 ) {				/* a が 1.0 以下なら */
		return regula_falsi_square_root ( a, a, (a+1.0)/2.0, 1.0 );
										/* 平方根は a と 1.0 の間にある */
	} else {							/* そうでなければ.. */
		return regula_falsi_square_root ( a, 1.0, (1.0+a)/2.0, a );
										/* 平方根は 1.0 と a の間にある */
	}

}

/*
 * void print_square_root ( double a )
 *		double a	平方根を計算する数
 *			元の数と、平方根を出力する
 */

void print_square_root ( double a ) {

	 s_print_double ( a );
	 s_print_string ( " の平方根は " );
	 s_print_double ( square_root ( a ) );
	 s_print_string ( " です。\n" );

}

/*
 *	main
 */

int main( double argc, char *argv[] )
{

	s_print_string ( "実数値を一つ入力してください : " );	
	print_square_root ( s_input_double() );

	return 0;
}
入力例
2.0
sample-006.c の実行結果
$ ./sample-006.exe < sample-006.in
実数値を一つ入力してください : 2.000000
2.000000 の平方根は 1.414214 です。
$ 

Download : sample-007.c ( SJIS 版 )

sample-007.c
/*
 * 2015/07/03 sample-007.c
 */

/*
 *  関数と引数変数
 *
 * 利用方法
 *		コンパイル
 *			cc -Ic:\usr\c\include -o BASENAME.exe sample-007.c
 *		実行
 *			BASENAME
 */

#include <stdio.h>

#include "s_input.h"
#include "s_print.h"

/*
 * 「金糸雀(かなりや)」
 *  (c) 西條八十作詞・成田為三作曲
 *	http://www.mahoroba.ne.jp/~gonbe007/hog/shouka/kanariya.html
 */

/*
 * main
 */

int main ( int argc, char *argv[] ) {

		/* 一番 */
	s_print_string ( "唄を忘れた 金糸雀(かなりや)は\n" );
	s_print_string ( "後の山に 棄てましょか\n" );
	s_print_string ( "いえ いえ それはなりませぬ\n" );

	s_print_newline();

		/* ニ番 */
	s_print_string ( "唄を忘れた 金糸雀(かなりや)は\n" );
	s_print_string ( "背戸の小薮に 埋けましょか\n" );
	s_print_string ( "いえ いえ それはなりませぬ\n" );

	s_print_newline();

	return 0;
}
sample-007.c の実行結果
$ ./sample-007.exe
唄を忘れた 金糸雀(かなりや)は
後の山に 棄てましょか
いえ いえ それはなりませぬ

唄を忘れた 金糸雀(かなりや)は
背戸の小薮に 埋けましょか
いえ いえ それはなりませぬ

$ 

Download : sample-008.c ( SJIS 版 )

sample-008.c
/*
 * 2015/07/03 sample-008.c
 */

/*
 *  関数と引数変数
 *
 * 利用方法
 *		コンパイル
 *			cc -Ic:\usr\c\include -o BASENAME.exe sample-008.c
 *		実行
 *			BASENAME
 */

#include <stdio.h>

#include "s_input.h"
#include "s_print.h"

/*
 * 「金糸雀(かなりや)」
 *  (c) 西條八十作詞・成田為三作曲
 *	http://www.mahoroba.ne.jp/~gonbe007/hog/shouka/kanariya.html
 */

void kyoku_1(void) {

		/* 一番 */
	s_print_string ( "唄を忘れた 金糸雀(かなりや)は\n" );
	s_print_string ( "後の山に 棄てましょか\n" );
	s_print_string ( "いえ いえ それはなりませぬ\n" );

	s_print_newline();
}

void kyoku_2(void) {

		/* ニ番 */
	 s_print_string ( "唄を忘れた 金糸雀(かなりや)は\n" );
	 s_print_string ( "背戸の小薮に 埋けましょか\n" );
	 s_print_string ( "いえ いえ それはなりませぬ\n" );

	 s_print_newline();
}

/*
 * main
 */

int main ( int argc, char *argv[] ) {

	kyoku_1();
	kyoku_2();

	return 0;
}
sample-008.c の実行結果
$ ./sample-008.exe
唄を忘れた 金糸雀(かなりや)は
後の山に 棄てましょか
いえ いえ それはなりませぬ

唄を忘れた 金糸雀(かなりや)は
背戸の小薮に 埋けましょか
いえ いえ それはなりませぬ

$ 

Download : sample-009.c ( SJIS 版 )

sample-009.c
/*
 * 2015/07/03 sample-009.c
 */

/*
 *  関数と引数変数 (「置き換え」による理解 )
 *
 * 利用方法
 *		コンパイル
 *			cc -Ic:\usr\c\include -o BASENAME.exe sample-009.c
 *		実行
 *			BASENAME
 */

#include <stdio.h>

#include "s_input.h"
#include "s_print.h"

/*
 * 「金糸雀(かなりや)」
 *  (c) 西條八十作詞・成田為三作曲
 *	http://www.mahoroba.ne.jp/~gonbe007/hog/shouka/kanariya.html
 */

void kyoku_n ( char *string ) {

	s_print_string ( "唄を忘れた 金糸雀(かなりや)は\n" );
	s_print_string ( string );
	s_print_string ( "いえ いえ それはなりませぬ\n" );

	s_print_newline();
}

void kyoku_1(void) {

		/* 一番 */
	kyoku_n ( "後の山に 棄てましょか\n" );
}

void kyoku_2(void) {

		/* ニ番 */
	kyoku_n ( "背戸の小薮に 埋けましょか\n" );
}

/*
 * main
 */

int main ( int argc, char *argv[] ) {

	kyoku_1();
	/*
		kyoku_1();
			↓
		kyoku_n ( "後の山に 棄てましょか\n" );
			↓
				string ← "後の山に 棄てましょか\n"

		s_print_string ( "唄を忘れた 金糸雀(かなりや)は\n" );
		s_print_string ( string );
		s_print_string ( "いえ いえ それはなりませぬ\n" );

		s_print_newline();
			↓
		s_print_string ( "唄を忘れた 金糸雀(かなりや)は\n" );
		s_print_string ( "後の山に 棄てましょか\n" );
		s_print_string ( "いえ いえ それはなりませぬ\n" );

		s_print_newline();
	*/

	kyoku_2();

	return 0;
}
sample-009.c の実行結果
$ ./sample-009.exe
唄を忘れた 金糸雀(かなりや)は
後の山に 棄てましょか
いえ いえ それはなりませぬ

唄を忘れた 金糸雀(かなりや)は
背戸の小薮に 埋けましょか
いえ いえ それはなりませぬ

$ 

Download : sample-010.c ( SJIS 版 )

sample-010.c
/*
 * 2015/07/03 sample-010.c
 */

/*
 *  関数と引数変数 (「代入」による理解 )
 *
 * 利用方法
 *		コンパイル
 *			cc -Ic:\usr\c\include -o BASENAME.exe sample-010.c
 *		実行
 *			BASENAME
 */

#include <stdio.h>

#include "s_input.h"
#include "s_print.h"

/*
 * 「金糸雀(かなりや)」
 *  (c) 西條八十作詞・成田為三作曲
 *	http://www.mahoroba.ne.jp/~gonbe007/hog/shouka/kanariya.html
 */

void kyoku_n ( char *string ) {

	s_print_string ( "唄を忘れた 金糸雀(かなりや)は\n" );
	s_print_string ( string );
	s_print_string ( "いえ いえ それはなりませぬ\n" );

	s_print_newline();
}

void kyoku_1(void) {

		/* 一番 */
	kyoku_n ( "後の山に 棄てましょか\n" );
}

void kyoku_2(void) {

		/* ニ番 */
	kyoku_n ( "背戸の小薮に 埋けましょか\n" );
}

/*
 * main
 */

int main ( int argc, char *argv[] ) {

	/*
	kyoku_1();
	*/

	{
		char *string = "後の山に 棄てましょか\n";	/* 変数宣言と代入 */

		s_print_string ( "唄を忘れた 金糸雀(かなりや)は\n" );
		s_print_string ( string );					/* 代入された値が使われる */
		s_print_string ( "いえ いえ それはなりませぬ\n" );

		s_print_newline();
	}

	kyoku_2();

	return 0;
}
sample-010.c の実行結果
$ ./sample-010.exe
唄を忘れた 金糸雀(かなりや)は
後の山に 棄てましょか
いえ いえ それはなりませぬ

唄を忘れた 金糸雀(かなりや)は
背戸の小薮に 埋けましょか
いえ いえ それはなりませぬ

$ 

Download : sample-011.c ( SJIS 版 )

sample-011.c
/*
 * 2015/07/03 sample-011.c
 */

/*
 *  変数宣言と代入
 *
 * 利用方法
 *		コンパイル
 *			cc -Ic:\usr\c\include -o BASENAME.exe sample-011.c
 *		実行
 *			BASENAME
 */

#include <stdio.h>

#include "s_input.h"
#include "s_print.h"

/*
 * 「金糸雀(かなりや)」
 *  (c) 西條八十作詞・成田為三作曲
 *	http://www.mahoroba.ne.jp/~gonbe007/hog/shouka/kanariya.html
 */

/*
 * main
 */

int main ( int argc, char *argv[] ) {

	{
		char *string = "後の山に 棄てましょか\n";	/* 変数宣言と代入 */

		s_print_string ( "唄を忘れた 金糸雀(かなりや)は\n" );
		s_print_string ( string );					/* 代入された値が使われる */
		s_print_string ( "いえ いえ それはなりませぬ\n" );

		s_print_newline();
	}

			/* ブロック内の宣言は、ブロックの外では無効 */

	{
		char *string = "背戸の小薮に 埋けましょか\n";	/* 再宣言 */

		s_print_string ( "唄を忘れた 金糸雀(かなりや)は\n" );
		s_print_string ( string );					/* 代入された値が使われる */
		s_print_string ( "いえ いえ それはなりませぬ\n" );

		s_print_newline();
	}

	return 0;
}
sample-011.c の実行結果
$ ./sample-011.exe
唄を忘れた 金糸雀(かなりや)は
後の山に 棄てましょか
いえ いえ それはなりませぬ

唄を忘れた 金糸雀(かなりや)は
背戸の小薮に 埋けましょか
いえ いえ それはなりませぬ

$ 

Download : sample-012.c ( SJIS 版 )

sample-012.c
/*
 * 2015/07/03 sample-012.c
 */

/*
 *  変数宣言と代入
 *
 * 利用方法
 *		コンパイル
 *			cc -Ic:\usr\c\include -o BASENAME.exe sample-012.c
 *		実行
 *			BASENAME
 */

#include <stdio.h>

#include "s_input.h"
#include "s_print.h"

/*
 * 「金糸雀(かなりや)」
 *  (c) 西條八十作詞・成田為三作曲
 *	http://www.mahoroba.ne.jp/~gonbe007/hog/shouka/kanariya.html
 */

/*
 * main
 */

int main ( int argc, char *argv[] ) {

	char *string;	/* 変数宣言 (変数宣言はブロックの先頭で行う) */

		/* 一番 */

	string = "後の山に 棄てましょか\n";	/* 代入 */

	s_print_string ( "唄を忘れた 金糸雀(かなりや)は\n" );
	s_print_string ( string );			/* 代入された値が使われる */
	s_print_string ( "いえ いえ それはなりませぬ\n" );

	s_print_newline();

		/* ニ番 */

	string = "背戸の小薮に 埋けましょか\n";	/* (再)代入 */

	s_print_string ( "唄を忘れた 金糸雀(かなりや)は\n" );
	s_print_string ( string );				/* 最後に代入された値が使われる */
	s_print_string ( "いえ いえ それはなりませぬ\n" );

	s_print_newline();

	return 0;
}
sample-012.c の実行結果
$ ./sample-012.exe
唄を忘れた 金糸雀(かなりや)は
後の山に 棄てましょか
いえ いえ それはなりませぬ

唄を忘れた 金糸雀(かなりや)は
背戸の小薮に 埋けましょか
いえ いえ それはなりませぬ

$ 

Download : sample-013.c ( SJIS 版 )

sample-013.c
/*
 * 2015/07/03 sample-013.c
 */

/*
 *  代入を使わざず、二つの整数の和を計算する
 *
 * 利用方法
 *		コンパイル
 *			cc -Ic:\usr\c\include -o BASENAME.exe sample-013.c
 *		実行
 *			BASENAME
 */

#include <stdio.h>

#include "s_input.h"
#include "s_print.h"

/*
 * print_sum
 */

void print_sum ( int a, int b ) {

	 s_print_int ( a );
	 s_print_string ( "と" );
	 s_print_int ( b );
	 s_print_string ( "の和は" );
	 s_print_int ( a+b );
	 s_print_string ( "です。\n" );

}

/*
 * print_sum_one_and_input
 */

void print_sum_one_and_input ( int a ) {

	print_sum ( a, s_input_int() );

}

/*
 * main
 */

int main ( int argc, char *argv[] ) {

	s_print_string ( "二つの数を入力してください\n" );
	print_sum_one_and_input ( s_input_int() );

	return 0;
}
入力例
12
56
sample-013.c の実行結果
$ ./sample-013.exe < sample-013.in
二つの数を入力してください
12
56
12と56の和は68です。
$ 

Download : sample-014.c ( SJIS 版 )

sample-014.c
/*
 * 2015/07/03 sample-014.c
 */

/*
 *  代入を利用して、二つの整数の和を計算する
 *
 * 利用方法
 *		コンパイル
 *			cc -Ic:\usr\c\include -o BASENAME.exe sample-014.c
 *		実行
 *			BASENAME
 */

#include <stdio.h>

#include "s_input.h"
#include "s_print.h"

/*
 * main
 */

int main ( int argc, char *argv[] ) {
	int a;		/* 変数の宣言 (ブロックの先頭でしかできない) */
	int b;		/* 変数の宣言 */

	s_print_string ( "二つの数を入力してください\n" );

	a = s_input_int();	/* 変数 a への代入 */
	b = s_input_int();	/* 変数 b への代入 */
						/* 命令の並びの順と、キーボードから入力される順が一致 */

	s_print_int ( a );
	s_print_string ( "と" );
	s_print_int ( b );
	s_print_string ( "の和は" );
	s_print_int ( a+b );
	s_print_string ( "です。\n" );

	return 0;
}
入力例
12
56
sample-014.c の実行結果
$ ./sample-014.exe < sample-014.in
二つの数を入力してください
12
56
12と56の和は68です。
$ 

Download : sample-015.c ( SJIS 版 )

sample-015.c
/*
 * 2015/07/03 sample-015.c
 */

/*
 *  1 〜 5 までを出力
 *
 * 利用方法
 *		コンパイル
 *			cc -Ic:\usr\c\include -o BASENAME.exe sample-015.c
 *		実行
 *			BASENAME
 */

#include <stdio.h>

#include "s_input.h"
#include "s_print.h"

/*
 * main
 */

int main ( int argc, char *argv[] ) {

	/*
	*/

	s_print_int ( 1 );
	s_print_newline();

	s_print_int ( 2 );
	s_print_newline();

	s_print_int ( 3 );
	s_print_newline();

	s_print_int ( 4 );
	s_print_newline();

	s_print_int ( 5 );
	s_print_newline();

	return 0;
}
sample-015.c の実行結果
$ ./sample-015.exe
1
2
3
4
5
$ 

Download : sample-016.c ( SJIS 版 )

sample-016.c
/*
 * 2015/07/03 sample-016.c
 */

/*
 *  1 〜 5 までを出力 (変数を導入してみる)
 *
 * 利用方法
 *		コンパイル
 *			cc -Ic:\usr\c\include -o BASENAME.exe sample-016.c
 *		実行
 *			BASENAME
 */

#include <stdio.h>

#include "s_input.h"
#include "s_print.h"

/*
 * main
 */

int main ( int argc, char *argv[] ) {

	int i = 1;

	/*
	*/

	s_print_int ( i );
	s_print_newline();

	i = i + 1;				/* 新しい i の値は、古い i の値で計算される */
							/* i ← 1 + 1 = 2 */

	s_print_int ( i );
	s_print_newline();

	i = i + 1;				/* i ← 2 + 1 = 3 */

	s_print_int ( i );
	s_print_newline();

	i = i + 1;				/* i ← 3 + 1 = 4 */

	s_print_int ( i );
	s_print_newline();

	i = i + 1;				/* i ← 4 + 1 = 5 */

	s_print_int ( i );
	s_print_newline();

	i = i + 1;				/* これは不要だが、規則性を尊んで.. */

	return 0;
}
sample-016.c の実行結果
$ ./sample-016.exe
1
2
3
4
5
$ 

Download : sample-020.c ( SJIS 版 )

sample-020.c
/*
 * 2015/07/03 sample-020.c
 */

/*
 * 再帰呼出しと代入
 *
 * 利用方法
 *		コンパイル
 *			cc -Ic:\usr\c\include -o BASENAME.exe sample-020.c
 *		実行
 *			BASENAME
 */

#include <stdio.h>

#include "s_input.h"
#include "s_print.h"

/*
 * factrial
 */

int factrial ( int n ) {

	if ( n > 1 ) {
		return factrial ( n - 1 ) * n;
	} else {
		return 1;
	}

}

/*
 * main
 */

int main ( int argc, char *argv[] ) {
	int n;
	int fac;

	s_print_string ( "一つの数を入力してください\n" );
	n = s_input_int();

	fac = factrial ( n );

	s_print_int ( n );
	s_print_string ( "の階乗は" );
	s_print_int ( fac );
	s_print_string ( "です。\n" );

	return 0;
}
入力例
4
sample-020.c の実行結果
$ ./sample-020.exe < sample-020.in
一つの数を入力してください
4
4の階乗は24です。
$ 

Download : sample-021.c ( SJIS 版 )

sample-021.c
/*
 * 2015/07/03 sample-021.c
 */

/*
 * 再帰呼出しと代入
 *
 * 利用方法
 *		コンパイル
 *			cc -Ic:\usr\c\include -o BASENAME.exe sample-021.c
 *		実行
 *			BASENAME
 */

#include <stdio.h>

#include "s_input.h"
#include "s_print.h"

/*
 * factrial
 */

int factrial ( int n ) {
	int retV = 1;

	if ( n > 1 ) {
		int n1;
		int fac1;

		n1 = n - 1;
		fac1 = factrial ( n1 );
		retV = fac1 * n;
	}

	return retV;
}

/*
 * main
 */

int main ( int argc, char *argv[] ) {
	int number;
	int fac;

	s_print_string ( "一つの数を入力してください\n" );
	number = s_input_int();

	fac = factrial ( number );

	s_print_int ( number );
	s_print_string ( "の階乗は" );
	s_print_int ( fac );
	s_print_string ( "です。\n" );

	return 0;
}
入力例
4
sample-021.c の実行結果
$ ./sample-021.exe < sample-021.in
一つの数を入力してください
4
4の階乗は24です。
$ 

Download : sample-022.c ( SJIS 版 )

sample-022.c
/*
 * 2015/07/03 sample-022.c
 */

/*
 * 再帰呼出しと代入
 *
 * 利用方法
 *		コンパイル
 *			cc -Ic:\usr\c\include -o BASENAME.exe sample-022.c
 *		実行
 *			BASENAME
 */

#include <stdio.h>

#include "s_input.h"
#include "s_print.h"

/*
 * factrial
 */

int factrial ( int n ) {
	int retV = 1;

	if ( n > 1 ) {
		int n1;
		int fac1;

		n1 = n - 1;

		{
			int retV = 1;
			int n;

			n = n1;

			if ( n > 1 ) {
				int n1;
				int fac1;

				n1 = n - 1;
				fac1 = factrial ( n1 );
				retV = fac1 * n;
		 	}

			fac1 = retV;			/* fac1 = factrial ( n1 ); */
		}

		retV = fac1 * n;
	}

	return retV;

}

/*
 * main
 */

int main ( int argc, char *argv[] ) {
	int number;
	int fac;

	s_print_string ( "一つの数を入力してください\n" );
	number = s_input_int();

	fac = factrial ( number );

	s_print_int ( number );
	s_print_string ( "の階乗は" );
	s_print_int ( fac );
	s_print_string ( "です。\n" );

	return 0;
}
入力例
4
sample-022.c の実行結果
$ ./sample-022.exe < sample-022.in
一つの数を入力してください
4
4の階乗は24です。
$ 

Download : sample-023.c ( SJIS 版 )

sample-023.c
/*
 * 2015/07/03 sample-023.c
 */

/*
 * 再帰呼出しと代入
 *
 * 利用方法
 *		コンパイル
 *			cc -Ic:\usr\c\include -o BASENAME.exe sample-023.c
 *		実行
 *			BASENAME
 */

#include <stdio.h>

#include "s_input.h"
#include "s_print.h"

/*
 * factrial
 */

int factrial ( int n ) {
	int retV = 1;

	while ( n > 1 ) {
		retV = retV * n;
		n = n - 1;
 	}

	return retV;

}

/*
 * main
 */

int main ( int argc, char *argv[] ) {
	int number;
	int fac;

	s_print_string ( "一つの数を入力してください\n" );
	number = s_input_int();

	fac = factrial ( number );

	s_print_int ( number );
	s_print_string ( "の階乗は" );
	s_print_int ( fac );
	s_print_string ( "です。\n" );

	return 0;
}
入力例
4
sample-023.c の実行結果
$ ./sample-023.exe < sample-023.in
一つの数を入力してください
4
4の階乗は24です。
$ 

本日の課題

課題プログラム内の「/*名前:ここ*/」の部分を書き換え「/*この部分を完成させなさい*/」の部分にプログラムを追加して、プログラムを完成させます。

課題 20150703-01 : 一つ浮動小数点数値をキーボードから入力し、その立方根を出力する

Download : 20150703-01.c ( SJIS 版 )

20150703-01.c
/*
 * TITLE
 *
 * CDATE FILENAME
 *
 * 方程式 \\cos{x} - x = 0 の正値解を、二分法により、数値的に求める
 *
 * 利用方法
 *		コンパイル
 *			cc -Ic:\usr\c\include -o BASENAME.exe FILENAME -lm
 *				数学関数を利用する場合は -lm を指定する必要がある
 *		実行
 *			./BASENAME.exe
 */

#include <stdio.h>
#include <math.h>		/* 数学関数を利用する場合に必要 */
#include "s_print.h"

/*
	f(x) = x - \cos{x}
*/

double f( double x ) {

	   /* f(x) = x - \cos{x} の値を返す */

	/*
	**	 この部分を完成させなさい
	*/


}

/*
  f(x_0) = 0 となる x_0 が区間 [a,b] の中にはいっていて
		a < b
		f(a) < 0 < f(b)
*/

double solve ( double a, double b ) {

  if ( b - a < 0.0001 ) {
	/* この位、精度があれば、解とみなそう.. */
	return (b+a)/2.0;
  } else {
	/* まだ、[a,b] は広過ぎるので、幅を狭める必要がある */
	if ( f((b+a)/2.0) > 0 ) {
	  /* 答えは、[a,(b+a)/2.0] の中にある */

	/*
	**	 この部分を完成させなさい
	*/

	} else {
	  /* 答えは、[(b+a)/2.0,b] の中にある */
	  return solve ( (b+a)/2.0, b );
	}
  }
}

int main(void) {

  s_print_string ( "f(x)=\\cos{x} - x = 0 の解は " );

	/* 解ある範囲を指定して、関数 solve を呼び出す */

	/*
	**	 この部分を完成させなさい
	*/

  s_print_string ( "です。\n" );

  s_print_string ( "実際に、元の関数に、その値を代入すると " );
  s_print_double ( f( solve ( 0.0, M_PI/2.0 ) ) );
  s_print_string ( " になり、\nかなり 0 に近い事がわかります。\n" );

  return 0;

}
入力例
12.34
20150703-01.c の実行結果
$ ./20150703-01-QQQQ.exe
f(x)=\cos{x} - x = 0 の解は 0.739043です。
実際に、元の関数に、その値を代入すると -0.000070 になり、
かなり 0 に近い事がわかります。
$ 

課題 20150703-02 : C-Curve を描画するプログラム

Download : 20150703-02.c ( SJIS 版 )

20150703-02.c
/*
 * TITLE
 *
 * CDATE FILENAME
 *
 * 標準正規分布
 *	f(x) = \frac{1}{\sqrt{2\pi}}\exp{-x^2/2}
 * の、区間 [0,1] の定積分
 *
 * 利用方法
 *		コンパイル
 *			cc -Ic:\usr\c\include -o BASENAME.exe FILENAME -lm
 *				数学関数を利用する場合は -lm を指定する必要がある
 *		実行
 *			./BASENAME.exe
 */

#include <stdio.h>
#include <math.h>		/* 数学関数を利用する場合に必要 */
#include "s_print.h"

/*
  f(x)=
*/

double f(double x) {

	   /* f(x) = \frac{1}{\sqrt{2\pi}}\exp{-x^2/2} の値を返す */

	/*
	**	 この部分を完成させなさい
	*/

}

/*
 sum ( int k, int n )
	\sum_{i=k}^{n-1} S_i
		= S_k + \sum_{i=k+1}^{n-1} S_i
		= S_k + sum( k+1, n )			再帰呼出し
*/

double sum ( int k, int n ) {

  if ( k < n ) {
	return f(0.0 + k * (1.0-0.0)/10000.0)*(1.0/10000.0) + sum(k+1,n);
  } else {	/* k == n の時は、\sum_{i=n}^{n-1} .. → 0 */

	/*
	**	 この部分を完成させなさい
	*/

  }

}

int main(void) {

s_print_string ( "\\frac{1}{\\sqrt{2\\pi}}\\exp{-x^2/2} を [0,1] 区間で積分すると " \
    );
  s_print_double ( sum ( 0, 10000 ) );
  s_print_string ( " になります。\n" );

  return 0;
}
入力例
abc123
20150703-02.c の実行結果
$ ./20150703-02-QQQQ.exe
\frac{1}{\sqrt{2\pi}}\exp{-x^2/2} を [0,1] 区間で積分すると 0.341353 \
    になります。
$