このページは、練習問題の解答例や解説のページです。
次の列挙型で、列挙子の値はそれぞれいくつですか?
enum class Fruit {
,
apple,
banana= 10,
melon ,
orange= -10,
strawberry ,
watermelon};
最初の列挙子の値は、=
を使って明示しなければ 0
であると決まっています(本編解説)。したがって、apple は 0
です。
2つ目以降の列挙子は、=
を使って明示しなければ、手前の列挙子の値に +1 したものになります(本編解説)。banana は、apple の値 +1
なので、1 ということになります。
melon は明示的に 10 を与えているので、これは指定通り 10 です。
orange は melon の次なので、10 + 1 で 11 です。
strawberry は明示的に -10 を与えているので、-10 です。
watermelon は strawberry の値 +1 なので、-9 になります。
次の中から、エラーになるものをすべて選んでください。
1番はコンパイルエラーです。整数型から scoped enum には暗黙的には変換されず、static_cast が必要です(本編解説)。
2番はコンパイルエラーです。整数型から scoped enum に暗黙的に変換されないですし、scoped enum から整数型にも暗黙的に変換されません(本編解説)。これもstatic_cast が必要です。
3番は問題ありません。unscoped enum から整数型へは暗黙的に変換できます(本編解説)。
4番はコンパイルエラーです。整数型から unscoped enum へは暗黙的に変換されず、static_cast が必要です(本編解説)。
5番はコンパイルエラーです。scoped enum はほかの型に暗黙的に変換されることがないため、やはり static_cast をしない限りは比較できません。
トランプのマークを表現する列挙型の値を渡すと、その色を返す関数を作成してください。色についても列挙型で表現するようにしてください。
マークと色の関係は、スペードとクラブが黒、ダイヤとハートが赤とします。
特に事情がなければ scoped enum を使いましょう。次のように実装できます。
#include <iostream>
#include <string>
// カードのマーク
enum class CardMark {
,
spade,
club,
diamond,
heart};
// カードのマークの色
enum class CardMarkColor {
,
black,
red};
// カードのマークの色を返す
// card_mark: カードのマーク
// 戻り値: card_mark に対応する色
(CardMark card_mark)
CardMarkColor get_mark_color{
if (card_mark == CardMark::spade || card_mark == CardMark::club) {
return CardMarkColor::black;
}
else {
return CardMarkColor::red;
}
}
// カードのマークの色に応じた文字列表現を返す
// card_mark_color: カードのマークの色
// 戻り値: card_mark_color を文字列化した結果
std::string get_mark_color_string(CardMarkColor card_mark_color)
{
switch (card_mark_color) {
case CardMarkColor::black:
return "black";
case CardMarkColor::red:
return "red";
default:
return "";
}
}
int main()
{
auto spade_color = get_mark_color(CardMark::spade);
auto club_color = get_mark_color(CardMark::club);
auto diamond_color = get_mark_color(CardMark::diamond);
auto heart_color = get_mark_color(CardMark::heart);
std::cout << get_mark_color_string(spade_color) << "\n";
std::cout << get_mark_color_string(club_color) << "\n";
std::cout << get_mark_color_string(diamond_color) << "\n";
std::cout << get_mark_color_string(heart_color) << "\n";
}
実行結果:
black
black
red
red
次のような関数は分かりづらいといえます。列挙型を使って改善してください。
// 物体の位置を移動させる。
// pos: 元の位置
// isUp: true を指定すると上へ、false を指定すると下へ移動する
// isFast: true を指定すると高速に移動、false を指定すると通常の速度で移動する
// 戻り値: 移動後の位置
(const Position& pos, bool isUp, bool isFast); Position move
分かりづらい理由は、呼び出し方を考えてみると分かります。たとえば、次の2つの呼び出しは何を意味しているでしょう?
= move(pos, true, false);
pos = move(pos, false, true); pos
呼び出し元のコードだけでは2つの bool値の意味が不明瞭です。このコードだけで、1行目が上への移動を意味しており、2行目が下への高速移動を意味していることは普通読み取れません。もしかすると、2つとも false を指定した場合、「移動しない」という意味に感じる人もいるかもしれません(実際には下へ移動する)。
そこで、次のように列挙型を定義して、引数をその型に変更します。
enum class MoveDirection {
,
up,
down};
enum class MoveSpeed {
,
normal,
fast};
// 物体の位置を移動させる。
// pos: 元の位置
// direction: 移動させる方向
// speed: 移動の速さ
// 戻り値: 移動後の位置
(const Position& pos, MoveDirection direction, MoveSpeed speed); Position move
こうすると、呼び出し元は次のようになります。
= move(pos, MoveDirection::up, MoveSpeed::normal);
pos = move(pos, MoveDirection::down, MoveSpeed::fast); pos
記述は面倒になるかもしれませんが、意味は非常に明確になります。
プログラム全体はこうなります。
#include <iostream>
#include <string>
// 位置
struct Position {
int x;
int y;
};
// 移動の方向
enum class MoveDirection {
,
up,
down};
// 移動の速さ
enum class MoveSpeed {
,
normal,
fast};
// 物体の位置を移動させる。
// pos: 元の位置
// direction: 移動させる方向
// speed: 移動の速さ
// 戻り値: 移動後の位置
(const Position& pos, MoveDirection direction, MoveSpeed speed)
Position move{
= pos;
Position new_pos int v {speed == MoveSpeed::fast ? 12 : 4};
switch (direction) {
case MoveDirection::up:
.y -= v;
new_posbreak;
case MoveDirection::down:
.y += v;
new_posbreak;
default:
break;
}
return new_pos;
}
int main()
{
{10, 20};
Position pos
= move(pos, MoveDirection::up, MoveSpeed::normal);
pos std::cout << pos.x << ", " << pos.y << "\n";
= move(pos, MoveDirection::down, MoveSpeed::fast);
pos std::cout << pos.x << ", " << pos.y << "\n";
}
実行結果:
10, 16
10, 28
はてなブックマーク に保存 | Pocket に保存 | Facebook でシェア |
X で ポスト/フォロー | LINE で送る | noteで書く |
RSS | 管理者情報 | プライバシーポリシー |