先日は、
にて変数とconstを使った変数の取り扱いについて書きました。
C++では、std::coutを使用することでPythonのprint関数やC言語のprintf関数のように文字の表示が出来るのですが、変数の取り扱いがC言語よりも行いやすくなっているので、変数を使用する際にも
■ std::cout<<文字列
■ std::cout<<数値
■ std::cout<<変数
のような形で代入できるようになっています。また、基本的な文字列は、文字配列を使用する部分はC言語と同じなので、
■ char 変数名[]=”値”
で指定できるようになっています。変数を指定する際には、変数のように変更可能なもの(あとで、演算処理で変更できるもの)と、コード内での変更を行わないものに分けることが出来ますが、値を固定する際に使用するのがconstになります。
constはJava Scriptにも存在していますが、Java Scriptの場合だと、
■ 変数 : let
■ 定数 : const
のような使い方が出来ます。定数と言うよりは、変数の条件の指定と考えたほうが良いのですが、constを使用するとブロックスコープ(関数などの処理を包含するブロックに包含されている場合、外部からの参照などができなくなる仕様)だけでなく、
■ 宣言
■ 代入
のような代入処理が行えなくなります。その為、constで指定を行った場合には宣言ではなく、
■ const int a=10
のように 【 宣言+値の代入 】 の形で使用することになります。この方法を 【 初期化 】 と言います。
入力待ちを使う
C言語で表示を行う際には 【 std::cout 】 を使用すると 【 << 】 を使用することで何でも接続して表示が出来るようになっていますが、変数を使用すると様々な値を使用できるようになります。
と言っても、内部処理だけだと自動処理になるので、変数の初期化で確定した値を指定しておいて、そこから、演算などで値を変更するしかありません。
もしくは std::cout で接続して
■ 文字列同士の結合
■ 文字列と数字の結合
などをして使用することになります。これが、自動処理ですが、ここに 【 操作 】 を導入すると数がくで使用する 【 変数a 】 のように不確定な状態を作ることが出来ます。
高校の数学の記述にすると、変数を使用した一変数関数の場合、 【 f(x)=x 】 のような状態になります。これを中学校一年生で学習する関数の形にすると 【 y=x 】 となるので、数直線上の数値の変化と全く同じものになります。
この時に 【 f(1) 】 とした場合、変数xに1を代入した状態になりますから、先程の関数だと 【 f(1)=1 】 になります。
このように 【 変数xに値を代入した場合 】 の条件を作る場合、この書式が登場した際のテストの問題として登場するのは、
【 変数が確定している時の関数の値を求めるもの 】
になりますから、
【 問題 】
f(x)=3x+9 の時の解を求めよ
【1】 f(1)
【1】 f(3)
【1】 f(9)
のような感じになりますが、出題されている状態は定数化した値が代入されているので、変数の値は変数xではなく、定数になっています。
プログラミング言語も初期化を行うとこのように定数を指定することになるので、値を使用して演算を行うと、定数の値を用いて演算処理を行うことになります。
アプリケーションの場合、
■ 自動処理
■ 操作が必要なもの
が存在しますが、変数の初期化と処理を実装しただけだと自動処理を行っているのと同じ状態になります。
これに対して操作を導入すると、入力値が変数化するので、任意の値を使用した処理を実装することが出来ます。
エンドユーザーが使用しているものはGUIを使った環境で操作をするものになっていますが、内部処理はCUIなので、基本を学習する際にはターミナルで動作するものを学ぶことになります。
GUI環境については、JavaScriptと考え方は同じなので、
■ イベントハンドラ
■ ウィジェットのValueの値
■ ウィジェットなどの状態変化
を扱うことになりますが、
■ 表示 : HTML
■ 装飾 : CSS
■ 制御 : JavaScript
で行っています。この時のウィジェットもHTMLでの配置になりますが、この時の値の参照や変化はウィジェットとコード内の変数のやり取りで成立しています。
その為、このやり取りをするコードを通常のコードに実装すればGUIでの処理にあるので、最初に処理部分乗り会をしないと何もスタートしないので、コーディングを行う際に学習するのはターミナルで動作するコンソールアプリになります。
流石に入門用のもので対象年齢が低いと言う条件になると、それだと難しすぎるので、ScratchやMakeCodeを使用したり、ブロックの使い方と処理の学習をするために、Hour Of CODEなどを使うことになります。
コンソールアプリでの入出力を行う場合、
■ キーボードでの入力
■ ターミナル上への表示
になりますが、最初に登場するのは 【 入力待ち 】 になります。
これは、どの言語でも実装されえているものになりますが、BASICインタプリタのINPUTと同じ機能のものになります。Pythonだとprint関数になりますが、C言語だとscanf関数に該当するものになります。
これを使用すると
■ 入力待ちなので流れが止まる
■ キー入力を行う
■ 入力した値がバッファに貯まる
■ Enterキーで確定
■ メモリー内にデータが格納される
と言う仕組みになっています。ちなみに、変数の初期化を行った場合、特定のアドレスから指定した型の容量文の区画が用意されるので、先頭のアドレスが、指定したアドレスで、そこから型の容量分だけの区画が用意されます。
データを扱う場合には、型の容量の範囲で値を使用することになりますが、初期化後には指定したアドレスから区画分だけの容量が配置されて指定した値が格納されます。
C言語やC++の場合には手動でのメモリー管理が出来るので、初期化と開放がかのうになっていますが、Pythonだとガーベージコレクタを使用するとメモリーの開放を行うことが出来ます。これをコマンドで実行するとコードの実行時に格納していたプログラムで指定した変数などの値をメモリーから消去することが出来るようになっています。
このように変数の宣言と入力待ちでは処理そのものが異なるのですが、C言語でも入力待ちを使用することで任意の値を代入して使用することが出来ます。
cinを使う
C++で入力待を使用する差には、
【 std::cin 】
を使用します。std::cinの書式ですが、
【 std::cin >> 変数 】
のような記述になります。coutが
【 std::cout << 変数 】
なので、対象が逆になっているので、【 >> 】 の向きも逆になっています。
【 出力(表示) 】
■ std::cout << 変数
【 入力待ち 】
■ std::cin >> 変数
実際にコードを書いてみると
のようになりますが、これを
のコマンドでコンパイルして
のコマンドで実行すると入力待になるので、
のように文字を入力して実行すると、
のようにエラーがでます。Pythonのinput関数などではこうした問題に遭遇しないのですが、C++の場合だと、文字配列ではutf-8の文字のコーディングの文字列を使用できないので、別の方法を用いることになります。
通常はこの部分を無視して英文字だけで対応することになりますが、日本語が使用できたほうがいいので、日本語の記述が出来るようにします。
stringを使う
日本語の文字列を使用する場合には、色々なホ言う方がありますが、記述が簡素でコード内に追加するだけと言う条件だと、 【 string 】 を使用する方法があります。
実際にコードを書くと
のようになりますが、
のように string を include することで文字列を使用できるようになります。コードを見てもらうと変数の宣言部分が
のようになりますが、stdのネームスペースを用意してstringを使用しています。この状態で
のようにコードをコンパイルして
のようにコードを実行すると
のように日本語のテキストを使用してもエラーが出なくなります。
usingを使う
c言語でコードを書くとネームスペースが前に来るので、同じような記述が頻繁に登場します。先程の
のコードを見ると
■ cout
■ cin
■ string
の前に 【 std:: 】 の表記が並んでいます。これは必要な記述なので省略するとエラーになりますが、このネームスペースを省略する方法も用意されています。
この時に使用するのが 【 using 】 です。使用する時の記述ですが
【 using namespace ネームスペース名 】
で指定することになりますが、実際に使用すると
のように処理の記述を簡素にすることが出来ます。このコード内では、 【 std:: 】 の記述が頻発していたので、
のようにstdを対象とすることで、
のように 【 std:: 】 の部分を省略することが出来ます。
このコードを
のようにコンパイルして
のように実行してみると、
のように入力待ちになり、
のように入力を行ってEnterキーで確定すると
のように文字列が破綻します。これは、文字列によって表示できるものとそうでないものがあるためですが、1バイト文字でもcinだと対応していない処理も存在します。
その為、 【 一つの文節 】 だと問題がないのですが、文を記述するとエラーが出ないが実行されるというバグ取りが大変そうな問題が発生してしまいます。
その為、単語レベルだとcinは問題がないのですが、万能ではない事を理解して使用する必要があります。
なので、cinを単独で使用する場合だと
【 cinの文字列は単語レベルのもの 】
と考えてコードを書くことになります。
C++のコードを書く場合
英語圏だとほとんど関係ありませんが、UTF-8の3バイト文字(SHIFT-JISだと2バイトでUTF-8だと3バイト)を使う場合だと、 【 string 】 が必要になりますが、ネームスペースが大量に発生する場合だと、 【 using 】 で省略することが出来ます。その為、コドの学習を行って完全な状態で呼び出しを理解した後だと、usingを使用して省略した状態で書いたほうが良いのですが、最初からusingが使用されているコードを見ても処理の方法の理解には至らないので、学習段階だとusingを使わないコードを書いて使い方を覚えることになります。
先程のコードは、
のような形にすることが出来ますが、このコードにはしっかりと、 【 return 0 】 が入っています。これがないとオーバーフローする(桁溢れが生じる)ので、必ず付与しておく必要があります。
先程のコードは、【 retrn 0がなくても実行可能 】 だったわけですが、オーバーフロー対策がされていないので、これも
【 問題があるのに、ごく当たり前に実行できてしまう
コードの一種 】
になります。
コードを書く場合、
を最初に記述すると、
■ ストリームの利用
■ stringの利用
■ ネームスペースの省略
が可能になります。その後、
のようにmain関数を用意してその中にコードを記述することになりますが、
のようにstring( 実際には std::string )を使用して変数の宣言を行うと日本語入力した文字列でも使用することが出来るようになります。
空白を含む場合
cinを使用すると 【 単語 】 は大丈夫ですが、スペースが入ると片方しか記録されません。単語のような文字列を入力して使用する場合には
■ 文字配列
■ 数値型
■ string
で変数を作成してcinを使用すれば大丈夫ですが、間にスペースが入るようなものだと別のものを使用しなくてはなりません。
この時に使用するのが 【 getline 】 になります。空白対策をするだけだと
【 getline(cin, 変数名) 】
で対応出来るのですが、これが 【 入力待ち 】 として機能するので、空白を含めた文字列を変数として扱えるようになります。cinの部分が処理で、変数名が格納先になりますが、コードにすると
のような感じになります。実際に使用してみると、
のように1バイト文字は問題がないのですが、日本語の場合だと、
のように句読点対策などが必要なので、別の処理を用いる必要があります。
cinの場合
cinを使用すると入力待が使用できますが、問題が出ないのは1バイト文字だけなので、日本語を使うとエラーが出ます。これは変数の型の問題になりますが、これを解消する場合には、stringを使用することになります。
1バイト文字の場合だと、getlineを使用すると空白を含めた処理が出来ますが、日本語だと特定の文字でおかしな挙動になるので別の対策が必要になります。