所以我正在阅读我的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()循环后的;
以及它们如何工作?
提前致谢
答案 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--;
澄清并强调他的真实意图。