修剪一个字符串,while循环之后为什么会有分号?
所以我在读从我的C语言编程过程中的一些代码,和对面这个问题问出来:修剪一个字符串,while循环之后为什么会有分号?
修剪字符串:" 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()循环后;
做的,又是如何工作?
在此先感谢
空体很简单,因为while
的条件有副作用,所以整个循环被封装在条件并没有什么放于身体。
所以:
while (isspace(*s++))
;
是一样的:
while (isspace(*s)) { s++; }
他们把分号上多余的线,更清楚地表明环路是空的(否则你可能会认为下一个真正的语句是循环的一部分)。其他人也可能在那里发表评论,甚至重写它以避免身体空虚。
代码的一些描述性注释:
这个循环拿起每个字符依次递增s
指向未来,并继续这样做,直到我们拿起字符不是一个空白字符。请注意,因为它在测试之前递增,所以会增加s
一次太多,所以这就是循环结束后递减的原因。 (isspace(* s)) ;
s--;
这将是等效的,不需要单独的递减:
while (isspace(*s)) { s++; }
这个循环副本从s
每个字符所以从第一个非空白字符d
最初指着字符串的开始。如果没有前导空格,它会直接在其本身上复制字符。循环在复制空字符(即字符串的结尾)后结束。由于之前有一个增量太多,所以我们必须递减d
以空字符终点确定:
while (*d++ = *s++)
;
d--;
这个循环递减d
然后拿起任何字符它指向的。如果它是空白字符,则用空字符替换它。请注意,没有检查字符串的开头,所以如果初始字符串是空的(即,一个空字符),它会高兴地向后弦外存储器损坏字节,只要它们是空白的工作:
while (isspace(*--d))
*d = 0;
非常感谢。如果你不介意回答他们,我还想问另外两个问题。 首先,如果你可以解释它背后的逻辑,那么循环** while(isspace(* s ++)); **与** s - **一起工作,另外a.k.a如何修剪? 第二,如何做** while(* d ++ = * s ++); d - ; **和** while(isspace(* - d))* d = 0; **工作,如果您可以为我解构它们,我会很感激! –
或者有时一个单独的'continue;'语句放在循环体中,以清楚地表明循环体什么都不做。 –
是,或者至少是一个*空格*,例如'while(foo){}'(正如Andre在他的回答中所指出的那样)。至少原始问题在单独的一行中有分号,它太容易错过写作'while(foo);' –
可以重写:
while (condition);
如下:
while (condition) { /* empty block */ }
如果condition
包含要执行的语句,只要条件满足,就会执行和评估这些语句,在您的示例中就是这种情况。
1. 你的情况第一while循环:
while (isspace(*s++));
循环,直到它创立的第一个字符是没有空间(这是米的使在这案件)。因为有一个后缀增量将指向的使:
" make trim \0"
^ ^
d| s|
2. 之后s
递减(s--;
)在启动(米的指着化妆)。
" make trim \0"
^^
d| s|
3. 的第二while循环写有开始做的字符缓冲区的开始,因为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。 的最后while循环将搜索的第一个字符是没有空间(与d
),但以相反的顺序:
while (isspace(*--d))
*d = 0;
它将写入多个空终止'\0'
,直到它找到一个字符是没有空间。
"make trim\0\0\0\0 \0"
所以得到的字符串将是:
"make trim"
这是没有必要写多个空终止'\0'
这里,而是一个空终止'\0'
会后米被足够多的修剪 。
非常感谢,答案是彻底的和超清晰的! :) –
嗨@JustinHerchel如果这个或任何答案已解决您的问题,请点击复选标记,考虑[接受它](https://meta.stackexchange.com/q/5234/179419)。这向更广泛的社区表明,您已经找到了解决方案,并为答复者和您自己提供了一些声誉。没有义务这样做。 –
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--;
澄清和强调他的真实意图。
只有';'在其他空行上是空的语句。除语法和语义上添加语句外,它什么都不做。 –
如果您想知道它是如何工作的,请了解*指针*,*指针算术*以及如何使用*调试器*在监控变量及其值时逐行浏览代码。 –
感谢您的建议。我目前正在为期末考试进行学习,这是2周后,如果您可以提供一些** C-String **问题汇编或一些很好的字符串(算法)书籍和评论一些链接? –