第9回 アカデミックスキルII C言語(2) 変数の使い方と標準入力
Table of Contents
1 このページの更新履歴
2 円と球の公式を使って計算してみる(サンプルプログラム2-1)
ある半径に対して,円周の長さ,円の面積,球の表面積および体積を計算して表示させるプログラムを ~/cpp
ディレクトリの下に sample2-1.cpp
という名前で作り,コンパイル,実行してみよう.
- Emacs を起動して
~/cpp/sample2-1.cpp
というファイルを作成する(C-x C-f ~/cpp/sample2-1.cpp
) - 作成した
sample2-1.cpp
の中身を以下のように編集して保存する(C-x C-s
).なお,コピーした内容を Emacs バッファに貼り付けるにはC-y
. - コンパイルする
Emacs 上で
M-!
(shell-command)とするか, 端末上で(cd ~/cpp
で~/cpp
ディレクトリに移動していた後で)以下を入力するg++ sample2-1.cpp -o sample2-1.o
- 実行する
端末や Emacs から
sample2-1.o
を実行してみよう../sample2-1.o
以下のような実行結果が表示されたかな?
半径:12.34 円周の長さ:77.4952 円の面積:478.145 球の表面積:1912.58 球の体積:7867.09
3 sample2-1.cpp
解説
3.1 算術演算ライブラリ <math.h>
のインクルード
3行目の
#include <math.h>
は,算術演算ライブラリを読み込んでいる.これにより, 12〜14行目で使う「べき乗関数」 pow(x,y)
が利用できる.
3.2 演算子
11行目〜14行目は,乗算,除算,べき乗を使って,円周の長さ,円の面積,球の表面積お よび球の体積を,それぞれ,計算している.C++ には,標準で,以下のような基本的な算 術演算子が用意されている.
演算子 | 意味 | 用例 | 評価結果( int 型) |
評価結果( double 型) |
---|---|---|---|---|
+ |
加算 | 123 + 45 |
168 |
168 |
- |
減算 | 123 - 45 |
78 |
78 |
* |
乗算 | 123 * 45 |
5535 |
5535 |
/ |
除算 | 123 / 45 |
2 |
2.73333 |
% |
剰余 | 123 % 45 |
3 |
エラー |
さらに, <math.h>
をインクルードすると, 以下のような算術演算子も利用可能になる.
演算子 | 意味 | 用例 | 結果 |
---|---|---|---|
pow |
べき乗 | pow(x, y) |
x の y 乗 |
sqrt |
平方根 | sqrt(x) |
x の平方根 |
exp |
指数 | exp(x) |
x の指数 |
log |
自然対数 | log(x) |
x の指数 |
sin, cos, tan |
三角関数 | sin(x), cos(x), tan(x) |
x の正弦,余弦,正接 |
4 半径や円周率を変えてみる
sample2-1.cpp
を,以下のケースについて計算するように修正してみよう.
- 半径は 56.789 cm, 円周率は 3.141
- 半径は 43.21 cm, 円周率は 3.14159
- 半径は 3.14 cm, 円周率は 3.14
それぞれ, 以下のようなソースコードを書けばよさそうに思える.
しかし,この方法では,1., 2., 3. のそれぞれについて,
ファイル内の全ての半径と円周率を修正しないといけない.
特に, sample2-1-error3.cpp
では 3.14 という値が
半径なのか円周率なのか判らないため,
このプログラムの「半径だけを 3.1 に修正」しようとするととても大変.
このコードのようにたった16行程度なら可能かもしれないが,
数百,数千行に渡るコードの中から修正すべきところを全部探すのは無理
(実際, 最初の2つのファイルには,それぞれ1つづつ間違いがある).
5 半径や円周率を変数を使って表現する(サンプルプログラム2-2)
上述の半径や円周率のように, 「何度も使う数値」や「何らかの意味がある数値」をシステマティックに取り扱うには, 変数 を使うのが一般的.
~/cpp/sample2-2.cpp
というファイルを作り,その中に以下のソースコードを書き込んで
コンパイル,実行してみよう.
6 sample2-2.cpp
の解説
6.1 変数の宣言
8〜9行目:
double r = 12.34; // 半径 double pi = 3.14; // 円周率
は,それぞれ,倍精度実数(double
)型の 変数 として r
と pi
の2つを 宣言 し,
それぞれを 12.34
と 3.14
という値で 初期化 している.
半径や円周率を変えたい場合は,これらの数値を修正するだけで,
それ以外の部分には手をつける必要がない.
変数を 宣言 するには,
変数の型 変数名;
というセンテンスを用いる. n個の変数を同時に宣言する場合は,
変数の型 変数名1, 変数名2, ..., 変数名n;
のようにコンマで区切る.
宣言と同時に変数を 初期化 するには, = を使って
変数の型 変数名 = 値; 変数の型 変数名1 = 値1, 変数名2 = 値2, ..., 変数名n = 値n;
とする.「値」の部分は 3.14
のような定数でもよいし,既に定義された変数でもよい.例えば,
int a = 123; // 整数型変数 a を定義し, 123 で初期化 int b = a; // 変数型変数 b を定義し, a の値で初期化
とした場合, a
の値も b
の値も 123
となる.
一度宣言した変数に値を代入するには,
変数名 = 値;
というセンテンスを用いる. もともと値が格納されている変数に,値を代入すると,古い値は新しい値によって上書きされる. 例えば,
int a = 123, b; // 整数型の変数 a, b を定義し, a の値を 123 で初期化 b = a; // b に a の値を代入する(bの値は 123 となる) a = 456; // a に 456 を代入(古い値 456 は失われる)
とした場合, a
の値は 456
となるが, b
の値は 123
のままである.
変数の名前は,
- 半角英字(大文字と小文字は区別される)
- 半角数字(ただし,変数名の先頭には使えない)
- 半角アンダーバー(
_
)
の組み合わせで構成される.ただし,以下のようないくつかの単語には予め役割が与えら れている(予約語 と呼ばれる)ため,変数名として使うことはできない(一部または全部を大文字とすればその限りではない).
alignas, alignof, and, and_eq, asm, auto, bitand, bitor, bool, break, case, catch, char, char16_t, char32_t, class, compl, const, constexpr, const_cast, continue, decltype, default, delete, do, double, dynamic_cast, else, enum, explicit, export, extern, false, float, for, friend, goto, if, inline, int, long, mutable, namespace, new, noexcept, not, not_eq, nullptr, operator, or, or_eq, private, protected, public, register, reinterpret_cast, return, short, signed, sizeof, static, static_assert, static_cast, struct, switch, template, this, thread_local, throw, true, try, typedef, typeid, typename, union, unsigned, using, virtual, void, volatile, wchar_t, while, xor, xor_eq
変数の型には,整数型(int
), 単精度実数型(float
), 倍精度実数型(double
), 文字
型(char
)などがある.本講義で主に用いるのは, 整数型(int
) と 倍精度実数(double
) だ.
変数には,宣言された時に指定された型の値しか格納できない.
int
型の変数は 3.14
という「実数」を格納できないし,
double
型の変数は 3
という「整数」を格納できない.
C++では,宣言時の型と異なる型が代入された時には 暗黙の型変換 が行なわれる.
例えば,
int
型の変数a
に実数3.14
を代入する(int a=3.14
)と, 実数3.14
が整数3
に変換された上でa
に代入される(int a=3
と同じ).double
型の変数b
に整数3
を代入する(double b = 3
)と, 整数3
が倍精度実数3.00000000...
に変換された上でb
に代入される(double b = 3.0
と同じ).
といった変換が行なわれる.暗黙の型変換は,直感に反しないように設計されているが,どのような処理が行なわれているかを正確に把握するまでは,無闇に使わない方がよい.
6.2 変数の値を出力する
変数を使わないコード sample2-1.cpp
の 10〜14行目:
cout << "半径: " << 12.34 << " 円周率: " << 3.14 << endl; cout << "円周の長さ:" << 2.0 * 3.14 * 12.34 << endl; cout << "円の面積:" << 3.14 * pow(12.34, 2.0) << endl; // pow(x,y) は x の y 乗を返す cout << "球の表面積:" << 4.0 * 3.14 * pow(12.34, 2.0) << endl; cout << "球の体積:" << 4.0/3.0 * 3.14 * pow(12.34, 3.0) << endl;
に対して,変数を使ったコード sample2-2.cpp
の 11〜15行目:
cout << "半径: " << r << " 円周率: " << pi << endl; // 半径と円周率を表示 cout << "円周の長さ:" << 2.0 * pi * r << endl; // 円周率×直径 cout << "円の面積:" << pi * pow(r, 2.0) << endl; // 円周率×半径の2乗 cout << "球の表面積:" << 4.0 * pi * pow(r, 2.0) << endl; // 4×円周率×半径の2乗 cout << "球の体積:" << 4.0/3.0 * pi * pow(r, 3.0) << endl; // 4/3×円周率×半径の3乗
では,半径の数値(12.34)の代わりに r
を,
円周率の数値(3.14)の代わりに pi
を使っている.
こうすることで,以下のようなメリットがある:
- 半径や円周率が代わっても, 計算部分はまったく 変更する必要がない.
- 公式の表現に近い表現を使うことができ,コードが 読み易くなる.
これらの点は,単にコーディングを容易にするだけでなく, ソースコードの保守 を確実に行う上でも,極めて重要である.
7 標準入力から得られた値を使おう(サンプルプログラム2-3)
変数を使うことで,半径を色々変えて円周長,円の面積,球の表面積,球の体積を計算してみたい場合でも, ソースコードの中で,その変数に与える値の部分を修正するだけで対応できる. しかし,計算すべき半径が 100通りある場合,それぞれに対してソースファイルを作ってコンパイル+実行しなければならない. そこで, プログラムの実行中にユーザーが半径を入力 できるようにしてみよう.
~/cpp/sample2-3.cpp
というファイルを作り,その中に以下のソースコードを書き込んで
コンパイル,実行してみよう.
こうすれば,半径が 12.34
でも 567.89
でも 3.14
でも,プログラムそのものを
一切修正することなく計算できる.
8 sample2-3.cpp
の解説
8.1 C++ での標準入力
- C++ でプログラム実行中にキーボードから値を入力させるには,標準入力ストリームを用いる.
- 標準入力ストリームは
std::cin
という名前で<iostream>
ライブラリ内に定義されている. - 入力ストリームから変数に値を渡すには,入力演算子
>>
を用いて,入力ストリーム >> 変数
とする.
sample2-3.cpp
の12行目:cin >> r; // 標準入力 cin から半径を得る
では,標準入力
cin
(4行目で名前空間を宣言してるのでstd::
は省略可能)から,半径を表す変数r
に値を渡している.
8.2 半径と円周率を両方入力できるようにする
sample2-3.cpp
の11〜12行目を
cout << "半径と円周率を入力して下さい: "; cin >> r >> pi; // 標準入力 cin から半径を得る
と修正すれば,半径に続けて円周率も入力できるようになる.キーボードから複数の値を入力する場合は,スペースもしくは改行で区切る.
9 「円筒」の表面積と体積を求めて表示させるプログラム
sample2-3.cpp
をベースにして, 円筒 の「底面の半径」と「高さ」を入力させ,その表面積と体積を表示させるプログラムを作ってみよう.ヒントは以下の通り:
- 円筒 の体積は「底面の面積」×「高さ」 に等しい.
- 円筒 の表面積は 「底面の面積」 × 2 + 「側面の面積」に等しい.
- 円筒 の「側面の面積」は「底面の円周長」×「高さ」に等しい.
簡単すぎる?じゃぁ, 円錐 ではどうだろう?
10 「円錐」の表面積と体積を求めて表示させるプログラム
円錐 の「底面の半径」と「高さ」を入力させ,その表面積と体積を表示させるプログラムを作ってみよう.まずは ヒント無し で作ってみよう!
ヒントを見るには↓にスクロール.
- 円錐 の体積は「底面の面積」×「高さ」÷3 に等しい.
- 円錐の表面積は「底面の面積」+「側面の面積」に等しい.
- 円錐の側面は 扇形 になり,その半径は「底面の半径」と「高さ」の 二乗和平方根 に,中心角は「底面の円周」÷「扇形の半径」に,面積は「中心角」×「半径の二乗」÷2に等しい.
- C++ で 平方根 を表現するには,
<math.h>
ライブラリに含まれるsqrt
関数を使う.sqrt(x)
はx
の平方根を返す. - 例えば,円周率, 底面の半径,円錐の高さ,円錐の側面(扇形)の半径, 中心角および面積を,それぞれ,
double pi; // 円周率 double r, h; // 底面の半径, 円錐の高さ double R, theta, S; // 側面(扇形)の半径, 中心角, 面積
と定義しておいた場合,円錐の側面の扇形の半径, 中心角および面積は以下のように計算できる(ハズ):
R = sqrt( pow(r,2.0) + pow(h, 2.0)); // 側面(扇形)の半径は // 「底面の半径」と「円錐の高さ」の二乗和平方根に等しい theta = 2.0 * pi * r / R; // 側面(扇形)の中心角は「底面の円周」÷「側面の半径」に等しい S = theta * pow(R,2.0) / 2.0; // 側面(扇形)の面積は「中心角」×「半径の二乗」÷ 2に等しい