我写了一个小字符串压缩算法作为练习的一部分(基本上采用字符串“aaaabbbccc”并返回“a4b3c3”)。代码如下:
char *compress(char string[])
{
char buffer[256];
char *pBuffer = buffer;
char* pStr = (string - 1);
char currentCharacter = 0;
int length = 0;
while (*++pStr != 0)
{
currentCharacter = *pStr;
int currentCharacterLength = 1;
while ((*(pStr + 1) == currentCharacter) && (*pStr != 0))
{
currentCharacterLength++;
++pStr;
}
*pBuffer++ = currentCharacter;
*pBuffer++ = (char)currentCharacterLength;
}
(*pBuffer) = 0;
return buffer;
}
但是看着它,我想知道我是否应该创建另一个实际符合返回字符串正确大小的缓冲区。显然,这样做需要更多的处理时间,但会导致更严格的解决方案。所以我想知道,这样的事情的一般做法是什么。牺牲记忆速度是否更好(一般情况下),还是更好地保持原样?
或者甚至更好,有没有更好的方法来编写我甚至不知道的解决方案?
答案 0 :(得分:3)
如果是c ++,更好的方法实际上是使用std :: string类型。
当然,如果你试图理解指针/数组/字符串的行为或处理C库,你需要在某些时候使用字符。
从函数中返回(char *) - 以及任何其他类型的指针时最大的问题是如何处理该指针的所有权。你什么时候摆脱这个指针指向的内容?它可以在代码的多个范围内使用,它可以为您提供所有类型的内存泄漏和未处理的异常。
如果您正在使用c ++,从函数返回指针的最佳方法是使用std :: shared_ptr,因为您不需要直接处理该指针的内存处理。
哦,当然,返回指向堆栈分配的内存的指针:
char buffer[256];
char *pBuffer = buffer;
是您代码中最大的错误。
正确的方法是在堆上分配它:
char *pBuffer = new char[256];
答案 1 :(得分:3)
返回buffer
是未定义的行为:只要您的函数存在,该缓冲区的内容就可以是任何内容。您应该动态分配内存 - 至少返回strdup(buffer)
。
由于这是C ++,因此首选使用std::string
:它将为您正确管理内存,因此即使您没有正确猜测字符串的大小,也不会有缓冲区溢出。如果压缩字符串恰好超过256个字符,则您当前的解决方案将失败;基于std::string
的解决方案将没有这个缺点。
答案 2 :(得分:1)
根据你的回答,像往常一样,这取决于......
您最有限的资源是什么?什么是托管您的申请?如果这是一个嵌入式项目,那么你的应用程序内存是否足以容纳char [256]缓冲区?
如果您在Xcode或Eclipse中的完整计算机设置上运行此程序,那些IDE将在此级别上管理几乎所有内存问题,但是如果您有一个大文件(例如,尝试使用此文件压缩小说schema)然后速度是优化的情况。
如果是这样的话,我会小心你的代码,因为你有一个嵌套循环,它可以将整个压缩算法减慢到O(string.length()^ 2),这对于大字符串来说很糟糕(再次,就像压缩一样)一本书。)
所以在回答你的问题时,如果你想使用这种特殊方法而不是霍夫曼编码或其他一些更有效的算法(在时间和空间上),那么我会保留你当前的设置,但是删除双重时,使用递归代替查找相似字母序列的流。
答案 3 :(得分:1)
如果你想使用指针,你可以这样做:
bool compress(char string[], char* encodedOut, int &encodedSize);
这样您就可以知道编码数组的大小,并且可以处理范围问题。