freepeople性欧美熟妇, 色戒完整版无删减158分钟hd, 无码精品国产vα在线观看DVD, 丰满少妇伦精品无码专区在线观看,艾栗栗与纹身男宾馆3p50分钟,国产AV片在线观看,黑人与美女高潮,18岁女RAPPERDISSSUBS,国产手机在机看影片

正文內(nèi)容

c++數(shù)據(jù)類型-文庫吧

2025-07-20 08:52 本頁面


【正文】 :st++測試的是st中的地址是否為零,而不是它指向的字符是否為空。這個條件將一直為真,因為循環(huán)的每次迭代都給st中的地址加1。程序?qū)⒂肋h執(zhí)行下去或者由系統(tǒng)終止它。這樣的循環(huán)被稱作為無限循環(huán)(infinite loop)我們的第二個版本改正了這個錯誤。它能執(zhí)行到結(jié)束。不幸的是:輸出的結(jié)果是錯誤的。你能發(fā)現(xiàn)我們這次犯的錯誤嗎?include iostreamconst char *st = “The expense of spirit\n”。int main() {int len = 0。while ( *st++) ++len。cout len “。 ” st。return 0。}這次的錯誤是st已經(jīng)不再指向字符串文字常量。st已經(jīng)前進到終止空字符之后的字符上去了。(程序的輸出結(jié)果取決于st所指向的內(nèi)存單元的內(nèi)容。)下面是一種可能的解決辦法:st = st –len。cout len “: ” st。編譯并執(zhí)行程序。但是,輸出仍然是不正確的。它產(chǎn)生如下結(jié)果:22: he expense of spirit這反映了程序設(shè)計某些本質(zhì)的方面。你能看到這次我們犯的錯誤嗎?在計算字符串的長度的時候,空字符并沒有被考慮在內(nèi)。st必須被重新定位到字符串長度加1的位置。下列代碼是正確的。st = st –len 1。編譯并執(zhí)行,程序最終產(chǎn)生正確的結(jié)果如下:22: The expense of spirit現(xiàn)在程序是正確了,但是,從程序風格的角度來說,它還有些不太雅致。語句:st = st –len 1。被加進來,以便改正由直接遞增st引起的錯誤。st的賦值不符合程序的原始邏輯,而且,現(xiàn)在的程序有些難以理解。像這樣的程序修正通常被稱作補丁(patch) – 把某些東西伸展開以便補上現(xiàn)有程序中的洞。我們通過補償原始設(shè)計中的邏輯錯誤來補救我們的程序。較好的解決方案是修正原始設(shè)計中的漏洞。一種方案是定義第二個指針,用st對它進行初始化。例如:const char *p = st?,F(xiàn)在可以用p來計算st的長度,而st不變:while ( *p++)字符串類型正如我們前面所看到的,因為字符指針的底層特性,用它表示字符串很容易出錯。為了將程序員從許多“與使用C風格字符串相關(guān)的錯誤”中解脫出來,每個項目、部門或公司都提供了自己的字符串實現(xiàn),那么程序的可移植性和兼容性就變得非常困難。C++標準庫提供了字符串類抽象的一個公共實現(xiàn)。你希望字符串類有哪些操作呢?最小的基本行為集合由什么構(gòu)成呢?1. 支持用字符序列或第二個字符串對象來初始化一個字符串對象。C風格的字符串不支持用另外一個字符串初始化一個字符串。 2. 支持字符串之間的拷貝。C風格字符串通過使用庫函數(shù)strcpy()來實現(xiàn)。3. 支持讀寫訪問單個字符。對于C風格字符串,單個字符訪問由下標操作符或直接解除指針引用來實現(xiàn)。4. 支持兩個字符串的相等比較。對于C風格字符串,字符串比較通過庫函數(shù)strcmp()來實現(xiàn)。5. 支持兩個字符串的連接:把一個字符串接到另一個字符串上,或?qū)蓚€字符串組合起來形成第三個字符串。對于C風格的字符串,連接由庫函數(shù)strcat()來實現(xiàn)。把兩個字符串連接起來形成第三個字符串的實現(xiàn)是,用strcpy()把一個字符串拷貝到一個新實例中,然后用strcat()把另一個字符串連接到新的實例上。6. 支持對字符串長度的查詢。對于C風格字符串,字符串長度由庫函數(shù)strlen()返回。7. 支持字符串是否為空的判斷。對于C風格字符串,通過下面兩步條件測試完成。char *str = 0。// …if (!str || ! *str) return。標準C++提供了支持這些操作的string類。要使用string類型,必須先包含相關(guān)的頭文件;include stringstring st( “The expense of spirit\m”)。st的長度由size()操作返回(不包含終止空字符)cout “The size of “ st “ is ” () ” characters, including the newline\n”。string 構(gòu)造函數(shù)第二種形式定義了一個空字符串。例如:string st2。 //空字符串我們怎樣能保證它是空的?當然,一種辦法是測試size()是否為0。if (! () ) // OK: 空如果字符串中不含有字符,則empty()返回布爾常量true;否則,返回false.第三種形式的構(gòu)造函數(shù),用一個string對象來初始化另一個string對象。例如:string st3( st)。將st3初始化成st的一個拷貝。怎樣驗證呢?等于操作符比較兩個string對象,如果相等則返回true:if (st == st3 ) //初始化成功怎樣拷貝一個字符串呢?最簡單的辦法是使用賦值操作符。例如:st2 = st3。 //把st3拷貝到st2中。首先將與st2相關(guān)聯(lián)的字符存儲區(qū)釋放掉,然后再分配足夠存儲與st3相關(guān)聯(lián)的字符的存儲區(qū),最后將與st3相關(guān)聯(lián)的字符拷貝到該存儲區(qū)中。 我們可以使用加操作符“+”或看起來有點怪異的復合賦值操作符“+=”,將兩個或多個字符串連接起來。例如,給出兩個字符串:string st1( “ hello, ”)。string st2( “ world\n”)。我們可以按如下方式將兩個字符串連接起來形成第三個字符串:string st3 = st1 + st2。如果希望直接將s2附加到s1后面,那么可使用“+=”操作符:s1 += s2。s1和s2的初始化包含了一個空格、一個逗號以及一個換行,這多少有些不方便。它們在存在限制了對這些string對象的重用,盡管它滿足了眼前的需要。一種替代做法就是混合使用C風格的字符串與string對象,如下所示:const char *pc = “, ”。string s1(“hello”)。string s2(“world”)。string s3 = s1 + pc + s2 + “\n”。這種連接策略比較受歡迎,因為它使s1和s2處于一種更容易被重用的形式。這種方法能夠生效是由于string類型能夠自動將C風格的字符串轉(zhuǎn)換成string對象。例如,這使我們可以將一個C風格的字符串賦給一個string對象string s1const char *pc = “a character array”。s1 = pc。 // OK但是,反向的轉(zhuǎn)換不能自動執(zhí)行。對隱式地將string對象轉(zhuǎn)換成C風格的字符串,string類型沒有提供支持。例如:下面試圖用s1初始化str,就會在編譯時刻失?。篶har *str = s1。 //編譯時刻類型錯誤為實現(xiàn)這種轉(zhuǎn)換,必須顯式地調(diào)用名為c_str()的操作:char *str = ()。 //幾乎是正確的,但是還差一點。名字c_str()代表了string類型與C風格字符串兩種表示法之間的關(guān)系。字面意思是:給我一個C風格的字符串表示,即:指向字符數(shù)組起始處的字符指針。但是,這個初始化還是失敗了。這次是由于另外一個不同的原因:為了防止字符數(shù)組被程序直接處理,c_str()返回了一個指向常量數(shù)組的指針const char*str被定義為非常量指針,所以這個賦值被標記為類型違例。正確的初始化如下:const char *str = ()。 //OKstring類型支持通過下標操作訪問單個字符。例如,在下面的代碼段中,字符串中的所有句號被下劃線代替:string str(“”)。int size=()。for (int ix=0。 ixsize。 +ix) if (str[ix] == ‘.’) str[ix] = ‘_’。上面還可以有replace((), (), ‘.’, ‘_’)。begin()和end()操作返回指向string開始和結(jié)束處的迭代器(iterator)。迭代器是指針的類抽象,由標準庫提供。replace()掃描begin()和end()之間的字符。每個等于句號的字符,都被替換成下劃線。const限定修飾符下面的循環(huán)有兩個問題,都是由于使用512作為循環(huán)上限引起的:for (int index = 0。 index 512。 ++index)第一個問題是可讀性。用512來測試index是什么意思?在這里被稱為魔數(shù)(magic number),它的重要性在上下文中沒有體現(xiàn)出來,就好像這個數(shù)是憑空出現(xiàn)的。第二個問題是可維護性。這兩個問題的解決方案就是使用一個被初始化為512的對象。通過選擇一個助記名,可能是bufSize,使程序更具可讀性?,F(xiàn)在,條件測試變成與對象作比較,而不是與一個文字常量作比較:index bufSize我們不需要再把320個出現(xiàn)的512的地方一一找出來,只需改變bufSize的值就行了。我們只需改變bufSize被初始化的那一行。這種方法不僅只需要很少的工作量,而且大大減少了出錯的可能性。這種方案的代價是一個額外的變量?,F(xiàn)在512被稱為是局部化的(localized)。int bufSize = 512。 //緩沖區(qū)大小//…for (int index = 0。 index bufSize。 ++index) //…這種方案的問題是,bufSize是一個左值。在程序中bufSize有可能被偶然修改。例如,下面是一個常見的程序錯誤:// 偶然地改變了bufSize的值If (bufSize = 1) // …在C++中,“=”是賦值操作符,而“==”是等于操作符。程序員不小心將bufSize的值改成1,將導致了一個很難跟蹤的錯誤。(這種錯誤很難被發(fā)現(xiàn),因為程序員一般不會認為這行代碼是錯的,這就是為什么許多編譯器會對此類的賦值表達式生成警告的原因。)const類型限定修飾符提供了一個解決方案。它把一個對象轉(zhuǎn)換成一個常量(constant)。例如const int bufSize = 512。 //緩沖區(qū)大小定義bufSize是一個常量,并將其初始化為512。在程序中任何改變這個值的企業(yè)都將導致編譯錯誤。因此,它被稱為是只讀的(readonly)。例如:// 錯誤:企業(yè)寫入const對象If (bufSize = 0) …因為常量在定義后就不能被修改,所以它必須被初始化。未初始化的常量定義將導致編譯錯誤。const double pi。 //錯誤:未初始化的常量一旦一個常量被定義了,我們就不能改變與const對象相關(guān)聯(lián)的值。另一方面,我們能把它的地址賦值給一個指針嗎?例如,下面代碼是否可行?const double minWage = 。double *prt = amp。minWage。這是否可行呢?minWage是一個常量對象,因此它不能被改寫為一個新的值。但是ptr是一個普通指針,沒有什么能阻止我們寫出這樣的代碼:*ptr += 。 //修改了minWage!一般編譯器不能跟蹤指針在程序中任意一點指向的對象。[這種內(nèi)部工作需要進行數(shù)據(jù)流分析(data flow analysis), 通常由單獨的優(yōu)化器(optimizer)組件來完成。]允許非const對象的指針指向一個常量對象,把“試圖通過該指針間接地改變對象值”的動作標記為非法的,這對編譯器來說是不可行的。因而任何“試圖將一個非const對象的指針指向一個常量對象”的動作都將引起編譯錯誤。這并不意味著我們不能間接地指向一個const對象,只意味著我們必須聲明一個指向常量的指針來做這件事。例如:const double *cptr。cptr是一個指向double類型的const對象的指針。(我們可以從右往左把這個定義讀為“cptr是一個指向double類型的、被定義成const的對象的指針”)此中微妙在于cptr本身不是常量。我們可以重新賦值cptr,使其指向不同的對象,但不能修改cptr指向的對象。例如:const double *pc = 0。const double minWage = 。// OK: 不能通過pc修改minWagepc = amp。minWage。double dval = 。// OK: 不能通過pc修改dval, 雖然dval本身不是一個常量pc = amp。dval。dval = 。 // ok*pc = 。 // NGconst對象的地址只能賦值給指向const對象的指針,例如pc。但是,指向const對象的指針可以被賦予一個非const對象的地址,例如pc = amp。dval。雖然dval 不是常量,但試圖通過pc修改它的值,仍會導致編譯錯誤(因為在運行程序的任意一點上,編譯器不能確定指針所指的實際對象)。在實際的程序中,指向const的指針常被用作函數(shù)的形式參數(shù)。它作為一個約定來保證:被傳遞給函數(shù)的實際對象在函數(shù)中不會修改。例如:// 在實際的程序中,指向常量的指針// 往往被用作函數(shù)參數(shù)int strcmp(const char *str1, const char *str2)。我們可以定義一個const指針指向一個const或一個非const對象。例如:int errNumb = 0。int *const curErr = amp。errNumb。curErr是指向一個非const對象的const指針。(我們可以從右到左把定義讀作“curErr是一個指向int類型對象的const指針”。)這意味著不能賦給curErr其他的地址值,但可以修改curErr指向的值。下面的代碼說明我們可以怎樣使用curErr:do_something()。if (*curErr) {errorHandler()。*curErr = 0。
點擊復制文檔內(nèi)容
環(huán)評公示相關(guān)推薦
文庫吧 www.dybbs8.com
備案圖鄂ICP備17016276號-1