在C++中创建一个字符串常量集合

3
这可能听起来像一个基础问题,但它是可以解决的,我正在寻找一种快速而优雅的解决方案。
我想创建一个程序专用的保留字集合: {"apple", "orange", "peach"} 它是常量,我希望能在运行时检查字符串是否为保留字(如果是集合的一部分)。
我考虑过使用std::set,但我不想手动将我的每个保留字添加到集合中。此外,我不需要set的全部功能,例如我不需要添加新元素或删除元素。
有什么优雅的方法吗?

如果您不想使用std::set来表示一个集合,可以使用数组和std::find - K-ballo
3个回答

6
你可以将单词存储在数组中,然后使用 std::set 的范围构造函数:
char const* raw_words[] = { "apple", "orange", "peach" };

std::set<std::string> const words(std::begin(raw_words), std::end(raw_words));

这个可以使用 C++11 中的新函数 beginend 来实现,不过在 C++03 中也可以通过指向数组第一个元素和最后一个元素之后的指针来实现。
在 C++11 中,你还可以使用初始化列表来初始化 std::set,但并不是所有编译器都支持这个特性。
另外,需要注意的是,如果单词集合的内容从不改变,那么使用排序的 std::vector<std::string> 并使用 std::lower_boundstd::binary_search 来查找元素可能会更好。这样做的性能可能会更好。

这就是我需要的。之前尝试使用字符串数组而不是char *来完成。谢谢。 - Michael
std::string raw_words[] 也可以正常工作。我选择 char const* 是为了避免 std::string 不必要的开销。由于 raw_words 的唯一用途是初始化 words,因此在那里没有必要使用 std::string 的特性。 - James McNellis

6

在现代C++(C++11)中:

const std::set<std::string> v = { "xyzzy", "plugh", "abracadabra" };

1
既不是std::set也不是std::string友好的constexpr:https://godbolt.org/g/CmvaZa - 为避免传播错误信息,您应该删除您的答案 - Vittorio Romeo
@VittorioRomeo 我将 constexpr 替换为 const - log0

2
我不想手动将每个保留词添加到集合中。
如果您的意思是您不希望代码看起来像这样:
reserved_word.insert("apple");
reserved_word.insert("orange");
reserved_word.insert("peach");

在一些需要在其他代码之前运行的初始化代码中,你可以采用以下方式(使用 C++11):

const std::set<std::string> reserved_word = {"apple", "orange", "peach"};

尽管如此,它仍然会在运行时执行初始化。
您也可以简单地使用预排序的char const *reserved_word[] = { ... }。这将避免任何运行时初始化的需要。但是,最好在源代码中正确排序,否则在尝试使用其中一个已排序序列搜索算法搜索单词时,您将获得意外的行为。
此外,我不需要set的全部功能。
我不认为这是避免使用它的好理由。更好的理由是,如果它允许您想要禁止的事情。例如,如果您实际上想要防止添加和删除内容,则使用非const set不是最佳选择。但是,由于您可以使用const set,因此没有必要避免set。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接