前回(2021/05/21)の内容 複雑な数学パズルを、再帰を用いて解決する 順接/条件分岐/再帰の万能性の現れ => プログラムの万能性 計算の結果が、現実に反映さえられる仕組みがあれば、 「計算の結果で、すべての事ができる」という意味で、 計算機(で表現できるプログラム)は、万能性を持つ <= 現実でできない事は、計算機でもできない 再帰的に問題を解くパズル ハノイの塔 砂漠の旅人 => 前回の課題は、後でやる 「数学」と「アルゴリズム」 数学的な「ものの考え方」が問題を解く鍵(アルゴリズム)になる => おいおい紹介したい 文字と文字列 文字とは : ASCII Code 表に記載されたもの(キーボードから入力可能な半角文字) 文字列とは : 文字の 0 個以上の並び 文字の表現 : 「'(シングルクォート)」で「一文字」を挟む 文字列の表現 : 「"(ダブルクォート)」で「文字の並び」を挟む 文字の出力 : putchar 関数を利用する 文字列の出力 : printf 関数を利用する 文字の計算 : +1/-1 すると、ASCII Code 表の一つ後、一つ前の文字になる 文字列の計算 : +1 すると、先頭の文字が削られ、長さが短くなる 文字列から文字を取り出す方法 文字列の頭に「*(アスタリスク)」を付けると、先頭の文字が取り出せる 文字列の後ろに「[N]」(N=0〜)を付けると、N+1 番目の文字が取り出せる 文字列[N] <-> *(文字列 + N) 空文字列と空文字(NULL 文字 : '\0' ) 空文字列 : "" *"" <= 空文字列の先頭の文字 => NULL 文字 実は、長さ N の文字列は、N + 1 個の文字からなっている 例 : "abc" = { 'a', 'b', 'c', '\0' } => 文字列の、最後の文字は、常に NULL 文字 ('\0') "" = { '\0' } *"" => '\0' 空文字列("")かどうかを判定するには、 その先頭(*をつけた結果)が、NULL文字('\0')かどうかで判定できる p-008.c => myprinf を作った => 文字列の中文字を、いっこずつ処理する手段になっている 例: myprintf は、個々の文字を、単に出力する この考え方を応用すれば、色々な事ができる 例: 指定された文字列(英大文字からなる)を小文字に変換して出す [分割コンパイル] 関数の定義を複数のファイルに分けて、個々にコンパイルし、 リンクによって、一つ実行ファイルを作るという方式 !! 一つのファイルに、すべての関数定義を記述してもよい !! => もし、同じ関数を、異なるプログラムで使いたい場合 !! もし、プログラムを一つのファイル内で利用するならば、 !! 同じ関数を、複数のファイルに記述する必要がある 分割コンパイルを利用する事により、 一つ関数(定義)を、複数のプログラムで共有できる [ポイント] 同じ関数の定義を、色々なプログラムで共有する場合には、 その関数の定義を一つのソースコードに分離し、 分割コンパイルし、あとでリンクでつなぐ事が望ましい !! printf/putchar のような「ライブラリ関数」も、 !! 実は、別に記述されていて、リンク時に繋がれている !! !! <= コンパイルとリンクが異なる作業である理由 == 12345 <= たくさんのものを処理 1 2345 <= 先頭と、残りに分ける 個別に処理する 12345 / | 1 2345 / | 2 345 / | 3 45 /| 4 5 最初に先頭を処理して、 後から残りを処理する 処理(1) 1 の結果 処理(2345) 2345 の結果 12345 <- [1] / | 1 2345 <- [3] [2] / | 2 345 <- [5] [4] / | 3 45 <- [7] [6] /| 4 5 [8] [9] 結果 : [2], [4], [6], [8], [9] 1 2 3 4 5 <= 正順 最初に残りを処理して、 後から先頭を処理 処理(2345) 2345 の結果 処理(1) 1 の結果 12345 <- [1] / | 1 2345 <- [2] [9] / | 2 345 <- [3] [8] / | 3 45 <- [4] [7] /| 4 5 <- [5] [6] [5] 結果 : [5], [6], [7], [8], [9] 5 4 3 2 1 <= 逆順 全体を分けて、 頭と残りの二つにする 処理の対象を 頭が先で、残りを後と処理すると 結果的に、頭からひとつずつになる(正順) し、 残りを先で、頭を後に処理すると 結果的に、尻からひとつずつになる(逆順) という性質がある(事が証明できる)ので、それを利用している