前回(2021/06/04)の内容 先週から二周目 一周目 C 言語の外観を学ぶ 一通りのこと ( 原理的には、できる事はすべてできるところまでやった ) 「できる事」:画面に文字列出力する => コーディング(実際の目的と 1 対 1 に対応する文字列を考える) => 任意の「実際の目的」に対応した「文字列」が出力できる 例: 1 進法 「自然数」を「文字列の長さ」で表現する手段(コーディングの手段の一つ) => 「自然数の計算」をするプログラム # 自然数の計算結果を表す 1 進法による文字列を出力する 二周目 改めて、C 言語を 0 から学びなおす => 計算機できることを C 言語で実現(表現)できるようにする 例: グラフィックス 「Hello, World」再び 最も単純なプログラム : Hello, World 差分プログラミング : 少しずつ修正を加えながら改良して行く 「Hello, World」の謎 御呪い:「#include」/「int」/「return 0;」は何をしている ?? 関数 命令列に名前をつけたもの 関数定義 : 命令に名前を付ける ( <= 関数が定義される ) 関数呼び出し : 関数名を利用して、その名前がつけられた命令列を呼び出す 一周目 : 関数を定義する手順を説明 二周目 : 関数定義の表現の部分部分の名前も説明した void func(void) { .. } ^^^^^^^^^^^^^^^ ^^^^^^ 関数頭部 関数本体 関数には、引数を付ける事ができる 文字を引数に持つ関数 一週目 : 引数として、「文字列」だけを例とした => 関数の仮引数変数の宣言のところでは「char *」という「おまじない」 「仮引数変数の宣言」 => 関数の引数の「型」を指定している 「型」: データの取りうる値の集合 + それを処理する演算の集まり 例 : 整数 <=> < { .., -2, -1, 0, 1, 2, .. }, {+,-,*,/} > => データの取りうる値の集合だけでは型を決められない 数学 : -> 「群」を作る事ことができる -> 「体」を作る事ができる !! 数学の色々な「空間」は、型の具体例になっている 関数の引数には型がある 関数を適用(関数を呼び出す)場合、 実引数には、それに適した「型」のデータを与える必要がある 例: printf の引数は「文字列」 putchar の引数は「文字」 !! 関数の引数には、(その関数が期待している..型の) !! 適切なデータを与える必要がある !! 数学 : 実数の平方根を求める関数には、非負の実数を与える必要がある !! => 関数の定義域 型宣言 (仮引数変数の char 宣言) 「型」: 値の集合だけでなく、その上での演算子も定めている [2021/06/11] 文字 出力 : putchar 関数を利用 <= 文字を引数関数の実例 入力 : getchar 関数 キーボードから一文字入力して、 その結果を返す関数 <= プログラムに対して、「入力」ができる => getchar関数により、プログラム内で、キーボードから入力された文字を扱う(計算の対象/情報処理の対象にする)事ができる getchar を利用する事により、 プログラムの基本パターンの一つ : 「入力->処理->出力」が可能に 文字の比較 条件分岐 ( 一周目でやった ) => 「条件によって、二つの命令のどちから一方を実行する」という表現 => if 構文 if ( 条件 ) { 条件が成立した時の命令 } else { 条件が不成立の時の命令(それ以外) } 「条件」 一周目 : !strcmp を利用して、「文字列の比較」をする !strcmp(A,B) 文字列 A と文字列 B が等しい文字列の時、 真(条件成立)となる 二周目 : 「文字」の比較のしかた 文字 A, B が与えられた時に A == B => A が B と等しい ( A と B が等しい ) A != B => A が B に等しくない A < B => A が B より(ASCII コード表の順番で..) 前 例 : 'A' < 'B', '0' < '1', 'A' < 'a' A > B => A が B より(ASCII コード表の順番で..) 後 A <= B => A が B 以下 A >= B => A が B 以上 関数の再帰的定義 一周目: 関数の定義の時に関数の本体で、自分自身を呼び出す 無条件に自分自身を呼び出すと、無限ループになる 一般的には(無限ループを避けるため)、 条件分岐を利用して、 自分自身を呼び出す場合とそうでない場合を作る => 自分自身を呼び出すときに、 引数の値を変更する事により、 最終的に、自分自身を呼び出さないようにする void rec( V ) { if ( V に関する終了条件 ) { 再帰しない } else { 何か ( 繰り返したい内容 ) rev ( V' ); <= 再帰呼び出しをするとき、 引数の値を変更し、 なんどか変更したら、最終的に、 Vに関する終了条件が成立するようにする !! 具体例: !! 引数の文字列を与え、 !! 再帰呼び出しをするときに、文字列の長さを短くする !! 終了条件を、「文字列の長さが 0 になる」にするよい !! cf. !! 数学的帰納法 !! 最初の条件が, n = 0 ( n = 1 ) !! n の値を一減らす !! \forala n \in N P(n) !! <=> !! P(0) !! P(k) -> P(k+1) !! <= !! P(3) ? !! P(3) <= P(2) !! P(2) <= P(1) !! P(1) <= P(0) !! P(0) } C 言語の関数 => 命令に名前をつけたもの cf. 数学の「関数」 定義域、値域があたえられていて、 定義域の任意の要素 x に対して、地域の要素 y を 対応すける規則の事 例: f(x) = x^3 定義域 : 実数 R 値域域 : 実数 R 対応規則 : x -> x * x * x を対応させる 関数の値 : 具体的な値に関数を適用した時の結果 f(2) = 2 * 2 * 2 = 8 !! これまで学んだ「C 言語の『関数』」は、 !! 引数は与えているが、その結果となる値は、不明(指定していない) !! 唯一、getchar() は、なんらかの値(キーボードから読み込んだ文字)を持つが、 !! 関数的なふるまいではない.. 実は.. C 言語の関数も、「値」を返す事ができ、 また、その「値」をプログラム内で利用する事ができる => 返り値をもつ関数(値を返す関数)の定義方法 返り値をもつ関数の定義の仕方 関数の頭部の一番前(これまでは void)に、 「返す値の型」を書き込む # void は、「値を返さない」という特別な意味 # cf. # 仮引数変数のところで「void」とかくと # 「引数が無い関数」の意味 # => 「void」=>「何かがない」 関数本体に return 式 命令をかくことにより、 関数の返り値(関数値)として、「式」の値が指定される return 命令を実行した時点で、関数は終了する C 言語の関数も、 数学の関数と同様に、 入力に対して、返り値を求める、規則をプログラムとして書く !! 普通の数学の関数と同様な関数を C 言語で実現する事ができる !! 関数の引数の型宣言や返り値の型宣言は、 !! (数学の関数における..) 定義域や値域を示している