Powered by SmartDoc

ソフトウェア概論A/B (2019/11/08)
Ver. 1.0

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

目次

講義資料

当日の OHP 資料

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

Download : sample-001.c

sample-001.c
/*
 * 2019/11/08 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.c の実行結果
$ ./sample-001.exe
現在の栗野の残高は 100 万円です。
栗野の口座に 10 万円の振込を行います。
現在の栗野の残高は 110 万円です。
$ 

Download : sample-002.c

sample-002.c
/*
 * 2019/11/08 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.c の実行結果
$ ./sample-002.exe
数学の前評価の結果は B でした。
再度確認した所、採点ミスが見付かり、加点した所、グレードが一つ高くなりました。
その結果、数学の最終評価は A になりました。
$ 

Download : sample-003.c

sample-003.c
/*
 * 2019/11/08 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.c の実行結果
$ ./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

sample-004.c
/*
 * 2019/11/08 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.c の実行結果
$ ./sample-004.exe
点 P の直交座標は (2.000000,3.000000) です。
点 R の直交座標は (-2.000000,-3.000000) です。
$ 

Download : sample-005.c

sample-005.c
/*
 * 2019/11/08 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.c の実行結果
$ ./sample-005.exe
始点 ( 1.000000, 2.000000 ) と終点 ( 4.000000, 6.000000 ) との距離は 5.000000 です。
$ 

Download : sample-006.c

sample-006.c
/*
 * 2019/11/08 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.c の実行結果
$ ./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

sample-007.c
/*
 * 2019/11/08 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.c の実行結果
$ ./sample-007.exe
点 ( 1.000000, 2.000000 ) と原点に対して点線対称な点は ( -1.000000, -2.000000 ) となります。
$ 

Download : sample-008.c

sample-008.c
/*
 * 2019/11/08 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.c の実行結果
$ ./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

sample-009.c
/*
 * 2019/11/08 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.c の実行結果
$ ./sample-009.exe
点 ( 1.000000, 2.000000 ) と原点に対して点線対称な点は ( -1.000000, -2.000000 ) となります。
$ 

Download : sample-010.c

sample-010.c
/*
 * 2019/11/08 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.c の実行結果
$ ./sample-010.exe
点 P の直交座標は ( 1.000000, 2.000000 )です。
$ 

Download : sample-011.c

sample-011.c
/*
 * 2019/11/08 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.c の実行結果
$ ./sample-011.exe
点 P の直交座標は ( 1.000000, 2.000000, 3.000000 )です。
これと、原点に対して対称な、点 Q の直交座標は ( -1.000000, -2.000000, -3.000000 )です。
$ 

Download : sample-012.c

sample-012.c
/*
 * 2019/11/08 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.c の実行結果
$ ./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 )です。
$ 

講議中に作成したプログラム

本日の課題

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

課題 20191108-01 : 極座標で表現されている点 Q から、それと原点に対して対称な点 R を求める

Download : 20191108-01.c

20191108-01.c
/*
 * 課題 20191108-01
 *
 * 20191108 20191108-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;
}
20191108-01.c の実行結果
$ ./20191108-01-QQQQ.exe
点 Q の極座標は (7.000000,1.047198) です。
点 R の極座標は (7.000000,4.188790) です。
$ 

課題 20191108-02 : 構造体を利用し、平行移動を行う関数を作成する

Download : 20191108-02.c

20191108-02.c
/*
 * 課題 20191108-02
 *
 * 20191108 20191108-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
20191108-02.c の実行結果
$ ./20191108-02-QQQQ.exe
点 ( 1.000000, 2.000000 ) を x 軸方向に 10.000000, y 軸方向に -100.000000 移動した点は ( 11.000000, -98.000000 ) となります。
$ 

課題 20191108-03 : 3 次元ベクトルの差の計算

Download : 20191108-03.c

20191108-03.c
/*
 * 課題 20191108-03
 *
 * 20191108 20191108-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;
}
20191108-03.c の実行結果
$ ./20191108-03-QQQQ.exe
  1.200000
( 2.300000  )
  3.400000
と
  -9.800000
( 8.700000  )
  0.000000
の差は
  11.000000
( -6.400000  )
  3.400000
となります。
$