day03:数据类型转换
1. 类型转换
- 自动类型转换
- 强制类型转换
- 字符型和整型的转换
1.自动类型转换
在不同数据类型的混合运算中,编译器会隐式地进行数据类型转换,称为自动类型转换。
自动类型转换遵守以下规则:
(1)若参与运算的数据类型不同,则先转换成同一类型,然后进行运算。
(2)转换按数据长度增加的方向进行,以保证精度不降低。例如int类型和long long类型运算时,先把int转换为long long后再运算。
(3)在赋值运算中,赋值号两边的数据类型不一样时,将把右面表达式的类型转换为左边变量的类型。如果右边表达式的数据类型长度比左边的长时,将丢失一部分数据。
即:char -->short -->int --> float -->double
#include<bits/stdc++.h>
using namespace std;
int main(){
int a = 1, b = 2;
double c = 1.2, d = 2.3;
double e = a + b + c + d;//a,b会隐式转换为double类型
cout<<e; //输出结果:6.5
return 0;
}
2.强制类型转换
当自动类型转换不能实现目的时,可以显示的进行类型转换,称为强制类型转换。
强制类型转换的一般形式是: (类型名)(表达式) (类型名)变量
如(double)a 是将a转换为double型,
(int)(x + y) 是将 x+y 的值转换为整型,
(float)5/3 是将 5 的值转换成float型,再与 3 运算。
double为双精度浮点型,float为单精度浮点型,区别在于他们的精度不同。
#include<bits/stdc++.h>
using namespace std;
int main(){
double a = 1.2, b = 2.3;
int c = (int)a;
double d = (int)a+b;
cout<<a<<" "<<b<<" "<<c<<" "<<d<<endl;
//输出结果:1.2 2.3 1 3.3
return 0;
}
3.字符型和整型的转换
将一个字符放到内存单元时,实际上并不是把该字符本身放到内存中,而是将该字符的ASCII代码放到存储单元中。
如字符变量c1的值是'a',c2的值是'b',则在变量中存放的是 'a' 的ASCII码97,'b' 的ASCII码98
#include<iostream>
using namespace std;
int main(){
char a = 'a';
cout<<a<<" "<<(int)a<<endl;//a 97
char b = 'b';
cout<<b<<" "<<(int)b<<endl;//b 98
int c = 97;
cout<<c<<" "<<(char)c<<endl;//97 a
int d = 98;
cout<<d<<" "<<(char)d<<endl;//98 b
cout<<++a<<endl;//b
cout<<--b<<endl;//a
cout<<(char)(c-32)<<endl;//A
cout<<(char)(d-32)<<endl;//B
return 0;
}
2. c++输入输出
基本输入输出格式 | 输入 | 输出 |
---|---|---|
符号 | cin | cout |
单个使用 | cin>>a; | cout<<a; |
多个使用 | cin>>a>>b>>c; | cout<<a<<" "<<b<<" "<<c; |
注意:任何变量在使用前都需要先定义。
预定义对象 cin 和 cout 都是 iostream 类的实例,与流插入运算符 <<
结合使用,使用前需要导入头文件iostream
。
cin 对象附属到标准输入设备,通常是键盘。
cout 对象"连接"到标准输出设备,通常是显示屏。
c++中对于浮点数的输出需要注意,这一点在之前已经提过,这里不过老生常谈!
浮点数也就是小数,同理还存在定点数,也就是我们说的整数。
当我们要输出 :3.1415926535 小数点后3位的时候,就需要使用输出格式控制了!如下程序
#include<iostream>
#include<iomanip>
using namespace std;
int main(){
cout<<fixed<<setprecision(3)<<3.1415926535<<endl;
return 0;
}
通过fixed<<setprecision(3);
就可以达到这个效果了,如下图。
但是我们使用的这个函数是其他库里的,所以我们需要导入iomanip
这个头文件。fixed
:是指定位小数点setprecision(num)
:是指控制输出num位有效数字
原则还是和数学上相同:对第num+1位进行四舍五入
具体详细说明见以下程序,并在之后附有执行效果图:
#include<iostream>
#include<iomanip>
using namespace std;
int main(){
//默认输出6位有效数字
cout<<3.1415926535<<endl; //3.14159
//默认输出6位有效数字,如果数据过大,会使用科学计数法输出
cout<<3141592.6535897<<endl; //3.14159e+006
//输出3位有效数字
cout<<setprecision(3)<<3.1415926535<<endl; //3.14
//输出小数点后3位有效数字
cout<<fixed<<setprecision(3)<<3.1415926535<<endl; //3.142
//fixed<<setprecision(3)的作用还存在
cout<<3.1415926535<<endl; //3.142
//fixed的作用还存在
cout<<setprecision(4)<<3.1415926535<<endl; //3.1416
//清除所有与域相关,与基数相关,与浮点相关的设置
cout.unsetf(ios::adjustfield | ios::basefield | ios::floatfield) ;
//fixed作用已经取消,但是setprecision(3)的作用还存在
cout<<3.1415926535<<endl; //3.142
//重新设置成原默认设置,fixed作用已经取消
cout<<setprecision(6)<<3.1415926535<<endl; //3.14159
return 0;
}
3. C语言输入输出
基本输入输出格式 | 输入 | 输出 |
---|---|---|
符号 | scanf | printf |
int类型的输入输出 | scanf("%d",&a); | printf("%d",a); |
float类型的输入输出 | scanf("%f %f",&a, &b); | printf("%f %f",a, b); |
double类型的输入输出 | scanf("%lf",&a); | printf("%lf",a); |
注意:使用前需要导入头文件cstdio
#include<cstdio>
using namespace std;
int main(){
int a;
scanf("%d", &a); //输入并赋值给a,注意输入有符号&,输出没有
printf("a = %d\n", a); //输出a的值,并换行
float b;
scanf("%f", &b);
printf("b = %f\n", b); //输出b,默认保留小数后6位
printf("b = %.4f\n", b);//输出b,保留小数后4位
double c;
scanf("%lf", &c);
printf("c = %6.4lf\n", c);//输出c,宽度为6,保留小数后4位
long long d;
scanf("%ld", &d);
printf("d = %ld\n", d);//输出d
//也可以一起使用
printf("a = %d b = %f c = %lf d = %lld\n",a,b,c,d);
printf("a = %d b = %2.3f c = %3.4lf d = %lld\n",a,b,c,d);
return 0;
}
函数名:scanf
功 能:执行格式化输入
用 法:int scanf(char *format[,argument,...]);
scanf()函数是通用终端格式化输入函数,它从标准输入设备(键盘) 读取输入的信息。
可以读入任何固有类型的数据并自动把数值变换成适当的机内格式。
其调用格式为: scanf("<格式化字符串>",<地址表>);
scanf()函数返回成功赋值的数据项数,出错时则返回EOF
。
C++和C语言输入输出的比较
- cin和cout在DevC++中只能调用库,而其他输入输出格式要调用<stdio.h>库或库。
- cin和cout属于C++的概念,调用时涉及输入输出流,而scanf和printf属于C的概念,是C语言的标准输入/输出库中的函数,所以在时效上,scanf和printf优于cin、cout,对于大数据的输入输出,通常情况下应该用scanf、printf。
- 对于普通数据的输入输出,cin和cout比较方便,而在格式化方面,scanf和printf比较容易。cin效率比scanf低很多,尤其输入数据达到20万以上时非常明显,在100万时cin读入就会超时。
- scanf和printf也有缺点,cin和cout能够自动识别变量的数据类型,因此,在进行输入输出时,不需要指定数据类型,printf和scanf函数在输入输出时需指定数据类型。
格式表示 | 意义 |
---|---|
%c | 一个(ASCII)字符,一个汉字实际上在内存中要占据两个字符的位置。 |
%s | 一串字符,字符串。 |
%nd %ld | 一个十进制整数,n为输出占位宽度。 printf(“%12d”,a); 如a为数字8,则前面补齐11个空格, ld表示 长整型数据 |
%nx %nX | 一个十六进制整数,n为输出占位宽度。 |
%no | 一个八进制整数,n为输出占位宽度。 |
%n.mf | 单精度浮点数,n代表该浮点数的占位宽度,.m代表小数点后保留几位 a为12.2324,printf(“%.3”,a); 12.232,自动四舍五入。 |
%n.mlf | 双精度浮点数,n代表该浮点数的占位宽度,.m代表小数点后保留几位 a为12.2324,printf(“%.3”,a); 12.232,自动四舍五入。 |
%E | 输出科学计数法,12.12 输出为 1.212000E+001,只适用 float,double。 |
%p | 指针(变量的地址) |
%% | 输出时有用,表示输出一个% |
注意:格式在输入时不能有,在输出时可以有也可以没有
注意:%为变量占位符,\只在printf中使用,为特殊字符的转义字符
流操纵算子 | 作用 |
---|---|
dec | 以十进制形式输出整数 cout << hex << 12 << " " << 24; 则输出:c 18 |
hex | 以十六进制形式输出整数 |
oct | 以八进制形式输出整数 |
fixed | 以普通小数形式输出浮点数 |
scientific | 以科学计数法形式输出浮点数 |
left | 左对齐,即在宽度不足时将填充字符添加到右边 |
right | 右对齐,即在宽度不足时将填充字符添加到左边 |
setbase(b) | 设置输出整数时的进制,b=8、10 或 16 |
setw(w) | 指定输出宽度为 w 个字符,或输人字符串时读入 w 个字符 |
setfill(c) | 在指定输出宽度的情况下,输出的宽度不足时用字符 c 填充(默认情况是用空格填充) |
setprecision(n) | 设置输出浮点数的精度为 n, 在使用非fixed且非scientific 方式输出的情况下,n 即为有效数字最多的位数, 如果有效数字位数超过 n,则小数部分四舍五人,或自动变为科学计数法输出并保留一共 n 位有效数字 在使用 fixed 方式和 scientific 方式输出的情况下,n 是小数点后面应保留的位数 |
setiosflags(标志) | 将某个输出格式标志置为 1,设置输出标志 |
resetiosflags(标志) | 将某个输出格式标志置为 0,清除输出标志 |
4. 转义字符
作用:用于表示一些不能显示出来的ASCII字符
现阶段我们常用的转义字符有: \n \\ \t
转义字符 | 含义 | ASCII码值(十进制) |
---|---|---|
\a | 警报 | 007 |
\b | 退格(BS) ,将当前位置移到前一列 | 008 |
\f | 换页(FF),将当前位置移到下页开头 | 012 |
\n | 换行(LF) ,将当前位置移到下一行开头 | 010 |
\r | 回车(CR) ,将当前位置移到本行开头 | 013 |
\t | 水平制表(HT) (跳到下一个TAB位置) | 009 |
\v | 垂直制表(VT) | 011 |
\\ | 代表一个反斜线字符"\" | 092 |
' | 代表一个单引号(撇号)字符 | 039 |
" | 代表一个双引号字符 | 034 |
? | 代表一个问号 | 063 |
\0 | 数字0 | 000 |
\ddd | 8进制转义字符,d范围0~7 | 3位8进制 |
\xhh | 16进制转义字符,h范围0 ~ 9,a ~ f,A ~ F | 3位16进制 |
5. 实例练习
1.地球人口承载力估计【小学奥数7653】
假设地球上的新生资源按恒定速度增长。照此测算,地球上现有资源加上新生资源可供x亿人生活a年,或供y亿人生活b年。为了能够实现可持续发展,避免资源枯竭,地球最多能够养活多少亿人?
输入:一行,包括四个正整数 x,a,y,b,两个整数之间用单个空格隔开。x>y,a<b,ax<by,各整数均不大于10000
输出:一个实数z,表示地球最多养活z亿人,舍入到小数点后两位。
样例输入: 110 90 90 210
样例输出: 75.00
本题题解
本题目主要找到平衡点,也就是不变量来建立等式
本题目所求的是避免资源枯竭,地球最多能够养活多少亿人,也就是说在现有资源不被消耗的情况下,刚好将新增资源消耗完毕的时候,能养活多少人,也就是要求出新生资源的增长速度。
由于题目中说明新生资源按恒定速度增长,证明新生资源的增长速度是一个定量,那么我们假设该定量为 m.
又地球上现有资源加上新生资源可供x亿人生活a年,或供y亿人生活b年。
首先,现有资源一定是一个定量,新生资源由于ab的变化在发生变化,所以我们可以建立以下等式现有资源 = x*a - m*a;
现有资源 = y*b - m*b;
所以 m = (x*a-y*b)/(a-b);
所以标程(针对本题的解答程序)如下:
#include<cstdio>
int main(){
int x,a,y,b;
scanf("%d %d %d %d",&x, &a, &y, &b);
double z = 1.0*(x*a-y*b)/(a-b);
printf("%.2lf", z);
return 0;
}
2.数学中经典的"鸡兔同笼"问题,已知头共30个,脚共90只,问笼中的鸡和兔各有多少只?
解决方案一:
听我口令,所有动物,提起一只脚
听我口令,所有动物,提起第二只脚
好了,现在着地的还有90-30-30=30只脚
由于鸡只有两只脚,所以这时候的全部鸡都是跪着的,
这30只脚应当都是兔子的,每只兔子有4只脚,提起2只,还剩2只
所以兔子的数量为:30/2=15只
所以鸡的数量为30-15只
解决方案二:
差值求解
假设都为兔,则 缺少 30*4 - 90 = 30支脚
所以这 缺少的脚就是鸡, 所以鸡的数量 = 30/2=15;
兔的数量 = 30-15;
解决方案三:
列方程,设鸡 x只,兔 y只, 则
x + y = 30
2*x + 4*y = 90
解得 x = 15, y = 15
解决方案四:
循环遍历,假设 鸡兔都为0只,每次递增+1,直到满足方案三中方程的xy出现
输出结果
#include<cstdio>
int main(){
int x,y;
x = (30*4-90)/2;
y = 30-x;
printf("%d %d\n", x, y);
}
3.计算并联电阻的阻值
对于阻值为r1和r2的电阻,其并联电阻阻值公式计算如下:R = 1/(1/r1 + 1/r2)。
输入两个电阻阻抗大小,浮点型。输出并联之后的阻抗大小,结果保留小数点后2位。
输入:两个电阻阻抗大小,浮点型,以一个空格分开。
输出:并联之后的阻抗大小,结果保留小数点后2位
样例输入:1 2
样例输出:0.67
#include<cstdio>
int main(){
double r1,r2,R;
scanf("%lf%lf", &r1, &r2);
R = 1/(1/r1+1/r2);
printf("%.2lf\n", R);
}
4.海伦公式
传说古代的叙拉古国王海伦二世发现的公式,利用三角形的三条边长来求取三角形面积。已知△ABC中的三边长分别为a,b,c,求△ABC的面积。(提示:海伦公式)
#include<cstdio>
#include<cmath>
int main(){
double a, b, c, p, s;
scanf("%lf%lf%lf", &a, &b, &c);
p = (a+b+c)/2;
s = sqrt(p*(p-a)*(p-b)*(p-c));
printf("%.2lf\n", s);
}