- 简单语句
- 空语句
- 复合语句
- 条件语句
- if 语句
- switch 语句
- 迭代语句
- while语句
- 传统 for 语句
- 范围 for 语句(C++11)
- do while 语句
- 跳转语句
- break 语句
- continue 语句
- goto 语句
简单语句
大多数语句以分号结束。
ival + 5; //没有实际用处的表达式
cout<<ival; //有用的表达式
空语句
只包含一个单独的分号:
;
用处:
循环的全部工作在条件部分完成。
while (cin >> s && s != sought); //空语句
注意:使用空语句是应该加上注释,令读这段代码的人知道该语句是有意省略的。
可以在任何允许使用语句的地方使用空语句。
ival = v1 + v2;; //正确:第二个分号表示一条多余的空语句
多余的空语句并非总是无害的。
while (iter != svec.end()); //while 循环体是那条空语句
{++iter; //递增运算不属于循环的一部分
}
复合语句
花括号括起来的语句和声明的序列,也被称作 块 。
{//块
}
程序语法上需要一条语句,逻辑上需要多条语句时,使用复合语句。
代码演示:while循环计算 0 到 10 的和。
#include <iostream>using namespace std;int main()
{int val = 0;int sum = 0;while (val <= 10){sum += val;++val;}cout << "sum: " << sum << endl;return 0;
}
运行结果:
代码演示:for循环计算 0 到 10 的和。
#include <iostream>using namespace std;int main()
{int sum = 0;for (int val = 0; val <= 10; ++val){sum += val;}cout << "sum: " << sum << endl;return 0;
}
运行结果:
块不以分号作为结束。
{//块开始//块内部
}//块结束,无 ;
空块:内部没有任何语句的一对 { }
,等价于空语句。
{}
条件语句
if 语句
if 语句:
if (condition) //condition为真 执行statementstatement
if else 语句:
if (condition)//condition为真 执行statementstatement
else //condition为假 执行statement2statement
condition
必须能够转换为 bool
。
注意使用花括号:作为块执行的语句没有添加花括号。
代码演示:作为块执行的语句没有添加花括号。
#include <iostream>using namespace std;int main()
{bool b = false;if (b)cout << "yes" << endl;elsecout << "no" << endl;cout << "error" << endl;return 0;
}
运行结果:
本质上我们希望 b
为 false
的时候 打印 no
和 error
,但是上面程序无论 b
的值为 false
或 true
, error
都会打印。
上面的错误非常难发现,因为没有任何语法错误。
修改:在while、for、 if 和 else 之后必须写上花括号,避免代码混乱不清。
代码演示:作为块执行的语句没有添加花括号。
#include <iostream>using namespace std;int main()
{bool b = true;if (b){cout << "yes" << endl;}else{cout << "no" << endl;cout << "error" << endl;}return 0;
}
运行结果:
悬垂else问题: if
嵌套语句中,if
分支多余 else
。
C++解决: else
和最近尚未匹配的 if
匹配。
代码演示:C++解决悬垂else问题。
#include <iostream>using namespace std;int main()
{bool b1 = true;bool b2 = true;bool b3 = true;if (b1)if (b2)if (b3)cout << "true" << endl;else//和 if (b3) 匹配cout << "false" << endl;return 0;
}
如果想让 else
或者 if (b2)
或者 if (b2)
匹配,则可以在内层 if
语句两端加上 { }
使其成为一个 块
。
代码演示:else 和非最近未匹配的 if 匹配。
#include <iostream>using namespace std;int main()
{bool b1 = true;bool b2 = true;bool b3 = true;if (b1){if (b2){if (b3){cout << "true" << endl;}}else//和 if (b2) 匹配{cout << "false" << endl;}}return 0;
}
运行结果:
switch 语句
#include <iostream>using namespace std;int main()
{int switch_on = 3;switch (switch_on) //switch_on 表达式必须能够转换成整数,然后与所有 case匹配。{case 1: //标签后面必须跟一条语句或者另一个 case标签。break; case 2: //switch_on 和某一个 case 匹配成功,从该case下一行开始顺序执行所有case分支,直到swith结尾或遇到break。break;case 3: //下一个 case 标签之前应该有一条 break 语句。break; //break:中断当前控制流,转移控制权到 switch 语句外。case 4:break; //任何两个 case 标签不能相同。case 5: //case 选项数量固定break;default: //和所有 case 不匹配,执行 default 标签。default 标签后面必须跟上一条空语句或空块。break; //一般不要省略最后一个case分支的break语句。如果没有写请注释说明。}return 0;
}
代码演示:case标签执行完成后加break影响效果。
#include <iostream>using namespace std;int main()
{int switch_on = 3;switch (switch_on) {case 1:cout << "case 1" << endl;break;case 2:cout << "case 2" << endl;break;case 3: //匹配cout << "case 3" << endl; //执行break; //退出 switch语句case 4:cout << "case 4" << endl;break;case 5: cout << "case 5" << endl;break;default:cout << "default" << endl;break;}return 0;
}
运行结果:
代码演示:case标签执行完成后不加break影响效果。
#include <iostream>using namespace std;int main()
{int switch_on = 3;switch (switch_on) {case 1:cout << "case 1" << endl;case 2:cout << "case 2" << endl;case 3: //匹配cout << "case 3" << endl; //执行case 4:cout << "case 4" << endl; //执行case 5: cout << "case 5" << endl; //执行default:cout << "default" << endl; //执行}return 0;
}
运行结果:
switch 内部的定义变量:
switch 跳转到某个特定 case,该 case 标签之前的部分会被忽略。
疑问:如果被忽略的部分还有变量定义怎么办?
解答:初始化变量(包括显示和隐式)和使用变量跳跃 case 属于非法行为,未初始化的变量则不影响。
代码演示:初始化变量和使用变量跳跃 case属于非法行为。
#include <iostream>
#include <string>using namespace std;int main()
{int switch_on = 2;switch (switch_on){case 1: //程序跳过 case1 执行 case2,绕开初始化语句。cout << "case 1" << endl;int num1 = 10; //num 显式初始化为10string str; //str 隐式初始化为空字符串break;case 2: //编译器报错位置,带有初值的变量跳跃标签 case2cout << "case 2" << endl;cout << num1 << endl; //不允许跨过初始化语句直接跳转到另外的位置。cout << str << endl; //不允许跨过初始化语句直接跳转到另外的位置。break;default:cout << "default" << endl;break;}return 0;
}
编译器报错:
代码演示:未初始化变量和使用变量跳跃 case 赋值和使用则不影响。
#include <iostream>
#include <string>using namespace std;int main()
{int switch_on = 2;switch (switch_on) {case 1:cout << "case 1" << endl;int num1;break;case 2:cout << "case 2" << endl;num1 = 10;cout << num1 << endl;break;default:cout << "default" << endl;break;}return 0;
}
运行结果:
如果某个 case 定义并初始化变量,应该把变量定义在块内,确保后面所有 case 都在变量的作用域之外。
代码演示:把变量定义在块内,确保后面所有 case 都在变量的作用域之外。
#include <iostream>
#include <string>using namespace std;int main()
{int switch_on = 1;switch (switch_on){case 1: {cout << "case 1" << endl;int num1 = 10; string str; cout << num1 << endl;cout << str << endl;break;} //出块,num1 和 str无法被访问到。case 2:cout << "case 2" << endl;break;default:cout << "default" << endl;break;}return 0;
}
运行结果:
迭代语句
迭代及循环,重复执行操作直到满足某个条件才停下来。
- while 语句:执行循环体前先检查条件。
- for 语句:执行循环体前先检查条件。
- do while 语句:先检查条件再执行循环体。
while语句
语法:
while(condition)statement
执行过程:while语句
通常由条件本身或循环体改变condition
的值,否则可能循环无法终止。
定义在condition
和statement
的变量每次迭代都经历从创建到销毁。
#include <iostream>
#include <string>using namespace std;int main()
{while (int i = 1)//创建i{int j = 2;//创建j}//销毁 i , jreturn 0;
}
当不确定到底要迭代多少次时,使用 while 循环更合适。
代码演示:当不确定到底要迭代多少次时,使用 while 循环更合适。
#include <iostream>
#include <string>using namespace std;int main()
{int num = 10;while (cin >> num){if (20 == num){cout << num << endl;}}return 0;
}
运行结果:
传统 for 语句
for(init-statemen;condition;expression)statement
执行过程:传统 for 语句
init-statemen
必须是三种格式之一:
- 声明语句。
- 表达式语句。
- 空语句。
for 语句头中定义的对象只在for循环体中可见。
init-statemen
可以用多个对象,但是只能有一条声明语句,所有变量的基础类型相同。
代码演示:
#include <iostream>
#include <string>using namespace std;int main()
{for (int i = 0, j = 5,k = 10; i < 3; ++i){cout << "i: " << i << " ,j: " << j << " ,k: " << k << endl;}return 0;
}
运行结果:
省略 for 语句头的某些部分或全部,但是分号必须保留。
- 省略
init-statemen
:无需初始化时使用。 - 省略
condition
:等价于条件部分永远是true
。statement 中必须要有语句负责退出循环,否则就会死循环。 - 省略
expression
:循环体或者条件部分必须改变迭代变量的值。
范围 for 语句(C++11)
遍历所有容器或其他序列。
for (declaration:expression)statement
expression
必须是一个序列:初始值列表、数组、vector、string等拥有能返回迭代器成员 begin
和 end
成员。
declaration
定义一个变量,序列中每个元素都能转换成该变量的类型,最简单的方法是使用 auto
自动推导。
需要需要对序列元素执行写操作,循环变量必须声明成引用类型。
每次迭代重新定义循环控制变量,并将其初始化成序列中的下一个值,之后执行 statement。
statement 可以是一条单独的语句,也可以是语句块。
代码演示:把 vector 对象中的每个元素翻倍。
#include <iostream>
#include <string>
#include <vector>using namespace std;int main()
{vector<int> vi = { 0,1,2,3,4,5};for (auto& r : vi){cout << r << " ";}cout << endl;for (auto& r : vi){r *= 2;cout << r << " ";}return 0;
}
运行结果:
范围 for 语句的定义来源于与之等价的传统 for 语句。
代码演示:
#include <iostream>
#include <string>
#include <vector>using namespace std;int main()
{vector<int> vi1 = { 0,1,2,3,4,5};for (auto& r : vi1){cout << r << " ";}cout << endl;for (auto& r : vi1){r *= 2;cout << r << " ";}cout << endl;vector<int> vi2 = { 0,1,2,3,4,5 };for (auto beg = vi2.begin(), end = vi2.end(); beg != end; ++beg){auto& r = *beg;cout << r << " ";}cout << endl;for (auto beg = vi2.begin(), end = vi2.end(); beg != end; ++beg){auto& r = *beg;r *= 2;cout << r << " ";}return 0;
}
for (auto beg = vi2.begin(), end = vi2.end(); beg != end; ++beg)
等价于
for (auto& r : vi1)
运行结果:
强调:不能通过范围 for
语句增加 vector
对象(其他容器)的元素,因为在范围 for
语句中,预存了 end()
的值。一旦序列中添加或删除元素,end
函数的值可能变得无效。
do while 语句
do while语句先执行循环体后检查条件。
不管条件值如何,至少执行一次循环。
dostatement
while(condition);
while(condition)
后面用 ;
表示语句结束。
condition
不能为空。
condition
使用的变量必须定义在循环体之外。
不允许在条件中定义变量:
说明:对于 do while 语句来说先执行语句或块,后判断条件,如果允许在条件部分定义变量,则变量使用出现在了定义之前是不合理的。
执行过程:do while 语句
跳转语句
中断当前执行过程。
4种:break
,continue
,goto
,return
。
break 语句
终止离它 最近的 while,do while,for,switch 语句,并从这些语句之后第一条语句开始执行。
只能出现在 循环语句 或者 switch语句 内部(包括嵌套在此类循环里面的语句或块的内部)。
代码演示:for语句,while语句,do while 语句,switch语句中的 break
#include <iostream>
#include <string>using namespace std;int main()
{for (int num = 10; num <= 10; ++num){if ( num < 0){break; //#1离开 for 循环}while (num > 100){if (num % 3){break; //#2离开 while 循环}do {if (++num){break; //#3离开 do while 循环}switch (num--){case 10:cout << "num" << endl;break; //#4离开 switch 语句case 20:break; default:break; }//#4将控制权转移到这里} while (num*=2);//#3将控制权转移到这里}//#2将控制权转移到这里}//#1将控制权转移到这里return 0;
}
说明:上述代码仅用来说明 break 语句的转移权跳转,无实际功能意义。
continue 语句
终止最近的循环中的当前迭代,并立即开始执行下一次迭代。
只能出现在 for
、while
、do while
循环的内部或嵌套在此类循环里的语句或块的内部。
代码演示:
#include <iostream>
#include <string>using namespace std;int main()
{for (int num = 10; num <= 10; ++num){if ( num < 0){continue; //终止当前迭代,进入下一次 for 循环迭代}while (num > 100){if (num % 3){continue; //终止当前迭代,进入下一次 while 循环迭代}do {if (++num){continue; //终止当前迭代,进入下一次 do while 循环迭代}} while (num*=2);}}return 0;
}
只有 switch 语句嵌套在循环语句内部时,才能在switch 中使用 continue。
goto 语句
不要在程序中使用 goto 语句,因为它会使程序难以理解和修改。