C++中Switch语句中的Do While循环

Do-While Loop within Switch Statement in C++

本文关键字:While 循环 Do 语句 Switch C++      更新时间:2024-05-10
#include <iostream>
using namespace std;
int main(int argc, char *argv[]) {
int n = 12;
int q = (n + 3) / 4;

cout << q;
cout << ' ';
cout << n%4;
cout << ' ';

switch (n % 4) { 
case 0:  cout << n; cout << ' ';
do { n++; cout << n; cout << ' ';
case 3: n++; cout << n; cout << ' ';
case 2: n++;
case 1: n++; cout <<n;  cout << ' ';

} while (--q > 0);
}

cout << n; 
}

使用上面的代码,我得到了以下内容:

3 0 12 13 14 16 17 18 20 21 22 24 24

我不熟悉C++语言。

为什么它会在while循环的第二次和第三次迭代中失败?

switch case语句是否保存初始的n%4值,并在do while循环期间应用该值?

大小写标签只是标签。在switch语句中,代码是按顺序执行的,因为没有跳转语句,例如break、goto或return。

为了更清楚地表明,当表达式n % 4等于0时,可以按以下方式重写switch语句。

goto Label0;
{ 
Label0:  cout << n; cout << ' ';
do { n++; cout << n; cout << ' ';
n++; cout << n; cout << ' ';
n++;
n++; cout <<n;  cout << ' ';

} while (--q > 0);
}

所以,如果你将运行你的程序与修改

#include <iostream>
using namespace std;
int main() 
{
int n = 12;
int q = (n + 3) / 4;

cout << q;
cout << ' ';
cout << n%4;
cout << ' ';

goto Label0;
{ 
Label0:  cout << n; cout << ' ';
do { n++; cout << n; cout << ' ';
n++; cout << n; cout << ' ';
n++;
n++; cout <<n;  cout << ' ';
} while (--q > 0);
}

cout << n;  return 0;
}

你会得到同样的结果。

3 0 12 13 14 16 17 18 20 21 22 24 24

例如,如果您将在标签案例2之前插入一个break语句,如

switch (n % 4) { 
case 0:  cout << n; cout << ' ';
do { n++; cout << n; cout << ' ';
case 3: n++; cout << n; cout << ' ';
break;
case 2: n++;
case 1: n++; cout <<n;  cout << ' ';

} while (--q > 0);
}

那么这个break语句实际上就在do-while语句的复合语句中。因此,do while语句将被中断,控制将传递到switch语句的右大括号之前的点。因此switch语句也将被中断。

在这种情况下,程序输出将是

3 0 12 13 14 14

"开关盒";总是失败,除非您明确地将break从交换机中删除。

开关盒结构本质上是一组美化的goto,但比手动构建的结构更健壮。

(你的代码看起来像是传说中的"达夫设备"的一个稍微变异的版本,这是一个让几代C程序员感到困惑的循环展开结构。(

翻译成非结构化的";goto码";,您的交换机在逻辑上等同于

int x = n % 4;
if (x == 0)
goto zero;
if (x == 1)
goto one;
if (x == 2)
goto two;
if (x == 3)
goto three;
zero:
cout << n << ' ';
loop:
n++;
cout << n << ' ';
three:
n++;
cout << n << ' ';
two:
n++;
one:
n++;
cout << n << ' ';
if (--q > 0)
goto loop;

但是编译器可能能够通过使用实际的跳转表,从开关创建比该系列条件语句更高效的代码。


脚注:gcc实际上允许您使用标签作为值并跳转到它们,因此您可以自己创建这样的表;

void* table = { &&zero, &&one, &&two, &&three };
goto *table[n % 4];
zero:
cout << n << ' ';
loop:
n++;
cout << n << ' ';
three:
n++;
cout << n << ' ';
two:
n++;
one:
n++;
cout << n << ' ';
if (--q > 0)
goto loop;

(并不是说你应该,但你<em]可以>。一个好的编译器会把你的开关编译成类似的东西,如果它是有益的,它比一个人更了解这一点。(