目录
一、语句分类
C++的语句大致可分为简单语句、条件语句、迭代语句、跳转语句、try语句块和异常处理。
二、主要内容
1.简单语句
1.1 空语句
一条简单语句一般以分号结尾,而只有单独的一个分号便是空语句。空语句单独存在没有任何意义,但与迭代语句结合可以表示单纯的循环,如:
; //单独空语句,没有任何意义
int a = 10;
while (a--) ; //空语句,单纯地将a自减至0
在编写时应该注意,尽量避免无意义的空语句,就算多出来的空语句不会报错。
int a = 10;;;;;;;;;;;;; //多了很多分号(很多空语句)
while (a--) ; //多出来的空语句导致变成了空循环,但原意是打印a个"hello world\n"
cout << "hello world" << endl;
1.2 复合语句(块)
复合语句简而言之就是用花括号括起来的语句块,一般称作语句块,语句块中的语句一般是按顺序执行的,如:
int a = 10;
while (a--) {
cout << "hello"; //语句块中的第一条语句
cout << "world"; //语句块中的第二条语句
} //循环语句块
int b = 10;
while (b--) { } //空块
2.条件语句
条件语句主要分为两种,一种是if语句,另一种是switch语句。
2.1 if语句
if语句的关键字有三种——if、else if、else,用自然语言来说分别就是“如果”、“或者如果”、“否则”。其作用是通过条件值判断执行不同分支的代码,如:
int a = 50;
if (a <= 20) {
cout << "a不比20大\n";
} else if (a > 20 && a <= 40) {
cout << "a大于20,但小于等于40\n";
} else if (a > 40 && a <= 60) {
cout << "a大于40,但小于60\n";
} else if (a > 60 && a <= 80) {
cout << "a大于60,但小于80\n";
} else {
cout << "a比80大\n";
}
if语句按顺序依次判断,因为a等于50,显然上述代码会输出“a大于40,但小于60”。
if语句的语句块里可以写很多其他类型的语句,if语句也能嵌套使用,如:
int a = 50;
if (a > 20) {
if (a > 30) {
cout << "a比30大\n";
//其他语句,例如迭代语句while
while (a--) {
cout << a << endl;
}
} else {
cout << "a的值在21~30之间\n";
}
} else {
cout << "a不比20大\n";
}
上述例子并不是多么优美的写法,只为展示if语句的嵌套,下面是其流程图。
2.2 switch语句
switch适合在条件值为基本类型并且固定值选项较多的时候使用,如:
int a = 5;
if (0 == a) {
cout << "a为0";
} else if (1 == a) {
cout << "a为1";
} else if (2 == a) {
cout << "a为2";
} else if (3 == a) {
cout << "a为3";
} else if (4 == a) {
cout << "a为4";
} else if (5 == a) {
cout << "a为5";
} else if (6 == a) {
cout << "a为6";
} else if (7 == a) {
cout << "a为7";
} else if (8 == a) {
cout << "a为8";
} else {
cout << "a不是上面这些数";
}
//...
这种把每种情况都列举出来的if语句写法显得非常笨拙,于是可以使用switch:
int a = 5;
switch (a) {
case 0:
cout << "a为0";
break;
case 1:
cout << "a为1";
break;
case 2:
cout << "a为2";
break;
case 3:
cout << "a为3";
break;
case 4:
cout << "a为4";
break;
case 5:
cout << "a为5";
break;
case 6:
cout << "a为6";
break;
case 7:
cout << "a为7";
break;
case 8:
cout << "a为8";
break;
default:
cout << "a不是上面这些数";
break;
}
其中的case x就相当于if (a == x),default相当于else。其中每个case分支都要加上break,以代表执行完这个case分支就退出switch语句,如果不加break,程序会向后执行到遇到break为止,如:
int a = 5;
switch (a) {
case 0:
cout << "a为0";
case 1:
cout << "a为1";
case 2:
cout << "a为2";
case 3:
cout << "a为3";
case 4:
cout << "a为4";
case 5:
cout << "a为5";
case 6:
cout << "a为6";
case 7:
cout << "a为7";
case 8:
cout << "a为8";
default:
cout << "a不是上面这些数";
}
a等于5,则会跳转到case 5,一直向下执行,因为没有遇到break,会输出:a为5a为6a为7a为8a不是上面这些数。可以利用连在一起的标签:
int a = 5;
switch (a) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
cout << "a是0~5"
break;
default:
cout << "a不是上面这些数";
break;
}
tips: 条件变量只能是一些基本数据类型,最好是整形或字符,不可用浮点数。defualt不加也可以,就像else不写一样,默认会跳出语句,但为了代码品质,最好加上。
3.迭代语句
迭代语句又叫循环,一般用于重复执行某些代码。
3.1 while循环
while(condition) { },如果condition为true则执行while后面的语句块,如:
int a = 10;
while (a != 0) {
cout << a << ' ';
a--;
}
上述代码输出:10 9 8 7 6 5 4 3 2 1。while循环嵌套:
int a = 10, b = 10;
while (a != 0) {
while (b != 0) {
cout << a << ' ' << b;
b--;
}
a--;
}
无限循环:
while (true) {
cout << "无限";
}
3.2 do while循环
先执行一次do语句块,再进行循环,与while的区别就是while是先判断再执行,do while是先执行再判断如:
int a = 0;
//输出:0。再判断条件,不满足,退出循环
do {
cout << a;
} while (a != 0);
//不满足条件,不执行语句块
while (a != 0) {
cout << a;
}
3.3 for循环
for循环主要由四个部分构成:初始化区、条件判断区、变量处理区、语句块
for (初始化区; 条件判断区; 处理区) { 语句块 },如:
for (int i = 0; i < 5; ++i) {
cout << i << ' ';
}
//输出 0 1 2 3 4
//嵌套,输出5 x 5 = 25个hello world
for (int i = 0; i < 5; ++i) {
for (int j = 0; j < 5; ++j) {
cout << "hello world\n";
}
}
//无限循环
for (int i = 0; ; ++i) {
cout << "hello world\n";
}
初始化区在整个循环中只执行一次,条件判断区和处理区每次循环都会执行,条件判断区是在语句块执行前执行,但处理区是在语句块执行后执行。每个区都可以省略不写。简单循环可以用while,复杂一点的循环建议用for。
3.4 C++11的范围for循环
for (序列项 :待访问序列) { 语句块 },如:
int a[5] = { 0, 1, 2, 3, 4 };
//输出:0 1 2 3 4
for (auto item : a) {
cout << item << ' ';
}
vector<int> b = { 0, 1, 2, 3, 4 };
//输出:0 1 2 3 4
for (auto& item : b) {
cout << item << ' ';
}
item在每次循环被赋予数组中的值。
4.跳转语句
4.1 break语句
break语句在上述内容出现过,在switch用于退出,而在循环中也可用于退出,如:
int a = 5;
while (true) {
a--;
if (3 == a) { //a等于3时退出循环
break;
}
}
for (int b = 5 ; ; --b) {
if (3 == b) { //b等于3时退出循环
break;
}
}
每个break只能退出一层循环(break所在的那一层)。
4.2 continue语句
主要在循环中直接开始下一次循环(从条件判断开始),语句块中continue后面的代码不会被执行:
int a = 1;
while (true) {
//a永远大于0,continue语句将永远在每次循环中被执行
if (a > 0) {
a++;
continue;
}
cout << "什么时候执行到我啊?\n"; //这句话永远不会被执行
}
4.3 goto语句
goto语句的作用是从goto语句无条件跳转到同一函数内的另一条语句。如:
//在main函数中
int main() {
A:
//跳转到这里
int a = 0;
if (0 == a) {
goto A; //跳转到标签A的语句
}
return 0;
}
A: int a = 0; 是一条带标签语句。上述代码将会使程序在A:与goto A语句之间被无限跳转,在跳转过程中a不会被重复定义,因为在跳转后,变量a会被销毁。注意,不能在跳转时绕过用到的变量的定义,如:
int main() {
goto A; //跳转
int a = 0;
A:
//跳转到这里,错误,a是未定义的
cout << a;
return 0;
}
虽然说存在便有意义,但不要在程序中使用goto语句,这会导致程序难以理解以及难以修改,就当是做个了解。使用了goto语句的代码基本上是设计很差的代码,goto语句看起来虽然酷,但会使代码质量非常低,也会暴露程序员的水平非常低。
try语句块与异常处理
异常处理属于更进阶一些的内容,这里只作简单介绍。可以捕捉在try语句块中发生的异常,try语句块中抛出异常的语句后面的语句不会被执行,就像goto语句:
try {
int a;
cout << "请输入一个大于0的数:";
cin >> a;
if (a < 0) {
throw a; //如果用户输入了小于0的数,抛出异常
}
/*
假如这里有其他代码,例如分配动态空间,或使用某种STL容器
*/
cout << "hello world\n"; //如果抛出异常
} catch (int e) {
//这个分支捕捉int类型的异常,并将抛出的值赋值给e
cout << "输入的数" << a << "小于0";
} catch (bad_alloc ba) {
//如果在分配动态空间时捕捉到bad_alloc异常
cout << "分配失败";
}
或许你会想说,上面的例子用if语句判断一下不就行了吗?是的,但这是作为一个使用者的角度考虑,假如你要写一个库给别人使用,有时你只能选择将异常抛出给库的使用者处理。如果在抛出异常后,没有找到匹配的catch子句,那么将中止该函数并在调用该函数的函数继续寻找,一层一层,顺着函数调用链往前找,如果找到最后还没有找到,程序将转到名为terminate的标准库函数,这时,程序一般会异常退出。也许你在写代码的时候已经遇到过程序错误提示“未经处理的异常xxx”。
本篇博客就先介绍到这里,欢迎各位同学积极在评论区评论、提问。