/* * 20180427-01-QQQQ.c * 歌詞を出力する */ #include <stdio.h> /* * 「一番星みつけた」 * (C) 生沼勝作詞(注)・信時潔作曲/文部省唱歌(一年) * http://www.mahoroba.ne.jp/~gonbe007/hog/shouka/ichibanboshi.html */ void uta ( char *ichi, char *basyo, char *ki ) { printf ( ichi ); printf ( "番星みつけた。\n" ); printf ( "あれあの" ); printf ( basyo ); printf ( "の\n" ); printf ( ki ); printf ( "の木のうえに。\n" ); } void itibanboshi() { uta ( "一", "森", "杉" ); printf ( "\n" ); uta ( "二", "どて", "柳" ); printf ( "\n" ); uta ( "三", "どて", "柳" ); printf ( "\n" ); } /* * main */ int main ( void ) { itibanboshi(); return 0; }
/* p-001.c 「関数の作り方(関数定義)」の復習 例 : 「pritnf ( "Hello, World\n" );」に print_hello という名前を付ける事を考える 1. 名前(関数名)を決める 「print_hello」とした 2. その名前を、main の前(外)に書く 3. 名前の前に 「void」, 後ろの 「(void)」 を書く 4. そのさらに後ろに空の 「{}」を入れる 5. 「{}」の間に、名前を付けたい命令を書く 「pritnf ( "Hello, World\n" );」に名前をつけたいので、 この内容を「{}」の間に、入れる 「関数の利用の仕方(関数呼び出し)」の復習 1. 名前を付けた命令を実行するには、「関数名();」とするだけ */ #include <stdio.h> /* 関数 print_hello の定義 */ void print_hello (void) { /* printf ( "@@@ : print_hello の開始\n" ); */ printf ( "Hello, World\n" ); } int main(void) { /* printf ( "@@@ : main の開始\n" ); */ print_hello(); return 0; }
/* p-002.c p-001.c の動作確認 [ポイント] p-001.exe を実行すると、メッセージが一つ表示される。 関数 print_hello の中の「printf(...):」 Q.1 main などいらないのでは ? A.1 main がないと、リンクの時に「main がない」と怒られる => main は必要 Q.2 命令は、どの順で実行されるのか ? # print_hello が頭にあるから、これから ?? C Program は、必ず、main から始まる => main は必ず必要 # おまじないとして main を.. # => C の Program の開始部分を指定している [p-002.c プログラムの構造] 0. main : 必ず main から実行される 1. printf 2. hello_world : 関数呼び出しがあると.. 2.1 printf : それぞれ、名前つけられた命令が実行される 2.2 printf 2.3 printf 3. printf [p-001.c プログラムの構造] 0. main 1. hello_world 1.1 printf p-001.c の動作を理解するために p-002.c で追加した printf 命令は。何時、何が、どの様に、起きているかを知る 「手がかり」として「(特別に)追加した」print 命令 => 「デバッグプリント」と呼ぶ !! プログラムの振る舞いがよくわからないとき !! => プログラムのあちらこちらに、「デバッグプリント」 !! を入れると、理解できる事がよくある */ #include <stdio.h> /* 関数 print_hello の定義 */ void print_hello (void) { printf ( "@@@: print_hello の最初\n" ); /* 2.1 */ printf ( "Hello, World\n" ); /* 2.2 */ printf ( "@@@: print_hello の最後\n" ); /* 2.3 */ } int main(void) { printf ( "@@@: main の最初\n" ); /* 1 */ print_hello(); /* 関数 print_hello の呼び出し */ /* 2 */ printf ( "@@@: main の最後\n" ); /* 3 */ return 0; }
/* p-003.c 「Hello, 色々」という形プログラムを考える 例: Hello, 世界 Hello, 皆さん Hello, 友達 ... */ #include <stdio.h> int main(void) { printf ( "Hello, 世界\n" ); printf ( "Hello, 皆さん\n" ); printf ( "Hello, 友達\n" ); return 0; }
/* p-004.c 「Hello, 色々」という形プログラムを考える 例: Hello, 世界 Hello, 皆さん Hello, 友達 ... 方針 関数を作って、main は、関数呼び出しにする print_hello_world print_hello_yours print_hello_friend */ #include <stdio.h> void print_hello_world(void) { printf ( "Hello, 世界\n" ); } void print_hello_yours(void) { printf ( "Hello, 皆さん\n" ); } void print_hello_friend(void) { printf ( "Hello, 友達\n" ); } int main(void) { print_hello_world(); print_hello_yours(); print_hello_friend(); return 0; }
/* p-005.c 「Hello, 色々」という形プログラムを考える 例: Hello, 世界 Hello, 皆さん Hello, 友達 ... 方針 関数を作って、main は、関数呼び出しにする print_hello_world print_hello_yours print_hello_friend [考察] 新しくつくった三つの関数は、よく似ている hello, 何か # コンピュータは繰り返しが得意 # 人間は、繰り返しが苦手 # 人間が不得意な繰り返しをコンピュータにやらせる # => プログラミング ## 今回はコピー&ペーストですんだので、それほど大変はないが.. ## プログラミングで「コピー&ペースト」は危険 うまく、一つのことで、三つの事ができないか ? [単純な案] print_hello_world();を三度呼ぶ => print_hello_world()を一つだけ定義すればよい <= 同じメッセージしかでない => 不都合 [問題点] (現状)関数が同じだと、同じ結果しかでない => 不自由 (希望)関数を減らしたい(一つにしたい) 結果は変えたい 「数学の「関数」」であれば、引数を指定して 同じ関数で、異なる値を返す事ができる => C 言語の関数でも同じ事ができる [複数の関数をまとめる] もし、 -- 8< ---- 8< ---- 8< ---- 8< ---- 8< -- void print_hello_X(void) { printf ( "Hello, X\n" ); } -- 8< ---- 8< ---- 8< ---- 8< ---- 8< -- として、X のところが変わるならうれしい... => できない やりたいことの「違い」が、「違う命令の有り無し」になるようにする printf の () の中が異なるだけ => その中身に「X」という名前を付ける #「""」で挟まれたものは、 # 「文字列」という「情報を表すもの(data)」 ## ここでは、「データに名前をつけて」いる ## cf. 関数定義が、「命令に名前を付けて」いる */ #include <stdio.h> void print_hello_X(char *X) { /* (void) => (char *X) : 名前を使う */ printf ( "Hello, " ); printf ( X ); /* 関数の特徴となるデータに X という名前を付けた */ } /* 違うものが、同じとみなせる */ /* 「引数付き」関数 */ void print_hello_world(void) { /* printf ( "Hello, " );*/ /* printf ( "世界\n" );*/ /* world の特徴は この行 */ print_hello_X("世界\n" ); /* hello_X の X に "世界\n" を指定 */ /* 引数付き関数に、変更したい部分として、 引数を指定する事により、個々の 具体的なふるまいをさせる事ができる */ } void print_hello_yours(void) { printf ( "Hello, " ); printf ( "皆さん\n" ); /* yours の特徴は この行 */ } void print_hello_friend(void) { printf ( "Hello, 友達\n" ); } int main(void) { print_hello_world(); print_hello_yours(); print_hello_friend(); return 0; }
/* p-006.c print_hello_X という「引数付き関数」を利用して、 他の関数も作成してまう */ #include <stdio.h> void print_hello_X(char *X) { printf ( "Hello, " ); printf ( X ); /* 具体的には、引数で指定された値に入れ替わる */ /* X は「値が変わる」ので、「変数」と呼ばれる */ /* cf.数学の関数と同じ f(x)=x*x の時は、 f(3) -> 3*3 -> 9 */ } void print_hello_yours(void) { print_hello_X("皆さん\n" ); /* print_hello_X("皆さん\n" ); call print_hello_X(char *X) が見つかる X = "皆さん\n" として printf ( "Hello, " ); printf ( X ); の二つの命令が実行される。 これは結果的には、変数 X のところに「皆さん\n」が入って printf ( "Hello, " ); printf ( "皆さん\n" ); と同じ */ } void print_hello_world(void) { print_hello_X("世界\n" );} void print_hello_friend(void) { print_hello_X("友達\n" ); } int main(void) { print_hello_world(); print_hello_yours(); print_hello_friend(); return 0; }
/* p-007.c print_hello_X という「引数付き関数」を利用して、 他の関数も作成してまう main print_hello_world print_hello_X printf print_hello_yours print_hello_X printf print_hello_firend print_hello_X printf */ #include <stdio.h> void print_hello_X(char *X) { printf ( "@@@ X 開始\n" ); printf ( "Hello, " ); printf ( X ); /* 具体的には、引数で指定された値に入れ替わる */ /* X は「値が変わる」ので、「変数」と呼ばれる */ /* cf.数学の関数と同じ f(x)=x*x の時は、 f(3) -> 3*3 -> 9 */ } void print_hello_yours(void) { printf ( "@@@ yours 開始\n" ); print_hello_X("皆さん\n" ); /* print_hello_X("皆さん\n" ); call print_hello_X(char *X) が見つかる X = "皆さん\n" として printf ( "Hello, " ); printf ( X ); の二つの命令が実行される。 これは結果的には、変数 X のところに「皆さん\n」が入って printf ( "Hello, " ); printf ( "皆さん\n" ); と同じ */ } void print_hello_world(void) { printf ( "@@@ word 開始\n" ); print_hello_X("世界\n" );} void print_hello_friend(void) { printf ( "@@@ friend 開始\n" ); print_hello_X("友達\n" ); } int main(void) { printf ( "@@@ main 開始\n" ); print_hello_world(); print_hello_yours(); print_hello_friend(); return 0; }
/* p-008.c 引数付き関数、いろいろ (その 1) 同じ文字列を二度出力する two_print */ void two_print(char *message) { printf ( message ); /* 同じメッセージを二度書きたい */ printf ( message ); /* メッセージそのものは引数指定.. */ /* メッセージとなる変数には、「message」 という名前を付ける */ /* [ポイント] 変数は、何度でも参照可能で、その値は毎回同じ */ } int main(void) { two_print ( "Hello, World\n" ); two_print ( "こんにちは、みなさん\n" ); return 0; }
/* p-009.c 引数付き関数、いろいろ (その 2) 複数の引数をとる 誰が、誰に、何をする who_whom_did */ #include <stdio.h> void who_whom_did(char *who,char *whom,char *did) { /* 変数は、複数もつことができる */ /* 関数の定義の時に、複数指定したら、呼び出すときも同じ数 */ printf ( who ); /* A さん */ printf ( "が、" ); /* が */ printf ( whom ); /* B さん */ printf ( "に、" ); /* に */ printf ( did ); /* キス */ printf ( "した。\n" ); /* した。 */ /* 命令の複数の部分を変更できる => 変更したい箇所に応じて、変数を設けて、置き換えればよい */ } int main(void) { who_whom_did ( "A 君", "B さん", "キス" ); who_whom_did ( "X さん", "Y さん", "メール" ); return 0; }
/* p-010.c 課題 : 20180427-01 の安易な答え */ #include <stdio.h> 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" ); return 0; }
# # Makefile (拡張子はない) # # # # は Makefile の中ではコメント # # 空白と[TAB] は、区別される # 空白のところには、空白を、[TAB] のところには[TAB] を入れる # # # 20180427-01-9999.exe の作り方 # 「20180427-01-9999.exe」 を作るには、「20180427-01-9999.o」を材料に # 「cc -o 20180427-01-9999.exe 20180427-01-9999.o」という調理をする 20180427-01-9999.exe : 20180427-01-9999.o cc -o 20180427-01-9999.exe 20180427-01-9999.o # # 20180427-01-9999.o の作り方 # 「20180427-01-9999.o」 を作るには、「20180427-01-9999.c」を材料に # 「cc -c 20180427-01-9999.c」という調理をする 20180427-01-9999.o : 20180427-01-9999.c cc -c 20180427-01-9999.c
?O?????K 1. ??????????A??????????????s????? ???? : ?uprintf("???b?Z?[?W");?v???? ???s??????A?????L?q???????????????(????) # cf. # ?^?????v???O??????A?????`(?v???O??????????Z???s????) # ???????????X?g??A???????? # ???X?g?????????????????? 2. ???????O??t????(???) a) ????(??)????O??t???鎖??????? (?????`) i) ???????閼?O??t???鎖??A?????????? ii) (????..) ???????A?????яo?????????? => ?v???O?????S?????????Z?????A?????????? # ?????b?g?????????????A??????????????? b) (??????O?????????????)??????O(?????)??????A ?Q??????(?????яo??) ?????v???O???? : helloworld -- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< -- #include <stdio,h> int main(void) { pritnf ( "Hello, World\n" ); /* ???????????????????????? */ return 0; } -- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< -- => (????) -- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< -- Hello, World -- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< -- [?????????] -- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< -- #include <stdio,h> int main(void) { pritnf ( "Hello, World\n" ); /* ????????? */ pritnf ( "Hello, World\n" ); pritnf ( "Hello, World\n" ); return 0; } -- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< -- => (????) -- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< -- Hello, World /* ????(????o??)?????? */ Hello, World Hello, World -- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< -- [???????????????] -- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< -- #include <stdio,h> int main(void) { pritnf ( "Hello, World\n" ); pritnf ( "????????A?F????\n" ); pritnf ( "?j?[?n?I\n" ); return 0; } -- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< -- => (????) -- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< -- Hello, World /* ?????????????? */ ????????A?F???? ?j?[?n?I -- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< -- == [???T????e] ????????(??)
Download : 20180511-01.c
/* * 20180511-01-QQQQ.c * 分割コンパイルの main */ #include <stdio.h> /* * main */ int main ( void ) { sub_20180511_01_9999(); /* サブルーチンを呼ぶ */ return 0; }
Download : 20180511-01-01.c
/* * 20180511-01-01-QQQQ.c * 分割コンパイルの sub */ #include <stdio.h> /* * sub_20180511_01_9999 */ void sub_20180511_01_9999 ( void ) { printf ( "これは、9999 番のサブルーチンです\n" ); }
Download : Makefile-20180511.txt
# # Makefile-20180511-9999.txt # 分割コンパイルの Makefile # 20180511-01-9999.exe : 20180511-01-9999.o 20180511-01-01-9999.o cc -o 20180511-01-9999.exe 20180511-01-9999.o 20180511-01-01-9999.o 20180511-01-9999.o : 20180511-01-9999.c cc -c 20180511-01-9999.c 20180511-9999-01-01.o : 20180511-01-01-9999.c cc -c 20180511-01-01-9999.c
$ ls 20180511-01-9999.c 20180511-01-01-9999.c Makefile $ make cc -c 20180511-01-9999.c cc -c 20180511-01-01-9999.c cc -o 20180511-01-9999.exe 20180511-01-9999.o 20180511-01-01-9999.o $ ./20180511-01-QQQQ.exe これは、9999 番のサブルーチンです $