建议改进C ReplaceString函数?

时间:2010-09-22 17:20:04

标签: c string replace

我刚开始接受C编程,并会对我的ReplaceString函数表示赞赏。 它似乎非常快(它没有为结果字符串分配除一个malloc之外的任何内存)但它看起来非常冗长,我知道它可以做得更好。

使用示例:

printf("New string: %s\n", ReplaceString("great", "ok", "have a g grea great day and have a great day great"));
printf("New string: %s\n", ReplaceString("great", "fantastic", "have a g grea great day and have a great day great"));

代码:

#ifndef uint
    #define uint unsigned int
 #endif

char *ReplaceString(char *needle, char *replace, char *haystack)
{
    char *newString;
    uint lNeedle = strlen(needle);
    uint lReplace = strlen(replace);
    uint lHaystack = strlen(haystack);
    uint i;
    uint j = 0;
    uint k = 0;
    uint lNew;
    char active = 0;
    uint start = 0;
    uint end = 0;

    /* Calculate new string size */    
    lNew = lHaystack;

    for (i = 0; i < lHaystack; i++)
    {

        if ( (!active) && (haystack[i] == needle[0]))
        {
            /* Start of needle found */
            active = 1;
            start = i;
            end = i;
        }
        else if ( (active) && (i-start == lNeedle) )
        {
            /* End of needle */
            active = 0;
            lNew += lReplace - lNeedle;
        }
        else if ( (active) && (i-start < lNeedle) && (haystack[i] == needle[i-start]) )
        {
            /* Next part of needle found */
            end++;
        }
        else if (active)
        {
            /* Didn't match the entire needle... */
            active = 0;
        }

    }
    active= 0;
    end = 0;


    /* Prepare new string */
    newString = malloc(sizeof(char) * lNew + 1);
    newString[sizeof(char) * lNew] = 0;

    /* Build new string */
    for (i = 0; i < lHaystack; i++)
    {

        if ( (!active) && (haystack[i] == needle[0]))
        {
            /* Start of needle found */
            active = 1;
            start = i;
            end = i;
        }
        else if ( (active) && (i-start == lNeedle) )
        {
            /* End of needle - apply replacement */
            active = 0;

            for (k = 0; k < lReplace; k++)
            {
                newString[j] = replace[k];
                j++;
            }
            newString[j] = haystack[i];
            j++;

        }
        else if ( (active) && (i-start < lNeedle) && (haystack[i] == needle[i-start])
                )
        {
            /* Next part of needle found */
            end++;
        }
        else if (active)
        {
            /* Didn't match the entire needle, so apply skipped chars */
            active = 0;

            for (k = start; k < end+2; k++)
            {
                newString[j] = haystack[k];
                j++;
            }

        }
        else if (!active)
        {
            /* No needle matched */
            newString[j] = haystack[i];
            j++;
        }

    }

    /* If still matching a needle... */
    if ( active && (i-start == lNeedle))
    {
        /* If full needle */
        for (k = 0; k < lReplace; k++)
        {
            newString[j] = replace[k];
            j++;
        }
        newString[j] = haystack[i];
        j++;
    }
    else if (active)
    {
        for (k = start; k < end+2; k++)
        {
            newString[j] = haystack[k];
            j++;
        }
    }

    return newString;
}

有什么想法吗?非常感谢!

5 个答案:

答案 0 :(得分:3)

不要叫strlen(haystack)。您已经在检查字符串中的每个字符,因此计算字符串长度对于循环是隐含的,如下所示:

for (i = 0; haystack[i] != '\0'; i++)
{
    ...
}
lHaystack = i;

答案 1 :(得分:2)

你有可能以自己的方式做这个练习。如果是这样,你会得到很多积分。

如果没有,您通常可以使用C运行时库(CRT)中的函数与编写自己的等效函数来节省时间。例如,您可以使用strstr来找到要替换的字符串。其他字符串操作函数也可能对您有用。

一个很好的练习是让你满意地完成这个例子,然后使用CRT重新编码,看看编码和执行的速度有多快。

答案 2 :(得分:1)

在第一次循环时,您应该将索引保留在需要替换的位置,并跳过函数的strcopy / replace部分。这将导致一个循环,您只能从haystack执行strncpy或替换为新的字符串。

答案 3 :(得分:0)

制作参数const

char *ReplaceString(const char *needle, const char *replace, const char *haystack)

哦......这个函数应该只用于每个单词一次吗?

ReplaceString("BAR", "bar", "BARBARA WENT TO THE BAR")

答案 4 :(得分:0)

我的一个建议与提高性能无关,但提高了可读性。

“可爱”参数名称比描述性名称更难理解。您认为以下哪个参数能够更好地传达其目的?

char *ReplaceString(char *needle, char *replace, char *haystack)
char *ReplaceString(char *oldText, char *newText, char *inString)

有了一个,你必须有意识地将名字映射到一个目的。另一方面,目的是名称。在尝试理解一段代码时,在脑海中处理一堆名称映射会变得很困难,尤其是随着变量数量的增加。

当您是唯一一个使用您的代码的人时,这似乎并不那么重要,但是当您的代码被其他人使用或阅读时,这一点至关重要。有时候,“别人”就是你自己,一年后,看着你自己的代码,想知道你为什么要搜索干草堆并试图更换针头;)