编程竞赛宝典:C++语言和算法入门
上QQ阅读APP看书,第一时间看更新

1.2 数据类型及运算

E:\朱老师电子书\2021\PB55461-0101\tt1-web-resources\image\01C++语言入门-02_数据类型及运算.jpg

扫码看视频

编程需要用到各种类型的数据,例如整数、浮点数(包含小数)、字符串等。Dev-C++是Windows平台下的编译器,常用数据类型的字节长度和取值范围如表1.1所示。

表1.1



 

E:\朱老师电子书\2021\PB55461-0101\5546-web-resources\image\3.png

浮点数是表示小数的一种方法,简单理解就是小数点可以任意浮动的数字,例如3.14可以写成3.14×100、31.4×10-1、314×10-2等多种表现形式。而3.4×1038这种表示法也可以用科学记数法表示为3.4E+38,例如2E-2即2×10-2


 

现代数码产品使用二进制数(0和1)来存储各类数据。例如,有一张存储视频的CD,图1.13(a)所示的螺旋形轨道表示存储的视频数据,图1.13(b)所示是在显微镜下显示出来的CD表面一个个的“坑”。我们将有坑的地方表示为1,没有坑的地方表示为0,这就是CD用二进制数存储数据的原理。

E:\朱老师电子书\2021\PB55461-0101\5546-web-resources\image\0113.jpg

图1.13

位(bit)是计算机存储信息的最小单位,代表1个二进制位,其值为0或1,可以表示2种状态/2个数值;2个二进制位可以表示4个数值,即00、01、10、11;n个二进制位可以表示2n个数值。例如,短整型的字节长度为16位,可以表示216即65 536个数值,考虑到正数、负数及0的表示,所以取值范围为-32 768~32 767。


 

E:\朱老师电子书\2021\PB55461-0101\5546-web-resources\image\3.png

8个二进制位为1字节(Byte);1 024字节为1KB;1 024KB为1MB;1 024MB为1GB;1 024
GB为1TB ……


 

不同的编译器支持的各数据类型的字节长度可能不同,sizeof()可用于获取各数据类型的字节长度,例如输出各数据类型的字节长度的代码如下所示。

cout<<"int的字节长度为"<<sizeof(int)<<"\n";
cout<<"short的字节长度为"<<sizeof(short)<<"\n";
cout<<"long long的字节长度为"<<sizeof(long long)<<"\n";

C++程序用到的算术运算符如表1.2所示。

表1.2

 

E:\朱老师电子书\2021\PB55461-0101\5546-web-resources\image\3.png

C++语言以圆括号代替数学中的方括号和花括号,程序运行时将按由内到外的顺序计算圆括号里的值。例如数学表达式2×{4-[3-(2-9)]},转换成C++语言中的表达式为2*(4-(3-(2-9)))

诸如x2y2这样的表达式,转换成C++语言中的表达式为x*x+y*y


 

数学中常用xy等字符代表未知数或未定数,例如代数方程xy等。类似地,C++语言也用字符代表某个数值,其在程序运行中没有固定值、可以改变的数值称为变量。

代表变量的字符只能由字母、数字、美元符号和下划线等字符组成,且第一个字符必须为字母、下划线或美元符号。例如,可以定义变量名为_sum、abc、Day1、school_name、lotus_1_2、$sum,而Mr.Wang、234NUM、#34、a>=b、¥1234这些变量名是错误的。


 

E:\朱老师电子书\2021\PB55461-0101\5546-web-resources\image\3.png

为增加程序的可读性,应注意做到“见名知意”,即选择有含义的英文单词(或其缩写)作为变量名,例如count、total、price等,尽量少用简单的符号,例如a、b、c、u1、v1等。


 

1.2.1 求两个整数的积和平均值(calc)

【题目描述】

试编写一个程序,使得程序运行时,用键盘输入两个整数(两个整数之间以一个或多个空格间隔)后按Enter键,计算机显示器上输出这两个整数的积和平均值。

【输入格式】

输入两个整数。

【输出格式】

第一行输出两个整数相乘的完整表达式。

第二行输出平均值(仅输出整数部分),注意最后应以换行结束。

【输入样例】

5 6

【输出样例】

5*6=30

5

参考程序如下所示。

 1 /*
 2   这个程序的名字叫作求两个整数的积和平均值,它真的太强大了!好吧,
 3   这么说有点无聊,但反正是注释语句,不影响程序运行 
 4 */
 5 #include <bits/stdc++.h>
 6 using namespace std;
 7 
 8 int main()                      //这也是注释语句,不影响程序运行
 9 {
 10   int a,b,c;                    //定义变量 a、b、c,此时a、b、c的值未知
 11   cin>>a>>b;                    //输入a和b的值
 12   c=a*b;                        //计算a和b的乘积,把结果赋值给c
 13   cout<<a<<"*"<<b<<"="<<c<<endl;//输出的变量和字符串要用"<<"隔开 
 14   cout<<(a+b)/2<<endl;          //整数除整数会舍去小数部分,自动取整 
 15   return 0;
 16 }

第1~第4行中的“/*…… */”用作C++代码的多行注释,表示从“/*” 开始,到“*/”结束的这一段语句均为注释部分。

“//”用作C++代码的单行注释,表示从“//”开始,一直到本行结束的语句均为注释部分。


 

E:\朱老师电子书\2021\PB55461-0101\5546-web-resources\image\3.png

注释语句只是方便阅读代码的人更好地理解代码,编译程序时,编译器会自动忽略注释语句,它不会对程序的运行产生任何影响。


 

int a,b,c;定义了a、b、c这3个整型变量,C++语言规定变量必须要先定义才能使用。定义变量相当于向计算机内存申请“房子”,变量只有住进“房子”里才允许使用,数据类型规定的存储空间有多大,分配的“房子”就有多大。例如定义了两个变量,如图1.14所示。因为a是整型变量,所以内存给它分配了4字节的空间;因为x是超长整型变量,所以内存给它分配了8字节的空间。

E:\朱老师电子书\2021\PB55461-0101\5546-web-resources\image\0114.jpg

图1.14

可以在定义变量数据类型的同时给它赋值(初始化),例如:

int a=5;       //定义a为整型变量,初始值为5
float f=3.45;   //定义f为单精度浮点型变量,初始值为3.45

诸如int a=5;这样的语句,相当于下面两条语句:

int a;
a=5;

也可以对定义的变量的其中一部分变量赋值,例如:

int a,b,c=5;    //定义了整型变量a、b、c,其中c的初始值为5,a和b的初始值未知

注意,在程序中a、b、c之间要用逗号分隔。

如果对几个变量均赋值为5,应该写成int a=5,b=5,c=5;,而不能写成int a=b=c=5;。


 

E:\朱老师电子书\2021\PB55461-0101\5546-web-resources\image\3.png

变量数据类型的定义应视题目的要求而定,选取的数据类型的字节长度数值过大会降低运算速度、浪费内存空间,过小可能会导致数据溢出。


 

第11行是输入语句,cin表示程序运行时,用键盘输入“>>”右边的变量的值。 cin>>a>>b;表示用键盘输入两个整数。

第12行中的“=”和数学运算中用到的等号不同,它是赋值运算符,表示将右边的值赋给左边的变量,所以如果将代码写成a+b=c,程序将无法编译。

第13行中的endl代表换行,类似于换行符“\n”。


 

E:\朱老师电子书\2021\PB55461-0101\5546-web-resources\image\3.png

用键盘输入数据时,要严格按输入语句要求的格式输入。例如上例中,如果a=1,b=2,那么cin>>a>>b语句的正确输入方式应该是用英文输入法输入半角字符1 2后按Enter键,其中1和2之间以一个或多个空格分隔,但不能是其他符号。如果用键盘输入a=1,b=2,或者1,2之类的均是错误的。

输入/输出语句应严格按照格式编写,例如不能写成cin>>a,b,c或者cout<<a+b=c等。输入/输出的各变量之间应使用“>>”或“<<”分隔。


 

1.2.2 3个浮点数相加(add2)

【题目描述】

输入3个双精度类型的浮点数,计算3个浮点数相加的和。

【输入格式】

输入3个浮点数(整数部分不超过2位,小数部分不超过3位)。

【输出格式】

输出3个浮点数相加的和,注意最后应以换行结束。

【输入样例】

1.2 3.2 1

【输出样例】

5.4

浮点数在内存中是用有限的存储单元存储的,所以能提供的有效数字总是有限的,在有效位以外的数字将会被舍去,由此可能会产生一些误差。

下面的程序演示了浮点数的舍入误差。

 1 //浮点数的舍入误差演示
 2 #include <bits/stdc++.h>
 3 using namespace std;
 4
 5 int main()
 6 {
 7   float a=2345678900.001;         //定义一个很大的浮点数
 8   float b=3;                      //定义一个很小的浮点数
 9   cout<<fixed<<a<<endl;           //fixed表示可禁止以科学记数法形式输出
 10   float c=a+b;
 11   cout<<c<<endl;
 12   return 0;
 13 }

输出结果如图1.15所示。

E:\朱老师电子书\2021\PB55461-0101\5546-web-resources\image\0115.jpg

图1.15

可以看到,两个浮点数相加后的结果没有变化,这是由于单精度浮点型的精度为6~7位有效数字,后面的数字被忽略,并不能准确地表示该数。例如定义float f=3456.12345;,当运行cout<<f语句输出f时,结果为3456.12。

所以在使用浮点数时要避免因浮点数运算产生的误差而导致结果错误。例如,应避免将一个很大的浮点数和一个很小的数直接运算,否则会“丢失”小的数。

1.2.3 捡石头(stone)

【题目描述】

小光捡了3块石头,这3块石头的质量的输入在代码中用cin语句实现,他想再捡一块石头,让这4块石头的质量正好为30千克,请编程用cout语句输出第4块石头的质量。

【输入格式】

输入3个数,数与数之间以空格间隔,表示3块石头的质量。

【输出格式】

输出一个数,表示第4块石头的质量,注意最后应以换行结束。

【输入样例】

1 1 1

【输出样例】

27

1.2.4 简单解方程(equation)

【题目描述】

S=(a+b) / 2,给定aS的值,求b的值。

【输入格式】

输入两个整数aS-1\, 000 \leqslant aS \leqslant 1\, 000)。

【输出格式】

输出一个整数b

【输入样例】

4 3

【输出样例】

2

1.2.5 计算多项式的值(cal)

【题目描述】

试计算多项式y=ax3+bx2+cx+d的值,其中abcdx的值由键盘输入。

【输入格式】

输入5个整数,分别代表abcdx的值。

【输出格式】

输出一个整数,即多项式的值,注意输出最后应以换行结束。

【输入样例】

3 4 5 6 5

【输出样例】

506

E:朱老师电子书021PB55461-0101546-web-resourcesimage.png


 

初学者容易将表达式ax3+bx2+cx+d写成ax^3+bx^2+cx+d这样的错误形式,其正确形式应该为a*x*x*x+b*x*x+c*x+d

程序写好后,试输入1999 1999 1999 1999 1999,观察输出结果有什么异常。


 

每种类型的数据都有各自的取值范围,请务必确保所定义的数据不超过该类型数据的取值范围,否则会造成数据的溢出而导致结果错误。数据的溢出在编译和运行程序时并不报错,完全要靠编程者的细心和经验来保证结果的正确性。

下面的程序显示了整型数据溢出的错误。

 1 //整型数据的溢出
 2 #include <bits/stdc++.h>
 3 using namespace std;
 4 
 5 int main()
 6 {
 7   int a=2147483647;
 8   a=a+1;
 9   cout<<"a="<<a<<endl;                    //输出a=-2147483648
10   return 0;
11 }

1.2.6 混合运算(cal2)

【题目描述】

试编程用键盘输入a、b、c、d、e的值后计算图1.16所示的算式的值。

\frac{a b+a c}{b+\frac{c}{d-e}}

图1.16

【输入格式】

输入5个双精度浮点数,分别为a、b、c、d、e的值。

【输出格式】

输出混合运算的结果。

【输入样例】

2.1 2.2 2.3 2.4 2.5

【输出样例】

-0.454327

如表1.3所示,如果程序中定义的某个数据类型的值永远不可能出现负数时,可以使用unsigned将其定义为无符号的数据类型,这样就使正整数的取值范围大约比原先扩大了一倍。

表1.3

1.2.7 两个整数相乘(mul)

【题目描述】

使用cin语句输入两个整数ab,计算两个整数的乘积并输出。

【输入格式】

输入两个整数ab1 \leqslant ab \leqslant 4\, 000\, 000\, 000)。

【输出格式】

输出两个整数的乘积。

【输入样例】

100 10

【输出样例】

1000

1.2.8 巨型人造天体(aster)

【题目描述】

制造巨型人造天体需要A部件和B部件,其质量分别为2 012 345 678克、1 912 345 678克。

(1)试计算这两种部件的质量之和的最后4位数。

(2)试计算12 345 678个A部件的总质量的最后4位数。

【输入格式】

无输入。

【输出格式】

输出两行,第一行为两种部件的质量之和的最后4位数,第二行为12 345 678个A部件的总质量的最后4位数。

E:\朱老师电子书\2021\PB55461-0101\tt1-web-resources\image\0116.jpg

使用“内容市场”
App扫描看视频

【输入样例】

略。

【输出样例】

略。

【算法分析】

提示:(a+b)%c=(a%c+b%c)%c,(a*b)%c=(a%c*b%c)%c

与变量相对应,在程序运行中,值不能被改变的数值称为常量,常量使用关键字const标识,例如:

const int num=34;   //定义num为整型常量,值为34

const float pi=3.1415;//定义pi为单精度浮点型常量,值为3.1415

程序运行时,常量的值不能被更改。下面是一个试图改变常量a的错误程序,程序编译会出现“assignment of read-only variable ' a ' ”的错误,即只读变量'a'的赋值错误。

 1 //试图改变常量a的错误程序
 2 #include <bits/stdc++.h>
 3 using namespace std;
 4 
 5 int main()
 6 {
 7   const int a=34;                 //定义了一个整型常量a,a的值为34
 8   a=a*5;                          //试图将a乘以5后再将其值赋给a
 9   cout<<a<<endl; 
10   return 0;
11 }

也可以用预处理指令#define定义常量的值,例如下面的程序中用#define定义PRICE代表数值34,此后凡是在该程序中出现的PRICE都代表34。常量名一般用大写字母表示,可以和变量一样运算。

 1 //预处理指令定义常量
 2 #include <bits/stdc++.h>
 3 using namespace std;
 4 #define PRICE 34     //定义PRICE为一个常量,值为34,注意末尾无分号
 5 
 6 int main()
 7 {
 8   int num=10;
 9   int total=num*PRICE;                     //PRICE会替换为34来运算
10   cout<<"total="<<total<<endl;             //输出结果为total=340
11   return 0;
12 }

 

E:朱老师电子书021PB55461-0101546-web-resourcesimage.png

定义常量的好处是含义清晰,而且在需要改变常量值时能做到“一改全改”。例如,将#define PRICE 34改为#define PRICE 100,则程序中所有用到PRICE的地方就全部由34变成100而无须一个一个修改。