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语言版本性能明显落后。主要原因如下:

  1. 频繁的内存分配和释放: C语言版本中replaceCstr函数使用动态内存分配,每次替换都需要分配新的内存空间,导致频繁的内存分配和释放,带来较大开销。而Go语言中的字符串是不可变的,不会产生内存分配和释放操作。

  2. 字符串匹配算法效率: Go语言中的strings.ReplaceAll函数使用Boyer-Moore算法实现,该算法是一种高效的字符串匹配算法。而C语言版本中replaceCstr函数是手动实现的字符串查找和替换,效率较低。

优化建议:

  1. 避免频繁的内存分配:

    • 尽量使用静态数组或预先分配足够大的内存空间,避免在每次替换时进行内存分配。
    • 可以使用StringBuilder或其他可变字符串类来减少内存分配。
  2. 采用更高效的字符串匹配算法:

    • 考虑使用Boyer-Moore算法或KMP算法等高效的字符串匹配算法来提高查找和替换效率。
  3. 尝试多线程或并发处理:

    • 可以将字符串处理任务分配到多个线程或协程上,利用多核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 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录