C++ 演算子を実装する

C++C++Beginner
今すぐ練習

💡 このチュートリアルは英語版からAIによって翻訳されています。原文を確認するには、 ここをクリックしてください

はじめに

この実験では、基本的な数学演算、インクリメント/デクリメント、関係演算子および論理演算子、ビット演算、複合代入、演算の順序、および三項条件演算子を含むさまざまな C++ 演算子を実装する方法を学びます。これらの基本演算子は、C++ プログラミングにおける算術演算、比較、およびデータ操作を行うために不可欠です。一連の実習問題を通じて、これらの演算子を効果的に活用して、より複雑で効率的な C++ アプリケーションを構築する方法を十分に理解するようになります。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL cpp(("C++")) -.-> cpp/BasicsGroup(["Basics"]) cpp(("C++")) -.-> cpp/ControlFlowGroup(["Control Flow"]) cpp(("C++")) -.-> cpp/IOandFileHandlingGroup(["I/O and File Handling"]) cpp(("C++")) -.-> cpp/StandardLibraryGroup(["Standard Library"]) cpp/BasicsGroup -.-> cpp/operators("Operators") cpp/ControlFlowGroup -.-> cpp/conditions("Conditions") cpp/ControlFlowGroup -.-> cpp/if_else("If...Else") cpp/IOandFileHandlingGroup -.-> cpp/output("Output") cpp/StandardLibraryGroup -.-> cpp/math("Math") subgraph Lab Skills cpp/operators -.-> lab-446084{{"C++ 演算子を実装する"}} cpp/conditions -.-> lab-446084{{"C++ 演算子を実装する"}} cpp/if_else -.-> lab-446084{{"C++ 演算子を実装する"}} cpp/output -.-> lab-446084{{"C++ 演算子を実装する"}} cpp/math -.-> lab-446084{{"C++ 演算子を実装する"}} end

基本的な数学演算を行う(+、-、*、/、%)

このステップでは、C++ において基本的な数学演算を行う方法を学びます。数学演算はプログラミングの基礎であり、標準の算術演算子を使って数値を操作することができます。

WebIDE を開き、~/projectディレクトリに新しいファイルmath_operations.cppを作成します。

touch ~/project/math_operations.cpp

math_operations.cppファイルに次のコードを追加します。

#include <iostream>

int main() {
    // 数学演算用の変数を宣言する
    int a = 10;
    int b = 3;

    // 加算(+)
    int sum = a + b;
    std::cout << "加算:" << a << " + " << b << " = " << sum << std::endl;

    // 減算(-)
    int difference = a - b;
    std::cout << "減算:" << a << " - " << b << " = " << difference << std::endl;

    // 乗算(\*)
    int product = a * b;
    std::cout << "乗算:" << a << " \* " << b << " = " << product << std::endl;

    // 除算(/)
    int quotient = a / b;
    std::cout << "除算:" << a << " / " << b << " = " << quotient << std::endl;

    // 剰余(%)- 除算の余り
    int remainder = a % b;
    std::cout << "剰余:" << a << " % " << b << " = " << remainder << std::endl;

    return 0;
}

このプログラムをコンパイルして実行します。

g++ math_operations.cpp -o math_operations
./math_operations

実行結果の例:

加算: 10 + 3 = 13
減算: 10 - 3 = 7
乗算: 10 \* 3 = 30
除算: 10 / 3 = 3
剰余: 10 % 3 = 1

数学演算子を分解してみましょう。

  1. +(加算):2 つの数値を加算します。たとえば、5 + 38になります。
  2. -(減算):最初の数値から 2 番目の数値を引きます。たとえば、10 - 46になります。
  3. *(乗算):2 つの数値を乗算します。たとえば、6 * 742になります。
  4. /(除算):最初の数値を 2 番目の数値で割ります。両方の数値が整数の場合、整数除算になり、小数部分は切り捨てられます。たとえば、10 / 33になります。
  5. %(剰余):除算の余りを返します。たとえば、10 % 31になります。なぜなら、10 を 3 で割った余りは 1 だからです。

いくつかの重要なポイント:

  • 整数除算では小数部分が切り捨てられます。たとえば、5 / 22になり、2.5にはなりません。
  • 剰余演算子は整数型のみで動作します。浮動小数点数型(floatdoubleなど)では使用できません。
  • ゼロ除算には常に注意が必要です。ゼロでの除算は実行時エラーを引き起こします。ゼロでの除算を試みると、プログラムがクラッシュします。

前置と後置のインクリメント/デクリメントを使用する(++i、i++)

このステップでは、C++ におけるインクリメント演算子とデクリメント演算子について学びます。これらの演算子を使うと、変数の値を 1 増やしたり減らしたりすることができますが、前置インクリメントと後置インクリメントには微妙な違いがあります。

WebIDE を開き、~/projectディレクトリに新しいファイルincrement_decrement.cppを作成します。

touch ~/project/increment_decrement.cpp

increment_decrement.cppファイルに次のコードを追加します。

#include <iostream>

int main() {
    // 前置インクリメント(++i)
    int a = 5;
    std::cout << "a の元の値:" << a << std::endl;

    // 前置インクリメント:値が使用される前にインクリメントが行われます
    std::cout << "前置インクリメント(++a): " << ++a << std::endl;
    std::cout << "前置インクリメント後の値:" << a << std::endl;

    // 後置インクリメント(i++)
    int b = 5;
    std::cout << "\nb の元の値:" << b << std::endl;

    // 後置インクリメント:値が使用された後にインクリメントが行われます
    std::cout << "後置インクリメント(b++): " << b++ << std::endl;
    std::cout << "後置インクリメント後の値:" << b << std::endl;

    // デクリメント演算子も同様に動作します
    int c = 5;
    std::cout << "\n前置デクリメント(--c): " << --c << std::endl;

    int d = 5;
    std::cout << "後置デクリメント(d--): " << d-- << std::endl;
    std::cout << "後置デクリメント後の値:" << d << std::endl;

    return 0;
}

このプログラムをコンパイルして実行します。

g++ increment_decrement.cpp -o increment_decrement
./increment_decrement

実行結果の例:

aの元の値: 5
前置インクリメント(++a): 6
前置インクリメント後の値: 6

bの元の値: 5
後置インクリメント(b++): 5
後置インクリメント後の値: 6

前置デクリメント(--c): 4
後置デクリメント(d--): 5
後置デクリメント後の値: 4

主な違い:

  • 前置インクリメント++i:式で使用される前に値をインクリメントします。コード例では、++aはまずaを 6 にインクリメントし、その後cout文で値 6 が使用されます。
  • 後置インクリメントi++:まず式で現在の値を使用し、その後値をインクリメントします。コード例では、b++はまずcout文でbの現在の値である 5 を使用し、その後bを 6 にインクリメントします。

同じ原則がデクリメント演算子--ii--にも当てはまります。--iはまずデクリメントしてから値を使用し、i--はまず値を使用してからデクリメントします。

重要なポイント:

  • 前置インクリメントは式で使用される前に値を変更します。つまり、インクリメントされた値がすぐに使用できるようになります。
  • 後置インクリメントはまず元の値を使用し、その後インクリメントします。これは、現在の文では元の値が得られ、次の文ではインクリメントされた値が得られることを意味します。
  • これらの演算子は、ループ(たとえばforループ)や複雑な式で変数を変更しながらその値も使用したい場合に一般的に使用されます。
  • これらの演算子を使用する場合、特に複雑な式では、意図した動作を得るために前置版と後置版のどちらを使用するかを念頭に置くことが重要です。

関係演算子を使用して値を比較する(<、>、==、!=)

このステップでは、C++ における関係演算子について学びます。これらの演算子は、値を比較し、異なる数値または変数間の関係を判断するのに役立ちます。

WebIDE を開き、~/projectディレクトリに新しいファイルrelational_operators.cppを作成します。

touch ~/project/relational_operators.cpp

relational_operators.cppファイルに次のコードを追加します。

#include <iostream>

int main() {
    int a = 10;
    int b = 5;
    int c = 10;

    // 未満(<)
    std::cout << "未満(<):" << std::endl;
    std::cout << a << " < " << b << " は " << (a < b) << std::endl;
    std::cout << b << " < " << a << " は " << (b < a) << std::endl;

    // より大きい(>)
    std::cout << "\nより大きい(>):" << std::endl;
    std::cout << a << " > " << b << " は " << (a > b) << std::endl;
    std::cout << b << " > " << a << " は " << (b > a) << std::endl;

    // 等しい(==)
    std::cout << "\n等しい(==):" << std::endl;
    std::cout << a << " == " << b << " は " << (a == b) << std::endl;
    std::cout << a << " == " << c << " は " << (a == c) << std::endl;

    // 等しくない(!=)
    std::cout << "\n等しくない(!=):" << std::endl;
    std::cout << a << "!= " << b << " は " << (a!= b) << std::endl;
    std::cout << a << "!= " << c << " は " << (a!= c) << std::endl;

    return 0;
}

このプログラムをコンパイルして実行します。

g++ relational_operators.cpp -o relational_operators
./relational_operators

実行結果の例:

未満(<):
10 < 5 は 0
5 < 10 は 1

より大きい(>):
10 > 5 は 1
5 > 10 は 0

等しい(==):
10 == 5 は 0
10 == 10 は 1

等しくない(!=):
10!= 5 は 1
10!= 10 は 0

関係演算子に関する要点:

  • <(未満):左辺の値が右辺の値より小さいかどうかを確認します。たとえば、5 < 10は真(1 を返す)ですが、10 < 5は偽(0 を返す)です。
  • >(より大きい):左辺の値が右辺の値より大きいかどうかを確認します。たとえば、10 > 5は真(1 を返す)ですが、5 > 10は偽(0 を返す)です。
  • ==(等しい):2 つの値が正確に等しいかどうかを確認します。たとえば、5 == 5は真(1 を返す)ですが、5 == 6は偽(0 を返す)です。
  • !=(等しくない):2 つの値が等しくないかどうかを確認します。たとえば、5!= 6は真(1 を返す)ですが、5!= 5は偽(0 を返す)です。
  • これらの演算子は1(真)または0(偽)を返します。C++ では、1は真を表し、0は偽を表します。これらの値は条件文で使用できます。

重要なポイント:

  • 関係演算子は条件文を作成するための基本であり、プログラムが比較に基づいて決定を行うことを可能にします。
  • 常にブール値を返します。C++ では整数で表されます(真は 1、偽は 0)。
  • これらの演算子は一般的にif文、whileループ、forループで使用され、実行の流れを制御します。

論理積(&&)と論理和(||)を使って条件を結合する

このステップでは、C++ において論理積(&&)と論理和(||)演算子を使って複数の条件を結合する方法を学びます。これらの演算子は、複数の条件を評価することで、より複雑な条件文を作成するのに役立ちます。

WebIDE を開き、~/projectディレクトリに新しいファイルlogical_operators.cppを作成します。

touch ~/project/logical_operators.cpp

logical_operators.cppファイルに次のコードを追加します。

#include <iostream>

int main() {
    int x = 10;
    int y = 5;
    int z = 15;

    // 論理積(&&)演算子
    std::cout << "論理積(&&)演算子:" << std::endl;

    // 両方の条件が真でなければならない
    if (x > y && x < z) {
        std::cout << "x は y より大きく、かつ z より小さい" << std::endl;
    }

    if (x > 20 && y < 10) {
        std::cout << "これは表示されません" << std::endl;
    }

    // 論理和(||)演算子
    std::cout << "\n論理和(||)演算子:" << std::endl;

    // 少なくとも 1 つの条件が真でなければならない
    if (x > 20 || y < 10) {
        std::cout << "少なくとも 1 つの条件が真です" << std::endl;
    }

    if (x > 20 || z < 20) {
        std::cout << "もう 1 つの真の条件" << std::endl;
    }

    // 論理積と論理和を組み合わせる
    std::cout << "\n論理積と論理和を組み合わせる:" << std::endl;

    if ((x > y && y < z) || x == 10) {
        std::cout << "複雑な条件が真です" << std::endl;
    }

    return 0;
}

このプログラムをコンパイルして実行します。

g++ logical_operators.cpp -o logical_operators
./logical_operators

実行結果の例:

論理積(&&)演算子:
xはyより大きく、かつzより小さい

論理和(||)演算子:
少なくとも1つの条件が真です
もう1つの真の条件

論理積と論理和を組み合わせる:
複雑な条件が真です

論理演算子に関する要点:

  • &&(論理積):&&で結ばれた両方の条件が真でなければ、式全体が真になりません。どちらかの条件が偽であれば、式全体は偽と評価されます。コードでは、x > y && x < zは真です。なぜなら、x > y(10 > 5)とx < z(10 < 15)の両方が真だからです。
  • ||(論理和):||で結ばれた条件の少なくとも 1 つが真でなければ、式全体が真になりません。すべての条件が偽であれば、式全体は偽と評価されます。コードでは、x > 20 || y < 10は真です。なぜなら、y < 10(5 < 10)が真だからです。
  • 括弧を使って評価の順序を制御することで、複数の条件を組み合わせることができます。これにより、複雑な式を読みやすく理解しやすくすることができます。
  • これらの演算子は、条件文内で複雑な判断ロジックを作成する際に非常に役立ちます。

重要なポイント:

  • 論理演算子は、if文、whileループ、その他の制御フロー構造で頻繁に使用され、プログラムをより汎用的にするのに役立ちます。
  • 複数の基準を同時にチェックすることができるため、より洗練された条件チェックを行うのに役立ちます。
  • 短絡評価
    • &&の場合、最初の条件が偽であれば、2 番目の条件は評価されません。なぜなら、2 番目の条件が何であれ、式全体は偽になるからです。この最適化により、パフォーマンスが向上します。
    • ||の場合、最初の条件が真であれば、2 番目の条件は評価されません。なぜなら、式全体は真になるからです。

バイナリ操作にビット演算を適用する

このステップでは、C++ におけるビット演算子について学びます。これらの演算子は整数のバイナリ表現に直接作用し、個々のビットを操作することができます。

WebIDE を開き、~/projectディレクトリに新しいファイルbitwise_operations.cppを作成します。

touch ~/project/bitwise_operations.cpp

bitwise_operations.cppファイルに次のコードを追加します。

#include <iostream>
#include <bitset>

int main() {
    // 数値のバイナリ表現
    unsigned int a = 5;   // 2 進数では 0101
    unsigned int b = 3;   // 2 進数では 0011

    // ビット論理積(&)
    std::cout << "ビット論理積(&):" << std::endl;
    std::cout << "a = " << std::bitset<4>(a) << " (10 進数で 5)" << std::endl;
    std::cout << "b = " << std::bitset<4>(b) << " (10 進数で 3)" << std::endl;
    unsigned int and_result = a & b;
    std::cout << "a & b = " << std::bitset<4>(and_result)
              << " (" << and_result << " 10 進数で)" << std::endl;

    // ビット論理和(|)
    std::cout << "\nビット論理和(|):" << std::endl;
    unsigned int or_result = a | b;
    std::cout << "a | b = " << std::bitset<4>(or_result)
              << " (" << or_result << " 10 進数で)" << std::endl;

    // ビット排他的論理和(^)
    std::cout << "\nビット排他的論理和(^):" << std::endl;
    unsigned int xor_result = a ^ b;
    std::cout << "a ^ b = " << std::bitset<4>(xor_result)
              << " (" << xor_result << " 10 進数で)" << std::endl;

    // ビット否定(~)
    std::cout << "\nビット否定(~):" << std::endl;
    unsigned int not_result = ~a;
    std::cout << "~a = " << std::bitset<32>(not_result)
              << " (" << not_result << " 10 進数で)" << std::endl;

    // 左シフト(<<)
    std::cout << "\n左シフト(<<):" << std::endl;
    unsigned int left_shift = a << 2;
    std::cout << "a << 2 = " << std::bitset<8>(left_shift)
              << " (" << left_shift << " 10 進数で)" << std::endl;

    // 右シフト(>>)
    std::cout << "\n右シフト(>>):" << std::endl;
    unsigned int right_shift = a >> 1;
    std::cout << "a >> 1 = " << std::bitset<4>(right_shift)
              << " (" << right_shift << " 10 進数で)" << std::endl;

    return 0;
}

このプログラムをコンパイルして実行します。

g++ bitwise_operations.cpp -o bitwise_operations
./bitwise_operations

実行結果の例:

ビット論理積(&):
a = 0101 (10進数で5)
b = 0011 (10進数で3)
a & b = 0001 (10進数で1)

ビット論理和(|):
a | b = 0111 (10進数で7)

ビット排他的論理和(^):
a ^ b = 0110 (10進数で6)

ビット否定(~):
~a = 11111111111111111111111111111010 (10進数で4294967290)

左シフト(<<):
a << 2 = 00010100 (10進数で20)

右シフト(>>):
a >> 1 = 0010 (10進数で2)

ビット演算子に関する要点:

  • &(論理積):2 つの数値の対応するビットを比較します。両方のビットが 1 の場合、結果のビットは 1 になります。それ以外の場合は 0 になります。コード例では、5 & 3(2 進数で0101 & 0011)の結果は0001で、10 進数で 1 になります。
  • |(論理和):2 つの数値の対応するビットを比較します。少なくとも 1 つのビットが 1 の場合、結果のビットは 1 になります。それ以外の場合は 0 になります。例では、5 | 3(2 進数で0101 | 0011)の結果は0111で、10 進数で 7 になります。
  • ^(排他的論理和):2 つの数値の対応するビットを比較します。ビットが異なる場合、結果のビットは 1 になります。それ以外の場合は 0 になります。例では、5 ^ 3(2 進数で0101 ^ 0011)の結果は0110で、10 進数で 6 になります。
  • ~(否定):数値のすべてのビットを反転させます。ビットが 1 の場合は 0 に、0 の場合は 1 になります。出力~a11111111111111111111111111111010で、これは数値を 32 ビットの符号なし整数として扱ったときの結果のバイナリ表現です。
  • <<(左シフト):数値のビットを指定された数のポジションだけ左にシフトします。シフトするごとに、数値は実質的に 2 倍になります。例では、5 << 2(2 進数で0101 << 2)はビットをシフトして010100になり、10 進数で 20 になります。
  • >>(右シフト):数値のビットを指定された数のポジションだけ右にシフトします。シフトするごとに、数値は実質的に 2 で割られます。例では、5 >> 1(2 進数で0101 >> 1)はビットをシフトして0010になり、10 進数で 2 になります。

重要なポイント:

  • ビット演算は整数のバイナリ表現に直接作用し、低レベルの操作と最適化を可能にします。
  • これらは、エンベデッドシステム、グラフィックスプログラミング、および値内の個々のビットを設定、クリア、またはテストする必要があるシナリオで一般的に使用されます。
  • 符号付き整数と符号なし整数に注意が必要です。右シフトの動作は異なる場合があります(算術シフトと論理シフト)。
  • std::bitsetを使用すると、これらの演算がビットレベルでどのように機能するかを視覚化するのに役立ちます。

複合代入演算子(+=、-=、*=)を使用する

このステップでは、C++ における複合代入演算子について学びます。これらの演算子は、算術演算と代入を組み合わせることで、コードをより簡潔で読みやすくします。

WebIDE を開き、~/projectディレクトリに新しいファイルcompound_operators.cppを作成します。

touch ~/project/compound_operators.cpp

compound_operators.cppファイルに次のコードを追加します。

#include <iostream>

int main() {
    // 変数を初期化する
    int x = 10;
    int y = 5;

    // 加算代入(+=)
    std::cout << "加算代入(+=):" << std::endl;
    std::cout << "初期の x: " << x << std::endl;
    x += 3;  // x = x + 3 と同等
    std::cout << "x += 3: " << x << std::endl;

    // 減算代入(-=)
    std::cout << "\n減算代入(-=):" << std::endl;
    std::cout << "初期の y: " << y << std::endl;
    y -= 2;  // y = y - 2 と同等
    std::cout << "y -= 2: " << y << std::endl;

    // 乗算代入(\*=)
    std::cout << "\n乗算代入(\*=):" << std::endl;
    int z = 4;
    std::cout << "初期の z: " << z << std::endl;
    z \*= 3;  // z = z \* 3 と同等
    std::cout << "z \*= 3: " << z << std::endl;

    // 除算代入(/=)
    std::cout << "\n除算代入(/=):" << std::endl;
    int a = 15;
    std::cout << "初期の a: " << a << std::endl;
    a /= 3;  // a = a / 3 と同等
    std::cout << "a /= 3: " << a << std::endl;

    // 剰余代入(%=)
    std::cout << "\n剰余代入(%=):" << std::endl;
    int b = 17;
    std::cout << "初期の b: " << b << std::endl;
    b %= 5;  // b = b % 5 と同等
    std::cout << "b %= 5: " << b << std::endl;

    return 0;
}

このプログラムをコンパイルして実行します。

g++ compound_operators.cpp -o compound_operators
./compound_operators

実行結果の例:

加算代入(+=):
初期のx: 10
x += 3: 13

減算代入(-=):
初期のy: 5
y -= 2: 3

乗算代入(\*=):
初期のz: 4
z \*= 3: 12

除算代入(/=):
初期のa: 15
a /= 3: 5

剰余代入(%=):
初期のb: 17
b %= 5: 2

複合代入演算子に関する要点:

  • +=(加算して代入):右辺の演算子を左辺の演算子に加え、結果を左辺の演算子に代入します。x += 3x = x + 3と同等です。
  • -=(減算して代入):右辺の演算子を左辺の演算子から引き、結果を左辺の演算子に代入します。y -= 2y = y - 2と同等です。
  • *=(乗算して代入):左辺の演算子を右辺の演算子で乗算し、結果を左辺の演算子に代入します。z *= 3z = z * 3と同等です。
  • /=(除算して代入):左辺の演算子を右辺の演算子で除算し、結果を左辺の演算子に代入します。a /= 3a = a / 3と同等です。
  • %=(剰余を求めて代入):左辺の演算子を右辺の演算子で割った剰余を求め、結果を左辺の演算子に代入します。b %= 5b = b % 5と同等です。

重要なポイント:

  • 複合代入演算子は、演算と代入を 1 ステップで組み合わせることで、コードをより簡潔で読みやすくします。
  • すべての基本的な算術演算(+、-、*、/、%)と共に機能します。
  • 入力を減らし、コードを短くすることができ、場合によってはパフォーマンスも向上させることができます。

複数の演算子を使った演算の順序を理解する

このステップでは、C++ における演算の順序について学びます。これは、しばしば略語 PEMDAS(丸括弧、指数、乗算と除算、加算と減算)で覚えられます。この順序を理解することは、正しい数学的式を書くために重要です。

WebIDE を開き、~/projectディレクトリに新しいファイルorder_of_operations.cppを作成します。

touch ~/project/order_of_operations.cpp

order_of_operations.cppファイルに次のコードを追加します。

#include <iostream>

int main() {
    // 基本的な演算の順序の示し方
    int a = 10;
    int b = 5;
    int c = 3;

    // 加算よりも乗算が先に行われる
    std::cout << "加算よりも乗算が先に行われる:" << std::endl;
    int result1 = a + b * c;
    std::cout << "a + b * c = " << result1 << std::endl;

    // 丸括弧が演算の順序を変える
    std::cout << "\n丸括弧が順序を変える:" << std::endl;
    int result2 = (a + b) * c;
    std::cout << "(a + b) * c = " << result2 << std::endl;

    // 複数の演算子を含む複雑な式
    std::cout << "\n複雑な式:" << std::endl;
    int x = 4;
    int y = 2;
    int z = 3;

    int complex_result = x + y * z - (x / y);
    std::cout << "x + y * z - (x / y) = " << complex_result << std::endl;

    // インクリメントと乗算の優先順位の示し方
    std::cout << "\nインクリメントと乗算:" << std::endl;
    int m = 3;
    int n = 2;
    int precedence_result = m++ * n;
    std::cout << "m++ * n = " << precedence_result << std::endl;
    std::cout << "演算後の m = " << m << std::endl;

    return 0;
}

このプログラムをコンパイルして実行します。

g++ order_of_operations.cpp -o order_of_operations
./order_of_operations

実行結果の例:

加算よりも乗算が先に行われる:
a + b * c = 25

丸括弧が順序を変える:
(a + b) * c = 45

複雑な式:
x + y * z - (x / y) = 8

インクリメントと乗算:
m++ * n = 6
演算後のm = 4

演算の順序に関する要点:

  • 演算の順序は、演算子の優先順位とも呼ばれ、式がどのように評価されるかを決定します。C++ はこれについて数学の規則に従います。
  • PEMDAS/BODMAS:これは順序を覚えるための一般的なメモリ助けです。
    • Parentheses / Brackets:丸括弧または角括弧内の式は最初に評価されます。
    • Exponents / Orders:指数または累乗(平方根のようなもの)は次に評価されます。ただし、C++ には組み込みの指数演算子はありません。このステップはpow()のような演算を指します。
    • MD 乗算と除算:乗算と除算は同じ優先順位であり、左から右に評価されます。
    • AS 加算と減算:加算と減算は同じ優先順位であり、左から右に評価されます。
  • コードのint result1 = a + b * c;10 + (5 * 3)と評価され、10 + 15 = 25になります。なぜなら、乗算は加算よりも優先順位が高いからです。
  • 丸括弧はデフォルトの演算順序を上書きできます。式int result2 = (a + b) * c;(10 + 5) * 3と評価され、15 * 3 = 45になります。なぜなら、丸括弧内の式が最初に計算されるからです。
  • インクリメント/デクリメント演算子には特定の優先順位の規則があり、時に混乱することがあります。コードで使用されている後置インクリメント演算子m++の場合、乗算m * nでは最初にmの元の値が使用され、その後に変数mがインクリメントされます。
  • 複雑な式x + y * z - (x / y)では、乗算と除算は加算と減算よりも先に行われます。丸括弧により、整数除算x / yが最初に行われることが保証されます。
  • 常に意図を明確にするために丸括弧を使用してください。特に複雑な式の場合。これはコードを読みやすくするだけでなく、式が意図通りに評価されることを保証します。

重要なポイント:

  • PEMDAS/BODMASは式がどのように評価されるかを予測するのに役立ちますが、C++には組み込みの指数演算子がないことを覚えておいてください。
  • 疑問がある場合は、順序を明示的に定義するために丸括弧を使用してください。これにより、コードが明確になり、誤解された優先順位によるエラーを防ぐことができます。
  • 一部の演算子は同じ優先順位であり、左から右に評価されます。たとえば、a - b + cの場合、減算が加算よりも先に行われます。
  • 丸括弧を使用せずに単一の式に複数の演算子を組み合わせる場合、特に注意が必要です。演算子の優先順位を正しく理解していないと、微妙なバグが発生する可能性があります。

三項条件演算子を使って練習する

このステップでは、三項条件演算子について学びます。これは、単一行で簡単な if-else 文を書くためのコンパクトな方法です。この演算子は、コード内で判断を行うための簡潔な方法を提供します。

WebIDE を開き、~/projectディレクトリに新しいファイルternary_operator.cppを作成します。

touch ~/project/ternary_operator.cpp

ternary_operator.cppファイルに次のコードを追加します。

#include <iostream>

int main() {
    // 基本的な三項演算子の構文
    // 条件?真の場合の値 : 偽の場合の値

    // 単純な比較
    int x = 10;
    int y = 5;

    // 大きい方の数を決定する
    int max_value = (x > y)? x : y;
    std::cout << "大きい方の値:" << max_value << std::endl;

    // 数が偶数か奇数かをチェックする
    int number = 7;
    std::string result = (number % 2 == 0)? "偶数" : "奇数";
    std::cout << number << " は " << result << std::endl;

    // ネストした三項演算子
    int a = 15;
    std::string category = (a < 10)? "小"
                         : (a < 20)? "中"
                         : "大";
    std::cout << "カテゴリ:" << category << std::endl;

    // 関数呼び出しを伴う三項演算子
    int abs_value = (x < 0)? -x : x;
    std::cout << "x の絶対値:" << abs_value << std::endl;

    // 出力内の三項演算子
    std::cout << "x は y より大きいですか? "
              << ((x > y)? "はい" : "いいえ") << std::endl;

    return 0;
}

このプログラムをコンパイルして実行します。

g++ ternary_operator.cpp -o ternary_operator
./ternary_operator

実行結果の例:

大きい方の値: 10
7 は 奇数
カテゴリ: 中
xの絶対値: 10
xはyより大きいですか? はい

三項演算子に関する要点:

  • 構文条件? 真の場合の値 : 偽の場合の値。これは、単一行で if-else 文を書くための省略記法です。
  • 条件が評価されます。条件が真の場合、式は真の場合の値を返します。それ以外の場合は、偽の場合の値を返します。
  • コード内のint max_value = (x > y)? x : y;は、xyの間で大きい方の数を決定します。xyより大きい場合、max_valuexが代入されます。それ以外の場合は、yが代入されます。xが 10 でyが 5 なので、max_value10になります。
  • std::string result = (number % 2 == 0)? "偶数" : "奇数";は、剰余演算子%を使って数が偶数か奇数かをチェックします。チェックの結果に応じて、結果は「偶数」または「奇数」となり、文字列変数resultに代入されます。
  • 三項演算子はネストできますが、そうするとコードが読みにくくなることがあります。例では、ネストした三項演算子は、整数aの値に応じて文字列「小」、「中」、または「大」を変数categoryに代入します。
  • int abs_value = (x < 0)? -x : x;の例は、三項演算子を使ってxの絶対値を取得する方法を示しています。xが負の場合、xを否定することで絶対値に変換します。それ以外の場合は、そのままxを返します。
  • 最後の例は、三項演算子の結果を直接出力する方法を示しています。std::cout << "xはyより大きいですか? " << ((x > y)? "はい" : "いいえ") << std::endl;

重要なポイント:

  • コードの読みやすさを維持するために控えめに使用してください。三項演算子、特にネストしたものを過度に使用すると、コードが追いにくくなります。
  • 複雑すぎる場合、読みにくくなることがあります。複雑な判断は、通常、完全な if-else ブロックで表現する必要があります。
  • 主に、2 つの値のうち 1 つを返すか代入する簡単で明確な条件に使用されます。

まとめ

この実験では、C++ において加算、減算、乗算、除算、剰余などの基本的な数学演算を行う方法を学びました。また、前置および後置のインクリメント/デクリメント演算子の使用方法を調べ、それらの微妙な違いを理解しました。さらに、値を効果的に比較および結合するための関係演算子および論理演算子について学びました。また、バイナリ操作のためのビット演算と代入との算術演算を単純化および凝縮するための複合代入演算子を練習しました。最後に、複数の演算子を持つ演算の順序を理解し、簡潔な条件文に三項条件演算子を使用しました。これらの基本概念は、堅牢で効率的な C++ プログラムを構築するために不可欠です。これらの基本演算子をマスターすることで、より複雑なコーディングチャレンジに対処する準備ができます。