知识积累
关系表达式与逻辑表达式
关系表达式
在C++中常常能见到被括号括起的式子,里面是两个数字或变量被一个符号连接起来,那样的式子一般是关系表达式,中间的符号是关系运算符。只要按照标准格式写,一整个括号和括号里的式子就相当于一个布尔值,若式子成立,则布尔值为1,若不成立,则布尔值为0,准确来说,就是在关系运算符两边放表达式,就会计算这两边的关系,返回1或者0;
#include<iostream>
#include<cmath>
using namespace std;
int main(){
int a,b;
cin>>a>>b;
cout<<(a>b)<<endl;
cout<<(a<=b)<<endl;
cout<<(a==b)<<endl;
cout<<(a!=b)<<endl;
/*
double m,n;
cout<<(fabs(a-b)<1e-6)<<endl;
//浮点数不能直接用==,因为有误差,不会完全相等,
只能说两者的差的绝对值很小,就看作二者相等了。
*/
在比大小问题里,特别需要注意的是,不可以在同一个表达式里同时出现多个大于号或小于号,比如 (a<=b<=c) ,这是不允许的,只能写成 (a<=b&&b<=c)。
在题目中,关系表达式有时候会很长,这样直接写在cout语句里就显得很麻烦,看起来也很繁琐,所以可以先将关系表达式的布尔值赋给一个整型变量,用 int、char 都可以,但习惯上会定义 bool 型的变量,因为占用字节少,只能表示0和1这两种取值;
#include<iostream>
using namespace std;
int main(){
int x;
bool p1,p2;
p1=x%2==0;//这里将表达式返回的布尔值直接赋给bool型变量p1,不需要加括号;
p2=x<12;
cout<<(p1&&p2)<<endl;//cout语句里的表达式就需要加括号;
return 0;
}
在一些刁钻的题目里,关系表达式十分复杂,里面包含了各种四则运算符号和关系运算符,但是计算机不是按字面顺序来处理表达式返回布尔值的,计算机的处理会按照特定的顺序进行,也就是遵照一定的优先级,下面表格里的运算符从左到右,优先级从高到低:
( ) | * 、 /、 % | + - | <、 >、 <=、 >= | ==、 != |
逻辑表达式
在C++中还可以使用一下几种逻辑运算符:
- 与运算符:&& 判断两个条件是否同时成立;
- 或运算符:|| 判断两个条件是否至少有一个成立;
- 异或运算符:^ 判断两个条件是否刚好一个成立、一个不成立;
- 非运算符:! 将一个条件取反,若条件返回值是1,则变成0,返回值是0同理;
在逻辑运算符中,非运算符!的优先级仅次于括号,与运算符&&的优先级高于或运算符||(没有括号掺和的情况下,先处理&&再处理||),或运算符||的优先级和异或运算符^相同,这三个的优先级都排在最后(也就是做完算术运算和关系运算后才轮到它们)。
典例 闰年判断
输入一个年份,判断这一年是否为闰年,如果是就输出1,否则输出0。
分析:被4整除是闰年,被100整除不是闰年,而被400整除又是闰年。基于此,可以这样写,被400整除作为一个表达式,被4整除且不被100整除作为另一个表达式,这两个表达式只要至少有一个成立,就可以判断为闰年。
#include<iostream>
using namespace std;
int main(){
int year;
bool p1,p2,p3;
cin>>year;
p1=year%400==0;
p2=year%4==0;
p3=year%100==0;
cout<<(p1||p2&&!p3)<<endl;
return 0;
}
分支语句
if条件语句
if (成立条件表达式) {
当条件成立时需要执行的语句 ;
}
else if (另一条件成立表达式) {
这一条件成立时需要执行的语句 ;
}
else {
当上面条件都不成立时需要执行的语句;
}
可以没有 else if 和 else,它们的使用视情况而定。
需要注意的是,if语句是按书面顺序来执行的,若满足了第一个条件语句并执行后,下面的条件就会全部跳过,所以在做题时,不能将范围较大的条件放在上面,而应该从上往下逐渐扩大条件范围。
典例 肥胖问题
BMI指数是国际上常用的衡量人体胖瘦程度的一个标准,其算法是m/h^2,其中m是指以kg为单位的体重,h是指以m为单位的身高。
不同体型范围与判定结果如下:
- 小于 18.518.5:体重过轻,输出
Underweight
; - 大于等于 18.518.5 且小于 2424:正常体重,输出
Normal
; - 大于等于 2424:肥胖,不仅要输出 BMI 值(使用
cout
的默认精度),然后换行,还要输出Overweight
;
现在给出体重和身高数据,需要根据 BMI 指数判断体型状态并输出对应的判断。
输入格式
共一行。
第一行,共 22 个浮点数,m,nm,n,分别表示体重(单位为 kgkg),身高(单位为 mm)。
输出格式
输出一行一个字符串,表示根据 BMI 的对应判断。特别地,对于 Overweight
情况的特别处理请参照题目所述。
#include<iostream>
using namespace std;
int main(){
double m,h,BMI;
cin>>m>>h;
BMI=m/h/h;
if(BMI<18.5)
cout<<"Underweight"<<endl;
else if(BMI<24)
cout<<"Normal"<<endl;
/*如果这一步能执行,那么上一步已经帮我们筛掉了体重过轻的情况,
这样小于24的只剩下正常体重,这就是条件范围从上往下逐渐扩大,
而且,这样还能避免出现 18.5<=BMI 的情况出现,
因为不能直接对浮点数进行相等的比较!*/
else
cout<<BMI<<'\n'<<"Overweight"<<endl;
return 0;
}
switch条件语句
switch (变量名) {
case 变量可能的情况1:执行语句1;break;
case 变量可能的情况2:执行语句2;break;
……
default : 执行语句n;break;
}
在switch语句里,变量可能的情况只能是确定的常量,确定的常量可以是int型的整数,也可以是char型的字符,但不能是double型或float型的浮点数,若要用浮点数,则应使用多重if嵌套来进行分支判断。
还需注意,case的执行语句里不能再定义变量或常量!!要定义请在switch之前最开始就定义好。
另外,若能保证输入数据一定是合法的,那么最后也可以不写default语句。
典例 月份天数
题目描述
输入年份和月份,输出这一年的这一月有多少天。需要考虑闰年。
输入格式
输入两个正整数,分别表示年份 yy 和月数 mm,以空格隔开。
输出格式
输出一行一个正整数,表示这个月有多少天。
#include<iostream>
using namespace std;
int main(){
int y,m;
cin>>y>>m;
switch(m){
case 1:case 3:case 5:case 7:case 8:case 10:case 12:cout<<31<<endl;break;
case 4:case 6:case 9:case 11:cout<<30<<endl;break; //case的情况可叠加;
case 2:if(y%400==0||y%4==0&&y%100!=0)
cout<<29<<endl;
else cout<<28<<endl;break;
default:break;//无论是case还是default,最后都务必加上break!
}
return 0;
}
问号表达式
形式为 S1?S2:S3 ,意思是如果条件S1成立,那么这个表达式的值为S2,否则这个表达式的值为S3。问号表达式的优先级相当低,所以要用问号表达式时,尽量独立一个句子赋值给变量。
刷题小得
ASCII的应用
将字符类型的数字转换为整型数字时,需要减去字符 '0'。
二、习题答案
习题3-1
四个表达式都成立。判断代码如下:
#include<iostream>
using namespace std;
int main(){
int a=3,b=4,c=5;
bool p1,p2,p3,p4;
p1=(a<b||b>c||a>b);
p2=(a>c||b>a&&c>b);
p3=(b-a==c-b);
p4=(a*b-c>a*c-b||a*b+b*c==b*b*(c-a));
cout<<p1<<" "<<p2<<" "<<p3<<" "<<p4<<endl;
return 0;
}
习题3-2
第三个表达式不成立,其余都成立。判断代码如下:
#include<iostream>
using namespace std;
int main(){
int a=1,b=0,c=1;
bool p1,p2,p3,p4,p5;
p1=!a||!b;
p2=(a&&!a)||(b||!b);
p3=a&&b&&c||!a||!c;
p4=a&&(b&&c||a&&c);
p5=!b&&(c&&(a&&(!c||(!b||(!a)))));
cout<<p1<<" "<<p2<<" "<<p3<<" "<<p4<<" "<<p5<<endl;
return 0;
}
习题3-3
(1) x是否为偶数。
x%2==0
(2) x是否为四位整数。
x>=1000&&x<10000
(3) x是否为完全平方数。
#include<iostream>
using namespace std;
int main(){
int x,i;
cin>>x;
for(i=0;i<100000000;i++){
if(i*i*i==x)
cout<<"x是完全平方数"<<endl;
}
return 0;
}
(4) x是否同时是奇数、完全立方数,而且是三位整数。
#include<iostream>
using namespace std;
int main(){
int x,i,k=0;
cin>>x;
for(i=5;i<10;i++){
if(x%2==1&&i*i*i==x)
k=1;
}
if(k==1)
cout<<"x同时是奇数、完全立方数,而且是三位整数"<<endl;
else
cout<<"x不同时是奇数、完全立方数和三位整数"<<endl;
return 0;
}
(5) x是否是水仙花数(各位数的立方和等于本身的3位整数)。
#include<cstdio>
#include<iostream>
using namespace std;
int main(){
char a,b,c;
int x,y;
scanf("%c%c%c",&a,&b,&c);
x=100*(a-'0')+10*(b-'0')+(c-'0');
y=(a-'0')*(a-'0')*(a-'0')+(b-'0')*(b-'0')*(b-'0')+(c-'0')*(c-'0')*(c-'0');
if(x==y)
cout<<"x是水仙花数"<<endl;
else
cout<<"x不是水仙花数"<<endl;
return 0;
}
习题3-4 保留小数新方法
小玉家的电费
收获:输出要保留一位小数,原来的浮点数要乘10加0.5,然后转换为整型,再除以10.0。若要保留两位小数,就可以里面乘100,外面除以100.0,保留n位小数以此类推。
#include<iostream>
using namespace std;
int main(){
int x;
double y;
cin>>x;
if(x<=150)
y=x*0.4463;
else if(x<=400)
y=150*0.4463+(x-150)*0.4663;
else
y=150*0.4463+(400-150)*0.4663+(x-400)*0.5663;
cout<<int(y*10+0.5)/10.0<<endl;
return 0;
}
习题3-5
#include <iostream>
using namespace std;
int main(){
int x, n;
cin>>x>>n;
int d=n/7*5;
int r=n%7;
if(r > 0)
{
if(r+x==7||x==7)
r-=1;
else if(r+x>=8)
r-=2;\\这两步不是很理解……
}
cout<<(d+r)*250<<endl;
return 0;
}
习题3-6
#include<iostream>
using namespace std;
int main(){
int a,b,c;
cin>>a>>b>>c;
if(a<=b&&a<=c){
if(a*a+b*b==c*c)
cout<<a<<"/"<<c<<endl;
else
cout<<a<<"/"<<b<<endl;
}
else if(b<=a&&b<=c){
if(b*b+a+a==c*c)
cout<<b<<"/"<<c<<endl;
else
cout<<b<<"/"<<a<<endl;
}
else{
if(c*c+a*a==b*b)
cout<<c<<"/"<<b<<endl;
else
cout<<c<<"/"<<a<<endl;
}
return 0;
}
习题3-7
#include<iostream>
using namespace std;
int main(){
int a,b,c,d,e,f,g,h,i,j;
int gao,num=0;
cin>>a>>b>>c>>d>>e>>f>>g>>h>>i>>j;
cin>>gao;
gao+=30;
if(gao>=a) num++;
if(gao>=b) num++;
if(gao>=c) num++;
if(gao>=d) num++;
if(gao>=e) num++;
if(gao>=f) num++;
if(gao>=g) num++;
if(gao>=h) num++;
if(gao>=i) num++;
if(gao>=j) num++;
cout<<num<<endl;
return 0;
}
习题3-8
#include<iostream>
using namespace std;
int main(){
int a,b,c;
cin>>a>>b>>c;
if(a-b>=c||a+b<=c||b-c>=a||b+c<=a||a-c>=b||a+c<=b)
cout<<"Not triangle"<<endl;
else{
if(a*a+b*b==c*c||a*a+c*c==b*b||b*b+c*c==a*a){
cout<<"Right triangle"<<endl;
if(a==b||b==c||a==c)
cout<<"Isosceles triangle"<<endl;}
else if(a*a+b*b>c*c&&a*a+c*c>b*b&&b*b+c*c>a*a){
cout<<"Acute triangle"<<endl;
if(a==b||b==c||a==c)
cout<<"Isosceles triangle"<<endl;
if(a==b&&b==c)
cout<<"Equilateral triangle"<<endl;}
else{
cout<<"Obtuse triangle"<<endl;
if(a==b||a==c||b==c)
cout<<"Isosceles triangle"<<endl;
}
}
return 0;
}
习题3-9
#include<iostream>
#include<algorithm>
using namespace std;
int a[3];
char A,B,C;
int main()
{
cin>>a[0]>>a[1]>>a[2];
cin>>A>>B>>C;
sort(a,a+3);
cout<<a[A-'A']<<" "<<a[B-'A']<<" "<<a[C-'A'];
return 0;
}