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

提交評論