Download : sample-001.c
/*
* 2021/11/12 sample-001.c
*/
/*
* 複素数型の定義と計算
*
* 利用方法
* コンパイル
* cc -c sample-001.c
* リンク
* cc -o sample-001.exe sample-001.c
* 実行
* ./sample-001.exe
*/
#include <stdio.h>
/*
* 複素数型を表す Complex の定義
*
* 複素数 z は、二つの実数 x, y を用いて
* z = x + yi ( i は虚数単位 )
* と表現できる。
* C 言語では実数を表すのに浮動小数点数型の double を用いる
* 型名 ( Complex ) を大文字で始めるのは「ソフトウェア概論ルール」
*/
typedef struct {
double real; /* 実部 */
double imaginary; /* 虚部 */
} Complex; /* 複素数型 */
/*
* Complex make_Complex ( double x, double y )
* Complex 型の数を作り、返す
* x, y -> z = x + yi
*/
Complex make_Complex ( double x, double y ) {
Complex newComplex; /* 新しく作られる複素数 */
newComplex.real = x; /* 新しく作られた複素数の実部は x */
newComplex.imaginary = y; /* 新しく作られた複素数の実部は y */
return newComplex; /* 新しく作られる複素数を値として返す */
}
/*
* double real_part ( Complex z )
* Complex 型の数の実部を返す
* z = x + yi -> x
*/
double real_part ( Complex z ) {
return z.real;
}
/*
* double imaginary_part ( Complex z )
* Complex 型の数の実部を返す
* z = x + yi -> x
*/
double imaginary_part ( Complex z ) {
return z.imaginary;
}
/*
* print_Complex ( Complex z )
* Complex 型の数の出力
* z = x + y i だが、y < 0 の時は z = x - (-y) i となるように工夫
*/
void print_Complex ( Complex z ) {
if ( z.imaginary > 0 ) {
printf ( "%f + %f i", z.real, z.imaginary );
} else {
printf ( "%f - %f i", z.real, - z.imaginary );
}
}
/*
* Complex add_Complex ( Complex z1, Complex z2 )
* Complex 型の数の足し算
* z1 = x1 + y1 i
* z2 = x2 + y2 i
* -> z1 + z2 = ( x1 + x2 ) + ( y1 + y2 ) i
*/
Complex add_Complex ( Complex z1, Complex z2 ) {
Complex result;
/* 複素数の和の実部は、実部の和 */
result.real = z1.real + z2.real;
/* 複素数の和の虚部は、虚部の和 */
result.imaginary = z1.imaginary + z2.imaginary;
return result;
}
/*
* main
*/
int main( int argc, char *argv[] )
{
Complex z1 = make_Complex ( 2.0, 3.0 ); /* z1 = 2 + 3i */
Complex z2 = make_Complex ( -1.0, 5.0 ); /* z2 = -1 + 5i */
Complex z3;
printf ( " z1 ( = " );
print_Complex ( z1 );
printf ( " ) と、" );
printf ( " z2 ( = " );
print_Complex ( z2 );
printf ( " ) の和は 、\n" );
z3 = add_Complex ( z1, z2 ); /* z3 <- z1 + z2 */
print_Complex ( z3 );
printf ( " です。\n" );
return 0;
}
$ ./sample-001.exe z1 ( = 2.000000 + 3.000000 i ) と、 z2 ( = -1.000000 + 5.000000 i ) の和は 、 1.000000 + 8.000000 i です。 $
Download : sample-002.c
/*
* 2021/11/12 sample-002.c
*/
/*
* 二次元行列型の定義と計算
*
* 利用方法
* コンパイル
* cc -c sample-002.c
* リンク
* cc -o sample-002.exe sample-002.c
* 実行
* ./sample-002.exe
*/
#include <stdio.h>
/*
*
*/
#define DIMENSION 2 /* 二次元 */
/*
* 行列 A は、2 x 2 = 4 の要素をもっている
*
* A = ( 1 2 ) = ( a[0][0] a[0][1] )
* 3 4 a[1][0] a[1][1]
*
*/
typedef struct {
double a[DIMENSION][DIMENSION]; /* 二次元の行列の要素は 2 x 2 */
} Matrix2D; /* Matrix2D 型の宣言 */
/*
* Matrix2D make_Matrix2D ( double a, double b, double c, double d )
* 「行列」を作成する
*
* A = ( a b ) = ( a[0][0], a[0][1] )
* ( c d ) ( a[1][0], a[1][1] )
*/
Matrix2D make_Matrix2D ( double a, double b, double c, double d ) {
Matrix2D newMatrix2D; /* 新しい行列 */
newMatrix2D.a[0][0] = a;
newMatrix2D.a[0][1] = b;
newMatrix2D.a[1][0] = c;
newMatrix2D.a[1][1] = d;
return newMatrix2D;
}
/*
* void print_Matrix2D ( Matrix2D ary );
* 「行列」を表示する (表示の都合上、常に独立した行に出力する)
* Matrix2D ary; 二次元行列
*/
void print_Matrix2D ( Matrix2D ary ) {
int r; /* 行 ( row ) */
int c; /* 列 ( colomun ) */
for ( r = 0; r < DIMENSION; r++ ) {
printf ( "(" );
for ( c = 0; c < DIMENSION; c++ ) {
printf ( " %10.5f", ary.a[r][c] );
/*
* [注意] %10.5f は %f と同じく浮動小数点数を出力するが
* 「全体の桁数は 10 桁、小数点数以下は 5 桁にする」
* という「表示上の指定」も加わっている
* 詳しくは google で「printf 書式」で検索
*/
}
printf ( " )\n" );
}
}
/*
* Matrix2D add_Matrix2D ( Matrix2D a1, Matrix2D a2 );
* 「行列」の和
*
* ( a b ) + ( e f ) = ( a + e b + f )
* ( c d ) ( g h ) ( c + g g + h )
*/
Matrix2D add_Matrix2D ( Matrix2D a1, Matrix2D a2 ) {
Matrix2D result; /* 計算結果 */
int r; /* 行 ( row ) */
int c; /* 列 ( colomun ) */
for ( r = 0; r < DIMENSION; r++ ) {
for ( c = 0; c < DIMENSION; c++ ) {
result.a[r][c] = a1.a[r][c] + a2.a[r][c];
}
}
return result;
}
/*
* main
*/
int main( int argc, char *argv[] )
{
/*
a1 = ( 1 2 )
( 3 -1 )
a2 = ( -3 1 )
( 1 -2 )
*/
Matrix2D a1 = make_Matrix2D ( 1.0, 2.0, 3.0, -1.0 );
Matrix2D a2 = make_Matrix2D ( -3.0, 1.0, 1.0, -2.0 );
/* 行列 a1 と行列 a2 の和を計算して出力する */
print_Matrix2D ( a1 );
printf ( " と、 \n" );
print_Matrix2D ( a2 );
printf ( " との、和は \n" );
print_Matrix2D ( a );
printf ( " です。\n" );
return 0;
}
$ ./sample-002.exe z1 ( = 2.000000 + 3.000000 i ) と、 z2 ( = -1.000000 + 5.000000 i ) の和は 、 1.000000 + 8.000000 i です。 $
/*
* 課題 20211105-01
*
* 20211105 20211105-01-QQQQ.c
*
* 極座標で表現されている点 Q から、それと原点に対して対称な点 R を求める
*
* |
* | * Q
* O|
* ----+----
* |
* *R |
* |
*
* 直交座標であれば
* Q (x,y) -> R (-x,-y)
* 極座標であれば
* Q (r,t) -> R (r',t')
* -> R (r,t+π)
* 考え方
* Q と R は原点を中心に対称
* 原点 O は、線分 QR の中点
* OR = OQ
* Q と O の間の長さと R とO の間の長さが等しい
* r' = r
* 角 QOR は 180 度 ( 点 Q, O, R が一直線上にある )
* t' = t + 180度 ( π )
*
* 情報 f データ
* i1 -----> d1=f(i1)
* | | d1 -> d2 -----+
* v v |
* i2 -----> d2= f(i2) |実現手段(プログラム)
* |が変化した理由は
* 情報 g データ |コーディングルールが
* i1 -----> d1'=g(i1) |変化したせい
* | | d1' -> d2' <--+
* v v
* i2 -----> d2'=g(i2)
*/
#include <stdio.h>
#include <math.h> /* M_PI を利用するので.. */
/*
* 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 の計算
*/
/* 対称なので原点から距離は同じ */
R_polar_radius = Q_polar_radius;
/* 180(π)だけ回転 */
R_polar_argument = Q_polar_argument + M_PI;
/*
* 点 R の表示
*/
print_polar ( 'R', R_polar_radius, R_polar_argument );
return 0;
}
/*
* 課題 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)
* 値 平行移動した結果
*
* 意味
* p (x,y) -> q(x+Δx,y+Δy) : x 軸方向にΔx だけ、 y 軸方向に Δy だけ平行移動
* q.x = p.x + Δx
* q.y = p.y + Δy
*/
Orthogonal shift_point ( Orthogonal pt, double delta_x, double delta_y ) {
Orthogonal result; /* 返す値を入れる変数 */
/* x 軸方向に delta_x だけ平行移動した result.x を得るには、
pt の x 座標に delta_x を加えればよい */
result.x = pt.x + delta_x;
/* y 軸方向に delta_y だけ平行移動した result.x を得るには、
pt の y 座標に delta_y を加えればよい */
result.y = pt.y + delta_y;
/*
result 変数は値として、平行移動した結果を表現する値を持つ
*/
return result; /* 構造体の値が返せる */
/* 変数 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 );
/* 構造体は、値としても取り出せるし、普通に代入もできる */
/* 変数 p2 に、移動した結果を代入したい.. ) */
p2 = shift_point ( p1, dx, dy );
/*
関数の値に構造体の値がつかえる
変数に対して、構造体の値の代入が可能
*/
print_point ( p2 );
printf ( " となります。\n" );
return 0;
}
/*
* 課題 20211105-03
*
* 20211105 20211105-03-QQQQ.c
*
* 3 次元ベクトルの差の計算
* 3 次元ベクトルなので、三つの要素 ( x, y, z ) からなる
*
*/
#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; 引くベクトル
* 帰り値 二つのベクトルの差となるベクトル
* dst.x
* dst = ( dst.y )
* dst.z
*
* src.x
* src = ( src.y )
* src.z
* dst.x - src.x result.x
* dst - src = ( dst.y - src.y ) = result = ( result.y )
* dst.z - src.z result.z
* =>
* result.x = dst.x - src.x
* result.y = dst.y - src.y
* result.z = dst.z - src.z
*
機能 実装
=>構造体
dst (dst.x, dst.y, dst.z)
src (src.x, src.y, src.z)
| |
v v
dst - src dst.x - src.x
<= dst.y - src.y
dst.z - src.z
( 一種の交換法則 : 可換図 )
全体の機能が、(構造体を利用した関係を用いて)
部分の機能の組み合わせで、実装される
*/
Vector3D sub_Vector3D ( Vector3D dst, Vector3D src ) {
Vector3D result; /* 計算結果(差)を收める変数 */
result.x = dst.x - src.x;
/* x 成分の計算 */
result.y = dst.y - src.y;
/* y 成分の計算 */
result.z = dst.z - src.z;
/* 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;
}
#include <stdio.h>
/*
構造体を用いて、
二次元平面上の点を直交座標で表現するために、
構造体を用いる
構造体は、新しい型を作る
=> 型宣言で利用できる
*/
int main(int argc, char *argv[]) {
struct {
double x;
double y;
} p; /* 構造体で作られた型を持つ変数 */
double qx; /* 構造体を使わずに、二つの変数で点を表現 */
double qy;
p.x = 1.0; /* 構造体の要素(メンバー)をタグ名を使って操作可能 */
p.y = 2.0;
/* 点 p に、座標 (1.0,2.0) を指定する */
/*
struct { double v1; double v2; }
<=>
double x double ( 直積空間 )
*/
qx = 3.0;
qy = 4.0;
/* 点 q に、座標 (3.0,4.0) を指定 */
/*
何が違うか ?
構造体を利用すると、
x 座標と y 座標は、一つの変数に収める事ができる
そうしない
複数の変数に収める必要がある
=>
個々の変数を「誤って」分けてつかってしまうと問題がおきる
*/
printf ( "p=(%f,%f)\n", p.x, p.y );
printf ( "q=(%f,%f)\n", qx, qy );
return 0;
}
#include <stdio.h>
typedef struct{
double m0;
double m1;
double m2;
} S;
S sub ( double x ) {
S result;
result.m0 = x;
result.m1 = x;
result.m2 = x;
return result;
}
int main(int argc, char *argv[]) {
double a[3]; /* この結果、配列 a が宣言され */
/* この配列の要素(となる変数)
a[0], a[1], a[2]
が利用できるようになる */
/*
cf.
struct {
double a0;
double a1;
double a2;
} a;
とすると、
構造体の値を持つ変数 a と、
その要素となる
a.a0, a.a1, a.a2
が利用できるようになる
構造体 配列
宣言されるもの 変数 配列名
変数として利用可能 構造体と要素 要素だけ
*/
S s; /* s という変数が宣言 ( 型:構造体 )
s.m0, s.m1, s.m2 も利用できる */
a[0] = 1.0;
a[1] = 2.0;
a[2] = 3.0;
printf ( "a[0]=%f\n", a[0] );
printf ( "a[1]=%f\n", a[1] );
printf ( "a[2]=%f\n", a[2] );
/* a[0], a[1], a[2] は別々の変数 */
s.m0 = 1.0;
s.m1 = 2.0;
s.m2 = 3.0;
printf ( "s.m0=%f\n", s.m0 );
printf ( "s.m1=%f\n", s.m1 );
printf ( "s.m2=%f\n", s.m2 );
/* s.m0, s.m1, s.m2 は別々の変数 */
s = sub( -100.0 );
/* s という変数があって、代入可能 */
/* s の値と、そのメンバーの値は、共有されている */
/*
s +---------+
|m0 +----+|
| | ||
|m1 +----+|
| | ||
|m2 +----+|
| | ||
| +----+|
+---------+
*/
printf ( "s.m0=%f\n", s.m0 );
printf ( "s.m1=%f\n", s.m1 );
printf ( "s.m2=%f\n", s.m2 );
/*
配列名は、定数値(配列のある場所)をもち、これに代入する事はできない
a -----> a[0]+----+
| |
a[1]+----+
| |
a[2]+----+
| |
+----+
*/
return 0;
}
/*
集合 : { 0, 1, 4, 9 } = { 0^2, 1^2, 2^2, 3^2 }
表
x | 0 1 2 3
----+-----------------
x^2=a[x]| 0 1 4 9
を表現
*/
#include <stdio.h>
int main(int argc, char *argv[]) {
int s[4];
int i;
s[0] = 0;
s[1] = 1;
s[2] = 4;
s[3] = 9;
/* 4 つの要素からなる集合 */
/* 集合操作:
集合全体への操作を、集合の個々の要素への操作に対応づける */
/* 個々の要素を出力する */
printf ( "{ " );
/*
printf ( "%d, %d, %d, %d ", s[0], s[1], s[2], s[3] );
*/
for ( i = 0; i < 4; i++ ) {
printf ( "%d", s[i] ); /* s の要素を添え字を利用して参照 */
if ( i < 4 - 1 ) {
printf ( ", " );
} else {
printf ( " " );
}
}
printf ( "}\n" );
/* s[i] = i^2
=> s[i] = i^3
s[i] <- s[i] * i = i^2 * i = i^3
s[0] = s[0] * 0;
s[1] = s[1] * 1;
s[2] = s[2] * 2;
s[3] = s[3] * 3;
*/
for ( i = 0; i < 4; i++ ) {
s[i] = s[i] * i;
}
printf ( "{ " );
for ( i = 0; i < 4; i++ ) {
printf ( "%d", s[i] ); /* s の要素を添え字を利用して参照 */
if ( i < 4 - 1 ) {
printf ( ", " );
} else {
printf ( " " );
}
}
printf ( "}\n" );
return 0;
}
/*
* 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;
}
/*
* 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; /* 構造体の値が返せる */
/*
C 言語の関数は、「値を一つ」しか返せない
もし、点を二つの値で表現すると
点の値を返す、関数を作る事が面倒
構造体を使えば、
複数の値の組を一つの値にする事ができるので、
(間接的に..) 複数の値の組み合わせを返す関数が作れる
*/
}
/*
* main
*/
int main( int argc, char *argv[] )
{
Orthogonal p1; /* Orthogonal 型の変数宣言が可能 */
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 );
/* p2 = p1 も可能
=> これは、自動的に
p2.x = p1.x
p2.y = p2.y
と同じ結果になる
*/
print_point ( p2 );
printf ( " となります。\n" );
return 0;
}
/*
* 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 型の宣言 */
/*
Orthogonal := double x double
Orthogonal
+-----------+
| double x |
| double y |
+-----------+
*/
/*
* 更に、「名前付き」の「点」の型
*/
typedef struct {
char name; /* 点の名前 */
Orthogonal coordinate; /* 点の座標 */
} NPoint;
/*
NPoint := char * Orthogonal
char * ( double * double )
NPoint
+-----------------------+
| char name |
| Orthogonal coordinate |
+-----------------------+
+-----------------------+
| char name |
| Orthogonal coordinate |
| +---------------+ |
| | double x | |
| | double y | |
| +---------------+ |
+-----------------------+
NPoint pt;
名前
pt.name
x 座標
pt.coordinate.x
別のアプローチ
typedef struct {
char name;
double x;
double y;
} NPoint2;
これは、NPoint とは違うものとして扱われる
+-----------------------+
| char name |
| double x |
| double y |
+-----------------------+
NPoint2 pt;
名前
pt.name
x 座標
pt.x
*/
/*
* 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 );
/*
すでに定義済の Orthogonal を利用する関数を用いて、
新しい NPoint 型の関数を実装している
=> すでに作った(過去の)資産を再利用するために、
できるだけ、新しい型の実装には、
古い型の実装を転用するとよい
*/
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;
}
先週からデータ構造の話
データ構造
既存のデータ型から、新しいデータ型を作る仕組み
# 新しいデータ型から、元となる既存のデータ型を取りだす事ができる
#
# 新しいデータ型
# +-----------------------+
# | 元となるデータ型 |
# +-----------------------+
# => 新しいデータ型 : 内部構造 ( 元となるデータ型と、新しいデータ型の関係 )
# => データ構造 ( 型の組合わせ )
コーディング ( 前回の内容 ) の方法を指す
* 表現したい情報を、(コンピュータの内部の)数値で、どのように表現するかという手段を表す
例:
文字を数値で表現するための手段 ( ASCII Code 表 )
二次元の直交座標を表現するために、x, y 座標値の組み合わせ
1. 表現したい情報自身が構造を持つ場合がある
二次元の直交座標は、x 座標と y 座標という内部構造を持つ
=> これを表現する時に、数値の方も、同じ内部構造を持つ方が扱いやすい
y
4 |
3 | * (4,3) 4, 3 という二つの数値の組
2 | 下に一つ平行移動
1 | y 座標を減らすだけ
0 +--------- x
0123456789
6
y17
4 |628
3 |4839 19 という一つの数値で座標を表現する事ができる
2 |2594 19 -> 14
1 |13605 平行移動を示す一般的な方法がなかなか思いつかない
0 +--------- x => 直観と反している
0123456789
情報に構造があった場合は、
それを表現するデータ型にも ( 同じような ) 構造があった方が便利
* データ型は、それ自身がなんらかの情報を表現ではなく、
そのデータ型の数値を、どのように扱うかで、表現する情報が異なる
例: ASCII Code : 'a' <-> 76
76 という数値が文字の 'a' を表すのは、
この数値を、ASCII Code 表での文字を表す数値としてとらえるから
'a' + 1 => 76 + 1 => 77 ( <= 整数値として扱っている )
この計算結果 ( 77 ) を改めて、文字を表現していると思うと、
'b' という文字とみなす事ができる
!! 情報処理 ( 計算機の中では計算によって実現されている ) は、
!! (コーディングを経由して..) 情報とデータ(数値)を行き来する事によって、実現されている
情報 データ
ASCII Code
文字 'a' --------------------> 76
| |
| (次の文字を得る) | +1 という計算ができる
v v
'b' <------------------ 77
演習
二次元平面の点の二つの表現
直交座標を使う
極座標を使う
[2021/11/12]
先週の資料に基づいて
データ構造
既存のデータ型から、新しいデータ型を作る仕組み
C 言語上での既存データ型
整数型 : int
浮動小数点数型 : double
文字 : char ( 小さな整数値 )
( 文字列 : char * => データ構造を持つ.. )
組み合わせ方
構造体
[構造体]
「点」のデータの構造の例
平面上の点を扱う事を考える
x 座標と y 座標の組で「点」を表現
点 p1 の x, y 座標をそれぞれ p1x, p1y で表現してみる
点の表示や、距離などは、普通に扱える [005]
「点」を 「x 座標と y 座標の組」で表現する
p1 <-> p1x, p1y
p2 <-> p2x, p2y
# これで、問題なく「点」を表現(扱う事)ができる
# 「p1 を表すのに p1x p1y という二つの変数を利用する」事は、
# (今)プログラムを書いている自分にしかわからない
# 他の人(後の自分を含む)には、なかなかわからない
# => C Compiler にもわからない
「点」を表すもの(データ構造)を考える
構造体 : 複数のデータをまとめて扱えるようにする仕組[009]
次のような形で、宣言されたもの
構文:
struct {
組み合わせる型と、その型のデータを参照するタグ名の宣言の並び
}
意味:
組み合わせる型の直積を作り、
その要素を参照する名前(タグ)を宣言する
struct { 中身 };
中身 : 直積を作る空間(となる型名)と、
その要素を取り出す(射影:projection)を行う場合に、
その要素を指定するタグ名を宣言している
構造体を作り、それを使いまわす場合、
構造体の宣言を毎回書くのは面倒なので、
構造体の宣言に名前を付けてしまう
typedef
構文
typedef 型宣言 新しい型名
意味
新しい型名を利用できるようにし、その意味は、
ここで指定した型宣言と同じ役割を与える
例:
typedef struct {
double x;
double y;
} Orthogonal;
=> 以下、
Orthogonal
とかくと、
struct {
double x;
double y;
}
と書いてあるがごとくふるまう
!! Orthogonal が ( int, double のような.. ) 型名として利用可能
!! => 型チェックもやってくれる
!! 変数同士の代入が可能
!! 方針
!! 構造体を利用する場合は、(構造体の宣言を毎回書くのは不便なので..)
!! いつでも、typedef を利用して、名前を付けて利用する
!! cf.
!! if / while の後ろには { } をつける..
構造体の中身は、色々な型を並べる事ができる[010]
課題:
20211105-03
C 言語には、三次元ベクトルを表す(組み込みの)データ型は存在しないが、
自分で、構造体を利用して、型宣言を行い、
さらに、その型の値に対して、操作を行う関数を実装すれば、
新しい型として、「三次元ベクトル」型を扱えるようになる
# 新しい型を増やす事ができる
!! 特に、
!! 構造体は、「直積空間」を作る役割を担う
!! 数学の世界での直積空間の事例は、全て、構造体で実装可能..
[配列]
配列
同じ型のデータが並んだ物を表現する仕組
例: double a0,a1,a2 -> double a[3]
配列名 : データの並びが入る変数の代表名
cf.
構造体との比較
struct { double a0; double a1; double a2; } a;
でも表現可能
構造体 配列
メンバーの型 色々な型を組み合わせる事ができる 同じ型
参照方法 タグ名(定数)で参照 添え字(数値:式が使える)
添字 「'[' + 整数値 ']'」を付けて、要素が参照できる
double a[3] で宣言された配列 a の要素は、
! <注意> 配列の宣言では、配列サイズは定数にする必要がある
a[0], a[1], a[2] の三つ
# i=1; a[i] とすれば、a[1] を表す事ができる
cf.
struct { double a0; double a1; double a2; } a;
の要素は、
a.a0. a.a1, a.a2 の三つ
配列の宣言
配列を利用する(宣言する)場合は、「配列名[サイズ]」の形にする
サイズの個数の変数がまとめて用意される
参照する場合は 0 ? サイズ-1 まで
cf.
for ( i = 0; i < サイズ; i++ ) {
配列の要素処理
配列名[i] i = 0 ? サイズ - 1
}
例: int ary[10]; とすると ary[0] ? ary[9] が使える
配列の利点
配列の要素を参照するときに添え字(場所を表す整数値)を指定するが、
その値は、式の結果でよい
=> 式の中に変数が含まれていれば、
同じ命令で、異なる機能が実現できる
例:
構造体 struct { x, y, z } s
s.x <= x の要素しか参照できない
# プログラミング時には決定しておく必要がある
配列 a[3]
a[i] <= i の値によって、a[0], a[1], a[2] が変化する
# 実行時に選択できる
配列プログラミング (集合操作)
配列 vs 集合
配列は、複数の同じ型の変数(配列の要素)をまとめたもの
個々の要素は、同じ型の値を保持する
一つの配列(が保持する値の集まり) は、その型の「集合」を表す
例:
集合 : { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }
一桁の非負の整数の集合
集合操作
配列の要素(複数)への操作を「繰返し」で表現する
「集合全体への操作」が、「個々の要素の操作の繰返し」になる
まとめ
データ構造上の処理は、
全体への処理を、個々の要素の処理の組み合わせで実現
構造体の場合は順接になる
struct { x, y, z } d, s
d.x = s.x
d.y = s.y
d.z = s.z
配列の場合は、くり返しなる
d[3], s[3]
for ( i = 0; i < 3; i++ ) {
d[i] = s[i]
}
課題プログラム内の「/*名前:ここ*/」の部分を書き換え「/*この部分を完成させなさい*/」の部分にプログラムを追加して、プログラムを完成させます。
Download : 20211112-01.c
/*
* 課題 20211112-01
*
* 20211112 20211112-01-QQQQ.c
*
* 複素数型の四則
*/
#include <stdio.h>
/*
* 複素数型の定義と計算
*
* 利用方法
* コンパイル
* cc -Ic:\usr\c\include -o BASENAME.exe 20211112-01-QQQQ.c
* 実行
* BASENAME
*/
#include <stdio.h>
/*
* 複素数型を表す Complex の定義
*
* 複素数 z は、二つの実数 x, y を用いて
* z = x + yi ( i は虚数単位 )
* と表現できる。
* C 言語では実数を表すのに浮動小数点数型の double を用いる
* 型名 ( Complex ) を大文字で始めるのは「ソフトウェア概論ルール」
*/
typedef struct {
double real; /* 実部 */
double imaginary; /* 虚部 */
} Complex; /* 複素数型 */
/*
* Complex make_Complex ( double x, double y )
* Complex 型の数を作り、返す
* x, y -> z = x + yi
*/
Complex make_Complex ( double x, double y ) {
Complex newComplex; /* 新しく作られる複素数 */
newComplex.real = x; /* 新しく作られた複素数の実部は x */
newComplex.imaginary = y; /* 新しく作られた複素数の実部は y */
return newComplex; /* 新しく作られる複素数を値として返す */
}
/*
* double real_part ( Complex z )
* Complex 型の数の実部を返す
* z = x + yi -> x
*/
double real_part ( Complex z ) {
return z.real;
}
/*
* double imaginary_part ( Complex z )
* Complex 型の数の実部を返す
* z = x + yi -> x
*/
double imaginary_part ( Complex z ) {
return z.imaginary;
}
/*
* print_Complex ( Complex z )
* Complex 型の数の出力
* z = x + y i だが、y < 0 の時は z = x - (-y) i となるように工夫
*/
void print_Complex ( Complex z ) {
if ( z.imaginary > 0.0 ) {
printf ( "%f + %f i", z.real, z.imaginary );
} else {
printf ( "%f - %f i", z.real, - z.imaginary );
}
}
/*
* Complex add_Complex ( Complex z1, Complex z2 )
* Complex 型の数の足し算
* z1 = x1 + y1 i
* z2 = x2 + y2 i
* -> z1 + z2 = ( x1 + x2 ) + ( y1 + y2 ) i
*/
Complex add_Complex ( Complex z1, Complex z2 ) {
Complex result;
/* 複素数の和の実部は、実部の和 */
result.real = z1.real + z2.real;
/* 複素数の和の虚部は、虚部の和 */
result.imaginary = z1.imaginary + z2.imaginary;
return result;
}
/*
* Complex sub_Complex ( Complex z1, Complex z2 )
* Complex 型の数の引き算
* z1 = x1 + y1 i
* z2 = x2 + y2 i
* -> z1 - z2 = ( x1 - x2 ) + ( y1 - y2 ) i
*/
Complex sub_Complex ( Complex z1, Complex z2 ) {
Complex result;
/* 複素数の差の実部は、実部の差 */
result.real = z1.real - z2.real;
/* 複素数の差の虚部は、虚部の差 */
/*
** この部分を完成させなさい
*/
return result;
}
/*
* Complex mul_Complex ( Complex z1, Complex z2 )
* Complex 型の数のかけ算
* z1 = x1 + y1 i
* z2 = x2 + y2 i
* の時
* z1 * z2 = (x1 * x2 - y1 * y2) + (x1 * y2 + x2 * y1) i
*/
Complex mul_Complex ( Complex z1, Complex z2 ) {
Complex result;
result.real = z1.real * z2.real - z1.imaginary * z2.imaginary;
/*
** この部分を完成させなさい
*/
return result;
}
/*
* Complex div_Complex ( Complex z1, Complex z2 )
* Complex 型の数の割り算
* z1 = x1 + y1 i
* z2 = x2 + y2 i
* の時
* z1 / z2 = ( x1 + y1 i ) / ( x2 + y2 i )
* = ( x1 + y1 i )( x2 - y2 i ) / ( x2 + y2 i )( x2 - y2 i )
* = ( x1 * x2 + y1 * y2) / ( x2^2 + y2^2 )
* + ( (- x1 * y2 + x2 * y1) / ( x2^2 + y2^2 ) ) i
*/
Complex div_Complex ( Complex z1, Complex z2 ) {
Complex result;
double denominator = z2.real * z2.real + z2.imaginary *z2.imaginary;
/* 実部、虚部の割る数 |z2|^2 を予め計算しておく */
/*
** この部分を完成させなさい
*/
result.imaginary = ( - z1.real * z2.imaginary + z1.imaginary * z2.real ) / denominator;
return result;
}
/*
* print_result 演算結果を出力する
*/
void print_result ( Complex z1, Complex z2, char *operator, Complex z ) {
print_Complex ( z1 );
printf ( " と、 " );
print_Complex ( z2 );
printf ( " との、%s は ", operator );
print_Complex ( z );
printf ( " です。\n" );
}
/*
* main
*/
int main( int argc, char *argv[] )
{
Complex z1 = make_Complex ( 20.0, -15.0 ); /* z1 = 20 - 15i */
Complex z2 = make_Complex ( 1.0, 2.0 ); /* z2 = 1 + 2i */
/* 和の出力 */
print_result ( z1, z2, "和", add_Complex ( z1, z2 ) );
/* 差の出力 */
/*
** この部分を完成させなさい
*/
/* 積の出力 */
/*
** この部分を完成させなさい
*/
/* 商の出力 */
print_result ( z1, z2, "商", div_Complex ( z1, z2 ) );
return 0;
}
$ ./20211112-01-QQQQ.exe 20.000000 - 15.000000 i と、 1.000000 + 2.000000 i との、和 は 21.000000 - 13.000000 i です。 20.000000 - 15.000000 i と、 1.000000 + 2.000000 i との、差 は 19.000000 - 17.000000 i です。 20.000000 - 15.000000 i と、 1.000000 + 2.000000 i との、積 は 50.000000 + 25.000000 i です。 20.000000 - 15.000000 i と、 1.000000 + 2.000000 i との、商 は -2.000000 - 11.000000 i です。 $
Download : 20211112-02.c
/*
* 課題 20211112-02
*
* 20211112 20211112-02-QQQQ.c
*
* 二次元行列型の定義と計算
*/
#include <stdio.h>
/*
*
*/
#define DIMENSION 2 /* 二次元 */
/*
* 行列 A は、2 x 2 = 4 の要素をもっている
*
* A = ( 1 2 ) = ( a[0][0] a[0][1] )
* 3 4 a[1][0] a[1][1]
*
*/
typedef struct {
double a[DIMENSION][DIMENSION]; /* 二次元の行列の要素は 2 x 2 */
} Matrix2D; /* Matrix2D 型の宣言 */
/*
* Matrix2D make_Matrix2D ( double a, double b, double c, double d )
* 「行列」を作成する
*
* A = ( a b ) = ( a[0][0], a[0][1] )
* ( c d ) ( a[1][0], a[1][1] )
*/
Matrix2D make_Matrix2D ( double a, double b, double c, double d ) {
Matrix2D newMatrix2D; /* 新しい行列 */
newMatrix2D.a[0][0] = a;
newMatrix2D.a[0][1] = b;
newMatrix2D.a[1][0] = c;
newMatrix2D.a[1][1] = d;
return newMatrix2D;
}
/*
* void print_Matrix2D ( Matrix2D ary );
* 「行列」を表示する (表示の都合上、常に独立した行に出力する)
* Matrix2D ary; 二次元行列
*/
void print_Matrix2D ( Matrix2D ary ) {
int r; /* 行 ( row ) */
int c; /* 列 ( colomun ) */
for ( r = 0; r < DIMENSION; r++ ) {
printf ( "(" );
for ( c = 0; c < DIMENSION; c++ ) {
printf ( " %10.5f", ary.a[r][c] );
/*
* [注意] %10.5f は %f と同じく浮動小数点数を出力するが
* 「全体の桁数は 10 桁、小数点数以下は 5 桁にする」
* という「表示上の指定」も加わっている
* 詳しくは google で「printf 書式」で検索
*/
}
printf ( " )\n" );
}
}
/*
* Matrix2D add_Matrix2D ( Matrix2D a1, Matrix2D a2 );
* 「行列」の和
*
* ( a b ) + ( e f ) = ( a + e b + f )
* ( c d ) ( g h ) ( c + g g + h )
*/
Matrix2D add_Matrix2D ( Matrix2D a1, Matrix2D a2 ) {
Matrix2D result; /* 計算結果 */
int r; /* 行 ( row ) */
int c; /* 列 ( colomun ) */
for ( r = 0; r < DIMENSION; r++ ) {
for ( c = 0; c < DIMENSION; c++ ) {
result.a[r][c] = a1.a[r][c] + a2.a[r][c];
}
}
return result;
}
/*
* Matrix2D sub_Matrix2D ( Matrix2D a1, Matrix2D a2 );
* 「行列」の差
*
* ( a b ) - ( e f ) = ( a - e b - f )
* ( c d ) ( g h ) ( c - g g - h )
*/
Matrix2D sub_Matrix2D ( Matrix2D a1, Matrix2D a2 ) {
Matrix2D result; /* 計算結果 */
int r; /* 行 ( row ) */
int c; /* 列 ( colomun ) */
for ( r = 0; r < DIMENSION; r++ ) {
for ( c = 0; c < DIMENSION; c++ ) {
/*
** この部分を完成させなさい
*/
}
}
return result;
}
/*
* Matrix2D mul_Matrix2D ( Matrix2D a1, Matrix2D a2 );
* 「行列」の積
*
* ( a b ) ( e f ) = ( a * e + b * g a * f + b * h )
* ( c d ) ( g h ) ( c * e + d * g c * f + d * h )
*/
Matrix2D mul_Matrix2D ( Matrix2D a1, Matrix2D a2 ) {
Matrix2D result; /* 計算結果 */
int r; /* 行 ( row ) */
int c; /* 列 ( colomun ) */
int i;
for ( r = 0; r < DIMENSION; r++ ) {
for ( c = 0; c < DIMENSION; c++ ) {
double products = 0.0; /* a1 の r 行と a2 の c 列の内積の結果 */
/* a1 の r 行と a2 の c 列の内積を計算する */
/*
** この部分を完成させなさい
*/
result.a[r][c] = products;
}
}
return result;
}
/*
* print_result 演算結果を出力する
*/
void print_result ( Matrix2D a1, Matrix2D a2, char *operator, Matrix2D a ) {
printf ( "%s の計算\n", operator );
print_Matrix2D ( a1 );
printf ( " と、 \n" );
print_Matrix2D ( a2 );
printf ( " との、%s は \n", operator );
print_Matrix2D ( a );
printf ( " です。\n\n" );
}
/*
* main
*/
int main( int argc, char *argv[] )
{
/*
a1 = ( 1 2 )
( 3 -1 )
a2 = ( -3 1 )
( 1 -2 )
*/
Matrix2D a1 = make_Matrix2D ( 1.0, 2.0, 3.0, -1.0 );
Matrix2D a2 = make_Matrix2D ( -3.0, 1.0, 1.0, -2.0 );
/* 和の出力 */
print_result ( a1, a2, "和", add_Matrix2D ( a1, a2 ) );
/* 差の出力 */
/*
** この部分を完成させなさい
*/
/* 積の出力 */
/*
** この部分を完成させなさい
*/
return 0;
}
123 987 456
$ ./20211112-02-QQQQ.exe 和 の計算 ( 1.00000 2.00000 ) ( 3.00000 -1.00000 ) と、 ( -3.00000 1.00000 ) ( 1.00000 -2.00000 ) との、和 は ( -2.00000 3.00000 ) ( 4.00000 -3.00000 ) です。 差 の計算 ( 1.00000 2.00000 ) ( 3.00000 -1.00000 ) と、 ( -3.00000 1.00000 ) ( 1.00000 -2.00000 ) との、差 は ( 4.00000 1.00000 ) ( 2.00000 1.00000 ) です。 積 の計算 ( 1.00000 2.00000 ) ( 3.00000 -1.00000 ) と、 ( -3.00000 1.00000 ) ( 1.00000 -2.00000 ) との、積 は ( -1.00000 -3.00000 ) ( -10.00000 5.00000 ) です。 $
Download : 20211112-03.c
/*
* 課題 20211112-03
*
* 20211112 20211112-03-QQQQ.c
*
* 整数型の配列を作り、それに 5 個のデータを入力し
* その値を 5 倍にしたものと 2 分の 1 にした値を
* それぞれ、画面に出力するプログラムを作りなさい
*
*/
#include <stdio.h>
/*
*
*/
#define DATA_SIZE 5 /* データのサイズ (個数) */
/*
*
*/
int main(int argc, char *argv[]) {
int array[DATA_SIZE]; /* サイズが DATA_SIZE の整数型の配列 array の宣言 */
int i; /* 添字変数 i を宣言 */
for ( i = 0; i < DATA_SIZE; i++ ) { /* 配列 array に数値を読み込む */
/* プロンプト */
printf ( "%d 番目の整数値を入力してください : ", i + 1 );
/* 配列へのデータ入力 */
scanf ( "%d", &array[i] );
}
/* 入力された個々の値を 5 倍した物を出力 */
for ( i = 0; i < DATA_SIZE; i++ ) {
printf ( "%d\n", /* p:ここ */ ); /* 5 倍 */
}
/* 入力された個々の値を 1/2 した物を出力 */
for ( i = 0; i < DATA_SIZE; i++ ) {
printf ( "%d\n", /* q:ここ */ ); /* 2 分の 1 */
/* 整数割り算になるので、小数点以下は切り捨て */
}
return 0;
}
3 8 13 2 4
$ ./20211112-03-QQQQ.exe $