処理の種類一覧
プロフラムの処理は、これらの演算処理が連続して行われています。1つ1つの演算は、セミコロン( ; )で区切られます。
処理文の種類 | 内容 |
---|---|
{} | 1つ以上の様々な演算を囲うのに使用します。 |
; | 式の終了を意味します。 |
return | 関数を終了し、呼び出し元のプログラムへ戻ります。 |
if else | 条件判定が必要な時に使用します。 |
?: | if else 文を簡易的にしたもの。 |
switch | 式の値と一致する場合に処理を行います。 |
while | 式が false になるまで、ループ処理を継続します。 式はループ処理の前に判定されます。 |
for | 式が false になるまで、ループ処理を継続します。 式はループ処理の前に判定されます。 |
do while | 式が false になるまで、ループ処理を継続します。 式はループ処理の後に判定されます。 ループ処理は最低1回は行われます。 |
break | 最も近くにある外側のループ処理( switch、while、do-while、for)から抜けます。 |
continue | 最も近くにある外側のループ処理(while、do-while、for)の次のループ処理を呼び出します。 |
new | クラスオブジェクトを作成します。 |
delete | new演算子によって作成されたオブジェクトを削除します。 |
1つの処理を、複数行に渡って記述することが出来ます。
2つ以上の処理を、同じ行に記述することも出来ます。
各処理文の使用例
重文処理 {}(中括弧、ブレース)
重文処理は、中括弧 {}で囲まれた1つ、または複数のさまざまな型で構成されます。括弧の後のセミコロン(;)は不要です。
if(x == 0)
{
Print("invalid position x = ", x);
return;
}
式の終わり ;(セミコロン)
式の最後は、セミコロン(;)を記述して終わります。
代入処理
x = 3;
y = x = 3;
bool equal = (x == y);
代入演算子は式の中で複数回使用出来ます。このケースでは、処理は右から左へ行われます。
関数の呼び出し方
関数名 (引数1,…, 引数N);
関数の呼び出しは、関数名の後に小括弧()をつけます。
引数がある場合(void型以外)は、小括弧内に対応する型の値を書きます。
戻り値がある場合は、代入演算子の右側に関数の呼び出しを書きます。
空の演算子
セミコロン( ; )のみで構成され、制御演算子の本体が、空であることを示すために使用されます。
参照:変数の初期化
関数の終了(return)
return 演算子は、実行中の関数を終了し、呼び出し元のプログラムに戻ります。
返り値がある場合は、呼び出し元の関数に値を返します。式は代入演算子を含むことが出来ます。
int CalcSum(int x, int y)
{
return(x+y);
}
void 型の関数では、return 演算子を省略することができます。
void SomeFunction()
{
Print("Hello!");
return; // この演算子は省略できる
}
関数の右中括弧{}は、式の部分を含まない、return 演算子の実行を暗黙的に示します。
return 処理で返り値として返すことが出来るのは、基本データ型、基本構造体、オブジェクトポインタがあります。
配列、クラスオブジェクト、複合構造体の変数を返すことは出来ません。
参照:変数の初期化
条件判定 if else
if (条件式)
処理x //条件式を満たしたときに行われる処理
else
処理y //条件式を満たさなかったときに行われる処理
条件式が true の場合、処理x が実行され、処理y は実行されません。
条件式が false の場合、処理y のみが実行されます。
if 文の else 部分は、省略することができます。
//--- else 部分は2つ目の if 演算子と関係する
if(x > 1)
if(y == 2)
z = 5;
else
z = 6;
//--- else 部分は1つ目の if 演算子と関係する
if(x > l)
{
if(y == 2)
z = 5;
}
else
z = 6;
//--- else 文の中で、更に if else 文に分岐
if(x == 'a')
{
y = 1;
}
else
if(x == 'b')
{
y = 2;
z = 3;
}
else
if(x == 'c')
{
y = 4;
}
else
Print("ERROR");
三項演算処理 ?:
三項演算子の一般的な形式は次の通りです。
式 1 ? 式 2 : 式 3
式1は、式の結果が、bool型であればどんな式でも使えます。
式1の結果がtrueの場合、式2の処理が実行されます。
式2の結果がfalseの場合、式3の処理が実行されます。
式2と式3は、void型以外の値を返す必要があります。
//--- 一日の始値と終値の差を正規化
double true_range = (High == Low) ? 0 : (Close - Open) / (High - Low);
//上記の式と、下記の式は、同じ意味合いです。
double true_range;
if(High == Low)
true_range = 0; // 高/安値が等しい場合
else
true_range = (Close - Open) / (High - Low); // 範囲が null でない場合
演算子の使用制限
三項演算については、いくつかの制限があります。
- ユーザ定義型と基本データ型や列挙型を混同してはいけません。ポインタには、NULLを使用出来ます。
- 値が基本型であれば、一番大きい型のオペレータが使用されます(型キャストをご参照ください)。
- 値のいずれかが列挙型で、2つ目が数値型の場合、列挙型は int 型に置き換えられ、2番目のルールが適用されます。
- 両方の値が列挙型の場合は、その型が同一である必要があり、演算子は列挙型となります。
ユーザ定義型(クラスまたは構造体)の制限について
- 型は同一であるか、2つ目が、1つ目からの派生型である必要があります。
- 型が同一(または継承)でない場合、子の型は暗黙的に親にキャストされ、演算子は親の型になります。
- オブジェクトとポインタを混同してはいけません。式は両方ともオブジェクトまたはポインタでなければいけません。ポインタにはNULL が利用出来ます。
条件演算子の結果の型は、プログラムのコンパイル時に定義されているので、条件演算子をオーバーロードされた、関数の引数として使用する場合はご注意ください。
この型は「式 2 」と「式 3 」の型のうち大きい方の型として定義されています。
void func(double d) { Print("double argument: ", d); }
void func(string s) { Print("string argument: ", s); }
bool Expression1 = true;
double Expression2 = M_PI;
string Expression3 = "3.1415926";
void OnStart()
{
func(Expression2);
func(Expression3);
func(Expression1 ? Expression2 : Expression3); // 文字列への暗黙的キャストに警告
func(!Expression1 ? Expression2 : Expression3); // 文字列への暗黙的キャストに警告
}
// 結果:
// double argument: 3.141592653589793
// string argument: 3.1415926
// string argument: 3.141592653589793
// string argument: 3.1415926
選択処理 switch
式の値と、全てのcaseの定数と比較し、一致する処理を行います。
caseの定数は、整数定数、リテラル定数が使用出来ます。
caseの定数に、変数又は関数の呼び出しは使用出来ません。
switch文は、整数型(int、uint)である必要があります。
switch(式)
{
case constant:
operators
case constant:
operators
...
default:
operators
}
caseの定数に一致する値が無い場合、defaultラベルの処理が実行されます。
defaultは省略する事が可能で、式の最後に記載しないことも可能です。
caseの定数に一致せず、defaultラベルも存在しない場合は、何も処理が行われません。
caseと定数はただのラベルです。複数のラベルが存在する場合、breakに到達するまで処理が実行されます。
定数式は、コンパイル時に計算されます。
1つのswitch 内で、複数の定数が同じ値を持つことは出来ません。
//--- 例1
switch(x)
{
case 'A':
Print("CASE A");
break;
case 'B':
case 'C':
Print("CASE B or C");
break;
default:
Print("NOT A, B or C");
break;
}
//--- 例 2
string res = "";
int i = 0;
switch(i)
{
case 1:
res = i;
break;
default:
res = "default";
break;
case 2:
res = i;
break;
case 3:
res = i;
break;
}
Print(res);
/*
結果
default
*/
ループ処理 while
while文は、満たされなければならない条件式と、条件を満たした場合に行う処理で構成されています。
while(式)
処理;
条件式が true であれば、条件式が false になるまで処理が継続して実行されます。
処理が実行される前に、条件式の値を判定します。
そのため、条件式が初めから false であれば、処理は一度も行われません。
ループ処理の回数が多いと予想される場合は、IsStopped()関数を使用して、ループから抜ける処理を施すことが推奨されています。
while(k < n && !IsStopped())
{
y = y * x;
k++;
}
ループ処理 for
for文は、3つの式と、それに伴う処理によって構成されています。
for(式 1 ; 式 2 ; 式 3 )
処理;
式1は、ループの初期値を記述します。
式2は、ループの終了条件を記述します。
式2の結果が true であれば処理が実行され、false になるまでループ処理が実行されます。false になるとループ処理が終了します。
式2が、最初から false の場合は一度も処理されません。
式3は、繰り返し処理の後で計算されます。
for文は、while文で下記のように記述することもできます。
式1;
while(式2)
{
処理;
式 3 ;
};
for文においては、式1~式3のいずれも、省略する事が出来ますが、式1~式3を区切っている、セミコロン(;)は省略出来ません。
式2を省略した場合は、式2が常に true であると判定されます。
式1~式3の全てを省略した場合は、while文と同じ動作になります。
式1と式3は、それぞれカンマ(,)によって結合された、複数の式を使う事が出来ます。
while文と同様に、ループ処理の回数が多いと予想される場合は、IsStopped()関数を使用して、ループから抜ける処理を施すことが推奨されています。
for(x = 1; x <= 7000; x++)
{
if(IsStopped())
break;
Print(MathPower(x, 2));
}
//--- 例 2
for(; !IsStopped();)
{
Print(MathPower(x, 2));
x++;
if(x > 10)
break;
}
//--- 例 3
for(i = 0, j = n - l; i < n && !IsStopped(); i++, j--)
a[i] = a[j];
ループ処理 do while
for文とwhile文では、ループ処理の前に終了条件を判定しますが、
do while文は、ループ処理の後で終了条件を判定します。
そのため、ループ処理は、最低でも1回は行われます。
do
処理;
while(式);
最初に do 以降の処理が実行され、その後に while の条件式が判定されます。
その結果が true であれば、再び処理が実行され、この流れがループします。
条件式が false であれば、ループ処理が終了します。
こちらも、ループ処理の回数が多いと予想される場合は、IsStopped()関数を使用して、ループから抜ける処理を施すことが推奨されています。
//--- フィボナッチ数列を計算する
int counterFibonacci = 15;
int i = 0, first = 0, second = 1;
int currentFibonacciNumber;
do
{
currentFibonacciNumber = first + second;
Print("i = ", i, " currentFibonacciNumber = ", currentFibonacciNumber);
first = second;
second = currentFibonacciNumber;
i++; // この演算子なしでは無限ループが発生する
}
while(i < counterFibonacci && !IsStopped());
ループ終了 break
break処理は、最も近くにある外側の switch、while、do while、forループの処理から抜けます。
break処理の目的のひとつは、変数が特定の値になった場合に、ループ処理を終了させることです。
for(i = 0; i < array_size; i++)
if(array[i] == 0)
break; //配列の i が 0 の時、forループを抜ける
次のループへ continue
continue処理は、最も近くにある外側の while、do while、forループの処理の始まりに戻ります。
continue処理の目的は、変数が特定の値になった場合に、次のループ処理へ移行することです。
int func(int array[])
{
int array_size = ArraySize(array);
int sum = 0;
for(int i = 0; i < array_size; i++)
{
if(a[i] == 0)
continue; //配列の i が 0 の時、forループの始まりに戻る(下の行の sum += a[i];は処理されない)
sum += a[i]; //配列の i が 0 以外の時に処理される
}
return(sum);
}
クラスオブジェクト生成 new
new演算子は、対応する大きさのオブジェクトを自動的に作成し、オブジェクトのコンストラクタを呼び出し、 作成されたオブジェクトの記述子を返します。
エラーが発生した場合、NULLを返します。
new演算子は、クラスのオブジェクトのみ適用でき、構造体には適用できません。
new演算子は、オブジェクト配列の作成には使用できません。
オブジェクト配列の作成には、ArrayResize()関数を使用します。
//+------------------------------------------------------------------+
//| 図の作成 |
//+------------------------------------------------------------------+
void CTetrisField::NewShape()
{
m_ypos = HORZ_BORDER;
//--- 7 つの可能な図形から 1 つをランダムに選んで作成する
int nshape = rand() % 7;
switch(nshape)
{
case 0:
m_shape = new CTetrisShape1;
break;
case 1:
m_shape = new CTetrisShape2;
break;
case 2:
m_shape = new CTetrisShape3;
break;
case 3:
m_shape = new CTetrisShape4;
break;
case 4:
m_shape = new CTetrisShape5;
break;
case 5:
m_shape = new CTetrisShape6;
break;
case 6:
m_shape = new CTetrisShape7;
break;
}
//--- 描画する
if(m_shape != NULL)
{
//--- 事前設定
m_shape.SetRightBorder(WIDTH_IN_PIXELS + VERT_BORDER);
m_shape.SetYPos(m_ypos);
m_shape.SetXPos(VERT_BORDER + SHAPE_SIZE * 8);
//--- 描画する
m_shape.Draw();
}
//---
}
オブジェクト記述子は、メモリアドレスへのポインタではありません。
new演算子を使用して作成したオブジェクトは、明示的に delete 演算子を使用して削除します。
クラスオブジェクト削除 delete
delete演算子は、new演算子によって生成されたオブジェクトを削除し、オブジェクトが使用していたメモリを解放します。
オブジェクトが削除された後は、オブジェクト記述子は無効になります。
//--- 図を解除する
delete m_shape;
m_shape = NULL;
//--- 新しい図を作成する
NewShape();