Download presentation
Presentation is loading. Please wait.
1
第 二 章 数据类型、运算符与表达式
2
主要内容 一、上机环境与步骤 ——Visual C++集成开发环境 二、C的数据类型 三、常量与变量 四、基本数据类型 五、运算符与表达式
3
一、上机环境与步骤 ——Visual C++集成开发环境
1、编辑 方法一:先创建C源程序 方法二:先创建空工程 2、编译和链接 编译|编译 Ctrl+F7 编译|构件 F7 3、执行 编译|执行 Ctrl+F5 文件|新建 主要参考实验指导书。结合具体环境进行介绍。 讲Vc工作环境。以先创建文件和先创建空工程两种方式讲解。 实验指导书中的#include “stdafx.h”去掉。
4
方法一:先创建C源程序 文件 标签 文件类型 文件名 目录 采用先创建C源程序的方法需要注意以下几点: 1、选择“文件”标签;
2、选择“C++ Source File”文件类型; 3、在“目录”文本框中输入C源程序所存放的目录。此目录建议用户自己提前新建好,以便查找,不建议使用缺省的目录; 4、在“文件”文本框中输入文件名。 目录
5
方法二:先创建空工程——步骤1 工程名 工程 标签 目录 工程类型 步骤一:新建工程 采用先创建空工程的方法需要注意以下几点:
1、选择“工程”标签; 2、选择“Win32 Console Application”工程类型; 3、在“目录”文本框中输入工程所存放的目录。此目录建议用户自己提前新建好,以便查找,不建议使用缺省的目录; 4、在“工程”文本框中输入工程名,在输入工程名的过程中会同时在位置框的原有目录中新建一个与工程名同名的目录,用来存放工程文件。
6
方法二:先创建空工程——步骤2 选择空工程 步骤二:选择空工程
7
方法二:先创建空工程——步骤3 文件 标签 选中此项 文件类型 文件名 步骤三:在空工程中添加C源文件
采用先创建空工程的方法添加源文件时需要注意以下几点: 1、选择“文件”标签; 2、选择“C++ Source File”文件类型; 3、“目录”文本框中默认为工程所在目录,不需修改。 4、在“文件”文本框中输入文件名。 5、选中“添加工程”复选框,将新建的文件直接添加到工程中,否则还需要另行添加。
8
二、C的数据类型 (一) 什么是数据类型? (二) C语言的数据类型有哪些?
9
数据结构+算法=程序 (一) 什么是数据类型? C语言中以 “数据类型”形式存在 对数据的描述 对操作的描述
一个程序应包括对数据的描述和对数据处理的描述。 .对数据的描述,即数据结构。数据结构是计算机学科的核心课程之一,有许多专门著作论述,本课程就不再赘述。 在C语言中,系统提供的数据结构,是以数据类型的形式出现的。 .对数据处理的描述,即计算机算法。算法是为解决一个问题而采取的方法和步骤,是程序的灵魂。为此,著名计算机科学家沃思(Nikiklaus Wirth)提出一个公式: 数据结构 + 算法 = 程序 实际上,一个程序除了数据结构和算法外,还必须使用一种计算机语言,并采用结构化方法来表示。 C语言提供的数据结构,是以数据类型形式出现的。具体如下页幻灯片所示。 C语言中以 “数据类型”形式存在
10
(二) C的数据类型 ? 数据类型 基本类型 整型 字符型 实型(浮点型) 枚举类型 构造类型 数组类型 结构体类型 共用体类型 指针类型
空类型 单精度型 双精度型 数据类型决定: 1. 数据占内存字节数 2. 数据取值范围 3. 其上可进行的操作 C语言中的数据,有常量和变量之分,它们分别属于上述这些类型。 本章将介绍基本类型中的整型、实型和字符型三种数据。 在程序中对用到的 所有数据都必须指 定其数据类型. 不同类型的数据,所占 内存的字节数不同, 对 应的操作也不相同。 ?
11
三、常量与变量 (一) 常 量 (二) 变 量
12
(一) 常量 概念 分类 符号常量的定义 意义 在程序运行过程中,其值不能被改变的量。
字符串常量 字面常量(直接常量): 'a' "Hello! " 符号常量:用一个标识符代表一个常量。 分类 习惯上常量名用大写, 变量名用小写。 格式:#define 常量名 字面常量 举例:#define PRICE 100 #define PI 3.14 #define C1 ’a’ 符号常量的定义 字面常量(直接常量):可分为整型常量、实型常量、字符常量和字符串常量,根据书写格式就可以判断。 标识符:指一个名字,有关标识符的命名规则将随后介绍。 符号常量的定义放在 函数外面。 1、含义清楚。 2、在需要改变一个常量时,能够做到“一改全改”。 意义
13
常量——举例(求某商品总价) #include <stdio.h> #define PRICE 100 //定义符号常量
void main() { int sum; sum=PRICE*20; printf("%d\n",sum); } 单价——符号常量 数量——直接常量 此例用来求20件某商品的总价sum。 商品的单价采用符号常量PRICE,数量采用直接整型常量20。 当商品的单价PRICE发生变化时,不需从程序中查找具体值,只需通过#define进行修改即可,做到一改全改;而当商品的数量发生变化时,只能从程序中查找具体值20,对其进行修改,尤其某一常量在程序中多处使用时,修改起来更加麻烦,也容易造成遗漏。 而
14
(二)变量 其值可以改变的量称为变量。 (1)变量名。每个变量都必须有一个名字──变量名,变量命名遵循标识符命名规则。
概念 (1)变量名。每个变量都必须有一个名字──变量名,变量命名遵循标识符命名规则。 (2)变量值。在程序运行过程中,变量值存储在内存中。在程序中,通过变量名来引用变量的值。 要素 变量的两个要素是:变量名和变量值。
15
1、标识符就是一个名字(如常量名、变量名、函数名……)。
identifier 1、标识符就是一个名字(如常量名、变量名、函数名……)。 2、组成:只能由字母、数字、下划线组成。且第一个字符必须为字母或下划线。 3、长度:标识符的有效长度随系统而异,如果超长,则超长部分被舍弃。VC++6.0中规定最大长度为247个字符。 4、标识符命名的良好习惯──见名知意 Turbo C规定 1、最大为32个字符,建议不超过8个字符。 2、变量说明应出现在函数体的声明部分。 例如,由于student_name和student_number的前8个字符相同,有的系统认为这两个变量,是一回事而不加区别。 在TC V2.0中,变量名(标识符)的有效长度为1~32个字符,缺省值为32。 注: VC++中规定前247个字符有效。 程序中用到的变量必须“先定义,后使用”。变量可以在程序的执行部分定义,但其作用域为定义后的区域。 (P44) 所谓“见名知意”是指,通过变量名就知道变量值的含义。通常应选择能表示数据含义的英文单词(或缩写)作变量名,或汉语拼音字头作变量名。 例如,name(姓名)、age(年龄)
16
思 考 ? 下列标识符是否合法,为什么? sum a1 b2 s_name #ss a.b.c 1a8bc 合法 不合法
17
数据类型 变量名[, 变量名2……]; 变量定义 int a1,a2; float x1,x2; double y1,y2;
数据类型 变量名[, 变量名2……]; 习惯上,变量名用小写字母。 常量名用大写字母。 int a1,a2; float x1,x2; double y1,y2; char c1,c2; 变量定义:类型名 变量名列表; 注:数据类型与变量名之间至少要有一个空格,变量名之间用逗号分开,末尾加分号。
18
方式: 1、定义变量的同时赋初值(也叫变量初始化)。 格式: 数据类型 变量名[=初值][, 变量名2[=初值2]……];
变量赋初值 出现在函数体 的声明部分 方式: 1、定义变量的同时赋初值(也叫变量初始化)。 格式: 数据类型 变量名[=初值][, 变量名2[=初值2]……]; 2、通过一个赋值语句给变量赋初值。 格式 : 变量名=初值; 出现在函数体 的执行部分 在C语言中称在定义变量的同时进行赋初值的操作为变量初始化,要求对所有用到的变量,必须先定义、后使用。 变量赋初值有两种方式:定义的同时赋初值和通过赋值语句赋初值。两者的效果是等价的。 int a,b; b=3; int a,b=3;
19
关于变量以及变量赋初值的几点说明 1、程序中用到的变量必须“先定义(declare),后使用”。 2、C语言的关键字不能用作变量名。
4、定义变量时,给几个变量赋相同的初值, 应写成 : int a=3,b=3,c=3; 不能写成: int a=b=c=3; 5、给变量赋值时,正常情况下应给变量赋相同类型的数据。若给变量赋与其类型不同的数据时,需进行类型转换。 32个关键字:(由系统定义,不能重作其它定义) auto break case char const continue default do double else enum extern float for goto if int long register return short signed sizeof static struct switch typedef unsigned union void volatile while 类型转换在赋初值和不同类型数据进行混合运算时都会遇到。 具体的转换规则参见课本P59页。将在下一节讲赋值运算符时具体介绍。
20
undeclared identifier
变量——举例 本程序中有几处错误? #include <stdio.h> void main() { int student,age; int if=adrress=1; float score=90; stadent=2; Age=20.7; printf("%d %d %d %f",if,student,age,score); } 错误: 1、if:为关键词 2、int if=address=1;应分别赋初值。 3、stadent:未定义的标识符,拼写错误 4、Age:未定义的标识符,大小写敏感。 对score和age赋值时会自动进行类型转化。9090.0;20.720 undeclared identifier
21
四、基本数据类型 (一) 整数类型 (二) 实数类型 (三) 字符类型 (四) 不同类型数据间的转换
对于基本类型分别从存储方式、常量和变量等方面进行讲解。
22
各类型整型变量占用的内存字节数,随系统而异。
(一) 整数类型——变量 类型 比特数 范围 int [signed] int ~32767(215-1) unsigned int ~65535 short [int] [signed] short [int] ~32767(215-1) unsigned short [int] ~65535 long [int] [signed] long [int] ~ unsigned long [int] ~ 分类及取值范围 整型变量 分类 根据占用内存字节数的不同,整型变量又分为4类: (1)基本整型(类型关键字为int)。 (2)短整型(类型关键字为short [int])。 (3)长整型(类型关键字为long [int])。 (4)无符号整型。无符号型又分为无符号基本整型(unsigned [int])、无符号短整型(unsigned short)和无符号长整型(unsigned long)三种,只能用来存储无符号整数。 2.占用内存字节数与值域 上述各类型整型变量占用的内存字节数,随系统而异。在16位操作系统中,一般用2字节表示一个int型变量,且long型(4字节)≥int型(2字节)≥short型(2字节)。 显然,不同类型的整型变量,其值域不同。占用内存字节数为n的(有符号)整型变量,其值域为:-2n*8-1~(2n*8-1-1);无符号整型变量的值域为:0~(2n*8-1)。 例如,PC机中的一个int型变量,其值域为-22*8-1~(22*8-1-1),即-32768~32767;一个unsigned型变量的值域为:0~(22*8-1),即0~65535。 我们使用的VC环境中int和unsigned int型数据所占的字节数为4,即32位,随之数据的表示范围也不同,分别为 ~ 和0~ 。 []表示可以省略
23
一个整型常量,可以赋给能容纳下其值的整型变量
整数类型——常量 以数字0开头 十进制: 123, -456, 0 八进制: 0123, , 十六进制: 0x123, -0x456 以0x开头 表示方法 如123l,315L 基本整型(数据范围与int型一样) 长整型 (在数值后面加“L(l)”, 数据范围与long int型一样) 分类 1.三种表示形式 整型常量即整常数,在C语言中可用三种形式表示: (1)十进制。例如10、36。 (2)八进制(以数字0开头)。例如012。 (3)十六进制(以数字0+小写字母x开头)。例如0x36。 2.分类 (1)基本整型。在16位机中,用2字节存储,其数据范围与int型变量一样。 (2)长整型(在数值后面加“L(l)”)。对超出基本整型值域的整型常量,可使用长整型常量表示,其取值范围可达-231-(231-1)。例如,123l、315L等。 3.类型匹配规则 类型匹配规则为:一个整型常量,可以赋给能容纳下其值的整型变量。 例如,其值在-215--(215-1)的整型常量,可以赋给int型变量和long int型变量;其值在-231--(231-1)的整型常量,就只能赋给long int型变量。 注意:常量无unsigned型。但一个非负整型常量,只要它的值不超过相应变量的值域(即取值范围),也可以赋给unsigned型变量。 类型匹配规则 一个整型常量,可以赋给能容纳下其值的整型变量
24
常量无unsigned型。但一个非负整型常量,只要它的值不超过相应变量的值域(即取值范围),也可以赋给unsigned型变量。
注意: 常量无unsigned型。但一个非负整型常量,只要它的值不超过相应变量的值域(即取值范围),也可以赋给unsigned型变量。 举例 #include <stdio.h> void main() { long int c,d=9L; unsigned int e=-3 , f; f =5; c=-6; printf("%ld\n%ld\n%u\n%u",c,d,e,f); } -6 9 65533 5 运行结果 将非负整数赋给无符号整型变量时,结果时正确的。 当把负整数赋给无符号整型变量时,结果出乎意料。要知其中原因,必须了解整数在存储器中的存储方式。
25
整数类型——存储方式 整型数据在内存中是以补码表示的。(参见教材P41) 编码 正数表示方法 负数表示方法 原码
最高位为符号位(0-正数,1-负数)。其他位为此数绝对值的二进制表示。 反码 同原码 最高位为符号位(1),其他位为原码表示的各位取反。 补码 最高位为符号位(1),其他位为原码表示的各位取反再末位加1。
26
例如: 求-10的补码表示(按16位存储)。 -10的原码 除符号位外各位取反 末位加1 则得到-10的二进制补码的表示。
27
整数类型——溢出举例(P44-例3.3) 32767 32768 #include <stdio.h> void main()
{ int a,b; a=32767; b=a+1; printf("%d\n%d",a,b); } 32767 32768 运行结果 改为 - 运行结果 VC中int型为32位。 因此当值大于32767时不会出现溢出。 当大于 时,将出现溢出。
28
(二) 实数类型——变量 分类及取值范围 类型 比特数 有效数字 数值范围 float 32 6~7 10-37~1038
类型 比特数 有效数字 数值范围 float ~ ~1038 double ~ ~10308 long double ~ ~104932 C语言的实型变量,分为两种: (1)单精度型。类型关键字为float,一般占4字节(32位)、提供7位有效数字。 (2)双精度型。类型关键字为double,一般占8个字节、提供15~16位有效数字。
29
实数类型——常量 表示方法 实型常量不分float型和double型。一个实型常量,可以赋给一个实型变量(float型或double型)。
数字和小数点组成 十进制小数形式: , , 0.0 指数形式: <尾数>E(e)<整型指数> 如0.23e2 ,-0.45e-3, 3.0E+5 表示方法 规范化指数形式 实型常量不分float型和double型。一个实型常量,可以赋给一个实型变量(float型或double型)。 关于分类 实型常量 1.表示形式 实型常量即实数,在C语言中又称浮点数,其值有两种表达形式: (1)十进制形式。例如3.14、9.8。 (2)指数形式:<尾数>E(e)<整型指数>。例如3.0E+5等。 2.关于类型 实型常量不分float型和double型。一个实型常量,可以赋给一个实型变量(float型或double型)。 所谓规范化的指数形式指:小数部分采用纯小数形式,且最高位不为0。
30
规范化指数形式:小数部分采用纯小数形式,且最高位不为0。
实数类型——存储方式 实型数据在内存中是按指数形式存储的。(P46) 指数形式(数符+小数部分+指数部分) 规范化指数形式:小数部分采用纯小数形式,且最高位不为0。 小数部分占的位数越多,数的有效 数字越多,精度越高.指数部分占的 位数越多,表示的数值范围越大. 所谓规范化的指数形式指:小数部分采用纯小数形式,且最高位不为0。 举例: 在内存中的存放形式为: +
31
(三) 字符类型——常量 表示方法 转义字符 用单引号括起来的一个字符. 'a' 'A' '9' '=' '? '
不同的两个字符 表示方法 将\后面的字符转换 为另外的意义.即是 一种控制符号. 用单引号括起来的一个字符. 'a' 'A' '9' '=' '? ' C语言还允许使用一种特殊形式的字符常量,就是以反斜杠"\ "开头的转义字符。 转义字符 字符形式 含义 (P48) \n 换行,从当前位置移到下一行开头 \t 水平制表(跳到下一个tab位置) \b 退格,将当前位置移到前一列 \r 回车,将当前位置移到本行开头 \' 单撇号字符 \\ 反斜杠字符 \" 双撇号字符 \ddd ~3位8进制数所代表的字符 \xhh ~2位16进制数所代表的字符 …… …… 1.字符常量的定义 用一对单引号括起来的单个字符,称为字符常量。 例如,‘A’、‘1’、‘+’等。 2.转义字符 C语言还允许使用一种特殊形式的字符常量,就是以反斜杠“\ ”开头的转义字符。 注意:注意:如果反斜杠、单引号或双引号本身作为字符常量,必须使用转义字符:'\\'、'\'' 、'\"'。
32
举例 结果: #include <stdio.h> void main() { printf("abc\bd\nxyz");
printf("\rlmn\topq\n"); } abd lmn opq 实际中,不会 这样使用! 结果: #include <stdio.h> void main() { printf("\x4F\x4B\x21\n"); /* 等价于printf("OK!\n"); */ printf("\x15 \xAB\n"); } OK! § ½
33
字符类型——变量 ch 类型及范围 char 大小写英文字母,数字,运算符,标点符号等 存储方式
以ASCII码存储,占一个字节(参见教材P50) 字符变量ch中存放字符'a',其ASCII码为97,在内存中以二进制形式存放,其格式如下: 举例 字符变量的类型关键字为char,一般占用1字节内存单元。 1.变量值的存储 字符变量用来存储字符常量。将一个字符常量存储到一个字符变量中,实际上是将该字符的ASCII码值(无符号整数)存储到内存单元中。 例如,char ch1, ch2; /*定义两个字符变量:ch1,ch2*/ ch1='a'; ch2='b'; /*给字符变量赋值*/ 2.特性 字符数据在内存中存储的是字符的ASCII码── 一个无符号整数,其形式与整数的存储形式一样(如图2-4所示),所以C语言允许字符型数据与整型数据之间通用。 ch 注意:字符型数据与整型数据在存储方式上的相似性使得两者之间可以通用。但字符型数据的表示范围是:0~255。
34
一个字符型数据,既可以字符形式输出,也可以整数形式输出
字符类型——举例1 一个字符型数据,既可以字符形式输出,也可以整数形式输出 [例] 字符变量的字符形式输出和整数形式输出。 #include <stdio.h> void main() { char ch1,ch2; ch1='a'; ch2='b'; printf("ch1=%c,ch2=%c\n",ch1,ch2); printf("ch1=%d,ch2=%d\n",ch1,ch2); } (1)一个字符型数据,既可以字符形式输出,也可以整数形式输出。 [例] 字符变量的字符形式输出和整数形式输出。 /*程序功能:用字符形式和整数形式输出字符变量*/ main() { char ch1,ch2; ch1='a'; ch2='b'; printf("ch1=%c,ch2=%c\n",ch1,ch2); printf("ch1=%d,ch2=%d\n",ch1,ch2); } 程序运行结果: ch1=a,ch2=b ch1=97,ch2=98 程序运行结果: ch1=a,ch2=b ch1=97,ch2=98
35
字符类型——举例2 允许对字符数据进行算术运算,此时就是对它们的ASCII码值进行算术运算
[例]字符数据的算术运算(参考教材P374的ASCII码表)。 #include <stdio.h> void main() { char ch1,ch2; ch1='a'; ch2='B'; /*字母的大小写转换*/ printf("ch1=%c,ch2=%c\n",ch1-32,ch2+32); /*用字符形式输出一个大于256的数值*/ printf("ch1+200=%d\n", ch1+200); printf("ch1+200=%c\n", ch1+200); printf("ch1+256=%d\n", ch1+256); printf("ch1+256=%c\n", ch1+256); } 程序运行结果: ch1=A,ch2=b ch1+200=297 ch1+200=) ch1+256=353 ch1+256=a (2)允许对字符数据进行算术运算,此时就是对它们的ASCII码值进行算术运算。 [例] 字符数据的算术运算。 /*程序功能:字符数据的算术运算*/ main() { char ch1,ch2; ch1='a'; ch2='B'; /*字母的大小写转换*/ printf("ch1=%c,ch2=%c\n",ch1-32,ch2+32); /*用字符形式输出一个大于256的数值*/ printf("ch1+200=%d\n", ch1+200); printf("ch1+200=%c\n", ch1+200); printf("ch1+256=%d\n", ch1+256); printf("ch1+256=%c\n", ch1+256); } 程序运行结果: ch1=A,ch2=b ch1+200=297 ch1+200=) ch1+256=353 ch1+256=a 思考:用字符形式输出一个大于256的数值,会得到什么结果? 先让学生自行运算,再给出正确结果,并对运行结果进行分析。 思考:用字符形式/整数形式输出一个大于256的数值,会得到什么结果?
36
字符串常量 概念 用一对双引号" "括起来的若干字符序列
用一对双引号" "括起来的若干字符序列 字符串中字符的个数。长度为0的字符串(即一个字符都没有的字符串)称为空串,表示为"" (一对紧连的双引号)。 字符串长度 书写字符串常量时,不必加结束字符‘\0’,否则画蛇添足,是由系统自动加的。 存储方式 C语言规定:在存储字符串常量时,由系统在字符串的末尾自动加一个'\0'作为字符串的结束标志。
37
"C:\\msdos\\v6.22"和"I say:\"Goodbye!\""
思考? 1、 字符串常量"How do you do."和"Good morning."的长度分别是多少? 14和13 2、 字符串C:\msdos\v6.22和I say: " Goodbye! "在C语言中的字符串常量形式如何表示? "C:\\msdos\\v6.22"和"I say:\"Goodbye!\"" 思考1:空格是字符。 思考2:如果反斜杠和双引号作为字符串中的有效字符,则必须使用转义字符。 思考3:C语言规定:在存储字符串常量时,由系统在字符串的末尾自动加一个‘\0’作为字符串的结束标志。 注意:在源程序中书写字符串常量时,不必加结束字符‘\0’,否则画蛇添足。 如果有一个字符串为“CHINA”,则它在内存中的实际存储如下所示: 最后一个字符'\0'是系统自动加上的,它占用6字节而非5字节内存空间。 3、 字符串"CHINA"在内存中的实际存储形式是怎样的?占用多少个字节的内存空间? 占用6字节而非5字节内存空间 C H I N A \0
38
注意: ? 1、'a'是字符, "a"是字符串。 2、 不能把一个字符串赋给一个字符变 量。如c="a"、c="Hello! "都是错误的。
请看教材52页 注意: 1、'a'是字符, "a"是字符串。 2、 不能把一个字符串赋给一个字符变 量。如c="a"、c="Hello! "都是错误的。 3、C语言中没有字符串变量,可以用字符数组来表示。 ? ‘a’和“a”的区别主要从存储形式上进行解释。
39
总结:字符与字符串的区别有哪些? 定界符不同:字符常量使用单引号,而字符串常量使用双引号;
长度不同:字符常量的长度固定为1,而字符串常量的长度,可以是0,也可以是某个整数; 存储要求不同:字符常量存储的是字符的ASCII码值,而字符串常量,除了要存储有效的字符外,还要存储一个结束标志’\0’。
40
(四) 不同类型数据间的转换 (一) 隐式转换(自动转换) (二) 显式转换(强制转换)
在C语言中,整型、实型和字符型数据间可以混合运算(因为字符数据与整型数据可以通用)。
41
(一)隐式转换(自动转换) 运算转换------不同类型数据混合运算时 赋值转换------把一个值赋给与其类型不同的 变量时
转换发生条件 先转换、后运算 运算转换------不同类型数据混合运算时 赋值转换------把一个值赋给与其类型不同的 变量时 输出转换------输出时转换成指定的输出格式 函数调用转换------实参与形参类型不一致时 转换 在C语言中,整型、实型和字符型数据间可以混合运算(因为字符数据与整型数据可以通用)。 如果一个运算符两侧的操作数的数据类型不同,则系统按“先转换、后运算”的原则,首先将数据自动转换成同一类型,然后在同一类型数据间进行运算。
42
隐式转换(自动转换) 转换规则 1、纵向向上的箭头表示不同类型的 转换方向(由低类型转化为高类 型),不表示转换所经的步骤。
说明: 必定的转换 运算对象类型 不同时转换 double float long unsigned int char,short 高 低 转换规则 1、纵向向上的箭头表示不同类型的 转换方向(由低类型转化为高类 型),不表示转换所经的步骤。 2、横向向左的箭头表示必须的转换。 详见教材54页 在C语言中,整型、实型和字符型数据间可以混合运算(因为字符数据与整型数据可以通用)。 如果一个运算符两侧的操作数的数据类型不同,则系统按“先转换、后运算”的原则,首先将数据自动转换成同一类型,然后在同一类型数据间进行运算。转换规则如图2-5所示。 1)横向向左的箭头,表示必须的转换。char和short 型在运算时必须转换成 int 型,float型在运算时必须转换成double型。 2)纵向向上的箭头,表示不同类型的转换方向。 例如,int型与double型数据进行混合运算,则先将int型数据转换成double型,然后在两个同类型的数据间进行运算,结果为double型。 注意:箭头方向只表示数据类型由低向高转换,不要理解为int型先转换成unsigned型,再转换成long型,最后转换成double型。
43
思考:根据已知变量定义及赋值语句,计算以下表达式的值,并说明每一步所得结果的数据类型。
int i; float f; double d; long e; …… i=2; f=2.5; d=3.9; e=3; 10+‘a’+i*f-d/e double 107 5.0 1.3 112. 0 110. 7 int double double double
44
(要转换成的数据类型)(被转换的表达式)
(二)显式转换(强制转换) (要转换成的数据类型)(被转换的表达式) 注:当被转换的表达式是一个简单表达式时,外面的一对圆括号可以缺省。 一般形式 float x,y; x=2.3 ; y=4.5; (int)(x+y) // (int) (int)x+y // (double) 举例 数据类型强制转换的一般格式为: (要转换成的数据类型)(被转换的表达式) 当被转换的表达式是一个简单表达式时,外面的一对圆括号可以缺省。 例如, (double)a (等价于(double)(a)) /*将变量a的值转换成double型*/ (int)(x + y) /*将x+y的结果转换成int型*/ (float)5 / 2(等价于(float)(5)/2) /*将5转换成实型,再除以2(=2.5)*/ (float)(5 / 2) /*将5整除2的结果(2)转换成实型(2.0)*/ 注意:强制转换类型得到的是一个所需类型的中间量,原变量或表达式类型并不发生变化。例如,(double)a 只是将变量a的值转换成一个double型的中间量,其数据类型并未转换成double型。 强制转换得到的是所需类型的中间变量,原变量或表达式的类型不变。 说明
45
结论:较高类型向较低类型转换时可能发生精度损失问题
思考:以下程序的输出结果是什么? 程序运行结果: #include <stdio.h> void main() { float x; int i; x=3.6; i=(int)x; printf("x=%f,i=%d",x,i); } x= ,i=3 结论:较高类型向较低类型转换时可能发生精度损失问题
46
? 举例:已知三角形的边长a、b、c,求三角形周长的一半。 程序运行结果: #include <stdio.h>
void main() { float a,b,c,s; a=3;b=4;c=5; s=1/2 * (a+b+c); printf("s=%8.2f",s); } s= 程序运行结果: 在求三角形面积时会用到周长的一半。 改为:1.0/ / /2.0 或 (float)1/2 1/(float)2) (float)1/(float)2 s= 改为:1.0/ (1/2.0) 或 (float)1/2 (1/(float)2)
47
五、运算符与表达式 (一)C运算符简介 (二)算术运算符和算术表达式 (三)赋值运算符和赋值表达式 (四)逗号运算符和逗号表达式
48
(一)、C运算符简介 详见55页! 分类 运算符 1、算术运算符 + - * / %
1、算术运算符 * / % 2、关系运算符 > < == >= <= != 3、逻辑运算符 ! && || 4、位运算符 << >> ~ | ^ & 5、赋值运算符 =及其扩展赋值运算符 6、条件运算符 ? : 7、逗号运算符 , 8、指针运算符 * & 9、求字节数运算符 sizeof 10、强制类型转换运算符 (类型) 11、分量运算符 12、下标运算符 [ ] 13、其他 如函数调用运算符() 分类 运算符 详见55页! 本章只介绍算术运算符和赋值运算符
49
两个整数相除的结果为整数,舍去小数部分。 当商为负数时,多采用“向零取整”的方法。
(二)、算术运算符和算术表达式 模运算符或求余运算符 基本算术运算符 * / % 两个整数相除的结果为整数,舍去小数部分。 当商为负数时,多采用“向零取整”的方法。 例: 5/3=1 -5/3=-1 说明 求余运算的两侧均应为整数 例:5%3=2 用算术运算符和括号将运算对象(也称操作数)连接起来的、符合C语法规则的式子。 算术表达式 常量、变量、函数等 例: a*b/c-1.5+’a’ 注意:两个整数相除,结果要求舍去小数部分,而不是四舍五入的方法。 通过例: a*b/c-1.5+’a’ 分析算术运算的优先级和结合性 如果加减乘除运算中有一个数为实数,则结果是double型。因为所有实数都按double型运算。 先乘除、后加减,有括号先算括号。 自左至右 优先级和结合性 说明 如果一个运算符两侧的数据类型不同,先自动进行类型转换,使二者具有同一类型,然后进行运算。
50
格式: 前置:++i , --i (在使用i之前,使i的值加(减)1) 后置:i++ , i-- (在使用i之后,使i的值加(减)1)
作用:自增运算符(++)使单个变量的值增1; 自减运算符(--)使单个变量的值减1。 自增、自减运算符 格式: 前置:++i , --i (在使用i之前,使i的值加(减)1) 后置:i++ , i-- (在使用i之后,使i的值加(减)1) i=i+1 i=i-1 i=3; …… A) j=++i; j=i++; j=-i++; 例1 A) j=4 i=4 j=3 i=4 j=-3 ? j,i j=-i++; 相当于j=-(i++); ++和--结合方向 是“自右至左”
51
例2 ? c, i 例3 ? i, j 例4 ? i=3; 两处i值都为3 …… A) c=(i++)+(i++);
B) a=i++; b=i++; c=a+b; 两处i值都为3 ? c, i A) c=6 i=5 B) c=7 i=5 例3 i=3; j=4; …… i+++j (i++)+j ? i, j 自左而右组合 i=4 j=4 表达式的值:7 例3中的自左至右不是指++运算符的结合性,而是指C编译系统在处理多个运算符连写情况时,多采用自左而右尽可能多的将若干个字符组成一个运算符。 例4 i=3; …… printf(“%d,%d”,i,i++) ? 函数参数自右至左求值 4, 3
52
说 明 (1) 自增、自减运算是C语言特有的,常用于循环语句中,使循环控 制变量加(或减)1,以及指针变量中,使指针指向下(或上)一个地址。
说 明 (1) 自增、自减运算是C语言特有的,常用于循环语句中,使循环控 制变量加(或减)1,以及指针变量中,使指针指向下(或上)一个地址。 (2) 自增、自减运算符,不能用于常量和表达式。 例如,5++、--(a+b)等都是非法的。 (3) ++和--的结合方向为自右至左。(P57) (4) 如果对一个变量的自增/自减运算,单独构成语句,而不是作为表达式的一部分时,前置和后置运算效果一样,都是使变量自加1。 如 i++;和 ++i;是一样的,都是使i加1。 (5) 在表达式中,连续使用同一变量进行自增或自减运算时,很容易出错,所以最好避免这种用法。
53
(三)、赋值运算符和赋值表达式 赋值运算符 简单赋值运算符:= 复合赋值运算符:+=, -=,*=,/=,%= ……
复合赋值运算符:+=, -=,*=,/=,%= …… 赋值运算符 简单赋值运算符的一般形式为: 变量 = 表达式 它的作用是将一个表达式的值赋给一个变量。 复合赋值运算的一般格式为: 变量 双目运算符 = 表达式 └──┬──┘ 复合赋值运算符 它等价于:变量 = 变量 双目运算符 (表达式)。只有当表达式简化为一个变量或一个常数时,两边的括号可以省略。 1.赋值运算 赋值符号"="就是赋值运算符,它的作用是将一个表达式的值赋给一个变量。 赋值运算符的一般形式为: 变量 = 赋值表达式 例如,x = y = (float)5 / 2 如果表达式值的类型,与被赋值变量的类型不一致,但都是数值型或字符型时,系统自动地将表达式的值转换成被赋值变量的数据类型,然后再赋值给变量。 思考题:假设变量num的数据类型为float,其值为2.5,则执行"num = (int)num"后,num的值等于多少? 2、复合赋值运算符是由赋值运算符之前再加一个双目运算符构成的。 复合赋值运算的一般格式为: 变量 双目运算符 = 表达式 └──┬──┘ 复合赋值运算符 它等价于:变量 = 变量 双目运算符 (表达式)。 当表达式为简单表达式时,表达式外的一对圆括号才可缺省,否则可能出错。 例如,x += /* 等价于x=x+3 */ y *= x + 6 /* 等价于y=y*(x+6),而不是y=y*x+6 */ C语言规定的10种复合赋值运算符如下: +=,-=,*=,/=,%=; /*复合算术运算符(5个)*/ &=,^=,|=,<<=,>>=; /*复合位运算符(5个)*/
54
赋值表达式 类型转换 例1 ? b 例2 例3 ? a,b 格式:<变量> <赋值运算符> <表达式>
格式:<变量> <赋值运算符> <表达式> 赋值表达式的值:被赋变量的值 赋值表达式 转换条件:当赋值运算符两侧的数据类型不一致时 转换原则:转换为被赋值变量的类型。具体见P59。 类型转换 例1 float a; int b; a=1.2; b=a*3; ? b b=3 例2 a+=3; x*=y+8 a=a+3; x=x*(y+8) 例3 a=b=5; a=7+(b=8) a=5 ;b=5 a=15;b=8 ? a,b 自右而左 的结合性
55
(四)、逗号运算符和逗号表达式 , 逗号运算符 逗号表达式 说明 表达式1,表达式2,… … ,表达式n
1、逗号表达式的求解过程为自左至右,依次计算各表达式的值,最后一个表达式的值即为整个逗号表达式的值; 2、逗号运算符的优先级最低。 3、使用逗号表达式的目的通常是想分别得到各个表达式 的值,而并非一定要得到整个表达式的值。 4、常用于for循环语句中,除此以外很少使用。 说明 C语言提供一种用逗号运算符","连接起来的式子,称为逗号表达式。逗号运算符又称顺序求值运算符。 1.一般形式 表达式1, 表达式2, ……, 表达式n 2.求解过程 自左至右,依次计算各表达式的值,"表达式n" 的值即为整个逗号表达式的值。 例如,逗号表达式"a = 3 * 5, a * 4"的值=60:先求解a = 3 * 5,得a=15;再求a * 4 = 60,所以逗号表达式的值=60。 又例如,逗号表达式“(a = 3 * 5, a * 4), a + 5”的值为20:先求解a = 3 * 5,得a=15;再求a * 4=60;最后求解a + 5=20,所以逗号表达式的值为20。 注意:并不是任何地方出现的逗号,都是逗号运算符。很多情况下,逗号仅用作分隔符。
56
例1 ? a 例2 ? a 例3 ? a a=3 a=(3*5,a*4) a=12 a=3 a=3*5,a*4 a=15 表达式的值为60
表达式的值为20 例3 ? a (a=3*5,a*4),a+5
57
作 业 P84: , 3.8,3.9, 3.10, 3.12 (其中, 3.6 、 3.7、 3.10是实验)
58
While((c=getchar())!=‘\n’)
{ if (c>=‘a’&&c<=‘z’ || c>=‘A’ && c<=‘Z’) c=c-4; if(c>=‘a-4’&&c<‘a’ || c>=‘A-4’ && c<‘A’)) c=c+26; printf(“%c”,c); }
59
求三个数的最大值 法一: max=a; if(b>max) max=b; if(c>max) max=c; 法二:
max= (a>b) ?a:b max=(max>c) ?max:c 可以定义一个函数 maxab(a,b) max=maxab(a,b); max=maxab(max,c);
60
法三: if(a>b) if(a>c) max=a; else max=c; else if(a>c) max=b; else max=c; 法四: if(a>b &&a>c) max=a; if(b>a&&b>c) max=b; if(c>a&&c>b) max=c;
61
#include <iostream.h>
int a; float b; char c; char s[3]=“dfd”; scanf (“%d”,&a); printf(“a=%d”,a); cin>>a; cout<<a; scanf (“%f”,&b); printf(“b=%f”,b); cin>>b; cout<<b; scanf (“%c”,&c); printf(“c=%d”,c); cin>>c; cout<<c;
Similar presentations