C语言字符串替换性能优化:对比Golang版本,提升效率
C语言字符串替换性能优化:对比Golang版本,提升效率
本文分析了C语言字符串替换代码的性能瓶颈,并与Golang版本进行对比,提供针对性的优化建议,帮助你提升代码执行效率。
C语言代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>
// 判断两个字符是否相等,根据 isCaseSensitive 参数决定是否区分大小写
int charEqual(char a, char b, int isCaseSensitive)
{
if (isCaseSensitive)
{
return a == b;
}
else
{
return tolower(a) == tolower(b);
}
}
// 在字符串 haystack 中查找第一次出现 needle 的位置,返回指向该位置的指针,如果找不到则返回 null
char* strstrCase(char* haystack, const char* needle, int isCaseSensitive)
{
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++)
{
int found = 1;
for (size_t j = 0; j < needleLen; j++)
{
if (!charEqual(haystack[i + j], needle[j], isCaseSensitive))
{
found = 0;
break;
}
}
if (found)
{
return haystack + i;
}
}
return NULL;
}
char* replaceCstr(const char* allStr, const char* searchStr, const char* replaceStr, int isCaseSensitive)
{
if (!allStr || !searchStr || !replaceStr || !*searchStr)
{
return (char*)allStr;
}
char* result = NULL;
size_t searchStrLength = strlen(searchStr);
size_t replaceStrLength = strlen(replaceStr);
size_t count = 0;
char* p = (char*)allStr;
while ((p = strstrCase(p, searchStr, isCaseSensitive)) != NULL)
{
count++;
p += searchStrLength;
}
if (count == 0)
{
return (char*)allStr;
}
size_t newStrLength = strlen(allStr) + count * (replaceStrLength - searchStrLength);
result = (char*) malloc(newStrLength + 1);
char* q = result;
p = (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;
}
int main()
{
clock_t start = clock();
char str[] = 'hello, world!';
const char* oldptr = str;
char* now = NULL;
for (int ii = 0; ii < 10000000; ii++)
{
now = replaceCstr(oldptr,'o','O',1);
free(now);
now = replaceCstr(oldptr,'l','1',1);
free(now);
now = replaceCstr(oldptr,',',' ',1);
free(now);
now = replaceCstr(oldptr,'!',' ',1);
free(now);
//str = str.replaceString('o', '0').replaceString('l', '1').replaceString(',', '').replaceString('!', '');
}
clock_t end = clock();
double time_spent = (double)(end - start) / CLOCKS_PER_SEC;
printf('C语言程序运行时间 :%f\n', time_spent);
return 0;
}
Golang代码:
package main
import (
'fmt'
'strings'
'time'
)
func main() {
start := time.Now()
str := 'hello, world!'
for i := 0; i < 10000000; i++ {
str = strings.ReplaceAll(str, 'o', '0')
str = strings.ReplaceAll(str, 'l', '1')
str = strings.ReplaceAll(str, ',', '')
str = strings.ReplaceAll(str, '!', '')
}
end := time.Now()
fmt.Println('Golang程序运行时间:', end.Sub(start).Milliseconds(), 'ms')
}
性能分析:
运行结果显示,C语言版本耗时2700ms,Go语言版本消耗时间400ms,C语言版本性能明显落后。主要原因如下:
-
频繁的内存分配和释放: C语言版本中replaceCstr函数使用动态内存分配,每次替换都需要分配新的内存空间,导致频繁的内存分配和释放,带来较大开销。而Go语言中的字符串是不可变的,不会产生内存分配和释放操作。
-
字符串匹配算法效率: Go语言中的strings.ReplaceAll函数使用Boyer-Moore算法实现,该算法是一种高效的字符串匹配算法。而C语言版本中replaceCstr函数是手动实现的字符串查找和替换,效率较低。
优化建议:
-
避免频繁的内存分配:
- 尽量使用静态数组或预先分配足够大的内存空间,避免在每次替换时进行内存分配。
- 可以使用StringBuilder或其他可变字符串类来减少内存分配。
-
采用更高效的字符串匹配算法:
- 考虑使用Boyer-Moore算法或KMP算法等高效的字符串匹配算法来提高查找和替换效率。
-
尝试多线程或并发处理:
- 可以将字符串处理任务分配到多个线程或协程上,利用多核CPU提高效率。
示例代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>
#define MAX_STRING_LENGTH 100
int main() {
clock_t start = clock();
char str[MAX_STRING_LENGTH] = 'hello, world!';
char* now = str;
for (int ii = 0; ii < 10000000; ii++) {
// 在原字符串上进行替换,避免内存分配
for (int i = 0; now[i] != '�'; i++) {
if (now[i] == 'o') {
now[i] = 'O';
} else if (now[i] == 'l') {
now[i] = '1';
} else if (now[i] == ',') {
now[i] = ' ';
} else if (now[i] == '!') {
now[i] = ' ';
}
}
}
clock_t end = clock();
double time_spent = (double)(end - start) / CLOCKS_PER_SEC;
printf('C语言程序运行时间 :%f\n', time_spent);
return 0;
}
总结:
通过优化C语言代码,可以显著提升其字符串替换性能,使其与Go语言版本接近。在选择语言和算法时,要考虑程序的性能需求,并根据实际情况进行优化。
参考链接:
注意:
本示例代码仅供参考,实际应用中需要根据具体情况进行调整和优化。
原文地址: https://www.cveoy.top/t/topic/ohVM 著作权归作者所有。请勿转载和采集!