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

下载本文档

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

文档简介

第三章数据类型

Chapter3

DataTypes2023/2/31本章学习目标:初始化和二维数组B数组指针运算D指针二维向量C向量基本类型及其表示方法A基本类型2023/2/32Contents整型子类(sub-intTypes)2C-串与string4整型(intTypes)31浮点型(Floating-PointType)

33向量(vectors)6数组(Arrays)35指针与引用(Pointer&References)372023/2/33这是个有类型的世界Q1:现实生活,有哪些信息可以用计算机可以管理呢?Q2:所有的这些信息,在计算机里都是以什么样的数据形式来表达呢?“二进数”,正确。“已数字化的数据”,也算正确。“0和1”,正确。“机器语言”,正确!2023/2/34所有的信息都用机器语言-那些0和1来表达编写程序岂不很难尽量向“高级动物”的思维习惯做了一些接近如果那么所以数据类型,就是计算机语言向人类语言靠近时,走出的第一步,很重要的一步。因为:机器语言或汇编语里,没有数据类型一说。2023/2/35整个世界都可以用数据和处理来表达

整个世界就是一个程序;而万物是世界的数据=2023/2/36通过抽象将人类世界中的类型,移植到计算机中。官方定义:数据类型是指定义了一组数据以及定义在这一组数据的操作,它是程序中最基本的元素。2023/2/37C++数据类型十分丰富,大体上可分为基本类型、空类型、构造类型、指针类型、类类型五种。如下图所示。最重要类型,也称为C/C++语言的基本数据类型,只有两个:“数值”和“字符”。第一是“数值类型”。这样,在职工的信息中,比如年纪,工龄、工资就有了归属第二是“字符类型”。像职工姓名或家庭住址2023/2/38数据类型基本类型空类型(无值类型)void构造类型类类型class指针类型整型int实型(浮点型)字符型逻辑型bool结构类型struct数组类型array枚举型类型enum向量类型vector联合型类型union单精度型float双精度型double单字符型char宽字符型w-char图:C++数据类型2023/2/39理解整型和实型

数值类型又被分为“整型”和“实型”。整型就是不带小数位的数,而实型则是指带小数位的数,也称为“浮点数”。问题:2=2.0,为什么不直接用浮点数来代替整数回答:因为在计算机里,对整数的运算要远远快于对浮点数的运算2023/2/310

折中的结果就是虽然都是数值类型,但程序员在程序时,必须事先想好,哪些数据是必须带小数计算的,那些数据定为实型。所以,在人类的思维习惯与计算机特点之间,必须做一个折中。2023/2/311理解数值的范围

同顾及计算机的运行速度一样,与速度同样重要的是计算机的空间的考虑。这就是计算机的空间问题:任何一个量,都有一个大的上限,和小的下限,出了这个范围(比上限还大,比下限还小),就会称为溢出。数值类型在被划分为整型和实型后,将根据所占用的空间而被继续划分为几种不同类型2023/2/312字符型和各种整型、实型类型标识符类型说明长度

(字节)范围备注char字符型1-128~127-27~(27-1)unsignedchar无符字符型10~2550~(28-1)shortint短整型2-32768~327672-15~(215-1)unsignedshortint无符短整型20~655350~(216-1)int整型4-2147483648~2147483647-231~(231-1)unsignedint无符整型40~42949672950~(232-1)float实型(单精度)41.18*10-38~3.40*1038

7位有效位double实型(双精度)82.23*10-308~1.79*10308

15位有效位longdouble实型(长双精度)103.37*10-4932~1.18*104932

19位有效位2023/2/3131.整型(intTypes)整型数的内部表示:二进制补码

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

(3)在整型符号int和字符型符号char的前面,可以加修饰符signed(表示“有符号”)或unsigned(表示“无符号”)。如果指定为signed,则数值以补码形式存放,存储单元中的最高位(bit)用来表示数值的符号。如果指定为unsigned,则数值没有符号,全部二进制位都用来表示数值本身。例如短整型数据占两个字节,见下图。2023/2/316有符号时,能存储的最大值为215~1,即32767,最小值为-32768。无符号时,能存储的最大值为216~1,即65535,最小值为0。有些数据是没有负值的,可以使用unsigned,它存储正数的范围比用signed时要大一倍。2023/2/3172.整型子类(Sub-intTypes)字符型:表示范围:

有符号:-128~127

无符号:0~255

输出形式与整型数不同:

inta=65;charb=65;cout<<a<<“\n”;cout<<b<<“\n”;

结果为:

65A

2023/2/318枚举型:自定义整数区间,甚至列举单个整数值

enumWeek{Mon,Tue,Wed,Thu,Fri,Sat,Sun};

最大特点是可以给每个值指定一个在程序中直接使用的标记-(枚举符).编程中将其当作整数常量用.如:

inta=7;if(a==Sun)cout<<“Sunday\n”;2023/2/319布尔型:表示范围仅含整数0和1,也可以表示成true和false,相当于:

enumbool{false,true};因为条件表达式、逻辑运算的结果都是0或1,所以,很多的表达式的值都与布尔型相对应2023/2/320常量的值是不能改变的,一般从其字面形式即可判别是否为常量。

常量包括两大类,即数值型常量(即常数)和字符型常量。如12,0,-3为整型常量,4.6,-1.23为实型常量,包含在两个单引号之间的字符为字符常量,如′a′,′x′。这种从字面形式即可识别的常量称为“字面常量”或“直接常量”。什么是常量2023/2/3211.普通的字符常量用单引号括起来的一个字符就是字符型常量。如′a′。′#′,′%′,′D′都是合法的字符常量,在内存中占一个字节。

注意:①字符常量只能包括一个字符,如′AB′是不合法的。

②字符常量区分大小写字母,如′A′和′a′是两个不同的字符常量。

③引号(′)是定界符,而不属于字符常量的一部分。如cout<<′a′;输出的是一个字母a。字符常量2023/2/3222.转义字符常量除了以上形式的字符常量外,C++还允许用一种特殊形式的字符常量,就是以“\”开头的字符序列。例如,′\n′代表一个“换行”符。“cout<<′\n′;”将输出一个换行,其作用与“cout<<endl;”相同。这种“控制字符”,在屏幕上是不能显示的。在程序中也无法用一个一般形式的字符表示,只能采用特殊形式来表示。常用的以“\”开头的特殊字符见书P70中表3-3。2023/2/3233.字符数据在内存中的存储形式及其使用方法将一个字符常量存放到内存单元时,实际上并不是把该字符本身放到内存单元中去,而是将该字符相应的ASCII代码放到存储单元中。如果字符变量c1的值为′a′,c2的值为′b′,则在变量中存放的是′a′的ASCII码97,′b′的ASCII码98,如图(a)所示,实际上在内存中是以二进制形式存放的,如图(b)所示。2023/2/3242023/2/325既然字符数据是以ASCII码存储的,它的存储形式就与整数的存储形式类似。这样,在C++中字符型数据和整型数据之间就可以通用。一个字符数据可以赋给一个整型变量,反之,一个整型数据也可以赋给一个字符变量。也可以对字符数据进行算术运算,此时相当于对它们的ASCII码进行算术运算。2023/2/326例1将字符赋给整型变量。#include<iostream>usingnamespacestd;intmain(){ inti,j; i=‘A’; j=‘B’; cout<<i<<‘’<<j<<‘\n’; return0;}2023/2/327执行时输出6566i和j被指定为整型变量。但在第5和第6行中,将字符′A′和′B′分别赋给i和j,它的作用相当于以下两个赋值语句:i=65;j=66;2023/2/328因为′A′和′B′的ASCII码为65和66。在程序的第5和第6行是把65和66直接存放到i和j的内存单元中。因此输出65和66。可以看到:在一定条件下,字符型数据和整型数据是可以通用的。但是应注意字符数据只占一个字节,它只能存放0~255范围内的整数。2023/2/329例2字符数据与整数进行算术运算。下面程序的作用是?#include<iostream>usingnamespacestd;intmain(){ charc1,c2; c1=′a′; c2=′b′; c1=c1-32; c2=c2-32; cout<<c1<<′′<<c2<<endl; return0;}2023/2/330运行结果为AB′a′的ASCII码为97,而′A′的ASCII码为65,′b′为98,′B′为66。从ASCII代码表中可以看到每一个小写字母比它相应的大写字母的ASCII代码大32。C++符数据与数值直接进行算术运算,字符a-32得到整数65,b-32得到整数66。将65和66存放在c1,c2中,由于c1,c2是字符变量,因此用cout输出c1,c2时,得到字符A和B(A的ASCII码为65,B的ASCII码为66)。2023/2/331浮点型(又称实型)数据分为单精度(float)、双精度(double)和长双精度(longdouble)3种;在VisualC++6.0中,对float提供6位有效数字,对double提供15位有效数字,并且float和double的数值范围不同。对float分配4个字节,对double和longdouble分配8个字节。

浮点型(Floating-PointType)2023/2/332一个浮点数可以用两种不同的方式表示:十进制小数形式。如21.456,-7.98等。它一般由整数部分和小数部分组成。C++编译系统把用这种形式表示的浮点数一律按双精度常量处理,在内存中占8个字节。浮点数的表示方法2023/2/333如果在实数的数字之后加字母F或f,表示此数为单精度浮点数,如1234F,-43f,占4个字节。如果加字母L或l,表示此数为长双精度数(longdouble),在GCC中占12个字节,在VisualC++6.0中占8个字节。2023/2/334(2)指数形式(即浮点形式)一个浮点数可以写成指数形式,如3.14159可以表示为0.314159×101,3.14159×100,31.4159×10-1,314.159×10-2等形式。在程序中应表示为:0.314159e1,3.14159e0,31.4159e-1,314.159e-2,用字母e表示其后的数是以10为底的幂,如e12表示1012。2023/2/335其一般形式为:数符数字部分指数部分上面各数据中的0.314159,3.14159,31.4159,314.159等就是其中的数字部分。可以看到:由于指数部分的存在,使得同一个浮点数可以用不同的指数形式来表示,数字部分中小数点的位置是浮动的。例如:2023/2/336a=0.314159e1;a=3.14159e0;a=31.4159e-1;a=314.159e-2;

以上4个赋值语句中,用了不同形式的浮点数,但其作用是相同的。在程序中不论把浮点数写成小数形式还是指数形式,在内存中都是以指数形式(即浮点形式)存储的。例如不论在程序中写成314.159或314.159e0,31.4159e1,3.14159e2,0.314159e3等形式,在内存中都是以规范化的指数形式存放,如右图2023/2/337大家都知道任何数据在内存中都是以二进制(1或着0)顺序存储的,每一个1或着0被称为1位,而在x86CPU上一个字节是8位。比如一个16位(2字节)的shortint型变量的值是1156,那么它的二进制表达就是:0000010010000100。由于IntelCPU的架构是LittleEndian,所以在IntelCPU中,1156应该怎样存放……?2023/2/338BigEndian和LittleEndian谈到字节序的问题,必然牵涉到两大CPU派系。那就是Motorola的PowerPC系列CPU和Intel的x86系列CPU。PowerPC系列采用bigendian方式存储数据,而x86系列则采用littleendian方式存储数据。那么究竟什么是bigendian,什么又是littleendian呢?

其实bigendian是指低地址存放最高有效字节(MSB)MostSignificantByte

,而littleendian则是低地址存放最低有效字节(LSB)LeastSignificantByte

2023/2/339

用文字说明可能比较抽象,下面用图像加以说明。比如数字0x12345678在两种不同字节序CPU中的存储顺序如下所示:2023/2/3402023/2/341为什么要注意字节序的问题呢?你可能这么问。当然,如果你写的程序只在单机环境下面运行,并且不和别人的程序打交道,那么你完全可以忽略字节序的存在。但是,如果你的程序要跟别人的程序产生交互呢?假如是两种语言-C/C++语言编写的程序里数据存储顺序是跟编译平台所在的CPU相关的,而JAVA编写的程序则唯一采用bigendian方式来存储数据。试想,如果你用C/C++语言在x86平台下编写的程序跟别人的JAVA程序互通时会产生什么结果?2023/2/342

就拿上面的0x12345678来说,你的程序传递给别人的一个数据,将指向0x12345678的指针传给了JAVA程序,由于JAVA采取bigendian方式存储数据,很自然的它会将你的数据翻译为0x78563412。什么?竟然变成另外一个数字了?是的,就是这种后果。因此,在你的C程序传给JAVA程序之前有必要进行字节序的转换工作。

2023/2/343无独有偶,所有网络协议也都是采用bigendian的方式来传输数据的。所以有时我们也会把bigendian方式称之为网络字节序。当两台采用不同字节序的主机通信时,在发送数据之前都必须经过字节序的转换成为网络字节序后再进行传输。目前应该little

endian是主流,因为在数据类型转换的时候(尤其是指针转换)不用考虑地址问题。

2023/2/344那么shortint型变量1156,即:0000010010000100。在奔腾系列的计算机中,1156应该怎样存放……?2023/2/345由于IntelCPU的架构是LittleEndian,所以在IntelCPU中,1156,即:0000010010000100是按字节倒序存储的,那么就因该是这样:1000010000000100这就是定点数1156在内存中的结构。那么浮点数是如何存储的呢?

2023/2/346目前已知的所有的C/C++编译器都是按照IEEE(InstituteofElectricalandElectronicsEngineers)-

(国际电子电器工程师协会)制定的IEEE754浮点数表示法来进行运算的。这种结构是一种科学表示法,用符号(正或负)、指数(或阶码)和尾数来表示,底数被确定为2,也就是说是把一个浮点数表示为尾数乘以2的指数次方再加上符号。2023/2/347下面来看一下具体的float的规格:float

共计32位,折合4字节

由最高到最低位分别是第31、30、29、……、0位

31位是符号位,1表示该数为负,0反之。

30~23位,一共8位是指数(阶码)位。

22~0位,一共23位是尾数位。

每8位分为一组,分成4组,分别是A组、B组、C组、D组。

每一组是一个字节,在内存中逆序存储,即:DCBA2023/2/348现在让我们按照IEEE浮点数表示法,一步步的将float型浮点数12345.0f转换为十六进制代码。在处理这种不带小数的浮点数时,直接将整数部转化为二进制表示:1,1110,0010,0100,0000也可以这样表示:1,1110,0010,0100,0000.02023/2/3491,1110,0010,0100,0000.0然后将小数点向左移,一直移到离最高位只有1位,这种情况下,其实最高位也就是:“1”!即:1.11100010010000000一共移动了16位,小数点每向左移一位就等于在以“2”为底的科学计算法表示中指数+1,所以原数就等于这样:1.11100010010000000*(2^16)。这就叫做二进制浮点数的“规格化”!注意:这和十进制科学计数法的规格化:X=0.X*(10^m),比如123=0.123*(10^3)是不同的喔^_^2023/2/350OK,现在我们要的尾数和指数都出来了。显而易见,最高位永远是“1”,因为你不可能把买了16个鸡蛋说成是买了0016个鸡蛋吧?所以这个1我们还有必要保留吗???2023/2/351好的,我们删掉他!再举一个例子!如:在32位浮点数中:

0.6=0.1001(2)

=1.0011,0011,0011,0011,0011,001如果删掉最高位的“1”,就比老老实实表示的23位尾数:

0.1001,1011,1001,1011,0011,101

多了一位精度。在具体实现中,去掉规格化的1,写入二进制浮点数!而当重新从机器中取出参加运算时,则补上1。因此23尾数,加上省略的一位,其精度或有有效尾数就变成了24位^_^2023/2/352呵呵^_^,继续回到我们的数12345.0f:

1.1110,0010,0100,000,00*(2^16)。这样尾数的二进制就变成了:1110,0010,0100,0000,0最后在尾数的后面补0,一直到补够23位:1110,0010,0100,0000,0000,000OK!到此为止,我们的尾数就计算完毕。2023/2/353再回来看阶码(即指数),一共8位,可以表示范围是0~255的无符号整数,也可以表示-128~127的有符号整数。但因为指数是可以为负的,所以为了统一,同时为了使得浮点数0与整数0统一,即符号位、阶码位和尾数位全部为零。把十进制的整数化为二进制时,都先加上127,而在取出该浮点数时,再做一个减127的逆操作!在这里,我们的16加上127后就变成了143,二进制表示为:10001111

思考:-128在机器中是如何表示的???2023/2/354注意:

由于补码中“0”的表示是唯一的,故【X】补

=1000……0,对应的真值应该是:X=

其实补码“1000……0”的形式是一个特殊情况,最高位的1既代表符号又代表数值!!!

2023/2/355继续由于12345.0f这个数是正的,所以符号位是0,那么我们按照前面讲的格式把它拼起来:

符号位阶码尾数

01000111111100010010000000000000

即:0100,0111,1111,0001,0010,0000,0000,0000再转化为16进制为:47F12000,最后把它翻过来,就成了:0020F147。即浮点数12345.0f在机器最终表示为:0020F147

现在把5432.0f转为二进制表示,试试看!!!2023/2/356有了上面的基础后,下面我再举一个带小数的例子来看一下为什么会出现精度问题。

按照IEEE浮点数表示法,将float型浮点数35.6f转换为十六进制代码。对于这种带小数的就需要把整数部和小数部分开处理。整数部直接化二进制:100011。小数部的处理比较麻烦一些了……2023/2/357具体办法,就是采用“乘2取整法”,即:对被转换的十进制小数乘以2,取其整数部分作为二进制的小数部分,再乘以2,直到小数部分为0,或者已经取到了足够的位数。每次取的整数部分,按先后次序,构成了二进制小数从高到低位的数字排列。具体如下:2023/2/3580.6×2=1.20.10.2×2=0.40.100.4×2=0.80.1000.8×2=1.60.10010.6×2=1.20.10011开始循环了哦……这说明0.6=0.100110011001……(2)2023/2/3590.6=0.100110011001……(2)假设,我们要求的精度是小数点后16位,那么,0.6的二进制表示形式应该是多少呢??

是:10011001

1001

1001

吗???

不对!!!正确的应该是:

10011001

10011010(见书P75)2023/2/360OK,我们继续^_^嗯,刚才那个数还没转完呢,反正最后一直求也求不尽,加上前面的整数部分算够24位就行了,即:100011.100110011001

100110。某DX问:“不是说尾数是23位吗?为什么要算够24位?”“晕!不是说过了要把第一个1去掉吗?所以当然要加一位喽!”2023/2/361现在开始向左移小数点,大家和我一起移,“1、2、3……”好了,一共移了5位,5加上127得132(呵呵~),二进制表示为:

10000100

所以:

35.6f的价码在计算机中表示为:

100001002023/2/362

So-符号位为……,然后再……,哎哟,不说了,越说越啰嗦,大家自己看吧:

0,10000100,000111001100

1100

1100110

即:

01000010

00001110

01100110

0110

0110

42

0E

66

66

42

0E

66

66

内存中应为:66

66

0E

422023/2/363一个IEEE754浮点数的问题?将(100.25)D转换成短浮点数。并且:

(1)把十进制转成二进制。

(2)规格化二进制

(3)计算出移码(阶码真值+偏移量)

2023/2/364

思考:这个110是如何得出来的?……一、把十进制转成二进制。

(100.25)D=(1100100.01)B二、规格化二进制

1100100.01=1.10010001*2^6三、计算出移码(阶码真值+偏移量)

110+01111111=100001012023/2/365补充:阶码是以移码的形式存储!对于单精度浮点数,偏移量为127(7FH),而双精度的偏移量为1023(3FFH)。存储浮点数的阶码之前,偏移量要先加到阶码上。比如:阶为2的三次方,则在单精度浮点数中,移码后的结果为127+3即130(82H),双精度为1026(402H)。2023/2/366最后,要特别注意:浮点数有两个例外!

A.数0.0存储为全零。

B.无限大数的阶码存储为全1,尾数部分全零。符号位用来指示是正无穷还是负无穷。2023/2/367作业:

将十进制数-12和0.25转换成单精度浮点数在计算机中存储的标准格式。2023/2/368十进制数-12和0.25转换成单精度浮点数后在计算机中存储的标准格式如下:2023/2/3694.C-串与string(C-string&string)C-串结构

每个字符占据1个字节一个C-串是一个字符序列,用来表示各种名字或者文字说明

C-串的字符序列的最后总是添加有一个结束标志。即在6个字符的字串(“Hello!”)其空间存储有7个字节左边三图是不同细节的同一空间结构描述’H’’e’’l’’l’’o’’!’’\0’

72101108108111330010010000110010101101100011011000110111100100001000000002023/2/370用双引号括起来的部分就是字符串常量,如″abc″,″Hello!″,″a+b″,″Liping″都是字符串常量。字符串常量″abc″在内存中占4个字节(而不是3个字节),见下图。编译系统会在字符串最后自动加一个′\0′作为字符串结束标志。但′\0′并不是字符串的一部分,它只作为字符串的结束标志。如:cout<<″abc″<<endl;

输出3个字符abc,而不包括′\0′。2023/2/371注意:

″a″和′a′代表不同的含义,″a″是字符串常量,′a′是字符常量。前者占两个字节,后者占1个字节。分析下面的程序片段:

charc;//定义一个字符变量c=′a′;//正确c=″a″;//错误,c只能容纳一个字符2023/2/372请思考:字符串常量″abc\n″包含几个字符?答:不是5个而是4个字符,其中“\n”是一个转义字符。但它在内存中占5个字节(包括一个“\0”字符)。编译系统遇到“\”时就会把它认作转义字符的标志,把它和其后的字符一起作为一个转义字符。So,字符串常量要用字符数组来存放!2023/2/373如果“\”后面的字符不能与“\”组成一个合法的转义字符(如″\b″),则在编译时显示出错信息。如果希望将“\”字符也作为字符串中的一个字符,则应写为″abc\\n″,此时字符串包括5个字符,即a,b,c,\,n。如果有以下输出语句:cout<<″abc\\\n″<<endl;则会输出:abc\,然后换行。思考一下:执行的输出又是什么呢??……cout<<″Isay\″Thankyou!\″\n″;2023/2/374输出是:Isay″Thankyou!″2023/2/375

知道了C-串首地址,即可知道整个串,所以可以藉字符首址(字符指针)来操作C-串,但要注意,串的第一个字符与整个串的操作不同,如:C-串的输出操作:

char*str=”Hello”;

cout<<*str<<endl;//

显示H

cout<<str<<endl;

//

显示Hello2023/2/376

C-串不能直接比较,因为字符指针的比较只是地址值的比较而不是C-串的字符序比较:1.

cout<<(“join”==”join”?“”:“not”)<<”equal\n”;

//字面值比较

2.

char*str1=“good”;

char*str2=“good”;

cout<<(str1==str2?“”:“not”)<<“equal\n”;

//字符指针比较

2023/2/377

3.charbuffer1[6]=“Hello”;

charbuffer2[6]=“Hello”;cout<<(buffer1==buffer2?“”:“not”)<<“equal\n”;//字符数组比较结果:

notequal

notequal

notequal2023/2/378So,不得不配备专门操作C-串的库函数:strcpy(s1,s2);

//从s2拷贝到s1strcmp(s1,s2);

//比较s1与s2strcat(s1,s2);

//连接s2到s1strrev(s);

//将s倒排

strset(s,‘c’);

//将s全置为cstrstr(s,“ell”);

//查找s中的子串strchr(s,‘c’);

//查找s中的字符

等等2023/2/379但字符指针操作C-串的安全性受到质疑:char*str1;char*str2=new

char[5];strcpy(str2,“ugly”);strcpy(str1,str2);

//

错:str1没有空间可储strcpy(str2,“Hello”);

//错:str2空间不够大str2=“Hello”;

//错:原来的”ugly”空间脱钩,导致内存泄漏根源:复制操作须以足够的目的地空间为前提,而所有C-串操作的空间调配都是人为安排的,C-串库函数一概不管。2023/2/380类串string-串类-自定义串对应字符指针的C-串操作:stringa,s1="Hello";strings2="123";a=s1;//copy

cout<<(a==s1?“”:"not“)<<"equal\n";

//compare

cout<<a+s2<<endl;//

connect

2023/2/381reverse(a.begin(),

a.end());//reverse

cout<<a<<endl;

cout<<a.replace(0,9,9,'c')<<endl;//set

cout<<(s1.find("ell")!=

-1?"":"not")<<"found\n";

//findstring

cout<<(s1.find('c')!=

-1?"":"not")<<"found\n";

//findchar2023/2/382输入C-串的string承载方式:cin>>

的读入方式总是将前导的空格(所谓空格,即包括空格、回车、水平或垂直制表符等)滤掉,将单词读入,在遇到空格时结束本次输入getline总是将行末的回车符滤掉,将其整行输入2023/2/383对字串“Hello,Howareyou?”的两种输入方式for

(strings;cin>>s;)

cout<<s<<“”;cout<<endl;

strings;getline(cin,s);cout<<s<<endl;2023/2/384

string流:将string实体看作是一个输入设备。给一个像cin这样的取名,作为流来操作,会很有用。例如,如果一个文件aaa.txt,有若干行,每行中含有不知道几个的整数,要输出每行的整数和:

ifstreamin("aaa.txt");

for(strings;getline(in,s);){

inta,sum=0;

for(istringstreamsin(s);sin>>a;sum+=a);

cout<<sum<<“\n”;

}2023/2/385string流

使用一个string流可以将输入输出设备和一块表示string字符串的内存区域连接起来。所有从程序的输出都将被保存到这块内存中,同时也可以从这块内存中读取数据到程序中。

使用string流必须包括sstream头文件,在这个头文件里定义了三个类:

1.

istringstream

类,从istream类派生出来;

2.

ostringstream

类,从ostream类派生而来;

3.

stringstream类,他从iostream类中派生而来。2023/2/3861.ostringstream类#include<string>#include<sstream>intmain(){

ostringstreamostring;

intival=1;

doubledval=1.0;

ostring<<ival<<""<<dval<<'\n';//输出为:11.0}2023/2/3872.istringstream类这个类主要的用途是将一个string字符串转换为算术类型,如:intmain(){

//……

//继续上面的程序//接收一个string字符串作为参数,这个参数作为其底层储存istringstreamistring(str);istring>>ival>>dval;

//将字符串转换为一个int和一个double}2023/2/388为了编程和阅读的方便,在C++程序设计中,常用一个符号名代表一个常量,称为符号常量,即以标识符形式出现的常量。符号常量2023/2/389例:

符号常量的使用。

#definePRICE30//注意这不是语句,末尾不要加分号intmain(){ intnum,total; num=10; total=num*PRICE; cout<<″total=″<<total<<endl; return0;}2023/2/390程序中用预处理命令#define指定PRICE在本程序单位中代表常量30,此后凡在本程序单位中出现的PRICE都代表30,可以和常量一样进行运算,程序运行结果为:total=3002023/2/391请注意符号常量虽然有名字,但它不是变量。它的值在其作用域(在本例中为主函数)内是不能改变的,也不能被赋值。如用赋值语句“PRICE=40;”给PRICE赋值是错误的。使用符号常量的好处是:(1)含义清楚。(2)在需要改变一个常量时能做到“一改全改”。如#definePRICE352023/2/392在定义变量时,如果加上关键字const,则变量的值在程序运行期间不能改变,这种变量称为常变量(constantvariable)。例如:constinta=3;//用const来声明这种变量的值不能改变,指定其值始终为3常变量2023/2/393在定义常变量时必须同时对它初始化(即指定其值),此后它的值不能再改变。常变量不能出现在赋值号的左边。例如上面一行不能写成

constinta;

a=3;//常变量不能被赋值可以用表达式对常变量初始化,如:

constintb=3+6,c=3*cos(1.5);

//b的值被指定为9,c的值被指定为3*cos(1.5)2023/2/394但应注意,由于使用了系统标准数学函数cos,必须将包含该函数有关的信息的头文件“cmath”(或math.h)包含到本程序单位中来,可以在本程序单位的开头加上以下#include命令:#include<cmath>或#include<math.h>2023/2/395变量的值应该是可以变化的,那为什么固定的量也称变量呢?其实,从计算机实现的角度看,变量的特征是存在一个以变量名命名的存储单元,在一般情况下,存储单元中的内容是可以变化的。对常变量来说,无非在此变量的基础上加上一个限定:存储单元中的值不允许变化。因此常变量又称为只读变量(read-only-variable)。2023/2/396请区别用#define命令定义的符号常量和用const定义的常变量。

符号常量只是用一个符号代替一个字符串,在预编译时把所有符号常量替换为所指定的字符串,它没有类型,在内存中并不存在以符号常量命名的存储单元。而常变量具有变量的特征,它具有类型,在内存中存在着以它命名的存储单元,可以用sizeof运算符测出其长度。2023/2/397用#define命令定义符号常量是C语言所采用的方法,C++把它保留下来是为了和C兼容。

C++程序员一般喜欢用const定义常变量。虽然二者实现的方法不同,但从使用角度看,都可以认为用了一个标识符代表了一个常量。有些书上把用const定义的常变量也称为定义常量,但我们应该了解它和符号常量的区别。2023/2/398sizeof的使用

用法:sizeof(数据类型)orsizeof(变量)sizeof是一种计算,计算的对象是指定的一种数据类型,计算的结果是该数据类型占用的字节数目。如:sizeof(char)=1;也就是说char类型占用1个字节。sizeof(int)

=

4;也就是说int类型占用4个字节。2023/2/399为数据类型起别名:typedef用法:typedef原类型名新类型的别名为什么要给现成的数据类型起别名?例如:typedef

unsignedchar

UCHAR typedef

unsignedlong

DWORD

它们的一切属性都和其原名unsignedchar/long的数据类型完全一致。只是名字变得更简单好记一点而已.2023/2/3100判断输入错误intnumber;cout

<<

“PleaseInputInteger!:

;cin>>numberif(number<0){ for(inti=0;(i<3)&&(number)<0;i++) {

cout<<“InputError!Pleaseenteranumberagain

”;

cin>>number }if(i==3){

cout<<“InputthreetimesError!Bye-bye!”;return1;}}……

-8589934602023/2/3101由于cin>>number只能接受整数,如果用户输入了字母,则这个字母会遗留在“输入缓冲区”中。因为缓冲中有数据,故而cin函数不会等待用户输入,直接就去缓冲中读取,可是缓冲中的却是字母,这个字母再次被遗留在缓冲中,如此反复……2023/2/3102判断输入错误1intnumber;cout

<<

“PleaseInputInteger!:

;while(!(cin>>number)){cin.clear();//清除输入流的错误标记,重置输入

//

把输入缓冲区中的残留字符清空

while(cin.get()!=‘\n’) continue;

cerr<<“InputError!Pleaseenteranumber:”;}2023/2/3103判断输入错误2#include

<limits>

intmain(

){

intival;

cout

<<

"PleaseInputInteger!:

"

;

while

(

!(

cin

>>

ival)

)

{

cerr

<<

“InputFormatError!\n";

cin.clear(

);

cin.ignore

(

numeric_limits

<

streamsize

>

::max(

),'\n'

)

;

}

cout

<<

"YouEntered:"

<<

ival<<endl;

}2023/2/3104判断输入错误2A.读到非法字符后,输入流将处于出错状态, 为了继续获取输入,首先要调用clear函数 来清除输入流的错误标记,然后才能调用

ignore函数来清除输入缓冲区中的数据。

B.numeric_limits<streamsize>::max()返回缓冲区的大小。注:numeric_limits<type>::digits-计算type的位数numeric_limits<type>::max()-计算type的最大值2023/2/3105stringb,a,s1="Hello";strings2="123";a=s1;

//copycout<<(a+=s2)<<endl;

//concatenatereverse(a.begin(),a.end());//reversecout<<endl;cout<<a<<endl;cout<<a.replace(0,9,9,‘c’)<<endl;

//replacecout<<a.replace(0,5,9,'c')<<endl;

2023/2/3106stringa,s1="Hello";strings2="123";a=s1;

//copycout

<<

(

a

+

=

s2

)

<<

endl;

//concatenatereverse

(

a.begin(

),

a.end(

)

);

//reversecout

<<

endl;cout

<<

a

<<

endl;cout

<<

a.replace

(

0,9,

9,

‘c’

)<<endl;

//replacecout

<<

a.replace

(

0,9,

9,

‘9’

)<<endl;cout

<<

a.replace

(

0,

5,

9,

‘c’

)<<endl;

2023/2/31075.数组(Arrays)

数组的元素排列在连续的空间中,按下标来标记。描述数组必须给出元素类型,元素个数元素个数必须在编程时确定,不允许使用变量,常变量除外!

int

a[’a’];//表示inta[97];

intn=100;

int

a[n];//错:元素个数必须预知

constintn=100;

int

a[n];//ok

int

a[];//错:无元素个数

inta[]={1,2,3,4,5};

//ok:通过初始化确定元素个数2023/2/3108数组初始化可选,但须遵循语法。无初始化的数组按规定取默认值。intarray1[5]={1,2,3,4,5,6};

//错:初始值个数超元素个数intarray2[5]={1,,2,3,4};

//

错:不能以逗号方式省略intarray3[5]={1,2,3,};

//错:同上2023/2/3109intarray4[5]={};

//错:初始值不能为空intarray5[5]={1,2,3};

//ok:后面元素取0intarray6[5]={0};

//ok:元素全为0intarray7[5];

//ok:元素值不确定inta[3][5]={{1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7}};2023/2/3110数组有诸多缺陷,造成编程艰难和不安全

inta[5]={1,2,3,4,5},c[5];

intb[5]=a;//错:无法拷贝创建

c=a;

//错:无法整体拷贝和局部拷贝

a[8]=10;//错:无法动态扩容和随意增减元素

for(int

i=0;i<=5;++i)

//

错:无法防范下标溢出

a[i]=i+1;

if(a==c)

a[0]=2;

//错:不可比较

inta[5]={1};

//初始化呆板,无法获得全1初值2023/2/3111二维数组的初始化,下标访问及输出

intarray1[2][3]={1,2,3,4,5};

intarray2[2][3]={{1,2},{4}};

cout<<"array1:";

for(int

i=0;i<2;++i)

for(int

j=0;j<3;++j)

cout<<array1[i][j]<<",";

cout<<"\narray2:";

for(int

i=0;

i<2;++i)

for(int

j=0;j<3;

++j)

cout<<array2[i][j]<<",";

cout<<"\n";2023/2/3112结果为:

array1: 1,2,3,4,5,0,

array2:

1,2,0,4,0,0,2023/2/3113作业:C++有哪几种主要的数据类型?简述其值域。编程显示你正在使用的计算机中的常用的数据类型的字节数。提示用户输入一个十进制整数,然后分别用十进制、八进制和十六进制形式输出(考虑错误处理)。编写一个函数,统计一个英文句子中字母的个数,在主程序中实现输入、输出。P101第5题2023/2/31146.向量(vector)

向量与数组的共同特征是元素的排列在逻辑上是线性序列结构,可以用下标进行访问。

向量的特性:

A.按需创建 B.拷贝创建 C.局部拷贝创建 D.异类拷贝和创建 E.灵活的初始化 F.随意扩容和元素增减 G.可通过异常来进行下标溢出追踪和处理……2023/2/3115intn=10;intt[5]={1,2,3,4,5};vector<int>a(n);//按需创建vector<int>b(10,1);//元素赋全1,灵活的初始化vector<int>c(b);//整体拷贝创建vector<int>f(t,t+5);//异类拷贝创建vector<int>d(b.begin(),

b.begin()+3);

//局部拷贝创建d为b的前3个元素a.assign(100);//动态扩容至100个元素2023/2/3116向量常用操作a.assign(b.begin(),

b.begin()+3);//b的前3个元素赋给aa.assign(4,2);//a向量含4个元素,全初始化为2intx=a.back();//a的最后一个元素赋给变量xa.clear();

//a向量清空(不再有元素)if(a.empty())

cout<<”empty”;//a判空操作inty=a.front();

//a的第

温馨提示

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

评论

0/150

提交评论