我过去并没有过多地使用C ++,并且最近做了很多C#,我真的很难再次回到C ++的基础知识。这是特别棘手的,因为工作要求不能使用最方便的C ++构造,因此所有字符串必须是char *,并且没有STL列表的规定。
我目前要做的是创建一个字符串列表,这些东西在我使用STL或C#时都没有时间。基本上我想要一个如下的功能:
char **registeredNames = new char*[numberOfNames];
然后,
RegisterName(const * char const name, const int length)
{
//loop to see if name already registered snipped
if(notFound)
{
registeredNames[lastIndex++] = name;
}
}
或者,如果是C#......
if(!registeredNames.Contains(name))
{
registeredNames.Add(name);
}
我意识到它不起作用。我知道传递的变量(一个const指针和一个const字符串)的const性质使它相当困难,但我的基本问题是我以前总是通过使用STL列表等来避免这种情况所以我从来没有不得不解决它!
我很抱歉发布这样一个微不足道的问题,任何帮助都会非常感激!
干杯,
XAN
答案 0 :(得分:6)
我可能会因为这个答案而被拒绝,因为这不是一个真正的答案,但有合法的理由可以避免STL。当在内存或速度非常高的固定环境中工作时,有时很难通过STL判断引擎的情况。是的,您可以编写自己的内存分配器,是的,速度通常不是问题,但跨平台的STL实现之间存在差异,并且这些差异会变得微妙且可能有问题。在考虑使用它时,记忆可能是我最关心的问题。我也为一家游戏公司工作,并且已经有很长一段时间了。记忆是珍贵的,我们如何使用它需要得到严格控制。除非你走这条路,否则这个概念可能没有意义,但这是真的。我们允许在工具(游戏代码之外)中使用STL,但在实际游戏中禁止使用它。另一个相关问题是代码大小。我稍微不确定STL可以为可执行文件大小做出多少贡献,但我们已经看到使用STL时代码大小明显增加。即使你的可执行文件“仅”大2M,你的游戏也可以减少2M的RAM。
STL确实很好。但是,那些不知道自己在做什么的程序员可能会滥用它。这不是故意的,但是当你不想看到它们时,它会提供令人讨厌的惊喜(再次,内存臃肿和性能问题)
我确信你已经接近你的解决方案了。
for ( i = 0; i < lastIndex; i++ ) {
if ( !strcmp(®isteredNames[i], name ) {
break; // name was found
}
}
if ( i == lastIndex ) {
// name was not found in the registeredNames list
registeredNames[lastIndex++] = strdup(name);
}
您可能不想使用strdup。这只是一个如何在给出示例的情况下存储名称的示例。您可能希望确保自己不想为新名称分配空间,或者使用可能已在应用程序中可用的其他内存构造。
请不要写一个字符串类。我举起字符串类可能是如何不在C ++中重新设计基本C构造的最糟糕的例子。是的,字符串类可以隐藏许多漂亮的细节,但它的内存使用模式很糟糕,而且它们不适合控制台(即ps3或360等)环境。大约8年前,我们做了同一时间。在我们点击主菜单之前,有200000多个内存分配。内存非常分散,我们无法让其他游戏适应固定环境。我们最终把它撕掉了。
类设计对某些事情很有用,但这不是其中之一。这是一个观点,但它基于现实世界的经验。
答案 1 :(得分:5)
您可能需要使用strcmp来查看字符串是否已存储:
for (int index=0; index<=lastIndex; index++)
{
if (strcmp(registeredNames[index], name) == 0)
{
return; // Already registered
}
}
然后,如果你真的需要存储字符串的副本,那么你需要分配一个缓冲区并复制字符。
char* nameCopy = malloc(length+1);
strcpy(nameCopy, name);
registeredNames[lastIndex++] = nameCopy;
您没有提到您的输入是否为NULL终止 - 如果没有,则需要格外小心,并且strcmp / strcpy不合适。
答案 2 :(得分:5)
如果可移植性存在问题,您可能需要查看STLport。
答案 3 :(得分:3)
为什么不能使用STL?
无论如何,我建议您实现一个简单的字符串类并列出自己的模板。这样,您可以使用与通常相同的技术,并将指针和内存管理限制在这些类中。如果你模仿STL,它会更好。
答案 4 :(得分:2)
如果你真的不能使用stl(我很遗憾相信当我在游戏行业时这是真的)那么你能创建自己的字符串类吗?最基本的字符串类将在构造和赋值时分配内存,并在析构函数中处理删除。稍后您可以根据需要添加更多功能。完全便携,非常容易编写和单元测试。
答案 5 :(得分:1)
编辑:我想我误解了你的问题。我知道这段代码中没有constness问题。
我是从头脑中做到的,但它应该是正确的:
static int lastIndex = 0;
static char **registeredNames = new char*[numberOfNames];
void RegisterName(const * char const name)
{
bool found = false;
//loop to see if name already registered snipped
for (int i = 0; i < lastIndex; i++)
{
if (strcmp(name, registeredNames[i] == 0))
{
found = true;
break;
}
}
if (!found)
{
registeredNames[lastIndex++] = name;
}
}
答案 6 :(得分:1)
使用char *需要您使用C函数。在你的情况下,你真正需要的是复制字符串。为了帮助您,您有strndup功能。然后你必须写下这样的东西:
void RegisterName(const char* name)
{
// loop to see if name already registered snipped
if(notFound)
{
registerNames[lastIndex++] = stdndup(name, MAX_STRING_LENGTH);
}
}
此代码假设您的数组足够大。
当然,最好的方法是正确实现你自己的字符串和数组并列出,......或者说服你的老板STL不再是邪恶了!
答案 7 :(得分:1)
使用:
const char **registeredNames = new const char * [numberOfNames];
允许您将const * char const
分配给数组的元素。
出于好奇,为什么“工作要求不能使用最方便的C ++结构”?
答案 8 :(得分:1)
我可以理解为什么你不能使用STL - 大多数人都非常臃肿你的代码。然而,游戏程序员有游戏程序员的实现 - RDESTL就是这样一个库。
答案 9 :(得分:0)
如果您不担心约定而只是想完成工作,请使用realloc。我一直在为列表做这种事情,它是这样的:
T** list = 0;
unsigned int length = 0;
T* AddItem(T Item)
{
list = realloc(list, sizeof(T)*(length+1));
if(!list) return 0;
list[length] = new T(Item);
++length;
return list[length];
}
void CleanupList()
{
for(unsigned int i = 0; i < length; ++i)
{
delete item[i];
}
free(list)
}
你可以做的更多,例如每次列表大小加倍时只重新分配,通过索引或检查相等性从列表中删除项目的功能,制作处理列表等的模板类...(我有一个我写的很久以前总是使用自己...但遗憾的是我在工作,不能只是复制粘贴在这里)。不过要说实话,这可能不会超过STL等价物,但如果你做了大量的工作或者STL的执行效果特别差,它可能会等于它的性能。
恼人的C ++没有运营商更新/调整大小来替换realloc,这将非常有用。
哦,如果我的代码出错,我会道歉,我只是把它从内存中拉出来。
答案 10 :(得分:0)
所有建议的方法都是有效的,我的观点是,如果C#的方式是吸引人复制它,创建自己的类/接口来呈现相同的抽象,即使用方法Contains和Add的简单链接列表类,使用其他答案提供的示例代码应该相对简单。
关于C ++的一个好处是,通常你可以让它看起来像你想要的那样,如果另一种语言有很好的实现,你通常可以重现它。
答案 11 :(得分:0)
const正确性仍然是const正确性。我相信您要找的是将注册名称设为const char **
,以便registeredNames[i]
(const char *
}的作业有效。
而且,这真的是你想要做的吗?看起来制作字符串的副本可能更合适。
此外,你不应该考虑将它存储在一个列表中给定你正在进行的操作,一组会更好。
答案 12 :(得分:0)
答案 13 :(得分:0)
这是一个明确的案例,你可以自己动手。并对矢量类做同样的事情。
如果您在MT环境中,请避免引用计数字符串缓冲区。