在嵌套的 while 循环中重新测试 while 循环条件
Retesting while loop condition inside a nested while loop
在这个程序中我不太明白为什么我们在嵌套的while循环中测试第一个while循环的条件1
程序是说一个字符串有多少个单词,单词之间用空格隔开
代码如下:
int count_words(char *ch){
int c = 0;
while(*ch!='[=10=]'){
if(*ch==' '){
ch++;
continue;
}
c++;
while(*ch && *ch !=' '){
ch++;
}
}
return c;
}
我不明白的是,为什么第一个 while 循环中的条件 1:(*ch!='\0') 在第二个 while 循环中再次被测试。
我是否总是需要在嵌套的 while 循环中测试返回条件?还是我哪里没掌握好?
谢谢
第一个测试是跳过单词之间的所有 spaces。它在到达第一个非 space,即单词的 开头 时停止。
内部 while 循环用于跳过字符,直到我们到达下一个 space,因此它找到该词的 end。
注意这两个条件是相反的。第一个是*ch == ' '
,第二个是*ch != ' '
。
*ch != '[=12=]'
和 *ch &&
用于在到达字符串末尾时停止(C 字符串以零字节结尾)。这在遍历字符串的任何循环中都是必需的,因此它不会超出结尾。
What I do not understand is why condition 1 which is : (*ch!='[=31=]') in the first while loop is tested again in the second while loop.
我将在这里重点介绍一些重要的细节:
while(*ch!='[=10=]') {
if(*ch==' ') {
ch++; // 1.
continue;
}
c++;
while(*ch && *ch !=' ') {
ch++; // 2.
}
}
在1
和2
中,char*
ch
加1,这使得ch
指向一个新地址——内容未知.
当再次到达 while
循环的起点时,它会测试 ch
指向的内容是否包含 null-terminator,它表示字符串的结尾。如果是,则循环结束 - 因为随后将对字符串进行全面检查。
所以,while(*ch!='[=19=]')
并不是一遍又一遍地测试同一件事。 ch
在每次循环后指向一个新的 char
。
你在内部循环中有相同的测试:
while(*ch && *ch !=' '){ // <-here
ch++;
}
在这里,*ch
也在做同样的测试,*ch != '[=23=]'
,但没有那么多话。
[=24=]
是空终止符的正确字符文字。
- 空终止符具有实际值
0
。
- 在布尔上下文中,
0
的计算结果为 false
,其他所有计算结果为 true
。
- 因此,
*ch
在布尔上下文中等于 *ch != '[=23=]'
这个问题说明了为什么在我看来,将事物分解成具有有意义名称的函数如此重要。
假设我们想要将字符串推进到前导白色space 字符之后。我们可以创建一个函数,它接受一个字符串 (char *
),创建一个指向它开头的指针,递增该指针直到它遇到一个不是 space、制表符或换行符的字符, 然后 returns 那个指针。
char * first_nonspace(char * s) {
char * iter = s;
for (; *iter && (*iter == ' ' || *iter == '\t' || *iter == '\n');
iter++);
return iter;
}
以同样的方式可以使函数跳到下一个白色space字符。
char * first_space(char * s) {
char * iter = s;
for (; *iter && !(*iter == ' ' || *iter == '\t' || *iter == '\n');
iter++);
return iter;
}
现在统计字数就简单多了。我们的 for 循环甚至不需要主体。它以 iter
指向字符串的第一个字符开始,count
设置为零。当我们没有 运行 进入空字符,并且第一个非 space 字符不为空时,它会继续。
每次我们通过获取第一个非 space 字符进行更新,然后从该指针前进到第一个 space。这有效地迭代了一个“词”。同时,我们通过将计数递增 1 来更新它。
int main() {
char * test = " hello world foo bar ";
char * iter;
int count;
for (iter = test, count = 0;
*iter && *first_nonspace(iter);
iter = first_space(first_nonspace(iter)), count++);
printf("Found %d words.\n", count);
}
将大问题分解成小问题非常有助于理解正在发生的事情。我所描述的是在您的程序中发生的相同逻辑(尽管我添加了处理制表符和换行符)但是在具有更有用名称的可管理块中。
在这个程序中我不太明白为什么我们在嵌套的while循环中测试第一个while循环的条件1
程序是说一个字符串有多少个单词,单词之间用空格隔开
代码如下:
int count_words(char *ch){
int c = 0;
while(*ch!='[=10=]'){
if(*ch==' '){
ch++;
continue;
}
c++;
while(*ch && *ch !=' '){
ch++;
}
}
return c;
}
我不明白的是,为什么第一个 while 循环中的条件 1:(*ch!='\0') 在第二个 while 循环中再次被测试。
我是否总是需要在嵌套的 while 循环中测试返回条件?还是我哪里没掌握好?
谢谢
第一个测试是跳过单词之间的所有 spaces。它在到达第一个非 space,即单词的 开头 时停止。
内部 while 循环用于跳过字符,直到我们到达下一个 space,因此它找到该词的 end。
注意这两个条件是相反的。第一个是*ch == ' '
,第二个是*ch != ' '
。
*ch != '[=12=]'
和 *ch &&
用于在到达字符串末尾时停止(C 字符串以零字节结尾)。这在遍历字符串的任何循环中都是必需的,因此它不会超出结尾。
What I do not understand is why condition 1 which is : (*ch!='[=31=]') in the first while loop is tested again in the second while loop.
我将在这里重点介绍一些重要的细节:
while(*ch!='[=10=]') {
if(*ch==' ') {
ch++; // 1.
continue;
}
c++;
while(*ch && *ch !=' ') {
ch++; // 2.
}
}
在1
和2
中,char*
ch
加1,这使得ch
指向一个新地址——内容未知.
当再次到达 while
循环的起点时,它会测试 ch
指向的内容是否包含 null-terminator,它表示字符串的结尾。如果是,则循环结束 - 因为随后将对字符串进行全面检查。
所以,while(*ch!='[=19=]')
并不是一遍又一遍地测试同一件事。 ch
在每次循环后指向一个新的 char
。
你在内部循环中有相同的测试:
while(*ch && *ch !=' '){ // <-here
ch++;
}
在这里,*ch
也在做同样的测试,*ch != '[=23=]'
,但没有那么多话。
[=24=]
是空终止符的正确字符文字。- 空终止符具有实际值
0
。 - 在布尔上下文中,
0
的计算结果为false
,其他所有计算结果为true
。 - 因此,
*ch
在布尔上下文中等于*ch != '[=23=]'
这个问题说明了为什么在我看来,将事物分解成具有有意义名称的函数如此重要。
假设我们想要将字符串推进到前导白色space 字符之后。我们可以创建一个函数,它接受一个字符串 (char *
),创建一个指向它开头的指针,递增该指针直到它遇到一个不是 space、制表符或换行符的字符, 然后 returns 那个指针。
char * first_nonspace(char * s) {
char * iter = s;
for (; *iter && (*iter == ' ' || *iter == '\t' || *iter == '\n');
iter++);
return iter;
}
以同样的方式可以使函数跳到下一个白色space字符。
char * first_space(char * s) {
char * iter = s;
for (; *iter && !(*iter == ' ' || *iter == '\t' || *iter == '\n');
iter++);
return iter;
}
现在统计字数就简单多了。我们的 for 循环甚至不需要主体。它以 iter
指向字符串的第一个字符开始,count
设置为零。当我们没有 运行 进入空字符,并且第一个非 space 字符不为空时,它会继续。
每次我们通过获取第一个非 space 字符进行更新,然后从该指针前进到第一个 space。这有效地迭代了一个“词”。同时,我们通过将计数递增 1 来更新它。
int main() {
char * test = " hello world foo bar ";
char * iter;
int count;
for (iter = test, count = 0;
*iter && *first_nonspace(iter);
iter = first_space(first_nonspace(iter)), count++);
printf("Found %d words.\n", count);
}
将大问题分解成小问题非常有助于理解正在发生的事情。我所描述的是在您的程序中发生的相同逻辑(尽管我添加了处理制表符和换行符)但是在具有更有用名称的可管理块中。