这篇文章将总结一下c++的条件分支。
在这之前,我先总结一下c++的判断符。
c++判断符有:>, <, ==, >=, <=, !=。其中,==的用处是判断符号两边是否相等,>=用来判断符号左边是否大于等于右边,<=用来判断符号左边是否小于等于右边,!=用来判断两边是否不等。这里要特别注意,判断相等是用==而不是=,一个等号是用来赋值的。这里你可以在编译器里试一试用=代替==的结果。
汉语中的条件可以总结成:“如果······就;如果不······则”等。而这些在c++中用if、else来表示。基本结构如下:
if(条件){
语句1;
}else{
语句2;
}
或者:
if(条件1){
语句1;
}else if(条件2){
语句2;
}else{
语句3;
}
我们只需要按照格式把东西塞进去就好了。
此外,说到条件又不得不提一下“三目运算符”。三目运算符是为了简化if、else的,但只有部分情况下才能够用上,因此并不常用。三目运算符的格式如下:
表达式1? 表达式2: 表达式3;
举两个例子:
if(a > b){
max = a;
}else{
max = b;
}
可以简化为:
maxn = a > b ? a : b;
以及下面这个例子:
if(flag == 1){
cout << "yes";
}else{
cout << "no";
}
可以简化为:
cout << (flag == 1 ? "yes" : "no");
*注意这里的括号。
判断的格式是可以扩展的,也就是说一组判断语句可以有多个else if(),但有且只能有一个if(),最多只能有一个else()。像下面这个例子:
if(a % 5 == 0){
cout << "0";
}else if(a % 5 == 1){
cout << "1";
}else if(a % 5 == 2){
cout << "2";
}else if(a % 5 == 3){
cout << "3";
}else{
cout << "4";
}
然而就像上面这个例子一样,有时判断语句写起来太过繁琐,所以我们引入一个新的判断语句:switch。switch的用法在一些情况下十分方便。大致结构如下:
switch(变量名){
case 变量值: 语句1; break;
case 变量值: 语句2; break;
default: 语句3; break;
}
switch也是可以扩展的,即你可以多塞几个case进去,但是default最多只能有1个,而且作为switch的结尾使用。当然你也可以不写default。这里我举个例子:
switch(a % 5){
case 0: cout << "0"; break;
case 1: cout << "1"; break;
case 2: cout << "2"; break;
case 3: cout << "3"; break;
default: cout << "4"; break;
}
这段语句跟前面那个全是if、else的例子作用是一模一样的,但是代码却精简了不少。
接下来说一说判断语句的嵌套。
判断语句的嵌套,即往判断语句里面再塞些判断语句。例如:
if(flag != 0){
if(flag2 != 0){
cout << "no";
}else{
cout << "yes";
}
}else{
if(flag2 != 0){
cout << "yes";
}else{
cout << "no";
}
}
学电路的朋友可以看出这段语句其实起到了一个异或门的作用。类似的,switch也可以进行嵌套,这里就不多举例了。
下面再讲一下c++判断语句中表示并列关系的运算符:&&,||。&&的意思是“并且”,用来判断两边是否都成立;||的意思是“或者”,用来判断两边是否至少有一边成立。下面是例子:
if((3 > 2) && (3 > 1)){
cout << "yes" << endl;
}else{
cout << "no" << endl;
}
if((3 > 2) && (3 > 4)){
cout << "yes" << endl;
}else{
cout << "no" << endl;
}
这段话则会得到“yes no”的输出。而如果把段落中&&符号换成||符号,则会得到两个“yes”的输出。
下面是条件分支的一些习题:
今天会下雨吗
Description
你需要写一个程序,读入当前的相对空气湿度 H(0.0≤H≤100.0),气象学家小信认为当相对空气湿度大于 55.4 时,就属于“很可能会下雨”的天气。请根据今天的相对空气湿度,判断今天是否是“很可能会下雨”的天气。
Input
输入一个实数,表示相对空气湿度 H(0.0≤H≤100.0)。
Output
输出为一行,如果 H > 55.4则输出 YES,表示会下雨;否则输出 NO,表示不会下雨。(注意输出全为大写,不要把 YES 写成 Yes 或把 NO 写成 No)
这题只需要简单地对空气湿度进行判断就好了:
#include<iostream>
using namespace std;
int main(){
float H;
cin >> H;
if(H > 55.4) cout << "YES";
else cout << "NO";
return 0;
}
*当判断语句只有一条语句时,是可以不打花括号的
求绝对值
Description
在数学中,实数的“绝对值”是一个很有意思的概念,对于小于 0 的实数 n 来说,它的绝对值等于 -n,而对于大于等于 0 的实数来说,它的绝对值等于自身。
接下来,请完成一个程序:对于输入的一个实数 n,输出它的绝对值。
Input
输入包含一个实数 n(−100.0≤n≤100.0)。
Output
输出为一行,为实数 n 的绝对值。
这题就比较经典了。其实只需要判断一下n与零的大小关系:
#include<iostream>
using namespace std;
int main(){
int n;
cin >> n;
if(n < 0){
n = -n;
}
cout << n;
return 0;
}
他的名字
Description
小信的老师喜欢用一个字母去记录班上五个同学的名字,他希望你可以在他喊出一个字母的时候告诉他同学的全名。我们知道他记录的字母和同学名字的对应关系:
h 对应 He
l 对应 Li
c 对应 Cao
d 对应 Duan
w 对应 Wang
你的程序将接受到一个字母,如果这个字母有对应的同学名字,则你需要将这个字母对应的同学的名字输出出来。如果这个字母没有对应的同学名字,则输出 Not here。
注意输出时所有字母大小写要与要求完全一致。
Input
输入包含一个字符 x。
Output
输出为一行。如果输入的字母有对应的同学名字,则你需要将这个字母对应的同学的名字输出出来。如果这个字母没有对应的同学名字,则输出 Not here。
请注意,输出的大小写和符号必须完全一致。
这题难度也不大,但是用switch写要精简许多:
#include<iostream>
using namespace std;
int main(){
char x;
cin >> x;
switch(x){
case 'h': cout << "He"; break;
case 'l': cout << "Li"; break;
case 'c': cout << "Cao"; break;
case 'd': cout << "Duan"; break;
case 'w': cout << "Wang"; break;
default: cout << "Not here"; break;
}
return 0;
}
7的倍数
Description
如果一个数既是 7 的倍数又不能被 2 整除,那么我们称之为 7 的奇倍数。你的程序会读入一个正整数 n,请你判断一下 n 是否是 7 的奇倍数。
Input
输入包含一个正整数 n(0≤n≤100)。
Output
输出为一行,如果输入的正整数 n 是 7 的奇倍数,则输出 YES,否则输出 NO。
这题只需要把题目读懂,然后写代码就行了:
#include<iostream>
using namespace std;
int main(){
int n;
cin >> n;
if(n % 7 == 0 && n % 2 != 0) cout << "YES";
else cout << "NO";
return 0;
}
面积问题
Description
小信的老师准备和很多个口袋,每个口袋里面有两张纸条。
第一张纸条上说明了我们将要面对的是一个怎样的图形(可能是三角形,也可能是矩形)
第二张纸条上说明了两条边的长度 m 和 n(分别对应三角形的底和高,或者矩形的长和宽)
小蒜会从口袋中随机挑一个,并把纸条上的信息给你,让你的程序计算出图形的面积。
Input
输入包含两行。输入的第一行为一个字符,只可能是 r 或 t。如果是 r 则表示我们要计算面积的图形是一个矩形;如果是 t 则表示我们要计算面积的图形是一个三角形。
输入的第二行为两个实数,m 和 n。分别对应三角形的底和高(或对应矩形的长和宽)(0.0<m≤100.0)。
Output
输出为一行,为目标图形的面积。
这道题需要对r和t进行一下判断,然后分别对应圆和三角形的公式。代码如下:
#include<iostream>
using namespace std;
int main(){
char ch;
double m, n;
cin >> ch >> m >> n;
double ans;
if(ch == 't') ans = m * n / 2;
else ans = m * n;
cout << ans << endl;
return 0;
}
四位数中有偶数吗
Description
请你通过程序设计,判断一下对于任意一个给定的四位正整数,其中是否存在一个数位上是偶数(提示:偶数是除以 2 余数为 0 的数)。
Input
输入包含一个四位正整数 n(1000≤n≤9999)。
Output
输出为一行,如果 n 的千位、百位、十位、个位中的任何一个为偶数,则输出 YES,否则输出NO。
这道题需要你灵活地运用/和%符号,将n的各个位数提取出来。大致方法为:提取个位,n % 10;提取十位,n / 10 % 10;提取百位,n / 100 % 10;提取千位,n / 1000。多思考就能懂啦!代码如下:
#include<iostream>
using namespace std;
int main(){
int n;
cin >> n;
int a, b, c, d;//分别为各位,十位,百位和千位
a = n % 10, b = n / 10 % 10, c = n / 100 % 10, d = n / 1000;
if(a % 2 == 0 || b % 2 == 0 || c % 2 == 0 || d % 2 == 0){
cout << "YES";
}else{
cout << "NO";
}
return 0;
}
递归的做法如下:
#include<iostream>
using namespace std;
bool check(int);//声明函数
int main(){
int n;
cin >> n;
if(check(n)) cout << "YES";
else cout << "NO";
return 0;
}
bool check(int n){
if(n % 2 == 0) return true;
if(n >= 10) check(n / 10);//递归调用
else return false;
}
提一下这里的布尔类型(bool)。布尔类型是一种占内存很小的变量,但是它的值只能为两种情况:真(1或true)和假(0或false),通常会用到判断语句中。
日期的合法性
Description
测试程序将随机给你一个空格分隔了年、月、日的日期(其中的数字都是没有前导零的,也就是说7不会被写成07)。你将需要判断这个日期在我们的公历体系内是否真实存在。如果存在则输出YES,否则输出NO(注意输出的字母都一定是大写字母)。
测试程序给出的测试输入数据中,年、月、日都是正整数(也就是大于零的整数),均不大于 3000。
已知,一年有 1 月到 12 月,共 12个不同的月份;其中 1 月、3 月、5 月、7 月、8 月、10 月、12 月有 31个合法的日,分别为 1 日到 31 日;4 月、6 月、9 月、11 月有 30个合法的日,分别为 1 日到 30 日。对于闰年,2 月有 29个合法的日,分别为 1 日到 29 日;对于平年(不是闰年的年称为平年),2 月有 28 个合法的日,分别为 1 日到 28日。
对于不大于 3000 年的年份,闰年遵循如下规律:
非整百年,能被 4 整除的为闰年。
整百年,能被 400 整除的是闰年。
之后呢,你需要做很多的判断,会嵌套地用到我们已经学的if...else...的结构。你将需要:
判断输入日期中的月份是不是合法的月份(这里特殊情况最少,建议第一层先判断);
针对每个月的日数判断输入日期中日的合法性;
注意抓住特殊的 2 月,在里面讨论年的问题(看是不是闰年);
对于闰年,允许 29 日的存在
对于非闰年不能允许 29 日的存在。
Input
输入3个数,分表表示某个日期的年、月、日。
Output
判断这个日期是否存在,如果存在输出“YES”,否则输出“NO”。
这题对判断语句使用的考察比较深,需要用到非常多的if/else语句,所以我们不妨写一个用来判断的函数:
#include<iostream>
using namespace std;
bool check(int, int, int);
int main(){
int y, m, d;
cin >> y >> m >> d;//年月日
if(check(y, m, d)) cout << "YES";//调用函数check
else cout << "NO";
return 0;
}
bool check(int y, int m, int d){
if(m < 1 || m > 12) return 0;//月是否合法
if(d < 1 || d > 31) return 0;//日是否合法
if(m == 2 && d > 29) return 0;//不管平年还是闰年,2月天数都不能超过29
if((m == 4 || m == 6 || m==9 || m == 11) && d > 30) return 0;//对30天的月进行判断
if(((y % 100 != 0 && y % 4 != 0) || (y % 100 == 0 && y % 400 != 0)) && m == 2 && d
>28) return 0;//对平年的二月进行判断
return 1;
}
这题主要把逻辑理清楚就好了。
包裹托运
Description
春节快到了,小信和爸爸一起来到邮局,打算给家住外地的爷爷、奶奶家里捎点年货。邮局的阿姨介绍,托运包裹的运费标准是:包裹重量不大于15 公斤时,每公斤6 元;超过 15 公斤后,其超过部分每公斤 9 元。
现已知包裹的重量为 X 公斤,请同学们和小信一起帮助邮局的阿姨计算一下,包裹的运费 Y应为多少元?
Input
输入只有一行,包含一个数值 X(其中1≤X≤100)表示包裹的重量,单位:公斤。
Output
输出只有一行,包含 1个数,表示包裹的运费。
对x和15的大小关系进行判断一下就行了:
#include<iostream>
using namespace std;
int main(){
int x;
cin >> x;
int ans;
if(x <= 15) ans = x * 6;
else ans = 90 + (x - 15) * 9;
cout << ans;
return 0;
}
乘车费用
Description
星期天上午小红乘出租车去本市的奶奶家。出租车计价方案为: 3公里以内(包括 3 公里)起步价是 13 元,超过 3 公里之后按 2.3 元/公里计价,整个乘车途中另加 1 元钱的燃油费。已知:小红到奶奶家的路程为 N 公里,请你计算一下小红到奶奶家的出租车费用是多少元?
Input
输入只有一行,包含 1个整数 N(其中1≤N≤30)表示路程,单位:公里。
Output
输出只有一行,包含 1 个数,表示出租车费用。
这题需要对N和3的大小关系进行判断,算出里程费之后再加上燃油费。代码如下:
#include<iostream>
using namespace std;
int main(){
int n;
cin >> n;
double ans;
if(n <= 3) ans = 14;
else ans = 14 + (n - 3) * 2.3;
cout << ans;
return 0;
}
彩票
Description
大乐透彩票的获奖编码由两位非零数组成。程序根据获奖编码和用户的输入,可以确定用户是否获奖,具体规则为:
如果用户输入的数与获奖编码完全相同,奖金为 100 元
如果用户输入的所有数字匹配获奖编码的所有数字,奖金为 20 元
如果用户输入的数字能够匹配获奖编码的一个数字,奖金为 2 元
程序输入获奖编码和用户的输入,判断用户最终能获得多少奖金。如果没有获奖,则奖金为 0。
Input
你的程序将会接受两个两位整数,分别表示获奖编码和用户的输入。
Output
输出一个整数,表示用户的奖金。
这题看似复杂,但是题目说了输入的数都是两位数,而且每一位都不为0,因此我们可以把每一位都提出来进行判断。但是注意规则的第二条,它看起来与第一条一样,但是第二条每个数的顺序可以不一样,也就是说如果用户输入12,获奖编码为21,这种情况不符合第一条规则但是是符合第二条规则的。代码如下:
#include<iostream>
using namespace std;
int main(){
int pass,in;
cin >> pass >> in;
int ans = 0;
if(pass == in) ans = 100;//用户的输入与获奖编码完全相同
else{
int p[2] = {pass / 10, pass % 10}, i[2] = {in / 10, in % 10};
if(p[0] == i[0] || p[0] == i[1]) ans += 2;匹配一个数字加2元
if(p[1] == i[1] || p[1] == i[0]) ans += 2;
if(ans == 4) ans = 20;若每个数字都能匹配,奖金变为20
}
cout << ans;
return 0;
}
这里用到了数组。数组就是用来存许多个排在一条线上的数据的,声明数组的方法为:变量类型 数组名[大小]。其中大小必须是整数,而且放在主函数外定义时大小必须为一个常数。但是如果开一个大小为n的数组,数组的下标会是0~n - 1而不是1~n。在访问数组的某个变量时只需要写上:数组名[下标]就可以访问这个下标对应的变量的值了。
这里还有一种特殊的运算:+=。ans += 2是等同于ans = ans +2的,用+=十分的简洁。同理,-=,*=,/=也是这样的。特殊地,当+= 1或者-= 1时,可以直接用++和--来代替。
生肖
Description
生肖基于 12 年一个周期,每年用一个动物代表——
猴(monkey)、鸡(rooster)、狗(dog)、猪(pig)、鼠(rat)、牛(ox)、虎(tiger)、兔(rabbit)、龙(dragon)、蛇(snake)、马(horse)或者羊(sheep)。
已知 1900 属鼠,对于程序输入的年份,输出年份对应的生肖单词。
Input
输入一个整数 year,表示年份(1≤year≤9999)。
Output
输出一个单词,表示生肖。
题目中告诉了1900属鼠,所以我们将1899定义为一个常量,再用输入的年份减去1899再对12取余,然后分情况输出就可以了。
代码如下:
#include<iostream>
using namespace std;
const int be = 1899;//const为修饰符,常量的意思
int main(){
int year;
cin >> year;
int ani;
ani = (year - be) % 12;
if(ani < 0) ani += 12;//对输入年份小于1899的情况进项处理
switch(ani){
case 1: cout << "rat"; break;
case 2: cout << "ox"; break;
case 3: cout << "tiger"; break;
case 4: cout << "rabbit"; break;
case 5: cout << "dragon"; break;
case 6: cout << "snake"; break;
case 7: cout << "hourse"; break;
case 8: cout << "sheep"; break;
case 9: cout << "monkey"; break;
case 10: cout << "rooster"; break;
case 11: cout << "dog"; break;
case 0: cout << "pig"; break;//switch是可以不写default的
}
return 0;
}
三角形形状
Description
读入三角形的三条边,进行如下的判断:
如果输入值不合法,输出illegal triangle,表示三角形不合法
如果输入值合法,两条较短边的平方和大于最长边的平方,则输出acute triangle,表示锐角三角形
如果输入值合法,两条较短边的平方和等于最长边的平方,则输出right triangle,表示直角三角形
如果输入值合法,两条较短边的平方和小于最长边的平方,则输出obtuse triangle,表示钝角三角形
如果任意两条边的和 大于 第三边,那么输入的三角形就是合法的。
Input
读入三个整数 a,b,c(1≤a,b,c≤100),表示三角形的三条边。
Output
根据情况输出illegal triangle、acute triangle、right triangle、obtuse triangle中的一种。
对于合法,即三角形任意两边之和大于第三边,之差小于第三边:
#include<iostream>//因为要用到sort
#include<algorithm>
using namespace std;
int check(int, int, int);
void print(int);
int main(){
int a[3];
cin >> a[0] >> a[1] >> a[2];
sort(a, a+3);//排序函数,两个参数分别为起始位置和结束位置,默认是从小到大排
int ans;
ans = check(a[0], a[1], a[2]);//判断三角形的四种情况
print(ans);//对应每种情况的输出
return 0;
}
int check(int a, int b, int c){
if(a + b <= c) return 0;//不合法
if(a * a + b * b > c * c) return 1;//锐角三角形
if(a * a + b * b == c * c) return 2;//直角三角形
return 3;//钝角三角形
}
void print(int n){
switch(n){
case 0: cout << "illegal triangle"; break;
case 1: cout << "acute triangle"; break;
case 2: cout << "right triangle"; break;
case 3: cout << "obtuse triangle"; break;
}
}
回文数
Description
读入一个不超过四位的整数,判断它是不是回文数。回文数是指正着看和倒着看一样的数,比如 111、1221 就是回文数,而 1515 不是。
Input
读入一个整数 n(1≤n<10000)。
Output
如果 n 是回文数,则输出YES,否则输出NO。
这题将输入的数从两边向中间进行判断就好了:
#include<iostream>
#include<cstring>//因为需要用到关于字符串的操作
using namespace std;
int main(){
string n;//声明一个字符串
cin >> n;
bool flag = true;//判断是否是回文数
for(int i = 0; i < n.size() / 2; i++){//for循环,基本结构为(变量;条件;命令){语句;}
if(n[i] != n[n.size() - i - 1]){//从两边向中间判断
flag = false;
break;//退出循环
}
}
if(flag){
cout << "YES";
}else{
cout << "NO";
}
return 0;
}
注意这里用到了循环和字符串,当然不用也是可以做出来的。
昨天和明天
Description
读入一个日期,算出这个日期前一天和后一天的日期。
Input
读入三个整数,分别表示日期的年、月、日。
Output
第一行输出三个用空格分隔的整数,表示前一天的年月日。第二行输出三个用空格分隔的整数,表示后一天的年月日。
对于昨天,只需要将日期减一就可以了;对于明天,只需要将日期加一就可以了。但是还需要判断一下日期是否合法,及时地对月份和年份进行加减的操作。代码如下:
#include<iostream>
using namespace std;
void before(int, int, int);
void after(int, int, int);
bool check(int, int, int);
void print(int, int, int);
int main(){
int y, m, d;
cin >> y >> m >> d;
before(y, m, d);
after(y, m, d);
return 0;
}
void before(int y, int m, int d){
bool flag;
do{
d--;
if(!d){d=31; m--; if(!m){m=12; y--;}}
flag = check(y, m, d);
if(flag) print(y, m, d);
}while(!flag);//do-while的作用是先执行一次括号里的操作,再判断是否继续循环
}
void after(int y, int m, int d){
bool flag;
do{
d++;
if(d == 32){ d = 1; m++; if(m == 13){m=1; y++;}}
flag = check(y, m, d);
if(flag) print(y, m, d);
}while(!flag);
}
bool check(int y, int m, int d){
if(y > 3000) return 0;
if(m < 1 || m > 12) return 0;
if(d < 0 || d > 31) return 0;
if(m == 2 && d > 29) return 0;
if((m == 4 || m == 6 || m == 9 || m == 11) && d > 30) return 0;
if(y % 4 != 0 && m == 2 && d > 28) return 0;
return 1;
}
void print(int y,int m,int d){
cout << y << " " << m << " " << d << endl;
}