Download : sample-001.c
/*
* 2021/11/05 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
/*
* 2021/11/05 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
/*
* 2021/11/05 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
/*
* 2021/11/05 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
/*
* 2021/11/05 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
/*
* 2021/11/05 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
/*
* 2021/11/05 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
/*
* 2021/11/05 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
/*
* 2021/11/05 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
/*
* 2021/11/05 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
/*
* 2021/11/05 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
/*
* 2021/11/05 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-02
*
* 20211022 20211022-02-QQQQ.c
*
* 標準入力から三つの整数値を読込み、それを小さい順に出力する (論理和)
*/
#include <stdio.h>
/*
* main
*/
int main( void )
{
int i1; /* 三つの整数値を入力するので、三つの整数型変数(i1〜i3)を準備する */
int i2;
int i3;
int o1; /* 結果も三つの整数値なので、同様に三つ (o1〜o3) を準備する */
int o2;
int o3;
/*
* とりあえず、三つの整数値を標準入力から入力
*/
/* 一つ目整数値の入力 */
printf ( "一つ目の整数値を入力してください : " );
scanf ( "%d", &i1 );
/* 二つ目整数値の入力 */
printf ( "二つ目の整数値を入力してください : " );
scanf ( "%d", &i2 );
/* 三つ目整数値の入力 */
printf ( "三つ目の整数値を入力してください : " );
scanf ( "%d", &i3 );
/*
* 入力された整数値の大小により、小さい順に変数 o1 〜 o3 に値を代入
*/
/* 最初に、まず、一番小さい数をみつけてしまう */
/*
i1, i2, i3
i1 が一番小さい
(i2 と i3 の間の大小関係はわからないが)
i1 は i2, i3 のどちらと比較しても、小さい
条件式
i1 < i2
i1 < i3
の両方が成立する場合(で、その時のみ)にいえる
# iff ( if 条件 only if )
条件 : i1 が一番小さい
<=> (iff:同値)
条件 「i1 < i2」と「i1 < i3」が両方成立
<=>
条件 「i1 < i2」と「i1 < i3」の論理積
<=>
(i1 < i2) && (i1 < i3)
*/
if ( (i1 < i2) && (i1 < i3) ) {/* i1 の値は i2, i3 の双方の値より小さい */
o1 = i1; /* 一番小さいのは i1 の値 */
if ( i2 < i3 ) { /* 残る二つの値を比較 */
o2 = i2; /* o2 には、i2 と i3 の小さい方をいれる*/
o3 = i3; /* o3 には、残りを入れる */
} else {
o2 = i3;
o3 = i2;
}
} else if ( (i2 < i1) && (i2 < i3) ) { /* i2 の値が.. */
o1 = i2; /* 一番小さいのは i2 の値 .. */
/* 一番小さいものがきまれば、後は 2 しかないので */
/* それを比較して、小さい方を o2 にいれる.. */
if ( i1 < i3 ) { /* 残る二つの値を比較 */
o2 = i1; /* o2 には、i2 と i3 の小さい方をいれる*/
o3 = i3; /* o3 には、残りを入れる */
} else {
o2 = i3;
o3 = i1;
}
} else { /* 残る可能性は i3 の値が最少ってこと */
o1 = i3; /* i3 が最小なので.. */
if ( i1 < i2 ) {
o2 = i1;
o3 = i2;
} else {
o2 = i2;
o3 = i1;
}
}
/*
* 変数 o1 〜 o3 に整数値が小さい順に入っているので、それを出力
*/
printf ( "入力された値を小さい順に並べると %d, %d, %d になります。\n",
o1, o2, o3 );
return 0;
}
/*
プログラムとしては、
20211022-01.c と、このプログラム ( 20211022-02.c ) は同じ機能
ただし、
20211022-01.c は、六つ場合分けを最小限度の比較で行っている
# 条件式のところで、同じ条件は一度しかチェックしていない
しかし、
20211022-02.c の方は、(実は..)同じ条件を何度もチェックしている
=> 効率が低下している
<= 20211022-01.c より分かりやすくなっている
!! プログラムは
!! 効率は重要だが、それ以上に、正しさが重要
!! 正しさを保証するために、わかりやすさを重視しましょう
*/
/*
* 課題 CNAME-03
*
* 20211022 20211022-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++ ) {
printf ( "| %d | %d | %d | %d | %d |\n",
P, Q, !P, P&&Q, P||Q
);
}
}
printf ( "+---+---+----+------+------+\n" );
return 0;
}
/*
$ ./20211022-03-QQQQ.exe
+-------+----+-------------+
| 論理値|否定|論理積|論理和|
+---+---+----+------+------+
| P | Q | !P | P&&Q | P||Q |
+---+---+----+------+------+
| 0 | 0 | 1 | 0 | 0 |
| 0 | 1 | 1 | 0 | 1 |
| 1 | 0 | 0 | 0 | 1 |
| 1 | 1 | 0 | 1 | 1 |
+---+---+----+------+------+
$
*/
/*
* 課題 CNAME-04
*
* CDATE FILENAME
*
* ド・モルガンの定理
* !(P&&Q) == (!P)||(!Q)
* !(P||Q) == (!P)&&(!Q)
*/
#include <stdio.h>
/*
* not_and ( P, Q ) == !(P&&Q)
*/
int not_and ( int P, int Q ) {
/*
P, Q は整数値だが、論理値として利用される
0 => 偽 => 0
0 以外は => 真 => 1
*/
return !(P&&Q);
}
/*
* or_not ( P, Q ) == (!P)||(!Q)
*/
int or_not ( int P, int Q ) {
return (!P)||(!Q); /* 論理式の計算結果をそのまま返す */
}
/*
* main : 真偽表の作成
*/
int main(void) /* (int argc, char *argv[]) でもよい .. */
{
int P; /* 論理値は、整数値なので、整数変数を二つ (P,Q) 利用 */
int Q;
/* 真偽値表 */
printf ( "+---+---+---------+------------+-----------------------+\n" );
printf ( "| P | Q | !(P&&Q) | (!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 | %d |\n",
P, Q, not_and(P,Q), or_not(P,Q),
not_and(P,Q) == or_not(P,Q)
);
}
}
printf ( "+---+---+---------+------------+-----------------------+\n" );
return 0;
}
#include <stdio.h>
int main(int argc, char *argv[]) {
/* 条件式のところには、整数値が来る */
if ( 0 ) { /* 整数値「0」は、「偽(不成立)」として扱われる */
printf ( "0 が真の場合\n" );
} else {
printf ( "0 が偽の場合\n" );
}
if ( 1 ) { /* 整数値「1」は、「真(成立)」として扱われる */
printf ( "1 が真の場合\n" );
} else {
printf ( "1 が偽の場合\n" );
}
if ( -987 ) { /* 整数値「-987」は、「(0 でないので)真(成立)」として扱われる */
printf ( "-987 が真の場合\n" );
} else {
printf ( "-987 が偽の場合\n" );
}
return 0;
}
#include <stdio.h>
int main(int argc, char *argv[]) {
printf ( "1 == 1 は(成立するので) %d になる\n", 1 == 1 );
/* 成立(真) => 1 */
printf ( "1 == 0 は(成立しないので) %d になる\n", 1 == 0 );
/* 不成立(偽) => 0 */
return 0;
}
#include <stdio.h>
int main(int argc, char *argv[]) {
int a; /* 真のつもりで 1 を代入 */
int b; /* 真のつもりで 1 を代入 */
printf ( "一つ目の条件をいれてください : " );
scanf ( "%d", &a ); /* 変数 a に整数値を読み込む */
printf ( "二つ目の条件をいれてください : " );
scanf ( "%d", &b ); /* 変数 b に整数値を読み込む */
if ( a * b ) {
printf ( "a = %d, b = %d の時に実行しました\n", a, b );
}
return 0;
}
/*
結果:
soft@DESKTOP-14IRHSD:~/c/20211105$ ./p-003.exe
一つ目の条件をいれてください : 1
二つ目の条件をいれてください : 1
a = 1, b = 1 の時に実行しました
soft@DESKTOP-14IRHSD:~/c/20211105$ ./p-003.exe
一つ目の条件をいれてください : 1
二つ目の条件をいれてください : 0
soft@DESKTOP-14IRHSD:~/c/20211105$ ./p-003.exe
一つ目の条件をいれてください : 0
二つ目の条件をいれてください : 1
soft@DESKTOP-14IRHSD:~/c/20211105$ ./p-003.exe
一つ目の条件をいれてください : 0
二つ目の条件をいれてください : 0
a/b | 0 1
----+----------------------
0 | 不実行 不実行
1 | 不実行 実行
0 => 偽 / 1 => 真
実行 => 条件が真 / 不実行 => 条件が偽
a/b | 偽(F) 真(T)
----+----------------------
偽 | 偽 偽
真 | 偽 真
=> 論理積の演算になっている
a * b => (a, b が論理値の時) a と b の論理積
a*b | 0 1
----+----------------------
0 | 0 0
1 | 0 1
# 論理値を、整数値として計算する => 整数の積が、論理積になる
*/
/*
* 2021/11/05 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;
}
/*
* 2021/11/05 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;
}
/*
* 2021/11/05 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;
}
前回の内容
条件分岐 (if 構文) アラカルト
(what) 条件によって、複数(>1)の命令のうち、
一つだけを実行すること
状況に応じて適切な手段を選択できる
(how) if 構文
(構文規則)
if ( 条件式 ) {
条件が成立し時の命令
} else {
条件が不成立の時の命令
}
(意味)
「条件式」が「真(成立する)」の場合
「条件が成立し時の命令」を実行する
そうでない場合は、
「条件が不成立の時の命令」を実行する
# 必ず、どちらか一方だけが実行される
(例)
if ( a != 0 ) { /* 分母が 0 でない場合.. */
c = 1/a; /* 割り算の実行 */
} else {
printf ( "分母が 0 なので割り算ができません\n" );
}
if 構文の色々なパターン
(C 言語の「言語仕様」で if 構文 )
if ( 条件式 )
文
[ else
文 ]
!! 前期との違い
!! 1. 「{、}」が不要
!! 2. else 節 ( else 以後 ) が省略可能
!! => 前期で学んだ形は、この仕様の特殊な場合
!! a. 他の人の書き方を見る時には、この一般的な形で理解
!! b. ぜひ、書く時には、前期の形式を踏襲する事をお勧め
!! <= 「{、}」がないと、間違いが起きやすくなる
!! 予防的なプログラミング ( 「失敗」を防ぐために、「失敗する可能性を、あらかじめ削除しておく」)
条件式と論理演算
if 構文や while (for) 構文で利用する「条件式」は、
=> 「成立(True/真)」か「不成立(False/偽)」
# 真偽値 ( Boolean : { 真, 偽 } )
C 言語における、条件式 => 整数値を取る式(整数式)
C 言語では、真偽値(条件式として現れる状況)が必要になった場合、
整数値に対して、
0 の時は、「偽」
0 以外の時は、「真」
として扱う。
# 整数値 => 真偽値として扱う場合
真偽値を返す場合、
「偽」の時は、0
「真」の時には、1
を返す約束になっている。
# 真偽値 => 整数値 として扱う場合
整数値 真偽値
0 <-------------> False (偽)
1 <-------------> True (真)
2 ------------------/
-1 -----------------/
... ---------------/
整数値にする理由
1. コンパイルした後の機械語がそうゆう性質をもっている
# cf. ++ (インクリメント演算子)
# => 機械語に、その命令があるので、
# その命令を積極的に使うために、言語仕様として C 言語に追加された
2. 整数値にする事により、
「計算の対象」になる
# 論理的な演算を、整数の演算で表現可能
# => 論理のための演算を特に、設けておらず、整数演算で、代用している
if 構文
(別の解釈)
データを文に変更する構文
if ( 整数値 ) {
文1
} else {
文2
}
整数値 真偽値 実行文
0 <-------------> False (偽) 文2
1 <-------------> True (真) 文1
2 ------------------/
-1 -----------------/
... ---------------/
# 条件式が、「計算可能」ということから、
# 「文が、『計算可能』になる」という事に繋がる
# => ノイマン型計算機の設計思想
# 万能性の根拠に繋がる
(整数値を)論理値とみなして、論理演算を行う演算子
&& 論理積
|| 論理和
! 否定
論理積 論理和 否定
P | Q | P && Q | P || Q | ! P
----+-------+-----------+-----------+--------
T | T | T | T | F
| F | F | T |
----+-------+-----------+-----------+--------
F | T | F | T | T
| F | F | F |
# 0 -> F -> 0
# 0 以外 -> T -> 1
休憩 10:50 開始
[2021/11/05]
講義: データ構造 (1)
構造体と配列
前回まで
三つの制御構造
順接:
A B => 命令 A, B をこの順に実行する
条件分岐:
if ( 条件 ) A else B
=> 条件によって、A と B の一方を実行
くり返し:
while ( 条件 ) A
=> 条件が成立する限り A を繰り返す
任意の(プログラムが実現可能な..) 機能は、
この三つの構文の組み合わせで実現可能 ( 万能性がある )
! プログラムを作成する
! 命令を組み合わせて、目的(とした機能)を実現する
今回以後
データ構造
データの組み合わせを実現したもの
!!! if 構文は、データを文に対応させる
!!! => データの組み合わせが、文の組み合わせ
プログラム(コード) データ
命令の組み合わせ 対応 データの組み合わせ
順接 構造体
条件分岐 <=> 共用体
くり返し 配列
Code Code -> Data Data
*------------------------------>*
| |
Code 組み合わせ | (可換図) | Data 組み合わせ
v v
*<------------------------------*
Data -> Code
!! Code の組み合わせを Data の組み合わせで表現可能(かもしれない)
!! Data の組み合わせで Programming が可能になる
!!
!! プログラミング時(コンパイル時) 実行時
!! Code 表現 固定
!! Data 型と関係 変化
!!
!! Code と Data の大きな違い
!! 実行時に変化するかしないか
!! もし、Data で Code が表現できる
!! 実行時に変化する Code (のようなもの)が作れる
!! # Computer Virus の動作原理
!! # Data が Code として(誤って)扱わられる事が原因
!! # # 「スタックオーバーフロー」
!! # # => scanf のうっかりとした利用法
コーディング
現実の世界の情報と計算機の世界のデータ(数値)の対応関係
例:
ASCII Code
文字(現実の世界の情報) <=> 整数値(計算機の世界のデータ)
コーディングによって、情報とデータの関係ができるので、
データ処理をつかって、情報処理が可能になり
コンピュータを利用して、現実で役立つ機能が実現できる
# コンピュータがさらに、装置(device)を利用すると、
# 自動化が可能
!! => 複雑な情報を表現するために、複雑なデータ(構造)が必要
データ構造
「プログラム」による「機能」の実現
プログラム : 「データ(数値)」の「処理(変更)」*しか* できない
機能 : 「情報」の「操作」によって実現される
どこでか「データ」と「情報」の *対応* が必要
例: 文字 (ASCII Code): 文字コード(数値) と 文字(情報)の対応を行う[002]
「情報」を「データ」の形にする
「データ」による「情報」の「表現」を考える[003]
現実の世界での情報処理が、(コーディングを経由して..)
計算機の世界でのデータ処理(数値計算)になっている例
背景:
二次元平面上の点(現実の情報)を、
表現(コーディング)したい
データ(数値)を利用して
# 「表現方法」は、一通りではない
# (x,y): 座標
# 直交座標
# 横が x , 縦が y 座標
# 右と上が正、左と下が負の方向
#
# 他の例:
# 軸の方向が逆のパターンがある
# 例: excel は、行は上が負、下が正
# => 紙に印刷する時の方向
例 1: 平面上の点を「(x, y):直交座標系の座標」で表現
例 2: 平面上の点を「(r, a):極座標系の距離と角度」で表現
# (x,y)でも(r,a)でもともに、二つの数値の組
# => それをみただけでは、区別できない
# <= 表現の「意味」を決めているのは、
# データの形(数値の組)だけでなく、
# そのデータの解釈仕方(扱いの仕方)で区別するしかない
# <= データ解釈を扱い方(code)で表現する
# # データの表現
# # データの組み合わせ + データを扱う基本的なコード
# # => 「オブジェクト」
「表現」が異れば、同じ「機能(操作)」を実現する場合でも、「プログラム(処理)」が異なる
例 : 点 P と原点対象な位置にある点 Q を求める「機能」の実現 (例 1 と 例 2 で「処理」が異なる)
「点」を表現するには、「二つの実数値の『対』」が必要
「点」には、『対』という「構造をもっている」と考えられる
#「構造を持つ」
# 1. 分解して、より小さなデータを取り出す事ができる
# 2. その小さなデータの間には、特定な関係がある(関係をつかって元に戻せる)
「点」
-> X 座標 / Y 座標
=>
X, Y 座標から、「点」が作れる
注意 : ただ「『対』という『形』」だけでは意味がない、「操作」まで含めて考える必要がある
sample-003.c
『点』P, Q は、ともに、Data としては、実数値(double) の「対」
として『データ表現』されているが、
それらが、直交座標なのか極座標なのかは、
それを扱う、扱い方 ( 出力する時に、
どちらの出力関数を使うか ? ) による
!! データは、それだけをみても、何を表現しているかは、原理的にはわからない
!! 例:
!! 整数値 65 は、小さな整数なのか、それとも ASCII Code 'A' を表現をしているか ?
!! それが(最終的に、現実の世界のどのような)情報に対応するかは、
!! その情報(データ)の扱われ方や、利用法から決まる
データ構造とは
「構造を持つデータ」と「それを作る要素」の「関係」の事
「既存のデータ表現」から、「新しいデータ表現」を作る方法にもなっている
課題プログラム内の「/*名前:ここ*/」の部分を書き換え「/*この部分を完成させなさい*/」の部分にプログラムを追加して、プログラムを完成させます。
Download : 20211105-01.c
/*
* 課題 20211105-01
*
* 20211105 20211105-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;
}
$ ./20211105-01-QQQQ.exe 点 Q の極座標は (7.000000,1.047198) です。 点 R の極座標は (7.000000,4.188790) です。 $
Download : 20211105-02.c
/*
* 課題 20211105-02
*
* 20211105 20211105-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
$ ./20211105-02-QQQQ.exe 点 ( 1.000000, 2.000000 ) を x 軸方向に 10.000000, y 軸方向に -100.000000 移動した点は ( 11.000000, -98.000000 ) となります。 $
Download : 20211105-03.c
/*
* 課題 20211105-03
*
* 20211105 20211105-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;
}
$ ./20211105-03-QQQQ.exe 1.200000 ( 2.300000 ) 3.400000 と -9.800000 ( 8.700000 ) 0.000000 の差は 11.000000 ( -6.400000 ) 3.400000 となります。 $