如何将 int 映射到 C/C++ 中的相应字符串
Posted
技术标签:
【中文标题】如何将 int 映射到 C/C++ 中的相应字符串【英文标题】:how can I map an int to a corresponding string in C/C++ 【发布时间】:2009-12-15 22:05:18 【问题描述】:我有 20 位数字,我想将它们与字符串相关联。除了使用 switch case 语句来实现这一点之外,还有更快的方法吗?
我需要将 int 转换为相应的字符串,并且数字不一定是打包的。 Qt
中的一些代码也可能有用吗?
示例:以下数字和字符串相互关联,
1: "Request System Info"
2: "Change System Info"
10: "Unkown Error"
【问题讨论】:
数字是否连续?如果是这样,只需使用字符串数组/向量。 我假设“20 个数字”,即整数。您需要 Unicode 才能获得比 '0'-'9' 更多的数字。 注意:没有 C/C++ 之类的东西 ... 答案都是针对 C++ 的。我需要一个 C 实现并且被误导了.. ;) 【参考方案1】:我推荐 std::map
#include <map>
#include <string>
std::map<int, std::string> mapping;
// Initialize the map
mapping.insert(std::make_pair(1, "Request System Info"));
mapping.insert(std::make_pair(2, "Change System Info"));
mapping.insert(std::make_pair(10, "Unkown Error"));
// Use the map
std::map<int, std::string>::const_iterator iter =
mapping.find(num);
if (iter != mapping.end())
// iter->second contains your string
// iter->first contains the number you just looked up
如果您有一个实现initalizer-list feature of the draft C++0x standard 的编译器,您可以结合地图的定义和初始化:
std::map<int, std::string> mapping = 1, "Request System Info",
2, "Change System Info"
10, "Unkown Error";
std::map 可以很好地扩展到大量条目,因为 std::map::find 在 O(log N) 中运行。拥有hash-map feature of the draft C++0x standard 后,您可以轻松地将其转换为 std::unordered_map,它应该能够在 O(1) 时间内查找内容。
【讨论】:
这是特定于 Windows 的编程吗? @yan - std::map 是标准 C++ 库的一部分,因此任何兼容的编译器都可以使用它。 +1 到 STL 地图,我打算建议它,但你打败了我;) IMO,此示例中的 insert(make_pair) 习语比 @pm100 的 mymap[key]=value 示例更难阅读。严格来说, insert(make_pair) 习惯用法可能会稍微快一些,因为使用括号运算符会导致默认的构造函数调用,但我想知道性能提升是否值得可读性的好处。 Chris,STL 是标准 C++ 库的一部分。 Netjeff,如果被复制的对象是重量级的(例如 std::string),则使用 std::map::insert 而不是 std::map::operator[] 的性能增益可能很大。另外,我不认为任何 C++ 程序员会查看对 map::insert 的调用,并且不知道发生了什么......【参考方案2】:Qt 还提供了它自己的地图实现 - QMap 和 QHash。
QMap<int, QString> myMap;
myMap[1234] = "Some value";
myMap[5678] = "Another value";
或
myMap.insert(1234, "Some value");
文档提供了更多示例,但非常易于使用。
【讨论】:
thx,因为我正在制作一个 Qt 应用程序,所以我会使用你的方法,但我的问题一般来说更多的是 C++,所以我将不得不接受另一个答案......希望你不介意(我希望我可以接受 2 个答案 :D)【参考方案3】:更简单的地图使用方式
std::map<int, std::string> mymap;
mymap[1] = "foo";
mymap[10] = "bar";
// ...
int idx = 10;
std::string lookup = mymap[idx];
【讨论】:
当然实现可以随意实现 map,包括开关、跳转表等(尽管几乎可以肯定会是二叉树) Pm100,标准要求某种二叉树结构。该标准明确禁止跳转表等。此外,在插入时,如果使用 std::map::insert 而不是 std::map::operator[],您将获得更好的性能。 使用 operator[] 进行查找的一个问题是,如果您正在查找的索引不在地图中,它将修改您的地图。【参考方案4】:如果您正在寻找速度,switch 语句将是最有效的。大多数 C/C++ 编译器会将其实现为二叉树,因此速度非常快。
【讨论】:
20 个密集值可能会出现在跳转表中 - 您的地图和树木都无法应对两次跳转... 似乎也更容易实现 我很确定会实现跳转表,但这是否会使其效率低于 std::map?【参考方案5】:如果您的字符串在编译时已知,那么您可以在 C 中执行此操作:
#include <stdio.h>
struct message
int val;
const char *msg;
;
int main(void)
struct message messages[] =
1, "Request System Info",
2, "Change System Info",
10, "Unkown Error"
;
size_t nmessages = sizeof messages / sizeof messages[0];
size_t i;
for (i=0; i < nmessages; ++i)
printf("%d : '%s'\n", messages[i].val, messages[i].msg);
return 0;
【讨论】:
其实这不是我需要的 这并不难过,如果错误代码的数量很少并且在编译时已知。当然,对于任何更复杂的事情,这个简单的方案都不是最优的。 @yan:你能解释一下吗?我相信您正在构建一个错误代码和错误消息表,对吧? 我需要能够将您正在使用的索引 i 直接映射到消息,即我从函数调用接收状态变量,我想在消息中插入相关定义而不查看每次都起来。 我需要能够将您正在使用的索引 i 直接映射到消息,即我从函数调用接收状态变量,我想在消息中插入相关定义而不查看每次或使用 switch 语句时,STL 映射都可以正常工作(不要介意他是个小气)。【参考方案6】:如果您的数字和字符串是常量,则映射将不起作用;它必须被加载。
对于常量和字符串,我推荐一个数组:
struct Entry
unsigned int key;
const char * text;
;
而对于大数量,使用二分查找算法;否则线性搜索的速度差不多(只要对数组进行排序)。
【讨论】:
【参考方案7】:类似:?
#include <sstream>
using namespace std;
string f(int i)
ostringstream oss;
oss << i;
return oss.str();
【讨论】:
【参考方案8】:我一直很喜欢将开关作为控制结构。易于理解和维护。请注意,早期的return
缩短了对break
的需求。
这个例子经过测试并且可以工作:
char* getError(int err)
switch(err)
case 1: return "Request System Info";
case 2: return "Change System Info";
case 10: return "Unkown Error";
default: return "Whaaaat!";
【讨论】:
【参考方案9】:在编译时是否知道字符串?如果是这样,请创建地图
std::map 消息;
messages[key] = "一些值"; messages[key2] = "其他值";
等
如果要从文件中读取它们,那么就像这样
std::ifstream ifile("the file")
while (ifile && !ifile.eof())
ifile >> key >> value;
messages[key] = value;
等
【讨论】:
【参考方案10】:如果您的数字是连续的(或几乎是连续的),一个简单的字符串数组或向量会很好地工作。
如果数字之间的差距很大,最快的方法可能是std::pair<int, std::string>
(或std::pair<int, char *>
)的数组。虽然大多数人会自动想到使用二分搜索来进行快速查找,但在这种情况下,要考虑的少量可能性很可能会让线性搜索非常有效地竞争——事实上,它很可能是可用的最快选择。原因很简单:虽然它会进行更多比较,但它避免了除法之类的事情,而且对 20 个整数的比较无论如何都会很快。
编辑:请注意,std::map 可能不是一个非常好的选择。 std::map 通常使用平衡二叉树,这意味着 20 个项目将使用 20 个节点,每个节点通常是单独分配的。除了您需要存储的 int 之外,每个节点通常还包含至少两个指针,因此您存储的数据量大致增加了三倍——所有这些都导致缓存局部性相对较差。鉴于所涉及的项目数量较少,一次缓存未命中将花费超过 20 次比较。
【讨论】:
【参考方案11】:std::map
再次阅读您的问题,我认为您是说您只有 20 个要映射的数字(您说 20 个数字,这让我想到了非常大的数字)。如果这些都在一个相当小的范围内,那么你最好只使用一个数组。您需要一个与largestIndex - smallestIndex + 1
一样大的字符串指针数组。然后要获取与某个数字关联的字符串,您可以执行以下操作:
std::string GetStatus(int statusID)
return statusArray[statusID - smallestIndex];
statusArray
变量被初始化为:
void SetStatus(int statusID, std::string description)
statusArray[statusID - smallestIndex] = description;
void InitStatuses()
statusArray = new std::string[largestIndex - smallestIndex + 1];
SetStatus(1, "Request System Info");
SetStatus(2, "Change System Info");
SetStatus(10, "Unknown Error");
这将比map
更快,并且非常易于使用。如果您的 ID 差异很大,那就不合适了。
【讨论】:
以上是关于如何将 int 映射到 C/C++ 中的相应字符串的主要内容,如果未能解决你的问题,请参考以下文章
如何将活动记录类特定属性映射到rails中相应的通用关注方法
Entity Framework 4.1 Code First - 如何将包含实体 ID(外键)的 csv 的字符串映射到相应的实体