c语言第2章数据类型运算符和表达式.ppt
第2章 数据类型、运算符与表达式,林淑玲,C语言,知识目标:掌握C语言的数据类型;深刻理解常量与变量;深刻理解整型、实型和字符型数据常量和变量的表示方法;掌握赋值运算符和赋值表达式、变量的赋值方法;理解各种数据类型之间的混合运算。能力目标:能正确定义“班级学生成绩管理系统”中的相关数据的类型。,第2章 数据类型、运算符与表达式,内容提要,基本数据类型;常量和变量;标识符命名;常用运算符和表达式;运算符的优先级与结合性,一个简单的C程序例子,#include/*函数功能:计算两个整数相加之和 入口参数:整型数据a和b 返回值:整型数a和b之和*/int Add(int a,int b)return(a+b);/*主函数*/main()int x,y,sum=0;printf(Input two integers:);scanf(%d%d,/*输出x和y相加之和*/,简单的C语言程序总结,总结C程序:(1)C程序是由函数构成的。这使得程序容易实现模块化。(2)一个函数由两部分组成:函数的首部:例2.1中的Add函数首部 int Add(int a,int b)函数体:花括号内的部分。若一个函数有多个花括号,则最外层的一对花括号为函数体的范围。函数体包括两部分:声明部分:int x,y,sum=0;可缺省执行部分:由若干个语句组成。可缺省,简单的C语言程序总结,(3)C程序是由函数构成的。总是从main函数开始执行的,与main函数的位置无关。(4)C程序书写格式自由,一行内可以写几个语句,一个语句可以分写在多行上,C程序没有行号。(5)每个语句和数据声明的最后必须有一个分号。(6)C语言本身没有输入输出语句。输入和输出的操作是由库函数scanf和printf等函数来完成的。(7)可以用/*/进行注释。,源程序的结构特点,1.一个语言源程序可以由一个或多个源文件组成。2.每个源文件可由一个或多个函数组成。3.一个源程序不论由多少个文件组成,都有一个且只能有一个main函数,即主函数。4.源程序中可以有预处理命令(include 命令仅为其中的一种),预处理命令通常应放在源文件或源程序的最前面。5.每一个说明,每一个语句都必须以分号结尾。但预处理命令,函数头和花括号“”之后不能加分号。6.标识符,关键字之间必须至少加一个空格以示间隔。若已有明显的间隔符,也可不再加空格来间隔。7.C语言程序中可加任意多的注释。通常情况下,“/”注释一行,“/*/”注释中间的所有内容。注释不参加编译,因此不进行错误查找处理。8.用户定义的变量或函数等其他的量必须先定义后使用。,书写程序时应遵循的规则,C语言程序书写中应当注意的问题(1)用分号作为语句的结束符,不可省略(即便是最后一个语句也不能省略)。3种不能加分号的情况:预处理命令后、定义函数名称(函数头)后、花括号()之后。(2)第一行是预处理命令行,其中的指令必须以符号“#”开始,所指定的头文件也必须用引号或尖括号标识。例如,#include stdio.h 或#include。(3)主函数main()后的括号不能缺省。,书写程序时应遵循的规则,编码风格1)源程序通常使用小写字母,只有符号常量或其他特殊用途的符号才大写。2)C语言可以一个语句占一行,也可多个语句占一行。但后者不规范,所以并不提倡。3)程序代码采用缩进格式。4)建议同一层次的语句应左对齐。5)用花括号对()表示各个结构层次的范围。它可以表示函数,也可以表示循环体等,书写程序时应遵循的规则,6)一个语句中不同成分之间应使用空格隔开。标识符、关键字之间必须至少加一个空格以示间隔。若已有明显的间隔符,也可以不再加空格来间隔。7)程序中的空白行不影响程序的执行。可以为使程序清晰而添加空行,但不要在一个语句中间加空行。8)建议使用注释语句,以增加程序的可读性。9)程序块的分界符(即花括号“”和“”)应各独占一行并且位于同一列,同时与引用它们的语句左对齐。,C程序常见符号分类,关键字(Keyword)又称为保留字,C语言中预先规定的具有固定含义的一些单词 标识符(Identifier)系统预定义标识符用户自定义标识符 运算符(Operator)34种,详见附录2 分隔符(Separator)空格、回车/换行、逗号等 其它符号 大花括号“”和“”通常用于标识函数体或者一个语句块“/*”和“*/”是程序注释所需的定界符 数据(Data)变量(Variable)常量(Constant),任务1“学生成绩管理系统”中相关数据设计,1任务情境“学生成绩管理系统”中的数据有常量与变量、简单类型数据和复杂类型数据。这些变量有简单类型变量,还有一些复杂类型变量,如数组、结构体、共用体、指针类型等变量。在这里我们只对“学生成绩管理系统”中的数据做一些简单的分析。“学生成绩管理系统”中的学生信息主要有:学号、性别、年龄、三门功课成绩、总成绩和平均成绩,再加上一些与计算全班成绩有关的最高成绩、最低成绩等。如学号、性别这类数据只是起到描述一些基本信息的作用,通常情况下不进行算术运算;而年龄、三门功课成绩、总成绩和平均成绩以及最高成绩、最低成绩等这类数据有可能进行算术运算。所以针对这二类数据我们在定义数据类型时,要根据实际情况选择不同的数据类型。下面我们通过相关理论的学习,掌握如何将“学生成绩管理系统”中的数据定义成C语言能够处理的数据。,2知识必备,数据类型常量变量,数据类型(Data Type),数据为什么要区分类型?不同类型的数据代表不同的数据表示形式合法的取值范围占用内存空间大小可参与的运算种类 从基本数据类型到抽象数据类型无数据类型基本数据类型 构造数据类型 抽象数据类型,数据类型(Data Type),标识符命名,变量名函数名由英文字母、数字和下划线组成,大小写敏感不可以是数字开头直观,见名知意,便于记忆和阅读最好使用英文单词或其组合切忌使用汉语拼音 下划线和大小写通常用来增强可读性variablenamevariable_nameVariableName,variableName不允许使用关键字作为标识符的名字 int,float,for,while,if等某些功能的变量采用习惯命名如:for语句所采用的循环变量习惯用i,j,k,Windows 风格,UNIX 风格,b,B,KB,MB,GB,TB,Megabyte(MB),中文叫法:兆Kilobyte(KB),中文叫法:KByte,中文叫法:字节bit,中文叫法:位Gigabyte(GB),中文叫法:GTerabyte(TB),中文叫法:T,1 TB=1,024 GB,1 GB=1,024 MB,1 MB=1,024 KB,1 KB=1,024 B,1 B=8 b,b,B,KB,MB,GB,TB,一个位有多大?只能是“0”或者“1”,这叫二进制一个字节有多大?保存一个字符(英文字母、数字、符号)ASCII(美国标准信息交换码)编码两个字节保存一个汉字GB编码可以表示数字0255,基本数据类型,int整数,在目前绝大多数机器上占4个字节。TC2中是2个字节float单精度浮点数,一般是4个字节长double双精度浮点数,一般是8个字节长char字符,一般是1个字节长用来表示256个ASCII字符,或者0255的整数,数据类型修饰符,shortshort int,短整数,一般2个字节长。通常简写为shortlonglong int,长整数,一般是4个字节长。通常简写为longlong double,长双精度(高精度)浮点数,一般是10个字节长。signed用来修饰char、int、short和long,说明他们是有符号的整数(正整数、0和负整数)。一般缺省都是有符号的,所以这个修饰符通常省略unsigned用来修饰char、int、short和long,说明他们是无符号的整数(正整数和0),假设编译系统为 int 型整数分配 2 个字节的存储空间,即 16 个二进制位中最高位是符号位,以 32767 为例,其在内存中的存储形式为:,有符号数与无符号数,若是无符号数,该数是 65535,若是有符号数,该数是-1。,-1 的原码,-1 的反码,-1 的反码加 1 后的结果,-1 的补码,TC2中int的范围是-3276832767如果我们给它一个小于-32768或者大于32767的数会如何呢?现场演示,小蛇能吞下大象吗?,超出取值范围会怎样?,一台安装了Windows 95/98的机器,如果连续运行49.7天没有重新启动,可能死机 原因:Windows自启动时刻起,有一个计数器,记录系统已经运行了多少毫秒。这个计数器是个unsigned long 类型的变量unsigned long 的最大值是:4294967295一天有 24*60*60*1000=86400000毫秒4294967295/86400000=49.71026961805当49.7天的时候,此计数器会溢出,引起死机,溢出(Overflow)造成的危害,如何选择恰当的数据类型?,具体问题具体分析,1+2+3+4+,1!+2!+3!+4!+.,13+23+33+43+.,使用变量要注意,不要对类型或变量所占的内存空间字节数想当然用sizeof获得变量或者数据类型的长度现场演示程序在Turbo C2.0和Visual C下的运行结果,注意!,#include main()printf(Data type Number of bytesn);printf(-n);printf(char%dn,sizeof(char);printf(int%dn,sizeof(int);printf(short int%dn,sizeof(short);printf(long int%dn,sizeof(long);printf(float%dn,sizeof(float);printf(double%dn,sizeof(double);,变量,变量定义语句:类型关键字 变量名1,变量名2,变量名3,定义变量时初始化方式:类型关键字 变量名1=常量1,变量名2=常量2,,变量声明,使用变量的基本原则变量必须先定义,后使用所有变量必须在第一条可执行语句前定义声明的顺序无关紧要一条声明语句可声明若干个同类型的变量声明变量,是初始化变量的最好时机不被初始化的变量,其值为危险的随机数char esc=a;int i=1;int sum=0;float eps=1.0e-5;,实型数据在内存中的存储,1234.56=0.123456X104=1.23456X103=12345.6x10-1,N=S X r j,有效位数(精度),取值范围,实型数据提供的有效数字位数,float型数据提供7位有效数字double型数据提供16位有效数字 使用不当导致舍入误差,#include main()float a;double b;a=123456.789e4;b=123456.789e4;printf(%fn%fn,a,b);,#include main()float f;f=123.456;if(f=123.456)printf(f is equal to 123.456 indeed.);elseprintf(In fact,f is equal to%fn,f);运行结果会是什么?,float.c,浮点数的陷阱,float的精度低,较易发生精度带来的相等性判断问题double精度高,这个问题发生的概率小一些,但也存在解决办法:if(fabs(f 123.456)1E-5),根据精度要求设定,浮点数的陷阱,char型与int型之间的关系,小写字母转换为大写字母,#include main()char ch=b;ch=b-32;printf(%c,%dn,ch,ch);,#include main()char ch=b;ch=b-(a-A);printf(%c,%dn,ch,ch);,常数(Constant),整型常数18、-31长整型常量 123l、123L、123456l、123456L无符号型常量 123u、123U浮点常数十进制小数形式 123.45、456.78指数形式 1e-2、4.5e3单精度实型常量 123.45f、456.78F、1e-2f、4.5e3F长双精度型常量 123.45l、456.78L、1e-2l、4.5e3L,八进制与十六进制常数,以数字“0”开始的整型常数是八进制数022、-037010和10大小不一样因为八进制并不常用,所以此种表示法比较少见以“0 x”或者“0X”开始的整型常数是十六进制AF和af用来表示十进制的1015十六进制的形式比较常用,尤其在进行位一级的控制的时候0 x12、-0 x1F,-0 x1f,字符(Character)常数,字符常数的表示方法a,A,5,%,$单引号内只能有一个字符,除非用“”开头就是一个普通整数,也可以参与各种数学运算每个字符具有一个0255之间的数值,可从ASCII表查出注意:5和整数5的区别字符的数学运算在密码学内用得比较多,字符常数,转义字符一些特殊字符(无法从键盘输入或者另有它用)用转义字符表示,字符串(String)常数,用双引号括住的由0个或多个字符组成的字符序列I am a string表示空字符串转义字符也可以在字符串中使用引号只作为字符串开始和结束的标志C语言内部用0表示字符串的结束除注释外,是唯一可以出现中文的地方x和x是不同的里定义了一系列专门的字符串处理函数,枚举(Enumeration)常量,一个被遗忘的角色从程序来窥其一斑 enum weeks MON,TUE,WED,THU,FRI,SAT,SUN;enum weeks today;enum response no,yes,none;enum response answer;today=TUE;answer=yes;if(answer=yes)printf(Today is Tuesday.n);else printf(Today is NOT Tuesday.n);,宏常量,宏常量也称符号常量一般采用大写字母表示#define 标识符 字符串不是语句,而是一种编译预处理命令宏替换(Macro Substitulition),#include#define PI 3.14159#define R 5.3main()printf(area=%fn,PI*R*R);printf(circumference=%fn,2*PI*R);,宏常量,宏常量也称符号常量一般采用大写字母表示#define 标识符 字符串不是语句,而是一种编译预处理命令宏替换(Macro Substitulition),#include#define PI 3.14159#define R 5.3main()printf(PI*R*R=%fn,PI*R*R);printf(2*PI*R=%fn,2*PI*R);,const常量,用const修饰定义的变量为常量const float pi=3.1425926;常量只能在定义时赋值,然后不能再改变其值常数、const常量、宏常量和枚举常量,都可以用来表示一个永远不会改变的数前者不建议直接使用,而用后三者代替,通过相关理论学习后,我们可以对“学生成绩管理系统”中相关数据进行分析及定义了。将现实中的数据处理成C语言能够理解的数据。1.常量定义在“学生成绩管理系统”中我们假定本系统能处理一个班40个学生的数据。通常情况下,学生人数这个数据在程序的运行过程中是不变的。因此,要把表示一个班学生总人数的数据定义成符号常量。定义符号常量的格式如下:#define STUNUM 40说明:符号常量(STUNUM)必须用大写字母。,3 任务实施,2.简单类型“学生成绩管理系统”中的学生信息主要包括:学号、姓名、性别、年龄、三门功课成绩、总成绩和平均成绩,另外还有一些与计算全班成绩有关的最高成绩、最低成绩等。这些数据在程序运行过程中是可能改变的,这里只对部分表示学生信息的简单数据定义,我们在定义变量时最好能做到“见名知义”。int stunum;/整数类型的学号 char stusex;/字符类型的性别 int stuage;/整数类型的年龄 float score1;/单精度类型的成绩1,float score2;/单精度类型的成绩2 float score3;/单精度类型的成绩3 float avescore;/单精度类型的平均成绩 float maxscore;/单精度类型的最高分 float minscore;/单精度类型的最低分 由于性别这类数据只是起到描述一些基本信息的作用,通常情况下不进行算术运算,所以我们定义为字符型;而年龄、三门功课成绩、总成绩和平均成绩以及最高成绩、最低成绩等这类数据有可能进行算术运算,所以我们定义为数值型。另外,在编程实践中还会遇到一些这里不能一一列举出来的变量、数组变量和指针变量,我们将在后续的学习逐渐认识与掌握。在“班级学生成绩管理系统”中变量定义完成以后,接下来我们还要在知识扩展环节里进一步学习如何给变量赋值。,4知识扩展,常用运算符及表达式赋值和表达式中的类型转换,算术运算符,+,-,*,/加、减、乘、除运算四则混合运算中,先算乘除,后算加减,按从左向右的顺序计算,左结合%求余运算,常用的标准数学函数,关系运算符,,=,=,=,!=大于,大于等于,小于,小于等于,等于,不等于关系运算符运算出的结果为0和非00,表示假,即该关系不成立非0,表示真,即该关系成立绝大多数编译器,关系运算得到的非0结果为1,但是不要利用这个1,逻辑运算符,逻辑运算也被称为布尔(Boolean)运算&与运算(a b&b c);a大于b,并且b大于c|或运算(a b|b c);a大于b,或者b大于c!求反(!a);如果a是0,结果非0;如果a是非0,结果是0并不改变a的值,实例,ch是英文大写字母(ch=A)&(ch=Z)判断某一年year是否是闰年的条件是满足下列两个条件之一:能被4整除,但不能被100整除;能被400整除;(year%4=0)&(year%100!=0)|(year%400=0),增一和减一运算符,n+,n-,+n,-n+让参与运算的变量加1,-让参与运算的变量减1作为后缀运算符时,先取n的值,然后加/减1作为前缀运算符时,先加/减1,然后取n的值m=n+;等价于m=n;n+;m=+n;等价于n+;m=n;,增一和减一运算符,良好的程序设计风格提倡:在一行语句中,一个变量只能出现一次加1或者减1运算过多的加1和减1运算混合,不仅可读性差,而且因为编译器实现的方法不同,导致不同编译器产生不同的运行结果,位操作运算符,&按位与运算|按位或运算按位异或运算,按位右移运算按位求反,赋值运算符,下面两个语句是等价的i=i+2;i+=2;+、-、*、/、%、&、|运算符都可以按此种方式处理这种形式看起来更直观,而且执行效率一般也能更高一些,逗号运算符,表达式1,表达式2,.,表达式n多数情况下,并不使用整个逗号表达式的值,更常见的情况是要分别得到各表达式的值主要用在循环语句中,同时对多个变量赋初值等 for(i=0,j=0;i j;i+,j+),条件表达式,把a和b中的最大值放入z中if(a b)z=a;else z=b;z=(a b)?a:b;此种表达式切忌用得过于繁杂,优先级,()-.!+-+-*&(类型)sizeof*/%+-=!=&|&|?:=+=-=*=/=%=&=|=,优先级,能背下优先级表的人凤毛麟角用括号来控制运算顺序更直观、方便,并减少出错的概率,结合性,多数运算符为左结合少数为右结合:一元运算符赋值运算符条件运算符,类型转换,在进行赋值操作时,会发生类型转换将取值范围小的类型转为取值范围大的类型是安全的反之是不安全的如果大类型的值在小类型能容纳的范围之内,则平安无事但是,浮点数转为整数,会丢失小数部分,非四舍五入反之,转换后的结果必然是错误的,具体结果与机器和实现方式有关。避免如此使用,字符串与数值类型之间的转换,int i=123这样用是不行地atof(),atoi(),atol()把字符串转为double,int和long定义在stdlib.h中sprintf()可以用来把各种类型的数值转为字符串定义在stdio.h中,自动类型转换,同种数据类型的运算结果,还是该类型不同种数据类型的运算结果,是两种类型中取值范围更大的那种long double double float long int short char把数据赋值给另外一种类型变量也会发生自动类型转换从小到大,顺利转换从大到小,可能丢失信息(好的编译器会发出警告),类型强转(Casting),消除从大到小的警告l=(long)i;可以通过“(类型)表达式”的方式把表达式的值转为任意类型强转时,你必须知道你在做什么强转与指针,并称C语言两大神器,用好了可以呼风唤雨,用坏了就损兵折将,#include main()int m=5;printf(m/2=%dn,m/2);printf(float)(m/2)=%fn,(float)(m/2);printf(float)m/2=%fn,(float)m/2);printf(m=%dn,m);,类型强转,强转与指针,并称C语言两大神器,用好了可以呼风唤雨,用坏了就损兵折将,屠龙刀,倚天剑,这一章我们学到了,变量的命名规则数据类型char,short,int,long,float,double,long doublesigned,unsignedenum常数、转义字符运算符算术运算符、关系运算符、逻辑运算符、增一/减一运算符、位运算符、赋值运算符、类型强转运算符、逗号运算符、条件运算符(?:)、sizeof类型转换优先级和结合性,ASCII字符表1,