第 4 回 | 2024-10-18¶
- 数の比較方法を学ぶ
- 数の比較結果による分岐の方法を学ぶ
- 複数の条件を組み合わせる方法を学ぶ
- 計算による変数の値の変更方法を学ぶ
- 繰り返しの方法とその終わり方を学ぶ
1. 数の比較と分岐¶
1.1 数を比べる¶
- 値の大小を比較する 4 つの記号
>
,<
,<=
,>=
がある。
記号 | 意味 | 結果 |
---|---|---|
a < b |
a が b より小さいか | 真(true)または偽(false) |
a > b |
a が b より大きいか | 真または偽 |
a <= b |
a が b 以下か | 真または偽 |
a >= b |
a が b 以上か | 真または偽 |
<=
と>=
は=
の位置を間違えやすい。- 次のプログラムは数を比較しているだけで、その結果を使っていないので、実行しても何も起こらない。
#include <iostream>
int main()
{
int power = 20, age = 30, score = 100, price = 900;
power > 10; // (1)!
age < 20; // (2)!
score <= 50; // (3)!
price >= 1000; // (4)!
}
power
が 10 より大きいかを調べる。age
が 20 未満であるかを調べる。score
が 50 以下であるかを調べる。<
と=
の順番に注意price
が 1000 以上であるかを調べる。>
と=
の順番に注意
1.2 条件を書く¶
if
(イフ)は()
の中の条件を満たすときに、それにつづく{ }
でかこんだ文を実行する。- 次のコードは、標準入力した値
age
が 18 未満のときにこども
と出力する。 { }
の内側は Tab キーを使ってインデントを行うと読みやすくなる。
#include <iostream>
int main()
{
int age;
std::cin >> age;
if (age < 18)
{
std::cout << "こども\n";
}
}
1.3 if とは無関係の場所¶
if
とは無関係な場所は、条件に関わらず実行する。- 次のコードにおいて、最後の
std::cout
はif
とは無関係の場所にあるため、age
にどのような値を入力しても、必ずおわり
を出力する。
#include <iostream>
int main()
{
int age;
std::cin >> age;
if (age < 18)
{
std::cout << "こども\n";
}
std::cout << "おわり\n";
}
1.4 条件に応じて違うことをする¶
if (条件) { }
で条件を満たしていない場合、それに続くelse
(エルス)があれば、else
に続く{ }
の中を実行する。- 次のコードは、キーボードで入力した値が 18 未満であれば、
こども
、18 以上であれば、大人
と出力する。
#include <iostream>
int main()
{
int age;
std::cin >> age;
if (age < 18)
{
std::cout << "こども\n";
}
else
{
std::cout << "大人\n";
}
}
1.5 数が等しいかを調べる¶
==
(イコール・イコール)の記号は、左の値と右の値が同じかどうかを調べる。- 次のコードは、キーボードで入力した値が 1 であれば、
行き止まり!
と出力し、それ以外の値であれば、出口!
と出力する。
#include <iostream>
int main()
{
std::cout << "どちらに進む? 1:左 2:右\n";
int answer;
std::cin >> answer;
if (answer == 1)
{
std::cout << "行き止まり!\n";
}
else
{
std::cout << "出口!\n";
}
}
== は比較、= は代入
初心者は比較の記号 ==
と、代入の記号 =
を混同する。次のコードは ==
と =
をまちがえているため、キーボードで「2」を入力したときにも主人公が左の道に進んでしまう。
1.6 数が異なるかを調べる¶
!=
(ノット・イコール)の記号は、左の値と右の値が異なるかどうかを調べる。- 次のコードは、キーボードで入力した値が 2 でなければ
はずれ
、2 であれば正解!
と出力する。
#include <iostream>
int main()
{
std::cout << "1 + 1 = ?\n";
int answer;
std::cin >> answer;
if (answer != 2)
{
std::cout << "はずれ\n";
}
else
{
std::cout << "正解!\n";
}
}
==
を使っても!=
を使っても、同じようなプログラムを作ることができる。どちらを使うかは自由。
#include <iostream>
int main()
{
std::cout << "1 + 1 = ?\n";
int answer;
std::cin >> answer;
if (answer == 2)
{
std::cout << "正解!\n";
}
else
{
std::cout << "はずれ\n";
}
}
1.7 計算結果を調べる¶
500 * count
のような数式を、比較の式の中で使うこともできる。- 次のコードは、購入額が 1 万円以上であれば、
1万円以上だから割り引きするよ
と出力する。
#include <iostream>
int main()
{
std::cout << "1個500円の回復薬、何個買うかい?";
int count;
std::cin >> count;
if (10000 <= (500 * count))
{
std::cout << "1万円以上だから割り引きするよ\n";
}
}
1.8 { }
の中で作った変数¶
{ }
の内側で作った変数は、その{ }
の外側では使えない。
間違ったコード
- 次のように修正するとよい。
#include <iostream>
int main()
{
int age = 18;
int fee = 1000; // 大人料金
if (age < 18)
{
fee = 500; // 子ども料金
}
std::cout << fee << "\n";
}
今後学ぶ条件演算子を使う
- 今後の講義で学ぶ条件演算子
? :
を使うと、次のように簡潔に書くことができる。 - 条件演算子
a ? b : c
は、a
が真のときb
を、偽のときc
を返す。
2. 複数の条件を組み合わせる¶
2.1 両方満たす¶
- 2 つの条件の両方を満たすかを調べるときは、「かつ」の記号
&&
を使う。 &&
は左右両方が真のときに真を返す。- 次のコードは、キーボードで入力した値が 10 以上 99 以下であれば、
n は 2 桁の整数
と出力する。
#include <iostream>
int main()
{
int n;
std::cin >> n;
if ((10 <= n) && (n <= 99)) // 両方満たす必要がある
{
std::cout << n << " は 2 桁の整数\n";
}
}
間違った書き方
if (0 <= n <= 99) が NG な理由
#include <iostream>
int main()
{
int n;
std::cin >> n;
if (10 <= n <= 99) // 比較の記述が正しくない
{
std::cout << n << " は 2 桁の整数\n";
}
}
このプログラムを実行し「500」を入力すると、「500 は 2 桁の整数」という間違った出力を得る。これは <
や ==
などの比較の記号が、+
や -
の記号と同じように、左から 1 つずつ順番に実行されることが理由である。
例えば 3 + 5 + 10
では、まず 3 + 5
を計算し、その結果である 8 を使って 8 + 10
が計算される。これを括弧でまとめると ((3 + 5) + 10)
となる。
10 <= n <= 99
にも同様のルールが適用され、((10 <= n) <= 99)
になる。
「500」を入力したとき、まずは 10 <= n
を実行する。その結果は「真」を意味する true
である(「偽」の場合は false
)。true
は整数との比較では 1
とみなされるため、ここでは次に 1 <= 99
が実行される。1 は 99 以下なので、この結果も真になる。つまり
if (10 <= n <= 99)
if ((10 <= n) <= 99)
if ((10 <= 500) <= 99)
if (1 <= 99)
という流れで解釈され、最終結果は、条件を満たす「真」と判断されてしまう。
2.2 全部を満たす¶
(A && B && C)
は((A && B) && C)
なので、A, B, C がすべて真のときのみ真になる。- 次のコードは、キーボードで入力した値が 10 以上 99 以下で、かつ偶数であれば、
n は 2 桁の偶数
と出力する。
#include <iostream>
int main()
{
int n;
std::cin >> n;
if ((10 <= n) && (n <= 99) && ((n % 2) == 0)) // 全部を満たす必要がある
{
std::cout << n << " は 2 桁の偶数\n";
}
}
2.3 どちらかを満たす¶
- 2 つの条件のうちどちらかだけを満たせばよいときは、「または」の記号
||
を使う。 ||
は左右どちらかが真のときに真を返す。- 次のコードは、キーボードで入力した値が 12 以下、あるいは 65 以上であれば、
割引料金
と出力する。
#include <iostream>
int main()
{
int age;
std::cin >> age;
if ((age <= 12) || (65 <= age)) // どちらかを満たせばよい
{
std::cout << "割引料金\n";
}
}
2.4 どれかを満たす¶
(A || B || C)
は((A || B) || C)
なので、A, B, C ひとつでも真のとき真になる。- 次のコードは、キーボードで入力した値が 12 以下、あるいは 65 以上、あるいは 18 であれば、
割引料金
と出力する。
#include <iostream>
int main()
{
int age;
std::cin >> age;
if ((age <= 12) || (65 <= age) || (age == 18)) // どれかを満たせばよい
{
std::cout << "割引料金\n";
}
}
3. 計算による変数の値の変更¶
変数の値は代入の記号 =
以外の方法でも変更できる。具体的には「20 を足す」「10 を引く」「2 倍にする」のように、増減を指定して変更する方法である。
3.1 数を増やしたり減らしたりする¶
+=
の記号は右辺の数だけ変数の値を増やす。-=
の記号は右辺の数だけ変数の値を減らす。
#include <iostream>
int main()
{
int hp = 80;
hp += 20;
std::cout << hp << "\n";
hp -= 10;
std::cout << hp << "\n";
}
- あえて
+=
,-=
を使わない場合は次のように書けるが、文字数が多くなる。
#include <iostream>
int main()
{
int hp = 80;
hp = (hp + 20);
std::cout << hp << "\n";
hp = (hp - 10);
std::cout << hp << "\n";
}
3.2 数をかけたり割ったりする¶
*=
の記号は右辺の数だけ変数の値をかける。/=
の記号は右辺の数で変数の値を割る。
#include <iostream>
int main()
{
int hp = 80;
hp *= 2;
std::cout << hp << "\n";
hp /= 4;
std::cout << hp << "\n";
}
3.3 1 ずつ変化させる¶
++
の記号は変数の値を 1 増やす。--
の記号は変数の値を 1 減らす。+= 1
と-= 1
と同じだが、より少ない文字数で書ける。
#include <iostream>
int main()
{
int power = 10;
++power;
std::cout << power << "\n";
--power;
std::cout << power << "\n";
}
- 新しい記号のはたらきをまとめると次のようになる。
記号 | はたらき |
---|---|
a += b; |
a = a + b; |
a -= b; |
a = a - b; |
a *= b; |
a = a * b; |
a /= b; |
a = a / b; |
++a; |
a = a + 1; |
--a; |
a = a - 1; |
++ と -- の前置、後置の違い
++
と --
は変数の前と後のどちらにも置くことができ、前に置くものを「前置(ぜんち)」、あとに置くものを「後置(こうち)」と区別する。前置も後置も、変数の値を 1 増やす、1 減らすというはたらきに関しては同じである。
#include <iostream>
int main()
{
int hp = 10;
++hp; // 前置
hp++; // 後置
std::cout << hp << "\n"; // 12
--hp;
hp--;
std::cout << hp << "\n"; // 10
}
前置と後置の違いは、次のコードを実行することで明らかになる。
#include <iostream>
int main()
{
int hp = 10;
std::cout << ++hp << "\n"; // 11
std::cout << hp << "\n"; // 11
hp = 10;
std::cout << hp++ << "\n"; // 10
std::cout << hp << "\n"; // 11
}
どちらの ++
も最終的には hp
を 11 に増やす。しかし、前置の ++
は変数の値を 1 増やした結果を返し、それが std::cout
に渡される一方、後置の ++
は増やす前の値を返し、それが std::cout
に渡される。--
の場合も同様の操作になる。後置はこうした複雑な挙動であるため、特に理由が無ければシンプルな前置を使うと良い。
4. 繰り返しとその終了¶
4.1 無限に繰り返す¶
for (;;)
は、それにつづく{ }
の中の処理を無限に繰り返す。- 次のコードは、モンスターの HP を 10 ずつ減らし続ける。
#include <iostream>
int main()
{
int monsterHP = 100;
for (;;)
{
monsterHP -= 10;
std::cout << "モンスターの HP: " << monsterHP << "\n";
}
}
プログラムの強制停止
4.1 のプログラムは無限ループになり、いつまでも終了しない。インタラクティブな環境で実行している場合、Ctrl+C キーを入力することで実行中のプログラムを強制停止できる。
4.2 繰り返しから脱出する¶
- ループの中で
break;
が実行されると、そのループから脱出できる。 - 次のコードは、モンスターの HP を 10 ずつ減らし続け、モンスターの HP が 0 以下になったら、
モンスターを倒した!
と出力してループから脱出する。
#include <iostream>
int main()
{
int monsterHP = 100;
for (;;)
{
monsterHP -= 10;
std::cout << "モンスターの HP: " << monsterHP << "\n";
if (monsterHP <= 0)
{
std::cout << "モンスターを倒した!\n";
break;
}
}
}
変数を作る位置を間違えた場合
変数 monsterHP
の作成を、次のようにループ for (;;)
の中に含めてしまうと、ループのたびに毎回変数を新しく作り直してモンスターの HP が 100 にリセットされるため、ねらい通りの結果にはならない。
4.3 特定の入力があるまで繰り返す¶
for(;;)
とbreak
を組み合わせることで、特定の値を入力するまで何度も入力できるプログラムを作れる。- 次のコードは繰り返し入力を受け付け、入力値が 18 未満であれば、
こども
、18 以上であれば、大人
と出力する。 - ただし -1 が入力されたら、
break
でループから脱出し、main
の終端に到達してプログラムが終了する。
#include <iostream>
int main()
{
for (;;)
{
int age;
std::cin >> age;
if (age == -1)
{
break;
}
if (age < 18)
{
std::cout << "こども\n";
}
else
{
std::cout << "大人\n";
}
}
}
✅ 振り返りチェックリスト¶
- 数の比較方法を学んだ
- 数の比較結果による分岐の方法を学んだ
- 複数の条件を組み合わせる方法を学んだ
- 計算による変数の値の変更方法を学んだ
- 繰り返しの方法とその終わり方を学んだ
課題¶
🐣 練習問題¶
コンサートのチケットの売り上げを計算するプログラムを作ります。
- 席は S 席、A 席、B 席の 3 種類あり、最初にそれぞれの価格が入力されます。
- 次に、「チケットの種類」と「販売数」のペアが繰り返し入力されます。
-1 -1
が入力されたら、販売数の入力は終了です。- 最後に売り上げの合計を出力してください。
- 料金は整数です。売り上げの合計が 1 億円を超えることはありません。
入力データ | 意味 |
---|---|
s_price | S 席の価格(0 以上 20000 以下の整数) |
a_price | A 席の価格(0 以上 20000 以下の整数) |
b_price | B 席の価格(0 以上 20000 以下の整数) |
type | チケットの種類(1 なら S 席、2 なら A 席、3 なら B 席) |
count | 販売数(1 以上 100 以下の整数) |
入力例 1
S 席が 8000 円、A 席が 5000 円、B 席が 3000 円です。
S 席が 7 枚、A 席が 9 枚、B 席が 10 枚売れたので、売り上げは 131000 円です。
入力例 2
S 席が 2000 円、A 席が 1000 円、B 席が 300 円です。
S 席が 2 枚、A 席が 9 枚売れたので、売り上げは 13000 円です。
解答例
#include <iostream>
int main()
{
// S 席、A 席、B 席の価格
int s_price, a_price, b_price;
std::cin >> s_price >> a_price >> b_price;
// 合計金額
int sum = 0;
for (;;)
{
// 席の種類と枚数を入力する
int type, count;
std::cin >> type >> count;
// 終了
if ((type == -1) && (count == -1))
{
break;
}
// S 席
if (type == 1)
{
sum += (count * s_price);
}
// A 席
if (type == 2)
{
sum += (count * a_price);
}
// B 席
if (type == 3)
{
sum += (count * b_price);
}
}
// 合計金額を出力する
std::cout << sum << "\n";
}
📝 提出課題¶
宝くじ売り場には宝くじの当せん番号照合機が設置されています。この機械は購入者のくじの番号と当せん番号を比較し、当せん状況を表示します。当せん番号と、購入者のくじの情報をもとに、当せん金額の合計を計算するプログラムを作成してください。
- 全国自治宝くじ(サマージャンボ宝くじ) の当選番号が最初に入力されます。
- 次に、購入者が持っている「くじの組」と「くじの番号」のペアが繰り返し入力されます。
-1 -1
が入力されたら、くじの入力は終了です。- 当せんした金額の合計を出力してください。
- 入力はすべて整数です。当せん金額の合計が 20 億円を超えることはなく、
int
型で計算できる範囲です。 - 等級と当せん金額は次の通りです。
等級 | 条件 | 当せん金額 | コピペ用 |
---|---|---|---|
1 等 | 1 等の組が一致し、1 等の番号にも一致 | 5 億円 | 500000000 |
1 等の前後賞 | 1 等の組が一致し、1 等の番号に対して直前または直後の番号である | 1 億円 | 100000000 |
1 等の組違い賞 | 1 等と組が不一致で、1 等の番号に一致 | 10 万円 | 100000 |
2 等 | 2 等と番号が一致 | 100 万円 | 1000000 |
3 等 | 番号の下 4 桁が 3 等と一致 | 1 万円 | 10000 |
4 等 | 番号の下 2 桁が 4 等と一致 | 3000 円 | 3000 |
5 等 | 番号の下 1 桁が 5 等と一致 | 300 円 | 300 |
- くじの組は 1 以上 100 以下の整数です。
- くじの番号は 100000 以上 199999 以下の整数です。
- 1 枚のくじが複数の等に重複当せんすることもあります。
- 1 等の番号が
150000
の場合、1 等前後賞の番号は149999
と150001
です。 - 1 等の番号が
199999
の場合、1 等前後賞の番号は199998
と100000
です。 - 1 等の番号が
100000
の場合、1 等前後賞の番号は199999
と100001
です。
firstUnit firstNumber
secondNumber
thirdNumberN4
fourthNumberN2
fifthNumberN1
unit number
unit number
...
unit number
-1 -1
入力データ | 意味 |
---|---|
firstUnit | 1 等の組(1 以上 100 以下) |
firstNumber | 1 等の番号(100000 以上 199999 以下) |
secondNumber | 2 等の番号(100000 以上 199999 以下) |
thirdNumberN4 | 3 等の番号(下 4 桁)(0 以上 9999 以下) |
fourthNumberN2 | 4 等の番号(下 2 桁)(0 以上 99 以下) |
fifthNumberN1 | 5 等の番号(下 1 桁)(0 以上 9 以下) |
unit | 購入者のくじの組(1 以上 100 以下) |
number | 購入者のくじの番号(100000 以上 199999 以下) |
入力例 1
1 等は 11 組 110955 番です。
2 等は 128739 番です。
3 等は下 4 桁が 4352 番です。
4 等は下 2 桁が 09 番です。
5 等は下 1 桁が 3 番です。
購入者は
- 11 組 110955 番(1 等)
のくじを持っています。当せん金額は 5 億円です。
入力例 2
1 等は 11 組 110955 番です。
2 等は 128739 番です。
3 等は下 4 桁が 4352 番です。
4 等は下 2 桁が 09 番です。
5 等は下 1 桁が 3 番です。
購入者は
- 11 組 110955 番(1 等)
- 55 組 110955 番(1 等の組違い賞)
- 77 組 110955 番(1 等の組違い賞)
- 99 組 128739 番(2 等)
のくじを持っています。当せん金額は 5 億 120 万円です。
入力例 3
1 等は 11 組 110955 番です。
2 等は 128739 番です。
3 等は下 4 桁が 4352 番です。
4 等は下 2 桁が 09 番です。
5 等は下 1 桁が 3 番です。
購入者は
- 11 組 110954 番(1 等の前後賞)
- 11 組 110955 番(1 等)
- 11 組 110956 番(1 等の前後賞)
- 12 組 110956 番(はずれ)
のくじを持っています。当せん金額は 7 億円です。
入力例 4
1 等は 11 組 110955 番です。
2 等は 128739 番です。
3 等は下 4 桁が 4352 番です。
4 等は下 2 桁が 09 番です。
5 等は下 1 桁が 3 番です。
購入者は
- 11 組 134352 番(3 等)
- 22 組 164352 番(3 等)
- 33 組 134509 番(4 等)
- 44 組 134569 番(はずれ)
- 55 組 133333 番(5 等)
- 66 組 155555 番(はずれ)
のくじを持っています。当せん金額は 2 万 3300 円です。
入力例 5
1 等は 99 組 199999 番です。
2 等は 156789 番です。
3 等は下 4 桁が 5599 番です。
4 等は下 2 桁が 99 番です。
5 等は下 1 桁が 9 番です。
購入者は
- 99 組 100000 番(1 等の前後賞)
- 11 組 100000 番(はずれ)
- 22 組 199999 番(1 等の組違い賞、4 等、5 等)
- 33 組 125599 番(3 等、4 等、5 等)
のくじを持っています。当せん金額は 1 億 11 万 6600 円です。
ヒント
- 123456 の下 4 桁を調べる場合、
123456 % 10000
で求めることができます。 - 1 等前後賞の番号(前)、前後賞の番号(後)をそれぞれ表す変数
firstNumberBefore
,firstNumberAfter
をあらかじめ作成しておくと、比較が簡単になります。 - 採点では、上記の入力例とは異なるデータでチェックします。
第 5 回は 🛜 オンデマンド講義
次週は出張のためオンデマンド講義です。講義ページを自分で読み進め、いつもどおり課題を提出してください。講義のライブ配信や動画はありません。教室は開室しています。講義日に Moodle で質問をすると、翌日までにスピード対応します。