制御フロー · 08
真偽値と三項演算子
真偽を変数に入れておく、二つの値から一つを選ぶ、「このどれかか」をたずねる。
「条件分岐」の単元では、比較を if の中でそのまま使いました。
今回はその結果を値として扱います。
下の例は曜日と客の年齢を読み、週末かどうかと子どもがいるかどうかを変数に入れておき、週末なら 12、平日なら 8 の入場料の合計を表示します。
day = input().strip()ages = list(map(int, input().split())) weekend = day in ("sat", "sun") # 포함 검사의 결과(참·거짓)를 변수에 담아요child = False # 깃발: 아직 어린이를 못 봤어요for age in ages: if age < 13: child = True price = 12 if weekend else 8 # 두 값 중 하나를 골라요print("weekend" if weekend else "weekday")print(price * len(ages))print("child" if child else "adults")const lines = require("fs").readFileSync(0, "utf8").split("\n");const day = lines[0].trim();const ages = lines[1].trim().split(/\s+/).map(Number); const weekend = ["sat", "sun"].includes(day); // 포함 검사의 결과(참·거짓)를 변수에 담아요let child = false; // 깃발: 아직 어린이를 못 봤어요for (const age of ages) { if (age < 13) child = true;} const price = weekend ? 12 : 8; // 두 값 중 하나를 골라요console.log(weekend ? "weekend" : "weekday");console.log(price * ages.length);console.log(child ? "child" : "adults");import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");const day: string = lines[0].trim();const ages: number[] = lines[1].trim().split(/\s+/).map(Number); const weekend: boolean = ["sat", "sun"].includes(day); // 포함 검사의 결과(참·거짓)를 변수에 담아요let child: boolean = false; // 깃발: 아직 어린이를 못 봤어요for (const age of ages) { if (age < 13) child = true;} const price: number = weekend ? 12 : 8; // 두 값 중 하나를 골라요console.log(weekend ? "weekend" : "weekday");console.log(price * ages.length);console.log(child ? "child" : "adults");import java.util.List;import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); String day = sc.nextLine().strip(); String[] ages = sc.nextLine().strip().split(" +"); boolean weekend = List.of("sat", "sun").contains(day); // 포함 검사의 결과(참·거짓)를 변수에 담아요 boolean child = false; // 깃발: 아직 어린이를 못 봤어요 for (String age : ages) { if (Integer.parseInt(age) < 13) child = true; } int price = weekend ? 12 : 8; // 두 값 중 하나를 골라요 System.out.println(weekend ? "weekend" : "weekday"); System.out.println(price * ages.length); System.out.println(child ? "child" : "adults"); }}using System;using System.Linq; class Program{ static void Main() { string day = Console.ReadLine().Trim(); string[] ages = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries); string[] rest = { "sat", "sun" }; bool weekend = rest.Contains(day); // 포함 검사의 결과(참·거짓)를 변수에 담아요 bool child = false; // 깃발: 아직 어린이를 못 봤어요 foreach (string age in ages) { if (int.Parse(age) < 13) child = true; } int price = weekend ? 12 : 8; // 두 값 중 하나를 골라요 Console.WriteLine(weekend ? "weekend" : "weekday"); Console.WriteLine(price * ages.Length); Console.WriteLine(child ? "child" : "adults"); }}#include <algorithm>#include <iostream>#include <string>#include <vector> int main() { std::string day; std::cin >> day; std::vector<int> ages; int age; while (std::cin >> age) ages.push_back(age); std::vector<std::string> rest = {"sat", "sun"}; bool weekend = std::find(rest.begin(), rest.end(), day) != rest.end(); // 포함 검사의 결과(참·거짓)를 변수에 담아요 bool child = false; // 깃발: 아직 어린이를 못 봤어요 for (int a : ages) { if (a < 13) child = true; } int price = weekend ? 12 : 8; // 두 값 중 하나를 골라요 std::cout << (weekend ? "weekend" : "weekday") << '\n'; std::cout << price * ages.size() << '\n'; std::cout << (child ? "child" : "adults") << '\n';}#include <stdbool.h>#include <stdio.h>#include <string.h> int main(void) { char day[16]; int ages[100], n = 0; scanf("%15s", day); while (scanf("%d", &ages[n]) == 1) n++; const char *rest[] = {"sat", "sun"}; bool weekend = false; // 포함 검사 도구가 없어서 하나씩 견줘요 for (int i = 0; i < 2; i++) { if (strcmp(day, rest[i]) == 0) weekend = true; } bool child = false; // 깃발: 아직 어린이를 못 봤어요 for (int i = 0; i < n; i++) { if (ages[i] < 13) child = true; } int price = weekend ? 12 : 8; // 두 값 중 하나를 골라요 printf("%s\n", weekend ? "weekend" : "weekday"); printf("%d\n", price * n); printf("%s\n", child ? "child" : "adults"); return 0;}day = コンソール.行読み().空白除去();ages = コンソール.数読み(); // 포함 검사의 결과(참·거짓)를 변수에 담아요weekend = ["sat", "sun"].含む(day);// 깃발: 아직 어린이를 못 봤어요child = 偽;それぞれ (age の中 ages){ もし (age < 13) { child = 真; }} // 두 값 중 하나를 골라요price = weekend ? 12 : 8;コンソール.書く(weekend ? "weekend" : "weekday");コンソール.書く(price * ages.個数);コンソール.書く(child ? "child" : "adults");sat 35 41 9
weekend 36 child
ポイント
- 比較の結果(
age < 13)は真偽値です。
数や文字列と同じように変数に入れておいて、何度も使えます。
入れておいた値は条件の場所にそのまま書きます。if (weekend)で十分で、== trueは付けません。 - フラグは、真偽値の変数を繰り返しと一緒に使う形です。
繰り返しの前で偽にしておき、探していたものに出会ったら真に変えます。
繰り返しが終わると「一つでもあったか」が残ります。 - 三項演算子は、条件によって二つの値のどちらかを選びます。
ifはすることを選び、三項は値を選びます。
だから代入の右側や出力の中にそのまま書けます。 - 三項は短いときだけ使います。
三項の中にまた三項を入れるようになったら、ifとelseで書き直すほうが読みやすくなります。 - 含まれるか判定は「この値はこれらのどれかか」をたずねます。
==を||で長くつなぐ代わりに、値をリストに入れて「入っているか」を1回だけたずねます。
答えは真偽値です。 - 真偽値をそのまま出力すると、言語によって違います。
Python と C# はTrue、JavaScript・Java・Craykon はtrue、C と C++ は1です。
だから例では三項で文字列を選んで表示しています。
言語ごとの書き方
| Python | weekend = day in ("sat", "sun")、フラグは child = False から True へ。三項は 12 if weekend else 8 — 真のときの値がいちばん前に来ます。否定は not weekend |
|---|---|
| JavaScript | const weekend = ["sat", "sun"].includes(day);、三項は weekend ? 12 : 8。in は含まれるか判定ではありません。"sat" in ["sat", "sun"] は false です(値ではなく番号があるかをたずねます) |
| TypeScript | JavaScript と同じです。 型の名前は boolean です |
| Java | boolean weekend = List.of("sat", "sun").contains(day);、三項は weekend ? 12 : 8。文字列一つと比べるときは day.equals("sat") |
| C# | bool weekend = rest.Contains(day); — 配列に使うには using System.Linq; が必要です。三項は weekend ? 12 : 8 |
| C++ | bool weekend = std::find(rest.begin(), rest.end(), day) != rest.end();(<algorithm>)、三項は weekend ? 12 : 8。bool をそのまま出力すると 1 で、先に std::boolalpha を送ると true |
| C | #include <stdbool.h> を入れると bool、true、false が使えます。含まれるかを調べる道具がないので、繰り返しで一つずつ strcmp(day, rest[i]) == 0 かを見ます。1文字なら strchr("aeiou", c) != NULL。三項は weekend ? 12 : 8 |
| Craykon | weekend = ["sat", "sun"].含む(day);、フラグは child = 偽; から 真 へ。三項は weekend ? 12 : 8。文字列にも "aeiou".含む("e") のようにたずねられます |
よくある間違い
フラグを else で偽に戻した
int[] ages = {9, 35, 41};
boolean child = false;
for (int age : ages) {
if (age < 13) child = true;
else child = false;
}
System.out.println(child ? "child" : "adults");→ adults — 9歳がいるのに、子どもはいないことになります。9 で真になったあと、35 と 41 でまた偽に上書きされました。こう書くと、フラグには「最後の客が子どもか」しか残りません。どの言語で書いても同じです
else を消します。
フラグは繰り返しの前で1回だけ偽にしておき、繰り返しの中では真に変えるだけにします。
繰り返しの中で child = age < 13; のように毎回入れ直すのも同じミスです。
== "sat" or "sun" で「どちらかか」をたずねたPython · JavaScript · TypeScript · C · C++ · Craykon
day = "mon"
if day == "sat" or "sun":
print("weekend")
else:
print("weekday")→ weekend — 月曜日なのに週末になります。(day == "sat") or "sun" と読まれるので、前が偽なら "sun" が条件になり、空でない文字列は真です
両側とも比較で書きます(day == "sat" or day == "sun")。
含まれるか判定ならもっと短くなります(day in ("sat", "sun"))。
Java と C# はこのコードをコンパイルエラーで止めてくれます。
三項をかっこなしで + のあとに付けたJavaScript · TypeScript · Python · C++ · Craykon
const ok = false;
console.log("Result: " + ok ? "yes" : "no");→ yes — + が先に計算されます。"Result: false" という文字列が条件になり、空でない文字列なのでいつも真です。Craykon も yes を表示します。Python の "Result: " + "yes" if ok else "no" は no だけを表示し、C++ の std::cout << ok ? "yes" : "no"; は 0 を表示します
三項全体をかっこで囲みます:"Result: " + (ok ? "yes" : "no")。
Java と C# はかっこがないとコンパイルエラーで知らせてくれます。
条件の場所に真偽値でない値を入れたとき、言語は二つに分かれます。
Java と C# はコンパイルエラーで止めます。
C・C++・Python・JavaScript・TypeScript・Craykon は
"sun" のような値も真とみなして進みます。何を偽とみなすかも言語によって違います。
空のリストは Python では偽ですが、JavaScript と Craykon では真です。
一つ目と三つ目のミスが黙って間違った答えを出すのはそのためです。
条件には比較か真偽値の変数だけを書く習慣をつけると安全です。