3.3 使用变量
微视频
变量是指在程序运行过程中其值可以改变的量。在程序定义变量时,编译系统就会给它分配相应的存储单元,用来存储数据。变量的名称就是该存储单元的符号地址。
3.3.1 认识变量
在C++程序设计中,变量用于存储程序中可以改变的数据。形象地讲,变量就像一个存放东西的抽屉,知道了抽屉的名字(变量名),也就能找到抽屉的位置(变量的存储单元)及抽屉里的东西(变量的值)。当然,抽屉里存放的东西是可以改变的。也就是说,变量值也是可以变化的。
从上面的叙述不难看出,变量具有以下4个基本属性。
(1)变量名:一个符合规则的标识符。
(2)变量类型:C++语言中的数据类型或者是自定义的数据类型。
(3)变量位置:数据的存储空间位置。
(4)变量值:数据存储空间内存放的值。
程序编译时,会给每个变量分配存储空间和位置。程序读取数据的过程,其实就是根据变量名查找内存中相应的存储空间,从其内取值的过程。
【实例3.10】编写程序,使用变量输出偶数2和4,再输出大写字母A和B(源代码\ ch03\3.10.txt)。
#include <iostream> using namespace std; int main() { int i=2; /*定义一个变量i并赋初值*/ char y='A'; /*定义一个char类型的变量y并赋初值*/ cout<<"第1次输出偶数i="<<i<<endl; /*输出变量i的值*/ i=4; /*给变量i赋值*/ cout<<"第2次输出偶数i="<<i<<endl; /*输出变量i的值*/ cout<<"第1次输出大写字母y="<<y<<endl; /*输出变量y的值*/ y='B'; /*给变量y赋值*/ cout<<"第2次输出大写字母y="<<y<<endl; /*输出变量y的值*/ }
程序运行结果如图3-10所示。从输出结果可以看出,变量i和y的值两次输出不一样。在本实例代码中变量i和y是先进行定义的,而且变量i和y都进行了两次赋值。可见,变量在程序运行中是可以改变它的值的。第5行和第7行是给变量赋初值的两种方式,是变量的初始化。
图3-10 例3.10的程序运行结果
☆大牛提醒☆
变量的名称可以由字母、数字和下画线字符组成,它必须以字母或下画线开头;大写字母和小写字母是不同的,因为C++语言中字母的大小写是有区别的。
3.3.2 变量的声明
变量声明的作用是向编译器保证变量以指定的类型和名称存在,这样编译器在不需要知道变量完整细节的情况下也能继续进一步的编译。变量的声明有以下两种情况。
情况1:需要建立存储空间。例如,int a在声明的时候就已经建立了存储空间。
情况2:不需要建立存储空间,通过使用extern关键字声明变量名而不定义它。例如,extern int a,其中变量a可以在其他文件中定义。
变量的声明包括变量类型和变量名两个部分,其语法格式如下:
变量类型 变量名
例如int num;double area;char c;等语句都是变量的声明。在这些语句中,int、double和char是变量类型,num、area和c是变量名。这里的变量类型也是数据类型的一种,即变量num为int类型、变量area为double类型、变量c为char类型。
变量类型可以是C++语言自带的数据类型和用户自定义的数据类型。C++语言自带的数据类型包括整型、字符型、浮点型、枚举型、指针类型、数组、引用、数据结构、类等。
【实例3.11】编写程序,在程序头部声明变量,从而计算两数之和。这里变量的定义与初始化在主函数内(源代码\ch03\3.11.txt)。
#include <iostream> using namespace std; //函数外定义变量x和y int x; int y; int addtwonum() { //函数内声明变量x和y为外部变量 extern int x; extern int y; //给外部变量(全局变量)x和y赋值 x =105; y =106; return x+y; } int main() { int result; //调用函数 addtwonum result = addtwonum(); cout<<"105+106="<<result<<endl; }
程序运行结果如图3-11所示。从输出结果可以看出,变量x和y相加后的值为“211”。
图3-11 例3.11的程序运行结果
变量名其实就是一个标识符。当然,标识符的命名规则在此处同样适用。因此,变量命名时需要注意以下几点:
● 命名时应注意区分大小写,并且尽量避免使用大小写上有区别的变量名。
● 不建议使用以下画线开头的变量名,因为此类名称通常是保留给内部和系统命名用的。
● 不能使用C++语言关键字或预定义标识符作为变量名。如int、define等。
● 避免使用类似的变量名。如total、totals、total1等。
● 变量的命名最好具有一定的实际意义。如sum一般表示求和,area表示面积。
● 变量的命名需放在变量使用前。
☆大牛提醒☆
如果变量没有经过声明而直接使用,则会出现编译器报错的现象。
3.3.3 变量的赋值
既然变量的值可以在程序中随时改变,那么变量必然可以多次赋值。变量除了通过赋值的方式获得值外,还可以通过初始化的方式获得值。把第一次的赋值行为称为变量的初始化。也可以这么说,变量的初始化是赋值的特殊形式。
下面给出几个变量赋值的语句。
int i; double f; char a; i=10; f=3.4; a='b';
在以上语句中,前3行是对变量的定义;后3行是对变量赋值,将10赋给int类型的变量i,将3.4赋给double类型的变量f,将字符'b'赋给char类型的变量a。后3行都是使用的赋值表达式。
从以上语句不难得出,对变量赋值的语法格式如下:
变量名=变量值;
对变量的初始化语法格式如下:
变量类型 变量名=初始值;
其中,变量必须在赋值前进行定义。符号“=”称为赋值运算符,而不是等号。它表示将其后边的值放入以变量名命名的变量中。变量值可以是一个常量或一个表达式。例如:
int i=5; int j=i; double f=2.5+1.8; char a='b'; int x=y+2;
更进一步讲,赋值语句不仅可以给一个变量赋值,还可以给多个变量赋值。语法格式如下:
类型变量名 变量名1=初始值1,变量名2=初始值2,…;
例如:
int i=8,j=10,m=12;
上面的代码分别给变量i、变量j、变量m赋值为8、10、12,相当于执行以下语句。
int i,j,m; i=8; j=10; m=12;
☆大牛提醒☆
变量的定义就是指让内存给变量分配内存空间。在分配好内存空间且程序尚没有运行前,变量会被分配一个不可知的混乱值。如果程序中没有对其进行赋值就使用,势必会引起不可预期的结果。因此,使用变量前,务必要对其初始化,而且只有变量的数据类型相同时,才可以在一个语句中进行初始化。
【实例3.12】编写程序,通过给变量赋值,计算奇数3与5的和(源代码\ch03\3.12.txt)。
#include <iostream> using namespace std; int main() { int a=3,b=5,c; c=a+b; cout<<"a="<<a<<endl; cout<<"b="<<b<<endl; cout<<"c="<<c<<endl; }
程序运行结果如图3-12所示。
图3-12 例3.12的程序运行结果
☆大牛提醒☆
在赋值的过程中,我们一定要注意C++中的左值和右值。
● 左值(lvalue):指向内存位置的表达式被称为左值表达式。左值可以出现在赋值号的左边或右边。
● 右值(rvalue):存储在内存中某些地址的数值被称为右值。右值是不能对其进行赋值的表达式,也就是说,右值可以出现在赋值号的右边,但不可以出现在赋值号的左边。
变量是左值,因此可以出现在赋值号的左边。数值型的字面值是右值,不能被赋值,因此不能出现在赋值号的左边。例如,下面语句是一条有效的语句。
int g=20;
但下面的语句就不是一条有效的语句,会产生编译错误。
10=20;
3.3.4 变量的作用域
变量按其作用域可分为局部变量和全局变量。全局变量在整个工程文件内都有效,静态全局变量只在定义它的文件内有效。局部变量在定义它的函数内有效,当函数返回后失效,静态局部变量只在定义它的函数内有效,只是程序仅分配一次内存,函数返回后该变量不会消失,只有程序结束后才释放内存。
1.局部变量
局部变量也称为内部变量,它是在函数内做定义、声明的变量。其作用域仅限于函数内,离开该函数后再使用这种变量是非法的。例如下面的代码段:
int fun(int a) /*函数fun()为a,b,c的作用域*/ { int b,c; } main() /*主函数main()为x,y的作用域*/ { int x,y; }
从上述代码可以看出,在函数fun()内定义了3个变量a、b、c,在该函数范围内变量a、b、c有效,或者说变量a、b、c的作用域限于函数fun()内。同理,变量x、y的作用域限于函数main()内。
☆大牛提醒☆
局部变量只有局部作用域,它在程序运行期间不是一直存在,而是只在函数执行期间存在。函数的一次调用执行结束后,变量被撤销,其所占用的内存也被收回。
2.全局变量
全局变量也称为外部变量,它是在函数外部定义的变量。全局变量不是属于哪一个函数,而是属于一个源程序文件,其作用域是整个源程序。在函数内使用全局变量,一般应做全局变量。也就是说,只有在函数内经过声明的全局变量才能使用。全局变量具有全局作用域,只需在一个源文件中定义,就可以作用于所有的源文件。当然,其他不包含全局变量定义的源文件需要用extern关键字再次声明这个全局变量。
例如下面的代码段:
int a,b; /*外部变量*/ void fun1() /*函数fun1()*/ {…} float c,d; /*外部变量*/ int fun2() /*函数fun2()*/ {…} main() /*主函数*/ {…} /*全局变量a,b,c,d的作用域*/
从上述代码可以看出,a、b、c、d是在函数外部定义的变量,都是全局变量。但变量c、d定义在函数fun1()后面, fun1()内又没有对变量c、d加以声明,所以它们在函数fun1()内无效。而变量a、b定义在源程序最前面,因此在函数fun1()、函数fun2()及函数main()内不加声明也可以使用。
☆大牛提醒☆
初始化局部变量和全局变量。当局部变量被定义时,系统不会对其初始化,用户必须自行对其初始化。而当定义全局变量时,系统会自动将其初始化为如表3-3中所示的值。
表3-3 全局变量的系统自动初始化值
正确地初始化变量是一种良好的编程习惯,否则有时候程序可能会产生意想不到的结果。
【实例3.13】编写程序,定义全局变量,然后为全局变量输入长方体的长、宽、高,最后求出长方体的体积及3个不同面的面积(源代码\ch03\3.13.txt)。
#include <iostream> using namespace std; int ar1,ar2,ar3; /*定义全局变量*/ int vol(int a,int b,int c) /*定义全局变量*/ {int v; v=a*b*c; /*计算长方体的体积*/ ar1=a*b; /*计算长方体第1个面的面积*/ ar2=b*c; /*计算长方体第2个面的面积*/ ar3=a*c; /*计算长方体第3个面的面积*/ return v; /*返回长方体的体积*/ } int main() /*定义主函数*/ {int v,l,w,h; /*定义变量*/ cout<<"输入长方体的长、宽和高"<<endl; /*提示输入长方体的长、宽和高*/ cin>>l>>w>>h; /*输入长方体的长、宽和高*/ v=vol(l,w,h); /*计算长方体的体积*/ cout<<"v="<<v<<endl; /*输出长方体的体积v*/ cout<<"s1="<< ar1<<endl; /*输出长方体s1面的面积*/ cout<<"s2="<< ar2<<endl; /*输出长方体s2面的面积*/ cout<<"s3="<< ar3<<endl; /*输出长方体s3面的面积*/ }
程序运行结果如图3-13所示。根据提示输入长、宽、高,按Enter键,即可计算出长方体的体积与面积。在本实例中,定义了全局变量ar1、ar2、ar3用来存放3个面积,其作用域为整个程序;函数vol()用来求长方体的体积和3个面积,函数的返回值为体积v;主函数main()用来完成长、宽、高的输入及结果输出。
图3-13 例3.13的程序运行结果
☆大牛提醒☆
C++语言规定函数返回值只有一个,当需要增加函数的返回数据时,用全局变量是一种很好的方式。本例中,若不使用全局变量,在主函数中就不可能取得v、ar1、ar2、ar3这4个值。而采用了全局变量,在函数vol()中求得的ar1、ar2、ar3在函数main()中仍然有效。可见,全局变量是实现函数之间数据通信的有效手段。
3.3.5 整型变量
在现实生活中,整数是最常用的计数描述形式,而在C++中则用整型来描述整数。整型规定了整数的表示形式、运算和表示范围。
在C++中,整型数据类型是用关键字int声明的常量或变量,其值只能为整数。根据unsigned、signed、short和long等修饰符,整型数据类型可分为4种,分别对应为无符号整型、有符号整型、短整型和长整型。整型变量的声明格式如下:
[修饰符] <int> <变量名>
每种整型变量都有不同的表示方式和取值范围,表3-4列出了每种整型变量的取值范围。
表3-4 整型变量的取值范围
下面通过一个实例来说明int类型和short int类型的使用方法。
【实例3.14】编写程序,定义整型变量a和短整型变量b,然后依次输出两变量的值和变量所占内存空间的大小(源代码\ch03\3.14.txt)。
#include <iostream> using namespace std; int main() { int a; //定义整型变量 a=100; //为变量a赋初值 cout<<"a="<<a<<endl; //输出a的值 cout<<"size a "<<sizeof(a)<<endl; short int b=100.01; //为变量b赋初值 cout<<"b="<<b<<endl; //输出b的值 cout<<"size b "<<sizeof(b)<<endl; }
程序运行结果如图3-14所示。在本实例中,首先定义了一个整型变量a,给该变量赋值为100,输出该变量的值和该变量所占内存空间的大小;接着又定义了一个短整型变量b,给该变量赋值为100.01,然后输出该变量的值和该变量占内存空间的大小。
图3-14 例3.14的程序运行结果
从运行结果可以看出,用int类型实现了定义整型变量的操作,用short int类型实现了定义短整型变量的操作。而整型变量与短整型变量的区别在于,它们的取值范围不同。
注意:整型数据在溢出后不会报错,达到最大值后又从最小值开始记。在编程时,注意定义变量的最大取值范围,且使用时一定不要超过这个取值范围。
3.3.6 实型变量
实型变量也称为浮点型变量,是指用来存储实型数据的变量,其由整数和小数两部分组成。在C++中,实型变量根据精度的不同,可以分为单精度类型、双精度类型和长双精度类型,如表3-5所示。
表3-5 实型变量的分类
1.单精度浮点型
单精度浮点型(float)专指占用32位存储空间的单精度值。当用户需要小数部分且对精度的要求不高时,单精度浮点型的变量是有用的。下面是一个声明单精度浮点型变量的例子。
float a,b;
2.双精度浮点型
双精度浮点型(double)占用64位的存储空间。当用户需要保持多次反复迭代计算的精确性时,或在操作很大的数据时,双精度型是最好的选择。例如,计算圆面积,声明的常量和变量均为双精度型。代码如下:
double radius,area;
3.长双精度浮点型
长双精度浮点型(long double)占用80、96或者128位存储空间。“精度”是指尾数中的位数。通常,float类型提供7位精度,double类型提供15位精度,long double类型提供19位精度,但double类型和long double类型在几个编译器上的精度是相同的。除了精度有所增加外,double类型和long double类型的取值范围也在扩大。下面通过一个实例来说明实型变量的应用。
【实例3.15】编写程序,定义浮点型变量,然后给变量赋值,最后输出变量的值(源代码\ ch03\3.15.txt)。
#include <iostream> #include <iomanip> using namespace std; int main() { float a; //定义浮点型变量 double b; //定义浮点型变量 a=3.1415926; //为变量赋初值 b=3.1415926; cout<<"a="<<a<<endl; //输出变量的值 cout<<"b="<<b<<endl; cout<<"b="<<setprecision(9)<<b<<endl; }
程序运行结果如图3-15所示。在本实例中,首先定义了一个float类型的变量a,又定义了一个double类型的变量b,给变量a和变量b赋值为3.1415926,然后将a和b输出,再调用setprecision()函数保留9位小数输出b。
图3-15 例3.15的程序运行结果
从运行结果来看,无论定义的变量是单精度数据类型还是双精度数据类型,其输出的小数位都相同,这是因为没有设置输出精度,系统默认输出6位小数(包括小数点)。如果需要double型变量输出更多的小数位,则应用设置精度函数。
3.3.7 字符型变量
在C++中,字符型数据类型只占据1个字节,其声明关键字为char。同样地,可以给其加上unsigned、signed修饰符,分别表示无符号字符型和有符号字符型。字符型变量的声明格式如下:
[修饰符] <char> <变量名>
在ASCII码表中,共有127个字符。其中编码1~31和编码127的字符为不可见字符,其余全部为可见字符。
字符型是为针对处理ASCII码字符而设的,在表示方式和处理方式上与整数吻合,在表示范围上为整数的子集,其运算可以参与到整数中,只要不超过整数的取值范围。
注意:计算机不能直接存储字符,所以所有字符都是用数字编码来表示和处理的。例如字母a的ASCII码值是97,字母A的ASCII码值是65。如果一个字符被当成整数使用,则其值就是对应的ASCII码值;如果一个整数被当成字符使用,则该字符就是这个整数在ASCII码表中对应的字符。
通常,单个字符使用单引号表示,例如字符a可以写为'a'。如果字符的个数大于1,那么就变成了字符串,只能使用双引号来表示。下面通过一个实例来说明字符型变量的使用方法。
【实例3.16】编写程序,定义字符型变量,然后给变量赋值,最后输出字符变量的值(源代码\ch03\3.16.txt)。
#include <iostream> using namespace std; int main() { char cch; //定义字符型变量 cch='B'; //为变量赋值 cout<<"cch="<<cch<<endl; int ich; //定义整型变量 ich='B'; //为变量赋值 cout<<"ich="<<ich<<endl; }
程序运行结果如图3-16所示。在本实例中,首先定义了一个char型变量cch,其后给cch赋值为'B',将字符变量cch输出,又定义了一个int型变量ich,给它赋值也是'B',然后将该变量输出。
图3-16 例3.16的程序运行结果
从运行结果来看,定义了字符型变量cch和整型变量ich,给它们赋值都为字符'B',输出后结果却不同,整型变量ich的输出值为66。这是因为字符型数据在计算机内部是转换为整型数据来操作的,如上述代码中的字母B,系统会自动将其转换为对应的ASCII码值66。
3.3.8 布尔型变量
布尔(bool)类型在C++中表示真假,其直接常量只有两个:true和false,分别表示逻辑真和逻辑假。要把一个整型变量转换成布尔型变量,其对应关系为:如果整型值为0,则其布尔型值为假(false);如果整型值为1,则其布尔型值为真(true)。布尔型输出形式可以选择,默认为整数1和0,如果要输出true和false,可以使用输出控制符“d”。
下面通过一个实例来说明布尔型变量的使用方法。
【实例3.17】编写程序,定义布尔型变量,然后给变量赋值,最后输出布尔型数值(源代码\ch03\3.17.txt)。
#include <iostream> using namespace std; int main() { bool bflag; //定义布尔型变量 int iflag; //定义整型变量 bflag=true; //为变量赋值 iflag=true; cout<<"bflag="<<bflag<<endl; //输出变量的值 cout<<"iflag="<<iflag<<endl; }
程序运行结果如图3-17所示。在本实例中,首先定义了一个布尔型的变量bflag,又定义了一个整型的变量iflag,给bflag和iflag都赋值为true,然后将它们输出。
图3-17 例3.17的程序运行结果
从运行结果来看,上述程序定义了布尔型变量bflag和整型变量iflag,但输出结果并不是true,而是都输出整数值1。这是使用布尔类型数据时需要注意的。