修改现有的 char* 或创建临时 char*?

modify existing char* or create a tmp char*?

某些语言,例如 Java,需要您创建另一个字符串才能解决某些类型的问题。但是当涉及到 C 时,什么时候应该创建另一个字符串,什么时候应该简单地修改现有的字符串?

以下面的代码为例:

    char *removeTags(char *s, int length)
{
    if (!s || length < 1)
    {
        exit(EXIT_FAILURE);
    }
    char *tmp = calloc(length, sizeof(char));
    int count = 0;
    for (int i = 0; i < length; i++)
    {
        if (s[i] == '<')
        {
            for (int k = i; k < length; k++)
            {
                if (s[k] == '>')
                {
                    i = k;
                    break;
                }
            }
        }
        else if (s[i] != '>' && s[i] != '<')
        {
            tmp[count] = s[i];
            count++;
        }
    }
    return tmp;
}

应该这样调用:

char *foo = (char *)calloc(length, sizeof(char)); foo = removeTags(foo, strlen(foo));

如果我只是修改 char *s 而不是创建 char *tmp 来帮助我会更好吗?

如果函数处理字符串,那么第二个参数是多余的,error-prone

char *removeTags(char *s, int length)

如果你想创建一个新的字符串,那么这个函数必须声明为

char * removeTags( const char *s );

即函数参数应具有限定符const.

如果您想就地更改字符串,则函数必须声明为

char * removeTags( char *s );

请注意,您不能更改字符串文字。

如果您还向函数传递字符串文字,则函数必须声明为

char * removeTags( const char *s );

您可以定义这两个函数,但在这种情况下您需要使用不同的函数名称。

每当您在 C 函数中修改字符串时,都有一个很好的理由来制作字符串的副本并修改 return 副本,同时使您的输入字符串参数成为 const char *

您的调用者不会通过传入字符串文字来调用未定义的行为。这可能会使您的整个过程崩溃,例如 SIGSEGV.

像这样:

char *removeTags(const char *s);

一般情况下,您不需要为字符串操作传递长度,除非您需要限制您正在操作的字符串的范围。

另一个不太重要的原因:调用者可能还没有完成对字符串的处理,可能需要不修改它。

如果您随后通过分析发现额外的复制步骤会导致性能或内存问题,那么您可以创建另一个函数,并像这样调用它:

void removeTagsInPlace(char *s);

请注意 return 值的差异,这使得字符串被修改的事实 in-place 不可能被遗漏。