if关键字用于执行语句或语句块中,有且仅有一个条件被满足。它的语法是:
if (condition) statement
这里,condition是正在计算的表达式。如果condition为真,statement则执行。
如果为假,statement则不执行(它被简单地忽略),
并且程序在整个选择语句之后继续。
例如,以下代码片段仅在x变量中存储的值确实为 100(x 值是 100)时才打印 message :
if (x == 100)
cout << "x is 100";
|
如果x不是 100,则忽略此语句,并且不打印任何内容。
如果要在满足条件时包含多个要执行的语句,则应将这些语句括在大括号 ( {}) 中,形成一个语句块:
if (x == 100)
{
cout << "x is ";
cout << x;
}
|
像往常一样,代码中的缩进和换行没有任何作用,所以上面的代码等价于:
if (x == 100){ cout << "x is "; *cout << x; }
|
如果条件不满足,if 语句 引入 else 语句执行替代的操作. 语法:
if (condition) statement1 else statement2
当 condition 为真(true)时,执行 statement1,否则执行 statement2.
例如:
if (x == 100)
cout << "x is 100";
else
cout << "x is not 100";
|
如果 x 是100,那么将打印 x is 100,否则,打印 x is not 100.
多个if + else 结构可以检验一个范围值.例如:
if (x > 0)
cout << "x is positive";
else if (x < 0)
cout << "x is negative";
else
cout << "x is 0";
|
这里通过两个 if-else 结构来检验 x 是正数、负数还是零。
同样,通过将语句分组到大括号:{}中的语句块中,也可以在每个情况下执行多个语句。
如果循环将语句重复执行一定次数,或在满足条件时一直重复执行。
可以通过关键字while,do和for操作.
while 循环
while 循环是简单循环的一种.语法:
while (expression) statement
当 expression 为真时, while 循环重复执行 statement.
当 expression 不为真时,则循环结束.程序执行循环后面的语句.
例如,让我们看一下使用 while 循环的倒计时:
// custom countdown using while
#include <iostream>
using namespace std;
int main ()
{
int n = 10;
while (n>0) {
cout << n << ", ";
--n;
}
cout << "liftoff!\n";
}
|
10, 9, 8, 7, 6, 5, 4, 3, 2, 1, liftoff! |
第一条语句 main 将 n 的值设置为 10。这是倒计时中的第一个数字。
然后 while 循环开始:如果该值满足条件 n > 0(即n大于零),则执行该条件之后的块,
并且只要条件 ( n>0) 保持为真就重复执行。
前面程序的整个过程可以根据下面的伪代码(从 main 开始)来解释:
1. n 被赋值
2. 该while语句被执行(n>0)。此时有两种可能:
条件为真:语句执行(第3步)
条件为假:忽略下面 3 语句并在它之后继续(到第 5 步)
3. 执行语句:( 打印值减1)
cout << n << ", ";
--n;
(打印n的值并将n减小1)
4. 结束第3步。自动返回到步骤 2。
5. 在语句块之后继续程序:
打印liftoff!并结束程序。
while 循环需要考虑的一个问题是循环应该在某个时刻结束,因此,
该语句应该以某种方式改变条件中检查的值,以迫使它在某个时刻变为假。
否则,循环将永远循环下去。在这种情况下,循环包括--n, 将条件 ( n) 中用来判断的变量的值减1,
这将在一定数量的循环迭代后最终使条件 ( n>0 ) 为假。
更具体地说,经过 10 次迭代后,n变为 0,使条件不再为真,并结束 while 循环。
请注意,此循环的复杂性对于计算机来说是微不足道的,因此整个倒计时会立即执行,
计数元素之间没有任何实际延迟(如果有兴趣,请参阅sleep_for带有延迟的倒计时示例)。
do-while 循环
一个非常相似的循环是 do-while 循环,其语法是:
do statement while (condition);
do-while在执行之后而不是之前进行判断,它的行为类似于 while 循环,
do-while保证至少执行一次,即使判断条件永远为假。
例如,以下示例程序会回显用户输入的任何文本,直到用户输入再见:
// echo machine
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string str;
do {
cout << "Enter text: ";
getline (cin,str);
cout << "You entered: " << str << '\n';
} while (str != "goodbye");
}
|
Enter text: hello
You entered: hello
Enter text: who's there?
You entered: who's there?
Enter text: goodbye
You entered: goodbye
|
当statement需要至少执行一次时,do-while 循环通常比 while 循环更合适,
例如在循环语句体内部确定循环结束的条件时。
在前面的示例中,语句块内的用户输入将决定循环是否结束。
因此,即使用户想尽快结束循环,循环中的语句块也至少执行一次用来提示输入,
循环条件实际上只有在执行后才能确定。
for 循环
for循环为多次迭代而设计.语法:
for (initialization; condition; increase) statement;
和 while 循环类似,当 condition 为真时,for 循环体 statement 重复执行.
但是,for循环提供了初始化和增加表达式的位置,分别在第一次循环开始之前和每次迭代之后执行。
因此,使用计数器变量作为循环条件特别有用。
它的工作方式如下:
1. 执行初始化(initialization)。通常,这会声明一个计数器变量,并将其设置为某个初始值。
这只在循环开始时执行一次.
2. 检查条件(condition)。如果为真,循环继续;否则,循环结束,语句(statement)被跳过,直接进入步骤5.
3. 执行语句 (statement)。通常,它可以是单个语句,也可以是括在花括号{}中的语句块.
4. 执行递增操作 (increase),循环返回到第2步。
5. 循环结束:继续执行程序的下一条语句。
下面是使用for循环的倒计时示例:
// countdown using a for loop
#include <iostream>
using namespace std;
int main ()
{
for (int n=10; n>0; n--) {
cout << n << ", ";
}
cout << "liftoff!\n";
}
|
10, 9, 8, 7, 6, 5, 4, 3, 2, 1, liftoff!
|
for循环中的三个控制字段(initialization; condition; increase)是可选的.
它们可以为空,但在任何情况下,它们之间的分号都是必需的。
例如, for (;n<10;) 是一个没有 initialization 和 increase(相当于while循环)的循环;
for (;n<10;++n)是一个递增循环,但是没有初始化(可能是因为变量在循环之前已经初始化了).
没有判断条件(condition)的循环等同于条件为true的循环(即无限循环).
因为每个控制字段都是在循环生命周期的特定时间内执行的,
所以在initialization, condition, 和 increase(原文是statement,怀疑有误,欢迎指正.)
中执行多个表达式可能是有用的。
可是,这些不是语句,而是简单的表达式,因此不能被语句块替换。
但是,作为表达式,它们可以使用逗号操作符(,):该操作符是表达式分隔符,
可以在通常只需要一个表达式的情况下分隔多个表达式。
例如,使用它,For循环可以处理两个计数器变量, initializing 和 increasing:
for ( n=0, i=100 ; n!=i ; ++n, --i )
{
// whatever here...
}
|
如果n和i都没有被修改,这个循环将执行50次:
n从0开始,i从100开始,条件是n !=i(即n不等于i)。因为n每次迭代增加1,
而i每次迭代减少1,在第50次迭代后,当n和i都等于50时,循环的条件将变为假.
基于范围(range)的 for 循环
for 循环还有另一种语法,专门用于特定范围:
for ( declaration : range ) statement;
这种for循环遍历范围(range)内的所有元素,声明语句(declaration)声明某个变量能够获取该范围内元素的值.
range是元素的集合,包括数组,容器和任意被 (begin 和 end) 函数支持的类型.
大多数类型在本教程中还没有介绍,但是我们至少已经熟悉了一种:字符串,它是一种字符序列.
使用字符串的基于特定范围的for循环示例:
// range-based for loop
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string str {"Hello!"};
for (char c : str)
{
cout << "[" << c << "]";
}
cout << '\n';
}
|
[H][e][l][l][o][!]
|
请注意,在for循环中冒号(:)之前的内容是如何声明一个char变量的(字符串中的元素是char类型的).
然后用变量c,在语句块中表示范围(str)内每个元素的值。
基于范围的循环通常也使用自动类型推导(auto)来判断元素的类型.
通常,上面基于范围的循环也可以写成:
for (auto c : str)
cout << "[" << c << "]";
|
这里,c的类型被自动推导为str中元素的类型.
跳转语句允许通过跳转到特定位置来改变程序执行顺序.
break 语句
Break会离开一个循环,即使终止的条件没有满足.
它可以用来结束一个无限循环,或者迫使它在正常结束之前结束.
例如,让我们在正常结束前停止倒计时:
// break loop example
#include <iostream>
using namespace std;
int main ()
{
for (int n=10; n>0; n--)
{
cout << n << ", ";
if (n==3)
{
cout << "countdown aborted!";
break;
}
}
}
|
10, 9, 8, 7, 6, 5, 4, 3, countdown aborted!
|
continue 语句
continue语句使程序在本轮循环中跳过循环的剩余部分,
就好像已经到达语句块的末尾,使它开始下一轮循环.
例如,让我们跳过倒计时中的第5个数字:
// continue loop example
#include <iostream>
using namespace std;
int main ()
{
for (int n=10; n>0; n--) {
if (n==5) continue;
cout << n << ", ";
}
cout << "liftoff!\n";
}
|
10, 9, 8, 7, 6, 4, 3, 2, 1, liftoff!
|
goto 语句
goto允许无条件跳转到程序中的另一个点。这种无条件跳转忽略嵌套级别,
并且不会自动
栈展开(stack unwinding)。
因此,它是一个需要谨慎使用的特性,
最好是在同一个语句块中使用,特别是在存在局部变量的情况下
目标跳转点由标签标识,然后作为goto语句的参数使用。
标签由一个有效的标识符后跟一个冒号(:)组成。
goto通常被认为是一个低级的特性,在c++通常使用的现代高级编程范例中没有特定的用例。
但是,就像这个例子,这是我们使用goto的倒计时循环的一个版本:
// goto loop example
#include <iostream>
using namespace std;
int main ()
{
int n=10;
mylabel:
cout << n << ", ";
n--;
if (n>0) goto mylabel;
cout << "liftoff!\n";
}
|
10, 9, 8, 7, 6, 5, 4, 3, 2, 1, liftoff!
|
注:每次函数调用的时候,都会执行保护现场,寄存器、参数压栈、为被调用的函数创建栈这几个操作,
它们都使栈增长。
每次函数返回则是恢复现场,使栈减小。
我们把函数返回过程中恢复现场的过程称为
栈展开 (stack unwinding).
switch 语句的语法有点奇怪。它是在许多可能的常量表达式中选择一个值。
它类似于if-else语句,但仅限于常量表达式。它最典型的语法是:
switch (expression)
{
case constant1:
group-of-statements-1;
break;
case constant2:
group-of-statements-2;
break;
.
.
.
default:
default-group-of-statements
}
|
它的工作方式如下:switch先判断expression是否等价于constant1;
如果是,则执行group-of-statements-1,直到break语句为止。
当它执行到这个break语句时,程序跳转到整个switch语句的末尾(右大括号)。
如果表达式不等于constant1,则判断expression是否等价于constant2;如果相等,
则执行group-of-statements-2,直到break为止,然后跳转到 switch 的末尾。
最后,如果表达式的值不匹配任何选项的常量(可能有不定数量的常量),
程序将执行default:标签之后的语句(如果存在)(因为它是可选的)。
以下两个代码片段具有相同的行为,演示了 switch 语句的 if-else 等效程序:
switch |
if-else |
switch (x) {
case 1:
cout << "x is 1";
break;
case 2:
cout << "x is 2";
break;
default:
cout << "value of x unknown";
}
|
if (x == 1) {
cout << "x is 1";
}
else if (x == 2) {
cout << "x is 2";
}
else {
cout << "value of x unknown";
}
|
switch语句具有从早期 C 编译器继承而来的有些奇特的语法,它使用标签而不是语句块。
在典型的使用中(如上所示),这意味着在每组语句之后都需要break语句。
如果没有break语句,则 case 后面的所有语句(包括任何其他标签下的语句)也将执行,
直到到达 switch 语句块的末尾或跳转语句(例如break).
如果上例中 case 1 的第一组后面缺少 break 语句,则程序在打印x is 1后不会自动跳转到 switch 块的末尾,
而是继续执行 case 2 的语句(因此也打印x is 2)。
然后它会继续这样做,直到遇到break语句或switch块的结尾。
这使得不必将每个 case 的语句括在大括号中{},并且对于针对不同的可能执行同一组语句也很有用。
例如:
switch (x) {
case 1:
case 2:
case 3:
cout << "x is 1, 2 or 3";
break;
default:
cout << "x is not 1, 2 nor 3";
}
|
请注意,switch仅限于将其判断表达式与常量表达式的标签进行比较。
不能将变量用作标签或范围,因为它们不是有效的 C++ 常量表达式。
要检查非常量的范围或值,最好使用if和else if语句的组合。