Download : sample-001.c
/* * 2019/05/10 sample-001.c */ /* * 最初のプログラムは "Hello, World" */ #include <stdio.h> /* * main 関数 */ int main ( void ) { printf ( "Hello, World\n" ); /* "Hello, World" という文字列と改行 ( "\n" ) を表示する */ return 0; }
$ ./sample-001.exe Hello, World $
Download : sample-003.c
/* * 2019/05/10 sample-003.c */ #include <stdio.h> /* * 「金糸雀(かなりや)」 * (c) 西條八十作詞・成田為三作曲 * http://www.mahoroba.ne.jp/~gonbe007/hog/shouka/kanariya.html */ /* * 関数を使わずに愚直に命令を並べた * プログラミングの基本はこれ (実行したい内容をその順に並べる) */ /* * int main ( void ) */ int main ( void ) { printf ( "唄を忘れた 金糸雀(かなりや)は\n" ); printf ( "後の山に 棄てましょか\n" ); printf ( "いえ いえ それはなりませぬ\n" ); printf ( "\n" ); printf ( "唄を忘れた 金糸雀(かなりや)は\n" ); printf ( "背戸の小薮に 埋けましょか\n" ); printf ( "いえ いえ それはなりませぬ\n" ); printf ( "\n" ); printf ( "唄を忘れた 金糸雀(かなりや)は\n" ); printf ( "柳の鞭で ぶちましょか\n" ); printf ( "いえ いえ それはかわいそう\n" ); printf ( "\n" ); printf ( "唄を忘れた 金糸雀(かなりや)は\n" ); printf ( "象牙の船に 銀の櫂\n" ); printf ( "月夜の海に 浮べれば\n" ); printf ( "忘れた唄を おもいだす\n" ); return 0; }
$ ./sample-003.exe 唄を忘れた 金糸雀(かなりや)は 後の山に 棄てましょか いえ いえ それはなりませぬ 唄を忘れた 金糸雀(かなりや)は 背戸の小薮に 埋けましょか いえ いえ それはなりませぬ 唄を忘れた 金糸雀(かなりや)は 柳の鞭で ぶちましょか いえ いえ それはかわいそう 唄を忘れた 金糸雀(かなりや)は 象牙の船に 銀の櫂 月夜の海に 浮べれば 忘れた唄を おもいだす $
Download : sample-004.c
/* * 2019/05/10 sample-004.c */ #include <stdio.h> /* * 「金糸雀(かなりや)」 * (c) 西條八十作詞・成田為三作曲 * http://www.mahoroba.ne.jp/~gonbe007/hog/shouka/kanariya.html */ /* * 共通する部分に名前を付け重複を減らす * 引数を利用しなくてもできる形 */ /* * void uta(void) * 「唄を忘れた 金糸雀(かなりや)は」を出力する */ void uta(void) { printf ( "唄を忘れた 金糸雀(かなりや)は\n" ); } /* * void ieie(void) * 「いえ いえ それはなりませぬ」を出力する */ void ieie(void) { printf ( "いえ いえ それはなりませぬ\n" ); } /* * void kyoku_1(void) * 「歌詞 1 」を出力する */ void kyoku_1(void) { uta(); printf ( "後の山に 棄てましょか\n" ); ieie(); } /* * void kyoku_2(void) * 「歌詞 2 」を出力する */ void kyoku_2(void) { uta(); printf ( "背戸の小薮に 埋けましょか\n" ); ieie(); } /* * void kyoku_3(void) * 「歌詞 3 」を出力する */ void kyoku_3(void) { uta(); printf ( "柳の鞭で ぶちましょか\n" ); ieie(); } /* * void kyoku_4(void) * 「歌詞 4 」を出力する */ void kyoku_4(void) { uta(); printf ( "象牙の船に 銀の櫂\n" ); printf ( "月夜の海に 浮べれば\n" ); printf ( "忘れた唄を おもいだす\n" ); } /* * int main ( void ) * 四つの歌詞を、間に空行を入れて出力する */ int main ( void ) { kyoku_1(); /* 一曲目 */ printf ( "\n" ); /* 空行 */ kyoku_2(); /* ニ曲目 */ printf ( "\n" ); /* 空行 */ kyoku_3(); /* 三曲目 */ printf ( "\n" ); /* 空行 */ kyoku_4(); /* 四曲目 */ return 0; }
$ ./sample-004.exe 唄を忘れた 金糸雀(かなりや)は 後の山に 棄てましょか いえ いえ それはなりませぬ 唄を忘れた 金糸雀(かなりや)は 背戸の小薮に 埋けましょか いえ いえ それはなりませぬ 唄を忘れた 金糸雀(かなりや)は 柳の鞭で ぶちましょか いえ いえ それはなりませぬ 唄を忘れた 金糸雀(かなりや)は 象牙の船に 銀の櫂 月夜の海に 浮べれば 忘れた唄を おもいだす $
Download : sample-005.c
/* * 2019/05/10 sample-005.c */ #include <stdio.h> /* * 「金糸雀(かなりや)」 * (c) 西條八十作詞・成田為三作曲 * http://www.mahoroba.ne.jp/~gonbe007/hog/shouka/kanariya.html */ /* * 1 〜 3 を引数付き関数でおきかえる */ /* * void uta(void) * 「唄を忘れた 金糸雀(かなりや)は」を出力する */ void uta(void) { printf ( "唄を忘れた 金糸雀(かなりや)は\n" ); } /* * void ieie(void) * 「いえ いえ それはなりませぬ」を出力する */ void ieie(void) { printf ( "いえ いえ それはなりませぬ\n" ); } /* * void kyoku_123 ( char *center ) * char *center ; 曲 1 〜 3 で異る部分 * 曲 1 〜 3 で異る部分を引数にする事により、歌詞全体を出力する */ void kyoku_123 ( char *center ) { uta(); printf ( center ); /* kyoku 1 〜 3 で異る部分を変数 (center) にした */ ieie(); } /* * void kyoku_1(void) * 「歌詞 1 」を出力する * kyoku_123 を利用して、歌詞 1 固有の部分だけを指定する */ void kyoku_1(void) { kyoku_123 ( "後の山に 棄てましょか\n" ); } /* * void kyoku_2(void) * kyoku_123 を利用して、歌詞 2 を出力 */ void kyoku_2(void) { kyoku_123 ( "背戸の小薮に 埋けましょか\n" ); } /* * void kyoku_3(void) * kyoku_123 を利用して、歌詞 3 を出力 */ void kyoku_3(void) { kyoku_123 ( "柳の鞭で ぶちましょか\n" ); } /* * void kyoku_4(void) * 「歌詞 4 」を出力する * 形が 1 〜 3 と異るので、kyoku_123 は使えない */ void kyoku_4(void) { uta(); printf ( "象牙の船に 銀の櫂\n" ); printf ( "月夜の海に 浮べれば\n" ); printf ( "忘れた唄を おもいだす\n" ); } /* * int main ( void ) * 四つの歌詞を、間に空行を入れて出力する */ int main ( void ) { kyoku_1(); /* 一曲目 */ printf ( "\n" ); /* 空行 */ kyoku_2(); /* ニ曲目 */ printf ( "\n" ); /* 空行 */ kyoku_3(); /* 三曲目 */ printf ( "\n" ); /* 空行 */ kyoku_4(); /* 四曲目 */ return 0; }
$ ./sample-005.exe 唄を忘れた 金糸雀(かなりや)は 後の山に 棄てましょか いえ いえ それはなりませぬ 唄を忘れた 金糸雀(かなりや)は 背戸の小薮に 埋けましょか いえ いえ それはなりませぬ 唄を忘れた 金糸雀(かなりや)は 柳の鞭で ぶちましょか いえ いえ それはなりませぬ 唄を忘れた 金糸雀(かなりや)は 象牙の船に 銀の櫂 月夜の海に 浮べれば 忘れた唄を おもいだす $
Download : sample-006.c
/* * 2019/05/10 sample-006.c */ #include <stdio.h> #include <string.h> /* strcmp を利用する場合は必要 */ /* * 「金糸雀(かなりや)」 * (c) 西條八十作詞・成田為三作曲 * http://www.mahoroba.ne.jp/~gonbe007/hog/shouka/kanariya.html */ /* * 4 の場合もまとめられないだろうか ? */ /* * void uta(void) * 「唄を忘れた 金糸雀(かなりや)は」を出力する */ void uta(void) { printf ( "唄を忘れた 金糸雀(かなりや)は\n" ); } /* * void ieie(void) * 「いえ いえ それはなりませぬ」を出力する */ void ieie(void) { printf ( "いえ いえ それはなりませぬ\n" ); } /* * void kyoku_1234 ( char *center ) * char *center ; 曲 1 〜 4 で最初に異る部分 * 曲 1 〜 3 は異る部分を、定型で、出力する事により * 曲 4 は、if と strcmp を利用して、区別し、特別扱いする事により * それぞれ、歌詞全体を出力する */ void kyoku_1234 ( char *center ) { /* 1 〜 4 共通部分 */ uta(); printf ( center ); /* 1 〜 3 と 4 では異る部分 */ /* strcmp で、比較し、その結果を if で区別する */ if ( !strcmp ( center, "象牙の船に 銀の櫂\n" ) ) { /* 4 の場合だった */ printf ( "月夜の海に 浮べれば\n" ); printf ( "忘れた唄を おもいだす\n" ); } else { /* それ以外.. */ /* 1 〜 3 の場合だった */ ieie(); } } /* * void kyoku_1(void) * kyoku_1234 を利用して、歌詞 1 を出力 */ void kyoku_1(void) { kyoku_1234 ( "後の山に 棄てましょか\n" ); } /* * void kyoku_2(void) * kyoku_1234 を利用して、歌詞 2 を出力 */ void kyoku_2(void) { kyoku_1234 ( "背戸の小薮に 埋けましょか\n" ); } /* * void kyoku_3(void) * kyoku_1234 を利用して、歌詞 3 を出力 */ void kyoku_3(void) { kyoku_1234 ( "柳の鞭で ぶちましょか\n" ); } /* * void kyoku_4(void) * kyoku_1234 を利用して、歌詞 4 を出力 */ void kyoku_4(void) { kyoku_1234 ( "象牙の船に 銀の櫂\n" ); } /* * int main ( void ) * 四つの歌詞を、間に空行を入れて出力する */ int main ( void ) { kyoku_1(); /* 一曲目 */ printf ( "\n" ); /* 空行 */ kyoku_2(); /* ニ曲目 */ printf ( "\n" ); /* 空行 */ kyoku_3(); /* 三曲目 */ printf ( "\n" ); /* 空行 */ kyoku_4(); /* 四曲目 */ return 0; }
$ ./sample-006.exe 唄を忘れた 金糸雀(かなりや)は 後の山に 棄てましょか いえ いえ それはなりませぬ 唄を忘れた 金糸雀(かなりや)は 背戸の小薮に 埋けましょか いえ いえ それはなりませぬ 唄を忘れた 金糸雀(かなりや)は 柳の鞭で ぶちましょか いえ いえ それはなりませぬ 唄を忘れた 金糸雀(かなりや)は 象牙の船に 銀の櫂 月夜の海に 浮べれば 忘れた唄を おもいだす $
Download : sample-007.c
/* * 2019/05/10 sample-007.c */ #include <stdio.h> #include <string.h> /* * 木霊 */ /* * 引数を利用して振舞を変える関数の例 */ /* * void echo ( char *message ) * char *message 与えらえたメッセージ、これをそのまま言い返す(木霊) * message が空の場合は、「言い返せない」と文句を言う */ void echo ( char *message ) { /* message の内容によって振舞を変える */ /* 「""」は「空文字列」を表す */ if ( !strcmp ( message, "" ) ) { /* もし、メッセージが空っぽならば.. */ printf ( "何か言わないと、言い返せないじゃないか.." ); } else { /* そうじゃなければ、そのまま答える */ printf ( message ); } } /* * void chat ( char *message ) * char *message 木霊に呼び掛けるメッセージ * こちらからの呼び掛けと、木霊の返答を表示する */ void chat ( char *message ) { printf ( "呼掛け : " ); printf ( message ); printf ( "\n" ); /* 呼掛けの言葉 */ printf ( "木霊 : " ); echo ( message ); printf ( "\n" ); /* 木霊の応答 */ } /* * main */ int main ( void ) { chat ( "ヤッホー" ); chat ( "オーイ" ); chat ( "" ); chat ( "生意気なやつだ" ); return 0; }
$ ./sample-007.exe 呼掛け : ヤッホー 木霊 : ヤッホー 呼掛け : オーイ 木霊 : オーイ 呼掛け : 木霊 : 何か言わないと、言い返せないじゃないか.. 呼掛け : 生意気なやつだ 木霊 : 生意気なやつだ $
Download : sample-008.c
/* * 2019/05/10 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
/* * 2019/05/10 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
/* * 2019/05/10 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
/* * 2019/05/10 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 : ******** $
/* * 20190510-01-QQQQ.c * 引数付き関数で、if 文で条件判断をするプログラムを作成しなさい */ #include <stdio.h> #include <strings.h> /* * こだまでしょうか * (c) 金子みすゞ * http://www.ad-c.or.jp/campaign/self_area/03/index.html */ void kakko ( char *message ) { /* kakko( "遊ぼ" ) => 「遊ぼ」 */ printf ( "「" ); printf ( message ); printf ( "」" ); } void iu ( char *message ) { /* 「遊ぼ」っていうと「遊ぼ」ていう */ kakko ( message ); /* 「遊ぼ」 */ printf ( "っていうと" ); /* っていうと */ /* 方針 b. で、とりあえず、1,2, 5 の部分を考える */ if ( !strcmp( message, "もう遊ばない" ) ) { /* 条件:message が「もう遊ばない」の時 */ /* (1) message が「もう遊ばない」の時は */ kakko ( "遊ばない" ); } else { /* (2) そうでないときには (これまでと同じ) */ kakko ( message ); /* 「遊ぼ」 */ } printf ( "っていう。\n" ); /* っていう。 */ } /* * main */ int main ( void ) { iu ( "遊ぼう" ); iu ( "馬鹿" ); iu ( "もう遊ばない" ); printf ( "そうして、あとでさみしくなって、\n" ); iu ( "ごめんね" ); printf ( "こだまでしょうか、いいえ、誰でも。\n" ); return 0; } /* [方針] 最終的な結果として、 -- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< -- 「遊ぼう」っていうと「遊ぼう」っていう。 「馬鹿」っていうと「馬鹿」っていう。 「もう遊ばない」っていうと「遊ばない」っていう。 そうして、あとでさみしくなって、 「ごめんね」っていうと「ごめんね」っていう。 こだまでしょうか、いいえ、誰でも。 -- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< -- を出力したい。 もちろん、何の工夫もなく、以下のように命令を並べても、求める結果が得られる -- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< -- printf ( "「遊ぼう」っていうと「遊ぼう」っていう。\n" ); printf ( "「馬鹿」っていうと「馬鹿」っていう。\n" ); printf ( "「もう遊ばない」っていうと「遊ばない」っていう。\n" ); printf ( "そうして、あとでさみしくなって、\n" ); printf ( "「ごめんね」っていうと「ごめんね」っていう。\n" ); printf ( "こだまでしょうか、いいえ、誰でも。\n" ); -- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< -- しかし、勉強のために、関数を利用する a. 1, 2, 5 は連続な感じで、3 だけ、不連続な感じ b. 1, 2, 5 を引数付きの関数で実現 c. 3 をあとから、if 構文(条件分岐)で対処 */
#include <stdio.h> #include <string.h> /* メッセージを出力すると、「やまびこ」のように、同じメッセージを出力 */ void echo( char *message ) { printf ( "あなた : " ); printf ( message ); /* 渡されたメッセージを出力 */ printf ( "Echo : " ); if ( !strcmp( message, "バカ\n" ) ) { printf ( "お前のほうこそ" ); printf ( message ); /* やまびこが返すメッセージ */ } else { printf ( message ); /* やまびこが返すメッセージ */ } } int main(void) { echo ( "こんにちは\n" ); echo ( "さようなら\n" ); echo ( "バカ\n" ); return 0; }
#include <stdio.h> int main(void) { printf ( "Hello, World\n" ); /* 「Hello, World」*/ printf ( "Hello, World\n" + 1 ); /* 文字列("?"の部分) に 1 を加える */ /* 先頭の 1 文字が削れて、長さが減る */ printf ( "Hello, World\n" + 2 ); /* +2 => +1 +1 => 2 文字減る */ return 0; }
#include <stdio.h> void abc_pramid(void) { printf ( "abc\n" + 0 ); /* 「abc」+「改行」*/ printf ( "abc\n" + 1 ); /* 「bc」+「改行」*/ printf ( "abc\n" + 2 ); /* 「c」+「改行」*/ printf ( "abc\n" + 3 ); /* 「」+「改行」*/ printf ( "abc\n" + 4 ); /* 「」=> printf ( "" ) */ /* 「""」 を「空文字列」と呼び、「長さ 0 」の文字列 */ } int main(void) { abc_pramid(); return 0; }
#include <stdio.h> /* 長さが 4 の文字列でのピラミッドの出力 */ void x_pramid(char *X) { if ( !strcmp ( X, "" ) ) { /* なにもしない */ } else { printf ( X ); x_pramid ( X + 1 ); } /* このままだと x_primaid ( "123\n" ); => printf ( "123\n" ); x_primaid ( "23\n" ); => printf ( "123\n" ); printf ( "23\n" ); x_primaid ( "3\n" ); => printf ( "123\n" ); printf ( "23\n" ); printf ( "3\n" ); printf ( "\n" ); printf ( "" ); x_primaid ( "" ); => いなくなってほしい */ } int main(void) { x_pramid("abc\n"); printf ( "====\n" ); x_pramid("xyz\n"); printf ( "====\n" ); x_pramid("123456789\n"); return 0; } /* 考察 固定の長さの文字列のピラミッドは可能 => その長さの分だけ、命令を書けばよい しかし.. いろいろな長さの文字列のピラミッドはどうすればよいか ? => 命令列の(列の)長さが変化していまう => 「順接」: 実行したい命令の個数と、プログラムに書く命令の個数が同じ => 「条件分岐」:長さが違う命令を実行できるが、二通しか分岐できない このままだと難しい [目的] priamid( "1234\n" ); => 1234\n 234\n 34\n 4\n \n => 1234\n 234\n 34\n 4\n \n => 1234\n => printf ( "1234\n" ); 234\n => pramid( "234\n" ); 34\n 4\n \n => 1234\n => printf ( "1234\n" ); 234\n => pramid( "1234\n" + 1 ); 34\n 4\n \n cf.再帰的な定義 1 (nが1のとき) n! = { n * (n-1)! 5! = 5 * 4 * 3 * 2 * 1 = 5 * (4*3*2*1) = 5 * 4! = 5 * (5-1)! */
/* * 2019/05/10 sample-003.c */ #include <stdio.h> /* * 「金糸雀(かなりや)」 * (c) 西條八十作詞・成田為三作曲 * http://www.mahoroba.ne.jp/~gonbe007/hog/shouka/kanariya.html */ /* * 関数を使わずに愚直に命令を並べた * プログラミングの基本はこれ (実行したい内容をその順に並べる) */ /* * int main ( void ) */ int main ( void ) { printf ( "唄を忘れた 金糸雀(かなりや)は\n" ); printf ( "後の山に 棄てましょか\n" ); printf ( "いえ いえ それはなりませぬ\n" ); printf ( "\n" ); printf ( "唄を忘れた 金糸雀(かなりや)は\n" ); printf ( "背戸の小薮に 埋けましょか\n" ); printf ( "いえ いえ それはなりませぬ\n" ); printf ( "\n" ); printf ( "唄を忘れた 金糸雀(かなりや)は\n" ); printf ( "柳の鞭で ぶちましょか\n" ); printf ( "いえ いえ それはかわいそう\n" ); printf ( "\n" ); printf ( "唄を忘れた 金糸雀(かなりや)は\n" ); printf ( "象牙の船に 銀の櫂\n" ); printf ( "月夜の海に 浮べれば\n" ); printf ( "忘れた唄を おもいだす\n" ); return 0; }
/* * 2019/05/10 sample-004.c */ #include <stdio.h> /* * 「金糸雀(かなりや)」 * (c) 西條八十作詞・成田為三作曲 * http://www.mahoroba.ne.jp/~gonbe007/hog/shouka/kanariya.html */ /* * 共通する部分に名前を付け重複を減らす * 引数を利用しなくてもできる形 */ /* * void uta(void) * 「唄を忘れた 金糸雀(かなりや)は」を出力する */ /* (1) 命令「printf ( "唄を忘れた 金糸雀(かなりや)は\n" );」に 「uta」という名前を付けた (2) utaという関数を定義した。 その内容は、「printf ( "唄を忘れた 金糸雀(かなりや)は\n" );」である */ void uta(void) { printf ( "唄を忘れた 金糸雀(かなりや)は\n" ); } /* * void ieie(void) * 「いえ いえ それはなりませぬ」を出力する */ void ieie(void) { printf ( "いえ いえ それはなりませぬ\n" ); } /* * void kyoku_1(void) * 「歌詞 1 」を出力する */ void kyoku_1(void) { uta(); /* (1)「uta」という関数名を指定だけで、命令が実行される */ /* (2) 関数「uta」を呼び出す */ printf ( "後の山に 棄てましょか\n" ); ieie(); } /* * void kyoku_2(void) * 「歌詞 2 」を出力する */ void kyoku_2(void) { uta(); printf ( "背戸の小薮に 埋けましょか\n" ); ieie(); } /* * void kyoku_3(void) * 「歌詞 3 」を出力する */ void kyoku_3(void) { uta(); printf ( "柳の鞭で ぶちましょか\n" ); ieie(); } /* * void kyoku_4(void) * 「歌詞 4 」を出力する */ void kyoku_4(void) { uta(); printf ( "象牙の船に 銀の櫂\n" ); printf ( "月夜の海に 浮べれば\n" ); printf ( "忘れた唄を おもいだす\n" ); } /* * int main ( void ) * 四つの歌詞を、間に空行を入れて出力する */ int main ( void ) { kyoku_1(); /* 一曲目 */ printf ( "\n" ); /* 空行 */ kyoku_2(); /* ニ曲目 */ printf ( "\n" ); /* 空行 */ kyoku_3(); /* 三曲目 */ printf ( "\n" ); /* 空行 */ kyoku_4(); /* 四曲目 */ return 0; }
/* * 2019/05/10 sample-005.c */ #include <stdio.h> /* * 「金糸雀(かなりや)」 * (c) 西條八十作詞・成田為三作曲 * http://www.mahoroba.ne.jp/~gonbe007/hog/shouka/kanariya.html */ /* * 1 〜 3 を引数付き関数でおきかえる */ /* * void uta(void) * 「唄を忘れた 金糸雀(かなりや)は」を出力する */ void uta(void) { printf ( "唄を忘れた 金糸雀(かなりや)は\n" ); } /* * void ieie(void) * 「いえ いえ それはなりませぬ」を出力する */ void ieie(void) { printf ( "いえ いえ それはなりませぬ\n" ); } /* * void kyoku_123 ( char *center ) * char *center ; 曲 1 〜 3 で異る部分 * 曲 1 〜 3 で異る部分を引数にする事により、歌詞全体を出力する */ void kyoku_123 ( char *center ) { uta(); printf ( center ); /* kyoku 1 〜 3 で異る部分を変数 (center) にした */ ieie(); } /* * void kyoku_1(void) * 「歌詞 1 」を出力する * kyoku_123 を利用して、歌詞 1 固有の部分だけを指定する */ void kyoku_1(void) { kyoku_123 ( "後の山に 棄てましょか\n" ); } /* * void kyoku_2(void) * kyoku_123 を利用して、歌詞 2 を出力 */ void kyoku_2(void) { kyoku_123 ( "背戸の小薮に 埋けましょか\n" ); } /* * void kyoku_3(void) * kyoku_123 を利用して、歌詞 3 を出力 */ void kyoku_3(void) { kyoku_123 ( "柳の鞭で ぶちましょか\n" ); } /* * void kyoku_4(void) * 「歌詞 4 」を出力する * 形が 1 〜 3 と異るので、kyoku_123 は使えない */ void kyoku_4(void) { uta(); printf ( "象牙の船に 銀の櫂\n" ); printf ( "月夜の海に 浮べれば\n" ); printf ( "忘れた唄を おもいだす\n" ); } /* * int main ( void ) * 四つの歌詞を、間に空行を入れて出力する */ int main ( void ) { kyoku_1(); /* 一曲目 */ printf ( "\n" ); /* 空行 */ kyoku_2(); /* ニ曲目 */ printf ( "\n" ); /* 空行 */ kyoku_3(); /* 三曲目 */ printf ( "\n" ); /* 空行 */ kyoku_4(); /* 四曲目 */ return 0; }
/* * 2019/05/10 sample-006.c */ #include <stdio.h> #include <string.h> /* strcmp を利用する場合は必要 */ /* * 「金糸雀(かなりや)」 * (c) 西條八十作詞・成田為三作曲 * http://www.mahoroba.ne.jp/~gonbe007/hog/shouka/kanariya.html */ /* * 4 の場合もまとめられないだろうか ? */ /* * void uta(void) * 「唄を忘れた 金糸雀(かなりや)は」を出力する */ void uta(void) { printf ( "唄を忘れた 金糸雀(かなりや)は\n" ); } /* * void ieie(void) * 「いえ いえ それはなりませぬ」を出力する */ void ieie(void) { printf ( "いえ いえ それはなりませぬ\n" ); } /* * void kyoku_1234 ( char *center ) * char *center ; 曲 1 〜 4 で最初に異る部分 * 曲 1 〜 3 は異る部分を、定型で、出力する事により * 曲 4 は、if と strcmp を利用して、区別し、特別扱いする事により * それぞれ、歌詞全体を出力する */ void kyoku_1234 ( char *center ) { /* 1 〜 4 共通部分 */ uta(); printf ( center ); /* 1 〜 3 と 4 では異る部分 */ /* strcmp で、比較し、その結果を if で区別する */ if ( !strcmp ( center, "象牙の船に 銀の櫂\n" ) ) { /* 条件「!strcmp(A,B)」は、「AとBが等しい時成立になる」という表記 */ /* 一致したので、4 の場合だった */ printf ( "月夜の海に 浮べれば\n" ); printf ( "忘れた唄を おもいだす\n" ); } else { /* それ以外.. */ /* 一致しなかったので、1 〜 3 の場合だった */ ieie(); } } /* * void kyoku_1(void) * kyoku_1234 を利用して、歌詞 1 を出力 */ void kyoku_1(void) { kyoku_1234 ( "後の山に 棄てましょか\n" ); } /* * void kyoku_2(void) * kyoku_1234 を利用して、歌詞 2 を出力 */ void kyoku_2(void) { kyoku_1234 ( "背戸の小薮に 埋けましょか\n" ); } /* * void kyoku_3(void) * kyoku_1234 を利用して、歌詞 3 を出力 */ void kyoku_3(void) { kyoku_1234 ( "柳の鞭で ぶちましょか\n" ); } /* * void kyoku_4(void) * kyoku_1234 を利用して、歌詞 4 を出力 */ void kyoku_4(void) { kyoku_1234 ( "象牙の船に 銀の櫂\n" ); } /* * int main ( void ) * 四つの歌詞を、間に空行を入れて出力する */ int main ( void ) { kyoku_1(); /* 一曲目 */ printf ( "\n" ); /* 空行 */ kyoku_2(); /* ニ曲目 */ printf ( "\n" ); /* 空行 */ kyoku_3(); /* 三曲目 */ printf ( "\n" ); /* 空行 */ kyoku_4(); /* 四曲目 */ return 0; }
[お知らせ] vnc を利用して、栗野の作業(Note-PC の)画面が見れる IP : 10.8.154.222 PW : vnc-2018 VcXsrv のインストール インストール作業を、講義を聴きながらやっておく 後で、使い方を説明する ディスクトップに「XLaunch」というアイコンができているので起動 => いろいろきいてくるが、基本[次へ]でよい => 右下に「小さい Xアイコン」ができる => ubuntu から GUI (Window や画像) を利用するプログラムが使えるようになる ubuntu で GUI を利用するアプリをインストールする => ubuntu で「sudo apt install x11-apps」で、GUI 関係のソフトをインストール パスワードは「soft」 => インストールは一回だけやればよい GUI を利用する場合 export DISPLAY=:0.0 => ubuntu を起動するたびに行う必要があるが、次の命令実行すると、 次回からは不要 echo export DISPLAY=:0.0 >> ~/.profile [前回の復習] 前回まで プログラムとは何か ? => 作業手順を記述したもの 例: Hello World プログラム 「画面に『Hello, World』というメッセージを出力しないさい」という命令を記述したプログラム # printf ( "Hello, World\n" ); という命令によって、画面にメッセージが出力される プログラミング言語とは何か => プログラムを記述するための記述言語 => プログラムは、人間とコンピュータのコミュニケーション手段の一つ プログラムを(人間にとって)書きやすいように工夫されている いろいろ => 計算機向き(効率が良い):機械語.アセンブラ / 人間向き(わかりやすい).. 計算機は、最終的に機械語しか理解できない <= 他の言語で記述されたプログラムは、機械語に翻訳されないといけない => この翻訳作業を「コンパイル」 コンパイルの方法 ubuntu で、cc コマンドを利用して、コンパイルする C 言語 プログラミング言語のひとつ/ソフトウェア概論では、C 言語でプログラム作成 ソフトウェア概論の目標は、「C 言語で(いろいろな)プログラムが作れるようになる」 C 言語でいろいろなプログラムを作る (自分の目的にそった結果を得るために..それに対応した..)表現方法を学ぶ 0. hello.c (いろいろなおまじないがあるが => 後述) 1. printf を使うと、メッセージが出力できる 2. 命令を並べると、その並び順に命令が実行される(順接) sample-003.c 3. 命令の並びに、名前を付ける事ができて、名前を指定するだけで、それらの命令列が実行できる => 関数の定義と、関数利用(関数呼び出し) sample-004.c 関数 kyoku_1 と 関数 kyoku_2 では、いずれも、三つの命令を実行していて、 1 つめと 3 つめは同じだが、2 つ目だけが異なる -- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< -- void kyoku_1(void) { uta(); printf ( "後の山に 棄てましょか\n" ); ieie(); } -- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< -- -- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< -- void kyoku_2(void) { uta(); printf ( "背戸の小薮に 埋けましょか\n" ); ieie(); } -- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< -- => この二つの関数を比較すると、2 つ目の命令のメッセージ部分が異なる => 異なる部分を「変数」にしてしまう (例えば「X」にしてしまう) -- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< -- void kyoku_1(void) { uta(); printf ( X ); ieie(); } -- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< -- -- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< -- void kyoku_2(void) { uta(); printf ( X ); ieie(); } -- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< -- => 結果的に同じ表現(命令列)になる -- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< -- void kyoku_123(void) { uta(); printf ( X ); /* 変数 X が利用されている.. */ ieie(); } -- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< -- => 共通にした表現(命令列)になる関数を新しく作る(名前を kyoku_123 とする) -- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< -- void kyoku_123(char *X) { /* 変数 X が利用されていることを引数の所に記述 */ uta(); printf ( X ); /* 変数 X が利用されている.. */ ieie(); } -- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< -- => 引数 (関数の後ろの 「()」の中)に、利用する変数(今回の場合は「X」)を書き、 さらに、その前に(おまじないとして..)「char *」をつける => 結果的に、(「X」という一つの)引数付きの関数を作る事ができる 4. 関数には、引数を指定する事ができて、同じ関数だが、引数を変更する事により、 異なる結果を得る事が可能 # 異なる結果をえる、似た関数を、引数をつかって一つにまとめる 引数付き関数の呼び出しの場合は、「関数名(変数にいれたいもの);」という形で呼び出す。 sample-005.c 関数 kyoku_1 の所で、kyoku_123 をよびだしている。 この時に kyoku_123 の後ろには、kyoku_1 と同じ振る舞いをするように、 変数 center に入るものを指定する。 -- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< -- void kyoku_123 ( char *center ) { /* kyoku_1, kyoku_2, kyoku_3 をまとめた */ uta(); printf ( center ); /* kyoku 1 〜 3 で異る部分を変数 (center) にした */ ieie(); } -- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< -- -- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< -- void kyoku_1(void) { uta(); printf ( "後の山に 棄てましょか\n" ); ieie(); } -- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< -- <= kyoku_1 がなってほしい内容(kyoku_1 の本来の定義) => kyoku_1 と kyoku_123 を比較すると、 「center」と「"後の山に 棄てましょか\n"」が異なる # これは「当然」で # kyoku_1 と kyoku_2 の違い # [kyoku_1] # +---------------------------------------+ # |uta(); | # |printf ( "後の山に 棄てましょか\n" ); | # |ieie(); | # +---------------------------------------+ # [kyoku_2] # +-------------------------------------------+ # |uta(); | # |printf ( "背戸の小薮に 埋けましょか\n" ); | # |ieie(); | # +-------------------------------------------+ # [kyoku_123] # +-------------------------------------------+ # |uta(); | # |printf ( center ); | # |ieie(); | # +-------------------------------------------+ # => # kyoku_1 と kyoku_2 の違う所を変数 center にして kyoku_123 を作った # kyoku_1 と kyoku_123 の違いは、center の部分 # => # kyoku_123 の center が "後の山に 棄てましょか\n"であれば、 # kyoku_123 は kyoku_1 と同じ命令列になる kyoku_123 ( "後の山に 棄てましょか\n" ) <=> kyoku_1() => 関数の引数付き呼びだし 5. 引きつき関数 動作の変化が、引数の変化と連動している(連続な感じ) sample-005.c の kyoku_1, kyoku_2, kyoku_3 は連続な感じ => 引数の違いによって、動作の違いが説明できる kyoku_4 は、kyoku_1,2,3 に比べて変化が不連続な感じ まったく異なる行動をしているように見える 条件分岐 条件の成立、不成立によって、(まったく)異なる命令をする構文 => if 構文 (文法:書き方) if ( 条件 ) { 条件が成立した時の命令 } else { 条件が不成立の時の命令 } # if 構文を利用すると、状況によって、まったく異なる二つの命令列のどちらか一方を選んで、実行する事ができる 「条件」: 「!strcmp(一つ目、二つ目)」 もし、一つ目と二つ目が同じ文字列なら、成立する そうでなければ、不成立 => 「場合分け」が必要場合に、if 構文が利用される 例: 割り算をする場合は、分母が 0 の場合とそうでない場合に分ける必要がある sample-006.c の説明 6 行目に「おまじない(#include <string.h>)」を追加 => strcmp を使う場合に必要 56 行目に「if 構文の利用例」がある C 言語では(どうゆうわけだか..) 文字列に +1 すると、先頭文字が欠ける => 文字列の長さが 1 だけ減る
課題プログラム内の「/*名前:ここ*/」の部分を書き換え「/*この部分を完成させなさい*/」の部分にプログラムを追加して、プログラムを完成させます。
Download : 20190510-01.c
/* * 20190510-01-QQQQ.c * 引数付き関数で、if 文で条件判断をするプログラムを作成しなさい */ #include <stdio.h> #include <strings.h> /* * こだまでしょうか * (c) 金子みすゞ * http://www.ad-c.or.jp/campaign/self_area/03/index.html */ void kakko ( char *message ) { printf ( "「" ); printf ( message ); printf ( "」" ); } void iu ( char *message ) { kakko ( message ); printf ( "っていうと" ); /* ** この部分を完成させなさい */ } /* * main */ int main ( void ) { iu ( "遊ぼう" ); iu ( "馬鹿" ); iu ( "もう遊ばない" ); printf ( "そうして、あとでさみしくなって、\n" ); iu ( "ごめんね" ); printf ( "こだまでしょうか、いいえ、誰でも。\n" ); return 0; }
$ ./20190510-01-QQQQ.exe 「遊ぼう」っていうと「遊ぼう」っていう。 「馬鹿」っていうと「馬鹿」っていう。 「もう遊ばない」っていうと「遊ばない」っていう。 そうして、あとでさみしくなって、 「ごめんね」っていうと「ごめんね」っていう。 こだまでしょうか、いいえ、誰でも。 $
Download : 20190510-02.c
/* * 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 ); /* ** この部分を完成させなさい */ } } void pyramid ( char *edge ) { up ( edge + 1 ); printf ( edge ); printf ( "\n" ); /* ** この部分を完成させなさい */ } /* * main */ int main ( void ) { pyramid ( "*****" ); printf ( "\n" ); pyramid ( "**********" ); return 0; }
$ ./20190510-02-QQQQ.exe * ** *** **** ***** **** *** ** * * ** *** **** ***** ****** ******* ******** ********* ********** ********* ******** ******* ****** ***** **** *** ** * $