有村秀孝 1
0.レポートの書き方
表紙を付ける.コンピュータプログラミング入門 (x)
(xは回), 実習日,学籍番号,氏名
を記入すること.プログラムのアルゴリズムと実行結果,プログラム自体を付けること.1つに
まとめてホッチキス止めして提出すること.
以上を満たさないレポートは受け取らない
.
コンパイラとテキストエディタのインストール
Windows ユーザ:
gcc コンパイラ Cygwin インストール:
https://www.sw.it.aoyama.ac.jp/2011/CP1/cygwin/
テキストエディタ
Terapad のインストール:
https://tera-net.com/
Mac ユーザ:
gcc コンパイラ Xcode インストール:
https://webkaru.net/clang/mac-compiler-gcc-install/
テキストエディタ
mi インストール:
https://www.mimikaki.net/
1.
C
言語基礎
(1)プログラム作成の流れ プログラミングとは、プログラムを作ることです。作ったプログラムは、一般的には、ソフトウエアと呼 ばれます。ソフトウエアは、コンピュータ(CPU,メモリ、ハードディスクなど)、プリンターなどのハー ドウエアを使って、いろいろな計算、画像処理などを実行します。したがって、ソフトウエア無しに、コン ピュータは動作しません。本演習では主に、画像処理のプログラムを作成します。皆さんが作成したプログ ラムに従って、コンピュータが画像を処理し、その結果を示してくれます。ただし、皆さんが作ったC言語有村秀孝 のプログラムはそのままでは、人間は理解できても、コンピュータは理解できません。皆さんが作るプログ ラムはソースプログラム(ソースファイル)と呼ばれます。C言語では、*.c という形式にファイルで作成し ます。そのソースプログラムをコンピュータが理解できるようなデータ形式に変換することをコンパイルと 呼びます。コンパイルした後のファイルは、マシン語の形式になっており、実行ファイルと呼ばれます。 Cygwin では、*.exe という形式になります。つまり、ソースプログラムをコンパイルすることによって、プ ログラムを実行することができます。実は、コンパイルの後に「リンク」も実行されます。リンクとは、い ろいろな標準関数(printf(表示する), scanf(入力する), fopen(ファイルを開く)など、ユーザーが作る 必要が無い標準的な関数)のオブジェクトファイル(マシン語の形式に変換されている)を皆さんが作った プログラムに組み込むことです。以上のことをいかにまとめます。 (1) エディターを使って、ソースプログラム(*.c)作成する。本実習では、エディタとして、TeraP adを使います。 (2) コンパイラを使って、ソースプログラムをマシン語に変換し、実行ファイルを作成する。本実習 では、コンパイラとしてCygwin の gcc を使います。 (3) 実行ファイルを使って、プログラムを実行します。 (2)基本プログラム1とコンパイル・実行の方法 1)基本プログラム1 以下のプログラムをTeraPad で作成してください.字下げをうまく使ってプログラムを書いてください. #include <stdio.h> /* (1) */ int main( ) /* (2) */ { /* (3) */
printf("Hi! How are you?¥n"); /* (4) */
} /* (5) */
TeraPad でファイルの種類は C/C++を選んで、****.c という名前にする。****は適当につける。
この例では、
hello.c という名前で保存します。
保存先は Cドライブの arimura とします.Cygwin での ディレクトリ(ホルダ)の移動は以下のように行う. cd /cygdrive/c cd arimura 2)コンパイル方法 Cygwin の gcc を用いて、コマンドラインで、つぎのようにタイプし、Enter を押します。以下の例では、 hello.c というソースプログラムをコンパイルして、hello という実行ファイルを作ります。$ gcc –o hello hello.c
(-o : この次にある引数は、実行ファイル名を書きます) 3)実行方法
実行ファイル名をコマンドラインに書いてEnter を押します。 $ ./hello
有村秀孝 3 4)基本プログラム1の解説 このプログラムはC言語の基本中の基本プログラムです。これを番号順に説明します。 1行目:stdio.h はインクルードファイルと呼ばれるファイルです。インクルードファイルにはいろいろあり、 例えば、このstdio.h にはC言語プログラムで使う基本的な関数(例えば、標準出力する関数 printf、ファイルを 開く関数fopen、データを読み込む関数 fread、データを書き込む関数 fwrite など)の定義が書かれています。他 には、数学的な関数sin( ), cos( )などが定義されている math.h などもあります。 #include< >はインクルード ファイルをここに読み込むという命令文です。このファイルを読み込むこと(インクルード)をしないと、こ れらの基本的な関数を使えません。/* */で囲んだものはコメント文として処理されます。
2行目:C言語のプログラムは必ずmain 関数1つを持ちます。main 関数の3と5行目の{ }の中にいろいろな 処理を書いていきます。main 関数の{ }を忘れないようにしてください.
3行目:printf は画面に文字列、数を出力したいときに用います。stdio.h に定義されている基本関数の一つで す。“Hi! How are you?¥n”のようにダブルコーテーションで囲んだ文字列を出力します.¥n は改行するための コードです。
(3)基本プログラム2
エディタを使って、「二つの整数の足し算をする」プログラムを作成します。 プログラム例(右側の説明はアルゴリズム)を以下に示します。
#include <stdio.h> /* (1) stdio.h を読み込む*/
int main(int argc, char *argv[]) /* (2) main 関数の定義*/ {
int a, b, c; /* (3) 変数宣言(a, b, c を使えるようにする)*/
a=atoi(argv[1]); /* (4) argv[1]の文字列を atoi の関数を用いて整数型の数値へ変換する*/
b=atoi(argv[2]); /* (5) argv[2]の文字列を atoi の関数を用いて整数型の数値へ変換する*/ c=a+b; /* (6) a+b を実行し、その結果を c へ代入する */
printf("sum = %d¥n", c); /* (7) “sum=c の値(十進数)”を、printf 関数を用いて表示する */ }
2)コンパイル方法
$ gcc –o cal_sum
cal_sum.c
3)実行方法 $
./
cal_sum 10 20 sum = 30 このプログラムもC言語のの基本プログラムです。これを番号順に説明します。 2行目:上記で説明しましたように,C言語のプログラムは必ずmain 関数1つを持ちます。この main 関数は 関数なので引数をとることができます。有村秀孝 int main(int argc, char *argv[]) /* (2) */
int argc コマンドラインに並べた引数の数を入れる変数です。実行プログラムを含みます。int は「argc は整数型として使います」という意味です。
char argv[ ] コマンドラインに並べた引数の文字列を入れる配列変数です。引数が順番に入ります。char は 「*argv[ ]は文字列型として使います」という意味です。 例えば、以下のようにプログラムを実行すると、 $
./
cal_sum.exe 10 20 以下のように代入されます。 argc = 3 argv[0]=’cal_sum’ argv[1]=’10’ argv[2]=’20’ 3行目:ここにはプログラムで使いたい変数をまず記述します。これを変数宣言といいます。例の場合、二つ の整数の合計を計算するので、それらの変数をa と b とし、整数型の int 型で宣言しています。C言語の文の 終わりには必ずセミコロン「;
」を付けます。4行目:argv[1]と argv[2]に入っている文字列を整数に変換するために atoi( )関数を用いています。ascii to integer の略です。戻り値は変換された整数になります。例の場合、a=atoi(argv[1]);では argv[1]に’10’が入っていたら、 a には整数10が代入されます。 5行目:これは「aとbを足して、その結果をcに代入する」と意味です。cはa+bに等しいという意味で はありません。 6行目:文字列だけでなく,printf は画面に計算結果の数値を出力したいときにも使えます。%d は出力するデ ータを符号付き整数(int 型)と解釈して、10進数に変換します。この場合、cを10進数に変換して’sum=’の 次に出力します。¥n は改行するためのコードです。 (4)変数宣言 プログラムで使いたい変数をまず記述します。これを変数宣言といいます。変数の型として主に以下のような ものがあります。 int 整数型の変数に用いる。通常、4 バイト。 符号付き(signed): -231(2147483648) ~ 231 – 1 (2147483647)、 符号無し(unsigned): 0 ~ 4294967296 short int より短い整数型。通常、2 バイト。16ビット画像データを扱うときによく用いる。 符号付き(signed): -32768 ~ 32767、 符号無し(unsigned): 0 ~ 65535
有村秀孝 5 float 実数型の変数に用いる。通常、4 バイト。 1e-38~1e+38 double 倍長実数型の変数に用いる。通常、8 バイト。 1e-307~1e+308 char 1 バイトの変数(通常、文字列の変数)に用いる。通常、1 バイト。 (5)レポート課題 基本プログラム2でa と b に非常に大きな値を入力した場合,足し算の結果が間違う場合があります.理由を 考えて,「変数の型とオーバーフロー」のレポートとして提出してください.提出日は、次回の演習時。
有村秀孝 2.ループ演算(1) (1) for 文 ~指定回数くり返す~ 「指定回数くり返す」ということを得意とする制御文があります。それがfor 文です。 for(式1;式2;式3) 文
for 文は while 文の拡張版と考えて差し支えありません。この文を while で書き直すとこうなります。
式1; while(式2){ 文 式3; } 例を以下に示します。 #include <stdio.h> main() { int i; for(i = 0; i < 10; i++){ printf("i = %d¥n", i); } printf("end.¥n"); } この例は、一番オーソドックスなfor 文の使い方です。ではこのプログラムがどう動いているのか、順を追 って説明します。while 文で書き直した図を見ながら理解してください。 1. まず「式1」を評価(実行)するので、iは0になります。 2. 次に「式2」を評価します。この時iは0ですから条件は成り立ちます。
有村秀孝 7 3. よって「文」を実行します。つまり画面にiの内容が表示されます。 4. 次に「式3」を評価(実行)、つまりここではiが1増えて、iの内容は1になります。
5.
これをくり返して、「式3」によってiが10になったときに、このループから抜け出します。適用例
1. 数学の∑ は for 文で計算できます.例えば,平均値(𝑓̅ ='&∑'()&𝑓()や分散(𝜎,='&∑'()&-𝑓(− 𝑓̅/,)を求めると き. 2.
画像ファイルからピクセル値をピクセルごとに読み込むときに用いる.
3.フィルタ処理(畳み込み積分)の計算
課題1 1 から 10 までの足し算を求めてみる S = 1 𝑖 &3 ()& 課題2.0.1 を 100 回足してみる(実数型の float と double, まるめ誤差) S = 1 0.1 &33 ()& レポート課題 課題2の結果に基づいて,まるめ誤差についてまとめ,レポートとして提出してください。有村秀孝 3.ループ演算(2)
課題1 for 文を用いて、char 型、short 型、int 型の変数における、階乗(n! = ∏: 𝑖
()& = 1 ∙ 2 ∙ 3 ∙ ⋯ ∙ n)を求め てください。ただしn=20 としてください。(階乗計算、変数の型とオーバーフロー) 課題2 ネイピアの数(自然対数の底)e(2.71828 18284 59045 23536 02874 71352…)を、マクローリン展開 を使って、求めてみる。(for文) マクローリン展開 𝑓(𝑥) = @𝑛!1𝑓(:)(0)𝑥: B :)3 𝑒D= 1𝑥( 𝑖! B ()3 = 1 + 𝑥 1!+ 𝑥, 2!+ 𝑥F 3!+ ⋯ + 𝑥: 𝑛! + ⋯ , −∞ < 𝑥 < ∞ 𝑒 = 11 𝑖! : ()3 = 1 +1 1!+ 1 2!+ 1 3!+ ⋯ + 1 𝑛! 上記の式とfor文を使って、ネイピアの数(自然対数の底)eの値を求めてください。 レポート課題 半径1の4分の1円の面積を求めることで,“π”の値を求めるプログラムを作成してください.二乗は x*x かpow(x, 2)です.√は sqrt( )()内は double 型です.
有村秀孝
9 4.文字列と制御文
課題1 名前を表示してみる。(配列) 配列
char name[10]; /* 10個の name の入れものができる。つまり、name[0], name[1], ,,,, name[9]で、name[9]には、 NULLというコードが入る。NULL はここで終わりという意味。 したがって、入力したい文字数+1個分の入れ物が必要。 例えば、strcpy(name, “Hide”); とすると、 name[0] => “H” name[1] => “i” name[2] => “d” name[3] => “e” name[4] => NULL 例を以下に示します。 #include <stdio.h> #define MAX_NAME_LENGTH 30 main() { int i; char name[MAX_NAME_LENGTH]; strcpy(name, "Your Name");
for(i = 0; i <= strlen(name); i++){
printf("name[%d] => %c¥n", i, name[i]); }
有村秀孝 }
上記のプログラム中のstrcpy(name, "Your Name");において、"Your Name"のところを自分の名前に書き換えて ください。ただし名前は半角英数字で入力してください。 またfor 文を変更して、名前を逆の順序で作成してください。ただしNULL文字は表示させない。 <表示例> name[3] => “e” name[2] => “d” name[1] => “i” name[0] => “H” 課題2 double 型の配列に適当な5個の実数を入れて、その中の最小値を求めてみる。 (配列、for 文と if 文) if文 制御の流れを分岐させるときの方法の一つとして、if 文があります。 一般的な構文は if(式) {文}; 式が真ならば文を実行。(0以外は真) if(式) {文1}; else {文2}; 式が真ならば文1を実行、偽ならば文2を実行。
有村秀孝 11 式としては一般的には次のようなものになります。 式1 関係演算子 式2 式1 論理演算子 式2 具体的には次のようなものが考えられるでしょう。 A = = B A が B に等しいならば真。 A != B A が B に等しくないならば真。 A < B A が B より小さいならば真。 A >= B A が B 以上ならば真。 式1 && 式2 式1 かつ 式2の両方成り立つならば真。 式1 || 式2 式1 または 式2のどちらか成り立つならば真。 最大値を求めるプログラムの例 #include <stdio.h> main() { int i; double MaxValue; double value[5] = {1.2, 3.4, 2.3, 5.1, 0.7}; MaxValue = 0.0; for(i = 0; i < 5; i++){ if(MaxValue < value[i]){ MaxValue = value[i]; printf("value[%d] => %f¥n", i, value[i]); } }
printf("Maximum value : %f ¥n", MaxValue); }
上記の最大値を求めるプログラム例をヒントにして、最小値を求めるプログラムを作成してください。
課題3 上記の最大値を求めるプログラム例を修正して、5個の実数の平均値を求めるプログラムを作成し てください。平均値の式は𝒇K =𝑵𝟏∑𝑵𝒊)𝟏𝒇𝒊です.
有村秀孝 5.ループ演算と制御文 課 題 1 以 下 の 10 人 分 の 身 長 の デ ー タ に 対 し 、 double 型 の 配 列 を 用 い 、 平 均 値 、 標 準 偏 差 (σ = Q'&∑ -𝑓(− 𝑓̅/ , ' ()& )を求め、平均値で2値化するプログラムを作成してください。(if文, sqrt 関数, pow 関数) 150.1, 186.4, 174.2, 189.9, 169.6, 159.2, 163.8, 156.9, 173.2, 167.4 (1)ルートの関数は、 sqrt( ここには double 型の変数を入れる) です。 たとえば、 A = sqrt(2.0); printf(“A = %f ¥n”, A); と書くと、実行結果は、 A=1.414….. と表示されるはず。 (2)xのy乗を求めるために、pow を使います。 Z = pow(x, y); Z, x, y は、すべて double 型です。 注意! sqrt、pow を使うために math.h をインクルードします。コンパイルする際は、最後に –lm を追加。 例) gcc –o kadai7 kadai7. c –lm
課題2 上記の課題1で作成したプログラムにおいて、平均値を求める関数を作成して、プログラムを書き 換えてください。(関数) 関数 C言語でのプログラムは「関数」という小さなプログラムの集まりで構成されます。 main() も関数ですし、 printf() や 上記の課題で用いた、pow()や sqrt()も関数です。 関数とは、いくつかの引数を受けて計算を行い、その結果を返すもので、何らかの値を与えると、それに応 じた値が返ってくる。関数は計算結果としてなんらかの型(int や char、double など)を持つ値を返します。 しかし、型のない関数(つまり値を返さない関数)も存在します。 printf() などの標準関数は、すでに用意されている関数なので、プログラム中で単に呼び出すだけでよ いのですが(実際には#include <stdio.h>によって標準関数についての読み込みが必要)、標準関数に用意 されていない関数は、自分で作らなければなりません。関数の定義は以下のとおりです。 [関数の型] 関数名[引数の宣言] { 関数本体 [return 返す値] } 関数の型とは、関数が返す値の型で、関数が扱う変数の型ではありません。関数名は、printf などといっ た名前です。printf 関数に渡していたデータを引数 といいます。
有村秀孝 13 関数が返す値を決めるものがreturn です。値を返すことで関数の働きは終了するのですから、この return 文で関数の実行が終了します。 関数が正しく設定され、利用されているかチェックするものに関数プロトタイプ宣言があります。関数プロト タイプ宣言とは、関数の引数の数とその型、そして関数自身が返す値の型をあらかじめ宣言することです。コ ンパイラは、関数と関数プロトタイプ宣言されたものと比較し、変数の数や戻り値の型が等しくなければエラ ーを出します。 2 ページの「二つの整数の足し算をするプログラム」を例に、「足し算」の関数を作成する例を示します。 #include <stdio.h> /* (1) */ int main(int argc, char *argv[]) /* (2) */ { int a, b, c; /* (3) */ a=atoi(argv[1]); /* (4) */ b=atoi(argv[2]); c=a+b; /* (5) */ printf("sum = %d¥n", c); /* (6) */ } 手順1.関数名、関数の返り値、引数を決める。
例)関数名→wa、関数の返り値の型→ int、引数の型→ int 、引数の個数→2個 手順2.関数を定義する。
前頁の「関数の定義」を参考に定義する。 int wa(int a, int b){
}
手順3.関数をmain()関数の外側に書く。 手順4.関数本体を作成。
関数wa は「二つの int 型の引数を足して、int の値を返す」という役割なので、関数本体は以下のようになる。 int wa(int a, int b){
int c; c = a+b; return c; } 手順5.プロトタイプ宣言を関数の前に書く。 関数名、関数の戻り値の型、引数の型、個数を書く。 int wa(int a, int b);
有村秀孝 6.演習(1) 課題1 角度θ[度]を入力し、sinθ,cosθ,tanθ の計算結果を出力するプログラムを作成してください。 C 言語での三角関数は、以下のとおりです。 double sin(double x) double cos(double x) double tan(double x) 引数の単位はラジアンです。 数学関数を使用するためには #include <math.h> として math.h というヘッダをインクルードする必要があります。また、コンパイル時は最後に –lm を追加。 例) gcc –o kadai9 kadai9. c –lm
課題2 次の微分方程式をオイラー法とルンゲクッタ法を使って解いてください。またそれぞれの方法によ って得られた数値解の精度を理論値(解析的に解いた解の式から求めた値)と比較してください。 常微分方程式の数値計算 物理学や工学において、導関数を含む関係式が与えられているとき、このような関係式を満たす関数を求め る必要がしばしば生じます。導関数を含む関係式から、関数そのものを求めるとき、導関数を含む関係式を微 分方程式といい、微分方程式に含まれる導関数が、一つの変数による微分であるとき、常微分方程式といいま す。 常微分方程式の数値解は,以下のようにして求めます。 を数値的に解くということは、 t = t0 = 0 で x=x0 から出発して,t = t1, t2, ……, tk, ….., tn でのx の数値 x = x1, x2, ……, xk, ….., xn を求めていくことである。ただし とする。 オイラー法 ルンゲクッタ法
x
dt
dx =
x
(
0
)
=
1
,
0
£
t
£
1
,
h
=
0
.
05
)
,
( t
x
f
dt
dx =
t = 0 で x=x0h
t
t
i+1-
i=
)
(
1 k k k kx
hf
x
t
x
+=
+
+
)
2
2
(
6
1
4 3 2 1 1x
h
k
k
k
k
x
k+=
k+
+
+
+
有村秀孝 15
)
,
(
)
2
,
2
(
)
2
,
2
(
)
,
(
3 4 2 3 1 2 1h
t
hk
x
f
k
h
t
hk
x
f
k
h
t
hk
x
f
k
t
x
f
k
k k k k k k k k+
+
=
+
+
=
+
+
=
=
有村秀孝 7.演習(2) 課題1 以下に示す範囲の f(x)をフーリエ級数展開してみましょう。 また級数において第 N 項まで求める 際、N=10、20、30 とした場合の結果を比較してください。 フーリエ級数展開 区間[-p, p] における積分可能な関数 f(x)は次のように展開することが可能です。 このように表現されるとき、上式のan、bnは以下のように与えられる。 <手順1> a0、an、bnを求める。 <手順2>