修剪字符串,为什么while循环后会出现分号?

时间:2017-08-03 12:50:24

标签: c string c-strings trim

所以我正在阅读我的C编程课程中的一些代码,并且遇到了这个问题:

将字符串" make trim "修剪为"make trim"。 这是代码:

#include <stdio.h>
#include <string.h>
#define MAX 100

void trim(char *s) {
    char *d = s;
    while (isspace(*s++))
        ;
    s--;
    while (*d++ = *s++)
        ;
    d--;
    while (isspace(*--d))
        *d = 0;
}
int main() {
    char s[MAX];
    gets(s);
    printf("[%s] -> ", s);
    trim(s);
    printf("[%s]", s);
    return 0;
}

所以,我想问的是,什么是

    while (isspace(*s++))
        ;
    s--;
    while (*d++ = *s++)
        ;
    d--;
    while (isspace(*--d))
        *d = 0;

增量字符串(*s++),while()循环后的;以及它们如何工作?

提前致谢

3 个答案:

答案 0 :(得分:4)

空体仅仅是因为while的条件具有副作用,所以整个循环被封装在条件中并且没有任何东西可以放入体内。

所以:

while (isspace(*s++))
    ;

与:

相同
while (isspace(*s)) { s++; }

他们将分号放在额外的行上,以使循环为空更清楚(否则你可能会认为下一个真正的语句是循环的一部分)。其他人也可以在那里发表评论,甚至重写它以避免身体变空。

带有一些描述性评论的代码:

此循环依次拾取每个字符,递增s以指向下一个字符并继续这样做,直到我们拾取的字符不是空格字符。请注意,因为它在测试之前递增,所以它会增加s一次太多,所以这就是为什么在循环结束后会有减量的原因。         while(isspace(* s))             ;

    s--;

这本来是等价的,并不需要单独的减量:

while (isspace(*s)) { s++; }

此循环从s复制每个字符,从第一个非空白字符开始到最初指向字符串开头的d。如果没有前导空格,则将字符直接复制到自身的顶部。在复制空字符(即字符串的结尾)之后,循环结束。和以前一样,有一个增量太多,所以我们必须递减d来终止空字符:

    while (*d++ = *s++)
        ;
    d--;

此循环递减d,然后拾取它现在指向的任何字符。如果它是一个空格字符,那么它将用空字符替换它。请注意,没有检查命中字符串的开头,所以如果初始字符串为空(即单个空字符),只要它们是空格,它就会很好地通过内存破坏字符串外的字节:

    while (isspace(*--d))
        *d = 0;

答案 1 :(得分:1)

你可以改写:

while (condition);

如下:

while (condition) { /* empty block */ }

如果condition包含要执行的语句,只要条件满足,这些语句就会被执行和评估,这就是你的例子。

1。 在您的情况下,第一次循环

while (isspace(*s++));

循环,直到它发现第一个字符没有空格(在这种情况下是 make m )。由于有一个后缀增量,它将指向 make a

"   make trim   \0"
 ^   ^
d|  s|

2。 之后s递减(s--;)指向开头( m make )。

"   make trim   \0"
 ^  ^
d| s|

3。 第二个while循环将以 make 开头的字符串写入字符缓冲区的开头,因为d指向开头,因为它设置为函数的开头(char *d = s;)。这样做直到达到空终止符'\0'

while (*d++ = *s++)

可以改写为:

while ((*d++ = *s++) != '\0')

并将导致(请注意,空终止符'\0'也被写入):

"make trim   \0  \0"
             ^   ^
            d|  s|

4。 现在d将递减(d--;)指向空终止符'\0'之前的空格。

"make trim   \0  \0"
            ^    ^
           d|   s|

5。 最后一次循环将搜索第一个没有空格的字符(使用d),但顺序相反:

while (isspace(*--d))
   *d = 0;

它将写入多个空终止符'\0',直到找到一个没有空格的字符。

"make trim\0\0\0\0  \0"

结果字符串将是:

"make trim"

在此处编写多个空终止符'\0'是必要的,但是在 m trim 后,将需要一个空终止符'\0' EM>

答案 2 :(得分:0)

while (isspace(*s++))
        ;

等于

while (isspace(*s++));

不要让;在新的一行让您感到困惑。总而言之,这只是一种强调此while循环没有正文的方法。并且一个没有正文的while循环正在执行,直到它的isspace(*s++)条件为假。同样isspace(*s++)它是唯一一个应该为这个循环完成的计算,所以这就是为什么不需要为这个循环设置一个主体。

当您读取这样的代码时,很容易错过这个;,然后您可以做出错误的假设,即循环正下方的表达式是一个循环体,但只是没有被包围{}

while (isspace(*s++));
    s--;

while (isspace(*s++))
    s--;

看到区别?在第二个示例中,s--while循环的正文。为了吸引注意力,程序员可以写:

while (isspace(*s++))
    ;
    s--;

澄清并强调他的真实意图。