先日は、
にてC言語を使用してみましたが、その中で
■ Hello,World!の表示
■ iostreamとstdioの違い
■ コーディングとコンパイル
について書きました。基本的にどのOSでも共通していますが、プログラミング言語をインストールした場合には、ターミナルなどを使用してコマンドで実行するので、コーディングの最小構成は
■ メモ帳
■ ターミナル
と言う組み合わせになります。Linuxの場合だと、ターミナルとVIMを開いて画面分割をすることで
■ VIM
■ ターミナル
■ パフォーマンスモニター
などを用意できますが、ターミナルの設定で
【 現在のカレントディレクトリで開く 】
ことも出来るのでターミナルを開いてcdコマンドでディレクトリを移動して作業フォルダーを選択しておいてviを立ち上げてから作業を行うと 【 :w ファイル名.拡張子 】 でファイルの記録を行った場合、作業用フォルダーに記録されます。この状態でターミナル分割表示にしてターミナルを開くとカレントディレクトリが選択されるので、作業用フォルダが選択されているので、ここでコードのコンパイルや実行を行うことが出来ます。
ホームフォルダーからの操作だと相対パスを使用してファイルを指定するとコンパイルや実行ファイルの実行が出来るようになります。
コーディングについては、
の中でターミナルで行っていますが、これと同じことがVIMでも行えます。
プログラミング言語のインストール
プログラミング言語はインストールしないと実行できませんが、OSには何かしらのプログラミング言語が実装されているので、導入後からコーディングを行えるようになっています。
基本的にどのOSにもWEBブラウザはプリインストールされているので、
■ HTML
■ XML
■ CSS
■ ECMA Script(Java Script)
を使用できるようになっています。これは、デスクトップアプリを作るのと同じ状態になるので、
■ M : XML
■ V : HTML/CSS
■ C : ECMA Script
で行うことになりそうですが、ファイル操作は出来ないもののメモリー内に記録したデータだけで動作するものを作る場合だと動くものを作ることが出来ます。ECMA Scriptは、外部ライブラリを使用できるので
■ NODE.js
■ JSON
などを使用すると、ローカルサーバ機能やファイル操作ができるようになったり、汎用性のあるデータを扱えるようになります。また、
■ Three.js
のようにGLSLを使用したコンテンツを作れるものもあるので、ライブラリで拡張するといろいろなことが出来るようになっています。この辺りはPythonと同じですが、こうした環境はどのOSでも体験できるようになっています。
Linux環境の場合だとディストリビューションによって収録されているものが異なるのですが、開発者用のディストリビューションの場合だと様々なプログラミング言語がインストールされています。
WINDOWS環境だと、.NET Frameworkを有効にするオプションがあるので、これを使用すると.NETを利用できるようになります。これは、
■ C#
■ VB.NET
■ j#
などのコンパイラを使った作業が出来るようになりますが、Hyper-Vなどと同様に通常はオフ担っていることが多いので、オプションで有効にする必要があります。
このように最初から使用できるものだと、
■ テキストエディタ
■ ターミナル
を使うことで作業を行うことが出来ますが、殆どのプログラミング言語はインストールされていないので、インターネット経由でダウンロードしてインストールする必要があります。
学校で使用する
■ Scratch
■ Python
などもそうですが、
■ C言語
■ C++
■ JAVA
■ RUST
■ DART
■ RUBY
■ PHP
などもインストールされていないのでこうしたプログラミング言語を使用できるようにソフトウェアをインストールする必要があります。
WINDOWSの場合だとインストーラーが用意されている場合が多いのですが、
■ 実行ファイル(.exe)
■ 実行ファイル(.msi)
の形で配布されている場合が多いのですが、Linuxの場合だとターミナルからコマンドでインストールすることになります。
WINDOWSでのC/C++
WINDOWS環境ではC/C++はそのままでは実行できないので、Linuxコマンドが使用できる状態にする必要があります。この時に使用するのが、
■ Cygwin
■ MinGW
になりますが、Cygwinだと大丈夫でMinGWではサポートしていないものもあるので、その条件で使用する場合には、Cygwinを使用することになります。この環境をインストールするとWINDOWS上でLinuxの小納戸が使用できるようになるのでgccやg++が使用できるようになります。
この時にコンパイルを行うと、OSとアーキテクチャに依存した実行ファイルが生成されますが、Linuxなどとは事なり、 【 a.exe 】 が生成されます。この実行ファイルはSmallBASICやコンパイル後のC#の実行ファイルと同じようにそのままダブルクリックで実行することが出来ますが、Linuxと同様にリネームすることで名称の重複を回避することが出来るようになっています。
Linuxの場合だとショートカットと言う名称はありませんが、ランチャーは配置できるので、ダブルクリックだけで実行するような仕組みはワークステーション版として配布されているものだと昔から存在しているのですが、WINDOWS環境のようにそれと同等の挙動のものが自動生成されることはありません。
その為、Linux環境だと少し異なる処理を行わないとそうした物を作ることが出来ない仕様になっています。
WINDOWS 7辺りだと、Virtual PCのクライアントがProfesshonal以上のグレードで用意されていたので、XPモード以外にクライアントを新規に追加してLinuxをインストールするとLinuxが動作するので、Linuxの環境でソースコードのビルドを行ってLinuxの実行ファイルを生成することも出来たのですが、クロスプラットフォームのかそうか環境だと 【 Virtualbox 】 などもあるので、こうした環境を使用すると感想化環境で
■ Debian
■ RHEL
■ BSD
などを個別にインストールして使用できるのでそれぞれの環境を試すことも出来るようになっています。と言っても、
■ Lilo(32bit)
■ GRUB(64bit)
が使用できるので、ブートローダーでOSの選択をして使用することも出来るようになっていますが、OSSのOSの場合だと、ライセンス料がかからないので、仮想化環境にインストールして気軽に試すことが出来るようになっています。現在のようにSSDがメインストレージになっている環境だとOSの区画に書き込みが集中するのはいただけないので、仮想化を使う場合だと、スピンドルの数を増やす(GPUのレーン数を減らしてSSDにレーン数を振る)ようにして運用するか、速度が低下するもののDASやNASを使用するとOSの入ったSSDの書き込み容量を少なくすることが出来ます。
OS区画のリカバリーは少し煩雑ですし、作業から考えると無駄な時間になりますから、なるべく、この作業が発生するまでの期間を長くしたほうが良いので、
■ ホストOS
■ ゲストOS
のような感じで同時にOSの起動が生じるような条件だとゲストOSの動作時のテンポラリーファイルなどは別のストレージに逃したほうが良いので、VMのイメージはストレージの外に持っていったり、余計な書き込みはWINDOWS環境だとOSの入ったSSDに密集しない夜にする必要があります。
DASもUSBの速度が向上しているので、結構速度が出るようになっていますが、流石にNVMe(GEN4)のSSDのような速度は出ないのパフォーマンスは下がりますが、個人のPCでOSの入ったSSDを換装して 【 システムのリカバリーを行う 】 となると結構な作業量になりますから、速度を気にしない場合だとDASやNASに仮想環境を構築してそのストレージから動作させると言う方法もあります。
WINDOWS 10以降だと
■ Hyper-V(Pro以上)
■ WSL2(全てのバージョン)
で使用できるので、Hyper-Vクライアントしか存在しない無印のWINDOWS環境でも設定を行えばWSL2は使用できるので、Linuxを動かせるようになっています。これは、CUIですから、ターミナルでの作業のような状態になりますが、この環境でUbuntuなどをインストールするとLinuxコマンドを使用してLinuxの実行ファイルをビルドすることが出来るようになります。
その為、C/C++環境の実行ファイルを作成する場合、
【 WINDOWS用実行ファイル(a.exe) 】
■ Cygwin
■ MinGW
【 Linux用実行ファイル(a.out) 】
■ 仮想化(VirtualBoxやHyper-Vなど)
■ WSL2
を使うことになります。
WINDOWSでのコーディング環境
OSにはカーネルを守るシェルが用意されており、動作の根幹をなすカーネルにアクセスするためにシェルコマンドを使用します。WINDOWSの前身はDOSなので、DOSコマンドが使用できる状態になっていますが、32bitアーキテクチャになった時に広報互換のために16bitの環境でも動作する仕組みが用意されていました。
これが、DOS窓になりますが、その後、NTカーネルになってからは、コマンドプロンプトが使用されるようになり、WINDOWS 7では
■ 実行方法の選択
■ 仮想化
と言うアプローチで広報k互換が担保されている状態になっていました。その為、DOSコマンドでsyロイを行えるようになっていたのですが、WINDOWS 10では、
■ PowerShell
■ コマンドプロンプト
を使用できるようになったので、DOSコマンドとは別にPowerShellが使用できるようになっています。
このPowerShellは、自動化をする為のシェルの統合開発環境なので、コマンドのヘルプと候補の表示も行ってくれる仕組みになっていますが、PowerShell SEと言う統合開発環境も用意されています。これはコーディングで必要な
■ コーディング
■ デバッグ
が可能な構造になっているので
■ テキストエディタ
■ ターミナル
を実装した構造になっていますから、PowerShell SEを開くだけでコードを書いて実行できる仕組みになっています。
環境変数
実行ファイルを生成した場合にはアプリケーションのある場所を指定してファイルの実行を行いますが、基本的にはこの仕様になっているので、通常は全く同じ処理をターミナルで実行することになります。
プログラミング言語は、ファイルの実行と同じ状態で使用するので、PowerShellで書いたコードを実行する場合でも、
【 ./相対パス/プログラミング言語名 ファイル名 】
で実行することになります。これは、Pythonも同じですが、コンパイル型言語の場合だとこの形でコンパイラを使用してビルドを行うことになります。
この状態だとひたすら長い相対パスを指定することになるので、DOSの時代からこのエイリアスを少t略する機能として 【 環境変数 】 が用意されています。
WINDOWS環境では、
■ プログラミング言語のインストール
■ 環境変数の登録
をすることで、Pythonだと
【 ./相対パス/python3 ファイル名.py 】
のようになるものを
【 ./python3 ファイル名.py 】
のようにして実行できるようになりますが、この記述をjdkやgccやg++でも行えるようになります。
Pythonのインストーラーだと環境変数のチェックを入れるようになっていますが、これを入れていない場合だと前述のようにコンパイラやプログラミング言語の実行時に常に相対パスを記述する必要がでてしまいます。
Scratchのようにアプリケーション自体が動作するものだとインストール後にそのまま使用できますが、ターミナルで動作させるようなものだとWINDOWSの場合だと環境変数を登録しておいたほうが作業が行いやすくなります。
この機能はDOSの時代から損刺し居ているので、DOSカーネルの時代の古いWINDWSでもこうした機能がしようできるようになっています。
C++と表示
C++は、C言語よりも変数の取り扱いがしやすいので、初期の学習で%Sなどを用意してそこに変数を代入するような記述を用いなくても大丈夫な仕様になっています。
先日も書きましたが、C++では、
【 STD::COUT<<"文字列" 】
の形で文字の表示が出来るので、バッファのフラッシュを行う必要がない場合だと、
【 STD::COUT<<"文字列"; 】
だけで文字の表示を行うことが出来ます。先日は文字列でしたが、数値も簡単に表示できるので
のような記述で数値なども扱えます。処理の内容は、
になりますが、
のように文字列の表示を行うだけでなく、
のように数字の指定も可能で、
のように文字列と数値を組み合わせることも可能です。
この状態だとプロンプトとつながってしまうので、【 \n 】 で改行をして
のようにg++を使用してコードをビルドして
のように実行すると
のように
■ 文字列
■ 数字
■ 文字列+計算結果
を表示することが出来ます。このように、C++では、 【 << 】 で接続することで型の変換なしに文字と数値の結合を行うことが出来るようになっています。
このコードでは、 【 算術演算子 】 を使用して数式を実装することで、計算結果を表示していますが、こうした物を文字列と結合する場合には、
■ 文字列
■ 数値
になるので、Pythonだと
【 print("1+1=" + str(1+1) 】
のような形にする必要がありますが、C++の場合だと【 << 】で接続するだけで表示を行うことが出来るようになっています。
変数と定数
先程の事例では、coutで表示するものをそのまま指定していましたが、先程の算術演算子を指定し処理の場合、変数で管理したほうが扱いやすくなります。C++では、
■ 変数
■ 変更できない値
■ 定数
が存在しており、目的の状態に合った記述を行うことになります。変数はそのまま表記できるのですが、コード内で変更しないようにする場合には、変更しない設定を行うことになります。これが、
■ 変更できない値
■ 定数
になります。数学だと両方とも定数になるような気がしますが、コード内でその状態にする場合には、
【 const 】
を用いることになります。これは、ECMA Scriptでも使用しますが、コードを書く際に
■ 変数 : let
■ 固定 : const
を使用します。この2つを使用すると再宣言と再代入の条件をコントロールできるのですが、letで宣言するとブロックスコープがかかり、varのように何でも大丈夫と言う状態ではなくなります。ただし、変数なので、再代入が出来るのですが、constを使用すると、初期化の後に再代入を行うとエラーが発生します。
この機能はPythonには実装されていないのですが、C++には実装されています。
その為、初期化の後にコード内で変更が生じないようにする場合には 【 const 】 を用いることになります。これとは別に、C++では、定数が存在していますが、これは値の固定がコンパイル時に行われると言う特性があります。
この時に使用するのが 【 define 】 になりますが、今回はこれは割愛します。defineはプリプロセッサへの処理の一つになりますが、プリプロセッサは、コンパイル前に処理を行うプログラムの事を指します。
コンパイル時の前処理として、マクロ名で指定した文字列を定数や式で置き換えます。この置き換えのことを
【 マクロ置換(または、マクロ処理) 】
といいますが、この処理を行う際にdefineを使用します。
defineは、
【 define マクロ名 定数や式 】
で指定するので、constなどと同じような記述になりますが、この処理はマクロなので、コンパイル時に値は全て書き換わる仕組みになっています。
また、defineの場合、
■ 関数
■ 複数文からなるマクロ
の指定も出来ます。
その為、コードで書いた場合には、constなどと殆ど同じ宣言方法になりますが、C++の学習の初期段階だと、
■ 変数
■ const
を使い分けるような使用方法が登場すると思います。
ちなみに、列挙型というものが存在しており、 【 enum 】 を使用することで複数の値を宣言できますが、C++では、この機能に加えてスコープありの 【 enum class 】 というのもあります。
変数の宣言
C言語では、変数を指定する時に
【 型 変数名=リテラル 】
と言う形になっていましたが、C++でも同じ形で宣言します。先程のコードを変数に置き換えると
のようになります。数値型については、int型なので
のようになりますが、文字列はPythonのようなstr型はない(string.hをインポートすると文字列型を使用できます。)ので、iostreamだけだとC言語と同じように文字配列を使用することになります。
配列は、Pythonのリストと同じなので、 【 変数名[] 】 で初期化ができるのですが、この状態を宣言して値を代入することで、文字列を扱うことが出来るようになっています。この際に使用するのが文字型のchar型になります。
これはASCIIコードの番号で文字の組み合わせで使用できる1バイトのデータになっているので、そのままだと1文字しか使用できないので、配列を使うことで複数の値を格納して使用することが出来るようになっています。
配列の場合、Pythonのリストと同じ構造になりますが、Pythonのstr型も文字配列を組み込み関数で使用できる構造になっているようで、str型でリテラルを用意した場合には、
【 変数名[インデックス] 】
の指定を行うと変数内のインデックスの位置の文字を抽出することが出来ます。
C++では、文字配列を使用できるので、
のように変数の指定が出来ますが、この2つの記述は、
■ 変数の宣言
■ 値の代入
を一つの記述で行っています。この記述を 【 初期化 】 と言いますが、constやdefineの場合だと代入や再代入と言う概念がないので、こうした物を使用する際には、 【 初期化を使う 】 ことになります。
そして、この変数を使用する場合も、C++は簡素な記述になっているので、
のように 【 << 】 を使用してcoutで表示するように指定することになります。このコードを
のようにコマンドでコンパイルを行って
のように実行すると
のような結果になります。このように、
■ 文字列
■ 数字
■ 変数
のように異なるものを使用する場合でも、C++の場合だと、coutに対して<<で接続するだけで出力できる仕様になっています。
constを使う
constは値の変更が出来ませんからコード内では、固定した状態で使用するものに使用します。デスクトップアプリだとウインドウサイズやUIの位置で使用しますが、コンソールアプリだと配列の大きさなどで使用します。
例えば、テトリスのミノには形がありますが、この場合、
■ 空間
■ 非空間
の場所が存在します。これは、0と1で指定できるようになっていますが、この範囲指定をする際に、ミノのサイズが必要になります。と言っても、この形状は 【 幅が2 】 という条件で統一されているので、
■ 2×2
■ 2×4
という形のものが存在していることになります。つまり、2×2のモジュールが連結された構造と考えることが出来ます。テトリス棒は1×4ですから、【 (0×4)+(1×4) 】 と考えることが出来ますし、凸の形のものは、3つですから、【 (0×2+1+0)+(0+1×3) 】 のようなパターンと考えることが出来るわけです。こうしたパターンはゲーム中では形が変わることはない(変わるとゲーム性が変わってしまうのでこれは変化しません。)ので、この状態はプログラムの中で変更しない状態で絵固定することになります。
こうした 【 アプリケーション内で変更しないもの 】 については、数学の定数のように明確な値の状態で固定しておく必要があります。この時に使用するのがconstやdefineなどになります。
constは、const修飾子になりますが、これを変数の先頭に付与することで、指定した変数名のリテラルの変更ができなくなります。書式としては、
【 const 型 変数名=リテラル 】
となります。この形は、 【 初期化 】 になっていますが、これを
const 型 変数名
変数名=リテラル
のように変数の宣言と代入のような形で行うとエラーになります。また、
const 型 変数名=リテラル
変数名=リテラル
のように初期化をした後にconstで指定した変数に値を再代入してもエラーになります。先程のコードの変数をconstに書き換えると
のようになりますが、この状態にすると、コード内での値の変更を行えなくなります。