没有和STL的C ++字符串
我过去很少使用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列表等避免这种情况。必须解决它!
很抱歉发布这样一个琐碎的问题,我们将不胜感激任何帮助!
干杯,
an
解决方案
编辑:我想我误解了你的问题。我知道的这段代码中没有常量性问题。
我从头开始这样做,但这应该是正确的:
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; } }
我们可能需要使用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将不适合。
使用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不再邪恶!
使用:
const char **registeredNames = new const char * [numberOfNames];
将允许我们将const * char const分配给数组的元素。
出于好奇,为什么"不能强制使用任何最方便的C ++构造"?
为什么不能使用STL?
无论如何,我建议我们实现一个简单的字符串类并列出自己的模板。这样,我们可以使用与通常相同的技术,并将指针和内存管理限制在这些类之内。如果我们模仿STL,那就更好了。
如果可移植性是一个问题,则可能要签出STLport。
如果我们真的不能使用stl(并且我在游戏行业时很遗憾地认为那是真的),那么我们是否可以不创建自己的字符串类?最基本的字符串类将在构造和分配时分配内存,并在析构函数中处理删除。以后,我们可以根据需要添加其他功能。完全可移植,非常容易编写和进行单元测试。
我能理解为什么我们最不能使用STL会使代码code肿。但是,游戏程序员可以为游戏程序员实现实现。RDESTL是这样的库之一。
我可能会对此投票否决,因为它并不是真正的答案,但是有正当理由可以避免使用STL。在内存或者速度非常重要的固定环境中工作时,有时很难分辨STL到底发生了什么。是的,我们可以编写自己的内存分配器,是的,速度通常不是问题,但是跨平台的STL实现之间存在差异,并且这些差异可能是微妙的并且可能有问题。考虑使用内存时,内存可能是我最大的担忧。我也为一家游戏公司工作,并且工作了很长时间。记忆是宝贵的,我们必须对其使用方式进行严格控制。除非我们一直走这条路,否则这个概念可能没有任何意义,但这是事实。我们确实允许在工具(游戏代码之外)中使用STL,但在实际游戏中禁止使用STL。另一个相关的问题是代码大小。我不太确定STL可以对可执行文件的大小做出多少贡献,但是我们已经看到使用STL时代码大小显着增加。即使可执行文件"仅"大2M,但游戏其他内容的RAM也要少2M。
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+个内存分配。内存非常分散,我们无法让游戏的其余部分适应固定环境。我们把它撕成碎片了。
类设计对于某些事情很有用,但这不是其中之一。这是一种观点,但是它基于现实世界的经验。
如果我们不担心约定,而只是想完成工作,请使用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,这将非常有用。
抱歉,如果我的代码出错,我只是将其从内存中拉出。
建议的所有方法都是有效的,我的意思是,如果Cdos吸引人的方式将其复制,请创建自己的类/接口以呈现相同的抽象,即使用由Contains和Add方法创建的简单链接列表类,并使用由提供的示例代码。其他答案这应该是相对简单的。
通常,关于C ++的一件大事就是,我们可以按照自己想要的方式使其外观和行为发生变化,如果另一种语言可以很好地实现某些功能,则通常可以复制它。
不管我们是否使用STL,const正确性仍然是const正确性。我相信我们正在寻找的是使registeredNames成为一个const char **
,以便对registeredNames [i]
(这是一个const char *
)的赋值起作用。
此外,这真的是我们想要做的吗?似乎复制字符串可能更合适。
而且,鉴于我们要对其进行的操作,我们不应该考虑将其存储在列表中,最好是一组。
我已经使用此String类多年了。
http://www.robertnz.net/string.htm
它几乎提供了
STL字符串,但是实现为真实类而不是模板
并且不使用STL。
这是一个显而易见的案例,我们可以自己动手做。并对向量类执行相同的操作。
- 通过测试优先编程来做到这一点。
- 把事情简单化。
如果我们在MT环境中,请避免引用计数字符串缓冲区。