Cプログラミング演習
ガイダンス
例題 数値計算 ・・・ 微分,積分等 画像処理 ・・・ 配列(2次元/3次元) データ処理 ・・・ ソート,選択 例題 数値計算 ・・・ 微分,積分等 画像処理 ・・・ 配列(2次元/3次元) データ処理 ・・・ ソート,選択 これら例題を通して,プログラミングの知識を習得
画像処理の例 左が元の画像、右が一次微分(roberts オペレータ)(利得3)の結果
C 言語での2次元画像の表現 濃淡画像(grayscale) の場合 image[Y_SIZE][X_SIZE] 2次元の配列 それぞれが画素 (画像の基本単位) Y_SIZE X_SIZE
C 言語での2次元画像の表現 カラー画像(color) の場合 image[3][Y_SIZE][X_SIZE] 3次元の配列 red, blue, green の3原色 red blue green
C言語 D. M. Ritchieが1970年にUNIXを記述するために作成した言語 低レベルの操作ができる メモリの操作など ANSI により規格化、汎用性が高い 広く利用されている 手続き型言語のひとつ プログラムの実行順序を明示 コンパイラ型言語のひとつ CR
コンピュータの振る舞いとメカニズム
コンピュータのハードウエア構成 CPU 入力装置 出力装置 メモリ 補助記憶装置
CPU CPU 入力装置 出力装置 コンピュータ全体の制御,演算を行う LSI チップ メモリ 補助記憶装置
CPU メモリ メモリ デジタルデータの記憶を行うLSIチップ デジタルデータを覚えさせたり,取り出したりの機能がある 出力装置 入力装置 補助記憶装置
CPU メモリ CPU CPU,メモリ間で デジタルデータが やり取りされる 入力装置 出力装置 メモリ 補助記憶装置
CPU 入力装置 出力装置 データ アドレス アドレスは, 読み書きしたいデータの場所 メモリ 補助記憶装置
CPU コントロールバス (control bus) メモリ (RAM) アドレスバス (address bus) データバス (data bus) CPU コントロールバス (control bus) R/W など R: Read W: Write メモリ (RAM)
CPU ① アドレス ② データ メモリからのデータ読み出し メモリ (RAM) 2バイト分 ① メモリに,アドレスを与えると のデータ ① アドレス ② データ CPU メモリからのデータ読み出し ① メモリに,アドレスを与えると ② メモリから,データが 読み出される 2バイト分 のデータ アドレス「4」 普通、メモリからは,複数バイト分 のデータが一括して読み出される アドレス4,5の メモリをオン この場合2バイト単位で読み出し メモリ (RAM)
CPU ① アドレス ① データ メモリへのデータ書き込み メモリ (RAM) ① メモリに,アドレスとデータを 2バイト分 与えると ① アドレス ① データ CPU メモリへのデータ書き込み ① メモリに,アドレスとデータを 与えると 2バイト分 のデータ ② データが書き込まれる アドレス「6」 前のデータは 消える(上書き) この場合2バイト単位で書き込み メモリ (RAM)
CPU メモリ 入力装置 出力装置 補助記憶装置 アドレス データ メモリからCPUへの読み出し 補助記憶装置
CPU メモリ 入力装置 出力装置 補助記憶装置 アドレス データ CPUからメモリへの書き込み 補助記憶装置
C言語によるプログラミング入門
メッセージ表示プログラム 画面に表示されたメッセージ #include "stdafx.h" int _tmain() { printf("Hello, world\n"); } Visual Studio C++ 2015, Visual Studio C++ 2013 などで動く書き方
メッセージ表示プログラム C言語での普通 の書き方 #include <stdio.h> int main(int argc, char** argv) { printf("Hello, world\n"); } C言語での普通 の書き方 (参考) Linux でプロ グラミングするときなど #include "stdafx.h" int _tmain() { printf("Hello, world\n"); } Visual Studio C++ 2015, Visual Studio C++ 2013 などで動く書き方
C言語での普通 の書き方 Linux でも Windows でも 動かしたいときの 書き方の例 #include <stdio.h> int main(int argc, char** argv) { printf("Hello, world\n"); } C言語での普通 の書き方 (参考) Linux でプロ グラミングするときなど #ifdef WIN32 #include "stdafx.h" #else #include <stdio.h> #endif int _tmain() int main(int argc, char** argv) { printf("Hello, world\n"); } Linux でも Windows でも 動かしたいときの 書き方の例 #include "stdafx.h" int _tmain() { printf("Hello, world\n"); } Visual Studio C++ 2015, Visual Studio C++ 2013 などで動く書き方
この資料では,この書き方 で統一します C言語での普通 の書き方 Linux でも Windows でも 動かしたいときの 書き方の例 #include <stdio.h> int main( int argc, char** argv ) { printf("Hello, world\n"); } C言語での普通 の書き方 (参考) Linux でプロ グラミングするときなど #ifdef WIN32 #include "stdafx.h" #else #include <stdio.h> #endif int _tmain() int main( int argc, char** argv) { printf("Hello, world\n"); } この資料では,この書き方 で統一します Linux でも Windows でも 動かしたいときの 書き方の例 #include "stdafx.h" int _tmain() { printf("Hello, world\n"); } Visual Studio C++ 2015, Visual Studio C++ 2013 などで動く書き方
メッセージ表示プログラム _tmain 関数の中で,他の 関数 printf を使っている 1つの関数 (関数名: _tmain) #include "stdafx.h" int _tmain() { printf("Hello, world\n"); } 1つの関数 (関数名: _tmain) _tmain 関数の中で,他の 関数 printf を使っている
メッセージ表示プログラム _tmain 関数 の本体 個々の文の終了を示す (セミコロン) #include "stdafx.h" 関数名 int _tmain() { printf("Hello, world\n"); } 関数名 _tmain 関数 の本体 個々の文の終了を示す (セミコロン)
プログラムの流れ メイン関数 printf 関数 プログラムの実行開始 関数呼び出し printf("Hello, world\n"); #include "stdafx.h" int _tmain() { printf("Hello, world\n"); } メイン関数 関数呼び出し printf("Hello, world\n"); printf 関数 戻り プログラムの実行終了
例題1.棒グラフ 整数から,その長さだけの棒を表示する関数 bar を作る 例) 6 → ****** 例) 6 → ****** 関数 bar を使って,「整数を読み込んで,読み込んだ長さの棒を表示するメイン関数を作る
棒グラフ メッセージ「len =」が表示されるので,キーボードで「6 Enter」とすると,長さ6の棒グラフが表示される 実行結果の例
プログラム実行順 普通,プログラム中の文は,上から下へ順に実行される 関数呼び出しでは,関数の先頭に「ジャンプ」する. 関数呼び出しの例) bar( len ); 呼び出された関数の中で return 文に出会うと,関数呼び出しの場所に戻る. このことは,C言語が「手続き型言語」と言われる理由の1つ
複数の関数を含む プログラム 棒グラフ bar関数 _tmain関数 プログラム実行は _tmain 関数(メイン 関数)から始まる #include "stdafx.h" #include <math.h> void bar( int len ) { int i; for (i=0; i<len; i++) { printf("*"); } printf("\n"); return; int _tmain() int len; char buf[256]; int ch; printf( "len =" ); fgets( buf, 256, stdin ); sscanf_s( buf, "%d\n", &len ); bar( len ); ch = getchar(); return 0; 複数の関数を含む プログラム bar関数 プログラム実行は _tmain 関数(メイン 関数)から始まる _tmain関数
プログラム実行順 戻り ④ ⑤ ⑥ ① ② ③ ⑦ ⑧ ⑨ #include "stdafx.h" #include <math.h> void bar( int len ) { int i; for (i=0; i<len; i++) { printf("*"); } printf("\n"); return; int _tmain() int len; int ch; printf( "len=" ); scanf_s( "%d", &len ); bar( len ); ch = getchar(); return 0; ④ ⑤ ⑥ 戻り メイン関数の先頭行 がプログラム実行の始まり ① ② ③ 関数呼び出し ⑦ ⑧ メイン関数内の return がプログラム実行の終わり ⑨
プログラムの流れ メイン関数 bar 関数 プログラムの実行開始 関数呼び出し bar( len ); return; プログラムの実行終了 #include "stdafx.h" #include <math.h> void bar( int len ) { int i; for (i=0; i<len; i++) { printf("*"); } printf("\n"); return; int _tmain() int len; int ch; printf( "len=" ); scanf_s( "%d", &len ); bar( len ); ch = getchar(); return 0; プログラムの実行開始 メイン関数 関数呼び出し bar( len ); bar 関数 * printf, scanf の 呼び出しについては 図では省略 return; プログラムの実行終了
変数 変数 変数名 データ(数値や文字)を入れるもの 英数字かアンダーバー(_)で作られる 最初の文字には数字は使えない 大文字と小文字を区別する 変数 i CR
ここで使用 ここで使用 #include "stdafx.h" #include <math.h> void bar( int len ) { int i; for (i=0; i<len; i++) { printf("*"); } printf("\n"); return; int _tmain() int len; char buf[256]; int ch; printf( "len =" ); fgets( buf, 256, stdin ); sscanf_s( buf, "%d\n", &len ); bar( len ); ch = getchar(); return 0; len をメモリエリア中に確保 変数 i をメモリエリア中に確保 ここで使用 変数 len, buf, ch をメモリエリア中に確保 ここで使用
変数は2種類使っている 整数を扱う int 型 文字を扱う char 型 整数は, 5, -3, 0 など #include "stdafx.h" #include <math.h> void bar( int len ) { int i; for (i=0; i<len; i++) { printf("*"); } printf("\n"); return; int _tmain() int len; char buf[256]; int ch; printf( "len =" ); fgets( buf, 256, stdin ); sscanf_s( buf, "%d\n", &len ); bar( len ); ch = getchar(); return 0; len をメモリエリア中に確保 変数 i をメモリエリア中に確保 変数は2種類使っている 整数を扱う int 型 整数は, 5, -3, 0 など 変数 len, buf, ch をメモリエリア中に確保 文字を扱う char 型 文字は, 1, 0, 3, -, a など 数字(1, 0, 3 など)も文字の一種
例題.平方根の計算 浮動小数データを読み込んで,平方根の計算と表示を行うプログラムを作る. 但し,負の数の場合には,メッセージを表示すること. 負の数であるかどうかによって条件分岐を行うために if 文を使う. 例) 9のとき: 3 -1のとき: メッセージを表示
条件分岐とは Yes 条件式 No B A 「ある条件式」が成り立てばAを、成り立たなければBを実行
平方根の計算 実行結果の例 x=9 sqrt(9.000000)=3.000000 x=-1 負なので計算できません
条件式 条件が成り立つ 場合に実行され る部分 条件が成り立た ない場合に実行 される部分 #include "stdafx.h" #include <math.h> int _tmain() { double x; double y; char buf[256]; int ch; printf("x="); fgets( buf, 256, stdin ); sscanf_s( buf, "%lf\n", &x ); if ( x < 0 ) { printf("負なので計算できません\n"); } else { y = sqrt(x); printf("sqrt(%f)=%f\n", x, y); ch = getchar(); return 0; 条件式 条件が成り立つ 場合に実行され る部分 条件が成り立た ない場合に実行 される部分
実行順 (x<0) の場合 #include "stdafx.h" #include <math.h> int _tmain() { double x; double y; char buf[256]; int ch; printf("x="); fgets( buf, 256, stdin ); sscanf_s( buf, "%lf\n", &x ); if ( x < 0 ) { printf("負なので計算できません\n"); } else { y = sqrt(x); printf("sqrt(%f)=%f\n", x, y); ch = getchar(); return 0; ① ② ③ ④ ⑤ ⑥ ⑦ ⑧ ⑨ ⑩ ⑪
実行順 (x≧0) の場合 #include "stdafx.h" #include <math.h> int _tmain() { double x; double y; char buf[256]; int ch; printf("x="); fgets( buf, 256, stdin ); sscanf_s( buf, "%lf\n", &x ); if ( x < 0 ) { printf("負なので計算できません\n"); } else { y = sqrt(x); printf("sqrt(%f)=%f\n", x, y); ch = getchar(); return 0; ① ② ③ ④ ⑤ ⑥ ⑦ ⑧ ⑨ ⑩ ⑪
変数は3種類使っている 整数を扱う int 型 文字を扱う char 型 整数は, 5, -3, 0 など 浮動小数を扱う double 型 #include "stdafx.h" #include <math.h> int _tmain() { double x; double y; char buf[256]; int ch; printf("x="); fgets( buf, 256, stdin ); sscanf_s( buf, "%lf\n", &x ); if ( x < 0 ) { printf("負なので計算できません\n"); } else { y = sqrt(x); printf("sqrt(%f)=%f\n", x, y); ch = getchar(); return 0; 変数は3種類使っている 変数 x, y, buf, ch をメモリエリア中 に確保 整数を扱う int 型 整数は, 5, -3, 0 など 文字を扱う char 型 文字は, 1, 0, 3, -, a など 数字(1, 0, 3 など)も文字の一種 浮動小数を扱う double 型 3.14, -1.414, 5, 0, -3 など (5, 0, -3 などの整数も浮動小数の一種)
繰り返しとは 条件 繰り返しとは,ある条件が満たされるまで,同じことを繰り返すこと. 繰り返しを行うための文としてwhile文, for 文 などがある.
繰り返し C言語での繰り返しは次の3通り ループ変数 (ループカウンタ) while文 do-while文 for文 ループ変数 (ループカウンタ) 繰り返しの回数を数える変数 インクリメント 値を1増やす (i++) デクリメント 値を1減らす (i--) CR
for 文による繰り返し 初期式 条件式 式 再設定式 Yes No 1.まず,「初期式」を実行 2.次に,「条件式」を実行.条件式が成立すれば, 式と「再設定式」を実行し,「条件式」に戻る
例題.繰り返し計算と ファイル出力 次のページのプログラムの機能 計算の繰り返し キーボードからのデータ読み込み ファイルへの書き出し
キーボードからの データ読み込みを 行っている部分 計算を行っている部分 y = sin ( x ) ファイルへの書き出し を行っている部分 #include "stdafx.h" #include <math.h> int _tmain() { double x; double y; char buf[256]; int i; double start_x; double step_x; FILE* fp; printf( "start_x =" ); fgets( buf, 256, stdin ); sscanf_s( buf, "%lf\n", &start_x ); printf( "step_x =" ); sscanf_s( buf, "%lf\n", &step_x ); fp = fopen( "z:\\data.csv", "w" ); for( i = 0; i < 20; i++ ) { x = start_x + ( i * step_x ); y = sin( x ); printf( "x= %f, y= %f\n", x, y ); fprintf( fp, "x=, %f, y=, %f\n", x, y ); } fprintf( stderr, "file z:\\data.csv created\n" ); fclose( fp ); return 0; キーボードからの データ読み込みを 行っている部分 計算を行っている部分 y = sin ( x ) ファイルへの書き出し を行っている部分
ここで 変数を使用 変数 x, y, buf, i, start_x, step_x, fp をメモリエリア中に確保 #include "stdafx.h" #include <math.h> int _tmain() { double x; double y; char buf[256]; int i; double start_x; double step_x; FILE* fp; printf( "start_x =" ); fgets( buf, 256, stdin ); sscanf_s( buf, "%lf\n", &start_x ); printf( "step_x =" ); sscanf_s( buf, "%lf\n", &step_x ); fp = fopen( "z:\\data.csv", "w" ); for( i = 0; i < 20; i++ ) { x = start_x + ( i * step_x ); y = sin( x ); printf( "x= %f, y= %f\n", x, y ); fprintf( fp, "x=, %f, y=, %f\n", x, y ); } fprintf( stderr, "file z:\\data.csv created\n" ); fclose( fp ); return 0; 変数 x, y, buf, i, start_x, step_x, fp をメモリエリア中に確保 ここで 変数を使用
変数は4種類使っている 整数を扱う int 型 文字を扱う char 型 整数は, 5, -3, 0 など 浮動小数を扱う double 型 #include "stdafx.h" #include <math.h> int _tmain() { double x; double y; char buf[256]; int i; double start_x; double step_x; FILE* fp; printf( "start_x =" ); fgets( buf, 256, stdin ); sscanf_s( buf, "%lf\n", &start_x ); printf( "step_x =" ); sscanf_s( buf, "%lf\n", &step_x ); fp = fopen( "z:\\data.csv", "w" ); for( i = 0; i < 20; i++ ) { x = start_x + ( i * step_x ); y = sin( x ); printf( "x= %f, y= %f\n", x, y ); fprintf( fp, "x=, %f, y=, %f\n", x, y ); } fprintf( stderr, "file z:\\data.csv created\n" ); fclose( fp ); return 0; 変数は4種類使っている 整数を扱う int 型 整数は, 5, -3, 0 など 文字を扱う char 型 文字は, 1, 0, 3, -, a など 数字(1, 0, 3 など)も文字の一種 浮動小数を扱う double 型 3.14, -1.414, 5, 0, -3 など 整数も浮動小数の一種 ファイルポインタ ファイル操作に使う変数
Cプログラムはメイン関数から 実行開始 プログラムは順次実行 この部分は繰り返し処理 (for 文による繰り返し) この部分を繰り返す #include <stdio.h> main() { double x; double y; char buf[256]; int i; double start_x; double step_x; FILE* fp; printf( "start_x =" ); fgets( buf, 256, stdin ); sscanf_s( buf, "%lf\n", &start_x ); printf( "step_x =" ); sscanf_s( buf, "%lf\n", &step_x ); fp = fopen( "z:\\data.csv", "w" ); for( i = 0; i < 20; i++ ) { x = start_x + ( i * step_x ); y = sin( x ); printf( "x= %f, y= %f\n", x, y ); fprintf( fp, "x=, %f, y=, %f\n", x, y ); } fprintf( stderr, "file z:\\data.csv created\n" ); fclose( fp ); return 0; Cプログラムはメイン関数から 実行開始 プログラムは順次実行 この部分は繰り返し処理 (for 文による繰り返し) この部分を繰り返す