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 となります。 $