C++程序設(shè)計(jì)教程-03_第1頁
C++程序設(shè)計(jì)教程-03_第2頁
C++程序設(shè)計(jì)教程-03_第3頁
C++程序設(shè)計(jì)教程-03_第4頁
C++程序設(shè)計(jì)教程-03_第5頁
已閱讀5頁,還剩123頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

第三章數(shù)據(jù)類型

Chapter3

DataTypes2023/2/31本章學(xué)習(xí)目標(biāo):初始化和二維數(shù)組B數(shù)組指針運(yùn)算D指針二維向量C向量基本類型及其表示方法A基本類型2023/2/32Contents整型子類(sub-intTypes)2C-串與string4整型(intTypes)31浮點(diǎn)型(Floating-PointType)

33向量(vectors)6數(shù)組(Arrays)35指針與引用(Pointer&References)372023/2/33這是個有類型的世界Q1:現(xiàn)實(shí)生活,有哪些信息可以用計(jì)算機(jī)可以管理呢?Q2:所有的這些信息,在計(jì)算機(jī)里都是以什么樣的數(shù)據(jù)形式來表達(dá)呢?“二進(jìn)數(shù)”,正確?!耙褦?shù)字化的數(shù)據(jù)”,也算正確?!?和1”,正確?!皺C(jī)器語言”,正確!2023/2/34所有的信息都用機(jī)器語言-那些0和1來表達(dá)編寫程序豈不很難盡量向“高級動物”的思維習(xí)慣做了一些接近如果那么所以數(shù)據(jù)類型,就是計(jì)算機(jī)語言向人類語言靠近時,走出的第一步,很重要的一步。因?yàn)椋簷C(jī)器語言或匯編語里,沒有數(shù)據(jù)類型一說。2023/2/35整個世界都可以用數(shù)據(jù)和處理來表達(dá)

整個世界就是一個程序;而萬物是世界的數(shù)據(jù)=2023/2/36通過抽象將人類世界中的類型,移植到計(jì)算機(jī)中。官方定義:數(shù)據(jù)類型是指定義了一組數(shù)據(jù)以及定義在這一組數(shù)據(jù)的操作,它是程序中最基本的元素。2023/2/37C++數(shù)據(jù)類型十分豐富,大體上可分為基本類型、空類型、構(gòu)造類型、指針類型、類類型五種。如下圖所示。最重要類型,也稱為C/C++語言的基本數(shù)據(jù)類型,只有兩個:“數(shù)值”和“字符”。第一是“數(shù)值類型”。這樣,在職工的信息中,比如年紀(jì),工齡、工資就有了歸屬第二是“字符類型”。像職工姓名或家庭住址2023/2/38數(shù)據(jù)類型基本類型空類型(無值類型)void構(gòu)造類型類類型class指針類型整型int實(shí)型(浮點(diǎn)型)字符型邏輯型bool結(jié)構(gòu)類型struct數(shù)組類型array枚舉型類型enum向量類型vector聯(lián)合型類型union單精度型float雙精度型double單字符型char寬字符型w-char圖:C++數(shù)據(jù)類型2023/2/39理解整型和實(shí)型

數(shù)值類型又被分為“整型”和“實(shí)型”。整型就是不帶小數(shù)位的數(shù),而實(shí)型則是指帶小數(shù)位的數(shù),也稱為“浮點(diǎn)數(shù)”。問題:2=2.0,為什么不直接用浮點(diǎn)數(shù)來代替整數(shù)回答:因?yàn)樵谟?jì)算機(jī)里,對整數(shù)的運(yùn)算要遠(yuǎn)遠(yuǎn)快于對浮點(diǎn)數(shù)的運(yùn)算2023/2/310

折中的結(jié)果就是雖然都是數(shù)值類型,但程序員在程序時,必須事先想好,哪些數(shù)據(jù)是必須帶小數(shù)計(jì)算的,那些數(shù)據(jù)定為實(shí)型。所以,在人類的思維習(xí)慣與計(jì)算機(jī)特點(diǎn)之間,必須做一個折中。2023/2/311理解數(shù)值的范圍

同顧及計(jì)算機(jī)的運(yùn)行速度一樣,與速度同樣重要的是計(jì)算機(jī)的空間的考慮。這就是計(jì)算機(jī)的空間問題:任何一個量,都有一個大的上限,和小的下限,出了這個范圍(比上限還大,比下限還?。蜁Q為溢出。數(shù)值類型在被劃分為整型和實(shí)型后,將根據(jù)所占用的空間而被繼續(xù)劃分為幾種不同類型2023/2/312字符型和各種整型、實(shí)型類型標(biāo)識符類型說明長度

(字節(jié))范圍備注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實(shí)型(單精度)41.18*10-38~3.40*1038

7位有效位double實(shí)型(雙精度)82.23*10-308~1.79*10308

15位有效位longdouble實(shí)型(長雙精度)103.37*10-4932~1.18*104932

19位有效位2023/2/3131.整型(intTypes)整型數(shù)的內(nèi)部表示:二進(jìn)制補(bǔ)碼

好處:二進(jìn)制補(bǔ)碼運(yùn)算沒有加減的區(qū)別;即--減法也可以用加法實(shí)現(xiàn);符號位也可以參加運(yùn)算。整型數(shù)的表示范圍:取決于二進(jìn)制位數(shù)一個m位的整型若采用原碼或反碼表示,其范圍是,若用補(bǔ)碼表示,則范圍是:。2023/2/314說明:整型數(shù)據(jù)分為長整型(longint)、一般整型(int)和短整型(shortint)。在int前面加long和short分別表示長整型和短整型。(2)整型數(shù)據(jù)的存儲方式為按二進(jìn)制數(shù)形式存儲,例如十進(jìn)制整數(shù)85的二進(jìn)制形式為1010101,則在內(nèi)存中的存儲形式如下圖所示。2023/2/315

(3)在整型符號int和字符型符號char的前面,可以加修飾符signed(表示“有符號”)或unsigned(表示“無符號”)。如果指定為signed,則數(shù)值以補(bǔ)碼形式存放,存儲單元中的最高位(bit)用來表示數(shù)值的符號。如果指定為unsigned,則數(shù)值沒有符號,全部二進(jìn)制位都用來表示數(shù)值本身。例如短整型數(shù)據(jù)占兩個字節(jié),見下圖。2023/2/316有符號時,能存儲的最大值為215~1,即32767,最小值為-32768。無符號時,能存儲的最大值為216~1,即65535,最小值為0。有些數(shù)據(jù)是沒有負(fù)值的,可以使用unsigned,它存儲正數(shù)的范圍比用signed時要大一倍。2023/2/3172.整型子類(Sub-intTypes)字符型:表示范圍:

有符號:-128~127

無符號:0~255

輸出形式與整型數(shù)不同:

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

結(jié)果為:

65A

2023/2/318枚舉型:自定義整數(shù)區(qū)間,甚至列舉單個整數(shù)值

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

最大特點(diǎn)是可以給每個值指定一個在程序中直接使用的標(biāo)記-(枚舉符).編程中將其當(dāng)作整數(shù)常量用.如:

inta=7;if(a==Sun)cout<<“Sunday\n”;2023/2/319布爾型:表示范圍僅含整數(shù)0和1,也可以表示成true和false,相當(dāng)于:

enumbool{false,true};因?yàn)闂l件表達(dá)式、邏輯運(yùn)算的結(jié)果都是0或1,所以,很多的表達(dá)式的值都與布爾型相對應(yīng)2023/2/320常量的值是不能改變的,一般從其字面形式即可判別是否為常量。

常量包括兩大類,即數(shù)值型常量(即常數(shù))和字符型常量。如12,0,-3為整型常量,4.6,-1.23為實(shí)型常量,包含在兩個單引號之間的字符為字符常量,如′a′,′x′。這種從字面形式即可識別的常量稱為“字面常量”或“直接常量”。什么是常量2023/2/3211.普通的字符常量用單引號括起來的一個字符就是字符型常量。如′a′?!?′,′%′,′D′都是合法的字符常量,在內(nèi)存中占一個字節(jié)。

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

②字符常量區(qū)分大小寫字母,如′A′和′a′是兩個不同的字符常量。

③引號(′)是定界符,而不屬于字符常量的一部分。如cout<<′a′;輸出的是一個字母a。字符常量2023/2/3222.轉(zhuǎn)義字符常量除了以上形式的字符常量外,C++還允許用一種特殊形式的字符常量,就是以“\”開頭的字符序列。例如,′\n′代表一個“換行”符?!癱out<<′\n′;”將輸出一個換行,其作用與“cout<<endl;”相同。這種“控制字符”,在屏幕上是不能顯示的。在程序中也無法用一個一般形式的字符表示,只能采用特殊形式來表示。常用的以“\”開頭的特殊字符見書P70中表3-3。2023/2/3233.字符數(shù)據(jù)在內(nèi)存中的存儲形式及其使用方法將一個字符常量存放到內(nèi)存單元時,實(shí)際上并不是把該字符本身放到內(nèi)存單元中去,而是將該字符相應(yīng)的ASCII代碼放到存儲單元中。如果字符變量c1的值為′a′,c2的值為′b′,則在變量中存放的是′a′的ASCII碼97,′b′的ASCII碼98,如圖(a)所示,實(shí)際上在內(nèi)存中是以二進(jìn)制形式存放的,如圖(b)所示。2023/2/3242023/2/325既然字符數(shù)據(jù)是以ASCII碼存儲的,它的存儲形式就與整數(shù)的存儲形式類似。這樣,在C++中字符型數(shù)據(jù)和整型數(shù)據(jù)之間就可以通用。一個字符數(shù)據(jù)可以賦給一個整型變量,反之,一個整型數(shù)據(jù)也可以賦給一個字符變量。也可以對字符數(shù)據(jù)進(jìn)行算術(shù)運(yùn)算,此時相當(dāng)于對它們的ASCII碼進(jìn)行算術(shù)運(yùn)算。2023/2/326例1將字符賦給整型變量。#include<iostream>usingnamespacestd;intmain(){ inti,j; i=‘A’; j=‘B’; cout<<i<<‘’<<j<<‘\n’; return0;}2023/2/327執(zhí)行時輸出6566i和j被指定為整型變量。但在第5和第6行中,將字符′A′和′B′分別賦給i和j,它的作用相當(dāng)于以下兩個賦值語句:i=65;j=66;2023/2/328因?yàn)椤銩′和′B′的ASCII碼為65和66。在程序的第5和第6行是把65和66直接存放到i和j的內(nèi)存單元中。因此輸出65和66??梢钥吹剑涸谝欢l件下,字符型數(shù)據(jù)和整型數(shù)據(jù)是可以通用的。但是應(yīng)注意字符數(shù)據(jù)只占一個字節(jié),它只能存放0~255范圍內(nèi)的整數(shù)。2023/2/329例2字符數(shù)據(jù)與整數(shù)進(jìn)行算術(shù)運(yùn)算。下面程序的作用是?#include<iostream>usingnamespacestd;intmain(){ charc1,c2; c1=′a′; c2=′b′; c1=c1-32; c2=c2-32; cout<<c1<<′′<<c2<<endl; return0;}2023/2/330運(yùn)行結(jié)果為AB′a′的ASCII碼為97,而′A′的ASCII碼為65,′b′為98,′B′為66。從ASCII代碼表中可以看到每一個小寫字母比它相應(yīng)的大寫字母的ASCII代碼大32。C++符數(shù)據(jù)與數(shù)值直接進(jìn)行算術(shù)運(yùn)算,字符a-32得到整數(shù)65,b-32得到整數(shù)66。將65和66存放在c1,c2中,由于c1,c2是字符變量,因此用cout輸出c1,c2時,得到字符A和B(A的ASCII碼為65,B的ASCII碼為66)。2023/2/331浮點(diǎn)型(又稱實(shí)型)數(shù)據(jù)分為單精度(float)、雙精度(double)和長雙精度(longdouble)3種;在VisualC++6.0中,對float提供6位有效數(shù)字,對double提供15位有效數(shù)字,并且float和double的數(shù)值范圍不同。對float分配4個字節(jié),對double和longdouble分配8個字節(jié)。

浮點(diǎn)型(Floating-PointType)2023/2/332一個浮點(diǎn)數(shù)可以用兩種不同的方式表示:十進(jìn)制小數(shù)形式。如21.456,-7.98等。它一般由整數(shù)部分和小數(shù)部分組成。C++編譯系統(tǒng)把用這種形式表示的浮點(diǎn)數(shù)一律按雙精度常量處理,在內(nèi)存中占8個字節(jié)。浮點(diǎn)數(shù)的表示方法2023/2/333如果在實(shí)數(shù)的數(shù)字之后加字母F或f,表示此數(shù)為單精度浮點(diǎn)數(shù),如1234F,-43f,占4個字節(jié)。如果加字母L或l,表示此數(shù)為長雙精度數(shù)(longdouble),在GCC中占12個字節(jié),在VisualC++6.0中占8個字節(jié)。2023/2/334(2)指數(shù)形式(即浮點(diǎn)形式)一個浮點(diǎn)數(shù)可以寫成指數(shù)形式,如3.14159可以表示為0.314159×101,3.14159×100,31.4159×10-1,314.159×10-2等形式。在程序中應(yīng)表示為:0.314159e1,3.14159e0,31.4159e-1,314.159e-2,用字母e表示其后的數(shù)是以10為底的冪,如e12表示1012。2023/2/335其一般形式為:數(shù)符數(shù)字部分指數(shù)部分上面各數(shù)據(jù)中的0.314159,3.14159,31.4159,314.159等就是其中的數(shù)字部分??梢钥吹剑河捎谥笖?shù)部分的存在,使得同一個浮點(diǎn)數(shù)可以用不同的指數(shù)形式來表示,數(shù)字部分中小數(shù)點(diǎn)的位置是浮動的。例如:2023/2/336a=0.314159e1;a=3.14159e0;a=31.4159e-1;a=314.159e-2;

以上4個賦值語句中,用了不同形式的浮點(diǎn)數(shù),但其作用是相同的。在程序中不論把浮點(diǎn)數(shù)寫成小數(shù)形式還是指數(shù)形式,在內(nèi)存中都是以指數(shù)形式(即浮點(diǎn)形式)存儲的。例如不論在程序中寫成314.159或314.159e0,31.4159e1,3.14159e2,0.314159e3等形式,在內(nèi)存中都是以規(guī)范化的指數(shù)形式存放,如右圖2023/2/337大家都知道任何數(shù)據(jù)在內(nèi)存中都是以二進(jìn)制(1或著0)順序存儲的,每一個1或著0被稱為1位,而在x86CPU上一個字節(jié)是8位。比如一個16位(2字節(jié))的shortint型變量的值是1156,那么它的二進(jìn)制表達(dá)就是:0000010010000100。由于IntelCPU的架構(gòu)是LittleEndian,所以在IntelCPU中,1156應(yīng)該怎樣存放……?2023/2/338BigEndian和LittleEndian談到字節(jié)序的問題,必然牽涉到兩大CPU派系。那就是Motorola的PowerPC系列CPU和Intel的x86系列CPU。PowerPC系列采用bigendian方式存儲數(shù)據(jù),而x86系列則采用littleendian方式存儲數(shù)據(jù)。那么究竟什么是bigendian,什么又是littleendian呢?

其實(shí)bigendian是指低地址存放最高有效字節(jié)(MSB)MostSignificantByte

,而littleendian則是低地址存放最低有效字節(jié)(LSB)LeastSignificantByte

。

2023/2/339

用文字說明可能比較抽象,下面用圖像加以說明。比如數(shù)字0x12345678在兩種不同字節(jié)序CPU中的存儲順序如下所示:2023/2/3402023/2/341為什么要注意字節(jié)序的問題呢?你可能這么問。當(dāng)然,如果你寫的程序只在單機(jī)環(huán)境下面運(yùn)行,并且不和別人的程序打交道,那么你完全可以忽略字節(jié)序的存在。但是,如果你的程序要跟別人的程序產(chǎn)生交互呢?假如是兩種語言-C/C++語言編寫的程序里數(shù)據(jù)存儲順序是跟編譯平臺所在的CPU相關(guān)的,而JAVA編寫的程序則唯一采用bigendian方式來存儲數(shù)據(jù)。試想,如果你用C/C++語言在x86平臺下編寫的程序跟別人的JAVA程序互通時會產(chǎn)生什么結(jié)果?2023/2/342

就拿上面的0x12345678來說,你的程序傳遞給別人的一個數(shù)據(jù),將指向0x12345678的指針傳給了JAVA程序,由于JAVA采取bigendian方式存儲數(shù)據(jù),很自然的它會將你的數(shù)據(jù)翻譯為0x78563412。什么?竟然變成另外一個數(shù)字了?是的,就是這種后果。因此,在你的C程序傳給JAVA程序之前有必要進(jìn)行字節(jié)序的轉(zhuǎn)換工作。

2023/2/343無獨(dú)有偶,所有網(wǎng)絡(luò)協(xié)議也都是采用bigendian的方式來傳輸數(shù)據(jù)的。所以有時我們也會把bigendian方式稱之為網(wǎng)絡(luò)字節(jié)序。當(dāng)兩臺采用不同字節(jié)序的主機(jī)通信時,在發(fā)送數(shù)據(jù)之前都必須經(jīng)過字節(jié)序的轉(zhuǎn)換成為網(wǎng)絡(luò)字節(jié)序后再進(jìn)行傳輸。目前應(yīng)該little

endian是主流,因?yàn)樵跀?shù)據(jù)類型轉(zhuǎn)換的時候(尤其是指針轉(zhuǎn)換)不用考慮地址問題。

2023/2/344那么shortint型變量1156,即:0000010010000100。在奔騰系列的計(jì)算機(jī)中,1156應(yīng)該怎樣存放……?2023/2/345由于IntelCPU的架構(gòu)是LittleEndian,所以在IntelCPU中,1156,即:0000010010000100是按字節(jié)倒序存儲的,那么就因該是這樣:1000010000000100這就是定點(diǎn)數(shù)1156在內(nèi)存中的結(jié)構(gòu)。那么浮點(diǎn)數(shù)是如何存儲的呢?

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

(國際電子電器工程師協(xié)會)制定的IEEE754浮點(diǎn)數(shù)表示法來進(jìn)行運(yùn)算的。這種結(jié)構(gòu)是一種科學(xué)表示法,用符號(正或負(fù))、指數(shù)(或階碼)和尾數(shù)來表示,底數(shù)被確定為2,也就是說是把一個浮點(diǎn)數(shù)表示為尾數(shù)乘以2的指數(shù)次方再加上符號。2023/2/347下面來看一下具體的float的規(guī)格:float

共計(jì)32位,折合4字節(jié)

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

31位是符號位,1表示該數(shù)為負(fù),0反之。

30~23位,一共8位是指數(shù)(階碼)位。

22~0位,一共23位是尾數(shù)位。

每8位分為一組,分成4組,分別是A組、B組、C組、D組。

每一組是一個字節(jié),在內(nèi)存中逆序存儲,即:DCBA2023/2/348現(xiàn)在讓我們按照IEEE浮點(diǎn)數(shù)表示法,一步步的將float型浮點(diǎn)數(shù)12345.0f轉(zhuǎn)換為十六進(jìn)制代碼。在處理這種不帶小數(shù)的浮點(diǎn)數(shù)時,直接將整數(shù)部轉(zhuǎn)化為二進(jìn)制表示:1,1110,0010,0100,0000也可以這樣表示:1,1110,0010,0100,0000.02023/2/3491,1110,0010,0100,0000.0然后將小數(shù)點(diǎn)向左移,一直移到離最高位只有1位,這種情況下,其實(shí)最高位也就是:“1”!即:1.11100010010000000一共移動了16位,小數(shù)點(diǎn)每向左移一位就等于在以“2”為底的科學(xué)計(jì)算法表示中指數(shù)+1,所以原數(shù)就等于這樣:1.11100010010000000*(2^16)。這就叫做二進(jìn)制浮點(diǎn)數(shù)的“規(guī)格化”!注意:這和十進(jìn)制科學(xué)計(jì)數(shù)法的規(guī)格化:X=0.X*(10^m),比如123=0.123*(10^3)是不同的喔^_^2023/2/350OK,現(xiàn)在我們要的尾數(shù)和指數(shù)都出來了。顯而易見,最高位永遠(yuǎn)是“1”,因?yàn)槟悴豢赡馨奄I了16個雞蛋說成是買了0016個雞蛋吧?所以這個1我們還有必要保留嗎???2023/2/351好的,我們刪掉他!再舉一個例子!如:在32位浮點(diǎn)數(shù)中:

0.6=0.1001(2)

=1.0011,0011,0011,0011,0011,001如果刪掉最高位的“1”,就比老老實(shí)實(shí)表示的23位尾數(shù):

0.1001,1011,1001,1011,0011,101

多了一位精度。在具體實(shí)現(xiàn)中,去掉規(guī)格化的1,寫入二進(jìn)制浮點(diǎn)數(shù)!而當(dāng)重新從機(jī)器中取出參加運(yùn)算時,則補(bǔ)上1。因此23尾數(shù),加上省略的一位,其精度或有有效尾數(shù)就變成了24位^_^2023/2/352呵呵^_^,繼續(xù)回到我們的數(shù)12345.0f:

1.1110,0010,0100,000,00*(2^16)。這樣尾數(shù)的二進(jìn)制就變成了:1110,0010,0100,0000,0最后在尾數(shù)的后面補(bǔ)0,一直到補(bǔ)夠23位:1110,0010,0100,0000,0000,000OK!到此為止,我們的尾數(shù)就計(jì)算完畢。2023/2/353再回來看階碼(即指數(shù)),一共8位,可以表示范圍是0~255的無符號整數(shù),也可以表示-128~127的有符號整數(shù)。但因?yàn)橹笖?shù)是可以為負(fù)的,所以為了統(tǒng)一,同時為了使得浮點(diǎn)數(shù)0與整數(shù)0統(tǒng)一,即符號位、階碼位和尾數(shù)位全部為零。把十進(jìn)制的整數(shù)化為二進(jìn)制時,都先加上127,而在取出該浮點(diǎn)數(shù)時,再做一個減127的逆操作!在這里,我們的16加上127后就變成了143,二進(jìn)制表示為:10001111

思考:-128在機(jī)器中是如何表示的???2023/2/354注意:

由于補(bǔ)碼中“0”的表示是唯一的,故【X】補(bǔ)

=1000……0,對應(yīng)的真值應(yīng)該是:X=

其實(shí)補(bǔ)碼“1000……0”的形式是一個特殊情況,最高位的1既代表符號又代表數(shù)值?。?!

2023/2/355繼續(xù)由于12345.0f這個數(shù)是正的,所以符號位是0,那么我們按照前面講的格式把它拼起來:

符號位階碼尾數(shù)

01000111111100010010000000000000

即:0100,0111,1111,0001,0010,0000,0000,0000再轉(zhuǎn)化為16進(jìn)制為:47F12000,最后把它翻過來,就成了:0020F147。即浮點(diǎn)數(shù)12345.0f在機(jī)器最終表示為:0020F147

現(xiàn)在把5432.0f轉(zhuǎn)為二進(jìn)制表示,試試看!?。?023/2/356有了上面的基礎(chǔ)后,下面我再舉一個帶小數(shù)的例子來看一下為什么會出現(xiàn)精度問題。

按照IEEE浮點(diǎn)數(shù)表示法,將float型浮點(diǎn)數(shù)35.6f轉(zhuǎn)換為十六進(jìn)制代碼。對于這種帶小數(shù)的就需要把整數(shù)部和小數(shù)部分開處理。整數(shù)部直接化二進(jìn)制:100011。小數(shù)部的處理比較麻煩一些了……2023/2/357具體辦法,就是采用“乘2取整法”,即:對被轉(zhuǎn)換的十進(jìn)制小數(shù)乘以2,取其整數(shù)部分作為二進(jìn)制的小數(shù)部分,再乘以2,直到小數(shù)部分為0,或者已經(jīng)取到了足夠的位數(shù)。每次取的整數(shù)部分,按先后次序,構(gòu)成了二進(jìn)制小數(shù)從高到低位的數(shù)字排列。具體如下: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開始循環(huán)了哦……這說明0.6=0.100110011001……(2)2023/2/3590.6=0.100110011001……(2)假設(shè),我們要求的精度是小數(shù)點(diǎn)后16位,那么,0.6的二進(jìn)制表示形式應(yīng)該是多少呢??

是:10011001

1001

1001

嗎???

不對?。。≌_的應(yīng)該是:

10011001

10011010(見書P75)2023/2/360OK,我們繼續(xù)^_^嗯,剛才那個數(shù)還沒轉(zhuǎn)完呢,反正最后一直求也求不盡,加上前面的整數(shù)部分算夠24位就行了,即:100011.100110011001

100110。某DX問:“不是說尾數(shù)是23位嗎?為什么要算夠24位?”“暈!不是說過了要把第一個1去掉嗎?所以當(dāng)然要加一位嘍!”2023/2/361現(xiàn)在開始向左移小數(shù)點(diǎn),大家和我一起移,“1、2、3……”好了,一共移了5位,5加上127得132(呵呵~),二進(jìn)制表示為:

10000100

所以:

35.6f的價碼在計(jì)算機(jī)中表示為:

100001002023/2/362

So-符號位為……,然后再……,哎喲,不說了,越說越啰嗦,大家自己看吧:

0,10000100,000111001100

1100

1100110

即:

01000010

00001110

01100110

0110

0110

42

0E

66

66

42

0E

66

66

內(nèi)存中應(yīng)為:66

66

0E

422023/2/363一個IEEE754浮點(diǎn)數(shù)的問題?將(100.25)D轉(zhuǎn)換成短浮點(diǎn)數(shù)。并且:

(1)把十進(jìn)制轉(zhuǎn)成二進(jìn)制。

(2)規(guī)格化二進(jìn)制

(3)計(jì)算出移碼(階碼真值+偏移量)

2023/2/364

思考:這個110是如何得出來的?……一、把十進(jìn)制轉(zhuǎn)成二進(jìn)制。

(100.25)D=(1100100.01)B二、規(guī)格化二進(jìn)制

1100100.01=1.10010001*2^6三、計(jì)算出移碼(階碼真值+偏移量)

110+01111111=100001012023/2/365補(bǔ)充:階碼是以移碼的形式存儲!對于單精度浮點(diǎn)數(shù),偏移量為127(7FH),而雙精度的偏移量為1023(3FFH)。存儲浮點(diǎn)數(shù)的階碼之前,偏移量要先加到階碼上。比如:階為2的三次方,則在單精度浮點(diǎn)數(shù)中,移碼后的結(jié)果為127+3即130(82H),雙精度為1026(402H)。2023/2/366最后,要特別注意:浮點(diǎn)數(shù)有兩個例外!

A.數(shù)0.0存儲為全零。

B.無限大數(shù)的階碼存儲為全1,尾數(shù)部分全零。符號位用來指示是正無窮還是負(fù)無窮。2023/2/367作業(yè):

將十進(jìn)制數(shù)-12和0.25轉(zhuǎn)換成單精度浮點(diǎn)數(shù)在計(jì)算機(jī)中存儲的標(biāo)準(zhǔn)格式。2023/2/368十進(jìn)制數(shù)-12和0.25轉(zhuǎn)換成單精度浮點(diǎn)數(shù)后在計(jì)算機(jī)中存儲的標(biāo)準(zhǔn)格式如下:2023/2/3694.C-串與string(C-string&string)C-串結(jié)構(gòu)

每個字符占據(jù)1個字節(jié)一個C-串是一個字符序列,用來表示各種名字或者文字說明

C-串的字符序列的最后總是添加有一個結(jié)束標(biāo)志。即在6個字符的字串(“Hello!”)其空間存儲有7個字節(jié)左邊三圖是不同細(xì)節(jié)的同一空間結(jié)構(gòu)描述’H’’e’’l’’l’’o’’!’’\0’

72101108108111330010010000110010101101100011011000110111100100001000000002023/2/370用雙引號括起來的部分就是字符串常量,如″abc″,″Hello!″,″a+b″,″Liping″都是字符串常量。字符串常量″abc″在內(nèi)存中占4個字節(jié)(而不是3個字節(jié)),見下圖。編譯系統(tǒng)會在字符串最后自動加一個′\0′作為字符串結(jié)束標(biāo)志。但′\0′并不是字符串的一部分,它只作為字符串的結(jié)束標(biāo)志。如:cout<<″abc″<<endl;

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

″a″和′a′代表不同的含義,″a″是字符串常量,′a′是字符常量。前者占兩個字節(jié),后者占1個字節(jié)。分析下面的程序片段:

charc;//定義一個字符變量c=′a′;//正確c=″a″;//錯誤,c只能容納一個字符2023/2/372請思考:字符串常量″abc\n″包含幾個字符?答:不是5個而是4個字符,其中“\n”是一個轉(zhuǎn)義字符。但它在內(nèi)存中占5個字節(jié)(包括一個“\0”字符)。編譯系統(tǒng)遇到“\”時就會把它認(rèn)作轉(zhuǎn)義字符的標(biāo)志,把它和其后的字符一起作為一個轉(zhuǎn)義字符。So,字符串常量要用字符數(shù)組來存放!2023/2/373如果“\”后面的字符不能與“\”組成一個合法的轉(zhuǎn)義字符(如″\b″),則在編譯時顯示出錯信息。如果希望將“\”字符也作為字符串中的一個字符,則應(yīng)寫為″abc\\n″,此時字符串包括5個字符,即a,b,c,\,n。如果有以下輸出語句:cout<<″abc\\\n″<<endl;則會輸出:abc\,然后換行。思考一下:執(zhí)行的輸出又是什么呢??……cout<<″Isay\″Thankyou?。堋澹躰″;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-串不能直接比較,因?yàn)樽址羔樀谋容^只是地址值的比較而不是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”;//字符數(shù)組比較結(jié)果:

notequal

notequal

notequal2023/2/378So,不得不配備專門操作C-串的庫函數(shù):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-串的安全性受到質(zhì)疑:char*str1;char*str2=new

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

//

錯:str1沒有空間可儲strcpy(str2,“Hello”);

//錯:str2空間不夠大str2=“Hello”;

//錯:原來的”ugly”空間脫鉤,導(dǎo)致內(nèi)存泄漏根源:復(fù)制操作須以足夠的目的地空間為前提,而所有C-串操作的空間調(diào)配都是人為安排的,C-串庫函數(shù)一概不管。2023/2/380類串string-串類-自定義串對應(yīng)字符指針的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>>

的讀入方式總是將前導(dǎo)的空格(所謂空格,即包括空格、回車、水平或垂直制表符等)濾掉,將單詞讀入,在遇到空格時結(jié)束本次輸入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實(shí)體看作是一個輸入設(shè)備。給一個像cin這樣的取名,作為流來操作,會很有用。例如,如果一個文件aaa.txt,有若干行,每行中含有不知道幾個的整數(shù),要輸出每行的整數(shù)和:

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流可以將輸入輸出設(shè)備和一塊表示string字符串的內(nèi)存區(qū)域連接起來。所有從程序的輸出都將被保存到這塊內(nèi)存中,同時也可以從這塊內(nèi)存中讀取數(shù)據(jù)到程序中。

使用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字符串轉(zhuǎn)換為算術(shù)類型,如:intmain(){

//……

//繼續(xù)上面的程序//接收一個string字符串作為參數(shù),這個參數(shù)作為其底層儲存istringstreamistring(str);istring>>ival>>dval;

//將字符串轉(zhuǎn)換為一個int和一個double}2023/2/388為了編程和閱讀的方便,在C++程序設(shè)計(jì)中,常用一個符號名代表一個常量,稱為符號常量,即以標(biāo)識符形式出現(xiàn)的常量。符號常量2023/2/389例:

符號常量的使用。

#definePRICE30//注意這不是語句,末尾不要加分號intmain(){ intnum,total; num=10; total=num*PRICE; cout<<″total=″<<total<<endl; return0;}2023/2/390程序中用預(yù)處理命令#define指定PRICE在本程序單位中代表常量30,此后凡在本程序單位中出現(xiàn)的PRICE都代表30,可以和常量一樣進(jìn)行運(yùn)算,程序運(yùn)行結(jié)果為:total=3002023/2/391請注意符號常量雖然有名字,但它不是變量。它的值在其作用域(在本例中為主函數(shù))內(nèi)是不能改變的,也不能被賦值。如用賦值語句“PRICE=40;”給PRICE賦值是錯誤的。使用符號常量的好處是:(1)含義清楚。(2)在需要改變一個常量時能做到“一改全改”。如#definePRICE352023/2/392在定義變量時,如果加上關(guān)鍵字const,則變量的值在程序運(yùn)行期間不能改變,這種變量稱為常變量(constantvariable)。例如:constinta=3;//用const來聲明這種變量的值不能改變,指定其值始終為3常變量2023/2/393在定義常變量時必須同時對它初始化(即指定其值),此后它的值不能再改變。常變量不能出現(xiàn)在賦值號的左邊。例如上面一行不能寫成

constinta;

a=3;//常變量不能被賦值可以用表達(dá)式對常變量初始化,如:

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

//b的值被指定為9,c的值被指定為3*cos(1.5)2023/2/394但應(yīng)注意,由于使用了系統(tǒng)標(biāo)準(zhǔn)數(shù)學(xué)函數(shù)cos,必須將包含該函數(shù)有關(guān)的信息的頭文件“cmath”(或math.h)包含到本程序單位中來,可以在本程序單位的開頭加上以下#include命令:#include<cmath>或#include<math.h>2023/2/395變量的值應(yīng)該是可以變化的,那為什么固定的量也稱變量呢?其實(shí),從計(jì)算機(jī)實(shí)現(xiàn)的角度看,變量的特征是存在一個以變量名命名的存儲單元,在一般情況下,存儲單元中的內(nèi)容是可以變化的。對常變量來說,無非在此變量的基礎(chǔ)上加上一個限定:存儲單元中的值不允許變化。因此常變量又稱為只讀變量(read-only-variable)。2023/2/396請區(qū)別用#define命令定義的符號常量和用const定義的常變量。

符號常量只是用一個符號代替一個字符串,在預(yù)編譯時把所有符號常量替換為所指定的字符串,它沒有類型,在內(nèi)存中并不存在以符號常量命名的存儲單元。而常變量具有變量的特征,它具有類型,在內(nèi)存中存在著以它命名的存儲單元,可以用sizeof運(yùn)算符測出其長度。2023/2/397用#define命令定義符號常量是C語言所采用的方法,C++把它保留下來是為了和C兼容。

C++程序員一般喜歡用const定義常變量。雖然二者實(shí)現(xiàn)的方法不同,但從使用角度看,都可以認(rèn)為用了一個標(biāo)識符代表了一個常量。有些書上把用const定義的常變量也稱為定義常量,但我們應(yīng)該了解它和符號常量的區(qū)別。2023/2/398sizeof的使用

用法:sizeof(數(shù)據(jù)類型)orsizeof(變量)sizeof是一種計(jì)算,計(jì)算的對象是指定的一種數(shù)據(jù)類型,計(jì)算的結(jié)果是該數(shù)據(jù)類型占用的字節(jié)數(shù)目。如:sizeof(char)=1;也就是說char類型占用1個字節(jié)。sizeof(int)

=

4;也就是說int類型占用4個字節(jié)。2023/2/399為數(shù)據(jù)類型起別名:typedef用法:typedef原類型名新類型的別名為什么要給現(xiàn)成的數(shù)據(jù)類型起別名?例如:typedef

unsignedchar

UCHAR typedef

unsignedlong

DWORD

它們的一切屬性都和其原名unsignedchar/long的數(shù)據(jù)類型完全一致。只是名字變得更簡單好記一點(diǎn)而已.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只能接受整數(shù),如果用戶輸入了字母,則這個字母會遺留在“輸入緩沖區(qū)”中。因?yàn)榫彌_中有數(shù)據(jù),故而cin函數(shù)不會等待用戶輸入,直接就去緩沖中讀取,可是緩沖中的卻是字母,這個字母再次被遺留在緩沖中,如此反復(fù)……2023/2/3102判斷輸入錯誤1intnumber;cout

<<

“PleaseInputInteger!:

;while(!(cin>>number)){cin.clear();//清除輸入流的錯誤標(biāo)記,重置輸入

//

把輸入緩沖區(qū)中的殘留字符清空

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.讀到非法字符后,輸入流將處于出錯狀態(tài), 為了繼續(xù)獲取輸入,首先要調(diào)用clear函數(shù) 來清除輸入流的錯誤標(biāo)記,然后才能調(diào)用

ignore函數(shù)來清除輸入緩沖區(qū)中的數(shù)據(jù)。

B.numeric_limits<streamsize>::max()返回緩沖區(qū)的大小。注:numeric_limits<type>::digits-計(jì)算type的位數(shù)numeric_limits<type>::max()-計(jì)算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.數(shù)組(Arrays)

數(shù)組的元素排列在連續(xù)的空間中,按下標(biāo)來標(biāo)記。描述數(shù)組必須給出元素類型,元素個數(shù)元素個數(shù)必須在編程時確定,不允許使用變量,常變量除外!

int

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

intn=100;

int

a[n];//錯:元素個數(shù)必須預(yù)知

constintn=100;

int

a[n];//ok

int

a[];//錯:無元素個數(shù)

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

//ok:通過初始化確定元素個數(shù)2023/2/3108數(shù)組初始化可選,但須遵循語法。無初始化的數(shù)組按規(guī)定取默認(rèn)值。intarray1[5]={1,2,3,4,5,6};

//錯:初始值個數(shù)超元素個數(shù)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數(shù)組有諸多缺陷,造成編程艱難和不安全

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

intb[5]=a;//錯:無法拷貝創(chuàng)建

c=a;

//錯:無法整體拷貝和局部拷貝

a[8]=10;//錯:無法動態(tài)擴(kuò)容和隨意增減元素

for(int

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

//

錯:無法防范下標(biāo)溢出

a[i]=i+1;

if(a==c)

a[0]=2;

//錯:不可比較

inta[5]={1};

//初始化呆板,無法獲得全1初值2023/2/3111二維數(shù)組的初始化,下標(biāo)訪問及輸出

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結(jié)果為:

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

array2:

1,2,0,4,0,0,2023/2/3113作業(yè):C++有哪幾種主要的數(shù)據(jù)類型?簡述其值域。編程顯示你正在使用的計(jì)算機(jī)中的常用的數(shù)據(jù)類型的字節(jié)數(shù)。提示用戶輸入一個十進(jìn)制整數(shù),然后分別用十進(jìn)制、八進(jìn)制和十六進(jìn)制形式輸出(考慮錯誤處理)。編寫一個函數(shù),統(tǒng)計(jì)一個英文句子中字母的個數(shù),在主程序中實(shí)現(xiàn)輸入、輸出。P101第5題2023/2/31146.向量(vector)

向量與數(shù)組的共同特征是元素的排列在邏輯上是線性序列結(jié)構(gòu),可以用下標(biāo)進(jìn)行訪問。

向量的特性:

A.按需創(chuàng)建 B.拷貝創(chuàng)建 C.局部拷貝創(chuàng)建 D.異類拷貝和創(chuàng)建 E.靈活的初始化 F.隨意擴(kuò)容和元素增減 G.可通過異常來進(jìn)行下標(biāo)溢出追蹤和處理……2023/2/3115intn=10;intt[5]={1,2,3,4,5};vector<int>a(n);//按需創(chuàng)建vector<int>b(10,1);//元素賦全1,靈活的初始化vector<int>c(b);//整體拷貝創(chuàng)建vector<int>f(t,t+5);//異類拷貝創(chuàng)建vector<int>d(b.begin(),

b.begin()+3);

//局部拷貝創(chuàng)建d為b的前3個元素a.assign(100);//動態(tài)擴(kuò)容至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. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論