Download : sample-001.c
/* * 2020/07/17 sample-001.c * * [コンパイル] * cc -I ~/include -c sample-001.c * [リンク] * cc -o sample-001.exe sample-001.o * [実行] * ./sample-001.exe */ /* * 入力を一度だけ処理 */ #include <stdio.h> #include "s_input.h" #include "s_print.h" /* * main 関数 */ int main ( int argc, char *argv[] ) { s_print_string ( "整数値を一つ入力してください、一つ増やした値を出力します:" ); s_print_int ( s_input_int() + 1 ); /* 整数値を入力し、1 を増やし、出力 */ s_print_newline(); return 0; }
123
$ ./sample-001.exe < sample-001.in 整数値を一つ入力してください、一つ増やした値を出力します:123 124 $
Download : sample-002.c
/* * 2020/07/17 sample-002.c * * [コンパイル] * cc -I ~/include -c sample-002.c * [リンク] * cc -o sample-002.exe sample-002.o * [実行] * ./sample-002.exe */ /* * 入力を複数回処理 * 入力関数(s_input_int())が呼び出される度に、入力が行われる */ #include <stdio.h> #include "s_input.h" #include "s_print.h" /* * main 関数 */ int main ( int argc, char *argv[] ) { /* * 一回目 */ s_print_string ( "一回目:整数値を一つ入力してください、一つ増やした値を出力します:" ); s_print_int ( s_input_int() + 1 ); s_print_newline(); /* * ニ回目 */ s_print_string ( "ニ回目:整数値を一つ入力してください、一つ増やした値を出力します:" ); s_print_int ( s_input_int() + 1 ); s_print_newline(); /* * */ return 0; }
123 456
$ ./sample-002.exe < sample-002.in 一回目:整数値を一つ入力してください、一つ増やした値を出力します:123 124 ニ回目:整数値を一つ入力してください、一つ増やした値を出力します:456 457 $
Download : sample-003.c
/* * 2020/07/17 sample-003.c * * [コンパイル] * cc -I ~/include -c sample-003.c * [リンク] * cc -o sample-003.exe sample-003.o * [実行] * ./sample-003.exe */ /* * 一つの入力を複数回処理 * 入力関数の呼出し(入力)は一回だが、値(入力値)は複数利用したい * 関数(変数)を利用するしかない */ #include <stdio.h> #include "s_input.h" #include "s_print.h" /* * 引数で与えらえた値を複数回利用する(関数/引数変数の特権 !!) */ void print_add_one_result ( int value ) { s_print_string ( "整数値 " ); s_print_int ( value ); /* 一度目の利用 */ s_print_string ( " に 1 を加えた値は " ); s_print_int ( value + 1 ); /* 二度目の利用 */ s_print_string ( "これを 2 倍した値は " ); s_print_int ( value * 2 ); /* 三度目の利用 */ s_print_string ( " になります。\n" ); } /* * main 関数 */ int main ( int argc, char *argv[] ) { /* * 一回目 */ print_add_one_result ( s_input_int() ); /* 「入力(機能)」は「ここ」で一回 */ /* 「入力値」は、関数内で、何度も利用可能 */ /* * ニ回目 */ print_add_one_result ( s_input_int() ); /* 二度目の入力 */ /* * */ return 0; }
123 456
$ ./sample-003.exe < sample-003.in 123 整数値 123 に 1 を加えた値は 124これを 2 倍した値は 246 になります。 456 整数値 456 に 1 を加えた値は 457これを 2 倍した値は 912 になります。 $
Download : sample-004.c
/* * 2020/07/17 sample-004.c * * [コンパイル] * cc -I ~/include -c sample-004.c * [リンク] * cc -o sample-004.exe sample-004.o * [実行] * ./sample-004.exe */ /* * インプットループ * 入力を繰り返す関数 */ #include <stdio.h> /* * 改行 ('\n') が入力されるまで、文字を入力し、それを二度ずつ出力する */ void print_twice_char ( char ch ) { putchar ( ch ); /* とりあえず二度出力 */ putchar ( ch ); if ( ch == '\n' ) { /* 改行だった / もうこれ以上処理しない */ /* 何もしない */ } else { /* まだ処理する必要がある */ print_twice_char ( getchar() ); /* 入力をして、再帰 */ } } /* * main 関数 */ int main ( int argc, char *argv[] ) { /* * 最初の呼出しは main で.. */ print_twice_char ( getchar() ); /* * */ return 0; }
abc$
$ ./sample-004.exe < sample-004.in abc$ aabbcc$$ $
Download : sample-005.c
/* * 2020/07/17 sample-005.c * * [コンパイル] * cc -I ~/include -c sample-005.c * [リンク] * cc -o sample-005.exe sample-005.o * [実行] * ./sample-005.exe */ /* * 乱数 */ #include <stdio.h> #include "s_print.h" #include "s_random.h" /* s_random を利用するので.. */ /* s_init_random() --- 乱数系列を現在の時刻を利用して決定 s_random() --- 整数値を持つ(疑似)一様乱数を返す */ /* * main 関数 */ int main ( int argc, char *argv[] ) { /* * */ s_init_random(); /* 乱数系列の初期化 */ /* * */ s_print_string ( "乱数を出力します : " ); s_print_int ( s_random() ); s_print_newline(); /* * */ return 0; }
$ ./sample-005.exe 乱数を出力します : 1973597680 $
/* * 課題 CNAME-01 * * CDATE FILENAME * * キーボードから一文字入力し、その文字によって異る国の挨拶をする */ #include <stdio.h> /* * hello ( char contry ) * char contry : 国を表す一文字 * j : 日本 * e : 英語 * c : 中国 * f : フランス語 * g : ドイツ語 */ void hello ( char cmd ) { /* if 構文版 if ( cmd == 'j' ) { } else if ( cmd == 'e' ) { } .. switch ( cmd ) { case 'j': case 'e': .. } */ switch ( cmd ) { case 'j': /* 'j' の時は、日本語にする */ printf ( "こんにちは\n" ); break; case 'e': /* 'e' の時は、英語にする */ printf ( "Hello\n" ); break; case 'c': /* 'c' の時は、中国語にする */ printf ( "ニイハオ\n" ); break; case 'f': /* 'f' の時は、フランス語にする */ printf ( "Bonjour\n" ); break; /* ** この部分を完成させなさい */ printf ( "Guten tag\n" ); break; default: /* どれでもなければ.. */ printf ( "???\n" ); break; } } /* * main */ int main( void ) { printf ( "国を表す文字を入力してください\n" ); printf ( "\tj\t日本\n" ); printf ( "\te\t英語\n" ); printf ( "\tc\t中国\n" ); printf ( "\tf\tフランス\n" ); printf ( "\tg\tドイツ\n" ); hello ( getchar() ); /* getchar() で文字を入力し、それに対応する結果を出す */ return 0; }
#include <stdio.h> /* void is_digit_char ( char ch ) 引数で指定された『文字(コード)』が、「数字」を表す なら、「数字です」と出力、 そうでないならば、「数字ではありません」と出力 */ void is_digit_char ( char ch ) { /* 仮引数変数 ch (に入っている文字コード) が 「数字」を表すコードである事を確認する ASCII コード表 '0' <= ch <= '9' ( ch は '0' ? '9' ) => 二つの条件 '0' <= ch ch <= '9' が同時に成立している必要がある !! もし、C 言語で「 '0' <= ch <= '9'」という記述が !! 許されるなら !! if ( '0' <= ch <= '9' ) { !! printf ( "数字です\n" ); !! } else { !! printf ( "数字ではありません\n" ); !! } 二つの条件をチェックする例 (今の所)二つの条件は同時には判定できない => 一つずつ判定するしかない */ if ( '0' <= ch ) { /* '0' <= ch が成り立っている */ if ( ch <= '9' ) { /* 「'0' <= ch が成り立って」という状況で、更に 「ch <= '9'」が成立 */ /* => 二つの条件が共に成立している */ printf ( "数字です\n" ); } else { /* 「'0' <= ch」は成立するが「ch <= '9'」は不成立 */ printf ( "数字ではありません\n" ); } } else { /* 「'0' <= ch」が不成立 */ if ( ch <= '9' ) { /* 「'0' <= ch」は不成立、「ch <= '9'」が成立 */ printf ( "数字ではありません\n" ); } else { /* 「'0' <= ch」が不成立、「ch <= '9'」も不成立 */ printf ( "数字ではありません\n" ); } } } int main(void) { printf ( "文字を一文字入力して、[Enter]キーを押してください : " ); is_digit_char ( getchar() ); return 0; }
#include <stdio.h> /* void is_digit_char ( char ch ) 引数で指定された『文字(コード)』が、「数字」を表す なら、「数字です」と出力、 そうでないならば、「数字ではありません」と出力 */ void is_digit_char ( char ch ) { /* 仮引数変数 ch (に入っている文字コード) が 「数字」を表すコードである事を確認する ASCII コード表 '0' <= ch <= '9' ( ch は '0' ? '9' ) => 二つの条件 '0' <= ch ch <= '9' が同時に成立している必要がある !! もし、C 言語で「 '0' <= ch <= '9'」という記述が !! 許されるなら !! if ( '0' <= ch <= '9' ) { !! printf ( "数字です\n" ); !! } else { !! printf ( "数字ではありません\n" ); !! } 二つの条件をチェックする例 (今の所)二つの条件は同時には判定できない => 一つずつ判定するしかない */ if ( '0' <= ch ) { /* '0' <= ch が成り立っている */ if ( ch <= '9' ) { /* 「'0' <= ch が成り立って」という状況で、更に 「ch <= '9'」が成立 */ /* => 二つの条件が共に成立している */ printf ( "数字です\n" ); } else { /* 「'0' <= ch」は成立するが「ch <= '9'」は不成立 */ printf ( "数字ではありません\n" ); } } else { /* 「'0' <= ch」が不成立 */ /* 「ch <= '9'」の条件を確認するまでもなく、数字でない */ printf ( "数字ではありません\n" ); } } int main(void) { printf ( "文字を一文字入力して、[Enter]キーを押してください : " ); is_digit_char ( getchar() ); return 0; }
#include <stdio.h> #include "s_print.h" #include "s_input.h" /* void check_make_program ( int times ) switch 構文で実現 */ void check_make_program ( int times ) { switch ( times ) { case 1: /* times == 1 の意味 */ /* times == 1 の時の命令を記述する */ s_print_string ( "手でやる\n" ); break; /* ここで命令を終わり case - break <=> {} */ case 2: /* times == 2 の意味 */ /* times == 2 の時の命令を記述する */ s_print_string ( "自分で作るかどうか判断しろ\n" ); break; default: /* 上記以外の意味 */ /* 上で挙げた候補以外(その他) */ s_print_string ( "プログラムを作れ\n" ); break; } } int main(void) { s_print_string ( "その仕事は何度行いますか ? : " ); check_make_program ( s_input_int() ); return 0; }
#include <stdio.h> #include "s_print.h" #include "s_input.h" /* void check_make_program ( int times ) 引数で与えれた、仕事の繰り返し回数によって、 プログラムを作成するかどうかを判定して、 その指示を出力するプログラム 判定の基準と動作 times が 1 の時は、「手でやる」 times が 2 の時は、「自分で作るかどうか判断しろ」 times が 3(以上) の時は、「プログラムを作れ」 */ void check_make_program ( int times ) { if ( times == 1 ) { s_print_string ( "手でやる\n" ); } else if ( times == 2 ) { s_print_string ( "自分で作るかどうか判断しろ\n" ); } else { /* times != 1, times != 2, (仮定 times > 0 ) */ /* => times >= 3 */ s_print_string ( "プログラムを作れ\n" ); } } int main(void) { s_print_string ( "その仕事は何度行いますか ? : " ); check_make_program ( s_input_int() ); return 0; }
#include <stdio.h> #include "s_print.h" #include "s_input.h" /* void check_make_program ( int times ) 引数で与えれた、仕事の繰り返し回数によって、 プログラムを作成するかどうかを判定して、 その指示を出力するプログラム 判定の基準と動作 times が 1 の時は、「手でやる」 times が 2 の時は、「自分で作るかどうか判断しろ」 times が 3(以上) の時は、「プログラムを作れ」 */ void check_make_program ( int times ) { if ( times == 1 ) else if ( times == 2 ) s_print_string ( "自分で作るかどうか判断しろ\n" ); else s_print_string ( "プログラムを作れ\n" ); } int main(void) { s_print_string ( "その仕事は何度行いますか ? : " ); check_make_program ( s_input_int() ); return 0; }
前回(2020/07/10)の内容 条件分岐 (if 構文) 条件分岐 「複数の命令」の内、 「条件」によって、 その複数の命令の内の、「いずれか一つ」 を実行する仕組み => 命令を実行するかどうかの条件が記述できる <= 順接は、「問答無用」で実行される cf. 順接 : 命令を並べる事により、 複数の命令を、並べた順に、それぞれ実行する仕組み => 「記述量」がふえると、「実行量」が増える 与えれた状況に併せて、適切な対応を選択する仕組み プログラムの「柔軟性」を高める仕組み 「柔軟性」=>「汎用性」=>「再利用」 if 構文 : 条件分岐を実現する C 言語での表現方法 構文 : if ( 条件式 ) { then 節 条件が不成立時の文 } else { else 節 条件が成立時の文 } 条件式 : 真偽値(成立/不成立)を求める式 真 => 条件が成立 偽 => 条件が不成立 ( 成立しなかった ) 例: !strcmp ( A, B ) => A,B が同じ文字列なら真 例: 整数型の値や文字型の値は「比較」ができる ==, != (等しい、等しくない) <, >, <=, >= で、大小比較が可能 条件の成立時の文 条件が不成立時の文 : 複数の文(命令)が指定できる ( 空にする事も可能 ) 意味 「条件」が 『成立』した時に「条件の成立時の文」 を、 そうでない時には、「条件が不成立時の文」 を 実行する どちらか 一方だけ が実行される 「両方実行」も「両方不実行」も「無し」 「if 『文』」ではなく、 「if 『構文』」である理由 「『文』を対象として、『何かをする表現』」 なので「メタ表現」 文は、データを対象とする表現 構文は、文を対象とする表現 cf. 「順接」も「順接構文」 if 構文 アラカルト if 構文の基本 : if ( C ) { A } else { B } 「基本」は「基本の組み合せだけで何でもできる」ので秀逸 色々な組み合せ方を学ぶ必要がある => いかなる条件の判定も、(条件のサイズが有限なら) 基本の if 構文だけで、表現できる 二つの条件 C1, C2 の両方が成立した時に A、そうでない時に B という場合 # 基本の構文は、一つの条件しか確認できない # => 二つの条件 C1, C2 を、どのように利用するか ? 場合分け ( 真 : T / 偽 : F ) C1 C2 C1 と C2 の両方 T T T T F F F T F F F F # if 構文を利用すると、2 つの場合に分けられる # => if 構文数を N とすると、N+1 の状況が作れる 例: 引数の『文字(コード)』が数字かどうかを確認する (三つ目の if 構文を省略する場合の真偽表) 場合分け ( 真 : T / 偽 : F ) C1 C2 C1 と C2 の両方 T T T T F F F * F else 節の省略 else 節 : if 構文の 「else { B }」の部分 B が空の時は、 「else {}」としても良い が、 それを省略しても良い 基本: if ( C ) { A } else { } else 節の省略の場合: if ( C ) { A } /* else {} */ /* else 節を省略 */ then 節 ( { A } の所 ) は省略できない 基本: if ( C ) { } else { B } できない: if ( C ) else { B } if 構文の「入れ子」 if 構文の文の中に if 構文をいれる 複数の条件の「条件の組み合せ」を if 構文の組み合せで実現できる 例(複雑な条件) : ch が英大文字かどうか 'A' <= ch <= 'Z' [数学] => C 言語では、こう表現できません # 別の表現があるが、後期に話す 例 : if ( 'A' <= ch ) { /* ここでは、 「'A' <= ch」が成立している */ if ( ch <= 'Z' ) { /* ここでは「'A' <= ch」と「ch <= 'Z'」の両方が成立 */ /* ch が「英大文字」の時 */ } else {} } else {} [前回(2020/07/10) : 条件分岐 again ] 条件分岐 条件の可否によって、複数の命令の実行を選択できる 命令を組み合わせて新しい命令を作る仕組み ( cf. 順接 ) if 構文 C 言語で条件分岐を表現する仕組み 基本 : if ( C ) { A } else { B } => 基本の組み合わせ ( 入れ子 ) で任意の条件が判定可能 応用 else 節が省略可能 [2020/07/17] 複数条件の判定の内 ある値が複数の値をとりうる場合 例 : 入力される数値が、 1, 2, 3 の三通りある それぞれの場合に対して、別々の処理をしたい !! もし、取りうる範囲が 2 種類しかなければ、 !! if 構文一つで十分 例: それを 1 度しかやらないなら、すぐに手でやれ もし、2 度やるなら、どちらか悩んでください もし、3 度(以上)やるなら、プログラムを作って、PCにやらせろ 一般に N 通りの区別をするには、 else が N - 1 回深く もし、else の中身が、if 構文一つ場合 => else 節の {} を省略する else if 構文 (イデオム) else 節の文全体が一つの if 構文(入れ子)になっている場合 else 節のブレースを省略する 例: if ( C1 ) { A } else { if ( C2 ) { B } else { C } } => if ( C1 ) { A } else if ( C2 ) { B } else { C } 入れ子による、段の深化が防げる 複数の条件の関係が「視覚化」できます 入れ子 : 複数条件が適用されている else if : 一つのものに対する異なった条件が適用 一つのデータに対して、複数の条件の検査になっている 「表現」と「意味」の対応 (イデオム) 推奨しない if 構文の表現 その他の表現 いつでも、「基本」を守る事が肝要 自分で作成する時には、まずは、基本を守る 他人は、基本を守るとは限らないので、 いろいろな記法を学ぶ事も必要 ブレースの省略 then 節/else 節の文が一文の時にはブレースを省略できる !! 「本」には、 !! then/else 節には、「(一つの)文」が書ける !! 複数の文を書きたい場合は {} を使え !! 文が一つの場合は、{} を付けてもよい else if 構文は、その規則を特別な場合に適用している ブレース省略の是非 「省略」できるから、「手間」は減る (僅かな利点) 条件の適用範囲が不明瞭になる (大きな損失) 後から、変更を加える時に不便 (ミスの増大) ミスをしないためのちょっとした習慣(小さなコスト)が、 結果的に、大きなミス(多大な損害)を防ぐ事になります。 例 : {} を省略しない ぶら下がり構文の悲劇 ブレースの省略と else の省略が重なると悲惨 if ( C1 ) if ( C2 ) A else B は、次のどちらか ? (1) else が内側(後の/近い方の) if に対応 [正解] if ( C1 ) if ( C2 ) A else B if ( C1 ) { if ( C2 ) { A } else { B } } (2) else が外側(前の/遠い方の) if に対応 if ( C1 ) if ( C2 ) A else B if ( C1 ) { if ( C2 ) { A } } else { B } 1+2*3 => 1+(2*3) [switch 構文] switch 構文 条件分岐の表現方法の一つ !! if 構文は万能なので、なくてもよい 機能 多分岐構文 if 構文は 2 分岐だが switch 構文は n 分岐 構文 <switch 文> ::= switch ( <式> ) { <case 並び> } <case 並び> ::= <case> の繰返し <case> ::= <label> : 文並び ( 最後に break がある事を想定 ) <label> := case <定数> | default ※1 一つの <switch 文>内には、同じ <label> を含める事はできない ※2 文並び中に break 文があり、それが実行されると、switch 文は終了する 意味 もし、「式」の値が「定数」の何れか であれば、 そのラベル以下の文を実行する そうでなくて、 もし、 defualt があれば、そのラベル以下の文を実行する そのいずれでもなければ、何もしない [再帰呼出し again] 再帰呼出し ある関数定義の本体に、その関数自身の呼出しが含まれる事 => その関数は再帰呼び出しされる 関数が、再帰で定義されている (プログラミング言語) # [数学] # 帰納的に定義されている関数 # 例: # 1 ( n が 0 の時 ) # 階乗 n! = { # n * ( (n-1)! ) ( その他 ) # # n! を定義するのに、(n-1)! を利用している # 「循環定義(論法)」のように感じる # 「表は裏の裏」、「裏は表の裏」 # すべてのものは神が作った # 神を作ったのは ? 神様の神様 # 神様の神様を作ったのは神様の神様の神様 # 数学的帰納法の原理に基づく # 帰納的定義になっている # 3! => 3 * (3-1)! # => 3 * 2! # => 3 * ( 2 * (2-1)! ) # => 3 * 2 * 1! # => 3 * 2 * (1 * (1-1)!) # => 3 * 2 * 1 * 0! # => 3 * 2 * 1 # => 6 # # 自然数の定義(ペアノの公理) # [i] 0 は自然数 # [ii] n が自然数ならn+1も自然数 # [iii] [i],[ii] から作られるものだけが自然数 # # 3 は自然数か ? # => [ii] から 3 = 2 + 1, 2 が自然数なら自然数 # => 2 が自然数か ? # => [ii] から 2 = 1 + 1, 1 が自然数なら自然数 # => 1 が自然数か ? # => [ii] から 1 = 0 + 1, 0 が自然数なら自然数 # => 0 が自然数か ? # => [i] 0 は自然数なので OK # # => 数学的帰納法の原理 # 「再帰的に定義さらた関数の『一度』の呼出し」 で「その関数の定義の呼出しが」 が『何度』も呼び出される 「可能性」が生じる 注意 : 安易に「再帰呼出し」を記述すると、「無限ループ」になる 安易 : 「対象を『小さく』」していない や 最小の場合の対応をしていない 「再帰呼出しを『終了』させる」仕組 を「意図的に導入」する 「対象を『小さく』」する し、 最小の場合の対応をする を記述する必要がある 「条件分岐」が必須 再帰句 P は、停止条件 A は繰り返す命令、 X' は X から計算され、『何時か』 P(X)が成立する X' は X より「小さく」なり、 P(c) となる c (最小値)に X が何時かは成る 記述形式 f(X) { if ( P(X) ) { /* なにもしない *. } else { A(X); f(X'); } } 意味 : f(X) を呼ぶと、 P(X''..')が成立するまで A(X) を繰り返す ' の個数だけ A(X)を繰り返す ポイント : 「A(X) を繰り返す」ために「f() を再帰で定義」する 再帰関数 再帰呼出しを行う形で定義された関数 繰返し : 同じ命令(記述)を何度も呼び出す仕組 再帰呼出しを利用する事により、「繰返し」が実現できる 再帰関数は、「何らかの繰返し」を実現している
課題プログラム内の「/*名前:ここ*/」の部分を書き換え「/*この部分を完成させなさい*/」の部分にプログラムを追加して、プログラムを完成させます。
Download : 20200717-01.c
/* * 20200717-01-QQQQ.c * * 数当てを行う * * コンパイル : * cc -I ~/c/include -c 20200717-01-QQQQ.c * cc -o 20200717-01-QQQQ.exe 20200717-01-QQQQ.o * 実行 : * ./20200717-01-QQQQ.exe * */ #include <stdio.h> #include "s_print.h" /* s_print_int を利用するので.. */ #include "s_input.h" /* s_input_int を利用するので.. */ #include "s_random.h" /* s_random を利用するので.. */ /* * prompt * メッセージを出力し、キーボードから整数値を読み込んで、 * その値を返す関数 */ int prompt(void) { s_print_string ( "私が選んだ数を予想して入力してください : " ); return s_input_int(); } /* */ void game ( int input, int answer ) { if ( input == answer ) { /* 入力と答えが一致した */ s_print_string ( "お見事です。あたりました。\n" ); } else { if ( input > answer ) { /* 入力が、答えより大きい */ /* ** この部分を完成させなさい */ } else { /* 入力が、答えより小さい */ s_print_string ( "その数は小さすぎます。\n" ); } /* 未だ、答えが、当っていないので、ゲームを続ける.. */ /* ** この部分を完成させなさい */ } } /* * main */ int main( void ) { s_init_random(); /* 乱数系列の初期化 */ s_print_string ( "私が考えた 1 〜 100 数を予想して当ててみてください。\n" ); game ( prompt(), (s_random()%100) + 1 ); return 0; }
50 75 83 90 85 84
$ ./20180928-01-QQQQ.exe 私が考えた 1 〜 100 の数を予想して当ててみてください。 私が選んだ数を予想して入力してください : 5 5 その数は小さすぎます。 私が選んだ数を予想して入力してください : 60 60 その数は大きすぎます。 私が選んだ数を予想して入力してください : 30 30 お見事です。あたりました。 $
Download : 20200717-02.c
/* * CDATE FILENAME * * 与えられた自然数の素因数を出力する * * 12 は.. * * [コンパイル] * cc -I ~/include -c FILENAME * [リンク] * cc -o BASENAME.exe BASENAME.o * [実行] * ./BASENAME.exe * */ #include <stdio.h> #include "s_print.h" /* s_print_int を利用するので.. */ /* * void print_prime_factor_sequence ( int n, int p ) * 機能 : p 以上の n の素因数を小さい順に並べで表示する * 条件 : n には p 未満の素因数を含まれていないものとする * int n : p 未満の素因数を含まれていない自然数 * 返り値 : なし */ void print_prime_factor_sequence ( int n, int p ) { if ( p > n ) { /* もう n には p 以上の素因数を含まない */ /* 何もしなくてよい */ /* 本来、ここにくるのは n = 1 の時だが、念の為 */ } else if ( n % p == 0 ) { /* n が p を素因数として含む */ s_print_char ( ' ' ); /* 隙間を空け */ s_print_int ( p ); /* 素因数を表示し */ /* もう一度 p の要素があるかもしれないので、そこから試す [再帰] */ /* ** この部分を完成させなさい */ } else { /* n が p を素因数として含まない */ /* 本来は p の次の素数を試すべきだが.. */ /* その代りに p + 1 を試す (のは無駄だが、正く動く) [再帰] */ /* ** この部分を完成させなさい */ } } /* * void print_prime_factor_of ( int n ) * 機能 : n の素因数を出力する * int n : 素因数を表示したい自然数 * 返り値 : なし */ void print_prime_factor_of ( int n ) { if ( n < 1 ) { /* 与えらた数が自然数ではない */ s_print_int ( n ); s_print_string ( "は、自然数ではありません\n" ); } else if ( n == 1 ) { /* 与えられた数が 1 の場合 */ s_print_int ( n ); s_print_string ( "の素因数はありません\n" ); } else { s_print_int ( n ); s_print_string ( "の素因数分解は" ); /* ** この部分を完成させなさい */ s_print_string ( " となります。\n" ); } } /* * main */ int main( void ) { print_prime_factor_of ( 12 ); return 0; }
$ ./20200717-02-QQQQ.exe 12の素因数分解は 2 2 3 となります。 $
Download : 20200717-03.c
/* * 20200717-03-QQQQ.c * フィボナッチ数列の第 n 項を返す関数 */ #include <stdio.h> #include "s_input.h" #include "s_print.h" /* * int fibonacci ( int n ) * 引数で指定された n 番目 ( n = 0 〜 ) のフィボナッチ数を値として返す関数 * ただし、n 番目のフィボナッチ数 fib(n) は次のように再帰的に定義 * 0 (n = 0 の時) * fib(n) = { 1 (n = 1 の時) * fib(n-1) + fib(n-2) (n > 1 の時) * * 注意 : 引数に負の数を指定された場合の値は「未定義」 */ int fibonacci ( int n ) { if ( n < 2 ) { /* 本来は n = 0, n = 1 の時の処理 */ /* fib(0) = 0, fib(1) = 1 なので 0 <= n <= 1 の時 fib(n) = n */ return n; /* n < 0 (負の数) の時は、『未定義』なので、勝手に n を返している */ /* 本来は『未定義』の場合を含めるべきでない */ } else { /* 再帰を利用して計算 */ /* ** この部分を完成させなさい */ } } /* * */ void print_fibonacci ( int n ) { s_print_int ( n ); s_print_string ( " 番目のフィボナッチ数は " ); s_print_int ( fibonacci ( n ) ); s_print_string ( " です。\n" ); } /* * main */ int main ( void ) { s_print_string ( "整数値 n を入力してください : " ); print_fibonacci ( s_input_int() ); s_print_string ( "整数値 n を入力してください : " ); print_fibonacci ( s_input_int() ); return 0; }
4 10
$ ./20200717-03-QQQQ.exe 整数値 n を入力してください : 4 4 番目のフィボナッチ数は 3 です。 整数値 n を入力してください : 10 10 番目のフィボナッチ数は 55 です。 $