はじめに
この実験では、基本的な数学演算、インクリメント/デクリメント、関係演算子および論理演算子、ビット演算、複合代入、演算の順序、および三項条件演算子を含むさまざまな C++ 演算子を実装する方法を学びます。これらの基本演算子は、C++ プログラミングにおける算術演算、比較、およびデータ操作を行うために不可欠です。一連の実習問題を通じて、これらの演算子を効果的に活用して、より複雑で効率的な C++ アプリケーションを構築する方法を十分に理解するようになります。
この実験では、基本的な数学演算、インクリメント/デクリメント、関係演算子および論理演算子、ビット演算、複合代入、演算の順序、および三項条件演算子を含むさまざまな C++ 演算子を実装する方法を学びます。これらの基本演算子は、C++ プログラミングにおける算術演算、比較、およびデータ操作を行うために不可欠です。一連の実習問題を通じて、これらの演算子を効果的に活用して、より複雑で効率的な C++ アプリケーションを構築する方法を十分に理解するようになります。
このステップでは、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
数学演算子を分解してみましょう。
+
(加算):2 つの数値を加算します。たとえば、5 + 3
は8
になります。-
(減算):最初の数値から 2 番目の数値を引きます。たとえば、10 - 4
は6
になります。*
(乗算):2 つの数値を乗算します。たとえば、6 * 7
は42
になります。/
(除算):最初の数値を 2 番目の数値で割ります。両方の数値が整数の場合、整数除算になり、小数部分は切り捨てられます。たとえば、10 / 3
は3
になります。%
(剰余):除算の余りを返します。たとえば、10 % 3
は1
になります。なぜなら、10 を 3 で割った余りは 1 だからです。いくつかの重要なポイント:
5 / 2
は2
になり、2.5
にはなりません。float
やdouble
など)では使用できません。このステップでは、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 にインクリメントします。同じ原則がデクリメント演算子--i
とi--
にも当てはまります。--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
は偽を表します。これらの値は条件文で使用できます。重要なポイント:
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 になります。出力~a
は11111111111111111111111111111010
で、これは数値を 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 += 3
はx = x + 3
と同等です。-=
(減算して代入):右辺の演算子を左辺の演算子から引き、結果を左辺の演算子に代入します。y -= 2
はy = y - 2
と同等です。*=
(乗算して代入):左辺の演算子を右辺の演算子で乗算し、結果を左辺の演算子に代入します。z *= 3
はz = z * 3
と同等です。/=
(除算して代入):左辺の演算子を右辺の演算子で除算し、結果を左辺の演算子に代入します。a /= 3
はa = a / 3
と同等です。%=
(剰余を求めて代入):左辺の演算子を右辺の演算子で割った剰余を求め、結果を左辺の演算子に代入します。b %= 5
はb = b % 5
と同等です。重要なポイント:
このステップでは、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
演算の順序に関する要点:
pow()
のような演算を指します。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
が最初に行われることが保証されます。重要なポイント:
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;
は、x
とy
の間で大きい方の数を決定します。x
がy
より大きい場合、max_value
にx
が代入されます。それ以外の場合は、y
が代入されます。x
が 10 でy
が 5 なので、max_value
は10
になります。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;
重要なポイント:
この実験では、C++ において加算、減算、乗算、除算、剰余などの基本的な数学演算を行う方法を学びました。また、前置および後置のインクリメント/デクリメント演算子の使用方法を調べ、それらの微妙な違いを理解しました。さらに、値を効果的に比較および結合するための関係演算子および論理演算子について学びました。また、バイナリ操作のためのビット演算と代入との算術演算を単純化および凝縮するための複合代入演算子を練習しました。最後に、複数の演算子を持つ演算の順序を理解し、簡潔な条件文に三項条件演算子を使用しました。これらの基本概念は、堅牢で効率的な C++ プログラムを構築するために不可欠です。これらの基本演算子をマスターすることで、より複雑なコーディングチャレンジに対処する準備ができます。