変数

プログラムに計算させてみる

例題:次の図を描くプログラムをHandyGraphicを使って作成せよ(赤色の座標値は描かなくてよい)。ただし、ウィンドウの大きさは幅600x高さ400、長方形の左下と右上の座標は図に記したとおりである。
HandyGraphicではウィンドウの左下が原点(0, 0)であることに注意。

長方形を描くにはHgBox関数を使えばよいが、HgBox関数の引数は次のようになっている:

int HgBox(double x, double y, double w, double h)
長方形を描く
引数: x,y:左下隅の座標 w,h:幅と高さ

そこで、幅と高さを計算する必要があるが、これらを人間が手で計算するのも面倒臭い。コンピュータは計算が得意なのだからコンピュータに計算させればよいではないか。

プログラム中、数値を書くべきところには計算式を書くこともできる。計算式には四則演算を使える。計算の優先順位を指定するための()(括弧)も使うことができる。詳しくは教科書4章を参照。

この例の場合、次のようにして長方形を描くことができる。

HgBox(100, 100, 450 - 100, 270 - 100);

,の後や演算子の前後にスペースを入れるか入れないかは自由である。自分が読みやすいと思う方法で統一するとよい。

確認課題:このプログラムを完成させよ。

確認課題は、授業内に出来たかどうかを教員が確認する。ただし今回は、どの課題を確認するかは教員の指示による。

変数:数値を記憶する

例題:次の図を描くプログラムをHandyGraphicを使って作成せよ(赤色の矢印および比率を表す数字は描かなくてよい)。ただし、ウィンドウの大きさは幅600x高さ480、2つの正方形の大きさは114、横方向の端と正方形の間の長さはそれぞれ1:2:3の比率、縦方向の端と正方形の間の長さは1:2の比率である。図形描画に必要な座標値はプログラム中で計算させること。

先ほどと同様に、それぞれの正方形の左下の座標の計算式を考えればよいのだが、今回の計算は少々複雑である。

練習:計算手順を書き出してみよう。

縦方向と横方向はそれぞれ別々に計算すればよい。 縦方向は、ウィンドウの高さから正方形の大きさを引いた残りを2/3にすればよい(左下が原点であることに注意)。

横方向に関しては、例えば次のような計算手順が考えられる:

  1. 横方向の余白部分の和を計算する。
  2. 1で求めた余白部分を1:2:3の比率で配分したときに、1に相当する余白量を計算する。左側の正方形の左下隅のx座標はこの余白量となる。
  3. 2で求めた余白量に正方形の大きさを加え、さらに2で求めた余白量の2倍を足した値が右側の正方形の左下隅のx座標になる。

練習:1の値をd、2の値をg、3の値をxとしたとき、d, g, xを数式で表そう。

数式と同様、プログラムでも変数を使うことができるが役割は数式の変数とは若干異なる。プログラムにおける変数とは、何かの値(計算結果)を覚えておく箱、あるいは電卓のメモリ機能をイメージすればよい。変数は複数使うことができ、それぞれ名前を付けて区別する。(教科書3.1、3.2節)

変数の宣言(教科書3.2、3.4節)

Cのプログラムで変数を使う際には、どの名前の変数を使うか、その変数はどのような種類の値を扱うのか、を予め決めておく(宣言する)必要がある。例えば次のように書く(ただし、このプログラムは作成途中):

/*****
    calcGaps.c
    draw two rectangles by calculation
    2015.5.27 Mitsuru Minakuchi
*****/

#include <stdio.h>
#include <handy.h>

int main() {
    int xDist;  // 横方向の余白量
    int xGap;  // 横方向の余白を1:2:3で配分したときの1つ分
    int x;  // 2つめの正方形のx座標
    
    // 以下、未完成
}

変数の宣言は一般的に、次のような書式になる:

変数のデータ型 変数名;

int(integerの頭3文字)は整数のデータ型を表す。データ型については後述する。

変数の宣言は一般的には、関数の中の最初の位置に固めて書く。

関数の外に書く方法や、関数の途中で書く方法もあるが、意味が少々難しくなる。現時点では関数の最初に書く、としておく。

変数名はアルファベット、数字、アンダースコア_の組み合わせの任意の名前を付けることができる。大文字と小文字は区別される。ただし、最初の1文字目は数字はダメ。また、C言語で既に使われている名前(予約語と呼ぶ)も使用不可。既に宣言した変数が有効な範囲内で、同じ変数名を持つ変数を再度宣言することもできない。これらのダメな場合はコンパイラーがエラーを報告するので、容易に間違いに気付くはずである。(教科書3.2節)

練習:次の変数名はCのプログラム中で使うことができるか、使うことができないか?
c
Z
&
return
int
Integer
INT
intValue
float_value
_double_value
string  value
intValue2
thanks2you
4coming
thisIsToooooooooooooooooooooooooooLongName

変数名は任意であるので、aとかbでも良いような気がするが、一般的には「変数に格納される値の意味が端的に分かる単語」を使うべきである。複雑なプログラムになるとどのような計算をやっているのかわからなくなるし、プログラムを書いた本人ですら驚くほどに忘れてしまうものであるから。上記の例では、dの代わりにdistance(距離)のdist、gの代わりにgap(ギャップ、隙間)とし、さらに横方向=x軸であるのでxをつけてxDist、xGapとしている。英語でなくてもローマ字でもよいが、変な名前だとかえって読みにくくなるし、外国人には意味不明になるので注意(頑張って辞書を引いてよさげな名前を付けよう)。また、どのような値の変数なのか、意味をコメントで書いておくことが望ましい。

練習:xについてはどのような名前がより適しているだろうか?

一部、例外的にアルファベット1文字でも構わない場合がある。繰り返しの回で説明する。また、xのようにx座標であることを明確に表しているのであれば、それも構わないと思う。

複数の単語からなる名前を付ける場合、最初は小文字で始め、2番目以降の単語はそれぞれの単語の先頭を大文字にする書き方(キャメルケースと呼ぶ)や、x_distやx_gapのように書く書き方(スネークケース)が一般的である。プログラミング言語によって流儀があり、Cでは伝統的にスネークケースが使われているが、自分の好みで統一的に使えばよい。

値の代入(教科書3.5節)

変数を宣言したら、変数に値を設定したり、変数の値を使って計算する。数学の式と同じように書けばよい。Cでは=(イコール)は代入演算子と呼ばれ、=の右辺に書かれた値(計算式の計算結果)を、=の左辺に書かれた変数の値とする(代入する)ことを意味する。このような=を使った式を代入式と呼ぶ。プログラムでは1行の最後に;(セミコロン)を付けるのを忘れずに。

Cの=は数学のように左辺と右辺が等しいことを表すのではない点に注意。

最もシンプルな例として、変数に決まった値を代入するために次のように書ける。

int num;
num = 3;

C言語では変数を宣言しただけでは、変数の値は不定、つまりどのような値になっているか決まっていない。通常何かの値を最初に代入しておく(初期化、初期値を与える、などと呼ばれる)。変数の宣言と代入をまとめて、次のように書いてもよい。

int num = 3;

右辺は1つの数字でなくてもよく、計算式でもよい。

int num;
num = 1 + 2 * 3;

変数を使って値を計算することもできる。式の中に現れたときに格納されている値が計算に使われる。

int factor;
int value;
factor = 2;
value = factor * 3;

練習:valueの値は何になるか?

変数への値の代入は何度でも行うことができる。代入する度に値が変化することに注意。

int factor;
int value;
factor = 2;
factor = 3;
value = factor * 3;

練習:valueの値は何になるか?

変数の使用例

変数を使って最初のプログラムの続きを書くとつぎのようになる:

/*****
    calcGaps.c
    draw two rectangles
    Mitsuru Minakuchi
*****/

#include <stdio.h>
#include <handy.h>

int main() {
    int xDist;  // x方向の余白量
    int xGap;  // x方向の余白を1:2:3で配分したときの1つ分
    int x;  // 2つめの正方形のx座標
    
    xDist = 600 - 114 * 2;
    xGap = xDist / 6;
    x = xGap + 114 + xGap * 2;
    
    // 以下、未完成
}

練習:縦方向の座標値(正方形の左下隅のy座標)を変数を使って計算するコードを追加せよ。

必要な座標が計算できたら、後はそれらの値を使って図形を描くコードを追加すればよい。

確認課題:図形を描くコードを追加してプログラムを完成させよ。

プログラム中、114という数字が何度も出てきてあまり美しくないと感じるかもしれない。114という値を変数に格納して名前を付けておき、それを式に書く方法もある。あるいは、値が決まっていて変化しない定数に名前を付けて定義する方法がある。これらについては追々説明していく。

データ型(教科書3.3節)

コンピュータの内部では2進数で計算しているが人間は10進数を使っている。特に、コンピュータでは整数と実数では扱い方が大きく異なっている。そこでプログラム中に書かれた値をどのように解釈するか、どれくらいのデータ量(2進数の桁数)で値を表すか、などといったことを決めておかなければならない。

Cでは値や変数をどのように扱うかをプログラムを書く段階で決めておく。

「Cでは」とわざわざ書いているのは、他のプログラミング言語には予め決める必要の無いものもあるからである。Cのようなプログラムの段階で決めておくことを「静的型付け」と呼ぶ。対して、実行時に決めることを「動的型付け」と呼ぶ。

Cプログラムで扱う基本的なデータ型としては次のものが挙げられる:

整数 ..., -2, -1, 0, 1, 2, ...
プログラム中では数字をそのまま書けばよい(10進数の場合)
Lを最後に付けるとlong型であることを表す(long型は後述)
他に、8進数や16進数表記もあるが現時点では省略。

実数 1.2345, 6.02×10^23
プログラム中では小数点を使って書く。10^n(10のn乗の意味)の部分はC言語では6.02e23のように表記する(eは自然対数の底ではなく、Cでは10となる)。10と書くと整数、10.0と書くと実数になることに注意。
Fを最後に付けるとfloat型であることを表す(float型は後述)

文字 a, b, c, ...
プログラム中では'a'のように'(シングルクォーテーションマーク)で文字を囲って書く。
文字列を表す、"(ダブルクォーテーションマーク)で囲むのとは異なる点に注意。

これらをどれだけのデータ量(バイト数)で表現するか、で幾つかのバリエーションがあるが、macOSでは次のようになっている:

整数型
short型:2バイトで表現
int型:4バイトで表現
long型:8バイトで表現

実数型
float型:4バイトで表現
double型:8バイトで表現

文字型
char型:1バイトで表現
注:C言語では1byteの文字(いわゆる半角英数字)を対象とする。文字列、および日本語などの文字(マルチバイト文字、いわゆる全角文字)は複数の文字型の集合(配列)として扱われる。

他にもより多くのデータ量で表現する、long long int型やlong double型もあるが、通常のプログラムでは使うことはないだろう。

整数型と文字型はunsignedを付けて負の値を扱わないことを宣言することができる。例えばunsigned int、unsigned charなど。char型は1バイトの整数表現と考えればよい。

本演習では主に整数型(int型)のみを扱うことにする。

通常のプログラムで扱う値はint型で問題ないことが多いが、特に巨大な数値を扱う場合(指数的に値が増加するような計算など)は注意が必要である。この例については後日紹介しよう。

確認課題

次の図を描くプログラムrectAndCircle.cをHandyGraphicを使って作成せよ。ウィンドウの大きさは幅600x高さ400、青い塗りつぶしの正方形の上に黄色い塗りつぶしの円が内接している。円の中心はウィンドウの中心にあり、円の直径は300とする。図形描画に必要な座標値はプログラム中で計算させること(手計算はダメ)。変数は使ってもよいし、使わなくてもよい。