先日は、
の記事にてifの判定について書きました。
条件分岐を実装する場合、定数ではなく変数のほうが解りやすいのでscanf関数を使うことになりそうですが、ifで判定を入れることが出来ます。ちなみに、scanf関数はPythonのinput関数と同様にコンソールでの入力待ちを実装できるので、バッファに文字を格納してEnterキーで確定して変数に代入するような仕組みになっています。Pythonもprint関数で同じような記述が出来るように鳴っていますが、これを使うことで、数字の入力が出来ます。C言語では、文字型しかないので1Byteの数値のデータをキャラクターコードに割り当てて使用することになりますから、char型を使うと1文字しか扱うことが出来ません。
その為、 【 文字配列 】 を使って配列と言う形で複数のデータを格納することによって文字の集合である 【 文字列 】 を扱う仕様になっています。
scanfとprintfを使用するとPythonのinputとprintを使った処理と同じことが出来るので、
のようなコードを書いて実行すると
のように最初にprintfで指定した文字が表示され、その後、scanfが実行されるので、入力待が発生します。ここで
のように数値を入力すると
のようになります。これが、入力したものを表示するための処理になりますが、これが初期化された数値であったとしても
【 指定された文字を表示するだけ 】
ですから、決まった処理を行うだけのものに鳴ってしまいます。つまり、直列回路と同じ構造になっているので、判定という概念が存在しません。
入力を粉うと必ず 【 値の状態 】 が存在するので、 【 判定の条件 】 を用いることで、その値と対比してあhン亭によって処理を変えることが出来ます。
この時に使用するのが分岐になりますが、この条件で10以外だと異なるという表記をする場合だと、
【 変数の値≠10 】
の条件を用意して、処理を実装売ればいいので、
【 変数の値!=10 】
で処理を行って、その判定に対してprintfで表示を行うことになります。
この場合、
のようなコードですが、
の部分で 【 ≠ : ノットイコール 】 の判定を行っています。これを実行すると
のようになります。これが、【 事前に例外を除去した場合の処理 】 になりますが、これを逆にして一致の条件で処理をするようなコードを書くと
のようになりますが、ここでは、【 一致 】 の条件を指定しているので、【 等号 】 で判定を行っています。
これを実行すると
のように以外のものは問題がないのですが、一致所農研だと
のようになります。これは、コードの構造が順次の形に鳴っているので、スケジュールのように上から順番に処理を行っているので、判定の結果が出た後にその後の処理が実行されるのでこのような形になります。
処理の方法としては、 【 除外の判定を入れるだけのほうが簡素に条件を見つけることが出来る 】 ので、通常は、 【 除外対象を先に持ってくる 】 とコードを簡素に出来ます。
これが、数値の判定をする際に階調の判定をする前に 【 0の除外の判定 】 を行って、その条件と階調が組み合わさった時に値を取得するような作りにすれば、
【 0以外 】 ∧ 【 数値の値 】
という条件になるので、0以外の数値であり、かつ、存在する値を取得できるようになります。この判定方法は電気を使う時に使用しますが、通電の状態に0の判定を入れると難しいので、通電なしの状態を最初に除外しておけば、 【 何かしらの絶対値が取得できる 】 ので数値の階調を取得できます。中学一年生の数学では、最初に符号を学習しますが、この時に 【 0から見た時の数値の大きさ 】 である絶対値を一緒に学習します。この値を取得すると、符号の有無で正と負の変化を与えることが出来るのですが、これは、
■ 数直線 : 移動の向き
■ 回 転 : 回転方向の向き
を変更できます。中学校の数学では、πは円周率で使用するので、それをしっかりと覚えることを前提にカリキュラムが進むので、この段階では、図形で使用する 【 円周率 】 という認識で問題はありません。ただし、この 【 3.14159265358979323846264338... 】 のような数値は、 【 数直線上で示すことが出来る 】 ので円周の公式を変形させて 【 半径1の円の円周 】 を2πとして使うことで360度という分度器でしか使えない物を定規の世界に持ってくる方法を使用することになります。これが 【 弧度法(こどほう) 】 というものになります。
高校の数学の三角関数を使うと単位円が登場するので、弧度法を使うことになりますが、これを用いることで、角度を数値として式に導入して計算することが出来るようになります。義務教育で使用する角度は、分度器で図れるものになっていますが、この形を 【 度数法(どすうほう) 】 と言います。ちなみに、
■ 度数法 : °
■ 弧度法 : rad(ラジアン)
で示しますが、ラジアンは省略するので、πを基準とした表記になります。関数電卓やプログラミング言語でもこの2つを使い分けることになりますが、
■ 度数法 : Degree(デグリー)
■ 弧度法 : Radian(ラジアン)
という名称になっています。弧度法は 【 180° = π 】 なので、360°で2πですから、
■ 一回転 : 2π
■ 方 向 : 符号で制御
をすることが出来るので、モーターの角度を180°を上限として左右の回転で制御をするような仕組みにする場合、πまでの数値に対して符号で制御をすると、左右の向きの変化をコントロールすることが出来るようになります。これに対して、回転の場合往復運動になると困るので2πの状態をループさせることになります。この2πだと係数がついているので、この状態を扱う際には、360度を示す 【 τ (タウ) 】 を用いることになります。
このように符号を使うと色々なことが出来るのですが、
【 符号の状態 】 ∧ 【 値 】
で判定をすることで、符号濃霧を制御できるので、数値の判定をする場合には少なくとも階調の判定以外に
■ 0の除去
■ 符号の有無
の判定を用意することになります。これが、機械で動かす場合に考える方法になりますが、今回のように同じ処理をする場合でも判定の方法が異なると、別の処理を実装して最適に動作させる必要が出る場合もあります。今回のコードだと、
■ 不一致 : ループ
■ 一 致 : 処理の実行
という判定をするためのスイッチとして使用できるものになりますが、今回の事例で使用した 【 一致の条件で判定をしたい場合 】 には、コードの書き方が少し変わってきます。
▼ ここから
分岐を行う場合、一つの条件ではなく、複数の条件で分岐を行うこともあります。その時に使用する方法として、
■ if ~ else
■ if ~ else if ~ else
があります。
if ~ else ~
判定を行う際に、
■ 判定条件
■ 判定条件以外
で別の処理を行いたい場合がありますが、その時に使用するのが、
if ~ eles ~
の形になります。
例えば、scanf()で入力を行った時に
■ 一 致
■ 不一致
の判定をする場合、
■ 一致の条件で判定
■ 不一致の条件で判定
を用意しているので、ifが1つだけでは処理できません。その為、ifを2つ用意することになりますが、そういった記述をすると 【 コードがわかりにくくなる 】 ので、プログラミング言語では、
【 一つの判定の流れ 】
として判断できるようにifが連続しないように記述できるようになっています。
この時に使用するのが、 【 if ~ else ~ 】 の構文になります。
通常のifは
になりますが、elseを使う場合には、新規にelse用の判定を追加します。その為
のような形になります。
C言語では、main関数を用意してその中に処理を実装するような仕組みになっているので、こうした判定もmain関数の中に記述します。その為、
のような形で実装することになります。
サンプルコード
if ~ else ~ を使って
のようなもの青作ってみました。実行してみると
のようになり、 【 if ~ else ~ 】 でしっかりと数値の判定が行われています。
コードの概要
コードの概要ですが、C言語なので入出力を行うためにstdio.hを使用する必要があるので
のようにstdio.hをincludeしています。C言語ではPythonの組み込み関数のようなものでもライブラリから読み込む必要があるので、includeを行う必要があります。
その為、Pythonのimportを使った標準ライブラリの読み込みと同じ事を組み込み関数レベルのものでも行う必要があります。
C言語では、main関数の中に処理を実装するのでmain関数を実装することになりますが、この際に
型 関数名(引数){}
の形にする必要があるので、
のような形で宣言します。ここでは整数型のint型を使用してmainと言う名前の関数を作っており、引数としてvoidを指定しています。voidは値のない状態を示すものになりますが、このmain関数はコードを格納するためのものなので、C言語では、この構造を作ってその中に処理を記述することになります。
今回のコードでは、変数を使用するので、
のように変数aと変数bを用意しています。この2つでは記述が異なりますが、前者は、型と変数名の指定のみ行っていますが、これがが 【 宣言 】 でメモリーアドレスと型による容量の指定のみを行うものになっています。その為、この段階では変数の値が存在しません。
後者は宣言+値の代入を行っていますが、この記述の事を 【 初期化 】 になります。
コード内では、
■ 変数a : scanfの変数
■ 変数b : 判定用の変数
として使用しています。scanfは何も表示されませんから、入力をする場合には、入力待ちで何をすればいいのかを表示したほうが解りやすいのでprintfで文字列を表示しています。
そして、その後に、入力待ちを作るので、scanfを実装します。
C言語では、
■ 代入先
■ 代入する値
を用意して使用することになりますが、この形は、printfとscanfで同じ構造になっています。
Pythonだとformatメソッドが似た構造になっていますが、引用符で囲んだものの中の代入指定子に対して変数を代入することで使用することが出来るようになっています。scanfでは変数の前に 【 & 】 を付けることになりますが、この後の変数名に対してscanfで入力した値を代入出来るようになります。
scanfは、Pythonのinput関数と同じく、 【 バッファに記録する 】 形の入力になります。その為、 【 Enterキー 】 でバッファの内容を指定したメモリーの区画に記録する形になっています。
入力を行うと変数に値が存在するので、ifで判定を行うことが出来ます。その為、
のような形で判定を実装することが出来ます。これは単一の判定で実装する形になりますが、別の判定を入れる場合には、この後にifを追加しても処理を実装できますが、コードの内容的に構造がわかりにくくなるので、elseを使用します。
ifも関数と同じく 【 処理を包含した構造 】 になっていますから、ブロック内の処理には 【 ; 】 で処理の単位で分けることになります。
ブロックを持った構造は 【 {} 】 で範囲を指定することになりますが、関数と同様にこの構造の後に 【 ; 】 は入らない仕様になっています。
この状態で以上の指定が出来たので、
のように未満の判定を実装しています。このように 【 if ~ eles ~ 】 の構造にするとifの判定の構造で複数の判定を行う部分であることを目視で確認できるので、このような記述を用いることになります。Scratchの場合はブロックの形が違うので目視で判断できますが同様の処理を実装できるようになっています。
コンパイルと実行
プログラミング言語は人のわかる形の文字列で記述を行いますが、機械は電気の通電の有無を最小単位とした構造で動作しています。つまり、スイッチの状態で挙動の制御を行っているので、高水準言語のように言語に近い形の状態では理解が出来ません。その為、機械のわかるニ進数に変換したものを扱うことになりますが、この時の方法が、プログラミング言語によって異なります。
1970年代だとアセンブリ言語とFortrunが存在していますが、アセンブリ言語ではわかりにくい部分を処理の内容を見てわかるようになったのがFortrunになります。しかし、言語の体系が違いますから、Fortrunではコンパイルが必要になりますが、こういった高水準言語では、一旦全てを機械語に翻訳して使用する作りになっています。この時の処理がコンパイルになりますが、このコンパイルを行って機械語に一括翻訳をする形のものを 【 コンパイル型言語 】 と言います。
インタプリタが多言語は遅いので、メモリーアドレスにデータを直接読み書きできるPOKEやPEEKのようなコマンドが用意されていましたが、
C言語はコンパイル型言語になるので、コードを書いた後にコンパイルをする必要があるので、
のようにgccを使ってコンパイルをすることになりますが、この際に-oのオプションを付けてリネームを行っています。コンパイル自体はgccだけで行えるので、
gcc ファイル名
で実行ファイルが出来るのですが、コンパイルやリンクを行ってビルドをした場合、同じファイルが生成されるので、コンパイルするたびにファイルが上書きされてしまいます。また、どのファイルもa.out(WINDOWSの場合はa.exe)になるので、区別がつかないので、リネームをすることになります。ビルドが終わると
のようにソースコードと実行ファイルが生成されるのですが、この際に
のように
./ファイル名
と言う形で実行するとビルド済みのファイルが実行されます。
この記述はカレントディレクトリにファイルがある状態ですから、海藻が違うファイルの実行をする場合には相対パスでファイルの位置を指定して実行することになりますが、ライブラリのリンクがない条件だとこうした簡素な記述で実行ファイルを作ることが出来ます。
C言語やC++はネイティブなので、CPUのアーキテクチャが異なると命令セットが違うのでコンパイルしたあ^きてくちゃでなければ動かないのですが、OSが違うと生成される実行ファイルも違うので、 【 ビルドと実行する環境のアーキテクチャとOSを揃える 】 必要があります。これを解消する方法としてはクロス開発をする方法がありますが、ネイティブと比較すると遅くなる傾向があります。
JAVAや.NETはVMで動くようにコンパイルしてそれをVM上で動かすので、命令セットがVM用になっています。その為、ネイティブのようにアーキテクチャやOSによって実行するファイルが異なるということはありません。ただし、速度がネイティブよりも遅くなる場合があるのと処理の方法でおSくどが変わるので、構造を考えてコードを書く必要があります。
また、こうした仮想型の環境はメモリー消費量が肥大化しやすいと言う特徴もあります。