这是来自K& R的第65页。说明该函数返回字符串长度。这是代码:
int trim (char s[])
{
int n;
for (n = strlen(s)-1; n >= 0; n--)
if (s[n] != ' ' && s[n] != '\t' && s[n] != '\n')
break;
s[n+1] = '\0';
return n;
}
看起来它应该返回n + 1。空字符不被视为字符串的一部分吗?
示例:
char s[4];
s[0] = c, s[1] = a, s[2] = t, s[3] = '\0';
这不意味着字符串大小为3并且有3个可用元素吗?该函数将返回2,这是不正确的。
另外,字符串长度定义为什么?
答案 0 :(得分:3)
你绝对正确:退回的" n"在你的例子中==" strlen(s)-1&#34 ;; 不" strlen(s)"。
#include <stdio.h>
#include <string.h>
int
trim (char s[])
{
int initial_strlen = strlen(s);
int n;
for (n = initial_strlen-1; n >= 0; n--) {
if (s[n] != ' ' && s[n] != '\t' && s[n] != '\n')
break;
}
s[n+1] = '\0';
printf ("s=%s, initial strlen=%d, current strlen=%d, n=%d\n",
s, initial_strlen, strlen(s), n);
return n+1;
}
int
main (int argc, char *argv[])
{
char buf[80];
strcpy(buf, "cat ");
printf ("trim #1= %d\n", trim (buf));
strcpy(buf, "cat\t\t\t ");
printf ("trim #2= %d\n", trim (buf));
return 0;
}
示例输出:
s=cat, initial strlen=6, current strlen=3, n=2
trim #1= 3
s=cat, initial strlen=9, current strlen=3, n=2
trim #2= 3
答案 1 :(得分:3)
问题在于它只是一个糟糕的代码。它是不应该编写代码的一个例子。通常,任何错误代码都包含错误,此示例演示了此规则。:) 这是一个糟糕的代码,因为至少你甚至无法自信地说出函数必须返回的内容。:)如果它不返回strlen(s)那么为什么它必须返回strlen(s) - 1特别是为空字符串。
我会按照以下方式编写函数
size_t trim( char s[] )
{
size_t n = strlen( s );
while ( n != 0 && ( s[n-1] == ' ' || s[n-1] == '\t' || s[n-1] == '\n' ) ) --n;
s[n] = '\0';
return n;
}
将我的代码与您展示的代码进行比较。在我的代码中很明显,如果循环不会被迭代,函数将返回strlen( s )
。那就是你甚至不需要研究循环的作用。如果您删除循环,例如
size_t trim( char s[] )
{
size_t n = strlen( s );
s[n] = '\0';
return n;
}
代码将非常清晰易读。它是一个不变的。
至于循环,它使用C ++中的双向迭代器的习惯用法。所以这样的代码再次易于阅读。并且没有任何中断声明。:)
考虑到删除tralling white space后函数返回sizeof( s )
很重要。例如,当你想要连接两个字符串时可以使用它。
答案 2 :(得分:3)
你是正确的trim
的给定实现不会返回结果字符串的长度。
不一定不正确。
我的K&amp; R(第二版)副本说:
以下函数
trim
从字符串末尾删除尾随空格,制表符和换行符,使用break
从最右边的非空白非选项卡退出循环,找到非换行符。/* trim: remove trailing blanks, tabs, newlines */ [... code ...]
strlen
会返回字符串的长度....
它没有说明trim
的预期回报值是什么意思。虽然我同意它的实际返回值是不直观的,但它并不一定是错的,因为我们没有被告知它应该如何表现。
此外,您可能希望查看the errata for K&R's The C Programming Language(此示例未列出)。
答案 3 :(得分:1)
一方面,终止零字符不计入字符串 length 的一部分。这是strlen
的工作原理,例如。例如。字符串"ABCD"
的长度为4
,这是很自然的事情。
另一方面,上面的trim
函数确实返回的值少于实际的字符串长度。实际上,它应该返回n + 1
。
示例中的字符串长度确实为3
。这是正确的长度。终止零字符不计算为长度的一部分。如果计算终止零,则长度为4
。
答案 4 :(得分:1)
我想这本书中有一个错误,该函数应该是:
int trim(char s[])
{
int n;
for (n = strlen(s); n > 0; n--) {
if (s[n-1] != ' ' && s[n-1] != '\t' && s[n-1] != '\n') {
break;
}
}
s[n] = '\0';
return n;
}