获取和设置C++中的枚举
Get & Set for Enum in C++
我有一个名为School的类,它的一个成员是枚举"SchoolType",它有两个可能的值:Primary和Secondary。以下是我在学校头文件中的枚举:
enum class SchoolType {
Primary = 1,
Secondary = 2
};
在我的主C++文件中,我有一个函数ReadSchool
,它从用户输入中读取School的所有成员。所有其他成员都是int
和string
值,所以我在读取这些值时没有问题,但我不知道该如何处理枚举。我最好的想法是这样做:
School ReadSchool()
{
School tempSchool;
int type;
cout << "Name of School: ";
tempSchool.SetName(GetString());
cout << endl << "Type of School (1 = Primary, 2 = Secondary): ";
cin >> type;
if (type = 2)
tempSchool.SetTypeSchool(2);
else
tempSchool.SetTypeSchool(1);
return tempSchool;
}
在我的SetTypeSchool()
中放入一个int值是无效的,但写入Primary
或Secondary
也是无效的。如果有什么不同的话,我使用的是Visual Studio 2015。有人能提供一些清晰度或更好的方法来设置我的枚举值吗?感谢您的帮助
SchoolType GetSchoolType(string input)
{
// DeHumanize our input
if(input == "Primary")
{
return SchoolType::Primary;
}
else if(input == "Secondary")
{
return SchoolType::Secondary;
}
return SchoolType.None; // or throw an exception, or return a default SchoolType; up to you
}
您的代码有几个问题,例如if (type = 2)
应该是if (type == 2)
。要传递实际的常量,需要将它们称为SchoolType::Primary
和SchoolType::Secondary
。如果SetSchoolType
的参数的类型是SchoolType
,那么它将接受这两个常量。
几个回答者提到了从字符串转换值,包括为此定义流运算符。如果你不反对使用外部库,你可以用这样的语法来实现:
#include <enum.h>
BETTER_ENUM(SchoolType, int, Primary = 1, Secondary = 2)
// ...later...
SchoolType type;
cin >> type; // Expects to read the string "Primary" or "Secondary".
其余的用法在很大程度上类似于普通的枚举类。
该库可在以下位置找到:https://github.com/aantron/better-enums.它由一个单独的头文件组成。许可证是BSD,所以可以随心所欲地使用它。有一个Stack Overflow的答案解释了库内部的核心:https://stackoverflow.com/a/31362042/2482998.
由于一个不幸的限制,您将无法如您所描述的那样直接在School
中声明SchoolType
,但README
中显示了一个简单的解决方法。
免责声明:我是作者。
您可以为枚举类型编写流式操作符,之后它们可以自然地与<<
和>>
:一起使用
#include <iostream>
#include <string>
#include <sstream>
enum class SchoolType {
Primary = 1,
Secondary = 2
};
std::ostream& operator<<(std::ostream& os, SchoolType s)
{
return os << (s == SchoolType::Primary ? "Primary" :
s == SchoolType::Secondary ? "Secondary" :
throw std::runtime_error("invalid SchoolType output"));
}
std::istream& operator>>(std::istream& is, SchoolType& s)
{
std::string word;
if (is >> word)
{
if (word == "Primary") { s = SchoolType::Primary; return is; }
if (word == "Secondary") { s = SchoolType::Secondary; return is; }
is.setstate(std::ios::failbit);
}
return is;
}
int main()
{
std::cout << SchoolType::Primary << ' ' << SchoolType::Secondary << 'n';
std::istringstream iss("Primary Secondary Fail");
SchoolType a, b;
iss >> a >> b;
std::cout << a << ' ' << b << " good:" << iss.good() << 'n';
iss >> a;
std::cout << "good:" << iss.good() << 'n';
}
请参阅此处运行的代码。
注意:简单地流式传输到std::string
,然后检查枚举标识符,在使用时需要注意:标识符必须由空格(例如空格、制表符、换行符)或文件结尾分隔;诸如标点符号或括号/大括号/圆括号之类的尾随字符将被吸入字符串中,然后比较将失败并抛出。
这里提供了一个更复杂但健壮的版本,使用支持类Identifier
逐个字符输入,并在标识符中不合法的第一个字符处使用unget()
。这样,在operator>>(std::istream& is, SchoolType& s)
中,只需将std::string word;
替换为Identifier word;
。
struct Identifier : std::string { };
std::istream& operator>>(std::istream& is, Identifier& idn)
{
idn.clear();
char c;
if (is >> c)
{
if (!std::isalnum(c))
is.setstate(std::ios::failbit);
else
{
idn += c;
while (is.get(c))
if (std::isalnum(c) || c == '_')
idn += c;
else
{
is.unget();
break;
}
// hit EOF, is.get(c) will have left fail condition set
is.clear(); // doesn't matter that we also clear EOF
}
}
return is;
}
(在实践中,我更喜欢写入字符串和from字符串函数,然后使用这些函数编写流运算符:这有时更方便,例如,如果您快速想要一个字符串表示而不创建流)。
您应该允许用户输入字符串(例如"Primary"或"Secondary"),然后使用一个函数将字符串转换为enum
。
该功能有两个用途:
- 验证输入
- 执行从
string
到enum
的必要转换
一种方法是替换:
SetSchoolType(2);
带有
SetSchoolType(static_cast<SchoolType>(2));
- 不带大括号的枚举形式
- 枚举环境变量的惯用C++14/C++17方法
- 类似枚举的计算常量
- 如何正确实现和访问运算符的各种自定义枚举器
- 错误:从"int"到枚举c++的转换无效
- C++中构造函数中的枚举
- 访问在 C++ 结构中声明的枚举变量
- 枚举类'classname'的多重定义
- 强枚举类型定义:Clang Bug 还是 C++11 标准不确定性?
- typedef 枚举和枚举类有什么区别?
- 为什么我的开关/机箱在使用枚举时默认?
- 标准::可选枚举的比较运算符
- C++两个源文件之间共享的枚举的静态实例
- 打印没有铸件的枚举可以在C++中吗?
- 枚举成员与静态 int 成员?
- C++:枚举:错误:应使用标识符而不是"}"
- 带有 c++ 的枚举(输入检查)
- 在 qml 中使用 Q_ENUM 和 Q_PROPERTY 作为枚举类
- 为什么 int 类型的枚举类值不能用作 int
- 在 C++ 中输出枚举类类型的向量元素