Download : sample-001.c
/*
 * 2020/10/30 sample-001.c
 */
/*
 * 銀行口座への振込プログラム
 *
 * 利用方法
 *		コンパイル 
 *			cc  -c sample-001.c
 *		リンク 
 *			cc -o sample-001.exe sample-001.c 
 *		実行
 *			./sample-001.exe
 */
#include <stdio.h>
/*
 *	main
 *
 *			現実の世界						プログラムの世界
 *
 * [表現]	栗野の口座						kurino_account
 *
 * [事前]	100 万円						kurino_account = 1000000
 *
 *						振込額 10 万円		transfer_money = 100000
 * 			<振込>							kurino_account = kurino_account + transfer_money
 * [事後]	110 万円
 *
 *			<振込> という「情報上の機能」	<足し算> という「数値上の操作」
 */
int main( int argc, char *argv[] )
{
	int	kurino_account = 1000000;	/* 栗野の銀行口座に 100 万円入っている */
	int transfer_money = 100000;	/* 10 万円の振込をしたい.. */
	printf ( "現在の栗野の残高は %d 万円です。\n", kurino_account / 10000 );
	/* <振込> を行うプログラム */
	printf ( "栗野の口座に %d 万円の振込を行います。\n", transfer_money / 10000 );
			/* 「足し算」が「振込」になる */
	kurino_account = kurino_account + transfer_money;
	printf ( "現在の栗野の残高は %d 万円です。\n", kurino_account / 10000 );
	return 0;
}
$ ./sample-001.exe 現在の栗野の残高は 100 万円です。 栗野の口座に 10 万円の振込を行います。 現在の栗野の残高は 110 万円です。 $
Download : sample-002.c
/*
 * 2020/10/30 sample-002.c
 */
/*
 * ASCII Code を利用した「文字」の操作
 *
 * 利用方法
 *		コンパイル 
 *			cc  -c sample-002.c
 *		リンク 
 *			cc -o sample-002.exe sample-002.c 
 *		実行
 *			./sample-002.exe
 */
#include <stdio.h>
/*
 *	main
 */
int main( int argc, char *argv[] )
{
	char	mathematics_record = 'B';	/* 現在の数学の評価は 'B' */
	printf ( "数学の前評価の結果は %c でした。\n", mathematics_record );
	printf ( "再度確認した所、採点ミスが見付かり、加点した所、グレードが一つ高くなりました。\n" );
	/*
	 *
	 */
	/* 成績のグレードを高くするために 'B' を 'A' にする */
	/*
			現実の世界				データ/表現			プログラムの世界
									ASICC Code
								 ('B'=66, 'A'=65)
	グレードを一段階「高く」する : 'B' -----> 'A'
							      66 -----> 65			: 1 減らす
	*/
	mathematics_record = mathematics_record - 1;
	/*
	 *
	 */
	printf ( "その結果、数学の最終評価は %c になりました。\n", mathematics_record );
	return 0;
}
$ ./sample-002.exe 数学の前評価の結果は B でした。 再度確認した所、採点ミスが見付かり、加点した所、グレードが一つ高くなりました。 その結果、数学の最終評価は A になりました。 $
Download : sample-003.c
/*
 * 2020/10/30 sample-003.c
 */
/*
 * 平面上の「点」の二つの表現銀行口座への振込プログラム
 *
 * 利用方法
 *		コンパイル 
 *			cc  -c sample-003.c
 *		リンク  ( M_PI,sin,cos を利用するので 「-lm」が必須 )
 *			cc -o sample-003.exe sample-003.c -lm
 *		実行
 *			./sample-003.exe
 */
#include <stdio.h>
#include <math.h>		/* sin, cos を利用するので.. */
/*
 *	void print_orthogonal ( char name, double x, double y )
 *		直交座標の表示
 *		char name;	点の名前
 *		double x;	直交座標の X 座標
 *		double y;	直交座標の Y 座標
 */
void print_orthogonal ( char name, double x, double y ) {
	 printf ( "点 %c の直交座標は (%f,%f) です。\n", name, x, y );
}
/*
 *	void print_polar ( char name, double r, double a )
 *		極座標の表示
 *		char name;	点の名前
 *		double r;	極座標の動径
 *		double a;	極座標の偏角
 */
void print_polar ( char name, double r, double a ) {
	 printf ( "点 %c の極座標は (%f,%f) です。\n", name, r, a );
}
/*
 *	main
 */
int main( int argc, char *argv[] )
{
	/*
		点 P : 座標 (2,3)
	*/
	double P_orthogonal_x = 2.0;		/* 点 P の直交座標系の x 座標 */
	double P_orthogonal_y = 3.0;		/* 点 P の直交座標系の y 座標 */
	double P_polar_radius;		/* 点 P の極座標系の動径 */
	double P_polar_argument;	/* 点 P の極座標系の偏角 */
	/*
		点 Q : 原点から 7 離れており、角度は x 軸に対して 60 度 ( Pi/3 )
	*/
	double Q_orthogonal_x;		/* 点 Q の直交座標系の x 座標 */
	double Q_orthogonal_y;		/* 点 Q の直交座標系の y 座標 */
	double Q_polar_radius = 7.0;		/* 点 Q の極座標系の動径 */
	double Q_polar_argument = M_PI/3;	/* 点 Q の極座標系の偏角 */
	/*
	 * 点 P の表示
	 */
	print_orthogonal ( 'P', P_orthogonal_x, P_orthogonal_y );
			/*
			 * r = \sqrt{x^2+y^2} なので
			 */
	P_polar_radius = sqrt ( P_orthogonal_x * P_orthogonal_x + P_orthogonal_y * P_orthogonal_y );
			/*
			 *	a = \tan^{-1}{y/x} なので
			 *		cf. http://www1.cts.ne.jp/~clab/hsample/Math/Math2.html	  
			*/
	P_polar_argument = atan ( P_orthogonal_y / P_orthogonal_x );
	print_polar ( 'P', P_polar_radius , P_polar_argument );
	/*
	 * 点 Q の表示
	 */
	print_polar ( 'Q', Q_polar_radius, Q_polar_argument );
			/*
			 * x = r \cos{a} なので
			 */
	Q_orthogonal_x = Q_polar_radius * cos( Q_polar_argument );
			/*
			 * y = r \sin{a} なので
			*/
	Q_orthogonal_y = Q_polar_radius * sin( Q_polar_argument );
	print_orthogonal ( 'Q', Q_orthogonal_x, Q_orthogonal_y );
	return 0;
}
$ ./sample-003.exe 点 P の直交座標は (2.000000,3.000000) です。 点 P の極座標は (3.605551,0.982794) です。 点 Q の極座標は (7.000000,1.047198) です。 点 Q の直交座標は (3.500000,6.062178) です。 $
Download : sample-004.c
/*
 * 2020/10/30 sample-004.c
 */
/*
 * 直交座標で表現されている点 Q から、それと原点に対して対称な点 R を求める
 *
 * 利用方法
 *		コンパイル 
 *			cc  -c sample-004.c
 *		リンク 
 *			cc -o sample-004.exe sample-004.c 
 *		実行
 *			./sample-004.exe
 */
#include <stdio.h>
/*
 *	void print_orthogonal ( char name, double x, double y )
 *		直交座標の表示
 *		char name;	点の名前
 *		double x;	直交座標の X 座標
 *		double y;	直交座標の Y 座標
 */
void print_orthogonal ( char name, double x, double y ) {
	 printf ( "点 %c の直交座標は (%f,%f) です。\n", name, x, y );
}
/*
 *	main
 */
int main( int argc, char *argv[] )
{
	/*
		点 P : 座標 (2,3)
	*/
	double P_orthogonal_x = 2.0;		/* 点 P の直交座標系の x 座標 */
	double P_orthogonal_y = 3.0;		/* 点 P の直交座標系の y 座標 */
	double R_orthogonal_x;				/* 点 P と原点対称な点 R の x 座標 */
	double R_orthogonal_y;				/* 点 P と原点対称な点 R の y 座標 */
	/*
	 * 点 P の表示
	 */
	print_orthogonal ( 'P', P_orthogonal_x, P_orthogonal_y );
	/*
	 * 点 R の計算
	 */
				/* R の x 座標は P の x 座標の符号を変えた物 */
	R_orthogonal_x = - P_orthogonal_x;
				/* R の y 座標は P の y 座標の符号を変えた物 */
	R_orthogonal_y = - P_orthogonal_y;
	/*
	 * 点 R の表示
	 */
	print_orthogonal ( 'R', R_orthogonal_x, R_orthogonal_y );
	return 0;
}
$ ./sample-004.exe 点 P の直交座標は (2.000000,3.000000) です。 点 R の直交座標は (-2.000000,-3.000000) です。 $
Download : sample-005.c
/*
 * 2020/10/30 sample-005.c
 */
/*
 * 平面上の点を扱う
 *
 * 利用方法
 *		コンパイル 
 *			cc  -c sample-005.c
 *		リンク 
 *			cc -o sample-005.exe sample-005.c -lm
 *		実行
 *			./sample-005.exe
 */
#include <stdio.h>
#include <math.h>		/* sqrt を利用するので必要 (-lm も忘れずに ) */
/*
 * void print_point ( double px, double py )
 * 		「点」を表示する
 *		double px -- 「点」の x 座標
 *		double py -- 「点」の y 座標
 */
void print_point ( double px, double py )		{
	 printf ( "( %f, %f )", px, py );
}
/*
 * double point_distance ( double p1x, double p1y, double p2x, double p2y )
 * 		ニ「点」間の距離を返す
 *		double p1x -- 「始点」の x 座標
 *		double p1y -- 「始点」の y 座標
 *		double p2x -- 「終点」の x 座標
 *		double p2y -- 「終点」の y 座標
 */
double point_distance ( double p1x, double p1y, double p2x, double p2y ) {
	   double dx = p2x - p1x;	/* x 座標の差 */
	   double dy = p2y - p1y;	/* y 座標の差 */
	   return sqrt ( dx*dx + dy*dy );
}
/*
 *	main
 */
int main( int argc, char *argv[] )
{
	double p1x = 1.0;	/* p1 = ( 1.0, 2.0 ) */
	double p1y = 2.0;
	double p2x = 4.0;	/* p2 = ( 4.0, 6.0 ) */
	double p2y = 6.0;
	printf ( "始点 " );
	print_point ( p1x, p1y );
	printf ( " と終点 " );
	print_point ( p2x, p2y );
	printf ( " との距離は %f です。\n", point_distance ( p1x, p1y, p2x, p2y ) );
	return 0;
}
$ ./sample-005.exe 始点 ( 1.000000, 2.000000 ) と終点 ( 4.000000, 6.000000 ) との距離は 5.000000 です。 $
Download : sample-006.c
/*
 * 2020/10/30 sample-006.c
 */
/*
 * 平面上の点の操作
 *
 * 利用方法
 *		コンパイル 
 *			cc  -c sample-006.c
 *		リンク 
 *			cc -o sample-006.exe sample-006.c -lm
 *		実行
 *			./sample-006.exe
 */
#include <stdio.h>
#include <math.h>		/* sqrt を利用するので必要 (-lm も忘れずに ) */
/*
 * void print_point ( double px, double py )
 * 		「点」を表示する
 *		double px -- 「点」の x 座標
 *		double py -- 「点」の y 座標
 */
void print_point ( double px, double py )		{
	 printf ( "( %f, %f )", px, py );
}
/*
 * void mirror_x_point ( double py )
 * 		x 軸に対し線対称の「点」の y 座標を求める
 *		double py -- 「点」の y 座標
 */
double mirror_x_point ( double py )		{
	return - py;
}
/*
 * void mirror_y_point ( double px )
 * 		y 軸に対し線対称の「点」の x 座標を求める
 *		double px -- 「点」の x 座標
 */
double mirror_y_point ( double px )		{
	return - px;
}
/*
 *	main
 */
int main( int argc, char *argv[] )
{
	double p1x = 1.0;	/* p1 = ( 1.0, 2.0 ) */
	double p1y = 2.0;
	double p2x;
	double p2y;
			/* x 軸に対して線対象 */
	printf ( "点 " );
	print_point ( p1x, p1y );
	printf ( " と x 軸に対して線対称な点は " );
	p2x = p1x;						/* x 座標は変らない */
	p2y = mirror_x_point ( p1y );	/* y 座標のみ計算 */
	print_point ( p2x, p2y );
	printf ( " となります。\n" );
			/* y 軸に線対象 */
	printf ( "点 " );
	print_point ( p1x, p1y );
	printf ( " と y 軸に対して線対称な点は " );
	p2x = mirror_x_point ( p1x );	/* x 座標のみ計算 */
	p2y = p1y;						/* y 座標は変らない */
	print_point ( p2x, p2y );
	printf ( " となります。\n" );
	return 0;
}
$ ./sample-006.exe 点 ( 1.000000, 2.000000 ) と x 軸に対して線対称な点は ( 1.000000, -2.000000 ) となります。 点 ( 1.000000, 2.000000 ) と y 軸に対して線対称な点は ( -1.000000, 2.000000 ) となります。 $
Download : sample-007.c
/*
 * 2020/10/30 sample-007.c
 */
/*
 * 平面上の点の操作
 *
 * 利用方法
 *		コンパイル 
 *			cc  -c sample-007.c
 *		リンク 
 *			cc -o sample-007.exe sample-007.c 
 *		実行
 *			./sample-007.exe
 */
#include <stdio.h>
/*
 * void print_point ( double px, double py )
 * 		「点」を表示する
 *		double px -- 「点」の x 座標
 *		double py -- 「点」の y 座標
 */
void print_point ( double px, double py )		{
	 printf ( "( %f, %f )", px, py );
}
/*
 * void mirror_o_point_x ( double px )
 * 		原点に対し点対称の「点」の x 座標を求める
 *		double px -- 「点」の x 座標
 */
double mirror_o_point_x ( double px )		{
	return - px;
}
/*
 * void mirror_o_point_y ( double py )
 * 		原点に対し点対称の「点」の y 座標を求める
 *		double py -- 「点」の y 座標
 */
double mirror_o_point_y ( double py )		{
	return - py;
}
/*
 *	main
 */
int main( int argc, char *argv[] )
{
	double p1x = 1.0;	/* p1 = ( 1.0, 2.0 ) */
	double p1y = 2.0;
	double p2x;
	double p2y;
			/* 原点に点対象 */
	printf ( "点 " );
	print_point ( p1x, p1y );
	printf ( " と原点に対して点線対称な点は " );
		/* x と y の処理を別々に行う.. */
	p2x = mirror_o_point_x ( p1x );
	p2y = mirror_o_point_y ( p1y );
	print_point ( p2x, p2y );
	printf ( " となります。\n" );
	return 0;
}
$ ./sample-007.exe 点 ( 1.000000, 2.000000 ) と原点に対して点線対称な点は ( -1.000000, -2.000000 ) となります。 $
Download : sample-008.c
/*
 * 2020/10/30 sample-008.c
 */
/*
 * 平面上の点の操作
 *
 * 利用方法
 *		コンパイル 
 *			cc  -c sample-008.c
 *		リンク 
 *			cc -o sample-008.exe sample-008.c -lm
 *		実行
 *			./sample-008.exe
 */
#include <stdio.h>
#include <math.h>		/* sqrt を利用するので必要 (-lm も忘れずに ) */
/*
 * void print_point ( double px, double py )
 * 		「点」を表示する
 *		double px -- 「点」の x 座標
 *		double py -- 「点」の y 座標
 */
void print_point ( double px, double py )		{
	 printf ( "( %f, %f )", px, py );
}
/*
 * void mirror_x_point ( double py )
 * 		x 軸に対し線対称の「点」の y 座標を求める
 *		double py -- 「点」の y 座標
 */
double mirror_x_point ( double py )		{
	return - py;
}
/*
 * void mirror_y_point ( double px )
 * 		y 軸に対し線対称の「点」の x 座標を求める
 *		double px -- 「点」の x 座標
 */
double mirror_y_point ( double px )		{
	return - px;
}
/*
 *	main
 */
int main( int argc, char *argv[] )
{
	double p1x = 1.0;	/* p1 = ( 1.0, 2.0 ) */
	double p1y = 2.0;
	double p2x;
	double p2y;
			/* x 軸に対して線対象 */
	printf ( "点 " );
	print_point ( p1x, p1y );
	printf ( " と x 軸に対して線対称な点は " );
	p2x = p1x;						/* x 座標は変らない */
	p2y = mirror_x_point ( p1y );	/* y 座標のみ計算 */
	print_point ( p2x, p2y );
	printf ( " となります。\n" );
			/* y 軸に線対象 */
	printf ( "点 " );
	print_point ( p1x, p1y );
	printf ( " と y 軸に対して線対称な点は " );
	p2x = mirror_x_point ( p1x );	/* x 座標のみ計算 */
	p2y = p1y;						/* y 座標は変らない */
	print_point ( p2x, p2y );
	printf ( " となります。\n" );
	return 0;
}
$ ./sample-008.exe 点 ( 1.000000, 2.000000 ) と x 軸に対して線対称な点は ( 1.000000, -2.000000 ) となります。 点 ( 1.000000, 2.000000 ) と y 軸に対して線対称な点は ( -1.000000, 2.000000 ) となります。 $
Download : sample-009.c
/*
 * 2020/10/30 sample-009.c
 */
/*
 * 平面上の点の操作 (構造体の利用例)
 *
 * 利用方法
 *		コンパイル 
 *			cc  -c sample-009.c
 *		リンク 
 *			cc -o sample-009.exe sample-009.c 
 *		実行
 *			./sample-009.exe
 */
#include <stdio.h>
/*
 * 最初に、直交座標で「点」を表現する型を作ってしまう
 */
typedef struct {
	double x;		/* 直交座標の x 座標を表すタグ名 */
	double y;		/* 直交座標の y 座標を表すタグ名 */
} Orthogonal;		/* Orthogonal 型の宣言 */
/*
 * void print_point ( Orthogonal pt );
 * 		「点」を表示する
 *		Orthogonal pt; 直交座標系で表現された「点」の座標
 */
void print_point ( Orthogonal pt )		{
	 /*
	  *	構造体の要素は、タグ名を利用して参照できる
	  */
	 printf ( "( %f, %f )", pt.x, pt.y );
}
/*
 * Orthogonal mirror_o_point ( Orthogonal pt )
 * 		原点に対し点対称の「点」を求める
 *		Orthogonal pt; 直交座標系で表現された「点」の座標
 *		値 点対称の「点」を求める
 */
Orthogonal mirror_o_point ( Orthogonal pt )		{
	Orthogonal result;		/* 返す値を入れる変数 */
	result.x = - pt.x;		/* 結果の x 座標は、元の x 座標の符号をかえた物 */
	result.y = - pt.y;
	return result;			/* 構造体の値が返せる */
}
/*
 *	main
 */
int main( int argc, char *argv[] )
{
	Orthogonal p1;
	Orthogonal p2;
	p1.x = 1.0;	/* p1 = ( 1.0, 2.0 ) */
	p1.y = 2.0;
		/* 原点に点対象 */
	printf ( "点 " );
		/* 構造体は引数で、そのまま渡せる */
	print_point ( p1 );
	printf ( " と原点に対して点線対称な点は " );
		/* 構造体は、値としても取り出せるし、普通に代入もできる */
	p2 = mirror_o_point ( p1 );
	print_point ( p2 );
	printf ( " となります。\n" );
	return 0;
}
$ ./sample-009.exe 点 ( 1.000000, 2.000000 ) と原点に対して点線対称な点は ( -1.000000, -2.000000 ) となります。 $
Download : sample-010.c
/*
 * 2020/10/30 sample-010.c
 */
/*
 * 名前を付けた点
 *
 * 利用方法
 *		コンパイル 
 *			cc  -c sample-010.c
 *		リンク 
 *			cc -o sample-010.exe sample-010.c 
 *		実行
 *			./sample-010.exe
 */
#include <stdio.h>
/*
 * 最初に、直交座標で「点」を表現する型を作ってしまう
 */
typedef struct {
	double x;		/* 直交座標の x 座標を表すタグ名 */
	double y;		/* 直交座標の y 座標を表すタグ名 */
} Orthogonal;		/* Orthogonal 型の宣言 */
/*
 * 更に、「名前付き」の「点」の型
 */
typedef struct {
    char name;				/* 点の名前 */
	Orthogonal coordinate;	/* 点の座標 */
} NPoint;
/*
 * void print_point ( Orthogonal pt );
 * 		「点」を表示する
 *		Orthogonal pt; 直交座標系で表現された「点」の座標
 */
void print_point ( Orthogonal pt )		{
	 /*
	  *	構造体の要素は、タグ名を利用して参照できる
	  */
	 printf ( "( %f, %f )", pt.x, pt.y );
}
/*
 * void print_npoint ( NPoint npt );
 * 		名前付きの「点」を表示する
 *		NPoint npt; 名前付きの「点」
 */
void print_npoint ( NPoint npt ) {
	printf ( "点 %c の直交座標は ", npt.name );
	print_point ( npt.coordinate );
	printf ( "です。\n" );
}
/*
 *	main
 */
int main( int argc, char *argv[] )
{
	NPoint p;	/* 点「P」*/
	p.name = 'P';	/* 点「P」の名前は 'P' */
	p.coordinate.x = 1.0;	/* p.coordinate = ( 1.0, 2.0 ) */
	p.coordinate.y = 2.0;
	print_npoint ( p );		/* 点「P」を表示 */
	return 0;
}
$ ./sample-010.exe 点 P の直交座標は ( 1.000000, 2.000000 )です。 $
Download : sample-011.c
/*
 * 2020/10/30 sample-011.c
 */
/*
 * 三次元空間内の点の操作 (構造体の利用例)
 *
 * 利用方法
 *		コンパイル 
 *			cc  -c sample-011.c
 *		リンク 
 *			cc -o sample-011.exe sample-011.c 
 *		実行
 *			./sample-011.exe
 */
#include <stdio.h>
/*
 * 「名前付き」の空間の「点」の型
 */
typedef struct {
    char name;		/* 点の名前 */
	double x;		/* 直交座標の x 座標を表すタグ名 */
	double y;		/* 直交座標の y 座標を表すタグ名 */
	double z;		/* 直交座標の z 座標を表すタグ名 */
} NPoint3D;
/*
 * void print_point3D ( NPoint3D npt );
 * 		「点」を表示する
 *		NPoint3D npt; 直交座標系で表現された「点」の座標
 */
void print_point ( NPoint3D pt )		{
	printf ( "点 %c の直交座標は ", pt.name );
	printf ( "( %f, %f, %f )", pt.x, pt.y, pt.z );
	printf ( "です。\n" );
}
/*
 * NPoint3D mirror_o_point ( NPoint3D pt )
 * 		原点に対し点対称の「点」を求める
 *		NPoint3D pt; 直交座標系で表現された「点」の座標
 *		値 点対称の「点」を求める
 */
NPoint3D mirror_o_point ( char newName, NPoint3D pt )		{
	NPoint3D result;		/* 返す値を入れる変数 */
	result.name = newName;	/* 名前は新しい物にする */
	result.x = - pt.x;		/* 結果の x 座標は、元の x 座標の符号をかえた物 */
	result.y = - pt.y;		/* 以下同様 */
	result.z = - pt.z;
	return result;			/* 構造体の値が返せる */
}
/*
 *	main
 */
int main( int argc, char *argv[] )
{
	NPoint3D p;
	NPoint3D q;
	p.name = 'P';
	p.x = 1.0;	/* P = ( 1.0, 2.0, 3.0 ) */
	p.y = 2.0;
	p.z = 3.0;
		/* 原点に点対象 */
	print_point ( p );
		/* 構造体は、値としても取り出せるし、普通に代入もできる */
	q = mirror_o_point ( 'Q', p );
	printf ( "これと、原点に対して対称な、" );
	print_point ( q );
	return 0;
}
$ ./sample-011.exe 点 P の直交座標は ( 1.000000, 2.000000, 3.000000 )です。 これと、原点に対して対称な、点 Q の直交座標は ( -1.000000, -2.000000, -3.000000 )です。 $
Download : sample-012.c
/*
 * 2020/10/30 sample-012.c
 */
/*
 * N 次元空間内の点の操作 (構造体/配列の利用例)
 *
 * 利用方法
 *		コンパイル 
 *			cc  -c sample-012.c
 *		リンク 
 *			cc -o sample-012.exe sample-012.c 
 *		実行
 *			./sample-012.exe
 */
#include <stdio.h>
/*
 * 「名前付き」の空間の「点」の型
 */
#define	DIM	10	/* 10 次元 */
typedef struct {
    char name;					/* 点の名前 */
	double coordinate[DIM];		/* 直交座標の x 座標を表すタグ名 */
} NPointND;
/*
 * void print_pointND ( NPointND npt );
 * 		「点」を表示する
 *		NPointND npt; 直交座標系で表現された「点」の座標
 */
void print_point ( NPointND pt )		{
	int dim;
	printf ( "点 %c の直交座標は ", pt.name );
	printf ( "( " );
	dim = 0;
	while ( dim < DIM ) {
		printf ( "%f", pt.coordinate[dim] );
		if ( dim < DIM - 1 ) {
			printf ( ", " );
		}
		dim++;
	}
	printf ( " )" );
	printf ( "です。\n" );
}
/*
 * NPointND mirror_o_point ( NPointND pt )
 * 		原点に対し点対称の「点」を求める
 *		NPointND pt; 直交座標系で表現された「点」の座標
 *		値 点対称の「点」を求める
 */
NPointND mirror_o_point ( char newName, NPointND pt )		{
	NPointND result;		/* 返す値を入れる変数 */
	int dim;
	result.name = newName;	/* 名前は新しい物にする */
	dim = 0;
	while ( dim < DIM ) {
		result.coordinate[dim] = - pt.coordinate[dim];
		dim++;
	}
	return result;			/* 構造体の値が返せる */
}
/*
 *	main
 */
int main( int argc, char *argv[] )
{
	NPointND p;
	NPointND q;
	int dim;
	p.name = 'P';
	dim = 0;
	while ( dim < DIM ) {
		p.coordinate[dim] = dim; /* 浮動小数点型に整数値を入れると自動的に変換される */
		dim++;
	}
		/* 原点に点対象 */
	print_point ( p );
		/* 構造体は、値としても取り出せるし、普通に代入もできる */
	q = mirror_o_point ( 'Q', p );
	printf ( "これと、原点に対して対称な、" );
	print_point ( q );
	return 0;
}
$ ./sample-012.exe 点 P の直交座標は ( 0.000000, 1.000000, 2.000000, 3.000000, 4.000000, 5.000000, 6.000000, 7.000000, 8.000000, 9.000000 )です。 これと、原点に対して対称な、点 Q の直交座標は ( -0.000000, -1.000000, -2.000000, -3.000000, -4.000000, -5.000000, -6.000000, -7.000000, -8.000000, -9.000000 )です。 $
/*
 * 課題 CNAME-03
 *
 * 20201023 20201023-03-QQQQ.c
 *
 *	真偽表の作成
 *
 */
#include <stdio.h>
/*
 *	main : 真偽表の作成
 */
int main(void)
{
	int P;		/* 論理値は、整数値なので、整数変数を二つ (P,Q) 利用 */
	int Q;
		/* 真偽値表 */
	printf ( "+-------+----+-------------+\n" );
	printf ( "| 論理値|否定|論理積|論理和|\n" );
	printf ( "+---+---+----+------+------+\n" );
	printf ( "| P | Q | !P | P&&Q | P||Q |\n" );
	printf ( "+---+---+----+------+------+\n" );
	for ( P = 0; P <= 1; P++ )	{		/* これで P = 0(偽), 1(真) となる */
		for ( Q = 0; Q <= 1; Q++ )	{	/* これで Q = 0(偽), 1(真) となる */
			printf ( "| %d | %d |  %d |   %d  |   %d  |\n",
					    P,    Q,   !P,  P&&Q,     P||Q
			);
		}
	}
	printf ( "+---+---+----+------+------+\n" );
	return 0;
}
/*
 * 課題 CNAME-04
 *
 * CDATE FILENAME
 *
 *	ド・モルガンの定理 !(P&&Q) == (!P)||(!Q)
 *		<数学>
 *			not ( P and Q ) <=> (not P) or (not Q)
 *			not ( P or Q ) <=> (not P) and (not Q)
 *				# not を利用して、and を or に、あるいは or を and にできる
 *				#	not と and があれば or はいらない
 *				#		<= ド・モルガンをつかって or を not と and で表せる
 *				#	逆に、 not と or が and がいらない
 */
#include <stdio.h>
/*
 *	not_and ( P, Q ) == !(P&&Q)
 */
int not_and ( int P, int Q ) {
	return !(P&&Q);
}
/*
 *	or_not ( P, Q ) == (!P)||(!Q)
 */
int or_not ( int P, int Q ) {
	return (!P)||(!Q);
}
/*
 *	main : 真偽表の作成
 */
int main(void)
{
	int P;		/* 論理値は、整数値なので、整数変数を二つ (P,Q) 利用 */
	int Q;
		/* 真偽値表 */
	printf ( "+---+---+---------+------------+\n" );
	printf ( "| P | Q | !(P&&Q) | (!P)||(!Q) |\n" );
	printf ( "+---+---+---------+------------+\n" );
	for ( P = 0; P <= 1; P++ )	{		/* これで P = 0(偽), 1(真) となる */
		for ( Q = 0; Q <= 1; Q++ )	{
			printf ( "| %d | %d |    %d    |     %d      |\n",
				P, Q, not_and(P,Q), or_not(P,Q)
			);
		}
	}
	printf ( "+---+---+---------+------------+\n" );
	return 0;
}
#include <stdio.h>
int main(void) {
	int a = -1;
	if ( a > 0 ) {
		if ( a < 2 ) {
			printf ( "0 < a < 1\n" );
		} else {
			printf ( "a < 0\n" );
		}
	}
	return 0;
}
#include <stdio.h>
int main(void) {
	printf ( "(1 == 1) = %d\n", 1 == 1 );
		/* 条件が成立場合 (条件式の値が『真』の場合) */
	printf ( "(0 == 1) = %d\n", 0 == 1 );
		/* 条件が不成立場合 (条件式の値が『偽』の場合) */
	return 0;
}
#include <stdio.h>
#include <string.h>	/* strcmp : 文字列比較をする関数 */
int main(void) {
	printf ( "strcmp(%s,%s) = %d\n",
			"abc", "abc", strcmp( "abc", "abc" ) );
	/* 関数 strcmp の結果は、辞書順のどちら側かをもとめるので */
	/* 一致する場合は 0 => ! で反転して 1 => 真 */
	/*	if ( !strcmp ( a, b ) ) で、文字列 a, b の一致をチェックできる */
	/*		「! 条件式」:「条件式」の真偽値を反転する */
	/*			0 (偽) 		=> 1 (真)	*/
	/*			0 以外(真)	=> 0 (偽)	*/
	
	printf ( "strcmp(%s,%s) = %d\n",
			"abc", "xyz", strcmp( "abc", "xyz" ) );
	printf ( "strcmp(%s,%s) = %d\n",
			"xyz", "abc", strcmp( "xyz", "abc" ) );
	return 0;
}
#include <stdio.h>
/*
	論理演算以前 ( && を使わない場合 )
		二つの条件が同時に成立する事をどうやってやるか
			=> if 構文の組み合わせ
		例: 文字(ch)が大文字を表す
				大文字 ch = 'A' ? 'Z'
					( ASCII Code 表では 'A' から 'Z' がその順に続けて並んでいる )
					( 'A' <= ch ) と ( ch <= 'Z' ) の二つ条件が成立
*/
int main(void) {
	int ch;			/* 文字コードは小さな整数値 */
	printf ( "一文字入力してエンターキーを押してください : " );
	ch = getchar();	/* 一文字キーボードから読み込む */
	if ( 'A' <= ch ) {
		if ( ch <= 'Z' ) {
			printf ( "%c は大文字です。\n", ch );
		}
	}
	return 0;
}
#include <stdio.h>
/*
	論理演算の利用 ( && を使う場合 )
		二つの条件が同時に成立する事をどうやってやるか
			=> 二つの条件を && でつなげればよい
		例: 文字(ch)が大文字を表す
				大文字 ch = 'A' ? 'Z'
					( ASCII Code 表では 'A' から 'Z' がその順に続けて並んでいる )
					( 'A' <= ch ) と ( ch <= 'Z' ) の二つ条件が成立
*/
int main(void) {
	int ch;			/* 文字コードは小さな整数値 */
	printf ( "一文字入力してエンターキーを押してください : " );
	ch = getchar();	/* 一文字キーボードから読み込む */
	if ( ('A' <= ch) && (ch <= 'Z') ) {
		printf ( "%c は大文字です。\n", ch );
	}
	return 0;
}
#include <stdio.h>
/*
	論理演算の利用 ( && を使う場合 )
		二つの条件が同時に成立する事をどうやってやるか
			=> 二つの条件を && でつなげればよい
		例: 文字(ch)が大文字を表す
				大文字 ch = 'A' ? 'Z'
					( ASCII Code 表では 'A' から 'Z' がその順に続けて並んでいる )
					( 'A' <= ch ) と ( ch <= 'Z' ) の二つ条件が成立
*/
int main(void) {
	int ch;			/* 文字コードは小さな整数値 */
	int P;			/* 論理値を取る変数 */
					/* 論理値が「(整数)値」なので、
						(整数型の)変数に保存できる */
	printf ( "一文字入力してエンターキーを押してください : " );
	ch = getchar();	/* 一文字キーボードから読み込む */
	if ( 'A' <= ch ) {
		P = 1;
	} else {
		P = 0;
	}
	
	if ( ch <= 'Z' ) {
		P = P && 1;
	} else {
		P = P && 0;
	}
	if ( P ) {
		printf ( "%c は大文字です。\n", ch );
	}
	return 0;
}
/*
 * 2020/10/30 sample-001.c
 */
/*
 * 銀行口座への振込プログラム
 *
 * 利用方法
 *		コンパイル 
 *			cc  -c sample-001.c
 *		リンク 
 *			cc -o sample-001.exe sample-001.c 
 *		実行
 *			./sample-001.exe
 */
#include <stdio.h>
/*
 *	main
 *
 *			現実の世界						プログラムの世界
 *
 * [表現]	栗野の口座						kurino_account
 *
 * [事前]	100 万円						kurino_account = 1000000
 *
 *						振込額 10 万円		transfer_money = 100000
 * 			<振込>							kurino_account = kurino_account + transfer_money
 * [事後]	110 万円
 *
 *			<振込> という「情報上の機能」	<足し算> という「数値上の操作」
 */
int main( int argc, char *argv[] )
{
	int	kurino_account = 1000000;	/* 栗野の銀行口座に 100 万円入っている */
	int transfer_money = 100000;	/* 10 万円の振込をしたい.. */
	printf ( "現在の栗野の残高は %d 万円です。\n", kurino_account / 10000 );
	/* <振込> を行うプログラム */
	printf ( "栗野の口座に %d 万円の振込を行います。\n", transfer_money / 10000 );
			/* 「足し算」が「振込」になる */
	kurino_account = kurino_account + transfer_money;
	printf ( "現在の栗野の残高は %d 万円です。\n", kurino_account / 10000 );
	return 0;
}
/*
 * 2020/10/30 sample-002.c
 */
/*
 * ASCII Code を利用した「文字」の操作
 *
 * 利用方法
 *		コンパイル 
 *			cc  -c sample-002.c
 *		リンク 
 *			cc -o sample-002.exe sample-002.c 
 *		実行
 *			./sample-002.exe
 */
#include <stdio.h>
/*
 *	main
 */
int main( int argc, char *argv[] )
{
	char	mathematics_record = 'B';	/* 現在の数学の評価は 'B' */
	printf ( "数学の前評価の結果は %c でした。\n", mathematics_record );
	printf ( "再度確認した所、採点ミスが見付かり、加点した所、グレードが一つ高くなりました。\n" );
	/*
	 *
	 */
	/* 成績のグレードを高くするために 'B' を 'A' にする */
	/*
			現実の世界				データ/表現			プログラムの世界
									ASICC Code
								 ('B'=66, 'A'=65)
	グレードを一段階「高く」する : 'B' -----> 'A'
							      66 -----> 65			: 1 減らす
	*/
	mathematics_record = mathematics_record - 1;
	/*
	 *
	 */
	printf ( "その結果、数学の最終評価は %c になりました。\n", mathematics_record );
	return 0;
}
/*
 * 2020/10/30 sample-003.c
 */
/*
 * 平面上の「点」の二つの表現
 *
 * 利用方法
 *		コンパイル 
 *			cc  -c sample-003.c
 *		リンク  ( M_PI,sin,cos を利用するので 「-lm」が必須 )
 *			cc -o sample-003.exe sample-003.c -lm
 *		実行
 *			./sample-003.exe
 */
#include <stdio.h>
#include <math.h>		/* sin, cos を利用するので.. */
/*
 *	void print_orthogonal ( char name, double x, double y )
 *		直交座標の表示
 *		char name;	点の名前
 *		double x;	直交座標の X 座標
 *		double y;	直交座標の Y 座標
 */
void print_orthogonal ( char name, double x, double y ) {
	 printf ( "点 %c の直交座標は (%f,%f) です。\n", name, x, y );
}
/*
 *	void print_polar ( char name, double r, double a )
 *		極座標の表示
 *		char name;	点の名前
 *		double r;	極座標の動径
 *		double a;	極座標の偏角
 */
void print_polar ( char name, double r, double a ) {
	 printf ( "点 %c の極座標は (%f,%f) です。\n", name, r, a );
}
/*
 *	main
 */
int main( int argc, char *argv[] )
{
	/*
		点 P : 座標 (2,3)
	*/
	double P_orthogonal_x = 2.0;		/* 点 P の直交座標系の x 座標 */
	double P_orthogonal_y = 3.0;		/* 点 P の直交座標系の y 座標 */
	double P_polar_radius;		/* 点 P の極座標系の動径 */
	double P_polar_argument;	/* 点 P の極座標系の偏角 */
	/*
		点 Q : 原点から 7 離れており、角度は x 軸に対して 60 度 ( Pi/3 )
	*/
	double Q_orthogonal_x;		/* 点 Q の直交座標系の x 座標 */
	double Q_orthogonal_y;		/* 点 Q の直交座標系の y 座標 */
	double Q_polar_radius = 7.0;		/* 点 Q の極座標系の動径 */
	double Q_polar_argument = M_PI/3;	/* 点 Q の極座標系の偏角 */
	/*
	 * 点 P の表示
	 */
	print_orthogonal ( 'P', P_orthogonal_x, P_orthogonal_y );
			/*
			 * r = \sqrt{x^2+y^2} なので
			 */
	P_polar_radius = sqrt ( P_orthogonal_x * P_orthogonal_x + P_orthogonal_y * P_orthogonal_y );
			/*
			 *	a = \tan^{-1}{y/x} なので
			 *		cf. http://www1.cts.ne.jp/~clab/hsample/Math/Math2.html	  
			*/
	P_polar_argument = atan ( P_orthogonal_y / P_orthogonal_x );
	print_polar ( 'P', P_polar_radius , P_polar_argument );
	/*
	 * 点 Q の表示
	 */
	print_polar ( 'Q', Q_polar_radius, Q_polar_argument );
			/*
			 * x = r \cos{a} なので
			 */
	Q_orthogonal_x = Q_polar_radius * cos( Q_polar_argument );
			/*
			 * y = r \sin{a} なので
			*/
	Q_orthogonal_y = Q_polar_radius * sin( Q_polar_argument );
	print_orthogonal ( 'Q', Q_orthogonal_x, Q_orthogonal_y );
	return 0;
}
/*
 * 2020/10/30 sample-005.c
 */
/*
 * 平面上の点を扱う
 *
 * 利用方法
 *		コンパイル 
 *			cc  -c sample-005.c
 *		リンク 
 *			cc -o sample-005.exe sample-005.c -lm
 *		実行
 *			./sample-005.exe
 */
#include <stdio.h>
#include <math.h>		/* sqrt を利用するので必要 (-lm も忘れずに ) */
/*
 * void print_point ( double px, double py )
 * 		「点」を表示する
 *		double px -- 「点」の x 座標
 *		double py -- 「点」の y 座標
 */
void print_point ( double px, double py )		{
	 printf ( "( %f, %f )", px, py );
}
/*
 * double point_distance ( double p1x, double p1y, double p2x, double p2y )
 * 		ニ「点」間の距離を返す
 *		double p1x -- 「始点」の x 座標
 *		double p1y -- 「始点」の y 座標
 *		double p2x -- 「終点」の x 座標
 *		double p2y -- 「終点」の y 座標
 */
double point_distance ( double p1x, double p1y, double p2x, double p2y ) {
	   double dx = p2x - p1x;	/* x 座標の差 */
	   double dy = p2y - p1y;	/* y 座標の差 */
	   return sqrt ( dx*dx + dy*dy );
}
/*
 *	main
 */
int main( int argc, char *argv[] )
{
	double p1x = 1.0;	/* p1 = ( 1.0, 2.0 ) */
	double p1y = 2.0;
		/* 二つの変数を用いて、一つ対象を表現 */
		/*	p1 という点(仮想)を、
			p1x, p1y という二つ変数(実現)で
			対応づけて、表現している */
	double p2x = 4.0;	/* p2 = ( 4.0, 6.0 ) */
	double p2y = 6.0;
	printf ( "始点 " );
	print_point ( p1x, p1y );
	printf ( " と終点 " );
	print_point ( p2x, p2y );
	printf ( " との距離は %f です。\n", point_distance ( p1x, p1y, p2x, p2y ) );
	return 0;
}
/*
 * 2020/10/30 sample-009.c
 */
/*
 * 平面上の点の操作 (構造体の利用例)
 *
 * 利用方法
 *		コンパイル 
 *			cc  -c sample-009.c
 *		リンク 
 *			cc -o sample-009.exe sample-009.c 
 *		実行
 *			./sample-009.exe
 */
#include <stdio.h>
/*
 * 最初に、直交座標で「点」を表現する型を作ってしまう
 */
typedef struct {
	double x;		/* 直交座標の x 座標を表すタグ名 */
	double y;		/* 直交座標の y 座標を表すタグ名 */
} Orthogonal;		/* Orthogonal 型の宣言 */
/*
 * void print_point ( Orthogonal pt );
 * 		「点」を表示する
 *		Orthogonal pt; 直交座標系で表現された「点」の座標
 */
void print_point ( Orthogonal pt )		{
	 /*
	  *	構造体の要素は、タグ名を利用して参照できる
	  */
	 printf ( "( %f, %f )", pt.x, pt.y );
}
/*
 * Orthogonal mirror_o_point ( Orthogonal pt )
 * 		原点に対し点対称の「点」を求める
 *		Orthogonal pt; 直交座標系で表現された「点」の座標
 *		値 点対称の「点」を求める
 */
Orthogonal mirror_o_point ( Orthogonal pt )		{
	Orthogonal result;		/* 返す値を入れる変数 */
	result.x = - pt.x;		/* 結果の x 座標は、元の x 座標の符号をかえた物 */
	result.y = - pt.y;
	return result;			/* 構造体の値が返せる */
}
/*
 *	main
 */
int main( int argc, char *argv[] )
{
	Orthogonal p1;	/* 一つの点は、一つ変数 */
	Orthogonal p2;
	p1.x = 1.0;	/* p1 = ( 1.0, 2.0 ) */
	p1.y = 2.0;
		/* 原点に点対象 */
	printf ( "点 " );
		/* 構造体は引数で、そのまま渡せる */
	print_point ( p1 );
	printf ( " と原点に対して点線対称な点は " );
		/* 構造体は、値としても取り出せるし、普通に代入もできる */
	p2 = mirror_o_point ( p1 );
	print_point ( p2 );
	printf ( " となります。\n" );
	return 0;
}
2020/10/30 の内容
前回(2020/10/23)の内容
	条件分岐 (if 構文) アラカルト
		[基本]
			if ( 条件式 ) {
				条件が成立した時の文
			} else {
				条件が不成立の時の文
			}
		[本当の if 構文] (ぶら下がり構文)
			if ( 条件式 )
				条件が成立した時の文
			else
				条件が不成立の時の文
					=> これを組み合わる事により、色々な事ができる
			例: else if
				=> else 節の所に if 構文を入れる
					if ( 条件1 )
						条件 1 が成立した時の文
					else
						if ( 条件2 )
							条件 2 が成立した時の文
						else
							条件 2 も不成立の時の文
						=>
					if ( 条件1 )
						条件 1 が成立した時の文
					else if ( 条件2 )
						条件 2 が成立した時の文
					else
						条件 2 も不成立の時の文
		ぶら下がり構文の問題点
			if ( 条件1 )
				if ( 条件2 )
					命令1
			else
				命令 2
			# 見かけ上 : 命令 2 は、条件 1 が不成立の時に実行
			#	実際は、そうならない
			#		=> 直観に合わない表現ができてしまう..
			# かっこをわすれて、計算順番が変わる
			#	「3 に 2 を加えて 4 を掛ける」
			#		  3 + 2   * 4 => 11
			#		( 3 * 2 ) * 4 => 20
			#
			#	「3 に 2 を掛けて 4 を加える」
			#		  3 * 2   + 4 => 10
			#		( 3 * 2 ) + 4 => 10
			#			「安全」を図るために、(不要でも..) カッコを付ける
			#				=> ミス減らす
		[ポイント]
			2 分岐(条件の成立/不成立)を組み合わせる事により
				多様な条件判定や、多数の分岐が実現できる
					<=> switch 構文 ( 一つの式に対する多分岐 )
	条件式と論理演算
		条件式 : 整数値を取る式
			値(整数値)が 0 の時は「偽(条件が不成立)」
						それ以外は「真(条件が成立)」
			! 計算の結果、「真」の値を与える場合は、(代表値として..) 1 が採用される
		「式」=>「計算結果」が利用される
			「条件」を「計算」で求める事ができる
					数学				C 言語
				二つの条件式が		どちらか一方が
	論理積		ともに真の時に		0 の時は 0
				真になる			それ以外は 1
					P and Q				P && Q
	論理積	|	P		Q		|	P and Q
	--------+-------------------+------------
			|	真		真		|		真
			|	真		偽		|		偽
			|	偽		真		|		偽
			|	偽		偽		|		偽
	論理積		|		Q		|	
				+-------+-------+
	(P and Q)	|	真	|	偽	|
	--------+---+-------+-------+
			|真	|	真	|	偽	|
	P		+---+-------+-------+
			|偽	|	偽	|	偽	|
	--------+---+-------+-------+
				ふたつの条件式の	ともに
	論理和		一方が真の時に		0 の時は 0
				真になる			それ以外は 1
					P or Q				P || Q
	論理和	|	P		Q		|	P or Q
	--------+-------------------+------------
			|	真		真		|		真
			|	真		偽		|		真
			|	偽		真		|		真
			|	偽		偽		|		偽
	論理和		|		Q		|	
				+-------+-------+
	(P or Q)	|	真	|	偽	|
	--------+---+-------+-------+
			|真	|	真	|	真	|
	P		+---+-------+-------+
			|偽	|	真	|	偽	|
	--------+---+-------+-------+
				真偽値が反転		0 は 1
	否定			真 => 偽		0 以外は 0
					偽 => 真
					not P				!P
	否定	|	P	|	!P
	--------+-------+--------
			|	真	|	偽
			|	偽	|	真
	<<C 言語>>
	論理積	|	P		Q		|	P and Q
	--------+-------------------+------------
			|	0以外	0以外	|		1
			|	0以外	0		|		0
			|	0		0以外	|		0
			|	0		0		|		0
	論理積		|		Q		|	
				+-------+-------+
	(P and Q)	|0以外	|	0	|
	----+-------+-------+-------+
		|0以外	|	1	|	0	|
	P	+-------+-------+-------+
		|	0	|	0	|	0	|
	----+-------+-------+-------+
==
	条件が「値」なので、
		変数に代入したり、
			関数の実引数に渡したり、
				関数の返り値にすることができる
					「計算」ができる
		処理対象としてのデータ
			プログラムの制御には、間接的にしか、影響を与えない
		論理値としてのデータ
			プログラムの制御に対し、直接に影響を与える
		プログラムの構造 ( if 構文の組み合わせ )
			=> 計算(データ)の組み合わせに代わっている
	人間 => コードを書く => データを処理
					^			|
					|			|
					+-----------+
				論理値としてのデータ => コードに影響を与える
					!! コードは、プログラム作成時に決まる
					!!		=> 実行時点では「固定」
					!! データは、プログラム実行時に決まる
					!!		=> 実行時点ででも「可変」
					!!			=> データの方が柔軟性が高い(変化させる事ができるから..)
	これまで...
		プログラム <= コードを記述する
			コードを記述することが、プログラムを書く
				コードの組み合わせ方法
					順接 : コード(命令)並べる
					条件分岐 : if 構文 / switch 構文
					繰り返し : 再帰 / while, for
						=> コードの組み合わせによりデータを処理して
		機能を実現するために、
			コードだけでなく、データに焦点を置いた考え方が重要
				=> データ構造
==
	データ構造
		データの構造の話
			構造を持つデータの話
				=> データにある構造をみつけだし、それを明示的に記述する事により
					構造をもったデータを直接扱えるようにする
			例:	一つの整数 <= 構造をもっていない
				一つの整数型変数に、代入する事が
					「モノ」を表すときに「単純な一つ整数だけ」であらわすのは不適切な事がある
				気象:一つの地点で、三つの整数値
					<気象> <-> <気温,湿度,気圧>
						<気象> からその部分である<気温>(だけ)を抜き出す事ができる
							一つのものが複数のものから構成されている
								構造を持つ
		C 言語
			単純なものとそれ処理ができる
				|
			データ構造
				|
			複雑なものと、その処理が要求される
		現実の世界
		あるものを操作する時(A の世界)に、
			それが直接操作できない場合でも、
				それと同型なもの(B の世界)を操作すれば、
					間接的に、操作が可能なる
						同型なもの同士(A,B)の関係をコーディング
			!!! 数学では、たくさんの同型なもの扱う
			!!!		一つのやりかたで、複数のものが扱える
	データ構造
		単純なデータから、組み合わせて複雑なデータを作る
			ただし、表現が異なれば、それを処理する手段が異なる
				データ構造を考える場合は、その処理仕方と一緒に考える必要がある
					# データの構造と処理の仕方をまとめたものをオブジェクト
					!! 数学における「空間」=<集合、操作>
構造体
	データ型を作るための仕組み
		数学: 直積空間を作る
			A, B => C = A x B = { <a,b> | a \in A, b \in B }
			A, B, C => A x B x C = { <a,b,c> | a \in A, .. }
								 = { <<a,b>,c> | a \in A, .. }
								 = (A x B) x C
	C 言語での複数の型 ( 空間 ) から、その直積を作るしくみ
		例:
			double : x 座標
			double : y 座標
			double x double : 点	(直交座標)
				struct point {		/* 点 */
					double x;		/* x 座標 */
					double y;		/* y 座標 */
				}
	sample-005.c
		データ構造を使わない
			二つの変数の対で、一つの点という対象を表現する
				変数の対と点の対応(コーディング)は、
					プログラマの頭の中にしかない
課題プログラム内の「/*名前:ここ*/」の部分を書き換え「/*この部分を完成させなさい*/」の部分にプログラムを追加して、プログラムを完成させます。
Download : 20201030-01.c
/*
 * 課題 20201030-01
 *
 * 20201030 20201030-01-QQQQ.c
 *
 *	極座標で表現されている点 Q から、それと原点に対して対称な点 R を求める
 */
#include <stdio.h>
#include <math.h>		/* sin, cos を利用するので.. */
/*
 *	void print_polar ( char name, double r, double a )
 *		極座標の表示
 *		char name;	点の名前
 *		double r;	極座標の動径
 *		double a;	極座標の偏角
 */
void print_polar ( char name, double r, double a ) {
	 printf ( "点 %c の極座標は (%f,%f) です。\n", name, r, a );
}
/*
 *	main
 */
int main( int argc, char *argv[] )
{
	/*
		点 Q : 原点から 7 離れており、角度は x 軸に対して 60 度 ( Pi/3 )
	*/
	double Q_polar_radius = 7.0;		/* 点 Q の極座標系の動径 */
	double Q_polar_argument = M_PI/3;	/* 点 Q の極座標系の偏角 */
	double R_polar_radius;				/* 点 Q と原点対称な点 R の動径 */
	double R_polar_argument;			/* 点 Q と原点対称な点 R の偏角 */
	/*
	 * 点 Q の表示
	 */
	print_polar ( 'Q', Q_polar_radius, Q_polar_argument );
	/*
	 * 点 R の計算
	 */
			/* 対称なので原点から距離は同じ */
	/*
	**	 この部分を完成させなさい
	*/
				/* 180(π)だけ回転 */
	/*
	**	 この部分を完成させなさい
	*/
	/*
	 * 点 R の表示
	 */
	print_polar ( 'R', R_polar_radius, R_polar_argument );
	return 0;
}
$ ./20201030-01-QQQQ.exe 点 Q の極座標は (7.000000,1.047198) です。 点 R の極座標は (7.000000,4.188790) です。 $
Download : 20201030-02.c
/*
 * 課題 20201030-02
 *
 * 20201030 20201030-02-QQQQ.c
 *
 *	構造体を利用し、平行移動を行う関数を作成する
 */
#include <stdio.h>
/*
 * 最初に、直交座標で「点」を表現する型 (Orthogonal) を作ってしまう
 *	Orthogonal 型は、二つの要素 ( x, y ) からなり、それらの型は double 型
 *
 *		Orthogonal <----> double * double
 *          \in               \in
 *			p      <----> ( p.x, p.y )
 *
 *	残念ながら、C 言語の型定義機能で出来るのは「形(式)」の定義だけで
 *  「意味」の定義はできない
 *  「形」に「意味」をつけるのは、「それを扱うプログラム(関数)」の役目
 *
 *	コーディングルール:
 *		現実の世界					コンピュータの世界
 *		
 *		平面上の点 P : ( x, y )		Orthogonal 型の pt : ( pt.x, pt.y )
 *			P の x 座標 : 3				pt.x = 3.0
 *			P の y 座標 : -2			pt.y = -2.0
 *
 *		[注意]
 *				Orthogonal 型の pt を「現実の点 P」に対応させ、
 *					pt.x を点数 P の直交座標系における x 座標
 *					pt.y を点数 P の直交座標系における y 座標
 *				とする対応は、「决め(る)事」であり、
 *				「必然的に『決る物』」では *ない*
 *			<反例 1>
 *				x と y の名前は恣意的な物なので、逆にしても問題はない
 *				つまり、
 *					pt.x を点数 P の直交座標系における y 座標
 *					pt.y を点数 P の直交座標系における x 座標
 *				と、対応させても、「プログラム上」はなんら問題ない
 *				(正く動くように作る事ができる)
 *			<反例 2>
 *				x と y の値の対応も恣意的な物なので、変更してもよい
 *				つまり、
 *					pt.x を点数 P の偏角
 *					pt.y を点数 P の動径
 *				対応させても、「プログラム上」はなんら問題ない
 *				(正く動くように作る事ができる)
 */
typedef struct {
	double x;		/* 直交座標の x 座標を表すタグ名(x)とその型(double)の宣言 */
	double y;		/* 直交座標の y 座標を表すタグ名(y)とその型(double)の宣言 */
} Orthogonal;		/* Orthogonal 型の宣言 */
/*
 * void print_point ( Orthogonal pt );
 * 		「点」を表示する
 *		Orthogonal pt; 直交座標系の座標で表現された「点」
 */
void print_point ( Orthogonal pt )		{
	 /*
	  *	構造体の要素は、タグ名を利用して参照できる
	  */
	 printf ( "( %f, %f )", pt.x, pt.y );
}
/*
 * Orthogonal shift_point ( Orthogonal pt, double delta_x, double delta_y )
 * 		点を平行移動する
 *		Orthogonal pt; 直交座標系の座標で表現された「点」
 *		double delta_x;	x 軸方向の変異 (Δx)
 *		double delta_y;	y 軸方向の変異 (Δy)
 *		値 平行移動した結果
 */
Orthogonal shift_point ( Orthogonal pt, double delta_x, double delta_y )	{
	Orthogonal result;		/* 返す値を入れる変数 */
		/* x 軸方向に delta_x だけ平行移動した result.x を得るには、
           pt の x 座標に delta_x を加えればよい */
	/*
	**	 この部分を完成させなさい
	*/
		/* y 軸方向に delta_y だけ平行移動した result.x を得るには、
           pt の y 座標に delta_y を加えればよい */
	/*
	**	 この部分を完成させなさい
	*/
	return result;			/* 構造体の値が返せる */
}
/*
 *	main
 */
int main( int argc, char *argv[] )
{
	Orthogonal p1;
	Orthogonal p2;
	double dx = 10.0;
	double dy = -100.0;
	p1.x = 1.0;	/* p1 = ( 1.0, 2.0 ) */
	p1.y = 2.0;
		/* 平行移動 */
	printf ( "点 " );
		/* 構造体は引数で、そのまま渡せる */
	print_point ( p1 );
	printf ( " を x 軸方向に %f, y 軸方向に %f 移動した点は ", dx, dy );
		/* 構造体は、値としても取り出せるし、普通に代入もできる */
	/*
	**	 この部分を完成させなさい
	*/
	print_point ( p2 );
	printf ( " となります。\n" );
	return 0;
}
123 987 456
$ ./20201030-02-QQQQ.exe 点 ( 1.000000, 2.000000 ) を x 軸方向に 10.000000, y 軸方向に -100.000000 移動した点は ( 11.000000, -98.000000 ) となります。 $
Download : 20201030-03.c
/*
 * 課題 20201030-03
 *
 * 20201030 20201030-03-QQQQ.c
 *
 *	3 次元ベクトルの差の計算
 *
 */
#include <stdio.h>
/*
 *	3 次元ベクトル
 */
typedef struct {	/* 3 次元ベクトル */
	double x;		/* x 要素 */
	double y;		/* y 要素 */
	double z;		/* z 要素 */
} Vector3D;			/* 新しい型 : Vector3D */
/*
 * void print_Vector3D ( Vector3D v )
 *		ベクトルの内容を書き出す
 *		Vector3D v;		書き出すベクトル
 */	
void print_Vector3D ( Vector3D v ) {
	printf ( "  %f\n", v.x );		/* v の x 要素の出力 */
	printf ( "( %f  )\n", v.y );	/* v の y 要素の出力 */
	printf ( "  %f\n", v.z );		/* v の z 要素の出力 */
	/* TeX で表現するならば、
		printf ( "\\left(\\begin{array}{c} %f \\\\ %f \\\ %f \\end{array}\\right)\n", v.x, v.y, v.z );
	   などととすればよい。
	*/
}
/*
 * Vector3D sub_Vector3D ( Vector3D dst, Vector3D src )
 *		二つのベクトルの差を計算する
 *		Vector3D dst;		引かれるベクトル
 *		Vector3D src;		引くベクトル
 *		帰り値				二つのベクトルの差となるベクトル
 */
Vector3D sub_Vector3D ( Vector3D dst, Vector3D src ) {
	Vector3D result;				/* 計算結果(差)を收める変数 */
	/*
	**	 この部分を完成させなさい
	*/
						/* x 成分の計算 */
	result.y = dst.y - src.y;
				 		/* y 成分の計算 */
	/*
	**	 この部分を完成させなさい
	*/
				 		/* z 成分の計算 */
	return result;					/* 計算した結果を値として返す */
}
/*
 *	main
 */
int main( int argc, char *argv[] )
{
	Vector3D dst;
	Vector3D src;
	dst.x = 1.2;	/*         1.2		*/
	dst.y = 2.3;	/* dst = ( 2.3 )	*/
	dst.z = 3.4;	/*         3.4		*/
	src.x = -9.8;	/*         -9.8		*/
	src.y = 8.7;	/* dst = (  8.7 )	*/
	src.z = 0.0;	/*          0.0		*/
	print_Vector3D ( dst );		/* dst の出力 */
	printf ( "と\n" );
	print_Vector3D ( src );		/* src の出力 */
	printf ( "の差は\n" );
	print_Vector3D ( sub_Vector3D ( dst, src ) );
	printf ( "となります。\n" );
	return 0;
}
$ ./20201030-03-QQQQ.exe 1.200000 ( 2.300000 ) 3.400000 と -9.800000 ( 8.700000 ) 0.000000 の差は 11.000000 ( -6.400000 ) 3.400000 となります。 $