Presentation is loading. Please wait.

Presentation is loading. Please wait.

第2章 基本数据及其运算 本章学习的目标: 1、掌握基本数据的各种表示,基本数据常数的书写方法;

Similar presentations


Presentation on theme: "第2章 基本数据及其运算 本章学习的目标: 1、掌握基本数据的各种表示,基本数据常数的书写方法;"— Presentation transcript:

1 第2章 基本数据及其运算 本章学习的目标: 1、掌握基本数据的各种表示,基本数据常数的书写方法;
2、掌握算术运算、关系比较运算、逻辑运算、赋值运算等运算的意义; 3、掌握表达式的书写方法; 4、了解单个字符输入输出方法,掌握整数、浮点数、字符、字符串的格式输入和格式输出方法。

2 2.1 基本类型数据 2.2 输入和输出基础 2.3 数据运算 2.4 表达式

3 2.1 基本类型数据 基本数据有三种: 整数 浮点数 字符
整数 浮点数 字符 有无穷多的不同整数、浮点数、字符,但计算机只能用有限的二进位表示不同的数据。所以, 计算机只能表示有限的整数、有限的浮点数和有限的字符

4 整型数据 整型数据按其数值范围划分成三种: 按值内部的最高位不同理解又分两类: 整数是不带小数点和指数符号的数据
1.基本型:用 int 标记 2.短整型:用 short int 标记,简写为 short 3.长整型:用 long int 标记,简写为 long 按值内部的最高位不同理解又分两类: 1.带符号:存储单元最高位作为符号位 2.不带符号:存储单元中全部二进位用作存放数据本身,而没有符号位。 表示方法: unsigned int、 unsigned short、 unsigned long

5 常用的整数表示的数值范围  用16个二进位存储一个整数  用32个二进位存储一个整数 带符号整数的数值范围是
带符号数值范围: ~ ( -215 ~ ) 不带符号数值范围 0 ~ (0 ~ )  用32个二进位存储一个整数 带符号整数的数值范围是 ~ ( -231 ~ ) 不带符号整数的数值范围是 0 ~ ( 0 ~ )

6 带符号的整型数据与无符号整型数据的区别。
设整数用16位二进位表示 ↑最高位是符号位:0表示正 其余各位是数据位 带符号整数,值为32767(即215-1) 带符号整数,值为 -1(负数用补码表示) 16位二进位都是数据位 无符号整数,值为65535(即216-1)

7 在计算机中,负整数用补码表示。 若x是一个正整数,则-x的补码表示是x的反码加上1。 用补码表示负整数是为了简化整数的运算。

8 整型常量的书写形式  十进制整数:如 0,123,-45。
 八进制整数:以数字0开头,并由0~7组成的数字符序列。如:0123表示八进制整数,其值等于十进制整数为:1*82 + 2* = 83  十六进制整数:以0x(或0X)开头,并由十六进制数的数字符组成的数字符序列。表示十六进制数的数字符有 16 个:0~9 和 A、B、C、D、E、F,其中六个字母也可以小写。 如:0x123表示十六进制整数,其值等于十进制整数为:1* * = 291;0xabc,其值等于10* * = 2748。

9 长整型整数和无符号整数的表示  long 型整数:在整型常数后加字母 L 或 l,即为long 型整型常数。 例如:0L、132L 等。  不带符号的整型:在整型常数后加字母 U 或 u,即为 unsigned 型整型常数。例如:1U、122U 等。  不带符号的 long 型整数:在整型常数后同时加上字母 U 和 L,表明该整型常数是 unsigned long 型。 例如 22UL、35LU 等。

10 浮点型数据 浮点型数是带有小数点或指数符号的数值数据。 浮点型数据应考虑:数值大小(范围)、有效位数多少(精度)两个方面。 浮点型有三种:
1. 单精度型:用 float 标记。 如: float x, y; 2. 双精度型:用 double 标记。 如: double result; 3. 长双精度型:用 long double 标记。 如:long double z;

11 1. float 型 在内存中占用4个字节(32个二进位),约7个十进位有效数字,能表示绝对值约为10-38~1038。 2. double 型 在内存中占用8个字节(64个二进位),约15个十进位有效数字,能表示绝对值约为 ~ 10308。 3. long double 型 在内存中占用更多的字节,有更多的有效数字位数。但在VC中与double一样,也只占8个字节。

12 浮点型常量的一般书写格式 正负号 整数部分.小数部分 指数部分
浮点型常量的一般书写格式 正负号 整数部分.小数部分 指数部分 (1)指数部分e(或E)之前必须有数字,且e后面必须为整数。 (2)整数部分和小数部分可以任选,但不可同时没有。 (3)在浮点型常数后加f标识,表示float;加l(或 L)表示long double 型,而无后缀符的浮点型常数被认为是 double 型。 合法的浮点型常数:7.、.457、1E5、1.5e-6 不正确的浮点型常数: E4、.E5、4.0E 1.5、1.5f、1.5L 分别表示 double型、float型和long double型浮点型常数

13 (4)接受的浮点型值与书写的浮点数会有误差。
例如: float x = ; 因x只有约7位有效数字,浮点数 所对应的二进制形式中,超出存储位数的那些位就不会被存储。 (5)由于浮点数运算的计算误差,两个数学上完全等价的计算公式,会因计算顺序不同,得到的两个结果不能保证相等。 常用判别两浮点数非常相近的表达式 绝对误差 fabs(x-y) < 1e-6 相对精度 fabs(x-y) <= fabs(x*1e-6)

14 字符型数据 字符型数据用于表示一个字符值。 字符型数据的内部表示是字符的 ASCII 代码(二进制形式)。
字符型数据的类型符用 char 来标记。 如:char c1,c2; 字符型数据在内部用一个字节(8位二进位)表示,也可当作一个8位的整型数据。

15 字符型常量书写方法 普通字符: 用单引号括起一个字符。 如 ’a’。
特殊字符: 用’\字符或字符列’来标记。 如:’\r’、’\n’、 ’\t’。 见P.17 表2-1。 换行符’\r’:表示对当前行作重叠输出 回车符’\n’:使以后的输出从下一行首开始 制表符’\t’:使输出位置横向跳至下一个输出区开始列。

16 请注意:打印机与显示屏输出的组织方法稍有不同
打印机: 仅当一行字符填满或遇换行符时才输出,即整行一次性输出。当输出空格符或制表符时,作跳格处理,不用空格符填充。 显示器 逐个字符输出,空格符及制表符经过位置都用空格符输出。以上区别,仅当输出字符列中有回车符时才会发生差异。

17 表2-1 特殊字符表 标记形式 功 能 \n 换行符(打印位置移到下一行首) \t 制表符,横向跳格到下一个输出区首 \v 竖向跳格符
标记形式 功 能 \n 换行符(打印位置移到下一行首) \t 制表符,横向跳格到下一个输出区首 \v 竖向跳格符 \b 退格 \r 回车(打印位置移到当前行的首) \f 走纸换页 \a 产生响铃声 \\ 反斜杠字符 \ \’ 单引号符 ’ \” 双引号符 ” \ddd ddd为1至3个8进制数字,以该值为ASCII码的字符 \xhh hh为1至2个16进制数字,以该值为ASCII码的字符

18 字符型常量与字符串常量的区别 字符型数据可与整型数据混合运算 如:"China",机内:
字符串常量用双引号括起来的字符序列。 如:"China",机内: 注意:字符型常量’a’与字符串常量"a"不同,如:char c="a"错误。 字符型数据可与整型数据混合运算 字符型数据以 ASCII 代码的二进制形式存储,与整数的存储形式相类似。因此,在C程序中,字符型数据和整型数据之间可以通用,字符型数据与整型数据可混合运算。 C h i n a \0

19 【例2.1】字符型数据与整型数据通用。 #include <stdio.h> void main()
{ char c1, c2; /* 定义两个字符型变量 */ c1 = 97; /* ’a’的 ASCII 码值为 97 */ c2 = c1+1; /* 字符型与整型数据混合运算 */ printf("c1 = %c, c2 = %c\n", c1, c2); printf("%c's ASCII code = %d\n", c2, c2); } 程序输出: c1 = a, c2 = b b's ASCII code = 98

20 表2.2 基本数据类型的存储方式和取值范围 数据类型 类型符 占用字节数 数值范围
表2.2 基本数据类型的存储方式和取值范围 数据类型 类型符 占用字节数 数值范围 整型 int ~ 无符号整型 unsigned [int] ~ 短整型 short [int] ~ 32767 无符号短整型 unsigned short [int] ~ 65535 长整型 long [int] ~ 无符号长整型 unsigned long [int] ~ 单精度 float × ~ 3.4×1038 双精度 double × ~ 1.7×10308 长双精度 long double × ~ 1.7×10308 字符型 char ~ 127 无符号字符型 unsigned char ~ 255

21 2.2 数据输入和输出 在C程序中,数据的输入和输出是分别通过调用格式输入函数scanf()和格式输出函数printf()来实现的。
在C++程序中,主要是通过调用输入输出的流对象cin和cout来实现的。 在输入操作中,输入字节流从输入设备流向内存 在输出操作中,输出字节流从内存流向输出设备

22 字符输出函数 格式: putchar(c) 功能:将一个字符输出到标准输出设备(显示器) 输出ASCII代码为c值的字符。 说明: 1. c 是实参,可以是字符型常量、整型常量(包括控制字符和转义字符)、字符型变量、整型变量等。 2. 使用字符输入输出函数,在程序首必须书写 #include <stdio.h>

23 【例2.2】使用putchar( )示例 #include <stdio.h> void main()
{ char ch; int i; ch = ’h’; i = ’i’; putchar(’C’); /* 输出字符 C */ putchar(ch); /* 输出字符 h */ putchar(i); /* 输出字符 i */ putchar(’n’); /* 输出字符 n */ putchar(’\141’); /* 输出字符 a (141为八进制)*/ putchar(’\n’); /* 输出一个回车符 */ } 运行该程序将输出 China

24 字符输入函数 格式:getchar( ) 功能:从标准输入设备上(通常为键盘)读取 一个字符的ASCII代码。 说明:
1. 该函数没有参数,它只能接受一个输入字符。 2. getchar()得到的字符可以赋给一个字符变量或整型变量,也可以不赋给任何变量。 例如: putchar(getchar())

25 【例2.3】使用putchar( )示例 #include <stdio.h> void main() { char c ;
c = getchar(); /* 调用getchar(),无参数 */ putchar(c); /* 输出读入的字符 */ putchar(’\n’); /* 输出一个回车符 */ } 若:程序运行时从键盘键入字符 Z 和回车 则:程序输出 Z ( 其中变量 c 的值为 ’Z’)

26 #include <stdio.h>
void main() { char c1, c2; c1 = getchar(); /* 输入一个字符 */ c2 = getchar(); /* 再输入一个字符 */ putchar(c1); putchar(c2); printf("code1 = %d code2 = %d\n", c1, c2); } 若:程序运行时从键盘键入字符 Z 和回车 则:程序输出 Z code1 = 90 code2 = 10 (90和10分别是'Z'和回车的ASCII码值)

27 格式输出函数 格式:printf(格式控制字符串,输出项,输出项,…) 功能:将输出项按指定格式排版输出到标准设备上。
其中:格式控制字符串是用双引号括起来的字符串 格式控制字符串包含三类字符: 1. 普通字符:要求按原样输出的字符。 2. 转义字符:要求按转义字符的意义输出。如’\n’表示输出时回车换行,’\b’表示退格等。 3. 格式转换说明:由“%”和格式字符组成,如%d、%f、%c、%s等。 例: int a=3, b=5; printf("a=%d,b=%d,a+b=%d\n",a,b,a+b); 结果:a=3,b=5,a+b=8

28 格式转换说明 一般形式: %[-][+][ ][#][w][.p][h/l/L]输出格式符

29 输出格式符表 格式符 意 义 d或i 整型数据以十进制形式输出 o 无符号整型数据以八进制形式输出 x或X 无符号整型数据以十六进制形式输出
格式符 意 义 d或i 整型数据以十进制形式输出 o 无符号整型数据以八进制形式输出 x或X 无符号整型数据以十六进制形式输出 u 无符号整型数据以十进制形式输出 c 以单个字符形式输出 s 以字符串形式输出 f 以浮点形式输出实型数据 e或E 以标准指数形式输出实型数据 g或G 以f或e格式输出实型数据 p 指针值转换成一串可显示的字符输出 n 记录已输出的字符个数 % 输出一个字符%

30 输出格式修饰符 w 域宽说明。表示输出数据的字符数。若输出字符数>w,则输出实际字符数;若输出字符数<w,左边补空格(若左边有-,则在右边补空格)。若w有前导0,则以字符0作填充字符。 域宽说明为*,这时域宽大小由下一个输出项的整数值指出。 例如:printf("%*c",10, ’*’) 则:等同与%10c,即先输出9个空格,再输出一个*。

31 - 左对齐标志。当输出字符个数少于w时,右边补填充符。缺省时右对齐,即左边补填充符。
+ 正数也带符号输出。在输出数值前加符号‘+’或‘-’。缺省时,只对负数输出有负号‘-’。 空格 在输出数值前加空格。若’+’和空格同时出现,空格格式修饰说明被忽略。 # 对八进制数前加0;对十六进制数前加0x;对浮点数总显示小数点。

32 .p 对e、f格式,指明小数点之后输出的位数,缺省时,p=6。
对s格式,指明最多输出字符串的前p个字符,多余截断。 h/l/L 指明输出项的类型。 h与整型格式符一起使用,表示输出项是 short int 或 unsigned short int。 l与整型格式符一起使用,表示输出项是 long int 或 unsigned long int。 L与实型格式符一起使用,表示输出项是 long double型。

33 格式输出实例 (1)printf("%d,%+6d,%-6d,%ld\n", 1234, 1234, 1234, L) (2)printf("%#o,%4o,%6lo\n", 045, 045, -1); (3)printf("%#x,%4x,%6lX\n", 045, 045, -1); (4)printf("%d,%4u,%lu\n", u, u, -1); (5)printf("%c,%-3c,%2c\n", 045, ’a’, ’a’);// 八进制045对应的字符是% (6)printf("%f,%8.3f,%-7.2f,%.7f\n", f, f, f, ); 以上6 行代码的输出内容依次是: 045, 45, 0x25, 25,FFFFFFFF -1, , %,a , a , , ,

34 说明 1. 注意实型数据的有效位数。不要以为凡是打印或显示的数字都是准确的。因为,float型只有7位有效数字,double型有15位有效数字。实际上,因计算过程中的误差积累,通常不能达到所说的有效位数。 2. 注意%g格式的特殊性,当它选择 整数部分.小数部分 形式时,因格式修饰说明.p在e格式中的意义是指明精度,所以p的值是整数部分位数与小数部分位数之和(不是f格式中的小数位数)。 3. 格式修饰说明#表示:无意义的0及小数点照常输出;若无#,则不输出无意义的0及小数点。

35 进一步的例子: float g1 = 12.34f, g2 = 0.0f; double d = , g = ; int count; /* 记录已输出的字符数 */ printf("%g,%g,%#g,%#g%n\n",g1,g2,g1,g2,&count); printf("COUNT = %d\n", count); printf("%f,%g,%g,%g,%.8g",g1,g1,d,g,g) 将输出: 12.34,0, , COUNT = 23 ,12.34, ,123457,

36 格式输入函数 scanf(格式控制字符串,储存地址,存储地址,…) 格式: 功能:从标准设备读入数据,并按格式存储到对应的数据存储地址中。
其中:格式控制字符串是用双引号括起来的字符串 格式控制字符串有: 1. 空白类字符(空格符或制表符或换行符) 输入时忽略,直到遇到下一个非空白类字符。 2. 普通字符(不包括%) 输入时,这些字符要求输入。 3. 格式转换说明(以字符’%’开头) 输入的内容按要求进行格式转换。

37 格式转换说明的形式 %[*][w][h/l/L] 输入格式符 * 星号(赋值抑制符),跳过一个输入数据项。
* 星号(赋值抑制符),跳过一个输入数据项。 w 整型常数(域宽说明),输入数据项的字符宽度。若实际输入字符的宽度<w,以实际宽度为准。 h/l/L 长度修饰符,指明输入的是short int、long int 或 long double型。 例如:int i,j,k ; scanf(”%d%d%d”, &i, &j, &k); 为变量 i,j,k 输入数据。其中 &i,&j,&k 分别表示变量 i,j,k 的存储地址。

38 输入格式符表 格式符 意 义 d 以十进制形式输入整型数据 o 以八进制形式输入整型数据 x 以十六进制形式输入整型数据
格式符 意 义 d 以十进制形式输入整型数据 o 以八进制形式输入整型数据 x 以十六进制形式输入整型数据 u 输入无符号整型数据 c 输入字符数据 s 输入字符串 e、f、g 输入实型数据 p 输入指针值 n 记录已输入的字符个数 [] 输入匹配字符串 % 匹配输入字符

39 说明 1. 格式控制字符串之后给出的是变量地址,而不是变量名(除非是指针)。 例如:为整型变量 n 输入数据
写成: scanf("%d", n) 是不正确的 应写成: scanf("%d", &n) 2. 在格式控制字符串中,如果有普通字符,则在输入数据时应输入与这些字符相同的字符。 例如: scanf("%d,%d", &i, &j) 正确输入: 1,2 错误输入: 1 2

40 3. 在用"%c"格式入字符时,空白类字符和转义字符都作为有效字符输入。若要取输入的一串空白类字符之后的第一个非空白类字符,可采用格式 " %c"。
4. 在输入数值数据和字符串时,遇以下情况,就认为该数据结束: ⑴ 遇空白类字符:空白符、制表符、换行符。 ⑵ 已读入由宽度所指定的字符数:如 "%4d" 多至 4 个数字符。 ⑶ 对于输入数值数据,下一个字符不能构成正确的数据格式。

41 scanf("%4c", c); /* 输入4个字符 */ 输入: abcd 结果:
6. 请注意c格式符和s格式符的区别。 例: char c[100], s[100]; scanf("%4c", c); /* 输入4个字符 */ 输入: abcd 结果: scanf("%4s", s); /* 忽略前导空格 */ a b c d a b c d \0

42 7. e、f、g格式用来输入实数。如格式转换说明中含有长度修饰说明l,则为double型变量地址;含有长度修饰说明L,则为long double型变量地址;否则,为float型变量地址。
例如:float x; double y; long double; scanf("%f%lf%Lf",&x,&y,&z); 8. [匹配字符]格式 例如:格式"%[xy]" ,当输入字符序列中,只由字符x和y组成的字符序列才能与之匹配。 例如:格式"%[^xy]" ,当输入字符序列中,除字符x和字符y之外的其他字符才能与之匹配。 说明:从当前输入字符开始到第一个不能与之匹配的字符为止。

43 对应下列输入代码,要让变量i和j值分别为12和234,试指出合理的输入。
(1)scanf("%d,%d”,&i,&j); // 不能写成scanf("%d,%d”,i,j) (2)scanf("%d%d”,&i,&j); 对于(1),"%d,%d”中间的逗号是普通字符,必须按原样输入。所以,输入是:12,234 对于(2),两个输入格式之间没有其它字符,输入时,数据以一个或多个空格符分隔,也可以用Tab键、Enter键分隔。所以,可以输入:

44 对应下列输入代码,要让变量i和j值分别为12和234,试指出合理的输入。
(3)scanf("%2d%3d”,&i,&j); // 指定数据输入的数字符个数,分别是2个和3个 (4)scanf("%d%*d%d”,&i,&j) 对于(3),格式指定数据输入的数字符个数,分别是2个和3个,输入数据可以用空白符分隔,也可以有前2个数字符为变量i输入,后3个数字符为变量j输入。例如,输入12234也能满足要求,将12赋值给变量i,将234赋值给变量j。 对于(4),格式中的第2个输入格式有赋值抑制符,所以要输入3个整数,其中第二个整数用于输入不赋值的要求。只要3个整数有空白符分隔即可,例如,输入:

45 进一步的例子: int i; char c; float x; scanf("%d%c%f", &i, &c, &x) 若输入字符为:123a123x.26 则:变量i为123,变量c为字符a,变量x为123.0。 int i, j; scanf("%3d%*4d%d", &i, &j) 若输入字符为: 则: 变量i为123,j为78。其中数据 456 因赋值抑制符*的作用被跳过。

46 输入输出流cin和cout 在C++程序中,使用cin或cout流对象必须在程序的开头使用以下预处理命令把头文件iostream.h包含到程序中: #include <iostream.h> 头文件iostream.h包括了在输入输出流操作中所需的所有信息。一般情况下,cin对应标准输入流设备(通常指键盘),cout对应标准输出流设备(通常指显示器)。

47 输出流cout 使用输出流cout输出数据的一般格式为 cout << 表达式1 << 表达式2 << …… << 表达式n; 功能:从屏幕当前光标位置处开始,将各表达式的值依次输出。

48 说明: (1) << 称为流插入运算符,表示将表达式的数据依次插入到内存缓冲区,当遇到缓冲区满、输出换行符endl(或’\n’)、或清缓冲区的流格式控制符flush时,才将缓冲区中的数据输出到显示屏幕上,并清空缓冲区。 (2) 一个流插入运算符后只能插入一个输出项,如果有多个输出项,需有多个流插入运算符。例如: cout << x, y, z;// 错误,三个输出项只有一个流插入运算符 cout << x << y << z; // 正确,三个输出项应有三个流插入运算符

49 输入流cin 使用输入流cin输入数据的一般格式为 cin >> 变量1 >> 变量2 >> …… >> 变量n 功能:程序暂停执行,等待用户从键盘上输入数据。用户输入了所有数据后再以回车键表示输入结束。此时,程序将用户输入的数据依次送入各变量,并继续运行后继语句。

50 说明: (1) >>称为提取运算符,表示将内存缓冲区中的数据提取出来,并依次赋值给各个变量。 (2) 输入数值数据时,前导的空白类字符被自动忽略,符合类型要求的数据被接受,遇到不符合类型要求的字符结束一个数值数据的输入。通常,连续输入多个数值数据时,数据之间以空白符或回车键作为数值数据的分隔符。 (3) 输入字符数据时,键入的每个字符都被输入和存储。如果一次连续输入多个字符数据,字符之间不要另外输入分隔符。 (4) 与调用输入函数scanf()不同的是,变量名前不能有取地址运算符&。

51 例如: int x; char c1, c2; cin >>c1 >> x >> c2; cout << “c1 = “ << c1 << “,c2 = “ <<c2 <<”,x = “<<x <<endl; 如果输入:a123b 则输出为:c1 = a,c2=b,x=123

52 又例如: int x, y; cin >> x >> y; cout << ”x = ” << x << ” , y = ” << y; 如果输入: 则输出为:x = 123 , y = 456 如果输入:123,456 则输出又为:x = 123 , y = 0 由于逗号不是数值数据之间的分隔符,引起为变量y输入错误。 输入的数据必须与对应的变量类型相符,否则也可能导致输入不正确。例如,给整型变量输入一个浮点数,则遇小数点时就结束输入整数。

53 例如: int x; float y; char z; cin >> x >> y >> z; cout << ”x = ” << x << ” , y = ” << y << ”, z = ” << z << endl; 如果输入: a 输出为:x = 123 , y = 0.4 , z = 5 首先从输入流中提取123赋值给x。 继续往后提取0.4赋值给变量y;跳过空白分隔符再提取5赋值给变量z,因为z是字符型变量,只能取1个字符。 如果一次输入流调用没有把缓冲区中的字符用完,则剩余的字符可供以后输入流调用继续使用。

54 输入输出流的格式控制 C++提供了两类流格式控制符: 无参格式控制符 有参格式控制符 其中无参格式控制符在头文件iostream.h中定义 有参格式控制符在头文件iomanip.h中定义

55 流格式控制符 含 义 参 数 dec 数据用十进制表示 无 oct 数据用八进制表示 无 hex 数据用十六进制表示 无 endl 插入换行符(同’\n’) 无 flush 清缓冲区 无 setfill(c) 用c作为填充字符 有 setprecision(n) 设置浮点数有效数字为n位。在固定小数位数(fixed) 和指数形式输出(scientific)时,n表示小数位数 有 setw(n) 设置数据宽度 有 setiosflags(ios::fixed) 设置浮点数以固定小数位数形式输出 有 setiosflags(ios::scientific) 设置浮点数以指数形式输出 有 setiosflags(ios::left) 设置数据左对齐显示 有 setiosflags(ios::right) 设置数据右对齐显示 有 setiosflags(ios::lowercase) 十六进制的字母用小写 有 setiosflags(ios::uppercase) 十六进制的字母用大写 有

56 【例2.6】用流格式控制符实现输出的程序实例。
#include <iostream.h> #include <iomanip.h> int main() { int a = 54321; double b = ; cout << setiosflags(ios::right) << setw(10) << a << endl; // 右对齐,宽10 cout << setw(10) << b << endl; // 默认为6位有效数字 cout << setfill(’$’) << setw(10) << a << endl; // 用’$’代替前导空格 cout << hex << a << ”,” << setiosflags(ios::uppercase) << a << endl; // 加setiosflags(ios::uppercase),让十六进制中的字母使用大写 cout << setprecision(8) << b << ”,” // 有效数字为8位 << setiosflags(ios::scientific) << b << endl; // 指数形式,小数位数为8位 return 0; }

57 输出结果如下: 54321 $$$$$54321 d432,D431 , E+002

58 2.3 数据运算  运算符的优先级 优先级用来标志运算符在表达式中的运算顺序。优先级高的先运算,优先级低的后运算。
2.3 数据运算  运算符的优先级 优先级用来标志运算符在表达式中的运算顺序。优先级高的先运算,优先级低的后运算。 如:x-y*z 相当于 x-(y*z)  运算符的结合性 在优先级相同情况下,表达式的计算顺序由结合性来确定。大多数运算符的结合性是从左至右,只有单目、三目和赋值运算符的结合性是从右至左的。如:x=a+b-c; a=b=c=1.5;

59 赋值运算 最简单形式: 变量 = 表达式 执行过程: (1)计算表达式
最简单形式: 变量 = 表达式 执行过程: (1)计算表达式 (2)如表达式类型与变量类型不一致,将表达式值的类型转换成变量的类型。 (3)将值赋给变量 说明:赋值运算符的结合性是“自右至左”。 例1:int x; double y; y = x = 3.5 结果:x的值为3,y的值为3.0 例2:i=4+(j=7),使j值为7,i值为11 例3:i=(j=3)+(k=8),使j值为3,k为8,i为11

60 复合赋值运算 在赋值运算符“=”之前加上其他运算符,可构成复合赋值运算符。 复合赋值运算符:
+=、-=、*=、/=、%=、<<=、>>=、&=、^=、|= 例:x + = 等效于 x = x + 5.0 (将“x +”移到“=”右侧) x * = u + v 等效于 x = x * (u + v) a + = a - = b + 2 等效于 a = a+(a=a-(b+2))

61 记θ为某个双目运算符,复合赋值运算 x θ= e 的等效表达式为 x = x θ (e) 当e是一个复杂表达式时,等效表达式的括号是必需的。 赋值运算符和所有复合赋值运算符的优先级全部相同,并且都是“自右至左”结合,它们的优先级高于逗号运算符,低于其它所有运算符。

62 算术运算 单目: +(取正)、-(取负) 双目:+(加)、-(减)、*(乘)、/(除)、%(求余)、++(自增)、--(自减)
说明:两个整数相除结果为整数,如: 7/4 = 1。 求余运算符(%): 要求参与运算的两个分量均为整型数据,如 5 % 3 = 2。一般来说,求余运算所得结果的符号与被除数的符号相同。 如: -5 % 3 = -2 , 5 % -3 = 2 。 加、减、乘、除和求余运算都是双目运算符,结合性都是从左至右的。 取正(+)、取负(-)是单目运算符,结合性是从右至左,优先级高于 +、-、*、/、% 等双目运算符。

63 自增运算符:前缀 ++ 一般形式:++ 变量 说明: 变量限制为: 基本类型变量、指针变量、数组元素等。
自增运算符:前缀 ++ 一般形式:++ 变量 说明: 变量限制为: 基本类型变量、指针变量、数组元素等。 变量的数据类型必须是整型或某种指针类型。 运算规则:先使变量值增加1个单位,再引用该变量,即以增1后的变量值为结果。 例: ++x 等价 x=x+1 如果 x是指针,并且是指向数组的某个元素,则 ++x 使它指向数组的后一个元素。

64 自增运算符:后缀 ++ 一般形式: 变量 ++ 说明:对变量的要求同前缀 ++ 。 运算规则:
自增运算符:后缀 ++ 一般形式: 变量 ++ 说明:对变量的要求同前缀 ++ 。 运算规则: 先引用变量,然后使该变量增加1个单位。 例:i,j 为整型变量,且 i 现有值为 4 ① j = ++i; 结果:i = 5 , j = 5 ② j = i++; i = 5 , j = 4

65 自减运算符:前缀 -- 自减运算符:后缀 -- 一般形式:-- 变量 运算规则:先使变量值减少1个单位,再引用该变量。
自减运算符:前缀 -- 一般形式:-- 变量 运算规则:先使变量值减少1个单位,再引用该变量。 自减运算符:后缀 -- 一般形式: 变量 -- 运算规则:先引用变量,然后使该变量减少1个单位。

66 例如: i = 4; j = ++i; // i结果为5,j的结果为5 j = i++; // i结果为5,j的结果为4 j = --i; // i结果为3,j的结果为3 j = i--; // i结果为3,j的结果为4 由上述例子说明,对变量采用自增(或自减),用前缀形式或用后缀形式,对变量本身来说,效果是相同的,但表达式的值不同。前缀形式是变量运算之后的新值,后缀形式是变量运算之前的值。

67 自增/自减运算符注意事项: ++和--运算符只能用于变量,不能用于常量或表达式。如 4++ 或 (i+j)++ 都是不合法的。
++和--是带有副作用的运算符。不要在一个表达式中对同一变量多次使用这样的运算符。如i=4,表达式(i++)+(i++)的值为 8,表达式(++i)+(++i)的值为12。 如i=4,在printf("%d %d\n", i, i++)中,输出的结果可能是4 4(从左到右),也可能是5 4(从右到左)。

68 关系运算和逻辑运算 关系运算符:<、<=、>、>=、==、!=
关系运算符用于对两个值进行关系比较,判定比较条件是否满足。在C中,条件满足的值为1;条件不满足为 0。 优先级:<、<=、>、>= 高于 ==,!= 如:表达式 x > y == c < d 等价于 (x > y) == (c < d) 关系运算符的优先级低于算术运算符的优先级 如: x > u+v 等价于 x > (u+v)

69 逻辑运算符 &&(逻辑与)、||(逻辑或)、!(逻辑非)
其中:运算符 && 和 || 是双目运算符,要求有两个运算分量;运算符 ! 是单目运算符,只要求一个运算分量。 优先级:!、&&、|| 说明:逻辑运算结果也是一个逻辑量,即真(用1表示)或假(用0表示)。判定一个运算分量的值为真或假时,以运算分量的值不等于零为真,值等于0 为假。

70 逻辑运算真值表 a b !a a && b a || b 非0 非 0 非 优先级: ! (非) 算术运算符 关系运算符 && 和 || 赋值运算符

71 逻辑运算符按优先级排列为: ! 、&&、|| && 和 || 的优先级低于关系运算符的优先级;! 的优先级高于算术运算符的优先级。逻辑运算符||和&&的结合方向是自左至右,而逻辑运算符!的结合方向是自右至左。 如: a > b && x > y 等效于 (a > b) && (x > y) a != b || x != y 等效于 (a != b) || (x != y) x == 0 || x < y && z > y 等效于 (x == 0) || ((x < y) && (z > y)) !b || x > y || a > b 等效于 ((!b) || (x > y)) || (a > b) !a && b || x > y && z < y 等效于 ((!a) && b) || ((x>y) &&(z<y))

72 在算术、关系、逻辑混合运算的表达式中,不同位置上出现的运算分量,应区分哪些是算术运算分量、哪些是关系运算分量和哪些是逻辑运算分量。
例 如: > 1 && 4 && 7 < 3 + !0 等效于: ((2 > 1) && 4) && (7 < (3 + (!0))) 1 1 1 4

73 说明 1. 逻辑运算的分量也可以是字符型、指针型。以 0或非 0 判定它们的“假”或“真”。 2. “逻辑与”和“逻辑或”运算符的性质:
a && b,当 a 为 0 时,不管 b 为何值(不再 计算 b),结果为 0。 a || b,当 a 为 1 时,不管 b 为何值(不再计算b),结果为 1。 例1:a=1, b=2, c=3, c=4, m=5, n=6 (m=a>b) && (n=c>d) ∵ m = 0,∴ n=c>d不计算,n仍为6

74 例2: int a = 1, b = 1, c = 1; 计算 ++a || ++b && ++c ,因++a非0,不再计算逻辑或右边表达式++b&&++c。该表达式计算后,变量a的值变为2,而变量b和c的值不变,依旧为1。 3. 注意书写顺序: 例 如: y/x > 2 且 x != 0, 应写成: x != 0 && y/x > 2 因为,当 x 为0时,不会计算 y/x。 而写成: y/x > 2 && x != 0 是不正确的, 因为当 x 为0时,不能计算 y/x。

75 示例 例:判别某一年是否闰年。 闰年条件:每四年一个闰年,但每100年少一个闰年,每400年又增加一个闰年。 用逻辑表达式可描述闰年条件:
(year能被4整除,不能被100整除)或(year能被400整除) 用逻辑表达式可描述闰年条件: (year % 4 == 0 && year %100 != 0) || year % 400 == 0 用逻辑表达式可描述非闰年条件: !(year % 4 == 0 && year %100 !=0 || year % 400 == 0) 或下面表达式判别非闰年: (year % 4 != 0)|| (year %100 == 0 && year % 400 != 0)

76 条件运算 一般形式: 表达式1 ? 表达式2 :表达式3 计算规则: (1) 计算表达式1的值;
(2) 如果表达式1的值非0(真),则计算表达式2,并作为条件运算的结果; (3) 如果表达式1的值为0(假),则计算表达式3,并作为条件运算的结果。 例如: x > y ? x : y 如 x > y 为真,则条件运算取x值,否则取y值。 说明:条件运算符(?:)优先级高于赋值运算符,低于逻辑运算符、关系运算符和算术运算符。

77 条件运算的结合性 例 如: max = x > y ? x : y + 1 等效于: max = ((x > y) ? x : (y + 1)) 条件运算符的结合性为“自右至左”。 例 如: x > y ? x : u > v ? u : v 等效于: x > y ? x : (u > v ? u : v) 条件运算三个运算分量的数据类型可以各不相同。C语言约定,类型低的向类型高的转换。 如: i > j ? 2 : 3.5 当 i > j 时,条件表达式的值为2.0; 否则为3.5。

78 逗号运算 形式:表达式1,表达式2,… ,表达式n 作用:顺序计算各表达式,并以表达式n的值为连续逗号运算的结果。
例如:x = (i = 3, i * 2) 结果:使i等于3,x等于6。 说明:1.逗号运算目的是将多个表达式“串连”起来,分别求各表达式的值。 2.逗号运算常用于for循环结构,用于给多个变量赋初值。 3.逗号运算符的优先级最低。

79 2.4 表达式 表达式:由运算符和运算分量构成。 从表达式的构成形式区分,可分以下几类: 初等量表达式 单目运算表达式 双目运算表达式
条件运算表达式 赋值表达式 逗号表达式

80 初等量表达式 初等量又可有以下几种形式: 常量,如12,NULL。 变量,如x,y。 字符串,如"ABCD"。 函数调用,如sin(x)。
数组元素变量,如a[i]。 结构或联合的成分变量,如 s.no。 通过指针变量引用结构或联合的成分,如 p->no。 带圆括号的表达式(表达式),如(x+y)。

81 表达式加上圆括号成为初等量,实现用圆括号强制改变运算符的优先级。
例如: 表达式(x+y)*z 因(x+y)是初等量,使加法优先于乘法。 初等量运算符:()、[]、.、-> 优先级:最高 结合性:自左向右

82 单目运算表达式:只有一个运算分量 运算符: 优先级:低于初等量运算符 结合性:自右向左 & * 取地址、取内容 - + 取负、取原值
& * 取地址、取内容 取负、取原值 ! ~ 逻辑否定、按位取反 自增、自减 sizeof 求字节长度 (类型名) 强制类型 优先级:低于初等量运算符 结合性:自右向左

83 双目运算表达式 优先级高到低如下: 结合性:自左向右 * / % 乘、除、求余 + - 加、减
* / % 乘、除、求余 + - 加、减 >> << 左移、右移 < > <= >= 小于、大于、小于等于、大于等于 == != 等于、不等于 & 按位与 ^ 按位异或 | 按位或 && 逻辑与 || 逻辑或 结合性:自左向右

84 条件运算表达式 赋值表达式 逗号表达式 形式: 表达式 ? 表达式 : 表达式 结合性:自右向左 形式:左值 赋值运算符 表达式
形式:左值 赋值运算符 表达式 优先级:仅高于逗号运算符 逗号表达式 形式: 表达式,表达式 优先级:最低 结合性:自左向右

85 表达式的类型转换  隐式类型转换规则 高 double ← float ↑ long unsigned
低 int ← char, short 说明:1. 横向向左箭头←表示必定的转换。如,float型数据运行前必须先转换为double型。 2. 纵向的箭头↑表示,当运算对象为不同类型转换的方向。

86  强制类型转换 将一种类型的表达式值强制转换成另一种类型。 一般格式: (类型名)表达式
例:float x,y = 5.2 ,z = 3.5; int k; x = (int)(y+z); k = (int)y % (int)z; /* k = y%z 为错误*/ 结果:x = 8.0 , k = 2 说明:类型转换不只改变表达式值的类型,也可能会因两种表示形式上的差异,值的大小会有一些误差。

87 类型转换使内部表示形式改变的示意程序 #include <stdio.h> void main()
{ int k = 4; float h; long *lp = (long *)&h; h = (float)k; /* 将k 的值赋给h */ printf("h:%#lx k:%#x\n", *lp, k); if (h == k) printf("Equal.\n"); else printf("Not equal.\n"); } 运行上述程序,将输出以下字样: h:0x k:0x4 Equal. 说明:整数4转变成浮点数4.0 ,值的大小没有变,而4.0的float类型的内部十六进制形式的代码是 0x 。

88 【例2.7】表达式求值示例 #include <stdio.h> void main()
{ int i = 1, j = 2, k = 3; i += j += k; /* i = 6, j = 5, k = 3 */ printf("i=%d\tj=%d\tk=%d\n", i, j, k); printf("(i<j?i++:j++)=%d\n", i < j ? i++ : j++); printf("i=%d\tj=%d\n", i, j); /* i = 6, j = 6 */ printf("(k+=i>j?i++:j++)=%d\n", k += i>j ? i++ : j++); printf("i=%d\tj=%d\tk=%d\n", i, j, k); /* i=6, j=7, k=9 */ i = 3; j = k = 4; printf("(k>=j>=i)=%d", k >= j >= i); /* k>=j结果为1,而1<i */ printf("\t(k>=j&&j>=i)=%d\n", k >= j && j >= i); /* 1 && 1 */ i = j = 2; k = i++ - 1; printf("i=%d\tj=%d\tk=%d\n", i, j, k); /* i=3 ,j=2, k=1 */ k += -i j; /* k=1+(-3+(2+1)) */ printf("i=%d\tj=%d\tk=%d\n", i, j, k); /* i=4, j=3, k=1 */ k = i / ++i; /* k = 5 / 5 */ printf("k=%d\n\n", k); }

89 程序运行结果是 i=6 j=5 k=3 (i<j?i++:j++)=5 i=6 j=6 (k+=i>j?i++:j++)=9 i=6 j=7 k=9 (k>=j>=i)=0 (k>=j&&j>=i)=1 i=3 j=2 k=1 i=4 j=3 k=1 k=1

90 说明 (1) C表达式 k>=j>=i与数学式子k>=j>=i的区别。 C 表达式 k>=j>=i因运算符 >= 自左向右结合,可写成(k>=j)>=i。数学式子 k>=j>=i写成C表达式应该是 k>=j && j>=i。 (2) 注意运算符++和--,在不同系统中的差别。 如表达式 i / ++i的值,在 TURBO C 中,结果为1。但是,可能在有的系统中,这个表达式的值却为 0。表达式“i/++i”可以写成“i/(++i)”。C语言对上述两种可能的选择未作明确规定,由编译程序自行决定。不同的编译程序可能采用不同的方案,这会引起表达式的副作用。

91 #include <stdio.h>
【例2.8】表达式求值示例 #include <stdio.h> void main() { int a, b, c; a = b = c = 1; ++a || ++b && ++c; printf("a=%d\tb=%d\tc=%d\n", a, b, c); /* a=2,b=1,c=1 */ a = b = c = 1; ++a && ++b || ++c; printf("a=%d\tb=%d\tc=%d\n", a, b, c); /* a=2,b=2,c=1 */ a = b = c = 1; ++a && ++b && ++c; printf("a=%d\tb=%d\tc=%d\n", a, b, c); /* a=2,b=2,c=2 */ a = b = c = 1; --a && --b || --c; printf("a=%d\tb=%d\tc=%d\n", a, b, c); /* a=0,b=1,c=0 */ a = b = c = 1; --a || --b && --c; printf("a=%d\tb=%d\tc=%d\n", a, b, c); /* a=0,b=0,c=1 */ a = b = c = 1; --a && --b && --c; printf("a=%d\tb=%d\tc=%d\n", a, b, c); /* a=0,b=1,c=1 */ }

92 程序运行结果为 a=2 b=1 c=1 a=2 b=2 c=1 a=2 b=2 c=2 a=0 b=1 c=0 a=0 b=0 c=1
结束


Download ppt "第2章 基本数据及其运算 本章学习的目标: 1、掌握基本数据的各种表示,基本数据常数的书写方法;"

Similar presentations


Ads by Google