如何使用cout输出枚举元素?

How to output enum elements using cout?

我正在尝试输出我声明的枚举元素,但是例如,当我输入 push_ups 时,它会输出一个类似 8621623 的数字,而不是显示 push_ups。我不知道为什么。我是日本人,所以如果我的英语不好,我很抱歉。非常感谢。

#include <iostream>
#include <string>
using namespace std;

enum exercise { push_ups, sit_ups, squats, walking, radio_calisthenics };

istream& operator>>(istream& is, exercise& i)
{
    int tmp;
    if (is >> tmp)
        i = static_cast<exercise>(tmp);
    return is;
}

int main()
{
    exercise a;
    cin >> a;
    cout << a << endl;
}

I am trying to output a element of enum I declared but for example, when I input push_ups, it outputs a number like 8621623 instead of showing push_ups.

operator>> 重载中,std::cin 接受 整数 所以 push_ups 不是整数,所以 std::cin 会失败并且 i = static_cast<exercise>(tmp); 行将被跳过,使 a 未初始化,打印时可能导致 未定义的行为 发生。

如果你想将 strings 映射到相应的枚举值,你可以通过使用哈希映射手动将每个字符串映射到相应的枚举值来实现(在 C++ 中,该容器是称为 std::unordered_map):

#include <unordered_map>

// ...

const unordered_map<string, exercise> exercise_map {
    { "push_ups", push_ups },
    { "sit_ups", sit_ups },
    { "squats", squats },
    { "walking", walking },
    { "radio_calisthenics", radio_calisthenics }
};

istream& operator>>(istream& is, exercise& i) {
    std::string tmp;
    if (is >> tmp) {
        auto const it = exercise_map.find(tmp);
        if (it != exercise_map.end())
            i = it->second;
    }
    return is;
}

现在,要从枚举中打印出相应的 string 值,我们必须执行相反的操作,即使用以下值在 hashmap 中找到键:

ostream& operator<<(ostream& os, exercise& i) {
    auto const it = std::find_if(exercise_map.begin(), exercise_map.end(),
        [i](std::pair<std::string, exercise> const& e) {
            return e.second == i;
        }
    );
    if (it != exercise_map.end())
        os << it->first;
    return os;
}

完整代码应该是这样的:

#include <unordered_map>
#include <algorithm>
#include <utility>
#include <iostream>
#include <string>

using namespace std;

enum exercise { push_ups, sit_ups, squats, walking, radio_calisthenics };

const std::unordered_map<std::string, exercise> exercise_map {
    { "push_ups", push_ups },
    { "sit_ups", sit_ups },
    { "squats", squats },
    { "walking", walking },
    { "radio_calisthenics", radio_calisthenics }
};

istream& operator>>(istream& is, exercise& i) {
    std::string tmp;
    if (is >> tmp) {
        auto const it = exercise_map.find(tmp);
        if (it != exercise_map.end())
            i = it->second;
    }
    return is;
}

ostream& operator<<(ostream& os, exercise& i) {
    auto const it = std::find_if(exercise_map.begin(), exercise_map.end(),
        [i](std::pair<std::string, exercise> const& e) {
            return e.second == i;
        }
    );
    if (it != exercise_map.end())
        os << it->first;
    return os;
}

int main() {
    exercise a;
    cin >> a;
    cout << a << endl;
}

push_ups 不是您试图在 is >> tmp 处读取的有效整数值,因此 a 仍未初始化。如果要输入名称,则需要读取字符串,然后手动将其转换为相应的枚举值。输出相同。如果没有正确重载的运算符,<< a 将被视为整数。

您似乎在理解 enum 方面有问题。
我认为您输入了字符串值“push_ups”并假定程序会理解它是指您的 enum.
的值 enum 只是整数类型的占位符,主要用于增加程序的可读性。

查看枚举是表达类似内容的更好方式

// chess_piece = 1 : pawn
// chess_piece = 2 : rook
// chess_piece = 3 : bishop
...
int chess_piece;

作为

enum ChessPiece { Pawn, Rook, Bishop, ...};
ChessPiece chess_piece;

在上面的变体中,很明显 pawn、rook 等名称 仅供评论enum 在这方面没有什么不同。写成if(chess_piece == Pawn)显然可读性更好,但是“Pawn”这个词在编程语言中只是代码的一部分,在编译后的程序中没有。它不作为字符串值存在。

你可以做的是添加类似

的内容
exercise exercise_from_string(const std::string& input)
{
     if(input == "push_ups") return push_ups;
     ...

或与开关相同。我还建议您设置一个“未知”值,以防类似的函数找不到已知术语。

编辑:其他人之一在我写这篇文章时更新了他的答案,他使用 std::map 的代码比我的要好。
不过,希望我的回答能帮助您理解核心问题。

此行:

i = static_cast<exercise>(tmp);

当 tmp 持有 0 到 4 之间的 int 值时将完美工作,

但在你的情况下 tmp = push_ups 破坏了转换操作并且你的 ref i 被错误地初始化