没有<string>和STL </string>的C ++字符串

时间:2008-09-18 11:19:38

标签: c++ string list

我过去并没有过多地使用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

14 个答案:

答案 0 :(得分:6)

我可能会因为这个答案而被拒绝,因为这不是一个真正的答案,但有合法的理由可以避免STL。当在内存或速度非常高的固定环境中工作时,有时很难通过STL判断引擎的情况。是的,您可以编写自己的内存分配器,是的,速度通常不是问题,但跨平台的STL实现之间存在差异,并且这些差异会变得微妙且可能有问题。在考虑使用它时,记忆可能是我最关心的问题。我也为一家游戏公司工作,并且已经有很长一段时间了。记忆是珍贵的,我们如何使用它需要得到严格控制。除非你走这条路,否则这个概念可能没有意义,但这是真的。我们允许在工具(游戏代码之外)中使用STL,但在实际游戏中禁止使用它。另一个相关问题是代码大小。我稍微不确定STL可以为可执行文件大小做出多少贡献,但我们已经看到使用STL时代码大小明显增加。即使你的可执行文件“仅”大2M,你的游戏也可以减少2M的RAM。

STL确实很好。但是,那些不知道自己在做什么的程序员可能会滥用它。这不是故意的,但是当你不想看到它们时,它会提供令人讨厌的惊喜(再次,内存臃肿和性能问题)

我确信你已经接近你的解决方案了。

for ( i = 0; i < lastIndex; i++ ) {
    if ( !strcmp(&registeredNames[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)

无论你是否使用STL,

const正确性仍然是const正确性。我相信您要找的是将注册名称设为const char **,以便registeredNames[i]const char *}的作业有效。

而且,这真的是你想要做的吗?看起来制作字符串的副本可能更合适。

此外,你不应该考虑将它存储在一个列表中给定你正在进行的操作,一组会更好。

答案 12 :(得分:0)

我已经使用过这个String类多年了。

http://www.robertnz.net/string.htm

它实际上提供了所有的功能 STL字符串但实现为真正的类而不是模板 并且不使用STL。

答案 13 :(得分:0)

这是一个明确的案例,你可以自己动手。并对矢量类做同样的事情。

  • 使用测试优先编程来完成。
  • 保持简单。

如果您在MT环境中,请避免引用计数字符串缓冲区。