Powered by SmartDoc

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

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

目次

講義資料

当日の OHP 資料

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

Download : sample-001.c

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.c の実行結果
$ ./sample-001.exe
 z1 ( = 2.000000 + 3.000000 i ) と、 z2 ( = -1.000000 + 5.000000 i ) の和は 、
1.000000 + 8.000000 i です。
$ 

Download : sample-002.c

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.c の実行結果
$ ./sample-002.exe
 z1 ( = 2.000000 + 3.000000 i ) と、 z2 ( = -1.000000 + 5.000000 i ) の和は 、
1.000000 + 8.000000 i です。
$ 

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

本日の課題

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

課題 20211112-01 : 複素数型の四則

Download : 20211112-01.c

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.c の実行結果
$ ./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 です。
$ 

課題 20211112-02 : 二次元行列の和、差、積

Download : 20211112-02.c

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.c の実行結果
$ ./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  )
 です。

$ 

課題 20211112-03 : 配列を使って 5 個の数を入力し、その 5 倍と 1/2 を出す

Download : 20211112-03.c

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.c の実行結果
$ ./20211112-03-QQQQ.exe
$