D语言字符串替换函数betterc实现优化比较
D语言字符串替换函数betterc实现优化比较
本文比较了D语言中字符串替换函数betterc实现和原版实现的性能差异,并提供了优化建议。
原版实现:
import std.stdio;
import core.stdc.stdio:printf;
import core.stdc.string;
import core.stdc.stdlib : malloc, free;
import core.stdc.ctype:tolower;
import std:toUTFz;
import std.string:fromStringz,toStringz;
import std.datetime;
import std.conv:to;
/** 判断字符串是否以\0结束 **/
bool isStringEndsWithEmptyChar(string allStr)
{
if(allStr[$-1] == '\0')
{
return true;
}
auto thePtr = allStr.ptr;
if(thePtr[allStr.length]=='�')
{
return true;
}
return false;
}
/**
转为c语言char*类型
1,最后一个字符是否为\0空字符,如果是则直接转为c语言的char*
2,不是根据情况是否产生新的,比如判断是否是常量区域字符串
**/
char* toCharPtrByUtf(string allStr,bool isCanWrite=false)
{
auto thePtr = allStr.ptr;
bool isHasEmpty = isStringEndsWithEmptyChar(allStr);
if(!isCanWrite)
{
if(isHasEmpty)
{
return cast(char*)thePtr;
}
else
{
return toUTFz!(char*)(allStr);
}
}
//不是指向常量数据区域的指针
if (cast(ulong) thePtr >= 0x400000 && cast(ulong) thePtr <= 0x600000)
{
return toUTFz!(char*)(allStr);
}
if(isHasEmpty)
{
return cast(char*)thePtr;
}
else
{
return toUTFz!(char*)(allStr);
}
}
/**
转为c语言char*类型
1,最后一个字符是否为\0空字符,如果是则直接转为c语言的char*
2,总会复制一个信的字符串,利用toStringz
**/
char* toCharPtr(string allStr,bool isCanWrite=false)
{
auto thePtr = allStr.ptr;
bool isHasEmpty = isStringEndsWithEmptyChar(allStr);
if(!isCanWrite)
{
if(isHasEmpty)
{
return cast(char*)thePtr;
}
else
{
return cast(char*)(toStringz(allStr));
}
}
//不是指向常量数据区域的指针
if (cast(ulong) thePtr >= 0x400000 && cast(ulong) thePtr <= 0x600000)
{
return cast(char*)(toStringz(allStr));
}
if(isHasEmpty)
{
return cast(char*)thePtr;
}
else
{
return cast(char*)(toStringz(allStr));
}
}
/**
转为c语言const char*类型
**/
const(char) * toConstCharPtrByUtf(string allStr)
{
auto thePtr = allStr.ptr;
bool isHasEmpty = isStringEndsWithEmptyChar(allStr);
if(isHasEmpty)
{
return thePtr;
}
else
{
return toUTFz!(const(char) *)(allStr);
}
}
/**
转为c语言const char*类型
**/
const(char) * toConstCharPtr(string allStr)
{
auto thePtr = allStr.ptr;
bool isHasEmpty = isStringEndsWithEmptyChar(allStr);
if(isHasEmpty)
{
return thePtr;
}
else
{
return cast(const(char) *)(toStringz(allStr));
}
}
// 判断两个字符是否相等,根据 isCaseSensitive 参数决定是否区分大小写
private bool charEqual(char a, char b, bool isCaseSensitive) @nogc nothrow
{
if (isCaseSensitive)
{
return a == b;
}
else
{
return tolower(a) == tolower(b);
}
}
// 在字符串 haystack 中查找第一次出现 needle 的位置,返回指向该位置的指针,如果找不到则返回 null
private char* strstrCase(char* haystack, const char* needle, bool isCaseSensitive) @nogc nothrow
{
if (!haystack || !needle || !*needle)
{
return haystack;
}
size_t haystackLen = strlen(haystack);
size_t needleLen = strlen(needle);
if (needleLen > haystackLen)
{
return null;
}
if (isCaseSensitive)
{
return strstr(haystack, needle);
}
for (size_t i = 0; i <= haystackLen - needleLen; i++)
{
bool found = true;
for (size_t j = 0; j < needleLen; j++)
{
if (!charEqual(haystack[i + j], needle[j], isCaseSensitive))
{
found = false;
break;
}
}
if (found)
{
return haystack + i;
}
}
return null;
}
char* replaceCstr(const char* allStr, const char* searchStr, const char* replaceStr, bool isCaseSensitive=true) @nogc nothrow
{
if (!allStr || !searchStr || !replaceStr || !*searchStr)
{
return cast(char*)allStr;
}
char* result = null;
ulong searchStrLength = strlen(searchStr);
ulong replaceStrLength = strlen(replaceStr);
ulong count = 0;
char* p = cast(char*)allStr;
while ((p = strstrCase(p, searchStr, isCaseSensitive)) != null)
{
count++;
p += searchStrLength;
}
if (count == 0)
{
return cast(char*)allStr;
}
ulong newStrLength = strlen(allStr) + count * (replaceStrLength - searchStrLength);
result = cast(char*) malloc(newStrLength + 1);
char* q = result;
p = cast(char*)allStr;
while (count-- > 0)
{
char* r = strstrCase(p, searchStr, isCaseSensitive);
long length = r - p;
memmove(q, p, length);
q += length;
memcpy(q, replaceStr, replaceStrLength);
q += replaceStrLength;
p = r + searchStrLength;
}
strcpy(q, p);
return result;
}
void main()
{
auto start = Clock.currTime();
string str = 'hello, world!';
const(char*) oldptr = toConstCharPtr(str);
char* now = null;
for (int ii = 0; ii < 10000000; ii++)
{
now = replaceCstr(oldptr,'o'.ptr,'O'.ptr);
now = replaceCstr(oldptr,'l'.ptr,'1'.ptr);
now = replaceCstr(oldptr,','.ptr,''.ptr);
now = replaceCstr(oldptr,'!'.ptr,''.ptr);
//str = str.replaceString('o', '0').replaceString('l', '1').replaceString(',', '').replaceString('!', '');
}
if(oldptr!=now)
{
free(now);
}
auto end = Clock.currTime();
writeln('D语言程序运行时间 :', end-start);
}
replaceCstr相同功能内容:的betterc实现:
import core.stdc.stdlib : malloc, free;
import core.stdc.string;
import std.datetime;
import std.conv:to;
char* replaceCstr(const char* allStr, const char* searchStr, const char* replaceStr, bool isCaseSensitive=true) @nogc nothrow
{
if (!allStr || !searchStr || !replaceStr || !*searchStr)
{
return cast(char*)allStr;
}
char* result = null;
ulong searchStrLength = strlen(searchStr);
ulong replaceStrLength = strlen(replaceStr);
ulong count = 0;
char* p = cast(char*)allStr;
while ((p = strstr(p, searchStr)) != null)
{
count++;
p += searchStrLength;
}
if (count == 0)
{
return cast(char*)allStr;
}
ulong newStrLength = strlen(allStr) + count * (replaceStrLength - searchStrLength);
result = cast(char*) malloc(newStrLength + 1);
char* q = result;
p = cast(char*)allStr;
while (count-- > 0)
{
char* r = strstr(p, searchStr);
long length = r - p;
memmove(q, p, length);
q += length;
memcpy(q, replaceStr, replaceStrLength);
q += replaceStrLength;
p = r + searchStrLength;
}
strcpy(q, p);
return result;
}
void main()
{
auto start = Clock.currTime();
string str = 'hello, world!';
const(char*) oldptr = cast(const char*)str.ptr;
char* now = null;
for (int ii = 0; ii < 10000000; ii++)
{
now = replaceCstr(oldptr,'o','O');
now = replaceCstr(oldptr,'l','1');
now = replaceCstr(oldptr,',','');
now = replaceCstr(oldptr,'!','');
}
if(oldptr!=now)
{
free(now);
}
auto end = Clock.currTime();
writeln('D语言程序运行时间 :', end-start);
}
betterc实现:
import core.stdc.stdlib : malloc, free;
import core.stdc.string;
import std.datetime;
import std.conv:to;
char* replaceCstr(const char* allStr, const char* searchStr, const char* replaceStr, bool isCaseSensitive=true) @nogc nothrow
{
if (!allStr || !searchStr || !replaceStr || !*searchStr)
{
return cast(char*)allStr;
}
char* result = null;
ulong searchStrLength = strlen(searchStr);
ulong replaceStrLength = strlen(replaceStr);
ulong count = 0;
char* p = cast(char*)allStr;
while ((p = strstr(p, searchStr)) != null)
{
count++;
p += searchStrLength;
}
if (count == 0)
{
return cast(char*)allStr;
}
ulong newStrLength = strlen(allStr) + count * (replaceStrLength - searchStrLength);
result = cast(char*) malloc(newStrLength + 1);
char* q = result;
p = cast(char*)allStr;
while (count-- > 0)
{
char* r = strstr(p, searchStr);
long length = r - p;
memmove(q, p, length);
q += length;
memcpy(q, replaceStr, replaceStrLength);
q += replaceStrLength;
p = r + searchStrLength;
}
strcpy(q, p);
return result;
}
void main()
{
auto start = Clock.currTime();
string str = 'hello, world!';
const(char*) oldptr = cast(const char*)str.ptr;
char* now = null;
for (int ii = 0; ii < 10000000; ii++)
{
now = replaceCstr(oldptr,'o','O');
now = replaceCstr(oldptr,'l','1');
now = replaceCstr(oldptr,',','');
now = replaceCstr(oldptr,'!','');
}
if(oldptr!=now)
{
free(now);
}
auto end = Clock.currTime();
writeln('D语言程序运行时间 :', end-start);
}
性能比较:
测试结果表明,betterc实现的性能明显优于原版实现。这是因为betterc实现利用了C语言标准库中的strstr函数,而原版实现则自己实现了字符串查找功能,效率较低。
优化建议:
- 使用C语言标准库中的字符串处理函数,例如strstr、memcpy、memmove等,可以显著提高性能。
- 避免不必要的内存分配和释放,例如在循环中重复分配和释放内存,会降低性能。
- 使用@nogc修饰符,可以避免垃圾回收的开销,提高性能。
总结:
通过比较betterc实现和原版实现的性能差异,我们可以发现,betterc实现利用了C语言标准库中的函数,效率更高。在实际开发中,应尽量使用C语言标准库中的函数来提高代码性能。
原文地址: https://www.cveoy.top/t/topic/jom5 著作权归作者所有。请勿转载和采集!