この章ではswitch文で占いを作成します。
占いは毎回同じ判定では変なので、結果はランダムになるようにします。 初めにランダムな数をransuuに入れるのですが、このランダムな数を生成するにはrand関数を使用します。
rand関数は0か32767までの数字の中でランダムな数を返しますが、範囲を限定したい場合には例えばと書きますと1から6までのランダムな数を返すようになります。
0から6までの数値をランダムに返したいのならばと書きます。
しかし、このrand関数だけではプログラムを何回実行しても同じ結果にしかなりません。
これは乱数を初期化していないからです。
この乱数を初期化するにはsrand関数を使います。 srand関数は乱数の初期値を設定する関数です。
つまり、乱数に使う初期値を変える関数です。
例えばsrand(1)と書くと初期値が1、srand(2)と書くと初期値が2の乱数を導き出すことが出来ます。
では試しにを入れないで、rand関数を実行してみましょう。 この例の実行結果は以下の通りです。 ではもう一度実行してみましょう。
結果は以下の通りですが、1回目の結果と同じです。
rand関数はランダムに数値を導き出してくれますが、乱数になるのは1回だけです。 そこで違う乱数を導き出すためにsrand関数を使います。
次の例は先ほどの例にsrand(6)を追加しただけです。 結果は何度実行しても以下の通りです。 初期値を変えたので乱数の値は変わりましたが、この例のようにsrand関数の中の引数を固定した場合はいつまで経っても同じ値になります。
そこでsrandの引数にを使用します。
この中のtimeはtime関数で、1970年1月1日0時0分0秒からの経過時間を返します。
ですのでtime関数をsrandの引数に使うことで、その瞬間の時刻が引数に入りますので、その都度違う数値を引数に与えることができます。
time関数の引数はNULLにします。
time関数を使う時にはを記述する必要があります。 では占いの例に戻ります。
ransuuには0から6までの数値がランダムに入るので、それをswitch文で判断して、unsei変数に代入しています。
それを最後に出力します。
カテゴリー: C++
ポインタを使ってみよう
この章ではポインタについての具体例と配列のアドレスとポインタについて説明します。
以下の例は変数のアドレスを関数に渡し、ポインタ変数で受け取っている例です。 関数本体では以下のようにアドレスをポインタを受け取ります。 tashizan関数の中で*aと5を足して*aに代入し、*bと5を足して*bに代入しています。
*aには変数xのアドレスが入っているので、*aとxは同じ意味になります。
*bには変数yのアドレスが入っているので、*bとyは同じ意味になります。
つまり、*aは2と5を足して7になりましたが、*aが7になることによって、main関数の中のxが7に変わっています。
*bは4と5を足して9になりましたが、*bが9になることによって、main関数の中のyが9に変わっています。 次の例では配列のアドレスとポインタについて説明します。 もしくは以下のように書くことができます。 printf関数の変換指定文字を「%p」にして配列を出力すると配列の先頭のアドレスを取得することが出来ます。
つまり、配列のアドレスは配列の先頭の要素のアドレスになります。
つまり、配列名を書くだけで配列xの一番前のアドレスが取得出来ます。
と同じ結果はと書いても得ることが出来ます。
つまり、xと&x[0] (配列の先頭の要素のアドレス)はまったく同じアドレスです。
配列名でアドレスを取得するのとは違ってのアドレスを取得するには「&」を付けなくてはいけません。 それはのようにと記述してください。
xが先頭のアドレスを示すので、+1を付け加えることで先頭から一つアドレスを進めると言う意味になります。
つまり、と同じ意味になります。
は前から2番目のアドレスです。
*(x+0)と書くと配列の先頭要素を取り出すことが出来ます。
これを書き換えるととなります。
配列の2番目の要素を取り出すにはと書きます。
+1は先頭から一つアドレスを進めると言う意味になります。 結果は以下の通りです。次の例ではポインタの加算を使った値の書き換えの方法について説明します。 hairetsu(x);の箇所で配列xのアドレスをhairetsu関数のポインタ変数に渡しています。 hairetsu関数内で書き換えた結果、main関数の配列xの要素である「1,2,3」が「34,46,98」に書き換えられます。
先ほどの例をfor文を使って書き換えると以下のようになります。 次はポインタに関する演算について説明します。 この例ではポインタ *gに配列xのアドレスを入れています。
1 gにはxの先頭要素のアドレスが入っているので、「*」を付けることで1番前の要素を得ることが出来ます。
結果は4です。 g++;とありますが、これはポインタの指している位置を1つ先に進めると言う意味です。
ポインタを進めた後にと出力すると、前から2番目の要素の値である6を得ることが出来ます。
さらにポインタの指している位置を進めると8が得られます。
3 この箇所はポインタを戻しています。
ポインタをのように減算子を使って書くと、その時点のポインタから1つ後ろに戻る動作をします。
つまり8の時点から1つ下がるので6が得られます。
では次の例を見てみましょう。 これまでは配列のアドレスを関数本体に渡す時、ポインタで受け取っていましたが今度は他の方法で配列を関数に渡します。
hairetsu(x);のように配列のアドレスを渡すまでは同じですが、関数本体のほうはのように配列で受け取っています。
そして要素の数(3)だけ繰り返しループして、の結果をg配列に代入しています。
つまりg[i]のiに0から2までが代入され、その都度の計算結果が代入されることになります。 配列xと配列gはまったく同じなので(xもgも同じアドレスを示しています)、この例の結果は「10と10と10」になります。
では次の例に進みます。 仮引数にポインタを指定した場合、これまでは のように代入していましたが、実はこのような難しい表現を使わなくてものようにポインタにを付けて値を代入することもできます。
g[i]のiに0から2までが代入され、その都度の計算結果を代入します。 結果は「6と6と6」です。
次は文字列を扱う配列とポインタの関係について説明します。 配列の章で学習しましたが、文字列を配列で扱う時には型をcharにして、のように書きます。
と同じことをポインタを使って書き換えるとのように書くことが出来ます。
出力する時には もしくは と書きます。 ポインタを使ったのような書き方では再度のように代入(上書き)することができます。
では次の例に進みます。 関数の引数にポインタを使用している場合に、引数の値を変更したくない時があります。
そのような時にconstを変数の前に指定します。
constをつけることにより、引数の中身を書き換えないことを明確にできるメリットがあります。
関数の引数に const を指定すると、その関数の中では値を書き換えることができなくなります。
ですので、のような記述はできませんので、この例はエラーになります。
次の例は2次元配列とポインタの関係を学習します。 複数の文字列を配列に入れるには配列のポインタを使用します。 例ではの箇所です。
出力する方法は普通の配列と同じように添え字を使って出力します。
この章ではポインタについて説明します。
「ポインタ」を理解するためにはコンピュータがどのようにデータを記憶しているかの理解が必要です。
変数の値をコンピュータが記憶する場合、そのデータはメモリ上に置かれます。
メモリとは, 1バイトの幅の区画がビルの階のように連続してつながっているものと思ってください。
例えば、ビルは下から順番に1,2…と階数が付けられますが、メモリも同じで「1バイトの幅の区画」に順番に「番号」が付けられています。
この番号を「アドレス」と言います。
このアドレスは例えば0026FDE8のような16進数で表します。
変数を記憶するには1バイトで済むとは限らず、型によっては何バイトも必要になることがあります。
変数の型によって、使うバイト数が決まると言うことです。 では最初に戻ってアドレスについて詳しく説明します。
例えば2147483647と言う大きな整数を使用して4バイト分を使うとします。
この整数のアドレス(メモリ上で)はどこにあると思いますか?
実はこの整数のアドレスはその整数に割り当てられたアドレスの先頭のアドレスにあります。 ではアドレスが分かったところで次の例でポインタについて説明します。 ここではsizeof演算子で変数の大きさを測っています。
結果をバイト単位で表します。
変数iはsizeof演算子で調べた結果、4バイトあることがわかります。 変数iのアドレスを知るには変数の前に「&」を付けます。
これを付けることによって、変数iの値がメモリのどこに記憶されているか知ることが出来ます。
「&」をアドレス演算子と言います。
このアドレスは使っているコンピュータによって違います。
例えば「0044FA6C」などと表示されます。
そして、そのアドレスを出力するためのprintf関数の変換指定文字は「%p」を使います。
もしくは「std::cout」を使って以下のように書いてもいいです。 ここで「ポインタ」について説明します。
ポインタとは変数のアドレスを記憶する特殊な変数のことです。
これをポインタ変数と言います。
つまり、アドレスを記憶するだけの変数を作ることが出来るのです。
ポインタ変数も普通の変数と同じく宣言しなくてはいけません。 例ではと宣言しています。
そしてポインタの宣言をした後で、のように変数iのアドレスをポインタ変数gに代入します。
以下のように宣言と初期化を一緒に書くこともできます。 これで変数iのアドレスがポインタgに代入されましたので、の結果もと同じく0044FA6Cになります。
以下のように書いても同じ意味です。 ここでさらにポインタについての補足をします。先ほどiのアドレスをポインタgに入れましたが、これにより、iとgは同じアドレスを保有することになりました。
抽象的に言いますと、i君とgさんが同居することを意味していまして、gに起こった出来事はiに起こったことと同じ意味を持つようになります。
ですので一身同体のゆえ、次の5番ではポインタgからiの値を取り出しています。 gには変数iのアドレスが入っていますが、「*g」のようにという形で出力すると変数iの値を得ることが出来ます。
つまり、iとgには同じアドレスが入っているので、「*g」と書くことでiに入っている値が取り出すことが出来ます。
この例の結果は2147483647となり、iの値と同じになります。「*g」に2147483600を代入した後にiを出力するとどうなると思いますか?
結果は「2147483600」になります。 ポインタ変数「*g」は変数iの代わりに使うことが出来ることを意味します。
次の章で具体的なポインタの使い方について説明します。
オーバーロードについて知ろう
関数テンプレートについて知ろう
関数テンプレートとは同じ関数名で型だけ違う関数を「1つの関数」として扱うことが出来る仕組みです。
初めにテンプレート関数を使わない例を見てみましょう。 この例では2つのdisplay関数がありますが、引数の型が違えば同じ名前の関数を設定することが出来ます。 そして、関数を呼び出すときには引数の型と数に合った関数が呼び出されます。
例えば実引数が2つあり、両方ともint型の場合には仮引数もint型の引数が2つある関数が呼び出されます。 では先ほどの例を関数テンプレートを使って1つのdisplay関数に書き換える方法について次の例で説明します。 では関数テンプレートの作成方法について説明します。
初めにという形式で宣言します。 「タイプ」は関数が受け取るデータの型を意味します。
例えば「R」などと書きますと、ここが型名に置き換わります。
次に関数の定義を書きます。
戻り値と引数の型名には先ほど「タイプ」の箇所に書いた名前「R」を書いてください。 これで本来、2つ関数の定義を書かなくてはいけないところをテンプレート関数を使って1つに書き換えることができました。
インライン関数について知ろう
この章ではインライン関数について説明します。
では例をみてみましょう。 インライン関数は関数を呼び出す時間を短縮するために使います。
関数のあるプログラムは関数のないプログラムに比べて実行速度が遅くなります。
関数を呼ぶという行為はその関数のある場所に移動しなくてはいけないので時間がかかるわけです。
短いプログラムであれば気にする必要はありませんが、大きくて複雑なプログラムになると多くの関数を使うので、実行速度が遅くなってしまいます。
そこでインライン関数を使うことで実行速度を速くすることができます。
例のように短く小さい関数は関数の前に「inline」と記述することにより、そのインライン関数の中身が関数の呼び出し元に埋め込まれることになるので関数を呼ぶ時間はほとんどかかりません。 インライン関数で気を付けることはインライン関数にする関数はその中の実行する内容を短くしてください。
インラインにする関数が長い実行内容ですとインライン関数としてみなされない可能性があります。
次の補足について説明します。
今までは計算結果などを変数に入れてreturnで返していましたが、以下のように計算式をreturnの値に設定しても問題ありません。
関数に関してのC言語との違い
「関数について知ろう」の章では関数について説明しましたが、この章ではC言語にはない関数の使い方について説明します。
C++では関数プロトタイプ宣言で、デフォルト引数(あらかじめ決められている値)を設定することが出来ます。
つまり、関数プロトタイプ宣言で、デフォルト引数を設定すると、関数を呼び出すときの実引数を省略できます。
では例をみてみましょう。 次はデフォルト引数を複数設定した時の例を見てみましょう。
すべてに共通することは直接実引数を指定した場合はデフォルト引数よりも優先されます。 では次の例をみてみましょう。 デフォルト引数の設定の方法は関数プロトタイプ宣言に書く以外に関数の定義に直接書く方法もあります。
この例ではdisplay関数にデフォルト引数を設定しています。
また以下のように真ん中だけを設定することもできません。
関数のプロトタイプ宣言を知ろう
この章では関数のプロトタイプ宣言について説明します。 と書きましたが、関数のプロトタイプ宣言をすることで、このような制約は無くなります。
つまり関数の定義(以下の例ではhello関数)は関数の呼び出しよりも後に定義することが出来るということです。
では例をみてみましょう。 関数のプロトタイプ宣言は関数よりも前に宣言します。
引数がない場合、引数はvoidを入力します。
さらに戻り値も無いならば、戻り値の型の箇所にもvoidを入力します。 次の例は引数がdouble型の関数のプロトタイプ宣言を行っています。 引数のあるプロトタイプ宣言の場合には以下のように関数の引数を入力して宣言を行います。 しかし、以下のように引数の箇所はデータ型のみでも問題ありません。
グローバル変数とローカル変数について知ろう
この章ではグローバル変数とローカル変数について説明します。
詳しい説明は例の後で行います。
では例をみてみましょう。
グローバル変数とは関数の外で宣言された変数のことを言います。
この例で言いますと以下の箇所です。
int a=2
これまではmain関数の中で変数を使用してきましたが、こののように関数の外で宣言をするとグローバル変数になります。
グローバル変数は以下の通りどの関数の中でも使用することが出来ます。 ローカル変数とは関数の中で宣言された変数のことを言います。 ローカル変数は宣言をした関数の中でしか使用することが出来ませんので、複数の関数で同じ変数名を使用しても問題ありません。
つまり、関数の中だけが有効範囲なので、他の関数内で同じ変数名を作成してもお互い別の変数になるという訳です。
この例でいいますとmain関数とtashizan関数の中のローカル変数は同じ名前の変数名を付けても問題ありません。
例えば以下の例のようにmain関数とa関数の中でnumber変数を使用していますが、これらはお互いに影響を受けることはありません。
つまり、同じ変数名でも全く違う変数です。 ではもっと理解を深めるために次の例を見てみましょう。 まず初めにグローバル変数とローカル変数の確認から始めます。
関数の外側で宣言している
int a=23;
int b=25;
はグローバル変数です。
function1関数の中で宣言している変数はローカル変数です。
main関数の中で宣言している変数はローカル変数です。 次は変数の寿命について学習します。 関数の外でグローバル変数としてを宣言していますが、グローバル変数はプログラムが実行されてから終了するまで値を記憶しています。
functionは4つありますが、1回実行される度にグローバル変数はにより1が足されます。 後ほど学習しますがローカル変数はが1回実行される度にクリアされるので値を保持することができません。
次は「static」について説明します。
static int a=0;
関数内でstaticを付けないと、ただのローカル変数になってしまいますがstaticを付けることでグローバル変数と同じ機能を持つことが出来ます。
つまり、プログラムが実行されてから終了するまで値を記憶させておくことが出来ます。
このstaticが付いた変数を静的変数と言います。
functionは4つありますが、1回実行される度に静的変数はにより1が足されます。 これはグローバル変数の挙動とまったく同じです。
次はローカル変数について説明します。
function関数内で宣言されているはローカル変数です。
ローカル変数は関数が実行される度にデータがクリアにされるので情報を保持することはできません。
functionは4つありますが、を1回実行するたびにが実行されて、で1を足されるので、いつまでも1のままです。
結果は以下の通りです。
関数の仕組みはエクセルの関数の仕組みと意味は同じです。
エクセルをご存知の方はわかると思いますが、エクセル関数にSUMと言う関数が有りますが、この関数は指定した範囲のデータに基づいて足し算を行う関数です。
例えば指定した範囲のデータが「3,5,7」(引数)であるならば結果は「15」です。
SUMには初めから指定した範囲の足し算を行うと言う仕組みが備わっています。
つまり、エクセルの内部機構でSUMの機能は指定した範囲の足し算を行うと言うプログラムがされていると言うことです。
これが関数の意味です。
この章以前の関数は組み込み関数と言いまして、C++によって始めから用意されている関数です。
例えばprintf関数は文字列を出力する関数ですが、C++でそのような働きを作ってくれています。
組み込み関数の他にC++では自分で好き勝手に「ある働きを持った関数」を作ることができます。
これをユーザー定義関数と言いますが、この関数の作成方法をこの章で説明していきます。
例えば消費税を自動で計算する関数を自分で作りたいとします。
その場合、商品のお金を関数に渡すと関数は商品金額に消費税率を掛けた処理をして、その消費税を返すという関数を作ることになります。
関数の構文は以下の通りですが、これを関数の定義と呼びます。 〇引数とは関数が利用するデータのことを言います。
〇関数の中の引数は左端からと数えていきます。
〇1個以上の引数を記述する場合はカンマで区切ってください。
〇 returnを記述するときはという形で書きます。
returnは必要がない場合、省略することが出来ます。
main関数も関数の一種ですが、他にも色々な関数を作ることが出来ます。
main関数は特別で他にどんな関数を作っても一番初めに実行される関数です。
次は関数の実行方法について説明します。
関数はmain関数を除いて関数を定義しただけでは何も動きません。
関数を実行させるためには関数を呼び出す必要があります。
呼び出すことによって関数の中身が実行されます。 では1番簡単な例から、見てみましょう。 初めにプログラムの流れから説明します。 では関数の仕組みを詳しく見てみましょう。 戻り値の型の箇所にvoidと書かれていますが、この例の場合は戻り値が無いのでvoidと記述します。
関数とは入力したデータ(引数)に基づいて決められた処理を行い、戻り値という結果を返す機能を持っていますと説明しましたが、その戻り値の型を関数名の左側に書きます。
この例のようにreturn文がなくて戻すための値がない場合にはvoidと書きます。 つまり、関数の呼び出し元から渡されてくる引数が無いということです。 この例の場合はの箇所でhello関数を呼び出していますが、引数がカラです。 以下の書き方はエラーです。 次は引数のある関数についての説明をします。
では例をみてみましょう。 tashizan関数を実行し終えたのならばmain関数に戻ってきて,でプログラムを終了します。 次は戻り値のある例を見てみましょう。 tashizan関数の中で足し算の計算がされて、変数zにその結果を代入しています。
そして、そのz(戻り値)をreturn を使ってmain関数内のに戻して、その値を変数dに代入しています。 このようにreturnは関数の呼び出し元に値を返す役割があります。
returnの書き方はです。
図にすると以下のような過程で進みます。 では、どのような時にのように戻り値を返す必要があるのか?
それは呼びだし側であるmain関数でその値を活用したい場合に戻り値を返します。