以下は、1,2 限の間の休み時間い整備する CST Portal の今日のページ 本日の課題 [先週(2019/06/14)の内容] 文字型 (小さな整数 : ASCII Code) C 言語では、「文字」を小さな(1 byte : 0 〜 255) の整数値で扱う 「文字」と「数値」の関係 => ASCII Code 表で # 1 byte で区別可能な文字 256 通りなので.. # 半角の英数(大文字/小文字)、いくつかの(算用)記号しか表現できない # => 日本語の漢字など、表現できない # <= 「漢字」を表現するには、2 byte 以上の数値で対応付けが必要 # SJIS : 「全角(漢字・ひらがなを含む)」は 2 byte # UTF-8 : 3 byte 必要 ## 計算機で文字が扱えるのは、 ## この「コード化(情報と数値を1-to-1 対応付けする)」があるから 「文字」に関しては、「半角のみを扱う」 「日本語」に関しては、UTF-8 で「文字列」でのみ扱う 整数型 整数値( - 2^{-31} 〜 2^{31} -1 の範囲 ) を扱う int 型 普通に四則、あまりの計算、比較演算など可能 # 他にもいろいろあるが... => 調べてください 分割コンパイル 一つのプログラムが複数の関数から作ら得ているとき 関数単位で、複数のファイルに分けて記述可能 # ファイルを分割する最小単位は、関数より小さくできる.. => 個々にコンパイル(分割コンパイル)して、実行ファイルを作成する時 つまり、リンク時に、まとめて一つにする事ができる <= 再利用が可能(メリット) => 作業が増える(デメリット) # 工学(情報)では、何かを得くすると、何かを失う make と Makefile <= 分割コンパイルの手間を減らしてくれる # 「Makefile を作る」という小さなコスト(代償)で... => Makefile には、いろいろな事がかけるので、積極的に利用するとよい # ライブラリ(他者の作った関数)を利用する場合など... ## 技術や情報:コピーできるとよい ## Makefile は、「作成手順」というノウハウを「コピー」する手段になっている 「鉄則」 「Makefile があったら make する」 [本日の内容] 2019/06/07 の資料 コマンドライン処理 1. コマンドを実行する時に、「コマンドライン」で、「コマンドライン引数」を指定できる 「コマンドライン引数」は、個々の引数は「空白で区切られた『文字列』」 2. main 関数の引数である argc で引数の個数 + 1 を argv[k] で、引数そのものの「文字列」を得る事ができる コマンドラインは、プログラムに対する「(通常は『人間』による)入力」となる !! 常に『人間』は「間違う」可能性がある => コマンドライン引数がいつも適切に指定されるとは限らない => エラー処理(正常でないような入力に対しても、(それなりに)適切に対処)する事を考える コマンドラインでのよくある問題 1. 個数が不適切かも => 多いか少ないかという話なので、典型的な対応が可能 基本 : エラーメッセージを出力して「プログラムを終了」させる 2. 指定した内容が不適切かも => プログラム固有の問題なので、それぞれに個別に対応する エラー処理 プログラムが正常に動かない場合が起きる可能性がある 例 : 割り算をしたいのに、割る数に 0 が指定された 例 : 長さ 3 の文字列に、その長さ以上の数を加えた 文字列から、数を引く その場合に、 事前に、その場合に対して、「問題が起きにくい対処」を行う 特に、「エラーメッセージを出力してプログラムを『異常終了』させる」 事が「最低限度の処理」 C 言語では、exit 関数を用いる事により、 「プログラムの終了とエラーコードを返す事ができる」 # エラーコードは、exit 関数の整数値の引数で、 # 「0」は正常終了(エラーでない)が、「0 以外」は「エラー終了(異常終了)」と # 解釈される ! exit 関数を利用する場合は、 ! #include ! も加える 課題 20190607-01 20190607-01-QQQQ.c を 201905031/hanoi に保存 <= hanoi を使うので、「makefile」が使いたい コンパイルの仕方 make clean <= 本来は不要なはずだが、今回はミスで、「必要」らしい make BASE=20190607-01-QQQQ start ./20190607-01-QQQQ.exe 12345 <= 高さ 5 のハノイを解く hanoi ( f, t, w, size ) 高さ k+1 のハノイの塔は hanoi ( f, w, t, size + 1 ); 高さ k のハノイを塔をどかして s_hanoi_move( f, t ); 幅 k の円盤を移動してから hanoi ( w, t, f, size + 1 ); 高さ k のハノイの塔を乗せる 再帰呼び出しの良い ( (単純な) 繰り返しではない .. ) # 「数学的な考え方」の例 (復習) 関数のへの整数引数 「仮引数宣言では、『char *』でなく『int』」を指定 1. 今までは無条件に「char *」だったが、ちゃんと、書く規則がある # 「無条件」ではない => 「条件付き」 2. 整数の引数の場合は「int」を使う # 「文字列」の場合は、「char *」を使う 3. 「仮引数宣言(関数の引数の宣言)」には意味がある # 「いろいろなパターンがある」=> 「意味がある」 # => 他にもパターンがあるかもしれない... 「仮引数宣言」の『意味』 関数の引数に指定されるデータの種類(「型」)を指定してしている why ? エラーチェックなどの「サービス」が受けられる [実験(p-004.c)] 整数の引数の所に(敢えて、誤った..)文字列を指定 p-004.c:25:11: warning: passing argument 1 of ‘subfunc’ makes integer from pointer without a cast [-Wint-conversion] コンパイル時に「warning(警告)」が出る note: expected ‘int’ but argument is of type ‘char *’ [意訳] 本来「整数型(int)もの」が要求されているのだが、 しかしながら、実際には、引数に「文字列型(char *)」のものが指定されている !! subfunc は、引数に「整数型」の値を指定しないと、適切にふるまわない !! 引数の「型」を明示する事により、「誤りを自動検出」している !! # コンパイラが、コンパイル時に「この変数宣言の情報を利用して」エラーチェックする !!!! C 言語が「強い型」の言語である事を意味する !!!! 変数には、その変数の型と同じ型の値しか代入できない(してはいけない) !!!! => コンパイル時にエラーや警告が出る !!!! 「制約」 !!!! cf. python は、「タイプフリー」な言語で、変数にはいろいろなデータがいれらる !!!! => 例 : 同じ変数に、整数や、文字列や他のものも自由にいれられる !!!! !!! 「自由」!!! !!!! !!! <= 自己責任 !!!! => 「制約」がある => 「情報がある」=>「コンピュータがサービス可能」 !!!! => C コンパイラは、「エラーチェック」 C コンパイラは、 関数の仮引数変数の宣言を利用して、「エラーチェック」をしてくれる [実験(p-005.c, p-005-01.c)] 関数の部分を分離した(分割コンパイルしたい..) => p-005-01.c のコンパイルは問題ない p-005.c のコンパイルは、 「note」がなくなった # せっかくのエラーチェック機能が働いていない. エラーチェック(というサービス)を受けるためには、 関数の仮引数宣言の情報が必要 一つのファイルの中で、関数の呼び出し元と呼び出し先があれば、 自動的にチェックされる # 呼び出される側をファイルの先頭に置く必要がある # => 逆だと、呼び出したところで、警告が出る もし、ファイルを分けたい(分割コンパイルしたい)場合は プロトタイプ宣言を、関数を呼び出す側に残す事によって実現 プロトタイプ宣言は関数の型を示したもので、 記述法法は 「関数の宣言の頭部」の前に「extern」(後ろに「;」)を付ける 関数定義(A)と関数呼び出し(B)がある [ A=B をチェックしたい ] 1. 同じファイル内で、定義が呼び出しの前にあれば OK A, B がともに同じファイル内なのでチェック可能 2. 定義と呼び出しが別なら、呼び出しの前に、プロトタイプ宣言(C)をする A, C がともに同じファイルに内なので、チェック可能 # C と B が同じという保証は ? 3. まず、プロトタイプ宣言の記述を単独のファイルに記述 p-006.h (D) 呼び出し側で、#include する A=D チェックは OK # D と B の関係は不明 関数の定義側でも #include する # D と B のチェック ## A=D, D=B --> A=B のチェック可能なる *.h ヘッダファイルには、「関数宣言をまとめてある」 => 分割コンパイル時にも、エラーチェックが可能になる