Download : sample-001.c
/* * DATE sample-001.c */ #include <stdio.h> #include "s_turtle.h" /* 亀プログラムの場合に必要 */ /* * 亀プログラム */ /* * void move_ten(void) * * 現在向いている方向に 10 歩、足跡を残しながら進む */ void move_ten(void) { /* 「一歩進む」事を、10 回行う.. */ s_turtle_move(); s_turtle_move(); s_turtle_move(); s_turtle_move(); s_turtle_move(); s_turtle_move(); s_turtle_move(); s_turtle_move(); s_turtle_move(); s_turtle_move(); } /* * main */ int main ( void ) { /* * 最初は真中 (0,0) で上を向いている */ /* * 二十歩前に足跡を残しながら進む * 矩形の左辺を下から上に引く (0,0) -> (0,20) */ move_ten(); move_ten(); /* * 時計回りに 45 度を二回、すなわち 90 度向きを変える * 矩形の左上隅で右に向きを変える */ s_turtle_turn(); s_turtle_turn(); /* * 矩形の上辺を左から右に引く (0,20) -> (20,20) */ move_ten(); move_ten(); /* * 矩形の右上隅で下に向きを変える */ s_turtle_turn(); s_turtle_turn(); /* * 矩形の右辺を上から下に引く (20,20) -> (0,20) */ move_ten(); move_ten(); /* * 矩形の右下隅で左に向きを変える */ s_turtle_turn(); s_turtle_turn(); /* * 矩形の下辺を右から左に引く (0,20) -> (0,0) */ move_ten(); move_ten(); /* * 元の左下隅 (0,0) に戻った */ putchar ( '>' ); getchar(); s_turtle_stop(); return 0; }
$ ./sample-001.exe $
Download : sample-002.c
/* * DATE sample-002.c */ #include <stdio.h> #include "s_turtle.h" /* 亀プログラムの場合に必要 */ /* * 亀プログラム */ /* * void jump_ten(void) * * 現在向いている方向に 10 歩、足跡を残こさずに跳ねる */ void jump_ten(void) { /* 「一歩跳ねる」事を、10 回行う.. */ s_turtle_jump(); s_turtle_jump(); s_turtle_jump(); s_turtle_jump(); s_turtle_jump(); s_turtle_jump(); s_turtle_jump(); s_turtle_jump(); s_turtle_jump(); s_turtle_jump(); } /* * void move_ten(void) * * 現在向いている方向に 10 歩、足跡を残しながら進む */ void move_ten(void) { /* 「一歩進む」事を、10 回行う.. */ s_turtle_move(); s_turtle_move(); s_turtle_move(); s_turtle_move(); s_turtle_move(); s_turtle_move(); s_turtle_move(); s_turtle_move(); s_turtle_move(); s_turtle_move(); } /* * void turn_90(void) * * 現在向いている方向から時計回りに 90 度向きを * 進行方向の「右」に向きを変える */ void turn_90(void) { /* 「45 度向きを変える」事を、2 回行う.. */ s_turtle_turn(); s_turtle_turn(); } /* * void turn_270(void) * * 現在向いている方向から時計回りに 270 度向きを * 進行方向の「左」に向きを変える */ void turn_270(void) { /* 「90 度向きを変える」事を、3 回行う.. */ turn_90(); turn_90(); turn_90(); } /* * void move_and_turn(void) * * 現在向いている方向から 20 歩進んで右を向く * 四角形の一辺を書く */ void move_and_turn(void) { /* 20 歩進む */ move_ten(); move_ten(); /* 向きを変える */ turn_90(); } /* * void draw_sqare( void ); * * 一辺が 20 の長さの四角形を書く */ void draw_sqare( void ) { /* 「長さ 20 の辺を書いて右を向く」という事を 4 回繰り返す */ move_and_turn(); move_and_turn(); move_and_turn(); move_and_turn(); } /* * int main ( void ) */ int main ( void ) { /* * 最初は真中 (0,0) で上を向いている */ draw_sqare(); /* まず四角を書く */ turn_270(); /* 270 度回転 */ jump_ten(); /* 10 歩跳ねる */ draw_sqare(); /* また四角 */ turn_270(); jump_ten(); draw_sqare(); turn_270(); jump_ten(); draw_sqare(); putchar ( '>' ); getchar(); s_turtle_stop(); return 0; }
$ ./sample-002.exe $
Download : sample-003.c
/* * DATE sample-003.c */ #include <stdio.h> /* * 文字の出力 */ /* * int main ( void ) */ int main ( void ) { putchar ( 'a' ); /* 「a」という『文字』を出力する */ return 0; }
$ ./sample-003.exe a$
Download : sample-004.c
/* * DATE sample-004.c */ #include <stdio.h> /* * 文字の出力 */ /* * int main ( void ) */ int main ( void ) { putchar ( 'a' ); /* 「a」という『文字』を出力する */ putchar ( 'b' ); /* 同 「b」という『文字』を出力する */ putchar ( 'c' ); /* 「c」 */ putchar ( '\n' ); /* 「\n」は改行を表す */ return 0; }
$ ./sample-004.exe abc $
Download : sample-005.c
/* * DATE sample-005.c */ #include <stdio.h> /* * 文字の入力 */ /* * int main ( void ) */ int main ( void ) { printf ( "[Enter] キーを押してください : " ); getchar(); /* 文字を入力する (入力されるまで待つ) */ /* 目的は「入力」より「待つ」事が目的 */ return 0; }
$ ./sample-005.exe < sample-005.in [Enter] キーを押してください : $
Download : sample-006.c
/* * DATE sample-006.c */ #include <stdio.h> /* * 文字の echo Back */ /* * int main ( void ) */ int main ( void ) { printf ( " 2 文字入力して [Enter] キーを押してください : " ); putchar ( getchar() ); /* 一文字目を入力して出力 */ putchar ( getchar() ); /* ニ文字目を入力して出力 */ putchar ( getchar() ); /* 三文字目(改行)を入力して出力 */ /* [Enter] は、「改行」一文字になる */ return 0; }
3G
$ ./sample-006.exe < sample-006.in 2 文字入力して [Enter] キーを押してください : 3G 3G $
Download : sample-007.c
/* * DATE sample-007.c */ #include <stdio.h> /* * 文字の echo Back */ /* * int main ( void ) */ int main ( void ) { printf ( " 2 文字入力して [Enter] キーを押してください : " ); putchar ( getchar() + 1 ); /* 一文字目を入力して + 1 してから出力 */ putchar ( getchar() - 1 ); /* ニ文字目を入力して - 1 してから出力 */ putchar ( getchar() ); /* 三文字目(改行)を入力して出力 */ /* [Enter] は、「改行」一文字になる */ return 0; }
3G
$ ./sample-007.exe < sample-007.in 2 文字入力して [Enter] キーを押してください : 3G 4F $
Download : sample-008.c
/* * DATE sample-008.c */ #include <stdio.h> #include <string.h> /* * 文字列に 1 を加えると.. ? * 文字の長さが短くなる (頭の部分がなくなる..) */ /* * main */ int main ( void ) { printf ( "abcde\n" ); /* 当然 「abcde」が表示される.. */ printf ( "abcde\n" + 1 ); /* 文字列に 1 を加えるってどうゆうこと.. ? */ printf ( "abcde\n" + 2 ); printf ( "abcde\n" + 1 + 1 ); /* ("abcde\n" + 1) + 1 => "bcde\n" + 1 => "cde\n" */ return 0; }
$ ./sample-008.exe abcde bcde cde cde $
Download : sample-009.c
/* * DATE sample-009.c */ #include <stdio.h> #include <string.h> /* * void recursive ( char *string ) * char *string 指定した文字列からなる三角形を作る * 実行例 * recursive( "abc\n" ); * -> * abc "abc\n" * bc "bc\n" * c "c\n" * "\n" * 再帰呼出しを利用 */ void recursive ( char *string ) { if ( !strcmp ( string, "" ) ) { /* もし空文字列 ( "" ) ならば */ printf ( "" ); /* これで御仕舞い */ } else { /* そうでなければ、 */ printf ( string ); recursive ( string + 1 ); /* 再帰呼び出しする */ /* +1 を忘れると悲惨な事に.. */ } } /* * main */ int main ( void ) { recursive ( "abcdefg\n" ); recursive ( "xyz\n" ); return 0; }
$ ./sample-009.exe abcdefg bcdefg cdefg defg efg fg g xyz yz z $
Download : sample-010.c
/* * DATE sample-010.c */ #include <stdio.h> #include <string.h> /* * 再帰呼出しを利用して、"Hello, World\n" を沢山出力する */ /* * void rec_hello ( char *count ) * char *count 文字列を指定し、その長さで、繰り返えし回数の指数を指定 * 与えられた文字列の長さを n とすると 2^n 回だけ出力する */ void rec_hello ( char *count ) { if ( !strcmp ( count, "" ) ) { /* カラッポなら.. */ printf ( "Hello, World\n" ); /* 一つだけ表示してみる */ } else { /* そうでなければ.. */ rec_hello ( count + 1 ); /* 二倍にして再帰よびだし */ rec_hello ( count + 1 ); } } /* * main */ int main ( void ) { rec_hello ( "****" ); /* 2^4 = 16 回出力 */ /* 2^10 = 1024 だから、 "**********" を与えれば... */ return 0; }
$ ./sample-010.exe Hello, World Hello, World Hello, World Hello, World Hello, World Hello, World Hello, World Hello, World Hello, World Hello, World Hello, World Hello, World Hello, World Hello, World Hello, World Hello, World $
Download : sample-011.c
/* * DATE sample-011.c */ #include <stdio.h> #include <string.h> /* * フィボナッチ数の計算 */ /* * void fib ( char *n ) * char *n n の長さで何番目の項かを表す * n 番目のフィボナッチ数だけ '*' を表示する */ void fib ( char *n ) { if ( !strcmp ( n, "" ) ) { /* カラッポ(0)なら.. */ printf ( "*" ); /* 一つだけ : fib(0) = 1 だから */ } else if ( !strcmp ( n, "*" ) ) { /* 一つ(1)なら */ printf ( "*" ); /* 一つだけ : fib(1) = 1 だから */ } else { /* そうでなければ.. */ fib ( n + 1 ); /* fib ( n - 1 ) と */ fib ( n + 2 ); /* fib ( n - 2 ) だけだす */ } } /* * main */ int main ( void ) { printf ( "fib 3 : " ); fib ( "***" ); printf ( "\n" ); printf ( "fib 5 : " ); fib ( "*****" ); printf ( "\n" ); return 0; }
$ ./sample-011.exe fib 3 : *** fib 5 : ******** $
Download : sample-012.c
/* * DATE sample-012.c */ #include <stdio.h> #include <string.h> /* strcmp に必要 */ #include "s_turtle.h" /* 亀プログラムの場合に必要 */ /* * 亀プログラムと再帰呼出し */ /* * void jump_n( char *n ) * char *n 足跡の長さを表す * 指定された長さだけ現在向いている方向に足跡を残こさず跳ねる */ void jump_n( char *n ) { if ( !strcmp ( n, "" ) ) { /* n が空文字列 ("") なら何もしない */ } else { s_turtle_jump(); /* とりあえず、一歩跳ねる */ jump_n ( n + 1 ); /* 文字列を短くして、再帰呼出し */ } } /* * void move_n( char *n ) * * char *n 足跡の長さを表す * 指定された長さだけ現在向いている方向に足跡を残こして歩く */ void move_n(char *n) { if ( !strcmp ( n, "" ) ) { /* n が空文字列 ("") なら何もしない */ } else { s_turtle_move(); /* とりあえず、一歩歩く */ move_n ( n + 1 ); /* 文字列を短くして、再帰呼出し */ } } /* * void turn_n(char *n) * * 現在向いている方向から時計回りに n * 45 度向きを変える */ void turn_n(char *n) { if ( !strcmp ( n, "" ) ) { /* n が空文字列 ("") なら何もしない */ } else { s_turtle_turn(); /* とりあえず、45 度向きをかえる */ turn_n ( n + 1 ); /* 文字列を短くして、再帰呼出し */ } } /* * void turn_90(void) * * 現在向いている方向から時計回りに 90 度向きを * 進行方向の「右」に向きを変える */ void turn_90(void) { turn_n ( "**" ); } /* * void turn_270(void) * * 現在向いている方向から時計回りに 270 度向きを * 進行方向の「左」に向きを変える */ void turn_270(void) { turn_n ( "******" ); } /* * void move_n_and_turn(char *n) * * 現在向いている方向から n 歩進んで右を向く * 四角形の一辺を書く */ void move_n_and_turn( char *n ) { move_n ( n ); /* 向きを変える */ turn_90(); } /* * void draw_n_sqare( char *n ); * * 一辺が n の長さの四角形を書く */ void draw_n_sqare( char *n ) { /* 「長さ n の辺を書いて右を向く」という事を 4 回繰り返す */ move_n_and_turn(n); move_n_and_turn(n); move_n_and_turn(n); move_n_and_turn(n); } /* * int main ( void ) */ int main ( void ) { /* * 最初は真中 (0,0) で上を向いている */ draw_n_sqare( "********************" ); /* まず四角を書く */ turn_270(); /* 270 度回転 */ jump_n( "**********" ); /* 10 歩跳ねる */ draw_n_sqare( "********************" ); /* また四角 */ turn_270(); jump_n( "**********" ); draw_n_sqare( "********************" ); turn_270(); jump_n( "**********" ); draw_n_sqare( "********************" ); putchar ( '>' ); getchar(); s_turtle_stop(); return 0; }
$ ./sample-012.exe $
/* * 20190510-02-QQQQ.c * 底辺の長さが指定した文字列の二倍の長さ - 1 の横向のピラミッドを作成するプログラムを作成する */ #include <stdio.h> #include <strings.h> /* */ void down ( char *edge ) { if ( !strcmp ( edge, "" ) ) { /* なにもする必要はない */ } else { printf ( edge ); printf ( "\n" ); down ( edge + 1 ); } } void up ( char *edge ) { if ( !strcmp ( edge, "" ) ) { /* なにもする必要はない */ } else { up ( edge + 1 ); printf ( edge ); /* (2) の考察 */ printf ( "\n" ); } } void pyramid ( char *edge ) { up ( edge + 1 ); /* 上半分 */ printf ( edge ); /* 頂点 */ printf ( "\n" ); /* 下半分 (down) */ } /* * main */ int main ( void ) { pyramid ( "*****" ); printf ( "\n" ); pyramid ( "**********" ); return 0; } /* !!問題を解くときは、いきなり一般論では考えない !! => 具体的で、小さな場合をいくつか試す ( 数学 ) pyramid ( "*****" ); => # まず、最初と残りに分けてみる * -> printf ( "*\n"); ** *** **** ***** <= ここで、変化している **** *** ** * -> ?? => うまくゆかない (途中に変化の仕方に変化がある) => 山の前後は異なる => 分けて考える => # 改めて、山の頂点の所で分けて考える * ** *** **** => up ( だんだん増えてゆく) ***** **** => down ( だんだん減ってゆく) *** ** * => * ** *** **** ***** **** *** ** * [補題] down( "*****" ); => ***** **** *** ** * => ***** -> printf ( "*****" ); printf ( "\n" ); **** -> down ( "****" ); *** ** * => printf ( "*****" ); printf ( "\n" ); down ( "****" ); => 引数は "***** " にそろえた printf ( "*****" ); printf ( "\n" ); down ( "*****" + 1 ); => 引数が "" の時 ( 長さが 0 の時は、特別扱い => 再帰の終了 ) if ( !strcmp ( "*****", "" ) ) { } else { printf ( "*****" ); printf ( "\n" ); down ( "*****" + 1 ); } => down に関しては完成 ... (1) [補題] up( "*****" + 1 ); <= 引数の合わせている up( "****" ); => * ** *** **** => # 最初を特別扱い * ** *** **** # だめ => # 改めて、最後と残りに分ける * ** *** -> up ( "***" ); **** -> printf ( "****" ); printf ( "\n" ); => up ( "***" ); printf ( "****" ); printf ( "\n" ); => up ( "****" + 1 ); printf ( "****" ); printf ( "\n" ); => if ( !strcmp ( "****", "" ) ) { } else { up ( "****" + 1 ); printf ( "****" ); printf ( "\n" ); } ... (2) */
#include <stdio.h> /* 関数 sub では if 構文をつかってない => 引数が変化に対して、実行結果の変化が対応している */ void sub( char *a ) { printf ( a ); printf ( a ); printf ( a ); } int main(void) { sub ( "abc\n" ); printf ( "----\n" ); sub ( "xyz\n" ); printf ( "----\n" ); sub ( "123\n" ); return 0; }
#include <stdio.h> /* 関数 sub で if 構文を使う => 引数が変化に対して、実行結果の変化を急激変える事がきる */ void sub( char *a ) { if ( !strcmp ( a, "xyz\n" ) ) { /* 引数に "xyz\n" を指定した時だけ特別扱い */ printf ( "xxxyyyzzz\n" ); /* 普段と異なる振る舞いをする */ } else { printf ( a ); printf ( a ); printf ( a ); } } int main(void) { sub ( "abc\n" ); printf ( "----\n" ); sub ( "xyz\n" ); printf ( "----\n" ); sub ( "123\n" ); return 0; }
#include <stdio.h> /* 関数 sub で if 構文を使う => 引数が変化に対して、実行結果の変化を急激変える事がきる */ void taberu( char *food ) { if ( !strcmp ( food, "にんじん" ) ) { /* 引数に "にんじん" を指定した時だけ特別扱い */ printf ( "嫌い\n" ); /* 普段と異なる振る舞いをする */ } else { printf ( food ); printf ( "って、大好き\n" ); printf ( "おいしい\n" ); printf ( "おいしい\n" ); printf ( "おいしい\n" ); } } int main(void) { taberu ( "ごはん" ); printf ( "----\n" ); taberu ( "りんご" ); printf ( "----\n" ); taberu ( "にんじん" ); printf ( "----\n" ); taberu ( "ばなな" ); printf ( "----\n" ); return 0; }
#include <stdio.h> /* 一つ目の文字列を二つ目の文字列の長さだけ、出力する関数 req ( "abc\n", "***" ) abc abc abc req ( "abc\n", "******" ) abc abc abc abc abc abc */ void req ( char *string, char *length ) { if ( !strcmp ( length, "***" ) ) { printf ( string ); printf ( string ); printf ( string ); } else { if ( !strcmp ( length, "*" ) ) { printf ( string ); } else { printf ( string ); printf ( string ); printf ( string ); printf ( string ); printf ( string ); printf ( string ); } } } /* 順接と if 構文の(単純な..)組み合わせだけでは、 二つ目の文字列の長さが、無限に考えられるで、そのすべてに対応する事はできない => 根本的に異なる考え方が必要 */ int main(void) { req ( "abc\n", "***" ); printf ( "---\n" ); req ( "abc\n", "******" ); printf ( "---\n" ); req ( "abc\n", "*" ); printf ( "---\n" ); req ( "abc\n", "**" ); return 0; }
#include <stdio.h> /* 一つ目の文字列を二つ目の文字列の長さだけ、出力する関数 req ( "abc\n", "***" ) abc abc abc req ( "abc\n", "******" ) abc abc abc abc abc abc [再帰を配慮した考え方 => 実行される命令数が可変の時は常に必要] req ( "abc\n", "******" ) => # 長いものは、最初のものと、残りに分ける abc -> printf ( "abc\n" ); abc abc abc abc abc -> req ( "abc\n", "*****" ) => # 可変長さの命令が、二つ命令の順接でできてしまう printf ( "abc\n" ); req ( "abc\n", "*****" ) # そのかわりに、自分自身を呼び出している(再起呼び出し) => printf ( "abc\n" ); # "abc\n" は引数の値そのもの req ( "abc\n", "******" + 1 ) # "*****" は引数に比べ、一文字短くなっている # ここで、文字列は、+1 すると短くなる性質を利用 # そのかわりに、自分自身を呼び出している(再起呼び出し) => # どこかで、再起呼び出しをやめる必要がある # それ以上は不要な場合を考える # この例では, # 二つ目の引数の長さが、だんだんと短くなって、長さ 0 の時は、 # もう、出力する必要がない => この場合は、終わりする。 # if ( 二つめの引数の長さが 0 の時 ) { # なにもしない # } else { # 再帰呼び出しをする # } if ( !strcmp ( lenght, "" ) ) { 長さが 0 } else { printf ( "abc\n" ); req ( "abc\n", "******" + 1 ); } => abc abc abc abc abc abc */ void req ( char *string, char *length ) { /* ^^^ これから定義する関数が req の時.. */ if ( !strcmp ( length, "" ) ) { /* length が空文字列なので長さ 0 */ /* なにもしなくてよい (何もしないだけでなく、再起呼び出しを停止する) */ } else { printf ( string ); /* printf ( "abc\n" ); */ req ( string, length + 1 ); /* printf ( "******" + 1 ); */ /* ^^^ その関数の定義の中で自分自身を呼び出している(再帰呼び出し) */ } /* n! = n * ( (n-1)! ) # このままだとだめ # cf. 3! = 3 * 2! = 3 * 2 * 1! = 3 * 2 * 1 * 0! .... 終わらない # 数学の場合は、きちんと、「終わり」が指定されている # 具体的には、「n が 1」時だけ、自分自身を呼び出さない => 1 ( n が 1 の時は特別扱い ) n! = { n * ( (n-1)! ) ( そのほか ) */ } int main(void) { req ( "abc\n", "***" ); printf ( "---\n" ); req ( "abc\n", "******" ); printf ( "---\n" ); req ( "abc\n", "*" ); printf ( "---\n" ); req ( "abc\n", "**" ); return 0; }
#include <stdio.h> /* 自然数 ( 0, 1, 2, ... ) を "*" からなる文字列の長さで表現する事にする 0 * 1 ** 2 .. */ void plus ( char *tasareru, char *tasu ) { printf ( tasareru ); printf ( tasu ); printf ( "\n" ); } void minus ( char *hikareru, char *hiku ) { /* 答えが 0 以上の場合だけ */ if ( !strcmp ( hiku, "" ) ) { printf ( hikareru ); printf ( "\n" ); } else { minus ( hikareru + 1, hiku + 1 ); } } void multiply ( char *kakerareru, char *kakeru ) { if ( !strcmp ( kakeru, "" ) ) { /*なにもしない*/ printf ( "\n" ); } else { printf ( kakerareru ); multiply ( kakerareru, kakeru + 1 ); } } void fact_sub ( char *length, char *n ) { if ( !strcmp ( length, "" ) ) { /* do nothing */ } else { fact ( n ); fact_sub ( length - 1, n ); } } void fact ( char *n ) { /* n! */ if ( !strcmp ( n, "*" ) ) { printf ( "*" ); } else { fact_sub ( n, n + 1 ); /* n * (n-1)! */ } } int main(void) { printf ( "2+3=5 => ( ** + *** = ***** )\n" ); plus ( "**", "***" ); printf ( "2*3=6 => ( ** x *** = ****** )\n" ); multiply ( "**", "***" ); printf ( "5-3=2 => ( ***** - *** = ** )\n" ); minus ( "*****", "***" ); printf ( "3! = 6 => ( ***! = ****** )\n" ); fact ( "***" ); return 0; }
[OpenGL のセットアップ] 本日(2019/05/17)のページの download の所から、20190517.zip をダウロード ダウロード先は c:\usr\c 展開する 展開先を c:\ur\c にする XLaunch を起動 (先週インストールしたもの) 設定は、[次へ」で OK Ubuntu を起動 OpenGL のライブラリのインストール sudo apt-get install freeglut3 freeglut3-dev => ここでちょっと時間がかかるので、あらかじめやっておくr OpenGL のテスト cd c/20190517/ogltest make make test => 新しいウィンドウができて、中で四角が回転すれば OK [前回まで] 「if 構文」を学んだ What : 条件成立、不成立によって、異なる二つの命令のどちらか一方を実行する指示 if ( 条件 ) { 条件が成立したときの命令 } else { 条件が不成立の時の命令 } Why : 状況(条件確認する)によって、適切な命令を選択して実行できるようにする cf. if 構文導入前 : 基本、行う命令は同じ(変数の値は、引数によって変更が可能なので、 同じ命令でも、異なる振る舞いはできるが、振る舞いの違いは、変数に指定する 値の違いなので、「値に対して連続的な振る舞い」しかできなかった.. => if 構文の導入によって、 引数の値によって、まったく異なる二つの命令のどちらかが実行可能になる # 「値に対して、不連続な振る舞い」が記述できるようになった。 !! if 構文の導入によって、「できる事が増えた(順接だけではできな事ができる)」 !! 順接と、if 構文を導入しても、プログラムの記述量より、多くの命令は実行できない !! 順接(命令を並べると、その命令を並べた順に実行) => 並べた命令数と実行する命令数同じ (関数を使うと、行数よ、実行命令を増やす事ができるが、それでも有限の個数の命令しか実行できない) !! if 構文は、記述した二つの命令のうちどちらか一方を実行だから、記述量より、実行量のが少なくなる !! => 順接と if 構文(を単純に利用した場合)だけだと、実行される命令の個数は、(原理的に)有限になる !! => 最初に、最大値があって、それより多くの状況に対処できない !! # 結果として、特定な状況に対する適切な、有限の処理ができれば良いが.. !! cf. 長さが有限な文字列全体の集合は、無限 再帰呼び出し what : 関数を定義するときにその定義の内容の中で自分自身を呼び出す事 cf. 数学のいくつかの関数は再帰的に定義さている 自然数 n の階乗 n! は、次のように再帰的(帰納的)に定義されている 1 (n が 1 の時) n! = { n * ((n-1)!) (その他) 3! = 3 * ( (3-1)! ) = 3 * 2! = 3 * 2 * ((2-1)!) = 3 * 2 * 1! = 3 * 2 * 1 = 6 !! 有限の記述で、無限の場合に対応する表現が可能 why : 無限の状態に対して(有限の記述で)対応できるプログラムを記述できるように するため <= 同じ命令を、何度でも実行 ( 繰り返し ) how 関数定義の中で、自分を呼ぶ 1. 必ず、if 構文を使って、再帰をしない場合を作る 2. if 構文の条件で利用する変数を「減らして」行く # 最小値になった、終わり == プログラム 命令を並べたもの => 望んでいる仕事を、コンピュータにやらせる事ができる できることはなにか ? できない事 : 任意のプログラムが停止するかどうかを判定するプログラムは作れない 「できる事全体」は、いろいろ人が考えた結果.. どうも同じなっている => 「できる事ができる能力」の事を「万能性」と呼ぶ プログラムを命令の組み合わせで作るときには、 順接と、条件分岐(単純な if 構文)、繰り返し(再帰関数の定義) の三つの機能さえ提供すれば、「万能」になる事が証明されている。 => 命令の組み合わせの種類はこの三種類である トラブルシューティング 1. make とすると、「make がない」と言われる sudo apt install make 2. 「failed to open display '' 」と言われた場合 (先週[2019/05/10]の資料に書いてあるが..) export DISPALY=:0.0 とする
課題プログラム内の「/*名前:ここ*/」の部分を書き換え「/*この部分を完成させなさい*/」の部分にプログラムを追加して、プログラムを完成させます。
Download : 20190517-01.c
/* * 20180525-01-QQQQ.c * * 漢字の「回」という文字(にみえる..) 絵を Turtle Graphics で書きなさい */ #include <stdio.h> #include "s_turtle.h" /* * sub */ void jump_ten(void) { /* 10 歩跳ねる */ s_turtle_jump(); s_turtle_jump(); s_turtle_jump(); s_turtle_jump(); s_turtle_jump(); s_turtle_jump(); s_turtle_jump(); s_turtle_jump(); s_turtle_jump(); s_turtle_jump(); } void move_ten(void) { /* 10 歩進む */ s_turtle_move(); s_turtle_move(); s_turtle_move(); s_turtle_move(); s_turtle_move(); s_turtle_move(); s_turtle_move(); s_turtle_move(); s_turtle_move(); s_turtle_move(); } void turn_90() { /* 90 度向きをかえる */ s_turtle_turn(); s_turtle_turn(); } void small_square() { move_ten(); turn_90(); /* ** この部分を完成させなさい */ } void big_square() { move_ten(); move_ten(); move_ten(); turn_90(); /* ** この部分を完成させなさい */ } int main ( void ) { small_square(); /* ** この部分を完成させなさい */ big_square(); putchar ( '>' ); getchar(); s_turtle_stop(); return 0; }
$ ./20190517-01-QQQQ.exe $