Download : sample-001.c
/* * 2020/10/16 sample-001.c */ /* * 複数条件の分岐 * * 利用方法 * コンパイル * cc -I ~/c/include -o sample-001.exe sample-001.c * 実行 * sample-001 */ #include <stdio.h> /* * trump * トランプの番号から、その名前を表示する */ void trump ( int number ) { printf ( "数値 %d の表すカードは、", number ); if ( number == 1 ) { /* 番号が 1 なら エース (A) */ printf ( "エース" ); } else if ( number == 11 ) { /* 番号が 11 なら ジャック (J) */ printf ( "ジャック" ); } else if ( number == 12 ) { /* 番号が 12 なら クイーン (Q) */ printf ( "クイーン" ); } else if ( number == 13 ) { /* 番号が 13 なら キング (K) */ printf ( "キング" ); } else if ( number == 0 ) { /* 番号が 0 の場合は例外的に ジョーカー ($) */ printf ( "ジョーカー" ); } else { /* それ以外 */ if ( number < 0 ) { /* 番号が負の場合は.. */ printf ( "範囲外" ); } else if ( 13 < number ) { /* 番号が 13 より大きい場合は.. */ printf ( "範囲外" ); } else { /* それ以外は.. */ printf ( "%d の数カード", number ); } } printf ( "です。\n" ); } /* * main * */ int main( int argc, char *argv[] ) { trump ( -1 ); trump ( 0 ); trump ( 1 ); trump ( 7 ); trump ( 10 ); trump ( 13 ); trump ( 20 ); return 0; }
$ ./sample-001.exe 数値 -1 の表すカードは、範囲外です。 数値 0 の表すカードは、ジョーカーです。 数値 1 の表すカードは、エースです。 数値 7 の表すカードは、7 の数カードです。 数値 10 の表すカードは、10 の数カードです。 数値 13 の表すカードは、キングです。 数値 20 の表すカードは、範囲外です。 $
Download : sample-002.c
/* * 2020/10/16 sample-002.c */ /* * 複数条件の分岐(case 文を利用した場合) * * 利用方法 * コンパイル * cc -I ~/c/include -o sample-002.exe sample-002.c * 実行 * sample-002 */ #include <stdio.h> /* * trump * トランプの番号から、その名前を表示する */ void trump ( int number ) { printf ( "数値 %d の表すカードは、", number ); switch ( number ) { /* 一つの式の値で分岐 */ case 1: /* 番号が 1 なら エース (A) { (開きブロック) */ printf ( "エース" ); break; /* ここで 1 の場合がおわる } (閉じブロック) */ case 11: /* 番号が 11 なら ジャック (J) */ printf ( "ジャック" ); break; case 12: /* 番号が 12 なら クイーン (Q) */ printf ( "クイーン" ); break; case 13: /* 番号が 13 なら キング (K) */ printf ( "キング" ); break; case 0: /* 番号が 0 の場合は例外的に ジョーカー ($) */ printf ( "ジョーカー" ); break; case 2: /* 範囲は指定できないので、全て列挙 */ /* 2 の場合は 3 の場合と同じなので break しない */ case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: printf ( "%d の数カード", number ); break; /* 2 〜 10 の場合はここで、終了 */ default: /* それ以外は.. */ printf ( "範囲外" ); break; /* これは不要だが、つける習慣を (マナー) */ } printf ( "です。\n" ); } /* * main * */ int main( int argc, char *argv[] ) { trump ( -1 ); trump ( 0 ); trump ( 1 ); trump ( 7 ); trump ( 10 ); trump ( 13 ); trump ( 20 ); return 0; }
$ ./sample-002.exe 数値 -1 の表すカードは、範囲外です。 数値 0 の表すカードは、ジョーカーです。 数値 1 の表すカードは、エースです。 数値 7 の表すカードは、7 の数カードです。 数値 10 の表すカードは、10 の数カードです。 数値 13 の表すカードは、キングです。 数値 20 の表すカードは、範囲外です。 $
Download : sample-003.c
/* * 2020/10/16 sample-003.c */ #include <stdio.h> /* * for 文を利用して、0 から 9 の数値を表示する * * 利用方法 * コンパイル * cc -I ~/c/include -o sample-003.exe sample-003.c * 実行 * sample-003 */ int main(int ac, char *av[] ) { int i; /* for 文の制御変数 */ for ( i = 0; i < 10; i = i + 1 ) {/* i を 0 〜 9 迄変化 */ printf ( "%d\n", i ); /* i を出力 */ } return 0; }
$ ./sample-003.exe 0 1 2 3 4 5 6 7 8 9 $
Download : sample-004.c
/* * 2020/10/16 sample-004.c */ #include <stdio.h> /* * for 文を利用して、1 から 10 の数値を表示する * * 利用方法 * コンパイル * cc -I ~/c/include -o sample-004.exe sample-004.c * 実行 * sample-004 */ int main(int ac, char *av[] ) { int i; /* for 文の制御変数 */ for ( i = 1; i <= 10; i = i + 1 ) {/* i を 1 〜 10迄変化 */ printf ( "%d\n", i ); /* i を出力 */ } return 0; }
$ ./sample-004.exe 1 2 3 4 5 6 7 8 9 10 $
Download : sample-005.c
/* * 2020/10/16 sample-005.c */ #include <stdio.h> /* * for 文を利用して、0 から 9 の数値を表示する * * 利用方法 * コンパイル * cc -I ~/c/include -o sample-005.exe sample-005.c * 実行 * sample-005 */ int main(int ac, char *av[] ) { int i; /* for 文の制御変数 */ for ( i = 0; i < 10; i++ ) { /* i を 0 〜 9 迄変化 */ /* i++ は i = i + 1 と同じ */ printf ( "%d\n", i ); /* i を出力 */ } return 0; }
$ ./sample-005.exe 0 1 2 3 4 5 6 7 8 9 $
Download : sample-006.c
/* * 2020/10/16 sample-006.c */ #include <stdio.h> /* * for 文を利用して、0 から 9 迄の 10 個の数値を和を表示する * sum = \sum_{i=0}^{9} i * * 利用方法 * コンパイル * cc -I ~/c/include -o sample-006.exe sample-006.c * 実行 * sample-006 */ int main(int ac, char *av[] ) { int i; /* for 文の制御変数 */ int sum = 0; for ( i = 0; i < 10; i++ ) { /* i を 0 〜 9 迄変化 */ /* i++ は i = i + 1 と同じ */ sum = sum + i; /* sum に i の値を加える */ printf ( "%d %d\n", i, sum ); /* i と sum を出力 */ } printf ( "最終的には sum = %d\n", sum ); return 0; }
$ ./sample-006.exe 0 0 1 1 2 3 3 6 4 10 5 15 6 21 7 28 8 36 9 45 最終的には sum = 45 $
Download : sample-007.c
/* * 2020/10/16 sample-007.c */ #include <stdio.h> /* * for 文を利用して、0 から 9 の数値を表示する * プログラムを while に書き直す * * 利用方法 * コンパイル * cc -I ~/c/include -o sample-007.exe sample-007.c * 実行 * sample-007 */ int main(int ac, char *av[] ) { int i; /* for 文の制御変数 */ /* 元々のプログラム for ( i = 0; i < 10; i++ ) { printf ( "%d\n", i ); } step-1 <初期化式> を前にもってくる i = 0; for ( i < 10; i++ ) { printf ( "%d\n", i ); } step-2 <再初期化式> を、繰返し文の後にもって行く i = 0; for ( i < 10 ) { printf ( "%d\n", i ); i++; <= { 〜 } の一番最後 } step-3 for を while に書き換える i = 0; while ( i < 10 ) { printf ( "%d\n", i ); i++; } */ /* 元々のプログラム for ( i = 0; i < 10; i++ ) { printf ( "%d\n", i ); } */ i = 0; while ( i < 10 ) { printf ( "%d\n", i ); i++; } return 0; }
$ ./sample-007.exe 0 1 2 3 4 5 6 7 8 9 $
Download : sample-008.c
/* * 2020/10/16 sample-008.c */ #include <stdio.h> /* * for 文では、条件式がサボれる * * 利用方法 * コンパイル * cc -I ~/c/include -o sample-008.exe sample-008.c * 実行 * sample-008 */ int main(int ac, char *av[] ) { for ( ;; ) { /* while では条件を省略できないが for 文ではできる .. */ /* 条件が省略されると、「常に真」になるので無限ループ */ /* プログラムを停止させるには * Ctrl-C ([Ctrl] キーを押しながら [C] キーを押す) * を押す。 */ printf ( "動いています...\n" ); } return 0; }
動いています... 動いています... 動いています... 動いています... .... 動いています... 動いています... 動いています... 動いています... 動いてい^C
Download : sample-009.c
/* * 2020/10/16 sample-009.c */ #include <stdio.h> /* * for 文を利用して、0 から 99 の偶数の数値 * アプローチ * (その一) i を 0 〜 99 として、但し偶数だけを出す * * 利用方法 * コンパイル * cc -I ~/c/include -o sample-009.exe sample-009.c * 実行 * sample-009 */ int main(int ac, char *av[] ) { int i; /* for 文の制御変数 */ for ( i = 0; i < 100; i++ ) { /* i を 0 〜 99 迄変化 */ /* 但し、i が偶数の時だけ → if 文を利用する */ if ( i % 2 == 0 ) { /* i を 2 で割った余り(i%2)が 0 */ /* 即ち i が偶数の時.. */ printf ( "%d\n", i ); /* i を出力 */ } } return 0; }
$ ./sample-009.exe 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54 56 58 60 62 64 66 68 70 72 74 76 78 80 82 84 86 88 90 92 94 96 98 $
/* * 課題 CNAME-02 * * 20201016 20201016-02-QQQQ.c * * 0 〜 99 の偶数を出力する * */ #include <stdio.h> /* * for 文を利用して、0 から 99 の偶数の数値 (そのニ) i が 0 〜 99 の間の偶数だけを動くようにし、毎回 i を出す 0, 2, 4, .. ^^^ +2 */ int main(int ac, char *av[] ) { int i; /* for 文の制御変数 */ for ( i = 0; i < 100; i = i + 2 ) { /* i++ だと i = 0, 1, 2, .. */ /* ○○とすれば i = 0, 2, 4, .. */ printf ( "%d\n", i ); /* i を出力 */ } return 0; }
/* * 課題 CNAME-02 * * 20201016 20201016-02-QQQQ.c * * 0 〜 99 の偶数を出力する * */ #include <stdio.h> /* * for 文を利用して、0 から 99 の偶数の数値 (その一) 0 ? 99 の数値 : 100 個 偶数は、100/2 = 50 => 50 個出力する */ int main(int ac, char *av[] ) { int i; /* for 文の制御変数 */ for ( i = 0; i < 50; i++ ) { /* i = 0, 1, 2, .., 49 */ /* 2*i = 0, 2, 4, .., 98 */ printf ( "%d\n", 2*i ); /* 2*i を出力 */ } return 0; }
#include <stdio.h> /* 階乗の計算 (帰納的の定義) 1 ( n = 0 / n = 1 ) n! = { n * (n-1)! ( n > 1 ) 3! = 3 * (3-1)! = 3 * 2! = 3 * ( 2 * (2-1)! ) = 3 * ( 2 * 1! ) = 3 * ( 2 * ( 1 ) ) = 3 * 2 * 1 = 6 */ /* 階乗の計算の再帰版 * 数学の帰納的に定義された関数定義を、 * そのまま C 言語の関数再帰的定義 * で表現できる */ int fac ( int n ) { if ( n > 1 ) { /* n > 1 の時 */ return n * fac ( n - 1 ); /* n! = n * (n-1)! */ /* fac(n) = n * fac(n-1) */ } else { /* n <= 1 ( n = 1, 0 ) */ return 1; /* fac(1) = 1 */ } } int main(void) { printf ( "3! = %d\n", fac(3) ); printf ( "6! = %d\n", fac(6) ); return 0; }
#include <stdio.h> /* 階乗の計算 (帰納的の定義) 1 ( n = 0 / n = 1 ) n! = { n * (n-1)! ( n > 1 ) 3! = 3 * (3-1)! = 3 * 2! = 3 * ( 2 * (2-1)! ) = 3 * ( 2 * 1! ) = 3 * ( 2 * ( 1 ) ) = 3 * 2 * 1 = 6 */ /* 階乗の計算の繰り返し (while 構文) * n! を計算するには、1 から n まで、の自然数を順に掛け算する * 1 * 1 * 2 * 1 * 2 * 3 * ... * 1 * 2 * ... * n * 「* k 」を何度も繰り返す */ int fac ( int n ) { int result = 1; /* 最終的な答え(階乗の計算結果)を保持する変数 */ /* 最初は result = 1 にしておいて、 これに、順に n, n - 1, n - 2, .. をかけてゆく */ printf ( "Start: n = %d, result = %d\n", n, result ); while ( n > 1 ) { /* n > 1 の時 */ printf ( "Pre: n = %d, result = %d\n", n, result ); result = result * n; n = n - 1; printf ( "Post: n = %d, result = %d\n", n, result ); } printf ( "Result: n = %d, result = %d\n", n, result ); return result; } int main(void) { printf ( "3! = %d\n", fac(3) ); printf ( "6! = %d\n", fac(6) ); return 0; }
#include <stdio.h> /* ユークリッドの互助法で 二つの自然数(0 を含む) m,n の最大公約数 (m,n) を求める (m,0) = m (m,n) = (n,m % n) m ( n = 0 の時 ) gcm(m,n) = { (n,m % n) ( n > 0 の時 ) */ int gcm ( int m, int n ) { if ( n > 0 ) { return gcm ( n, m % n ); } else { return m; } } int main(void) { printf ( "gcm(12,18) = %d\n", gcm(12,18) ); printf ( "gcm(111111,111) = %d\n", gcm(111111,111) ); return 0; }
#include <stdio.h> /* ユークリッドの互助法で 二つの自然数(0 を含む) m,n の最大公約数 (m,n) を求める (m,0) = m (m,n) = (n,m % n) m ( n = 0 の時 ) gcm(m,n) = { gcm(n,m % n) ( n > 0 の時 ) 注意 : m % n は m を n で割った余り */ int gcm ( int m, int n ) { int w; /* work (作業用)変数で、変数の値を書き換えるときに */ /* 代入文を利用すると、変数の値が書き変わり、 以前の値が失われるので、それを避けるため使う変数 */ printf ( "(m,n) = (%d,%d)\n", m, n ); while ( n > 0 ) { /* gcm(m,n) <= gcm(n,m % n) m <- n n <- m % n */ w = m; /* 現在の変数 m の値を保存 */ m = n; /* m <- n */ n = w % n; /* w には、上の代入文の前の m の値が入っている */ printf ( "(m,n) = (%d,%d)\n", m, n ); } return m; } int main(void) { printf ( "gcm(12,18) = %d\n", gcm(12,18) ); printf ( "gcm(111111,111) = %d\n", gcm(111111,111) ); return 0; }
#include <stdio.h> /* 階乗の計算の繰り返し (for 構文) n! = n * (n-1) * .. * 2 * 1 */ /* while => for 1) while を for に書き換える 2) while の前に必ず、実行する命令がれば、<初期化式>に書く 3) <継続条件式>はそのまま 4) <繰返し文>の中で、変数を更新しているものを、 <再初期化式>の所に移動 */ int fac ( int n ) { int result; for ( result = 1; n > 1; n = n - 1 ) { /* for 構文の頭部に、繰り返しに関する情報が集約される */ result = result * n; /* 本体の部分は、主計算の部分だけ */ } return result; } int main(void) { printf ( "3! = %d\n", fac(3) ); printf ( "6! = %d\n", fac(6) ); return 0; }
#include <stdio.h> /* 階乗の計算の繰り返し (for 構文) n! = n * (n-1) * .. * 2 * 1 */ /* for 構文を使った別の例 */ int fac ( int n ) { int result = 1; int i; for ( i = 1; i <= n; i = i+1 ) { /* i = 1, (i が一ずつ増える), n ( i = n + 1 になったら終わり ) */ /* <繰返し文> の部分が n 回実行される */ result = result * i; } return result; } int main(void) { printf ( "3! = %d\n", fac(3) ); printf ( "6! = %d\n", fac(6) ); return 0; }
#include <stdio.h> /* for 構文の利用例 */ void nhello ( int n ) { int i; /* for 構文の制御変数とする */ for ( i = 1; i <= n; i = i + 1 ) { /* n 回繰り返す */ printf ( "Hello, World\n" ); } } int main(void) { printf ( "Start:\n" ); nhello ( 3 ); printf ( "Middle:\n" ); nhello ( 6 ); printf ( "End:\n" ); return 0; }
#include <stdio.h> /* for 構文の利用例 */ void nhello ( int n ) { int i; /* for 構文の制御変数とする */ for ( i = 0; i < n; i = i + 1 ) { /* n 回繰り返す ( i = 0, 1, .., n - 1 ) */ printf ( "Hello, World\n" ); } } int main(void) { printf ( "Start:\n" ); nhello ( 3 ); printf ( "Middle:\n" ); nhello ( 6 ); printf ( "End:\n" ); return 0; }
#include <stdio.h> /* for 構文の利用例 */ void nhello ( int n ) { int i; /* for 構文の制御変数とする */ for ( i = 0; i < n; i++ ) { /* i++ => i = i + 1 と同じ */ /* n 回繰り返す ( i = 0, 1, .., n - 1 ) */ printf ( "Hello, World\n" ); } } int main(void) { printf ( "Start:\n" ); nhello ( 3 ); printf ( "Middle:\n" ); nhello ( 6 ); printf ( "End:\n" ); return 0; }
#include <stdio.h> /* フィボナッチ数 0 ( n = 0 ) fib(n) = { 1 ( n = 1 ) fib(n-1)+fib(n-2) ( n > 1 ) n 0 1 2 3 4 5 6 fib n 0 1 1 2 3 5 8 */ int fib ( int n ) { if ( n > 1 ) { /* n > 1 の時 */ return fib(n-1)+fib(n-2); /* fib(n) = fib(n-1)+fib(n-2) */ } else { /* n <= 1 ( n = 1, 0 ) */ return n; } } int main(void) { printf ( "fib(3) = %d\n", fib(3) ); printf ( "fib(6) = %d\n", fib(6) ); printf ( "fib(40) = %d\n", fib(40) ); return 0; } /* fib(6) = fib(6-1) + fib(6-2) = fib(5) + fib(4) = fib(5-1) + fib(5-2) + fib(4-1) + fib(4-2) = fib(4) + fib(3) + fib(3) + fib(2) = fib(3) fib(2) fib(2) fib(1) fib(2) fib(1) fib(1) fib(0) = fib(2) fib(1) fib(1) fib(0) fib(1) fib(0) fib(1) fib(1) fib(0) fib(1) fib(1) = fib(1) fib(0) fib(1) fib(1) fib(0) fib(1) fib(0) fib(1) fib(1) fib(0) fib(1) fib(1) = 1 0 1 1 0 1 0 1 1 0 1 1 = 8 再帰的に定義すると 同じ計算を何度もやることになる => 効率が悪い # 同じ計算をする部分を、意識せずに、関数の定義ができる # => わかりやすさ ( 無駄を許す事により、単純になって、分かりやすい ) 再帰と非再帰は、「どちらかを使う」ではなく、 「両方使う」と考える 最初にプログラムを考えるときには、 (一般的に..) 再帰の方が簡単(考えやすい..)ので、 それでやる そして、次に効率の事を考えて (一般的に..) 非再帰の方が効率が良いので、 それに書き換える => 最適化を行う プログラム 正しく動いて、効率が良い事が望ましい */
#include <stdio.h> /* フィボナッチ数 0 ( n = 0 ) fib(n) = { 1 ( n = 1 ) fib(n-1)+fib(n-2) ( n > 1 ) n 0 1 2 3 4 5 6 fib n 0 1 1 2 3 5 8 */ int fib ( int n ) { int i; int f; /* 今のフィボナッチ数 */ int f1; /* 一つ前 */ int f2; /* 二つ前 */ if ( n < 2 ) { return n; } else { /* n >= 2 */ /* 最初 n = 2 の時は */ f2 = 0; f1 = 1; for ( i = 2; i <= n; i++ ) { /* 今のフィボナッチ数の計算 */ f = f1 + f2; /* 次のは、i が一つ増えるので、f1, f2 の値を更新 */ f2 = f1; f1 = f; /* 一つ前、二つ前をそれぞれ更新 */ } } return f; } int main(void) { printf ( "fib(3) = %d\n", fib(3) ); printf ( "fib(6) = %d\n", fib(6) ); printf ( "fib(40) = %d\n", fib(40) ); return 0; } /* 非再帰版(while/for 版) 一度計算した値を変数に保存して、 変数を参照する事により、同じ値を(再度計算せずに..)利用できる => 変数に、計算結果を保存し、 その同じ変数を何度も参照することにより、 無駄(同じ値を求める複数の[重複した])計算を省く事ができる */
#include <stdio.h> /* トランプの番号の表示をしたい 1 ? 13 1 ? 10 数札 => 数値 11 ? 13 役札 => 11 -> J 12 -> Q 13 -> K */ void ptrump( int n ) { if ( n < 1 ) { printf ( "?" ); } else if ( 13 < n ) { printf ( "?" ); } else if ( n < 11 ) { printf ( "%d", n ); } else if ( n == 11 ) { printf ( "J" ); } else if ( n == 12 ) { printf ( "Q" ); } else if ( n == 13 ) { printf ( "K" ); } /* else {} この状況になることはない */ } int main(void) { int n; for ( n = 0; n < 15; n++ ) { printf ( "%d : ", n ); ptrump ( n ); printf ( "\n" ); } return 0; }
#include <stdio.h> /* トランプの番号の表示をしたい 1 ? 13 1 ? 10 数札 => 数値 11 ? 13 役札 => 11 -> J 12 -> Q 13 -> K switch 構文版 */ void ptrump( int n ) { switch ( n ) { /* 条件の対象が n の値 */ case 1: /* n == 1 の時 */ case 2: /* n == 2 の時 */ case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: /* n == 10 の時 */ printf ( "%d", n ); break; /* いったん処理は終了(switch 構文は終了) */ case 11: /* n == 11 の時 */ printf ( "J" ); break; case 12: printf ( "Q" ); break; case 13: printf ( "K" ); break; default: /* 上記以外の値 */ printf ( "?" ); break; } } int main(void) { int n; for ( n = 0; n < 15; n++ ) { printf ( "%d : ", n ); ptrump ( n ); printf ( "\n" ); } return 0; }
前回の内容 while 構文 与えられた命令を、繰り返し実行する 関数の再帰的定義をする while ( 繰り返し条件 ) { 繰り返し命令 } 繰り返し条件 : 変数を含む条件式 繰り返し命令によって、 条件式に含まれる変数の値を変更(代入)して、 (結果として..) いつかは条件が成立しなくなるようにする必要がある 「代入を繰り返す」ための構文 cf. 再帰では、「代入」は(明示的には)現れない # 目的が実現されるまで、その作業を繰り返しする # 代入を繰り返し => 変数の値を、目的の値に近づけてゆく # <= 十分に近い(答えそのものになったら).. 繰り返しを終了 while 構文の応用 数値計算 (解析的発想:答えの近似値の精度を高めて行く) 解析的(厳密に「等号が成立する」=誤差を含まない答えを得る手段)に解けない場合でも、 近似的(誤差を含むかもしれない..)値を得る(数値的に解く) 例: sin(x) = 1 となる x を求めよ、 x = sin^{-1}(1) 二分方法 答えの範囲を半分半分にしてゆき、答えのある場所を探す 範囲は、1/2 になってゆくので、どんどん小さくなるが、 有限回しかできないと、区間の幅が残る => 幅 = 誤差 # 数値計算を利用する立場 # 誤差の有り無し、問題の解ける解けないをトレード # 誤差の大きさ、実行時間のトレード 数値積分 面積を求めるために、一度に求めるのではなく、 少しずつ、加えてゆく ( 求積法 ) # 数学 # ∫_a^b f(x) dx = F(b) - F(a) while 構文の考え方 変数の値に近似結果を入れ、 それを更新(近似度を高める..)事により、 より、精度の高い(答えに近い)値に変数の値を近づけてゆく 十分に近いなら、終了する ( 繰り返し条件 ) == for 構文とは 繰返しを記述する構文規則 ( cf. while ) for ( <初期化式>; <継続条件式>; <再初期化式> ) { <繰返し文> } # cf. # while ( <継続条件式> ) { <繰返し文> } 初期化式 : 最初に一度だけ、必ず行われる文 継続条件式 : 毎回、繰返し文の実行「前」に評価され これが偽の場合は終了(<繰り返し文>は実行されない)になる 繰返し文 : for 構文によって繰り返される命令 再初期化式 : <繰り返し文>の実行の「後」に毎回「実行」される 構文の実行状況 while ( <継続条件式> ) { <繰返し文> } <継続条件式> => 真 <繰返し文> <継続条件式> => 真 <繰返し文> .. <継続条件式> => 偽 終了 for ( <初期化式>; <継続条件式>; <再初期化式> ) { <繰返し文> } <初期化式> <継続条件式> => 真 <繰返し文> <再初期化式> <継続条件式> => 真 <繰返し文> <再初期化式> .. <継続条件式> => 偽 終了 for 構文と while 構文は、一方を他方の代わりに使える for 構文を利用すると、 「繰り返す」ための作業 繰り返し条件に含まれる変数 ( 制御変数 ) にかかわる記述 変数 => 初期化が必要 => <初期化式> 繰り返しなので、(制御変数を含む)条件式 => <継続条件式> 条件を終了させるために => 変数の値の更新 => <再初期化式> => for 構文では、 制御変数の処理が、一か所にまとめられるので (まとめておけば..) 繰り返しの様子が一目でわかる 「繰り返す」作業 の二つを分離できる インクリメント/デクリメント演算子 変数の値を 1 だけ増やしたり減らしたりする演算子 「++」: 変数を 1 だけ増やす => 「i++」 は、「i = i + 1 」と同じと思って良い 「--」: 変数を 1 だけ減らす => 「i--」 は、「i = i - 1 」と同じと思って良い for 構文では、<再初期化式> の所で、よく利用されている 「for ( i = 0; i < n; i++ ) { .. }」は、 「.. を n 回繰り返す」というイデオムになっている == 「繰り返し」 手段 a) 代入を使わない 関数の再帰的定義 b) 代入を使う while 構文 for 構文 a) と b) の使い分け 数学的に考えたい ( <= 数学の知識を利用してプログラムを書きたい ) => 再帰の方がよい (関数型言語的表現) 効率を高めたい / 変数の代入による手続型言語的表現 => while / for == switch 構文 条件分岐 ( if 構文 ) if 構文 => 二分岐 ( 条件が成立 / 不成立 ) switch 構文 => 一つの式の値が、複数の候補のどれかに一致する => 多分岐 => if 構文を複雑に組み合わせれば、 (ほぼ) switch 構文と同様な機能が実現です switch - case 構文 機能 多分岐構文 ( if 文は 2 分岐だが switch は n 分岐 ) 構文 <switch 文> ::= switch ( <式> ) { <case 並び> } <case 並び> ::= <case> の繰返し <case> ::= <label> : 文並び <label> := case <定数> | default ※1 一つの <switch 文>内には、同じ <label> を含める事はできない ※2 文並び中に break 文があり、それが実行されると、switch 文は終了する 意味 もし、「式」の値が「定数」の何れかであれば、そのラベル以下の文を実行する そうでなくて、もし、defualt があれば、そのラベル以下の文を実行する そのいずれでもなければ、何もしない
課題プログラム内の「/*名前:ここ*/」の部分を書き換え「/*この部分を完成させなさい*/」の部分にプログラムを追加して、プログラムを完成させます。
Download : 20201016-01.c
/* * 課題 CNAME-01 * * CDATE FILENAME * * キーボードから一文字入力し、その文字によって異る国の挨拶をする */ #include <stdio.h> /* * hello ( char contry ) * char contry : 国を表す一文字 * j : 日本 * e : 英語 * c : 中国 * f : フランス語 * g : ドイツ語 */ void hello ( char cmd ) { switch ( cmd ) { case 'j': /* 'j' の時は、日本語にする */ printf ( "こんにちは\n" ); break; case 'e': /* 'e' の時は、英語にする */ /* ** この部分を完成させなさい */ break; case 'c': /* 'c' の時は、中国語にする */ printf ( "ニイハオ\n" ); /* ** この部分を完成させなさい */ 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; }
f
$ ./20201016-01-QQQQ.exe 国を表す文字を入力してください j 日本 e 英語 c 中国 f フランス g ドイツ Bonjour $
Download : 20201016-02.c
/* * 課題 CNAME-02 * * 20201016 20201016-02-QQQQ.c * * 0 〜 99 の偶数を出力する * */ #include <stdio.h> /* * for 文を利用して、0 から 99 の偶数の数値 (そのニ) i が 0 〜 99 の間の偶数だけを動くようにし、毎回 i を出す */ int main(int ac, char *av[] ) { int i; /* for 文の制御変数 */ for ( i = 0; i < 100; /* p:ここ */ ) { /* i++ だと i = 0, 1, 2, .. */ /* ○○とすれば i = 0, 2, 4, .. */ printf ( "%d\n", i ); /* i を出力 */ } return 0; }
$ ./20201016-02-QQQQ.exe 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54 56 58 60 62 64 66 68 70 72 74 76 78 80 82 84 86 88 90 92 94 96 98 $