選択(selection)

代入演算子(assignment operator)

int a = 13;
と書くと,aという変数名がついた箱の中に13という整数値が記録される.図で表すと
\begin{figure}\centering\includegraphics[width=1.8cm]{CPPPIC/pic3-1.eps}
\end{figure}
のような感じである.

このとき用いた"="は代入演算子とよばれ,代入記号の右側の値を左側の変数に代入することを意味する.数学の等号ではないことに注意が必要である.等号の左側に来ることができる値を左側値(lvalue)という.例えば,
int n;
n = 44;
は可能だが,
44 = n;
はエラーである.

複合代入演算子(Composite Assignment Operator)

演算子 意味
+= a += b a+bをaに代入
-= a -= b a-bをaに代入
*= a *= b a*bをaに代入
/= a /= b a/bをaに代入
%= a %= b a%bをaに代入

練習問題 3..1   複合代入演算子に慣れる
a = 33, b = 44のとき,a*bの結果をaに代入し表示するプログラムを複合演算子を用いて作成せよ.

型変換(Type Conversions)

    int n = 22;
    float x = 3.141592;
    x += n;
    cout << x - 2 << endl;
において,x += n;により,整数n=22は自動的にn=22.0に変換される.また,x - 2において,2は2.0に変換される. このように,小さな幅の型から大きな幅の型への変換は自動的に行なわれるが,大きな型から小さな型へ変換は自動的ではない.

一般に,Tがある型で,vが別の型の値であるとき,

T(v)

により,vは型Tに変換される.このことをキャスト(cast)という.キャストは,変数もしくは定数の前につけることで型の変換を行う.
型(変数) 型(定数)
例えば,nが浮動小数点型のとき,int(n)またはC言語スタイルの(int) nと書くと,nは小数点以下を全て無視して整数型になる.

例題 3..1   キャスト
次のプログラムは
double値をint値にキャストする.

#include <iostream>
using namespace std;
int main()
{
    double t = 1345.2567;
    int n = int(t);
    cout << "t = " << t << ", n = " << n << endl;
}

実行結果

\begin{figure}% latex2html id marker 791
\centering\includegraphics[width=8.7cm]{CPPPIC/reidai3-1.eps}
\end{figure}

小さい型から大きい型への変換はプロモーション(promotion)といい,そのための演算子は何も必要としない.

練習問題 3..2   キャスト
double t = 1345.2567;を2通りの方法で,整数にキャストし表示するプログラムを作成せよ.

入力ストリーム(Input Streams)

キーボードからの入力(標準入力)を取り込むのに便利なものに,cinという入力ストリームがある.

例題 3..2   キーボードからの入力
コマンドラインから自分の名前を打ち込んだら次の行に"こんにちは誰々さん"と表示するプログラムを考えよ.

解答 キーボードから入力した名前を保存するには,配列,文字配列,文字列とC++には色々用意されているが,ここでは配列char name[8]を用いる.char name[8]とは,8個の文字を格納する場所を持った変数で,その変数名がnameである.キーボードから入力した名前はcin $>>$ name;で配列nameに格納される.また,配列の中身を表示するには,cout $<<$ nameと書けばよい. では,プログラムを作成しよう.

#include <iostream>
using namespace std;
int main()
{
    char name[8];
    cout << "名前はなんですか ?" << endl;
    cin >> name;
    cout << "こんにちは" << name << "さん" << endl;
}

別解 文字列を用いると

#include <iostream>
#include <string>
using namespace std;
int main()
{
    string name;
    cout << "名前はなんですか ?" << endl;
    cin >> name;
    cout << "こんにちは" << name << "さん" << endl;
}
となる.

実行結果

\begin{figure}% latex2html id marker 818
\centering\includegraphics[width=8.7cm]{CPPPIC/reidai3-2.eps}
\end{figure}

この例題では,名前をコマンドラインから入力した.それに対して,次の例題では表示させるものをコマンドライン引数として使う. C++のmain関数はmain(int argc, char* argv[])と書け,最初のint argcは引数の個数を表し,char* argv[]は引数となる文字列を意味する.第1引数はargv[1]となる.

例題 3..3   コマンドライン引数
自分の名前を引数として打ち込んだら次の行に"こんにちは誰々さん"と表示するプログラムを考えよ.

解答 main(int args, char *argv[])において第1引数,横田は,argv[1]に代入される.では,プログラムを作成しよう.

#include <iostream>
using namespace std;
int main(int argc, char *argv[]){
    cout << "こんにちは" << argv[1] << "さん" << endl;
}

argv[0]には,このプログラムのディレクトリが入る.実行するには,プログラム名の後にスペースを空けて自分の名前を打ち込んでからリターンキーを押す.VisualC++を用いている場合は,実行ファイルがDebugフォルダに作成されているので,コマンドプロンプトを起動し,Debugフォルダの中のreidai3-3.exeをコマンドプロンプト上にコピー&ペーストすればよい.

実行結果

\begin{figure}% latex2html id marker 827
\centering\includegraphics[width=8.7cm]{CPPPIC/reidai3-3.eps}
\end{figure}

練習問題 3..3   コマンドライン引数
argv[1]とargv[2]は第1引数と第2引数となる.そこで,2つの引数EnglishとMathを用いて,"好きな科目はEnglish and Mathです"と表示するプログラムを作成せよ.

if文(if Statement) もし〜ならば〜する

\begin{figure}\centering\includegraphics[width=10.0cm]{CPPPIC/flowchart.eps}
\end{figure}

if文の記述法は次のようである.

    if (条件式) 文1;

ここで,条件式が0以外ならば,文1を実行する.

例題 3..4   整除可能性のテスト
2つの整数を用意し,1つがもう1つの整数で割れるか判断するプログラムを作成せよ.

解答 n%dは整数nを整数dで割ったときのあまりを表すので,n%dが零ならば割り切れ,そうでないならば割り切れないとなる.また,if文の条件式は0ならば正しくなく,0以外ならば正しいとなるので,if(n%d) cout $<<$ "割り切れない"; if(n%d == 0) cout $<<$ "割り切れる";と書くことができる.

#include %lt;iostream>
using namespace std;
int main()
{
    int n,d;
    cout << "2つの整数を入力してください." << endl;
    cin >> n >> d;
    if (n%d){
        cout << n << "は" << d << "で割り切れない." << endl;
    }     if (n%d == 0){
        cout << n << "は" << d << "で割り切れる." << endl;
    }
}

実行結果

\begin{figure}% latex2html id marker 856
\centering\includegraphics[width=8.9cm]{CPPPIC/reidai3-4.eps}
\end{figure}

練習問題 3..4   %の用い方
%と/を用いて整数34の並びを逆にするプログラムを作成せよ.

if文の後の中括弧{と}は,セミコロン;で終了する文が一つの時は必要ないが,私の美的センスで書いている.

if … else文(if else Statement) もし〜でなければ〜する

3..1   変数の場合

#include <iostream>
using namespace std;
    int main()
{
    int a = 0;
    if(a){
        cout << "aは0ではありません" << endl;
    }
    else {
        cout << "aは0です" << endl;
    }
}

実行結果

\begin{figure}% latex2html id marker 876
\centering\includegraphics[width=8.9cm]{CPPPIC/rei3-1.eps}
\end{figure}

3..2   式の場合

#include <iostream>
using namespace std;
int main()
{
    int a = 0, b = 1;
    if(a*b){
        cout << "a*bは0ではありません" << endl;
    }
    else {
        cout << "a*bは0です" << endl;
    }
}

実行結果

\begin{figure}% latex2html id marker 884
\centering\includegraphics[width=8.7cm]{CPPPIC/rei3-2.eps}
\end{figure}

分岐条件の組み合わせ − 論理演算子(Logical Operators)

分岐の条件は範囲の指定などのときに,複数組み合わせられる.その組み合わせには,主に論理積&&と,論理和||の演算が用いられる.

3..3   論理積(&&)の場合:xがaからbの間にある場合

#include <iostream>
using namespace std;
int main()
{
    int a = 1, b = 3, x= 2;
    if(a < x && x < b){
        cout << "xはaとbの間にある.";
    }
    else {
        cout << "xはaとbの間にはない.";
    }
}

実行結果

\begin{figure}% latex2html id marker 894
\centering\includegraphics[width=8.8cm]{CPPPIC/rei3-3.eps}
\end{figure}

3..4   論理和(||)の場合:xがa以下またはb以上にある場合

#include <iostream>
using namespace std;
int main()
{
    int a = 1, b = 2, x= 3;
    if(x < a || b < x){
        cout << "xはaとbの間にない.";
    }
    else {
        cout << "xはaとbの間にある.";
    }
}

実行結果

\begin{figure}% latex2html id marker 902
\centering\includegraphics[width=8.8cm]{CPPPIC/rei3-4.eps}
\end{figure}

単純な分岐(Selection)−等価演算子,関係演算子(Comparison Operator)

単純な分岐とは,条件式に1つの式だけを使った選択構造である.

おもに式としては,等価演算子(=),関係演算子(< >)が使用される.変数や式が単独で設定されることもある.その場合は,その評価値が0ならば偽,0以外ならば真という判定になる.

x $<$ y // xはyより小さい
x $>$ y // xはyより大きい
x $<=$ y // xはy以下である
x $>=$ y // xはy以上である
x $==$ y // xはyと等しい
x != y // xはyと等しくない

論理演算子(Logical Operators)

コンピュータの計算は論理演算を用いて行なわれる.基本的な論理演算には,論理積(AND)論理和(OR)論理否定(NOT)排他的論理和(EOR,XOR)がある.なお,論理否定は単に否定ともいう.

論理演算の結果をまとめたものを真理値表(truth table)といい,次のような表である.

A B 論理積 論理和 排他的論理和 論理否定
    AB A+B A B
0 0 0 0 0 1
0 1 0 1 1 1
1 0 0 1 1 0
1 1 1 1 0 0

また,排他的論理和は,論理積,論理和,否定を用いて次のように展開できる.

$\displaystyle A \oplus B = A \cdot {\bar B} + {\bar A} \cdot B$

条件式には&&(AND), $\vert\vert$(OR), !(not)の3つの論理演算子を用いることができる.真理値表より,次の結果を得る.
DeMoivreの定理
1. !(A $\vert\vert$ B) = !A && !B
2. !(A && B) = !A $\vert\vert$ !B
3. A $\vert\vert$ (B && C) = (A $\vert\vert$ B) && (A $\vert\vert$ C)
4. A && (B $\vert\vert$ C) = (A && B) $\vert\vert$ (A && C)

if文(if Statement):もし〜ならば〜する

例題 3..5   2数の比較
2つの異なる数字を読み取って比較し,大きい方を求めるプログラムを(if文だけを使って)作成せよ.

解答

変数aとbに呼び込んだ値を入れる.つぎに,aとbの値がどちらが大きいかを比較をする.もしaがbより大きいならばmaxはaである. もしbがaより大きいならばmaxはbであるとなる.では,プログラムを作成しよう.

#include <iostream>
using namespace std;
int main ()
{
    int a, b;
    cout << "2つの異なる整数を入力";
    cin >> a >> b;
    int max;
   
    if (a > b) {
        max = a;
    }
    if (b > a) {
        max = b;
    }
    cout << "大きい方は" << max;
}

実行結果

\begin{figure}% latex2html id marker 957
\centering\includegraphics[width=9.0cm]{CPPPIC/reidai3-5.eps}
\end{figure}

if-else 文(if-else Construct):もし〜ならば〜し,そうでなければ〜する

上の例題でa $>$ bが正しければ,maxはa.そうでなければmaxはbと直せる.つまりif-else文を用いて書いたほうが分かりやすい.

例題 3..6   if-else 文の例 2数の比較
2つの数字を読み取って比較し,大きい方を求めるプログラムを作成せよ.

解答

もしaがbより大きいならばmaxはaで,そうでなければmaxはbである.

#include <iostream>
using namespace std;
int main ()
{
    int a, b;
    cout << "2つの整数を入力" << endl;
    cin >> a >> b;
    int max;
    if (a > b) {
        max = a;
    }
    else {
        max = b;
    }
    cout << "大きい方は" << max << endl;
}

実行結果

\begin{figure}% latex2html id marker 969
\centering
\includegraphics[width=9.0cm]{CPPPIC/reidai3-6.eps}
\end{figure}

練習問題 3..5   if-else 文の例 3数の比較
3つの数字30, 10, 40を読み取って比較し,一番大きい数字を求めるプログラムを作成せよ.

else-if文(else-if Construct):もし〜ならば〜し,そうでなければ〜し,それでもなければ〜する

この構文はif-elseのelseに新たに条件が加わった形である.この構文は選択条件が3つ以上あっても対処できる.

練習問題 3..6   else-if 文の例 3数の比較
3つの数字30, 10, 40を読み取って比較し,一番大きい数字を求めるプログラムを作成せよ.

よくあるプログラムエラー(Common Programming Errors)

例題 3..7   プログラムエラー
次のプログラムの誤りを正せ.

#include <iostream>
using namespace std;
int main ()
{
    int n;
    cout << "整数を入力してください.";
    cin >> n;
    if (n=23){
        cout << "入力した整数は" << "23です" << endl;
    }
    else{
        cout << "入力した整数は" << "23ではありません" << endl;
    }
}

解答 if(n=23)は誤りである.条件はn==23でなければならない.=は代入演算子である.

Switch文(switch Construct)

C++言語にはelse-if文の代わりにswitch文とよばれるものがある.switch文で書けるものはすべてelse-if文で書ける.しかし,逆は真ではない.とは,言うものの,switch文で書かれたプログラムを読むこともあるので,簡単にswitch文の紹介をする.swith文の構文は次のようになる.

switch (式)
{
    case 定数式:文
    case 定数式:
    default:文
}

switch文の動作

「ステップ1」  
  式の値を求める
「ステップ2」  
  式の値が
  (1) caseの定数式と等しい場合,
  そのcaseに続く文にプログラムの制御が移り,実行される.
  (2) どのcaseとも等しくないが,defaultが存在するとき,
  defaultに続く文にプログラムの制御が移り,実行される.
  (3)どのcaseとも等しくなく,defaultが存在しないとき,
  プログラムの制御は,switch文の次の文に移る.

各caseには1つ以上の数値を持つ定数あるいは定数式による名札を付ける.Defaultという名札の付いたcaseは,他のcaseのどれもが満足されなかったときに実行される.

例題 3..8   順位の判定
入賞者の判別を行うプログラムを作成せよ.

解答

#include <iostream>
using namespace std;
int main ()
{
    int rank;
    cout << "あなたの順位は?>>>";
    cin >> rank;

    switch (rank)
    {
        case 1:
            cout << "優勝者には,海外旅行です" << endl;
            break;
        case 2:
            cout << "2位のあなたには,国内旅行です" << endl;
            break;
        case 3:
            cout << "3位のあなたには,図書券です" << endl;
            break;
            default:
            cout << "タオルをどうぞ" << endl;
            break;
    }
}

実行結果

\begin{figure}% latex2html id marker 1013
\centering
\includegraphics[width=9.1cm]{CPPPIC/reidai3-8.eps}
\end{figure}

練習問題 3..7   switch文の練習
列挙型Season{SPRING=0,SUMMER=1,FALL=2,WINTER=3}を用意し,好きな季節を番号で選んでもらい,switch文で春ならば,春はあけぼの,夏ならば,夏は夜,秋ならば,秋は夕暮,冬ならば,冬はつとめてと表示するプログラムを作成せよ.

else-if構造(else-if Construct) もし〜ならば〜し,そうでなければ〜し,そうでなければ〜し,...そうでなければ〜する.

例題 3..9   うるう年の判定
西暦年数
yearを入力し,うるう年かを判定するプログラムを作成せよ.

解答 うるう年とは400で割り切れる年数.または,4で割り切れ,かつ100で割り切れない年数のことである.例えば1900年はうるう年ではない.なぜならば,4と100の両方で割り切れてしまうからである.

これをプログラムにするには,if (year % 400 == 0)ならばうるう年.else if (year % 4 == 0 && year % 100 != 0)ならばうるう年.else うる年ではないとすればよい.ではプログラムを作成しよう.

#include <iostream>
using namespace std;
int main ()
{
    int year;
   cout << "西暦年を入力してください >>>;
   cin >> year;
   if(year%400 == 0){
      cout << year << "はうるう年です";
    }
    else if(year%4 == 0 && year%100 != 0) {
        cout << year << "はうるう年です";
    }
    else {
       cout << year << "はうるう年ではありません";
    }
}

実行結果

\begin{figure}% latex2html id marker 1037
\centering
\includegraphics[width=9.0cm]{CPPPIC/reidai3-9.eps}
\end{figure}

if(year%400 == 0)以降は次のように書くこともできる.

if(year%400 == 0 $\vert\vert$ year%4 == 0 && year%100 != 0)

練習問題 3..8   うるう年の判定
if(year%400 == 0 $\vert\vert$ year%4 == 0 && year%100 != 0)を用いて, うるう年判定プログラムを作成せよ.

例題 3..10   2次方程式の解
$ax^2 + bx + c = 0$の解を求めるプログラムを作成せよ.

解答

判別式は $D = b^{2} - 4ac$で与えられ,解の公式より,解は $x = (-b \pm \sqrt{D})/2a$で与えられる.よって

「係数aが0であり,係数bが0ならば,   (条件1)
  解はない (文1)
「係数aが0であり,係数bが0でなければ   (条件2)
  x= -c/b (文2)
「係数aが0でなく,判別式が正ならば   (条件3)
  実数解が2つ (文3)
「係数aが0でなく,判別式が0ならば   (条件4)
  実数解は1つ (文4)
「係数aが0でなく,判別式が負ならば   (条件5)
  複素数解が2つ (文5)

これよりif〜else文を組み合わせて判断を行う.平方根を計算するために,標準関数であるsqrt()を用いる.この関数は$<$cmath$>$ライブラリにあるので,$<$cmath$>$をインクルードする必要がある.

ではプログラムを作成しよう.

#include <iostream>
#include <cmath>
using namespace std;
int main ()
{
    double a,b,c;
    cout << "ax2+bx+cの実数a,b,cを間にスペースを入れて入力してください" << endl;
    cin >> a >> b >> c;
    double D = b*b -4*a*c;
    double x1 = (-b + sqrt(D))/(2*a);
    double x2 = (-b - sqrt(D))/(2*a);
    double x3 = -b/(2*a);
    double x4 = (sqrt(-D)/(2*a);
    if(a == 0.0 && b == 0.0){
        cout << "解はありません"<< endl;
    }
    else if(a == 0.0 && b != 0.0){
        x1 = -c/b;
        cout << "解は" << x1 << "です" << endl;
    }
    else if (D > 0.0){
        cout << "解は" << x1 << "と" << x2 << "です" << endl;
    }
    else if(D == 0){
        cout << "解は重解となり" << x1 << "です" << endl;
    }
    else {
    cout << "解は" << x3 << "+" << "i" << x4 << "と" << x3 << "-"
    << "i" << x4 << "です"<< endl;
    }
}

実行結果

\begin{figure}% latex2html id marker 1068
\centering\includegraphics[width=9.3cm]{CPPPIC/reidai3-10.eps}
\end{figure}

三項演算子(Ternary Operator)

C++には,if ... else文の代わりに用いることができる演算子がある.その演算子は三項演算子(ternary operator)と呼ばれ,その構文は次のようになる.

条件 ? 式文1 : 式文2;
ここで,条件が満たされると,式文1が実行され,満たされない場合は式文2が実行される. 例えば,構文
min = (x < y ? x : y);
は,xとyの小さい方をminに代入する.
三項演算子は条件と式文が単純なときに用いるくらいで,複雑な式文の時は用いないようにする.

例題 3..11   2数の比較
2つの数字を読み取って比較し,三項演算子を用いて大きい方を求めるプログラムを作成せよ.

解答

3項演算子(a $>$ b ? a:b)により大きいほうを取り出せる.

#include <iostream>
using namespace std;
int main ()
{
    int a, b;
    cout << "2つの整数を入力" << endl;
    cin >> a >> b;
    cout << "大きい方は" << (a > b ? a : b) << endl;
}

実行結果

\begin{figure}% latex2html id marker 1082
\centering
\includegraphics[width=8.4cm]{CPPPIC/reidai3-11.eps}
\end{figure}

練習問題 3..9   3数の最大値
3つの数字を読み取って比較し,三項演算子を用いて一番大きな数字を求めるプログラムを作成せよ.

スコープ(Scope)

識別子のスコープとは,その識別子を用いることができるプログラムの部分である.例えば,変数は宣言されるまで用いることはできない.よって,そのスコープはその変数が宣言されているところで始まる.

例題 3..12   変数のスコープ

#include <iostream>
using namespace std;
int main()
{
    x = 11; // エラー:これはxのスコープに入っていない.
    int x;
    { x= 22; // OK:これはxのスコープに入っている.
    y= 33; // エラー:これはyのスコープに入っていない.
    int y; // OK:これはyのスコープに入っている.
    x = 44; // OK:これはxのスコープに入っている.
    y = 55; // OK:これはyのスコープに入っている.
    }
    x = 66; // OK:これはxのスコープに入っている.
    y = 77; // エラー:これはyのスコープに入っていない.
}

xのスコープはxが宣言されたところからmain()の最後までである.yのスコープはyが宣言されたところからブロックの終了までである. $ \blacksquare$

例題 3..13   スコープの適用範囲
次のプログラムは何を表示するか考えよ.

#include <iostream>
using namespace std;
int x = 11;
int main()
{
    int x =22;
    {
        int x = 33;
       cout << "メインの中のブロックの中では,x = " << x << endl;
    }
    cout << "メインの中ではx = " << x << endl;
    cout << "メインの中でスコープ解決演算子::を用いるとx = " << ::x << endl;
}

解答

実行結果

\begin{figure}% latex2html id marker 1107
\centering
\includegraphics[width=10.9cm]{CPPPIC/reidai3-13.eps}
\end{figure}

確認問題 3..1  

1. 次の命題は正しいか調べよ.

a. !(p || q) と !p || !qは同値である.
b. !!!pと!pは同値である.
c. p && q || rはp && (q || r)と同値である.

2. 次のプログラムコードはどこが間違っているか.

if (x = 0) cout << x << " = 0\n";
else cout << x << " != 0\n";

3. 次の命題を表す論理式を作成せよ.

a. scoreは80以上で90よりも低い
b. answerは'N'か'Y'のどちらかである
c. nは3で割り切れるが,30では割り切れない
d. chは大文字である

4. 次のプログラムコードはどこがいけないか.

if (x == 0)
    if (y == 0) cout << "xとyは共に0です" << endl;
else cout << "xは0ではありません" << endl;

5. 次の式の値を求めよ. (x < y ? -1: (x == y ? 0 : 1));

6. xの絶対値をabsxに代入する文を3項演算子を用いて表せ.

演習問題 3..1  

1. 代入を使って,変数aとbの内容を壊さずに,入れ替えるプログラムを完成しよう.ただし,変数aとb以外に作業用として変数wを用いることとする.

#include <iostream>
using namespace std;
int main()
{
    int a,b,w;
    a=10;
    b=20;
    cout << "a = " << a;
    cout << "b = " << b;
    //入れ替え
    (ア)
    (イ)
    (ウ)
    cout << "\na=" << a;
    cout << "\nb=" << b << endl;
}

2. 次のプログラムで,出力時に値が変化する可能性があるのはどれか.

==============================================

1 #include $<$iostream$>$
2 using namespace std;
3 int main()
4 {
5 int i,j;
6 long l;
7 float f;
8 cin $>>$ i;
9 cin $>>$ l;
10 cin $>>$ f;
11 j=1;
12 i=int(l);
13 l=long(f);
14 f=float(l);
15 l=long(i);
16 i=j;
17 cout $<<$ i $<<$ endl $<<$ l $<<$ endl $<<$ f $<<$ endl;
18 }

==============================================

3. 次のプログラムを実行した結果を数値で答えよ.

#include <iostream>
using namespace std;
int main()
{
    int a,b;
    a=9;
    b=2;
    cout << "a/bの結果= " << a/b; /*整数どうしの割り算を行うと,結果は
整数で表される.*/
    cout << "a%bの結果=" << a << endl;
}