在C++中制作动态文本可寻址列表

Making a dynamically text-addressable list in C++

本文关键字:文本 寻址 列表 动态 C++      更新时间:2023-10-16

在大多数脚本语言中,对象通常是项的集合,绑定到这些对象中的名称。例如(在Javascript中),假设我要初始化它:

colors = {
    Blue:  0x0000FF; //Hex Values
    Green: 0x00FF00;
    Red:   0xFF0000;
}

在运行时,如果用户键入列出的颜色,我可以使用 colors["given_color"] 轻松返回相应的十六进制值。

但是,我将如何用C++或其他编译语言来表达一个甚至非常相似的机制?创建一个enum只会在静态上有意义,在人为的例子中:

public enum colors{
    CYAN     =  0x00FFFF,
    MAGENTA  =  0xFF00FF,
    YELLOW   =  0xFFFF00
}

不能以任何方式用于查找相应的十六进制std::cin << givenColor;

话虽如此,我有哪些选项可以将std::string转换为数据点、指针或函数指针?

您要查找的数据结构称为映射(或字典或关联数组)。在C++中,有std::map总是排序的(通常实现为红黑树),std::unordered_map通常更快,因为它使用哈希表(但内容是任意顺序)。

std::unordered_map<std::string, int> colors = {
    {"blue", 0x0000FF},
    {"green", 0x00FF00},
    {"red", 0xFF0000}
};
std::string key = /* something */;
std::string value = colors[key];

回答评论中的问题:是的,您可以将任何您想要的东西存储在地图中。唯一的限制是,对于std::unordered_map,密钥类型需要实现哈希函数并operator==,而对于std::map,密钥类型需要实现operator<。值类型可以是任何值。

您可以使用std::unordered_map

#include <unordered_map>
#include <string>
int main() {
    std::unordered_map<std::string, unsigned int> colors =
    {
        {"CYAN", 0x00FFFF},
        {"MAGENTA", 0xFF00FF},
        {"YELLOW", 0xFFFF00},
    };
    unsigned int retrieved_color = colors["CYAN"];
}

现在,如果您尝试将C++用作像JavaScript这样的动态语言,这让我有点困扰。如果你真的需要映射一个字符串,你从你无法控制的地方得到的,也许你从网络收到,或者类似的东西,这很好。这是要走的路。

但是,如果您只需要能够在代码中使用名称CYAN,请将此解决方案与enum进行比较:

obj.set_color(CYAN);

obj.set_color(colors["CYAN"]);

第一个在编译时解析,set_color接收文本常量作为参数。

在第二个中,文字字符串"CYAN"用于初始化临时对象std::string,然后复制到堆分配的位置。然后计算这个字符串的哈希值(O(N),我相信字符串的大小,Java 在制作字符串哈希时只使用几个字符已经遇到了问题),然后有一个内存获取来获取实际值。最后,临时std::string被解除分配。然后调用函数set_color

这笔额外费用与您的计划无关吗?或。但最终,您的最终产品中会累积多少无关紧要的额外成本?

将 C++ 的效率与重载运算符<<的轻松调试相结合,如下所示:

enum class colors {
    CYAN     =  0x00FFFF,
    MAGENTA  =  0xFF00FF,
    YELLOW   =  0xFFFF00
};
std::ostream& operator<<(std::ostream& os, colors c)
{
    switch(c) {
        case colors::CYAN : os << "cyan"; break;
        case colors::MAGENTA : os << "magenta"; break;
        case colors::YELLOW : os << "yellow"; break;
    }
    return os;
}
BOOST_AUTO_TEST_CASE(play_colors)
{
    std::vector<colors> v { colors::CYAN, colors::YELLOW, colors::MAGENTA };
    std::copy(begin(v), end(v), ostream_iterator<colors>(cout, ", "));
    cout << endl;
}

预期输出(添加正确的标头后):

cyan, yellow, magenta,