C-程序设计教程-03解析课件_第1页
C-程序设计教程-03解析课件_第2页
C-程序设计教程-03解析课件_第3页
C-程序设计教程-03解析课件_第4页
C-程序设计教程-03解析课件_第5页
已阅读5页,还剩123页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第三章 数据类型 Chapter 3 Data Types2022/10/101第三章 数据类型 Chapter 3 Data Type本章学习目标:初始化和二维数组B数组指针运算D指针二维向量C向量基本类型及其表示方法A基本类型2022/10/102本章学习目标:初始B指针D二维C基本A2022/10/92Contents整型子类 ( sub-int Types )2C-串与string4整型 ( int Types )31浮点型 ( Floating-Point Type ) 33向量 ( vectors )6数组 ( Arrays )35指针与引用 ( Pointer & Referen

2、ces )372022/10/103Contents整型子类 ( sub-int Types )这是个有类型的世界Q1:现实生活,有哪些信息可以用计算机可以管理呢? Q2:所有的这些信息,在计算机里都是以什么样的数据形式来表达呢?“二进数”,正确。“已数字化的数据”,也算正确。“0和1”,正确。“机器语言”,正确!2022/10/104这是个有类型的世界Q1:现实生活,有哪些信息可以用计算机可以所有的信息都用机器语言那些0和1来表达编写程序岂不很难尽量向“高级动物”的思维习惯做了一些接近如果那么所以数据类型,就是计算机语言向人类语言靠近时,走出的第一步,很重要的一步。因为:机器语言或汇编语里,

3、没有数据类型一说。2022/10/105所有的信息都用机器语言那些0和1来表达编写程序岂不很难尽量整个世界都可以用数据和处理来表达整个世界就是一个程序;而万物是世界的数据=2022/10/106整个世界都可以用数据和处理来表达整个世界就是一个程序;=2通过抽象将人类世界中的类型,移植到计算机中。官方定义:数据类型是指定义了一组数据以及定义在这一组数据的操作,它是程序中最基本的元素。2022/10/107通过抽象将人类世界中的类型,移植到计算机中。官方定义:202C+数据类型十分丰富,大体上可分为基本类型、空类型、构造类型、指针类型、类类型五种。如下图所示。最重要类型,也称为C/C+语言的基本数

4、据类型,只有两个:“数值”和“字符”。第一是“数值类型”。这样,在职工的信息中,比如年纪,工龄、工资就有了归属第二是“字符类型”。像职工姓名或家庭住址2022/10/108C+数据类型十分丰富,大体上可分为基本类型、空类型、构造类数据类型基本类型空类型(无值类型)void构造类型类类型class指针类型整型int实型(浮点型)字符型逻辑型bool结构类型 struct数组类型 array枚举型类型 enum向量类型 vector联合型类型 union单精度型float双精度型double单字符型char宽字符型w-char图:C+数据类型2022/10/109数据类型基本类型空类型(无值类型)

5、void构造类型类类型cl理解整型和实型数值类型又被分为“整型”和“实型”。整型就是不带小数位的数,而实型则是指带小数位的数,也称为“浮点数”。问题:2=2.0,为什么不直接用浮点数来代替整数回答:因为在计算机里,对整数的运算要远远快于对浮点数的运算2022/10/1010理解整型和实型数值类型又被分为“整型”和“实型”。整型就是 折中的结果就是虽然都是数值类型,但程序员在程序时,必须事先想好,哪些数据是必须带小数计算的,那些数据定为实型。所以,在人类的思维习惯与计算机特点之间,必须做一个折中。2022/10/1011 折中的结果就是虽然都是数值类型,但程序员在程序时,必须事理解数值的范围同顾

6、及计算机的运行速度一样,与速度同样重要的是计算机的空间的考虑。这就是计算机的空间问题:任何一个量,都有一个大的上限,和小的下限,出了这个范围(比上限还大,比下限还小),就会称为溢出。数值类型在被划分为整型和实型后,将根据所占用的空间而被继续划分为几种不同类型2022/10/1012理解数值的范围同顾及计算机的运行速度一样,与速度同样重要的字符型和各种整型、实型类型标识符类型说明长度 (字节)范围备注char字符型1-128 127-27 (27 -1)unsigned char无符字符型10 2550 (28 -1)short int短整型2-32768 327672-15 (215 - 1)

7、unsigned short int无符短整型20 655350 (216 - 1)int整型4-2147483648 2147483647-231 (231 - 1)unsigned int无符整型40 42949672950 (232-1)float实型(单精度)41.18*10-38 3.40*10387位有效位double实型(双精度)82.23*10-308 1.79*1030815位有效位long double实型(长双精度)103.37*10-4932 1.18*10493219位有效位2022/10/1013字符型和各种整型、实型类型标识符类型说明长度 (字节)范1. 整型 (

8、 int Types )整型数的内部表示:二进制补码 好处:二进制补码运算没有加减的区别; 即减法也可以用加法实现;符号位也可以参加运算。整型数的表示范围:取决于二进制位数一个m位的整型若采用原码或反码表示,其范围是 ,若用补码表示,则范围是: 。2022/10/10141. 整型 ( int Types )整型数的内部表示:说明:整型数据分为长整型(long int)、一般整型(int)和短整型(short int)。在int前面加long和short分别表示长整型和短整型。(2) 整型数据的存储方式为按二进制数形式存储,例如十进制整数85的二进制形式为1010101,则在内存中的存储形式如

9、下图所示。2022/10/1015说明:2022/10/915 (3) 在整型符号int和字符型符号char的前面,可以加修饰符signed(表示“有符号”)或unsigned(表示“无符号”)。如果指定为signed,则数值以补码形式存放,存储单元中的最高位(bit)用来表示数值的符号。如果指定为unsigned,则数值没有符号,全部二进制位都用来表示数值本身。例如短整型数据占两个字节 ,见下图。2022/10/1016 (3) 在整型符号int和字符型符号char的前面,可以加 有符号时,能存储的最大值为2151,即32767,最小值为32768。 无符号时,能存储的最大值为2161,即6

10、5535,最小值为0。 有些数据是没有负值的,可以使用unsigned,它存储正数的范围比用signed时要大一倍。2022/10/1017 有符号时,能存储的最大值为2151,即327. 整型子类( Sub-int Types )字符型:表示范围: 有符号:-128127 无符号:0255 输出形式与整型数不同: int a = 65; char b = 65; couta“n”; coutb“n”; 结果为: 65 A 2022/10/1018. 整型子类( Sub-int Types )字符型:枚举型: 自定义整数区间,甚至列举单个整数值 enum Week Mon, Tue, Wed,

11、 Thu, Fri, Sat, Sun ; 最大特点是可以给每个值指定一个在程序中直接使用的标记(枚举符) 编程中将其当作整数常量用如: int a = 7; if ( a = = Sun ) cout “Sundayn ” ; 2022/10/1019枚举型:2022/10/919布尔型:表示范围仅含整数和1,也可以表示成true和false,相当于: enum bool false, true ;因为条件表达式、逻辑运算的结果都是或,所以,很多的表达式的值都与布尔型相对应2022/10/1020布尔型:2022/10/920 常量的值是不能改变的,一般从其字面形式即可判别是否为常量。 常量

12、包括两大类,即数值型常量(即常数)和字符型常量。如12,0,3为整型常量,4.6,1.23为实型常量,包含在两个单引号之间的字符为字符常量,如a,x。 这种从字面形式即可识别的常量称为“字面常量”或“直接常量”。什么是常量2022/10/1021 常量的值是不能改变的,一般从其字面形式即可判别1. 普通的字符常量 用单引号括起来的一个字符就是字符型常量。如a。#,%,D都是合法的字符常量,在内存中占一个字节。 注意:字符常量只能包括一个字符,如AB 是不合法的。 字符常量区分大小写字母,如A和a是两个不同的字符常量。 引号()是定界符,而不属于字符常量的一部分。如cout a;输出的是一个字母

13、 a 。字符常量2022/10/10221. 普通的字符常量字符常量2022/10/9222. 转义字符常量 除了以上形式的字符常量外,C+还允许用一种特殊形式的字符常量,就是以 “”开头的字符序列。例如,n代表一个“换行”符。“coutn; ” 将输出一个换行,其作用与“cout endl; ” 相同。 这种“控制字符”,在屏幕上是不能显示的。在程序中也无法用一个一般形式的字符表示,只能采用特殊形式来表示。常用的以“”开头的特殊字符见书P70中表33。2022/10/10232. 转义字符常量2022/10/9233. 字符数据在内存中的存储形式及其使用方法 将一个字符常量存放到内存单元时,

14、实际上并不是把该字符本身放到内存单元中去,而是将该字符相应的ASCII代码放到存储单元中。 如果字符变量c1的值为a,c2的值为b,则在变量中存放的是a的ASCII码97,b 的ASCII码98,如图(a)所示,实际上在内存中是以二进制形式存放的,如图(b)所示。2022/10/10243. 字符数据在内存中的存储形式及其使用方法2022/10/2022/10/10252022/10/925 既然字符数据是以ASCII码存储的,它的存储形式就与整数的存储形式类似。 这样,在C+中字符型数据和整型数据之间就可以通用。 一个字符数据可以赋给一个整型变量,反之,一个整型数据也可以赋给一个字符变量。也

15、可以对字符数据进行算术运算,此时相当于对它们的ASCII码进行算术运算。2022/10/1026 既然字符数据是以ASCII码存储的,它的存储形式就与整数例1 将字符赋给整型变量。#include using namespace std;int main( )int i,j; i = A; j = B; cout i j n; return 0;2022/10/1027例1 将字符赋给整型变量。2022/10/927执行时输出 65 66i和j被指定为整型变量。但在第5和第6行中,将字符A和B分别赋给i和j,它的作用相当于以下两个赋值语句:i 65;j 66;2022/10/1028执行时输出

16、 2022/10/928因为A和B的ASCII码为65和66。在程序的第5和第6行是把65和66直接存放到i和j的内存单元中。因此输出65和66。可以看到:在一定条件下,字符型数据和整型数据是可以通用的。但是应注意字符数据只占一个字节,它只能存放0255范围内的整数。2022/10/10292022/10/929例2 字符数据与整数进行算术运算。下面程序的作用是?#include using namespace std;int main( )char c1,c2; c1=a; c2=b; c1=c1-32; c2=c2-32; coutc1 c2endl; return 0;2022/10/1

17、030例2 字符数据与整数进行算术运算。下面程序的作用是?202运行结果为A B a的ASCII码为97,而A的ASCII码为65,b为98,B为66。 从ASCII代码表中可以看到每一个小写字母比它相应的大写字母的ASCII代码大32。C+符数据与数值直接进行算术运算,字符a32得到整数65,b32得到整数66。 将65和66存放在c1,c2中,由于c1,c2是字符变量,因此用cout输出c1,c2时,得到字符A和B(A的ASCII码为65,B的ASCII码为66)。2022/10/1031运行结果为2022/10/931 浮点型(又称实型)数据分为单精度(float)、双精度(double

18、)和长双精度(long double)3种; 在Visual C+ 6.0中,对float提供6位有效数字,对double提供15位有效数字,并且float和double的数值范围不同。对float分配4个字节,对double和long double分配8个字节。 浮点型 ( Floating-Point Type )2022/10/1032 浮点型(又称实型)数据分为单精度(float)、双精度(一个浮点数可以用两种不同的方式表示: 十进制小数形式。 如21.456,7.98等。它一般由整数部分和小数部分组成。C+编译系统把用这种形式表示的浮点数一律按双精度常量处理,在内存中占8个字节。浮点

19、数的表示方法2022/10/1033一个浮点数可以用两种不同的方式表示: 浮点数的表示方法202如果在实数的数字之后加字母F或f,表示此数为单精度浮点数,如1234F,43f,占4个字节。如果加字母L或l,表示此数为长双精度数(long double),在GCC中占12个字节,在Visual C+ 6.0中占8个字节。2022/10/1034如果在实数的数字之后加字母F或f,表示此数为单精度浮点数,如(2) 指数形式(即浮点形式) 一个浮点数可以写成指数形式,如3.14159可以表示为0.314159101,3.14159100,31.415910-1,314.15910-2等形式。 在程序中

20、应表示为: 0.314159e1,3.14159e0,31.4159e1,314.159e2,用字母e表示其后的数是以10为底的幂,如e12表示1012。2022/10/1035(2) 指数形式(即浮点形式)2022/10/935其一般形式为: 数符 数字部分 指数部分 上面各数据中的0.314159,3.14159,31.4159, 314.159 等就是其中的数字部分。可以看到: 由于指数部分的存在,使得同一个浮点数可以用不同的指数形式来表示,数字部分中小数点的位置是浮动的。例如: 2022/10/1036其一般形式为:2022/10/936a0.314159e1; a3.14159e0;

21、 a31.4159e1; a314.159e2; 以上4个赋值语句中,用了不同形式的浮点数,但其作用是相同的。 在程序中不论把浮点数写成小数形式还是指数形式,在内存中都是以指数形式(即浮点形式)存储的。例如不论在程序中写成314.159或314.159e0,31.4159e1,3.14159e2, 0.314159e3等形式,在内存中都是以规范化的指数形式存放,如右图2022/10/1037a0.314159e1; a3.14159e大家都知道任何数据在内存中都是以二进制(1或着0)顺序存储的,每一个1或着0被称为1位,而在x86CPU上一个字节是8位。比如一个16位(2字节)的 short

22、int型变量的值是1156,那么它的二进制表达就是:00000100 10000100。由于Intel CPU的架构是Little Endian,所以在Intel CPU 中,1156 应该怎样存放?2022/10/1038大家都知道任何数据在内存中都是以二进制(1或着0)顺序存储的Big Endian 和 Little Endian谈到字节序的问题,必然牵涉到两大CPU派系。那就是Motorola的PowerPC系列CPU和Intel的x86系列CPU。PowerPC系列采用big endian方式存储数据,而x86系列则采用little endian方式存储数据。那么究竟什么是big en

23、dian,什么又是little endian呢? 其实big endian是指低地址存放最高有效字节(MSB)Most Significant Byte ,而little endian则是低地址存放最低有效字节(LSB)Least Significant Byte 。 2022/10/1039Big Endian 和 Little Endian2022 用文字说明可能比较抽象,下面用图像加以说明。比如数字0 x12345678在两种不同字节序CPU中的存储顺序如下所示:2022/10/1040 用文字说明可能比较抽象,下面用图像加以说明。比如数字2022/10/10412022/10/941

24、为什么要注意字节序的问题呢?你可能这么问。当然,如果你写的程序只在单机环境下面运行,并且不和别人的程序打交道,那么你完全可以忽略字节序的存在。 但是,如果你的程序要跟别人的程序产生交互呢?假如是两种语言C/C+语言编写的程序里数据存储顺序是跟编译平台所在的CPU相关的,而JAVA编写的程序则唯一采用big endian方式来存储数据。试想,如果你用C/C+语言在x86平台下编写的程序跟别人的JAVA程序互通时会产生什么结果?2022/10/1042 为什么要注意字节序的问题呢?你可能这么问。当然,如果 就拿上面的0 x12345678来说,你的程序传递给别人的一个数据,将指向0 x123456

25、78的指针传给了JAVA程序,由于JAVA采取big endian方式存储数据,很自然的它会将你的数据翻译为0 x78563412。什么?竟然变成另外一个数字了?是的,就是这种后果。因此,在你的C程序传给JAVA程序之前有必要进行字节序的转换工作。2022/10/1043 就拿上面的0 x12345678来说,你的程序传递给别人无独有偶,所有网络协议也都是采用big endian的方式来传输数据的。所以有时我们也会把big endian方式称之为网络字节序。当两台采用不同字节序的主机通信时,在发送数据之前都必须经过字节序的转换成为网络字节序后再进行传输。目前应该littleendian是主流,

26、因为在数据类型转换的时候(尤其是指针转换)不用考虑地址问题。 2022/10/1044无独有偶,所有网络协议也都是采用big endian的方式来那么 short int型变量1156,即:00000100 10000100。在奔腾系列的计算机中,1156 应该怎样存放?2022/10/1045那么 short int型变量1156,即:00000100由于Intel CPU的架构是Little Endian,所以在Intel CPU 中, 1156,即:00000100 10000100是按字节倒序存储的,那么就因该是这样: 10000100 00000100 这就是定点数1156在内存中的

27、结构。 那么浮点数是如何存储的呢? 2022/10/1046由于Intel CPU的架构是Little Endian,所目前已知的所有的C/C+编译器都是按照IEEE (Institute of Electrical and Electronics Engineers) (国际电子电器工程师协会)制定的IEEE 754浮点数表示法来进行运算的。这种结构是一种科学表示法,用符号(正或负)、指数(或阶码)和尾数来表示,底数被确定为2,也就是说是把一个浮点数表示为尾数乘以2的指数次方再加上符号。2022/10/1047目前已知的所有的C/C+编译器都是按照IEEE (Inst下面来看一下具体的 fl

28、oat 的规格:float共计32位,折合4字节由最高到最低位分别是第31、30、29、0位31位是符号位,1表示该数为负,0反之。3023位,一共8位是指数(阶码)位。220位,一共23位是尾数位。每8位分为一组,分成4组,分别是A组、B组、C组、D组。每一组是一个字节,在内存中逆序存储,即:DCBA2022/10/1048下面来看一下具体的 float 的规格:2022/10/94现在让我们按照IEEE浮点数表示法,一步步的将float型浮点数12345.0f转换为十六进制代码。在处理这种不带小数的浮点数时,直接将整数部转化为二进制表示: 1,1110,0010,0100,0000也可以这

29、样表示: 1,1110,0010,0100,0000.02022/10/1049现在让我们按照IEEE浮点数表示法,一步步的将float型浮1,1110,0010,0100,0000.0然后将小数点向左移,一直移到离最高位只有1位,这种情况下,其实最高位也就是:“1”! 即:1.11100010010000000一共移动了16位,小数点每向左移一位就等于在以“2”为底的科学计算法表示中指数+1,所以原数就等于这样:1.11100010010000000 * ( 2 16 ) 。这就叫做二进制浮点数的“规格化”!注意:这和十进制科学计数法的规格化: X0.X * ( 10m ) , 比如 123

30、 0.123 * ( 10 3 ) 是不同的喔_2022/10/10501,1110,0010,0100,0000.02022/10OK,现在我们要的尾数和指数都出来了。显而易见,最高位永远是“1”,因为你不可能把买了16个鸡蛋说成是买了0016个鸡蛋吧?所以这个1我们还有必要保留吗?2022/10/1051OK,现在我们要的尾数和指数都出来了。2022/10/951好的,我们删掉他!再举一个例子!如:在32位浮点数中: 0.6 = 0.1001(2) 1.0011, 0011, 0011, 0011, 0011, 001如果删掉最高位的 “1” ,就比老老实实表示的23位尾数: 0.1001

31、, 1011, 1001, 1011, 0011, 101 多了一位精度。在具体实现中,去掉规格化的1,写入二进制浮点数!而当重新从机器中取出参加运算时,则补上1。因此23尾数,加上省略的一位,其精度或有有效尾数就变成了24位_2022/10/1052好的,我们删掉他!2022/10/952呵呵_,继续回到我们的数12345.0f: 1.1110, 0010,0100,000,00 * ( 2 16 ) 。这样尾数的二进制就变成了: 1110, 0010, 0100, 0000,0 最后在尾数的后面补0,一直到补够23位: 1110, 0010, 0100, 0000, 0000, 000OK

32、!到此为止,我们的尾数就计算完毕。2022/10/1053呵呵_,继续回到我们的数12345.0f:2022/10再回来看阶码(即指数),一共8位,可以表示范围是0255的无符号整数,也可以表示128127的有符号整数。但因为指数是可以为负的,所以为了统一,同时为了使得浮点数0与整数0统一,即符号位、阶码位和尾数位全部为零。把十进制的整数化为二进制时,都先加上127,而在取出该浮点数时,再做一个减127的逆操作!在这里,我们的16加上127后就变成了 143,二进制表示为:10001111思考:128在机器中是如何表示的?2022/10/1054再回来看阶码(即指数),一共8位,可以表示范围是

33、0255的注意: 由于补码中“0”的表示是唯一的,故 【X】补 10000,对应的真值应该是: X 其实补码 “10000” 的形式是一个特殊情况,最高位的1既代表符号又代表数值! 2022/10/1055注意:2022/10/955继续 由于12345.0f 这个数是正的,所以符号位是0,那么我们按照前面讲的格式把它拼起来:符号位 阶 码 尾 数 0 10001111 11100010010000000000000即:0100,0111,1111,0001,0010,0000,0000,0000再转化为16进制为:47 F1 20 00,最后把它翻过来,就成了: 00 20 F1 47。即浮

34、点数12345.0f 在机器最终表示为: 00 20 F1 47 现在把 5432.0f 转为二进制表示,试试看!2022/10/1056继续 2022/10/956有了上面的基础后,下面我再举一个带小数的例子来看一下为什么会出现精度问题。按照IEEE浮点数表示法,将float型浮点数 35. 6f 转换为十六进制代码。对于这种带小数的就需要把整数部和小数部分开处理。整数部直接化二进制:100011。小数部的处理比较麻烦一些了 2022/10/1057有了上面的基础后,下面我再举一个带小数的例子来看一下为什么会具体办法,就是采用“乘2取整法”,即:对被转换的十进制小数乘以2,取其整数部分作为二

35、进制的小数部分,再乘以2,直到小数部分为0,或者已经取到了足够的位数。 每次取的整数部分,按先后次序,构成了二进制小数从高到低位的数字排列。具体如下:2022/10/1058具体办法,就是采用“乘2取整法”,即:对被转换的十进制小数乘0.621.2 0.10.220.4 0.100.420.8 0.1000.821.6 0.10010.621.2 0.10011开始循环了哦这说明0.60.1001 1001 1001(2)2022/10/10590.621.2 0.12022/100.60.1001 1001 1001(2)假设,我们要求的精度是小数点后16位,那么,0.6的二进制表示形式应该

36、是多少呢? 是:1001 1001 1001 1001 吗? 不对!正确的应该是: 1001 1001 1001 1010(见书P75)2022/10/10600.60.1001 1001 1001(2) 是:OK,我们继续_嗯,刚才那个数还没转完呢,反正最后一直求也求不尽,加上前面的整数部分算够24位就行了,即: 10 0011.1001 1001 1001 1001 10。 某DX问:“不是说尾数是23位吗?为什么要算够24位?” “晕!不是说过了要把第一个1去掉吗?所以当然要加一位喽!”2022/10/1061OK,我们继续_2022/10/961现在开始向左移小数点,大家和我一起移,“

37、1、2、3”好了,一共移了5位,5加上 127得132(呵呵),二进制表示为: 1000 0100 所以: 35. 6f 的价码在计算机中表示为: 1000 01002022/10/1062现在开始向左移小数点,大家和我一起移,“1、2、3”好了 So 符号位为,然后再,哎哟,不说了,越说越啰嗦,大家自己看吧: 0, 10000100, 0001 1100 1100 1100 1100 110 即: 0100 0010 0000 1110 0110 0110 0110 0110 42 0E 66 66 42 0E 66 66内存中应为:66 66 0E 422022/10/1063 So 符号

38、位为,然后再,哎哟,不说了,越说越啰一个IEEE754浮点数的问题?将(100.25)D 转换成短浮点数。并且: (1)把十进制转成二进制。 (2)规格化二进制 (3)计算出移码(阶码真值+偏移量) 2022/10/1064一个IEEE754浮点数的问题?2022/10/964 思考:这个110是如何得出来的?一、把十进制转成二进制。 (100.25)D ( 1100100.01 ) B二、规格化二进制 1100100.011.10010001 * 26三、计算出移码(阶码真值+偏移量) 110+01111111100001012022/10/1065 思考:这个110是如何得出来的?一、把十

39、进制转成二进补充: 阶码是以移码的形式存储! 对于单精度浮点数,偏移量为127(7FH),而双精度的偏移量为1023(3FFH)。存储浮点数的阶码之前,偏移量要先加到阶码上。比如:阶为2的三次方,则在单精度浮点数中,移码后的结果为127+3即130(82H),双精度为1026(402H)。2022/10/1066补充:2022/10/966最后,要特别注意: 浮点数有两个例外! A.数0.0存储为全零。 B.无限大数的阶码存储为全1,尾数部分全零。符号位用来指示是正无穷还是负无穷。2022/10/1067最后,要特别注意:2022/10/967作业: 将十进制数12 和 0.25转换成单精度浮

40、点数在计算机中存储的标准格式。 2022/10/1068作业:2022/10/968十进制数12 和 0.25转换成单精度浮点数后在计算机中存储的标准格式如下:2022/10/1069十进制数12 和 0.25转换成单精度浮点数后在计算机中存4. C-串与string ( C-string & string )C-串结构每个字符占据1个字节一个C串是一个字符序列,用来表示各种名字或者文字说明C串的字符序列的最后总是添加有一个结束标志。即在6个字符的字串(“Hello!”)其空间存储有7个字节左边三图是不同细节的同一空间结构描述Hello!0 72 101 108 108 111 33 0010

41、010000110010101101100011011000110111100100001000000002022/10/10704. C-串与string ( C-string & s 用双引号括起来的部分就是字符串常量,如abc,Hello!,a+b,Li ping都是字符串常量。字符串常量abc在内存中占4个字节(而不是3个字节),见下图。编译系统会在字符串最后自动加一个0作为字符串结束标志。但0并不是字符串的一部分,它只作为字符串的结束标志。如:coutabcendl; 输出3个字符abc,而不包括0。2022/10/10712022/10/971注意: a和a代表不同的含义,a是字符

42、串常量,a 是字符常量。前者占两个字节,后者占1个字节。分析下面的程序片段: char c; /定义一个字符变量 c = a; /正确 c = a; /错误,c只能容纳一个字符2022/10/1072注意: a和a代表不同的含义,a是字符串常量,请思考: 字符串常量abcn包含几个字符?答:不是5个而是4个字符,其中“n”是一个转义字符。但它在内存中占5个字节(包括一个“0”字符) 。编译系统遇到“”时就会把它认作转义字符的标志,把它和其后的字符一起作为一个转义字符。So,字符串常量要用字符数组来存放!2022/10/1073请思考:答:不是5个而是4个字符,其中“n”是一个转义字符如果“”后

43、面的字符不能与“”组成一个合法的转义字符(如b),则在编译时显示出错信息。如果希望将“”字符也作为字符串中的一个字符,则应写为abcn,此时字符串包括5个字符,即a,b,c,n。如果有以下输出语句: cout abcn endl;则会输出: abc,然后换行。思考一下:执行的输出又是什么呢? cout I say Thank you!n;2022/10/1074如果“”后面的字符不能与“”组成一个合法的转义字符(如输出是: I say Thank you!2022/10/1075输出是: I say Thank you!2022/10 知道了C串首地址,即可知道整个串,所以可以藉字符首址(字符

44、指针)来操作C串,但要注意,串的第一个字符与整个串的操作不同,如:C串的输出操作: char* str = ”Hello”; cout *str endl; / 显示H cout str endl; / 显示Hello2022/10/1076 知道了C串首地址,即可知道整个串,所以可以藉字 C串不能直接比较,因为字符指针的比较只是地址值的比较而不是C串的字符序比较: 1. cout (“join” ”join” ? “ ” : “not”)”equaln”; / 字面值比较 2. char* str1 “good”; char* str2 “good”; cout ( str1str2 ? “

45、 ” : “not” ) “equaln”; / 字符指针比较 2022/10/1077 C串不能直接比较,因为字符指针的比 3. char buffer16 “Hello”; char buffer26 “Hello”; cout (buffer1buffer2 ? “ ” : “not” ) “equaln”; / 字符数组比较 结果: not equal not equal not equal2022/10/1078 3. char buffer16 “HelloSo,不得不配备专门操作C-串的库函数:strcpy(s1, s2); /从s2拷贝到s1strcmp(s1, s2); /比

46、较s1与s2strcat(s1, s2); /连接s2到s1strrev(s); /将s倒排 strset(s, c); /将s全置为cstrstr(s, “ell”); /查找s中的子串strchr(s,c); /查找s中的字符 等等2022/10/1079So,不得不配备专门操作C-串的库函数:2022/10/97但字符指针操作C串的安全性受到质疑:char* str1;char* str2 = new char5;strcpy ( str2, “ugly” );strcpy ( str1,str2 ); / 错: str1没有空间可储strcpy ( str2, “Hello” ); /

47、 错: str2空间不够大str2 = “Hello”; / 错:原来的”ugly”空间脱钩, 导致内存泄漏根源:复制操作须以足够的目的地空间为前提,而所有C串操作的空间调配都是人为安排的,C串库函数一概不管。2022/10/1080但字符指针操作C串的安全性受到质疑:2022/10/980类串string串类自定义串对应字符指针的C串操作: string a, s1 = Hello ; string s2 = 123; a = s1; / copy cout ( a s1 ? “” : not“ ) equaln; / compare cout as2 endl; / connect 202

48、2/10/1081类串string串类自定义串2022/10/981 reverse ( a.begin( ), a.end( ) ); / reverse cout a endl; cout a.replace ( 0, 9, 9, c ) endl; / set cout ( s1.find ( ell ) != 1 ? : not ) foundn; / find string cout ( s1.find ( c ) != 1 ? : not ) 的读入方式总是将前导的空格(所谓空格,即包括空格、回车、水平或垂直制表符等)滤掉,将单词读入,在遇到空格时结束本次输入getline 总是将

49、行末的回车符滤掉,将其整行输入2022/10/1083输入C串的string承载方式:2022/10/983对字串“ Hello,How are you?”的两种输入方式for ( string s; cin s; ) cout s “ ”;cout endl; string s;getline ( cin, s );cout s a ; sum += a ) ; cout sum “n” ; 2022/10/1085 string流:2022/10/985string流 使用一个string流可以将输入输出设备和一块表示string字符串的内存区域连接起来。所有从程序的输出都将被保存到这块内

50、存中,同时也可以从这块内存中读取数据到程序中。 使用string流必须包括sstream头文件,在这个头文件里定义了三个类: 1. istringstream 类,从istream类派生出来; 2. ostringstream 类,从ostream类派生而来; 3. stringstream 类,他从iostream类中派生而来。2022/10/1086string流2022/10/9861.ostringstream类#include #include int main()ostringstream ostring;int ival = 1;double dval = 1.0;ostring

51、 ival dval ival dval; /将字符串转换为一个int和一个double2022/10/10882.istringstream类2022/10/988为了编程和阅读的方便,在C+程序设计中,常用一个符号名代表一个常量,称为符号常量,即以标识符形式出现的常量。符号常量2022/10/1089为了编程和阅读的方便,在C+程序设计中,常用一个符号名代表例: 符号常量的使用。 # define PRICE 30 /注意这不是语句,末尾不要加分号int main ( ) int num,total;num = 10 ;total = num * PRICE ;cout total= to

52、tal endl ;return 0;2022/10/1090例: 符号常量的使用。 2022/10/990程序中用预处理命令 #define 指定PRICE在本程序单位中代表常量30,此后凡在本程序单位中出现的PRICE都代表30,可以和常量一样进行运算,程序运行结果为 : total = 300 2022/10/1091程序中用预处理命令 #define 指定PRICE在本程序单请注意符号常量虽然有名字,但它不是变量。它的值在其作用域(在本例中为主函数)内是不能改变的,也不能被赋值。如用赋值语句“PRICE = 40;”给PRICE赋值是错误的。 使用符号常量的好处是:(1) 含义清楚。(

53、2) 在需要改变一个常量时能做到“一改全改”。 如 # define PRICE 352022/10/1092请注意符号常量虽然有名字,但它不是变量。它的值在其作用域(在 在定义变量时,如果加上关键字const,则变量的值在程序运行期间不能改变,这种变量称为常变量(constant variable)。例如: const int a3 ; /用const来声明这种变量的值不能改变,指定其值始终为3常变量2022/10/1093 在定义变量时,如果加上关键字const,则变量在定义常变量时必须同时对它初始化(即指定其值),此后它的值不能再改变。常变量不能出现在赋值号的左边。例如上面一行不能写成

54、const int a; a3; /常变量不能被赋值可以用表达式对常变量初始化,如: const int b 3 + 6,c 3 * cos(1.5); /b的值被指定为9,c的值被指定为3*cos(1.5)2022/10/1094在定义常变量时必须同时对它初始化(即指定其值),此后它的值不但应注意,由于使用了系统标准数学函数cos,必须将包含该函数有关的信息的头文件“cmath”(或 math.h)包含到本程序单位中来,可以在本程序单位的开头加上以下#include命令:#include 或 #include 2022/10/1095但应注意,由于使用了系统标准数学函数cos,必须将包含该函

55、数变量的值应该是可以变化的,那为什么固定的量也称变量呢?其实,从计算机实现的角度看,变量的特征是存在一个以变量名命名的存储单元,在一般情况下,存储单元中的内容是可以变化的。对常变量来说,无非在此变量的基础上加上一个限定: 存储单元中的值不允许变化。因此常变量又称为只读变量(read-only-variable)。2022/10/1096变量的值应该是可以变化的,2022/10/996请区别用#define命令定义的符号常量和用const定义的常变量。符号常量只是用一个符号代替一个字符串,在预编译时把所有符号常量替换为所指定的字符串,它没有类型,在内存中并不存在以符号常量命名的存储单元。而常变量

56、具有变量的特征,它具有类型,在内存中存在着以它命名的存储单元,可以用sizeof运算符测出其长度。2022/10/1097请区别用#define命令定义的符号常量和用const定用#define命令定义符号常量是C语言所采用的方法,C+把它保留下来是为了和C兼容。C+程序员一般喜欢用const定义常变量。虽然二者实现的方法不同,但从使用角度看,都可以认为用了一个标识符代表了一个常量。有些书上把用const定义的常变量也称为定义常量,但我们应该了解它和符号常量的区别。2022/10/1098用#define命令定义符号常量是C语言所采用的方法,Csizeof 的使用用法: sizeof(数据类型

57、) or sizeof(变量)sizeof是一种计算,计算的对象是指定的一种数据类型,计算的结果是该数据类型占用的字节数目。如:sizeof(char) = 1;也就是说char类型占用1个字节。sizeof(int) =4; 也就是说int类型占用4个字节。2022/10/1099sizeof 的使用用法: sizeof(数据类型) or为数据类型起别名:typedef用法: typedef 原类型名 新类型的别名为什么要给现成的数据类型起别名?例如:typedef unsigned char UCHAR typedef unsigned long DWORD 它们的一切属性都和其原名 un

58、signed char / long 的数据类型完全一致。只是名字变得更简单好记一点而已.2022/10/10100为数据类型起别名:typedef用法: typedef 判断输入错误 int number;cout numberif ( number 0 ) for ( int i = 0; ( i 3 ) & ( number ) 0; i + ) cout number if ( i 3 ) cout number 只能接受整数,如果用户输入了字母,则这个字母会遗留在“输入缓冲区”中。因为缓冲中有数据,故而 cin 函数不会等待用户输入,直接就去缓冲中读取,可是缓冲中的却是字母,这个字母

59、再次被遗留在缓冲中,如此反复 2022/10/10102由于 cin number 只能接受整数,如果用户输入判断输入错误 1int number;cout number ) ) cin.clear( ); /清除输入流的错误标记,重置输入 / 把输入缓冲区中的残留字符清空 while ( cin.get( ) != n ) continue; cerr “Input Error!Please enter a number: ”; 2022/10/10103判断输入错误 12022/10/9103判断输入错误 2#include int main( ) int ival ; cout ival

60、 ) ) cerr “Input Format Error!n ; cin.clear( ); cin.ignore ( numeric_limits :max( ),n ) ; cout You Entered: ival endl; 2022/10/10104判断输入错误 22022/10/9104判断输入错误 2A. 读到非法字符后,输入流将处于出错状态, 为了继续获取输入,首先要调用clear函数 来清除输入流的错误标记,然后才能调用 ignore函数来清除输入缓冲区中的数据。 B. numeric_limits:max( ) 返回缓冲区 的大小。注:numeric_limits:di

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论