for ステートメント

QueSTudents
Yuto Takei


はじめに
C++





変数と型
演算子
ステートメントと制御構文
配列
オブジェクト指向の導入
 クラスの実装
 コンストラクタとデストラクタ

以下、第 2 回へ続く
休憩!

はじめに














ぐいぐい行きます・・・
置いてかれないように・・・
質問あればすぐに止めてください
途中で休憩いれます
プログラミングは簡単です
プログラマは狂人ではありません

独習 C++ 第3版
翔泳社 2002/11
ISBN4-79810-318-7
このスライドは
 独習 C++ 改訂版
翔泳社 1999/04
ISBN4-88135-701-8
を基にしています。


はじめに
C++





変数と型
演算子
ステートメントと制御構文
配列
オブジェクト指向の導入
 クラスの実装
 コンストラクタとデストラクタ

以下、第 2 回へ続く
休憩!


C++








変数と型
演算子
ステートメントと制御構文
配列
休憩!





これから扱うプログラミング言語は
C++ (シープラス) です。
簡単にいえば C 言語の子供
1983 年 Bell 研究所生まれ
ANSI/ISO 委員会によって標準化
最もよく利用される商用言語のひとつ


メモ帳 + コンパイラ
学校では Emacs と g++
IDE (統合開発環境)
現場ではこれを利用するが普通




Visual Studio® 2005 (Microsoft)
C++Builder® 2007 (Borland)
Xcode (Apple)
etc.
人間の書いたプログラム
を機械語に翻訳するため
のソフトウェア
Hello world!
#include <iostream>
using namespace std;
int main()
{
cout << "Hello world!" << endl;
return 0;
}



コンソールとは、コンピュータと人間が対話す
る画面のこと
黒い画面に白い文字とか
char name[80];
cout << "What's your name?" << endl;
cin >> name;
cout << "Hi " << name << "!";

変数は、プログラムの実行中の状態を保持する
ために利用する

type varName;
type varName = initValue;
type varName1, varName2, ...;

int i = 10;



コンピュータ内で、あるデータが何を示してい
るのかを理解するためのもの
01000001 (0x41)



整数としてみれば 65
文字としてみれば A
データが何の種類であるか、知る必要がある






int, long – 32 ビット符号付き整数
__int8 – 8 ビット符号なし整数
整数型は先頭に unsigned をつければ符号なし、
signed をつければ符号付き
float, double – 浮動小数点
char – 1 バイト文字 or 8 ビット整数
bool – 2 値変数 (真 true か偽 false か)

オペランドの数で次のような分類がある
 単項演算子
 二項演算子
 三項演算子 (多項演算子)

単項演算子は、前置もしくは後置
 -operand, operand++

二項演算子は、中置記法
 operand1 + operand2

三項演算子は、特殊な記述を用いる
 expression ? value1 : value2







算術演算子: + - * / %
論理演算子: & | ^ ! ~ && ||
ビット シフト演算子: << >>
関係演算子: == != < > <= >=
条件演算子: ?::
インクリメント, デクリメント: ++ -代入演算子:
= += -= *= /= %= &= |= ^= <<= >>=






主として数値計算を行うときに用いる演算子
加算: +
減算: 乗算: *
除算: /
剰余算: %


論理積, 論理和, 排他的論理和が定義される
たとえば 214, 115 をオペランドとすると・・・
11010110
&) 01110011
01010010

11010110
|) 01110011
11110111
11010110
^) 01110011
10100101
条件論理演算子 (ショート サーキット)
 bool 型オペランドどうしにのみ定義
 第 1 オペランドのみで値が判定できるなら、第 2 オペ
ランドを評価しない

単項演算子としては否定と補数がある

否定演算子 ! は bool 型にのみ適用可
 !true は false になり、!false は true になる

補数演算子 ~ は整数型に適用可
 ビットごとに 0, 1 を反転させていく
 たとえば 214 の補数は 41 である


ビットをずらすのに利用する
214 を左に 3 ビット分、シフトしてみる
11010110 =214
000 =167


214 << 3 = 176
左シフトの場合には、上位ビットは捨てられて、
下位ビットのほうに 0 が補填される
右シフトの場合には、下位ビットは捨てられて、
上位ビットのほうに 0 が補填される





2 つのオペランドの関係を比較する
等しいかどうか: ==
等しくないかどうか: !=
大小関係: < > <= >= (<= は ≤、>= は ≥ に対応)
比較関係が成立する場合には true が、そうで
ない場合には false が演算結果となる




唯一の三項演算子
expression ? value1 : value2
expression: bool 型の評価対象式
評価対象式が true ならば value1 を、false な
らば value2 を演算結果とする。
 score >= 50 ? "合格" : "不合格"

実はショートサーキットは条件演算子を用いて
記述できる。
 たとえば、bool 型の変数 A, B に対して
 A && B
 A || B

実はショートサーキットは条件演算子を用いて
記述できる。
 たとえば、bool 型の変数 A, B に対して
 A && B
 A || B
A ? B : false
A ? true : B


変数に 1 を足して (もしくは引いて)、その値を
返す
前置と後置では動作が変わる
 int
int
 int
int

a
b
a
b
=
=
=
=
10;
++a;
10;
a++;
a = 11, b = 11
a = 11, b = 10
デクリメントは 1 を引く。挙動はインクリメン
トと同様

単純代入演算子: 左オペランドに、右オペランド
の値を代入する
 rank = "不可"

複合代入演算子: 左オペランドと右オペランドの
間で演算を行った後、その値を左オペランドに
代入する。
 balance -= 30000
 balance = balance - 30000
 cf. ++a は a += 1 と同じ。

代入演算子の演算結果は、値を代入した後の左
オペランドの値になる
 k = (n % 2 == 0 ? n /= 2 : n -= 1) + 1

代入演算子の左オペランドは、値が代入できる
ものでなければならない
 i + 3 = 10
これはコンパイル エラー




int a = 10;
int b = ++a++;
このコードはどうなるでしょうか?
答え: 無効
++a は、変数ではなく単なる値である。した
がって (++a)++ は、++a という値に 1 を加える
ことになるので無効。



プログラム中にはメモを残すべき
単一行コメント: // comment
複数行コメント:
/*
This is a comment.
*/


C++ はフリー フォーム言語
#include <iostream>
using namespace std;
int main()
{
cout << "Hello world!" << endl;
return 0;
}


C++ はフリー フォーム言語
#include <iostream>
using // using directive
namespace /* comment */ std;
int
// this code is completely valid.
main(){cout<<
"Hello world!"
<< endl // break
; return 0; }

命令を記述する文章のこと
 ラベル付きステートメント
 式ステートメント
 Null ステートメント





複合ステートメント (aka. コード ブロック)
条件分岐ステートメント
繰り返しステートメント
ジャンプ ステートメント
宣言ステートメント


expressionopt;
expression は任意の式で、省略可能
 3;

// valid statement
Null ステートメント: expression を省略したス
テートメント
 ;
// Null statement


{ statements }
statements は複数のステートメント
 {
cout << "Hello world!";
cout << endl;
}
 { } // valid





プログラムは命令の流れ (フロー)
どのように実行されるかをコントロールする必
要がある
条件分岐
繰り返し
ジャンプ




if ステートメント
if (expression) then-statement
else else-statement
else 句以下は省略可能
if (score >= 80) rank = "優";
else if (score >= 65) rank = "良";
else if (score >= 50) rank = "可";
else rank = "不可";


for ステートメント
for (initializer; condition; iterator)
statement
iterator
initializer
for
statement
true
condition
false

ループ初期化子, 継続条件, ステップ
はすべて省略可能



ラベル付きステートメントを使う
goto ステートメント: 任意のラベルへ飛ぶ
for (int i = 0; ; i++)
if (i == 5) goto loopOut;
loopOut:
// label definition
cout << "i == 5";
High and Low


switch ステートメント: ある値がどれと等しい
かを元にして判定することができる。
switch (expression)
{
case value1: statement1
case および default は
ラベル付きステートメント
case value2: statement2
...
default: defaultStatement
}


case 句内では、break ステートメントを使わな
い限り、次の case 句以降に流れ落ちる。
switch (10) {
case 10: cout
case 15: cout
case 20: cout
}
// The output
<< "10 ";
<< "15 "; break;
<< "20 ";
will be 10 and 15.





while ステートメント
while (expression) statement
expression が true である限り statement を
実行する
expression は、ループに入るときと、
statement が実行されるたびに評価される
for ループのシンプル版

break ステートメント: ループ ブロックや
switch 文を 1 段階脱出するのに使用
 for (int i = 0; i < 10; i++) {
if (i == 5) break;
cout << i;
}
cout << "outside the loop";

continue ステートメント: ループ ブロックにお
いて、継続条件式に飛ぶために使用
 for (int i = 0; i < 10; i++) {
if (i == 5) continue;
cout << i;
}
cout << "outside the loop";
試験データの処理

do-while ステートメント

do statement while (expression);


while ループとの違いは、継続条件式の評価が
処理ステートメントの実行後であること
まず 1 回処理をした後、同じ処理を続けるか判
定するような場合に利用

こんな風なループもありと言えばあり:

// entering loop
lpStart:
// do something...
lpCond:
if (expression) goto lpStart;
else goto lpEnd;
lpEnd:;
// outside the loop
 推奨しないが、究極的にはこれが一番柔軟




return ステートメント: 実行中の関数を脱出し、
呼び出し元に制御を戻す。同時に関数の戻り値
を与える
return retValueopt;
戻り値を持つ関数ならば、retValue に戻り値の
型に合致する値を指定
戻り値がない関数ならば retValue は指定して
はいけない


int gcd(int a, int b) {
if (a < b) return gcd(b, a);
else if (b == 0) return a;
else return gcd(b, a % b);
}
void proc() {
// do something...
return;
}

次の値を求めよ

次の値を求めよ
∞
6
𝑘=0
𝑘
𝑙=1
𝑘
𝑙=1 2𝑘
2𝑙 − 1
⋅ 2𝑘 + 1 ⋅ 22𝑘+1

正弦関数の逆関数をテーラー展開
∞
sin−1 𝑥 =
𝑛=0


2𝑛
2𝑛+1
𝑥
𝑛 ⋅
=
22𝑛 2𝑛 + 1
で、x = 1/2 とすれば OK
展開すると、こうなる:
∞
𝑛=0
2𝑛 − 1 ‼ 𝑥 2𝑛+1
⋅
2𝑛 ‼
2𝑛 + 1
𝜋
1
1
1⋅3
1⋅3⋅5
=
+
+
+
+⋯
6 1 ⋅ 21 2 ⋅ 3 ⋅ 23 2 ⋅ 4 ⋅ 5 ⋅ 25 2 ⋅ 4 ⋅ 6 ⋅ 7 ⋅ 27
円周率の概算






配列とは、複数の同一型のオブジェクトを格納
するコンテナ
要は、複数の変数が一体となった変数
type arrayName[length];
type arrayName[length] =
{ elem1, elem2, ... }
type: 配列内の要素の型
length: 配列の要素数 (定数指定)

長さを変数で指定するときには、new 演算子を
利用して動的に配列を割り当て

type *ptName = new type[length];
使用後には必ず delete 演算子で解放

delete[] ptName;

ポインタの詳細については次回へ




要素は 0 番目から始まる
配列は作成した後には長さを変更できない
要素にアクセスするには [] 演算子を利用
 int num;
cin >> num;
int* fibo = new int[num];
fibo[0] = fibo[1] = 1;
for (int i = 2; i < num; i++)
fibo[i] = fibo[i - 2] + fibo[i - 1];
エラトステネスの篩


はじめに
C++





変数と型
演算子
ステートメントと制御構文
配列
オブジェクト指向の導入
 クラスの実装
 コンストラクタとデストラクタ

以下、第 2 回へ続く
休憩!







オブジェクト指向の導入
 クラスの実装
 コンストラクタとデストラクタ


プログラミング パラダイムの一つ
 構造化プログラミング
 データ指向プログラミング
 オブジェクト指向プログラミング
 etc.


設計対象となるシステムの構成要素をオブジェ
クトとみなす手法
システムをマルチ スケールに分析する



カプセル化 (encapsulation)
ポリモーフィズム (polymorphism)
継承 (inheritance)





システムの構成要素をオブジェクトとして扱う
オブジェクトは、その構成要素が持つデータと、
そのデータに付随する処理とを、包含する
オブジェクトは外部からの操作を受け付けるイ
ンタフェースを持つ
オブジェクトが提供するインタフェース以外で
は、オブジェクトが持つデータにアクセスでき
ない
完全なブラックボックス


複数の種類のオブジェクトに対して、同種の操
作を行うには、同じインタフェースを用いるこ
とができる
バイクにも大型トラックにも加速するためのイ
ンタフェースがある。ユーザであるドライバは、
このインタフェースを同じように利用すること
ができる



あるオブジェクトが、別のオブジェクトの性質
を持つとき、そのオブジェクトの性質を継承す
ることができる
「乗り物」オブジェクトは、「人の移動手段で
ある」という性質を持つ
「バイク」や「自動車」は「乗り物」の性質を
継承する
今までオブジェクト、と言っていたが・・・
 クラスは、オブジェクトの定義である
 インスタンスは、オブジェクトの実体である

たとえば、自動車の設計図があればそれはクラ
スであると考えることができ、それを基にして
実際に作成した自動車はインスタンスになる


class キーワードを用いる
class className
{
// private members
public:
// public members
} objectListopt;
メンバ変数やメンバ関数
などを定義




関数とは命令コードの集合体
type funcName(paramList)
{
カンマ区切りで変数宣
言リストを書く
...
}
type に void を指定すると、戻り値を持たない
ルーチンになる
戻り値を返すには return ステートメントを利
用

プロトタイプ: 関数の実体 (つまりコード本体) を
定義しないこともできる
 int main();

あるクラスのメンバ関数に実体を与えるときに
は、スコープ解決演算子 :: を用いて、どのクラ
スの関数であるかを明示する必要がある



class A { public: void Func(); };
void Func() { }
上のコードでは Func はグローバル関数
A::Func として定義すれば A クラスのメンバ関
数 Func の定義になる



プログラムを書くときには、*.cpp という拡張子
のコード ファイルに記述する
クラスの定義などについては、慣習的に、*.h と
いう拡張子のヘッダ ファイルに記述する
あるクラスを利用するときには、その定義が書
いてあるヘッダ ファイルを #include ディレク
ティブでインクルードする
学生クラスの実装




C++ では、パラメータ リストが異なる同名の関
数を定義することができる
ただし、戻り値が異なるだけで、パラメータ リ
ストと関数名が同じなのは不可
ポリモーフィズムを実現 (cf. インタフェース)
cf. メソッド シグニチャ: 関数名、パラメータ リ
スト、戻り値の組み合わせをひとまとめ

たとえば絶対値を返す関数
 int, char, double などの値の絶対値がほしい
 関数オーバーロードがなかったとすれば、iAbs, cAbs,
dAbs のように複数の関数を実装しなければいけない
 パラメータの型が異なるのでオーバーロードで対応。
結果として abs という関数だけで済む
絶対値関数の実装





クラスには初期化処理と終了処理を組み込むこ
とができる
コンストラクタ: インスタンスの作成時に実行さ
れる関数。パラメータを取ることができるが、
戻り値は持てない。関数名は className と同じ
デストラクタ: インスタンスが破棄されるときに
実行される関数。パラメータも戻り値も取れな
い。関数名は ~className になる
両方ともアクセス修飾できる
戻り値は void ではなく、そもそも存在しない
逆ポーランド記法 (RPN) への変換


中置記法: (1 + 5) * (8 + 1) = 54
逆ポーランド記法: 1 5 + 8 1 + * 54 =
 2 項演算子のオペランドを連続して記述した後に、オ
ペレータを置く記述法


逆ポーランド記法 (RPN) への変換