1.3 数据类型转换
1.3 数据类型转换
1. 类型转换
自动类型转换、强制类型转换、字符型和整型的转换
- 自动类型转换
在不同数据类型的混合运算中,编译器会隐式地进行数据类型转换,称为自动类型转换。
自动类型转换遵守以下规则:
(1)若参与运算的数据类型不同,则先转换成同一类型,然后进行运算。
(2)转换按数据长度增加的方向进行,以保证精度不降低。例如int类型和long long类型运算时,先把int转换为long long后再运算。
(3)在赋值运算中,赋值号两边的数据类型不一样时,将把右面表达式的类型转换为左边变量的类型。如果右边表达式的数据类型长度比左边的长时,将丢失一部分数据。
即:char -->short -->int --> float -->double
#include<iostream>
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;
}
- 强制类型转换
当自动类型转换不能实现目的时,可以显示的进行类型转换,称为强制类型转换。
强制类型转换的一般形式是: (类型名)(表达式) (类型名)变量
如(double)a 是将a转换为double型,
(int)(x + y) 是将 x+y 的值转换为整型,
(float)5/3 是将 5 的值转换成float型,再与 3 运算。
double为双精度浮点型,float为单精度浮点型,区别在于他们的精度不同。
#include<iostream>
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;
}
- 字符型和整型的转换
将一个字符放到内存单元时,实际上并不是把该字符本身放到内存中,而是将该字符的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 对象"连接"到标准输出设备,通常是显示屏。
浮点数输出格式控制
浮点数也就是小数,同理还存在定点数,也就是我们说的整数。
当我们要输出 :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("%n.mlf",a); |
char | scanf("%c",&a); | printf("%c",a); |
char* / char[] | scanf("%s",a); | printf("%s",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 | 以十进制形式输出整数 |
hex | 以十六进制形式输出整数 cout << hex << 12 << " " << 24; 则输出:c 18 |
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. 实例练习
B2006 地球人口承载力估计
题目描述
假设地球上的新生资源按恒定速度增长。照此测算,地球上现有资源加上新生资源可供 \(x\) 亿人生活 \(a\) 年,或供 \(y\) 亿人生活 \(b\) 年。
为了能够实现可持续发展,避免资源枯竭,地球最多能够养活多少亿人?
输入格式: 一行,包括四个正整数 \(x, a, y, b\),两个整数之间用单个空格隔开。
输出格式: 一个实数 \(z\),表示地球最多养活 \(z\) 亿人,舍入到小数点后两位。
样例输入 #1
110 90 90 210
样例输出 #1
75.00
提示: 对于 \(100 \%\) 的数据,\(1 \le x, a, y, b \le {10}^4\),\(x > y\),\(a < b\),\(a x < b y\)。
分析
本题目主要找到平衡点,也就是不变量来建立等式
本题目所求的是避免资源枯竭,地球最多能够养活多少亿人,也就是说在现有资源不被消耗的情况下,刚好将新增资源消耗完毕,能养活多少人。
由于新生资源按恒定速度增长,那么我们假设该增长速度为 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;
}
鸡兔同笼
数学中经典的"鸡兔同笼"问题,已知头共 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);
}
B2015 计算并联电阻的阻值
题目描述
对于阻值为 \(r1\) 和 \(r2\) 的电阻,其并联电阻阻值公式计算如下:\(R=1/(1/r1+1/r2)\)。
输入格式: 输入两个电阻阻抗大小,浮点型,以一个空格分开。
输出格式: 输出并联之后的阻抗大小,结果保留小数点后 \(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);
}