Download : sample-001.c ( SJIS 版 )
/* * DATE sample-001.c */ /* * [解説] * ファイル tgc.c から N Times の部分を切り出して s_rtg.h を作成 * 残った main 関数のみを sample-001.c に残す。 * #include を利用して、N Times の部分を取り込む事により * rtg.c と同じ動作のプログラムにする。 */ #include <stdio.h> /* 実は不要だが、「お呪い」なので.. */ #include "s_rtg.h" /* N Tims turtle graphics の時に必要 */ /* turtle.h は不要 */ /* この中に turlte.h と N Times が入っている */ /* * main 関数 (rtg.c と同じ事をする) */ int main ( void ) { /* 一度目 */ s_n_times_turtle_move ( "1234567890" ); /* 10 回 move */ s_n_times_turtle_turn ( "12" ); /* 2 回 turn */ /* ニ度目 */ s_n_times_turtle_move ( "1234567890" ); /* 10 回 move */ s_n_times_turtle_turn ( "12" ); /* 2 回 turn */ /* 三度目 */ s_n_times_turtle_move ( "1234567890" ); /* 10 回 move */ s_n_times_turtle_turn ( "12" ); /* 2 回 turn */ /* 四度目 */ s_n_times_turtle_move ( "1234567890" ); /* 10 回 move */ s_n_times_turtle_turn ( "12" ); /* 2 回 turn */ /* 最後の turn は、「四角を書く」という立場からは不要 */ return 0; }
$ ./sample-001.exe $
Download : sample-002.c ( SJIS 版 )
/* * DATE sample-002.c */ /* * [解説] * main 中の繰返しパターンの二行を関数 draw_10_edge_2_turn * として取り出す。 * rtg.c の main 関数の最後の行が無駄に思えたが、実は意味があり、 * プログラムをパターン化し、関数の利用を促進する意味があった事が、 * ここで、明らかになる。 */ #include <stdio.h> #include "s_rtg.h" /* N Tims turtle graphics の時に必要 */ /* * draw_10_edge_2_turn * 長さ 10 の辺を書き、向きを二度変更する * (プログラムの共通部分を見つけ関数化) */ void draw_10_edge_2_turn ( void ) { s_n_times_turtle_move ( "1234567890" ); /* 10 回 move */ s_n_times_turtle_turn ( "12" ); /* 2 回 turn */ } /* * main 関数 (rtg.c と同じ事をする) */ int main ( void ) { /* 一度目 */ draw_10_edge_2_turn(); /* ニ度目 */ draw_10_edge_2_turn(); /* 三度目 */ draw_10_edge_2_turn(); /* 四度目 */ draw_10_edge_2_turn(); /* 最後の turn がなかったら、ここだけ「特別扱い」にする必要がある */ /* プログラムの構造を簡単にする(パターン化)するために、敢えて無駄をする */ return 0; }
$ ./sample-002.exe $
Download : sample-003.c ( SJIS 版 )
/* * DATE sample-003.c */ /* * [解説] * 長さ 10 の矩形を書く関数 draw_rect_10 の作成と、その利用例 */ #include <stdio.h> #include "s_rtg.h" /* N Tims turtle graphics の時に必要 */ /* * draw_10_edge_2_turn * 長さ 10 の辺を書き、向きを二度変更する * (プログラムの共通部分をみつけ関数化) */ void draw_10_edge_2_turn ( void ) { s_n_times_turtle_move ( "1234567890" ); /* 10 回 move */ s_n_times_turtle_turn ( "12" ); /* 2 回 turn */ } /* * draw_rect_10 * 長さ 10 の矩形を作成 */ void draw_rect_10 ( void ) { /* draw_10_edge_2_turn を 4 度呼び出す */ draw_10_edge_2_turn(); draw_10_edge_2_turn(); draw_10_edge_2_turn(); draw_10_edge_2_turn(); } /* * main 関数 */ int main ( void ) { /* 四角形を 3 つ書く */ draw_rect_10(); s_n_times_turtle_jump ( "123456789012345" ); /* 15 回 jump */ draw_rect_10(); s_n_times_turtle_jump ( "123456789012345" ); /* 15 回 jump */ draw_rect_10(); s_n_times_turtle_jump ( "123456789012345" ); /* 15 回 jump */ /* 最後の jump は不要だが... */ return 0; }
$ ./sample-003.exe $
Download : sample-004.c ( SJIS 版 )
/* * DATE sample-004.c */ /* * [解説] * 関数 draw_rect_10 の別の利用例 */ #include <stdio.h> #include "s_rtg.h" /* N Tims turtle graphics の時に必要 */ /* * draw_10_edge_2_turn * 長さ 10 の辺を書き、向きを二度変更する * (プログラムの共通部分をみつけ関数化) */ void draw_10_edge_2_turn ( void ) { s_n_times_turtle_move ( "1234567890" ); /* 10 回 move */ s_n_times_turtle_turn ( "12" ); /* 2 回 turn */ } /* * draw_rect_10 * 長さ 10 の矩形を作成 */ void draw_rect_10 ( void ) { /* draw_10_edge_2_turn を 4 度呼び出す */ draw_10_edge_2_turn(); draw_10_edge_2_turn(); draw_10_edge_2_turn(); draw_10_edge_2_turn(); } /* * main 関数 */ int main ( void ) { /* 四角形を、向きを変更しながら 4 つ書く */ draw_rect_10(); s_n_times_turtle_turn ( "123456" ); /* 6 回 turn */ s_n_times_turtle_jump ( "12" ); /* 2 回 jump */ draw_rect_10(); s_n_times_turtle_turn ( "123456" ); /* 6 回 turn */ s_n_times_turtle_jump ( "12" ); /* 2 回 jump */ draw_rect_10(); s_n_times_turtle_turn ( "123456" ); /* 6 回 turn */ s_n_times_turtle_jump ( "12" ); /* 2 回 jump */ draw_rect_10(); s_n_times_turtle_turn ( "123456" ); /* 6 回 turn */ s_n_times_turtle_jump ( "12" ); /* 2 回 jump */ return 0; }
$ ./sample-004.exe $
Download : sample-005.c ( SJIS 版 )
/* * DATE sample-005.c */ /* * [解説] * 引数を利用して、矩形の辺の長さを可変する */ #include <stdio.h> #include "s_rtg.h" /* N Tims turtle graphics の時に必要 */ /* * draw_n_edge_2_turn * 長さ n の辺を書き、向きを二度変更する * (プログラムの共通部分を見つけ関数化) */ void draw_n_edge_2_turn ( char *n ) { s_n_times_turtle_move ( n ); /* n 回 move */ s_n_times_turtle_turn ( "12" ); /* 2 回 turn */ } /* * draw_rect_n * 長さ n の矩形を作成 */ void draw_rect_n ( char *n ) { /* draw_n_edge_2_turn を 4 度呼び出す */ draw_n_edge_2_turn( n ); draw_n_edge_2_turn( n ); draw_n_edge_2_turn( n ); draw_n_edge_2_turn( n ); } /* * main 関数 */ int main ( void ) { /* 大きさの違う四角形を 3 つ書く */ draw_rect_n( "123456789012" ); /* 一辺が 12 の矩形 */ s_n_times_turtle_jump ( "123456789012345" ); /* 15 回 jump */ draw_rect_n( "123456789" ); /* 一辺が 9 の矩形 */ s_n_times_turtle_jump ( "123456789012" ); /* 12 回 jump */ draw_rect_n( "123456" ); /* 一辺が 6 の矩形 */ s_n_times_turtle_jump ( "123456789" ); /* 9 回 jump */ /* 最後の jump は不要だが... */ return 0; }
$ ./sample-005.exe $
Download : sample-006.c ( SJIS 版 )
/* * DATE sample-006.c */ /* * [解説] * 連続的に小くなる四角の列を作る */ #include <stdio.h> #include <string.h> /* strcmp を利用する場合に必要 */ #include "s_rtg.h" /* N Tims turtle graphics の時に必要 */ /* * draw_n_edge_2_turn * 長さ n の辺を書き、向きを二度変更する * (プログラムの共通部分を見つけ関数化) */ void draw_n_edge_2_turn ( char *n ) { s_n_times_turtle_move ( n ); /* n 回 move */ s_n_times_turtle_turn ( "12" ); /* 2 回 turn */ } /* * draw_rect_n * 長さ n の矩形を作成 */ void draw_rect_n ( char *n ) { /* draw_n_edge_2_turn を 4 度呼び出す */ draw_n_edge_2_turn( n ); draw_n_edge_2_turn( n ); draw_n_edge_2_turn( n ); draw_n_edge_2_turn( n ); } /* * draw_down_3_size * 長さ 3 * n から 3 ずつ小くした矩形列を作る * <<<注意>>> 元の n の長さは、必ず 3 の倍数にする必要がある */ void draw_down_3_size ( char *n ) { if ( !strcmp ( n, "" ) ) { /* n が空文字列の時 */ /* 何もしなくてよい */ } else { draw_rect_n ( n ); /* 1 辺が n の矩形を描画 */ s_n_times_turtle_jump ( n ); /* 1 辺分を jump */ s_n_times_turtle_jump ( "123" ); /* 更に隙間を空けために 3 jump */ draw_down_3_size ( n + 3 ); /* 3 だけ、辺の長さを短かく */ } } /* * main 関数 */ int main ( void ) { /* 大きさの違う四角形系列を描画 */ draw_down_3_size ( "123456789012345678" ); /* 18 から開始 */ draw_down_3_size ( "123456" ); /* 6 から開始 */ return 0; }
$ ./sample-006.exe $
/* * 20150501-03-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 ); /* ** この部分を完成させなさい */ } } void pyramid ( char *edge ) { up ( edge + 1 ); printf ( edge ); printf ( "\n" ); /* ** この部分を完成させなさい */ } /* * main */ int main ( void ) { pyramid ( "*****" ); printf ( "\n" ); pyramid ( "**********" ); return 0; }
/* * 20150501-03-QQQQ.c * 底辺の長さが指定した文字列の二倍の長さ - 1 の横向のピラミッドを作成するプログラムを作成する */ #include <stdio.h> #include <strings.h> /* */ void down ( char *edge ) { /* p-006.c と同じ考え方 */ if ( !strcmp ( edge, "" ) ) { /* なにもする必要はない */ } else { printf ( edge ); printf ( "\n" ); down ( edge + 1 ); } } void up ( char *edge ) { /* p-006.c とはちょっと違う */ if ( !strcmp ( edge, "" ) ) { /* なにもする必要はない */ } else { up ( edge + 1 ); /* ** この部分を完成させなさい */ } } void pyramid ( char *edge ) { /* pyramid ( "***" ); の時 */ up ( edge + 1 ); /* 上の部分 */ /* * ** */ printf ( edge ); /* *** *. printf ( "\n" ); /* ** * */ /* ** この部分を完成させなさい */ down ( egde + 1 ); } /* * main */ int main ( void ) { pyramid ( "*****" ); printf ( "\n" ); pyramid ( "**********" ); return 0; }
#include <stdio.h> int main(void) { printf ( "Hello, World\n" ); return 0; }
#include <stdio.h> int main(void) { printf ( "Hello, World\n" + 1 ); /* 文字列に 1 を加えると何がおきるか ? */ return 0; }
#include <stdio.h> int main(void) { printf ( "Hello, World\n" ); printf ( "Hello, World\n" + 1 ); printf ( "Hello, World\n" + 2 ); /* +2 -> +1 +1 */ printf ( "Hello, World\n" + 3 ); printf ( "Hello, World\n" + 4 ); return 0; }
#include <stdio.h> int main(void) { printf ( "Hello, World\n" ); /* 13 文字 */ printf ( "Hello, World\n" + 1 ); printf ( "Hello, World\n" + 2 ); /* +2 -> +1 +1 */ printf ( "Hello, World\n" + 3 ); printf ( "Hello, World\n" + 4 ); printf ( "Hello, World\n" + 5 ); printf ( "Hello, World\n" + 6 ); printf ( "Hello, World\n" + 7 ); printf ( "Hello, World\n" + 8 ); printf ( "Hello, World\n" + 9 ); printf ( "Hello, World\n" + 10 ); printf ( "Hello, World\n" + 11 ); printf ( "Hello, World\n" + 12 ); /* "\n" の改行のみ */ printf ( "Hello, World\n" + 13 ); /* "" 空文字列なので何もしない*/ return 0; }
#include <stdio.h> void print_hello_7(char *X) { printf ( X + 0 ); /* 13 文字 */ printf ( X + 1 ); printf ( X + 2 ); /* +2 -> +1 +1 */ printf ( X + 3 ); printf ( X + 4 ); printf ( X + 5 ); printf ( X + 6 ); } int main(void) { printf ( "test 1\n" ); print_hello_7("0123456789\n"); printf ( "test 2\n" ); print_hello_7("Hello, World\n"); /* printf ( "Hello, World\n" + 0 ); printf ( "Hello, World\n" + 1 ); printf ( "Hello, World\n" + 2 ); printf ( "Hello, World\n" + 3 ); printf ( "Hello, World\n" + 4 ); printf ( "Hello, World\n" + 5 ); printf ( "Hello, World\n" + 6 ); */ print_hello_7("Hello, World\n"+7); /* printf ( ("Hello, World\n" + 7) + 0 ); printf ( ("Hello, World\n" + 7) + 1 ); printf ( ("Hello, World\n" + 7) + 2 ); printf ( ("Hello, World\n" + 7) + 3 ); printf ( ("Hello, World\n" + 7) + 4 ); printf ( ("Hello, World\n" + 7) + 5 ); printf ( ("Hello, World\n" + 7) + 6 ); */ return 0; }
#include <stdio.h> /* */ void print_down(char *X) { if ( !strcmp ( X, "" ) ) { /* X が "" (空文字列) だった */ /* 何もしない */ } else { /* そうでなかったら.. */ printf ( X ); /* とりあえず、その文字列を出す */ print_down ( X + 1 ); /* 問 : 残りはどうやって出せばよいか */ } /* 答 : 再帰呼出を利用する */ } int main(void) { printf ( "test 1\n" ); print_down ("0123456789\n"); printf ( "test 2\n" ); print_down ("Hello, World\n"); return 0; }
2015/05/08 文字列に 1 を加えると、先頭の文字が一文字かけて、 一文字短かい文字列ににかわる 例 : "abc" + 1 -> "bc" "abc" + 3 -> "" 文字列の長さだけ足すと空文字列("")になる <<疑問>> 文字の長さより大きな数を加えたら.. ? -> なにがおきるかわからない -> プログラムをかく人が気を付ける 「¥(エンマーク)」と「\(バックスラッシュ)」 windows では「¥」が ubuntu では「\」になる <目的> print_down( "abc\n" ); -> abc -> printf ( "abc\n" ); bc -> printf ( "bc\n" ); c -> printf ( "c\n" ); ((空行))-> printf ( "\n" ); となるようにしたい 結果は abc bc c ((空行)) なので、これを、最初の一つと残りに分ける つまり、 abc (step-1) と bc (step-2) c ((空行)) に分けて考える (分割統治法) (step-1) printf ( "abc\n" ); (step-2) print_down( "bc\n" ); -> print_down( "abc\n" + 1 ); <結論> void print_down ( char *X ) { if ( !strcmp ( X, "" ) ) { /* do nothing */ } else { printf ( X ); print_down( X + 1 ); /* 再帰呼出 */ } } <課題 20150501-03> pyramid ( "***" ); -> * ** *** ** * <考え方> * <step-1> ** *** <step-2> ** * <理由> 0: step-2 はできている (p-006) step-2 -> print_down ( "*** ); 1: <step-1> と <step-2> は ルールが違う <up> up ( "***" ); -> * ** *** -> * ** と *** に分割 -> ??? -> up ( "**" ); printf ( "***" ); printf ( "\n" ); <結論> void up ( char *X ) { if ( !strcmp ( X, "" ) ) { /* do nothing */ } else { up ( X + 1 ); printf ( X ); printf ( "\n" ); } }
課題プログラム内の「/*名前:ここ*/」の部分を書き換え「/*この部分を完成させなさい*/」の部分にプログラムを追加して、プログラムを完成させます。
Download : 20150508-01.c ( SJIS 版 )
/* * 20150508-01-QQQQ.c * * 入れ子になった四角を書く関数 */ #include <stdio.h> #include <string.h> /* strcmp を利用する場合に必要 */ #include "s_rtg.h" /* N Tims turtle graphics の時に必要 */ /* * draw_n_edge_2_turn * 長さ n の辺を書き、向きを二度変更する * (プログラムの共通部分を見つけ関数化) */ void draw_n_edge_2_turn ( char *n ) { s_n_times_turtle_move ( n ); /* n 回 move */ s_n_times_turtle_turn ( "12" ); /* 2 回 turn */ } /* * draw_rect_n * 長さ n の矩形を作成 */ void draw_rect_n ( char *n ) { /* draw_n_edge_2_turn を 4 度呼び出す */ draw_n_edge_2_turn( n ); /* ヒント: 後、三回呼び出す必要がある */ /* ** この部分を完成させなさい */ } /* * draw_down_4_size * 長さ 4 * n から 4 ずつ小くした矩形列を作る * <<<注意>>> 元の n の長さは、必ず 4 の倍数にする必要がある */ void draw_down_4_size ( char *n ) { if ( !strcmp ( n, "" ) ) { /* n が空文字列の時 */ /* 何もしなくてよい */ } else { draw_rect_n ( n ); /* 1 辺が n の矩形を描画 */ s_n_times_turtle_turn ( "1" ); /* 向きを 1 つだけ変更 */ s_n_times_turtle_jump ( "12" ); /* 2 つだけ jump */ s_n_times_turtle_turn ( "1234567" ); /* 向きを 7 つだけ変更 */ /* ヒント: 再帰呼出し ( n は幾つ変更する必要があるか ? ) */ /* ** この部分を完成させなさい */ } } /* * main 関数 */ int main ( void ) { /* 大きさの違う四角形系列を描画 */ draw_down_4_size ( "12345678901234567890" ); /* 20 から開始 */ s_n_times_turtle_jump ( "12345678901234" ); /* 14 jump */ draw_down_4_size ( "12345678" ); /* 6 から開始 */ return 0; }
$ ./20150508-01-QQQQ.exe $