C++primer 第 3 章 字符串、向量和数组 3.1 命名空间的using声明 3.2标准库类型string
生活随笔
收集整理的這篇文章主要介紹了
C++primer 第 3 章 字符串、向量和数组 3.1 命名空间的using声明 3.2标准库类型string
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
引言
- 除了第2章介紹的內(nèi)置類型之外,C++語(yǔ)言還定義了 -個(gè)內(nèi)容豐富的抽象數(shù)據(jù)類型庫(kù)。其中,string和 vector是兩種最重耍的標(biāo)準(zhǔn)庫(kù)類型,前者支持可變長(zhǎng)字符串,后者則 表示可變長(zhǎng)的集合。還有…種標(biāo)準(zhǔn)庫(kù)類型是迭代器,它是string和vector的配套類型,常被用于訪問(wèn)string中的字符或vector中的元素。
- 內(nèi)置數(shù)組是一種更基礎(chǔ)的類型,string和vector都是對(duì)它的某種抽象。本章將分別介紹數(shù)組以及標(biāo)準(zhǔn)摩類型string和 vector.
- 第2 章介紹的內(nèi)置類型是由C++語(yǔ)言直接定義的。這些類型,比如數(shù)字和字符,體現(xiàn)了大多數(shù)計(jì)算機(jī)硬件本身具備的能力。標(biāo)準(zhǔn)庫(kù)定義了另外一組具有更高級(jí)性質(zhì)的類型,它們尚未直接實(shí)現(xiàn)到計(jì)算機(jī)硬件中。
- 本章將介紹兩種最重要的標(biāo)準(zhǔn)庫(kù)類型:string和 vector。string表示可變長(zhǎng)的 字符序列,vector存放的是某種給定類型對(duì)象的可變長(zhǎng)序列。本章還將介紹內(nèi)置數(shù)組類型,和其他內(nèi)置類型一樣,數(shù)組的實(shí)現(xiàn)與硬件密切相關(guān)。因此相較于標(biāo)準(zhǔn)庫(kù)類型string和vector,數(shù)組在靈活性上稍顯不足。 在開始介紹標(biāo)準(zhǔn)庫(kù)類型之前,先來(lái)學(xué)習(xí)一種訪問(wèn)庫(kù)中名字的簡(jiǎn)單方法
3.1命名空間的using聲明
- 目前為止,我們用到的庫(kù)函數(shù)基本上都屬于命名空間std,而程序也顯式地將這一點(diǎn)標(biāo)示了出來(lái)。例如,std::cin表示從標(biāo)準(zhǔn)輸入中讀取內(nèi)容。此處使用作用域操作符(::)(參見1.2節(jié),第7頁(yè))的含義是:編譯器應(yīng)從操作符左側(cè)名字所示的作用域中尋找右側(cè)那個(gè)名字。因此,std::cin的意思就是要使用命名空間std中的名字cin。上面的方法顯得比較煩瑣,然而幸運(yùn)的是,通過(guò)更簡(jiǎn)單的途徑也能使用到命名空間中的成員。本節(jié)將學(xué)習(xí)其中一種最安全的方法,也就是使用using聲明(usingdeclaration).18.2.2節(jié)(第702頁(yè))會(huì)介紹另一種方法。
- 有了using聲明就無(wú)須專門的前綴(形如命名空間::)也能使用所需的名字了。using聲明具有如下的形式:
- using namespace::name;? ?一旦聲明了上述語(yǔ)句,就可以直接訪問(wèn)命名空間中的名字
每個(gè)名字都需要獨(dú)立的using聲明
- 按照規(guī)定,每個(gè)using聲明引入命名空間中的一個(gè)成員。例如,可以把要用到的標(biāo)準(zhǔn)庫(kù)中的名字都以u(píng)sing聲明的形式表示出來(lái),重寫1.2節(jié) (第 5 頁(yè))的程序如下:
- 在上述程序中,一開始就有對(duì)cin、cout和 endl的 using聲明,這意味著我們不用再 添加std::形式的前綴就能直接使用它們。C++語(yǔ)言的形式比較自由,因此既可以一行只放一條using聲明語(yǔ)句,也可以一行放上多條。不過(guò)要注意,用到的每個(gè)名字都必須有自己的聲明語(yǔ)句,而且每句話都得以分號(hào)結(jié)束。
頭文件不應(yīng)包含using聲明
- 位于頭文件的代碼(參見2.6.3節(jié),第67頁(yè))一般來(lái)說(shuō)不應(yīng)該使用using聲明。這是因?yàn)轭^文件的內(nèi)容會(huì)拷貝到所有引用它的文件中去,如果頭文件里有某個(gè)using聲明,那么每個(gè)使用了該頭文件的文件就都會(huì)有這個(gè)聲明。對(duì)于某些程序來(lái)說(shuō),由于不經(jīng)意間包含了一些名字,反而可能產(chǎn)生始料未及的名字沖突。
一點(diǎn)注意事項(xiàng)
- 經(jīng)本節(jié)所述,后面的所有例子將假設(shè),但凡用到的標(biāo)準(zhǔn)庫(kù)中的名字都已經(jīng)使用using語(yǔ)句聲明過(guò)了。例如,我們將在代碼中直接使用cin,而不再使用std::cin?為了讓書中的代碼盡量簡(jiǎn)潔,今后將不會(huì)再把所有using聲明和#include指令一一標(biāo)出。附錄A中的表A.1(第766頁(yè))列出了本書涉及的所有標(biāo)準(zhǔn)庫(kù)中的名字及對(duì)應(yīng)的頭文件。
3.2標(biāo)準(zhǔn)庫(kù)類型string
- 標(biāo)準(zhǔn)庫(kù)類型string表示可變長(zhǎng)的字符序列,使用string類型必須首先包含<~84~]string頭文件。作為標(biāo)準(zhǔn)庫(kù)的一部分,string定義在命名空間std中。接下來(lái)的示例都假定已包含了下述代碼:
- #include <string>? ? using std::string;
- 本節(jié)描述最常用的string操作,9.5節(jié) (第320頁(yè))還將介紹另外一些。?
3 .2 .1 定義和初始化string對(duì)象
- 如何初始化類的對(duì)象是由類本身決定的。一個(gè)類可以定義很多種初始化對(duì)象的方式,只不過(guò)這些方式之間必須有所區(qū)別:或者是初始值的數(shù)量不同,或者是初始值的類型不同。
表 3.1列出了初始化string對(duì)象最常用的一些方式,下面是幾個(gè)例子:
- 可以通過(guò)默認(rèn)的方式(參見2.2.1節(jié),第 40頁(yè))初始化一個(gè)string對(duì)象,這樣就會(huì)得到 —個(gè)空的string,也就是說(shuō),該string對(duì)象中沒有任何字符。如果提供了一個(gè)字符串字面值(參見2.1.3節(jié),第 36頁(yè)),則該字面值中除了最后那個(gè)空字符外其他所有的字符都被拷貝到新創(chuàng)建的string對(duì)象中去。如果提供的是一個(gè)數(shù)字和一個(gè)字符,則string對(duì)象的內(nèi)容是給定字符連續(xù)重復(fù)若干次后得到的序列
直接初始化和拷貝初始化
- 由2.2.1節(jié)(第39頁(yè))的學(xué)習(xí)可知,C++語(yǔ)言有幾種不同的初始化方式,通過(guò)string我們可以清楚地看到在這些初始化方式之間到底有什么區(qū)別和聯(lián)系。如果使用等號(hào)(=)初始化-個(gè)變量,實(shí)際上執(zhí)行的是拷貝初始化(copyinitialization),編譯器把等號(hào)右側(cè)的初始值拷貝到新創(chuàng)建的對(duì)象中去。與之相反,如果不使用等號(hào),則執(zhí)行的是直接初始化(directinitialization)。
- 等號(hào)使用拷貝初始化;無(wú)等號(hào)使用直接初始化
- 當(dāng)初始值只有一個(gè)時(shí),使用直接初始化或拷貝初始化都行。如果像上面的S4那樣初始化要用到的值有多個(gè),一般來(lái)說(shuō)只能使用直接初始化的方式:
3.2.2string對(duì)象上的操作
- 一個(gè)類除了要規(guī)定初始化其對(duì)象的方式外,還要定義對(duì)象上所能執(zhí)行的操作。其中,類既能定義通過(guò)函數(shù)名調(diào)用的操作,就像Sales_item類的isbn函數(shù)那樣(參見1.5.2節(jié),第20頁(yè)),也能定義<<、+等各種運(yùn)算符在該類知象上的新含義。表3.2中列舉了string的大多數(shù)操作。
讀寫string對(duì)象
- 第 1章曾經(jīng)介紹過(guò),使用標(biāo)準(zhǔn)庫(kù)中的iostream來(lái)讀寫int, double等內(nèi)置類型的 值。同樣,也可以使用IO操作符讀寫string對(duì)象:
- cin<<s;//將string對(duì)象讀入s,遇到空白停止
- cout<<s<<endl;//輸出s
使用getline讀取一整行
- 有時(shí)我們希望能在最終得到的字符串中保留輸入時(shí)的空白符,這時(shí)應(yīng)該用getline函數(shù)代替原來(lái)的>>運(yùn)算符。getline函數(shù)的參數(shù)是一個(gè)輸入流和一個(gè)string對(duì)象,函數(shù)從給定的輸入流中讀入內(nèi)容,直到遇到換行符為止(注意換行符也被讀進(jìn)來(lái)了),然后把所讀的內(nèi)容存入到那個(gè)string對(duì)象中去(注意不存換行符)。getline只要一遇到換行符就結(jié)束讀取操作并返回結(jié)果,哪怕輸入的一開始就是換行符也是如此。如果輸入真的一開始就是換行符,那么所得的結(jié)果是個(gè)空string。和輸入運(yùn)算符一樣,getline也會(huì)返回它的流參數(shù)。因此既然輸入運(yùn)算符能作為判斷的條件(參見1.4.3節(jié),第13頁(yè)),我們也能用getline的結(jié)果作為條件。例如,可以通過(guò)改寫之前的程序讓它一次輸出一整行,而不再是每行輸出一個(gè)詞了:
- 因?yàn)閘ine中不包含換行符,所以我們手動(dòng)地加上換行操作符。和往常一樣,使用endl 結(jié)束當(dāng)前行并刷新顯示緩沖區(qū)。
- 觸發(fā)getline函數(shù)返回的那個(gè)換行符實(shí)際上被丟棄掉了,得到的string對(duì)象中并不包含該換行符
string 的 empty 和 size 操作
- 顧名思義,empty函數(shù)根據(jù)string對(duì)象是否為空返回一個(gè)對(duì)應(yīng)的布爾值(參見第2.1節(jié),30頁(yè))。和Sales_item類(參見1.5.2節(jié),第20頁(yè))的isbn成員一樣,empty也是string的一個(gè)成員函數(shù)。調(diào)用該函數(shù)的方法很簡(jiǎn)單,只要使用點(diǎn)操作符指明是哪個(gè)對(duì)象執(zhí)行了empty函數(shù)就可以了。
- 在上面的程序中,if語(yǔ)句的條件部分使用了邏輯非運(yùn)算符(!),它返回與其運(yùn)算對(duì)象相反的結(jié)果。此例中,如果str不為空則返回真。size函數(shù)返回string對(duì)象的長(zhǎng)度(即string對(duì)象中字符的個(gè)數(shù)),可以使用size函數(shù)只輸出長(zhǎng)度超過(guò)80個(gè)字符的行:
string::size_type類型
- 對(duì)于size函數(shù)來(lái)說(shuō),返回一個(gè)int或者如前面2.1.1節(jié)(第31頁(yè))所述的那樣返回-個(gè)unsigned似乎都是合情合理的。但其實(shí)size函數(shù)返回的是一個(gè)string::size_type類型的值,下面就對(duì)這種新的類型稍作解釋。string類及其他大多數(shù)標(biāo)準(zhǔn)庫(kù)類型都定義了幾種配套的類型。這些配套類型體現(xiàn)了標(biāo)準(zhǔn)庫(kù)類型與機(jī)器無(wú)關(guān)的特性,類型size_type即是其中的一種。在具體使用的時(shí)候,通過(guò)作用域操作符來(lái)表明名字size_type是在類string中定義的。盡管我們不太清楚string::size_type類型的細(xì)節(jié),但有一點(diǎn)是肯定的:它是一個(gè)無(wú)符號(hào)類型的值(參見2.1.1節(jié),第30員)而且能足夠存放下任何string對(duì)象的大小。
- 所有用于存放string類的size函數(shù)返回值的變量,都應(yīng)該是string::size_type類型的。
- 過(guò)去,string::size_type這種類型有點(diǎn)兒神秘,不太容易理解和使用。在C++11新標(biāo)準(zhǔn)中,允許編譯器通過(guò)auto或者decltype(參見2.5.2節(jié),第61頁(yè))來(lái)推斷變量的類型:
- auto len=line.size();//len的類型是string::size_type
- 由于size函數(shù)返回的是一個(gè)無(wú)符號(hào)整型數(shù),因此切記,如果在表達(dá)式中混用了帶符號(hào)數(shù)和無(wú)符號(hào)數(shù)將可能產(chǎn)生意想不到的結(jié)果(參見2.1.2節(jié),第33頁(yè))。例如,假設(shè)n是一個(gè)具有負(fù)值的int,則表達(dá)式s.size()<n的判斷結(jié)果幾乎肯定是true。這是因?yàn)樨?fù)值n會(huì)自動(dòng)地轉(zhuǎn)換成一個(gè)比較大的無(wú)符號(hào)值。
- 如果一條表達(dá)式中已經(jīng)有了size()函數(shù)就不要再使用int了,這樣可以避免丁中混用int和unsigned可能帶來(lái)的問(wèn)題
比較string對(duì)象
- string類定義了幾種用于比較字符串的運(yùn)算符。這些比較運(yùn)算符逐一比較string對(duì)象中的字符,并且對(duì)大小寫敏感,也就是說(shuō),在比較時(shí)同一個(gè)字母的大寫形式和小寫形式是不同的。
- 相等性運(yùn)算符(==和!=)分別檢驗(yàn)兩個(gè)string對(duì)象相等或不相等,string對(duì)象相等意味著它們的長(zhǎng)度相同而且所包含的字符也全都相同。關(guān)系運(yùn)算符<、<=、>、>=分別檢驗(yàn)一個(gè)string對(duì)象是否小于、小于等于、大于、大于等于另外一個(gè)string對(duì)象。上述這些運(yùn)算符都依照(大小寫敏感的)字典順序:
- 1.如果兩個(gè)string對(duì)象的長(zhǎng)度不同,而且較短string對(duì)象的每個(gè)字符都與較長(zhǎng)string對(duì)象對(duì)應(yīng)位置上的字符相同,就說(shuō)較短string對(duì)象小于較長(zhǎng)string對(duì)象。
- 2,如果兩個(gè)string對(duì)象在某些對(duì)應(yīng)的位置上不一致,則string對(duì)象比較的結(jié)果其實(shí)是string對(duì)象中第一對(duì)相異字符比較的結(jié)果
兩個(gè)string對(duì)象相加
- 兩個(gè)string對(duì)象相加得到一個(gè)新的string對(duì)象,其內(nèi)容是把左側(cè)的運(yùn)算對(duì)象與右側(cè)的運(yùn)算對(duì)象串接而成。也就是說(shuō),對(duì)string對(duì)象使用加法運(yùn)算符(+)的結(jié)果是一個(gè)新的string對(duì)象,它所包含的字符由兩部分組成:前半部分是加號(hào)左側(cè)string對(duì)象所含的字符、后半部分是加號(hào)右側(cè)string對(duì)象所含的字符。另外,復(fù)合賦值運(yùn)算符(+=)(參見1.4.1節(jié),第10頁(yè))負(fù)責(zé)把右側(cè)string對(duì)象的內(nèi)容追加到左側(cè)string對(duì)象的后面:
字面值和string對(duì)象相加
- 如2.1.2節(jié)(第33頁(yè))所講的,即使一種類型并非所需,我們也可以使用它,不過(guò)前提是該種類型可以自動(dòng)轉(zhuǎn)換成所需的類型。因?yàn)闃?biāo)準(zhǔn)庫(kù)允許把字符字面值和字符串字面值(參見2.1.3節(jié),第36頁(yè))轉(zhuǎn)換成string對(duì)象,所以在需要string對(duì)象的地方就可以使用這兩種字面值來(lái)替代。利用這一點(diǎn)將之前的程序改寫為如下形式:
- string si = nhelloM , s2 = "world"; // 在 si 和 s2 中都沒有標(biāo)點(diǎn)符號(hào)
- string s3 = si + ", " + s2 + f \nf ;
- 當(dāng)把string對(duì)象和字符字面值及字符串字面值混在一條語(yǔ)句中使用時(shí),必須確保每個(gè)加 法運(yùn)算符( + ) 的兩側(cè)的運(yùn)算對(duì)象至少有一個(gè)是string:
- 用雙引號(hào)包含起來(lái)的叫做字符串字面值 / 字面值,等號(hào)兩邊至少一個(gè)需要 是string?
- s4和 s5初始化時(shí)只用到了一個(gè)加法運(yùn)算符,因此很容易判斷是否合法。s6的初始化形式之前沒有出現(xiàn)過(guò),但其實(shí)它的工作機(jī)理和連續(xù)輸入連續(xù)輸出(參見1.2節(jié),第 6 頁(yè))是一樣的,可以用如下的形式分組:
- string s6 = (si + ", ") + "world";
- 其中子表達(dá)式sl + "/的結(jié)果是一個(gè)string對(duì)象,它同時(shí)作為第二個(gè)加法運(yùn)算符的左側(cè)運(yùn)算對(duì)象,因此上述語(yǔ)句和下面的兩個(gè)語(yǔ)句是等價(jià)的:
- 很容易看到,括號(hào)內(nèi)的子表達(dá)式試圖把兩個(gè)字符串字面值加在一起,而編譯器根本沒法做到這一點(diǎn),所以這條語(yǔ)句是錯(cuò)誤的。
- 因?yàn)槟承v史原因,也為了與C兼容,所以C++語(yǔ)言中的字符串字面值并不是標(biāo)準(zhǔn)庫(kù)類型string的對(duì)象切記,字符串字面值與string是不同的類型.
3.2.3處理string對(duì)象中的字符
- 我們經(jīng)常需要單獨(dú)處理string對(duì)象中的字符,比如檢查一個(gè)string對(duì)象是否包含空白,或者把string對(duì)象中的字母改成小寫,再或者查看某個(gè)特定的字符是否出現(xiàn)等。這類處理的一個(gè)關(guān)鍵問(wèn)題是如何獲取字符本身。有時(shí)需要處理string對(duì)象中的每一個(gè)字符,另外一些時(shí)候則只需處理某個(gè)特定的字符,還有些時(shí)候遇到某個(gè)條件處理就要停下來(lái)。以往的經(jīng)驗(yàn)告訴我們,處理這些情況常常要涉及語(yǔ)言和庫(kù)的很多方面。
- 另一個(gè)關(guān)鍵問(wèn)題是要知道能改變某個(gè)字符的特性。在 cctype頭文件中定義了一組標(biāo)準(zhǔn)庫(kù)函數(shù)處理這部分工作,表 3.3列出了主要的函數(shù)名及其含義。
建議:使用C++版本的C標(biāo)準(zhǔn)庫(kù)頭文件
- C++標(biāo)準(zhǔn)庫(kù)中除了定義C++語(yǔ)言特有的功能外,也兼容了C語(yǔ)言的標(biāo)準(zhǔn)庫(kù)。C語(yǔ)言的頭文件形如name.h,C++則將這些文件命名為cname。也就是去掉了.h后綴,而在文件名mme之前添加了字母c,這里的c表示這是一個(gè)屬于C語(yǔ)言標(biāo)準(zhǔn)庫(kù)的頭文件。因此,cctype頭文件和ctype.h頭文件的內(nèi)容是一樣的,只不過(guò)從命名規(guī)范上來(lái)講更符合C++語(yǔ)言的要求。特別的,在名為cname頭文件中定義的名字從屬于命名空間std,而定義在名為.h的頭文件中的則不然。一般來(lái)說(shuō),C++程序應(yīng)該使用名cname的頭文件而不使用name.h的形式,標(biāo)準(zhǔn)庫(kù)中的名字總能在命名空間std中找到。如果使用.h形式的頭文件,程序員就不得不時(shí)刻牢記哪些是從C語(yǔ)言那兒繼承過(guò)來(lái)的,哪些又是C++語(yǔ)言所獨(dú)有的。
使用范圍for語(yǔ)句改變字符串中的字符
- 如果想要改變string對(duì)象中字符的值,必須把循環(huán)變量定義成引用類型(參見2.3.1節(jié),第45頁(yè))。記住,所謂引用只是給定對(duì)象的一個(gè)別名,因此當(dāng)使用引用作為循環(huán)控制變量時(shí),這個(gè)變量實(shí)際上被依次綁定到了序列的每個(gè)元素上。使用這個(gè)引用,我們就能改變它綁定的字符。
- 新的例子不再是統(tǒng)計(jì)標(biāo)點(diǎn)符號(hào)的個(gè)數(shù)了,假設(shè)我們想要把字符串改寫為大寫字母的形式。為了做到這一點(diǎn)可以使用標(biāo)準(zhǔn)庫(kù)函數(shù)toupper,該函數(shù)接收一個(gè)字符,然后輸出其對(duì)應(yīng)的大寫形式。這樣,為了把整個(gè)string對(duì)象轉(zhuǎn)換成大寫,只要對(duì)其中的每個(gè)字符調(diào)用toupper函數(shù)并將結(jié)果再賦給原字符就可以了:
- 每次迭代時(shí),變量c 引用string對(duì)象s 的下一個(gè)字符,賦值給c 也就是在改變s 中對(duì)應(yīng)字符的值。因此當(dāng)執(zhí)行下面的語(yǔ)句時(shí),
- c = toupper (c) ; // c 是一個(gè)引用,因此賦值語(yǔ)句將改變s 中字符的值
- 實(shí)際上改變了 c 綁定的字符的值。整個(gè)循環(huán)結(jié)束后,str中的所有字符都變成了大寫形式。
總結(jié)
以上是生活随笔為你收集整理的C++primer 第 3 章 字符串、向量和数组 3.1 命名空间的using声明 3.2标准库类型string的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 详解xml
- 下一篇: sqlite3的backup和resto