5.3 条件语句

C++中提供了两种条件控制语句,一个是if,通过条件控制控制流,一种是switch,他计算一个整型表达式的值,通过整型表达式的值来决定是执行几条路径的的哪一条。

if语句

if语句的作用是:判断一个指定的条件是否为真,根据判断结果决定是否执行另外一条语句。if 语句包括两种形式: 一种含有else分支,另外一种没有。

简单if语句的语法形式是:

if(condition)
statement

另一种是:

if(condition)
statement
else
statement

在这两个版本的if语句中,condition 都必须用圆括号包围起来,括号内部将进行表达式计算再转化成bool类型。condition 可以是一个表达式,也可以是一个初始化了的变量声明。不管是表达式还是变量,其类型都必须能转换布尔类型。通常情况下,statement是块语句,除非仅仅只需要运行一次。

如果condition为真,执行statement。当statement执行完成后,程序继续执行if语句后面的其他语句。

如果condition为假,跳过statement。对于简单if语句来说,程序继续执行if语句后面的其他语句;对于if else 语句来说,执行else后面的statement。

这里举个例子,来进行理解if-else例子:

#include<iostream>
#include<stdlib.h>
#include<time.h>
#include<vector>

using namespace std;

int get_num()
{
	srand((unsigned)time(NULL));
	return rand() % 100;
}

int main()
{
	const vector<string> grade = { "D","C","B","A" };
	int num = get_num();
	string stu_grade;
	if (num<60)
	{
		stu_grade = grade[0];
	}
	else if (num<75) //2
	{
		stu_grade = grade[1];
	}
	else if (num<85)
	{
		stu_grade = grade[2];
	}
	else
	{
		stu_grade = grade[3];
	}
	cout<<num<<"的等级是:"<<stu_grade;
	return 0;
}

值得注意的是,else if 和if的区别,如果在2处,将else去掉,程序在每次判断的时候,都会进行判断,而如果使用了else if则将会在if条件不满足的情况下,再进行判断。合理使用if else if减少程序的空间复杂度。

嵌套使用if

有时候我们生活中的条件并不是一串接着一串的,而是叠加的,比如我们需要男的员工,并且它的年纪还得在18-60岁之间的,这些情况下就得使用上嵌套循环,但是总的来说和原本的使用方式也差不多。

例子:

#include<iostream>

using namespace std;

int main()
{
	string sex = "男";
	int num = 20;
	if (sex=="男")
	{
		if (num>=18&&num<60)
		{
			cout << "您被录取了";
		}
		else
		{
			cout << "年纪不满足";
		}
	}
	else
	{
		cout << "性别不满足";
	}
	return 0;
}

注意使用花括号

在缺少花括号的情况下我们使用函数的时候将会与原本的预期执行不相同,原因就在于我们把花括号阔在一起的程序代码叫做块,即当作一个整体,在条件判断之后如果无花括号,仅执行一句;之后便结束执行,后续的函数将会被当作主函数当中的内容。

悬垂else

当一个if语句嵌套在另一个if语句内部时,很可能if分支会多于else分支。这时候问题出现了:我们怎么知道某个给定的else是和哪个if匹配呢?

这个问题通常称作悬垂else,在那些既有if语句又有if else语句的编程语言中是个普遍存在的问题。不同语言解决该问题的思路也不同,就C++而言,它规定else与离它最近的尚未匹配的if匹配,从而消除了程序的二义性。

举个例子:

#include<iostream>

using namespace std;

int main()
{
	int num = 70;
	if (num > 60)
		if (num < 70)
			cout << "C";
	else
		cout << "D";
	return 0;
}

C++当中并不以空格缩进控制if和else的归属,我特意写成这样子,大家可以去运行以下,看看输出。

switch语句

switch语句提供了一条 便利的途径使得我们能够在若干固定选项中做出选择。

基本的语法:

switch(ch)
case 变量:
statement;
break;
case 变量:
statement;
break;
······
default :
statement;
break;

样例:(统计一串字符串中出现a,b以及其他字符的数量)

#include<iostream>
#include<vector>
using namespace std;

int main()
{
	vector<int> num = { 0,0,0 }; 
	char str=0;
	while (cin >> str)
	{
		switch (str)
		{
		case 'a' :
			num[0] += 1;
			break;
		case 'b':
			num[1] += 1;
			break;
		case '\n':
			num[2] -= 1;
		default:
			num[2] += 1;
			break;
		}
	}
	cout << "a:" << num[0] << endl;
	cout << "b:" << num[1] << endl;
	cout << "其他:" << num[2] << endl;
	return 0;
}

输出结果:
在这里插入图片描述
switch语句首先对括号里的表达式求值,该表达式紧跟在关键字switch的后面,可以是一个初始化的变量声明。表达式的值转换成整数类型,然后与每个case标签的值比较。

如果表达式和某个case标签的值匹配成功,程序从该标签之后的第一条语句开始执行,直到到达了switch的结尾或者是遇到一条break语句为止

break语句的作用是中断当前的控制流。此例中,break语句将控制权转移到switch语外面。因为switch是while循环体内唯一的语句, 所以从switch语句中断出来以后,程序的控制权将移到while语句。此时while语句内部没有其他语句要执行,所以while会返回去再一次判断条件是否满足。

如果switch语句的表达式和所有case都没有匹配上,将直接跳转到switch结构之后的第一条语句。如果有default的话就跳到default上。

case关键字和它对应的值一起被称为case标签(case label)。case标签必须是整型常量表达式。任何两个case标签的值不能相同,否则就会引发错误。另外,default也是一-种特殊的case标签。

switch的控制流

程序在case标签之间的执行流程非常重要。如果某个case标签匹配成功,将从该标签开始往后顺序执行所有case分支,除非程序显式地中断(break)了这一过程,否则直到switch的结尾处才会停下来。要想避免执行后续case分支的代码,我们必须显式地告诉编译器终止执行过程。大多数情况下,在下一个case标签之前应该有一条break语句。

PS:即使不准备在default标签下做任何工作,定义一个default也是十分必要的,其目的就在于告诉读这个程序的人,我们已经考虑到了这种情况,这种情况下就是什么都不需要做。

switch的内部变量的定义

#include<iostream>

using namespace std;

int main()
{
	char str=0;
	switch (str)
	{		
	case 'a' :
		int j;//注意
		j = 1;
		cout << j;
		break;
	case 'b':
		j = 2;
		cout << j;
		break;
	case '\n':
		j = 3;
		cout << j;
	default:
		j = 5;
		cout << j;
		break;
	}
	return 0;
}

我们可以看到int j在其中某一个case当中,但我们知道的是,我们在运行switch的时候有可能会先跳过运行a,直接运行b,那这个为什么可以运行呢?原因只可能是程序在执行之前就已经给j定义了一个int空间,所以int j的执行阶段在程序运行之前,那么有什么是不能使用的呢?

如果我们直接int i = j;声明i并且进行初始化之后便不能进行运行了。原因就是需要初始化的变量的定义是在函数执行的时候进行的(虽然空间分配还是在程序执行之前分配的)。这会导致跳过某个定义,所以程序会报错。所以一些在声明的时候便进行默认初始化的也是不能使用的,比如string,或者自己的手动初始化。

那么我们该怎么在switch中使用这些初始化呢?也有办法,可以使用{}。

#include<iostream>

using namespace std;

int main()
{
	char str=0;
	switch (str)
	{		
	case 'a' :
		int j;
		{
			string j= "a";
			cout << j;
		}                          //{}
		break;
	case 'b':
		j = 2;
		cout << j;
		break;
	case '\n':
		j = 3;
		cout << j;
	default:
		j = 5;
		cout << j;
		break;
	}
	return 0;
}

如果需要为某个case分支定义并初始化一一个变量,我们应该把变量定义在块内,从而确保后面的所有case标签都在变量的作用域之外。

使用了{}之后定义的就不会跳过了,原因就在于{}内定义的变量,生存周期就在{}当中,外部时调用不了的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值