K&R C 编程书中 3.7 节的 trim 函数示例

3

我一直在跟随K&R第二版的C编程书,但在3.7部分中,这是函数和我的代码部分的截图:

enter image description here

#include <stdio.h>
#include <string.h>
/* trim: removing the trailing blanks, tabs and newlines  */
int trim(char s[]);
int main(){
    char s[] = "hello,world       \t\t\t\t\n\n\n\n";
    printf("%s\n", s);
    int length = trim(s);
    printf("%d\n", length);
    return 0;
}
int trim(char s[]){
   int n;
   for (n = strlen(s) -1 ; n >= 0 ; n--)
       if (s[n] != ' ' && s[n] != '\n' && s[n] != '\t')
            break;
   s[n+1] = '\0';
   return n;
}


以下是我运行它后得到的输出:

enter image description here

显然结果长度为11,即"hello,world",但程序输出为10,原因是s[n+1] = '\n',而不是s[++n]。我认为应该是s[++n],否则我会得到错误的输出==> 10,怎么处理?有人能看一下吗?

你为什么认为10是错误的,而11是正确的?“显然”不是一个好的理由。所设计的返回值(与期望的相对)的定义是什么?也许它是“最后一个字符的位置”,而不是“修剪后字符串的长度”。 - Yunnosch
@Yunnosch,我的问题是n应该是11而不是10,这是由于s[n+1] = '\0'引起的;但我想说s[n+1]不太对,s[++n]给了我正确的答案,这意味着书中的代码并不完全正确,你明白我的意思吗? - Thomas
在我最近的评论之前,可以找到我对你最新评论的回答。 - Yunnosch
也许应该是“最后一个字符的位置”而不是“修剪后字符串的长度”,我完全理解,我会说这个例子最好说明了n指的是什么。 - Thomas
1
@Yunnosch,是的,现在我明白了,这个例子并没有定义返回值的含义,也许我想太多了,感谢你指出来。 - Thomas
显示剩余4条评论
2个回答

0

我会迭代长度并向前(或向后?)查看一个元素,以确定是否需要修剪它:

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;
}

我认为OP并不是在寻找一种修剪和返回长度的方法。他们已经知道了一种方法。这里并不是所有的问题都是“如何编写代码?” - Yunnosch
Op问“如何处理它?”这可能是一种方式。但也许你是对的。如果没有帮助,我会删除我的答案。 - Allan Wind
除非我说服你持有相同的观点,否则请不要采取我的意见。这里相关的观点是原帖作者的观点。如果他们想要不同类型的答案,他们可能会澄清。 - Yunnosch

0

在我看来,这本书没有清晰地定义返回值的含义。
但几乎是这样的:

查找第一个非...的字符

我认为返回 10 可以匹配这个定义,如果考虑引用文本作为定义的话。
所以对我来说,10 实际上似乎是正确的值,它是字符串末尾的“第一个”(或“最后一个”)非空格字符的位置。

回答“如何处理?”的问题:
你可能并不真正关心,如果你只使用修改后的字符串而不使用返回值。
如果你确实使用了返回值,则需要按照定义使用它(如果你认为引用文本是定义),即为了得到长度,你必须在使用/调用函数中增加一次(而不是在被调用的函数中)。
或者像你描述的那样修改函数。这个选项只存在于你“拥有”代码的情况下(在你自己的项目和教程中你拥有它...)。然而要记住,在更大型的项目的专业背景下,这种选择通常是不可用的。那里的 API 和行为是在其他地方定义的,不能在本地进行更改。

顺便说一下,我同意并感同身受你(对可能定义的隐含拒绝)和至少一个评论者的观点。"最后一个非空白字符的位置"这个返回值的定义并不是容易想到的...


1
我认为您的答案完全有效(包括规范至关重要而不是我的评论这一事实)。话虽如此,“最后一个非空白字符的索引”作为返回值有什么用处呢?如果没有用处,那么它就是一个(规范)缺陷而不是特性。 - Allan Wind
@AllanWind 我同意。但是,代码及其正确性是由所使用的定义确定的 - 即使我们都不喜欢它。;-) 如果您还没有在专业领域遇到过这个问题,那么您生活在一个比我更适合我的愿望的更好的世界中。除此之外,只有当任何人以不同于设计时的方式使用代码并被其作为定义行事而不是期望时,才会存在错误。 - Yunnosch
嗯,我明白你的意思了,那就是for循环的作用,for循环将会找到第一个不是...的元素,并且想象一下如果有人调用这个函数,我认为他们期望的结果应该是11而不是10,从调用者的角度来看。 - Thomas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接