【修煉C++】基礎知識點筆記-第3章 字串,向量和陣列
重新學習c++的東西,此為《C++ Primer》讀書筆記,主要記錄零碎的知識。另外所有的C++11新標準也會被列出。
1,位於標頭檔案的程式碼一般來說不應該使用using宣告。這是因為標頭檔案的內容會拷貝到所有引用它的檔案中。
2,拷貝 初始化,直接初始化。【???】
3,string物件上的操作
os<<s 將s寫到輸出流os當中,返回os
is>>s 從is中讀取字串賦給s,字串以空白分隔,返回is
getline(is,s) 從is中讀取一行賦值給是,返回is
注意
(1)這三個操作的返回值,這使得多個輸入和多個輸出可以連起來寫
string s1,s2;
cin>>s1>>s2; //將第一個輸入讀到s1中,第二個輸入讀到s2中。
cout<<s1<<s2;
(2)在執行讀取操作(<<)時,string物件會自動忽略開頭的空白(即空格符,換行符,製表符等)並從第一個真正的字元開始讀起,直到遇到下一個空白為止。
(3)getline(is,s) 沒有上邊的問題,可以完整讀取一行,知道遇到換行符號。
(4)上述操作返回的是流引數,所以可以作為判斷條件讀取未知長度或者是未知行數的字串。知道其返回非法輸入或者是檔案結束。
4 string::size_type型別
s.empty() 判斷一個字串是否為空
s.size() 返回s中字元的個數
(1)size()函式返回值為string::size_type型別的值,它是一個無符號型別的值而且能足夠放下任何string物件的大小。為了不產生潛在的問題,那麼如果一條表示式中已經有了size()函式就不要再使用int了。
5、C++11新標準範圍for(range for)語句範圍for語句:遍歷給定序列中的每個元素並對序列中的每個值執行某種操作,其語法形式為:
for(declaration:expression)
statement
expression 表示的必須是一個序列,比如花括號括起來的初始值列表、陣列、或者vector或string等型別的物件,這些型別 的共同特點是擁有能返回迭代器的begin和end
每次迭代,declaration 部分的變數會被初始化為expression部分的下一個元素值,但是看第二個例子對引用型別進行初始化(這樣可以修改序列中的值),則應該是什麼型別呢?另一個變數。
注意:範圍for語句不可以用於增加vector物件的元素,因為在範圍for語句中,預存了end()的值,一旦序列中新增或者刪除了元素,end函式可能變得無效。
string s("Hello World!!!");
decltype(s.size()) punct_cnt = 0;
for(auto c : s)
if(ispunct(s))
++punct_cnt;
cout<<punct_cnt
<<"punctuation characters in "<<s<<endl;
//為了改變string物件中字元的值,把迴圈變數定義成引用型別。
for(auto&c : s)
c =toupper(c);
cout<<s<<endl;
6、vector能容納絕大多數型別的物件作為其元素,但是因為引用不是物件,所以不存在包含引用的vector。除此之外,其他大多數內建型別和類型別都可以構成vector物件,甚至組成vector的元素也可以是vector。
/*初始化vector物件的方法*/
vector<T> v1 /*v1是一個空vector,它潛在的元素是T型別的,執行預設的初始化*/
vector<T> v2(v1) /*v2中包含有v1所有元素的副本*/
vector<T> v2=v1 /*等價於v2(v1),v2中包含v1所有元素的副本*/
vector<T> v3(n,val) /*v3包含n個重複的元素,每個元素的值都是val*/
vector<T> v4(n) /*v4包含那個重複執行了值初始化的物件*/
vector<T> v5{a,b,c...} /*v5包含了初始值個數的元素,每個元素被賦予相應的初始值*/
vector<T> v5={a,b,c...} /*等價於v5{a,b,c...}*/
7、在某些情況下,初始化的真實含義依賴於傳遞初始值時用的是花括號還是圓括號。如果用的是花括號,初始化過程中儘可能地把花括號內的值當成是元素初始值的列表來處理,只有無法執行列表初始化時才會考慮其他初始化方式。
vector<string> v5{"hi"} /*列表初始化:v5有一個元素*/
vector<string> v6("hi") /*錯誤:不能用字串字面值構建vector物件*/
vector<string> v7{10} /*v7 有10個預設初始化的元素*/
vector<string> v8{10,"hi"} /*v8有10個值為“hi”的元素*/
8,只允許對已存在的元素執行下標操作,對vector如此,對string也是如此,注意不可以用下標操作對元素進行賦值。
9,有效的迭代器或者指向某個元素,或者指向容器中尾元素的下一個位置end迭代器或者叫尾迭代器(off-the-end iterator)。
10,迭代器型別,iterator 和 const_iterator。
const_iterator 和常量指標差不多,能讀取但不能修改它所指的元素值。若vector或者string物件是一個常量,則只能用const_iterator;
對於begin和end,其返回的具體型別由物件是否是常量決定。如果物件是常量,則返回const_iterator;若物件不是常量,返回iterator。
C++11新標準,引進cbegin和cend兩個新函式,針對物件只需要讀操作而無須寫操作的行為。
11,C++語言定義了箭頭運算子(->),箭頭運算子把解引用和成員訪問兩個操作結合在一起,也就是說it->mem和(*it).mem()表達的意思相同
12,二分搜尋程式中,使用mid=beg+(end-beg)/2
//使用迭代器完成二分搜尋
//text 必須是有序的
//beg和end表示我們搜尋的範圍
auto beg = text.begin(),end = text.end();
auto mid = beg +(end-beg)/2;//初始狀態下的中間點
//當還有元素尚未檢查並且我們還沒有找到sought時執行迴圈
while(mid!=end && *mid!=sought)
{
if(sought<*mid)
end=mid;
else
begin = mid+1;
mid = beg+(end-beg)/2; //新的中間點
}
13,陣列中元素的個數也屬於陣列型別的一部分,編譯時維度應該是已知的。因此,維度必須是一個常量表達式。陣列與vector不同的一點是陣列在定義時大小確定不變,vector在執行時可以動態調整, 也有維度限制。
14,
int *ptrs[10]; //ptrs是含有10個整型指標的陣列
int (*Patrray)[10] = &arr; //Parray指向一個含有10個整數的陣列
int (&arrRef)[10] = arr; //arrRef引用一個含有10個整數的陣列
int *(&arry)[10] = ptrs; //arry是陣列的引用,該陣列有10個指標