UP | HOME

第9回 アカデミックスキルII C言語(2) 変数の使い方と標準入力

Table of Contents

1 このページの更新履歴

2 円と球の公式を使って計算してみる(サンプルプログラム2-1)

ある半径に対して,円周の長さ,円の面積,球の表面積および体積を計算して表示させるプログラムを ~/cpp ディレクトリの下に sample2-1.cpp という名前で作り,コンパイル,実行してみよう.

  1. Emacs を起動して ~/cpp/sample2-1.cpp というファイルを作成する(C-x C-f ~/cpp/sample2-1.cpp)
  2. 作成した sample2-1.cpp の中身を以下のように編集して保存する(C-x C-s).なお,コピーした内容を Emacs バッファに貼り付けるには C-y.
  3. コンパイルする Emacs 上で M-! (shell-command)とするか, 端末上で(cd ~/cpp~/cpp ディレクトリに移動していた後で)以下を入力する
    g++ sample2-1.cpp -o sample2-1.o
    
  4. 実行する 端末や 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) xy
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 を,以下のケースについて計算するように修正してみよう.

  1. 半径は 56.789 cm, 円周率は 3.141
  2. 半径は 43.21 cm, 円周率は 3.14159
  3. 半径は 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)型の 変数 として rpi の2つを 宣言 し, それぞれを 12.343.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に等しい
    

Author: Takeshi Nagae

Created: 2014-06-06 Fri 15:56

Emacs 24.3.1 (Org mode 8.2.5h)

Validate