750 likes | 896 Views
第二章 数据描述与基本操作. 数据类型 常量和变量 运算符与表达式 不同类型间的数据转换 数据的输入与输出. 第二章 数据描述与基本操作. 数据与操作是构成程序的两个要素。本章主要介绍 C 语言支持的数据类型,描述数据的形式以及对数据的基本操作。. 数据类型. 数据是程序的必要组成部分,也是程序处理的对象。 在高级语言中广泛地使用 “ 数据类型 ” 这一概念。数据类型是对程序所处理的数据的 “ 抽象 ” 。 C 语言规定,在程序中使用的每个数据都属于一种数据类型。 C 语言提供有丰富的数据类型,.
E N D
第二章 数据描述与基本操作 数据类型 常量和变量 运算符与表达式 不同类型间的数据转换 数据的输入与输出
第二章 数据描述与基本操作 数据与操作是构成程序的两个要素。本章主要介绍C语言支持的数据类型,描述数据的形式以及对数据的基本操作。
数据类型 • 数据是程序的必要组成部分,也是程序处理的对象。 • 在高级语言中广泛地使用“数据类型”这一概念。数据类型是对程序所处理的数据的“抽象”。 • C语言规定,在程序中使用的每个数据都属于一种数据类型。 • C语言提供有丰富的数据类型, 构造类型数据是指由基本类型数据按一定的规律构造而成的。例如,若干个整型数的有序排列就构成一个整型数组。
0.314159| e+1 数值部分 (尾数) 指数部分 (阶码) 数值的定点与浮点表示 • 定点数:不带指数部分的数 如:3,3.14,-12.23 等 • 浮点数:带指数部分的数 如:22.5×103,314×10-2等 表示为:22.5E+3,314e-2 在C语言中,一个以指数形式表示的数分为数值(尾数)和指数(阶码)两部分。由于同一数值可用不同小数点位置的尾数和相应指数的组合来表示,所以称“浮点数” 在计算机内部,实数(即以小数形式表示的数)都以浮点形式存储,一个实数一般用4个字节存储,其中三个字节存放数字部分,一个字节存放指数部分(阶码) C语言将实数一律以浮点形式存储。如果在程序中出现小数形式的实数(如3.14159),C语言则把它按指数形式存放(如同写成3.14159e0一样)。
字符型数据的表示和存储形式 • C语言中,字符型数据用一对单引号中间插入一个可打印字符或转义字符表示: 如: ‘A’ ,‘b’, ‘\n’等 • 字符型数据在内存中占一个字节,以相应的ASCII码存放: 如:‘A’的ASCII 码为 65,‘b’的ASCII 码为 98 • 字符型数据可等价为与其ASCII码相应的整数: • 字符数据可以用数值形式输出。反之与字符ASCII码相对应的整数也可以用字符形式输出。 • 可以作为整数参加运算: 如:c=‘A’;b=c+2 b中的值为67即‘C’
例 2.2 字符型与整数型的等价转换 #include "stdio.h" main( ) { char ch; int i; ch= 'A'; ch=ch+32; i=ch; printf ("%d is %c\n", i, ch); printf ("%c is %d\n", ch, ch); } 运行结果如下: 97 is a a is 97 “%c”是输出字符的格式码,它的作用是将对应数据转换成字符形式。
各类数据的占用空间及值域 类型 长度 值域 • 字符 char 1 ASCII 0~255 • 整型 short ( int ) 2 -32768 ~ +32767 long 4 -2147483648 ~ +2147483647 • 实型 float 4 ± (3.4E-38 ~ 3.4E+38) 六位精度 double 8 ± (1.7E-308 ~ 1.7E+308) 十六位精度
带符号与无符号数据类型 • 带符号数:(signed) • 最高位表示符号(0: +,1: -) • 整型变量 int, short, long (隐式说明) • 无符号数:(unsigned) • 最高位也用与存放数据(取值范围增大一倍) • 整型变量声明前加 unsigned (int, short, long) • 字符型数据也分为signed 和unsigned。 • 实型变量无 signed 与 unsigned之分,均带符号
测定数据长度的运算符 • sizeof (类型标示符 / 常量 / 变量 ) 例如: sizeof(double) 8 sizeof(“double”) 7 sizeof(a) /* int a */ 2 sizeof(3.14) 8 sizeof(128) 2 sizeof(128L) 4 sizeof ( )是运算符,不是函数。测定某数据类型的长度时,括号中是类型名而不是双撇号括起的字符串。
常量和变量 在程序中,不同类型的数据既可以以常量形式出现,也可以以变量形式出现。常量是指,在程序执行期间值不能发生变化、具有固定值的量。变量则是其值可以变化的量,实际上变量是命名了的内存中指定的存储单元
直接常量与符号常量 • 直接常量 (字面常量) • 整型常量: 12 , 0 , - 4 • 实型常量: 4.6 , -1.23 • 字符型常量:‘a’ , ‘d’ • 字符串常量:“programming” • 符号常量(习惯上大写) • #define PI 3.1415926
符号常量 • 用一个自定义的标识符代表一个常量 #define PI 3.1415926 #define R 2.0 main( ) { printf(“area=%f”, PI*R*R) ; printf(“\tcircumference= %f\n”, 2.0*PI*R) ; }
直接常量的书写格式 • 整型常量 • 凡以数字 0 开头的 ----视为8进制 • 凡以 0X 开头的 ----视为16进制 • 凡以其它数字开头的 ----视为10进制 • 整数后加字母L(或l) ----视为长整数
整型常量举例 • 合法的整型常量 • 5121 --(十进制正数) • -32768 --(十进制负数) • 0111 --(八进制数,等于十进制数73) · • 010007 --(八进制数,等于十进制数4103) • 0XFFFF--(十六进制数,等于十进制数65537) • 0xA3 --(十六进制数,等于十进制数163) • -12L --(十进制长整数) • 不合法的整型常量: • 09876 --(0开头却有非八进制的数字8和9) • 20fa --(不是以0x开头,却有十六进制数字), • 0x10fr --(出现了非法字符)
直接常量的书写格式 • 实型常量 • 实型常量只能用十进制形式表示,不能用八进制或十六进制形式表示。 • 实型常量可以用小数形式或指数形式表示。 • 实型常量不分单精度型和双精度型,但可以赋给一个float型或double型变量。
直接常量的书写格式 • 字符常量 • 字符常量是用一对单撇号括起来的一个字符, 如:‘a’,‘A’,‘?’,‘#’等。 • 单撇号只是字符与其它部分的分隔符,或者说是字符常量的定界符,不是字符常量的一部分。 • 不能用双引号代替撇号,如"a"不是字符常量。 • 撇号中的字符不能是单撇号或反斜杠, 如:'''和,'\'不是合法的字符常量。
直接常量的书写格式 • 转义字符 • 用反斜杠开头后面跟一个字母代表一个控制字符。如: \n • 用\\代表字符“\”,用\'代表撇号字符 • 用\后跟1到3个八进制数代表ASCII码为该八进制数的字符; • 用\x后跟1到2个十六进制数代表ASCII码为该十六进制数的字符。
转义字符表 • \n 换行 • \t 横向跳格(即跳到下一个输出区) • \v 竖向跳格 • \b 退格 • \r 回车 • \f 走纸换页 • \\ 反斜杠字符“\” • \’ 单引号(撇号)字符 • \” 双引号(撇号)字符 • \ddd 1到3位8进制数所代表的字符 • \xhh 1到2位16进制数所代表的字符
‘A’ 65 “A” 65 0 “” 0 直接常量的书写格式 • 字符串常数 • 用一对双撇号括起来的零个或多个字符序列如: “hello”, “A”, “”等 • 字符串以双撇号为定界符,但它并不属于字符串 • 要在字符串中插入双撇号必须借助转义符\” • 字符串中的字符数称为该字符串的长度,在机器内存储时,系统自动在它的末尾加一个字符串结束标志,转义符“\0”。存储空间要多占用一个字节。 • 要特别注意字符常数与字符串常数的区别:‘A’是字符常数,“A”则是字符串常数
变量和对变量的赋值 • 数据总是被存储在一定的存储空间中,在高级语言中,数据连同其占用的存储空间被抽象为变量。 • 每个变量都有一个名字,这个名字称为变量名。它代表了某个存储空间及其所存储的数据。 • 这个空间中所存储的数据,称为该变量的值。 • 这个存储空间的首地址称为该变量的地址。 • 变量的值可以在程序运行时改变。 变量a表示了一个被命名为a的ftoat类型的数据,它占有8个单元的存储空间,分别是单元6300~6307。而6300就称为变量a的地址,记做&a或者说&a的值是6300。
变量和对变量的赋值 赋值运算的方向为由右向左,即将“=”右侧表达式的值赋给“=”左侧的变量。执行步骤为先计算(表达式的值)再(向变量)赋值。 • 把从运算器向变量所代表的存储单元传送数据的操作称为赋值。 • 在C语言中,赋值操作由赋值运算符“=”来完成。一般形式为: 变量 = 表达式; 如:y = 3*x+4*(b+c); “=”是赋值符号,不是等于号。在C语言中等于号用“==”表示。
变量的声明 • C语言规定,在程序中用到的每一个变量都要声明它属于哪一种类型。也就是说,要显式地指定变量的类型。
变量的声明 • 变量声明的意义 • 不同类型的数据在内存中占据不同长度的存储区,而且采用不同的表示方式(在机器内部的表示方式)。在程序中引用一个变量,实际上是对指定的存储空间的引用,必须先分配存储空间才能引用它。 • 每一种数据类型对应着一个取值的范围。 • 一种数据类型对应着一组允许的操作。例如,对整型数据可以进行“求余”运算,实型数就不可以;数值型数据可以进行四则运算,而结构体型数据就不可以等。
变量的声明 • 变量声明的一般形式: 类型标示符 变量名[=初值][,变量名=初值,…]; 例如:int i1,i2; /*声明i1,i2为整型变量*/ Short s1,s2; /*声明s1,s2为短整型变量*/ long l1,l2; /*声明l1,l2为长整型变量*/ char chl=‘a’,ch2=‘b’; /*声明chl,ch2为字符 型变量,并赋初值 */ • C语言允许在声明变量时对变量赋初值或初始化。用赋初值的办法使变量得到初值,程序简练,提高了程序的可读性。 • 经过声明,每一个被声明的名字,便与其类型相对应大小的存储空间相联系。 • 应当注意,在同一个程序中,一个变量只能属于某一类型,不能把一个变量声明为几个不同类型。
标 示 符 • 标识符是给程序中的实体——变量、常量、函数、数组、结构体以及文件所起的名字。可以由程序设计者指定,也可以由系统指定。
C语言标识符的命名规则 • 以字母或下划线开头,由字母、数字或下划线组成的字符序列。例如: • 合法标示符:sum, PI, Number_01, J5_7, _sys • 非法标示符:number-01, piece flag, 5_7, $123.4 • C语言有32个关键字(见附录Ⅱ),它们已有专门含义,用户不应采用与它们同名的标识符。 • 系统内部使用了一些用下划线开头的标识符,为防止与用户自己定义的标识符冲突,建议用户在定义标识符时尽量不要用下划线开头。
C语言标识符的命名规则 • C语言对标识符的长度无规定,但87 ANSI C规定可识别的有效长度为31个字符,有的C版本规定的长度可能很短,具体使用时应以所用C版本规定为准。如,Microsoft C识别前8个字符,Turbo C默认值为32,可由用户自己重新设定 • C语言是大小写敏感的语言,将相同字母的大写和小写视为两个不同字符。例如,TOTAL、Total、 total被认为是三个标识符。
定义C语言标识符应遵循的原则 • 尽量做到“见名知义”,以增加程序的可读性。 • 变量名、函数名用小写,符号常量用大写。 • 在容易出现混淆的地方尽量避免使用容易认错的字符。如: • 0(数字)——O(大写字母)--o(小写字母) • 1(数字)—— I(i的大写字母)——1(L的小写字母) • 2(数字)—— Z(大写字母)——z(小写字母)
2.3 运算符与表达式 • 运算(即操作)是对数据的加工。最基本的运算形式常常可以用一些简洁的符号记述。这些符号称为运算符或操作符。 • 被运算的对象——数据称为运算量或操作数。 • 表达式描述了对哪些数据,以什么顺序以及施以什么样的操作。它由运算符与运算量组成。运算量可以是常量、变量或函数。
C语言提供有丰富的运算符 • 算术运算符 ( + - * / % ++ -- ) • 关系运算符 ( > = < >= <= != ) • 逻辑运算符 ( ! && || ) • 位运算符 ( << >> ~ | ^ &) • 赋值运算符 ( =及其扩展赋值运算符) • 条件运算符 ( ? : ) • 逗号运算符 ( ,)
C语言提供有丰富的运算符 • 指针运算符 ( * 和 & ) • 求字节数运算符 ( sizoof ) • 强制类型转换运算符 ( 类型 ) • 分量运算符 ( . -> ) • 下标运算符 ( [ ] ) • 其它运算符 ( 如函数调用运算符( ) )
学习运算符时应注意以下几点 • 运算符的功能:如加、减、乘、除等。 • 与运算量的关系: • 要求运算量的个数。例如,有的运算符要求有两个运算量参加运算(如+、-、*、/ ),称为双项(或双元、双目)运算符;而有的运算符(如负号运算符、地址运算符&)只允许有一个运算量,称为单项(或一元、一目)运算符。 • 要求运算量的类型。如+、-、*、/的运算对象可以是整型或实型数据,而求余运算符要求参加运算的两个运算量都必须为整型数据。
学习运算符时应注意以下几点 • 运算的优先级别:如果一个运算量的两侧有不同的运算符,应先执行“优先级别”高的运算。 • 结合方向: • 如果在一个运算量的两侧有两个相同优先级别的运算符,则按结合方向顺序处理。 • 在C语言中并非所有的运算符都采取自左至右的结合(左结合性) ,有些运算符的结合方向是自右至左的(右结合性),如赋值运算符。 • 结果的类型:即表达式值的类型,尤其当两个不同类型数据进行运算时,更要特别注意。 • 附录Ⅲ列出了所有运算符的优先级别和结合性。
算术运算 • 自加自减是自反算术赋值运算中更特殊的情况:i++ i+=1 i=i+1 • 自加自减运算分前缀和后缀两种形式: • 前缀式(++i): 先增值后引用 • 后缀式(i++): 先引用后增值 • 双元算术运算符: ( + , - , * , / , %) • 自反算术赋值运算符: += (自反加赋值) -= (自反减赋值) *= (自反乘赋值) /= (自反除赋值) %=(自反模赋值) • 自加和自减运算符: ( ++ , -- ) • 正负号运算符: ( + , - ) • 自加和自减运算符是单目运算符,优先级别高于*、/运算,它的结合方向是自右至左,运算对象只能是整形变量,不能是表达式或和常量 • 综上所述:凡赋值运算符及其变种(包括自反算术赋值运算符、自加和自减运算符和正负号运算符),其结合方向都是自右至左。 • 优先级别为:*,/,%同级,+,-同级但低于*,/,% • 结合方向均为自左至右 • 正负号运算符也是单目运算符,优先级别高于*、/运算,它的结合方向也是自右至左 • 是算术运算符与赋值运算符的合成或简化。例如:a=a+b;合成为:a+=b; • 结合方向与赋值运算符一样,自右向左;优先级别低,与赋值同级。
赋值类运算符的副作用及其限制 • c=b*=a+2; 改为:c=a+2; b*=c; c=b; • x=i+++j; 改为:x=i+j; i++; • 费解、易被误解——对人的副作用 • 例子: c=b*=a+2; x=i+++j; • 避免的措施: • 将费解处分解 • 加一些不必要的括号 • 加注释说明 • c=b*=a+2; 改为:c= (b*=(a+2)); • x=i+++j; 改为:x=(i++)+j;
赋值类运算符的副作用及其限制 • 不定解——对机器的副作用 • 例子:j=3; i=(k=j+1)+(j=5); 执行程序时,不同机器上得到i的值可能是不同的。有的机器先执行(k=j+1)然后再执行(j=5),i值得9。而有的机器是先执行(j=5)后执行(k=j+1),i的值就成了11。 • 为了提高程序的可移植性,应当使表达式分解,使之在任何机器上运行都能得到同一结果。 上面语句可改为:j=3;k=j+1; j=5;i=k+j;
关系运算 • 关系运算是指对两个运算量之间的大小比较。 • C语言中提供的关系运算符有6个: >(大于) >=(大于等于) ==(等于) <(小于) <=(小于等于) !=(不等于) • ==和!=的优先级小于其它四个。并且,它们都低于纯算术类,高于赋值类。它们都是从左向右的结合方式。 • 关系表达式的值只有两个:关系表达式成立,即为“真”,C语言中以“1”表示;关系衰达式不成立,即为“假”,以“0”表示
关系运算注意事项 • 要说明x在区间[a,b]中,数学中使用表达式 a≤x≤b,但C语言中的表达式 a<=x<=b的含义与之不同。为了判别x是否在[a,b]范围内应写成:a<=x && x<=b • 由于关系表达式的值是整型数0或1,故也可以将其看成是一种整型表达式。 • 由于字符数据按ASCII码存储,所以可以把它作为整数参加运算和比较。 • 在判定两个浮点数是否相等时,由于存储上的误差,会得出错误的结果。例如:1.0/3.0*3.0==1.0并不成立。应避免对两个实数表达式作“相等”或“不相等”的判别,而改用判断两数差的绝对值是否小于某值。
逻辑运算 • C语言有三个逻辑运算符: && (逻辑与) || (逻辑或) ! (逻辑非) • C语言不提供逻辑型数据“真”和“假”,在进行关系运算时,结果为“真”用1表示,“假”用0表示。在进行逻辑时则把“非零”作为“真”,把0作为“假”。 • &&和||是二元运算符,结合方向为自左至右;!为一元运算符,结合方向为自右至左。 • &&和||的优先级低于关系运算符,而!的优先级高于关系运算符。
逻辑运算中的规律 0||a==a 1&&a==a 1||a==1 0&&a==0 a||!a==1 a&&!a==0 a||a==a a&&a==a !(a||b)==!a&&!b !(a&&b)==!a||!b !(!a)=a • 掌握上述规律能使复杂的逻辑运算简化、清晰 • 若逻辑表达式中有函数,则由于编译器对代码的优化可能在已知表达式结果的情况下,短路表达式的求值过程,不再调用该函数。
逻辑表达式优化的基本规则 • “真”和任何逻辑值进行“或”(||)运算总是“真”,当运算符“||”左边的部分为“真”(不为0)时,其右的表达式就不再计算; 如:x=y=z=1; ++x||++y||++z; 中,因++x值为2(真),无论++y||++z 为何值,最终结果肯定是“真”,所以++y||++z 就不再求值; • “假”和任何逻辑值进行“与”(&&)运算总是“假”,当运算符“&&”左边的部分为“假”(为0)时,其右的表达式也不再计算; 如:x=y=z=-1; ++x||++y&&++z; 中,因++x||++y的值为0,无论++z为何值,最终结果都是“假”,所以++z也没有执行;
条件运算 • 条件运算是一种在两个表达式的值中选择一个的操作。它的一般形式为: • 它也称为“条件表达式”,操作过程为:若e1为真(非0),则此条件表达式的值为e2的值;若 e1为假(0),则表达式取e3的值。若e2和e3值的类型不一致,则取二者中类型较高的。 • 条件运算符“? :”共要求三个运算量,是C语言中唯一的三元运算符。 e1 ? e2 : e3
例2.10 输入两数,输出大者 main( ) { float a,b,max; printf("input 2 reals please:"); scanf("%f%f",&a,&b); max = a>b ? a:b; printf("The max is%f\n",max); } • 条件运算符的优先级很低,仅仅比赋值操作符的级别高,结合方式也是从右至左。 • 这里语句max=a>b?a:b;相当于max=(a>b?a:b);
C语言运算符优先级口诀 • 括号成员加箭头 • 单目强制SIZEOF • 算术取余乘和除 • 加减运算在其后 • 左移右移排第五 • 关系运算六个六 • 按位运算单字符 • 逻辑与或并肩走 • 条件运算是三目 • 赋值自反跟在后 • 齐目赋值结合右 • 顺序逗号排最后
赋值表达式 • C语言中把用赋值号连结变量和表达式的式子称为赋值表达式。例如:a=3+5 • 赋值表达式的值就是被赋值后变量的值。如,表达式a=3+5的值是8。 • 可以将一个赋值表达式的值再赋给另一个变量。例如表达式:b=(a=3+5) • 可以连续赋值: 如 a=b=c=d+3.45
逗号表达式 • C语言还允许用逗号作为表达式间的分隔符把几个表达式组合在一起,形成一个复合型表达式,它们也称为逗号表达式。最后用分号结尾。就形成了一个逗号表达式语句。 例如:++i, --j; i=1, j=2; 等。 • 一个逗号表达式有一个值,它就是其中最后一个表达式的值。 例如:a=(a=6,a*3,a+3)*2; 则a的最后值为18
2.4 不同类型数据间的转换 • C语言允许数据值从一种类型转换成另一种类型。 • 数据类型的转换有如下三种基本形式: • 同一类型但长度不同的数据间的转换。 • 定点方式与浮点方式之间的转换。 • 整型数中有符号格式与无符号格式之间的转换
有关数据类型转换的概念 • 提升与降格 • 由低级的数据转换为高级的数据,称为数据提升。它包括如下一些提级转换: • 由短数据转换为长数据。如图2.5中的①,②,③,⑤,⑥。 • 由整数转换为浮点数。如图2.5中的④和⑤。 • 相反方向的转换称为降格,如图2.5中的虚线所示。 • 同一长度的整数带符号与不带符号的转换,属于同一级别。