有些语言,如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
来帮助我,会更好吗?
如果函数处理字符串,那么第二个参数是冗余的并且容易出错的
char *removeTags(char *s, int length)
如果你想创建一个新的字符串,那么函数必须像一样声明
char * removeTags( const char *s );
也就是说,函数参数应具有限定符const
。
如果你想在适当的位置更改字符串,那么函数必须像一样声明
char * removeTags( char *s );
请注意,您可能不会更改字符串文字。
如果您还将字符串文字传递给函数,则该函数必须像一样声明
char * removeTags( const char *s );
您可以定义这两个函数,但在这种情况下,您需要使用不同的函数名称。
无论何时修改C函数中的字符串,都有一个非常好的理由来复制该字符串并修改并返回该副本,同时将输入字符串参数设置为const char *
。
调用方不会通过传入字符串文字来调用未定义的行为。这可能会用SIGSEGV
之类的东西破坏你的整个过程。
像这样:
char *removeTags(const char *s);
通常,您不需要为字符串操作传递长度,除非您需要限制正在操作的字符串的范围。
另一个不太重要的原因是:调用者可能没有处理好字符串,可能需要对其进行修改。
如果您通过分析发现额外的复制步骤会导致性能或内存问题,那么您可以创建另一个函数,并将其命名为:
void removeTagsInPlace(char *s);
注意返回值的差异,这使得字符串在适当的位置被修改的事实不可能错过