可以說string和vector是C++標準庫中最重要的兩種型別,string支持可變長字串,而vector表示可變長的集合,
string
頭檔案:<string>
定義在命名空間 std 中,using std::string;
string s1; // 默認初始化,s1是一個空串
string s2(s1); // s2是s1的副本
string s3 = s1; // s3是s1的副本
string s4("value"); // s4是字面值"value"的副本,除了字面值最后的那個空字符外
string s5 = "value"; // 等價于上面的括號初始化
string s6(n, 'c'); // 把s6初始化為由連續n個字符c組成的串
View Code
這里需要區分直接初始化和拷貝初始化(后面學了類相關的知識就會知道,這兩種初始化呼叫分別呼叫的是建構式和拷貝控制的某種建構式),
使用等號(=)初始化一個變數,實際上執行的就是拷貝初始化(copy initialization),編譯器把等號右側的初始值拷貝到新創建的物件中去,反之,不使用等號,則執行的就是直接初始化(direct initialization),
string的操作
os << s 將s寫到輸出流os中,回傳os
is >> s 從is中讀取字串賦給s,字串以空白分隔,回傳is
getline(is, s) 從is中讀取一行賦給s,回傳is
s[n] 回傳s中第n個字符的參考,位置n從0計起
s1 + s2 回傳s1和s2連接后的結果
// 讀取未知數量的string物件
int main()
{
string word;
while (cin >> word)
cout << word << endl;
return 0;
}
View Code
string的size()函式回傳型別為string::size_type,它是一個無符號型別的值,而且能足夠存放下任何string物件的大小,
string物件與字符字面值或者字串字面值相加時,必須確保每個加法運算子(+)的兩側的運算物件至少有一個是string物件:
int main()
{
string str1("hell");
string str2 = str1 + 'o' + " world";
cout << str2 << endl;
return 0;
}
View Code
如何處理string物件中的字符呢?
頭檔案cctype中定義了一組標準庫函式
isalnum(c) 當c是字母或數字時為真
isalpha(c) 當c是字母時為真
iscntrl(c) 當c是控制字符時為真
isdigit(c) 當c是數字時為真
isgraph(c) 當c不是空格但可列印時為真
islower(c) 當c是小寫字母時為真
isprint(c) 當c是可列印字符時為真
ispunct(c) 當c是標點符號時為真
isspace(c) 當c時空白時為真(即c是空格、橫向制表符、縱向制表符、回車、換行、進紙符)
isupper(c) 當c是大寫字母時為真
isxdigit(c) 當c是十六進制數字時為真
tolower(c) 如果c是大寫字母,輸出對應的小寫字母;否則原樣輸出c
toupper(c) 如果c是小寫字母,輸出對應的大寫字母;否則原樣輸出c
string str3("abcdefgh0123");
for (auto c : str3) {
if (isxdigit(c)) {
cout << "0x" << c << endl;
} else {
cout << c << endl;
}
}
View Code
vector
也被稱為容器(container),頭檔案<vector>,using std::vector;
vector是一個類模板(class template),模板本身不是類或函式,可以將模板看作為編譯器生成類或函式撰寫的一份說明,編譯器根據模板創建類或函式的程序稱為實體化(instantiation),當使用模板時,需要指出編譯器應該把類或函式實體化成何種型別,
vector的使用
vector<int> ivec; // ivec保存int型別的物件
vector<ClassObj> co_vec; // co_vec保存ClassObj型別別的物件
vector<vector<string>> files; // files保存的元素是vector物件
定義和初始化
vector<T> v1; // v1是一個空vector,它潛在的元素是T型別的,執行默認初始化
vector<T> v2(v1); // v2中包含有v1所有元素的副本
vector<T> v2 = v1; // 等價于v2(v1)
vector<T> v3(n, val); // v3包含了n個重復的元素,每個元素的值都是val
vector<T> v4(n); // v4包含了n個重復地執行了值初始化的物件
vector<T> v5{a,b,c...}; // 串列初始化,包含了{}中的元素
vector<T> v6={a,b,c...}; // 同上
使用串列初始化時,注意:
vector<int> v1{10}; // v1只有一個元素
vector<int> v2(10); // v2有10個元素
vector<int> v3{10, 1}; // 2個元素,10、1
vector<int> v4(10, 1); // 10個元素,值都是1
用圓括號:提供的值用來構造(construct)vector物件
用花括號:串列初始化該vector物件,也就是說,初始化程序會盡可能地把花括號內的值當成是元素初始值的串列來處理,只有在無法執行串列初始化時才會考慮其他初始化方式,
vector<string> v5{10}; // v5有10個默認初始化的元素
vector<string> v6{10, "hi"}; // v6有10個值為"hi"的元素
上面兩條陳述句盡管使用了花括號,但是花括號中的值(10)與元素型別(string)不匹配,不能作為元素的初始值,編譯器會嘗試使用建構式去初始化物件,
vector<string> v7{10, "hi", "hello"}; // 錯誤
使用push_back向vector物件中添加元素
vector<int> ivec;
for (int i = 0; i != 10; ++i) {
ivec.push_back(i);
}
迭代器(iterator)
提供迭代器的型別,擁有begin和end成員函式,begin回傳指向第一個元素(或第一個字符)的迭代器;end回傳容器(或string物件)“尾元素的下一位置”的迭代器,
auto b = ivec.begin(), e = ivec.end();
如果容器為空,則begin和end回傳的是同一個迭代器,都是尾后迭代器,
擁有迭代器的標準庫型別使用iterator和const_iterator來表示迭代器的型別:
vector<int>::iterator iter1; // iter1能讀寫vector<int>的元素
string::iterator iter2;
vector<int>::const_iterator iter3; // iter3 只能讀元素,不能寫元素
vector和string迭代器支持的運算
iter + n iter - n iter += n iter -= n
iter1 - iter2 兩個迭代器相減的結果是它們之間的距離,參與元素的兩個迭代器必須指向的是同一個容器中的元素或尾元素的下一位置
>、>=、<、<=
注意:兩個迭代器不能相加!!!(沒有意義)
陣列
在C++代碼中,盡可能地使用vector,而不使用陣列,
陣列的宣告:a[d],其中a是陣列的名字,d是陣列的維度,維度說明了陣列中元素的個數,因此必須大于0,陣列中元素的個數也屬于陣列型別的一部分,編譯的時候維度必須是已知的,因此,維度必須是一個常量運算式:
unsigned cnt = 10;
constexpr unsigned sz = 10;
int arr[10]; // 正確
int *parr[sz]; // 含有10個整型指標的陣列
string err[cnt]; // 錯誤:cnt不是常量運算式
string strs[GetSize()]; // 當GetSize()是constexpr時正確,否則錯誤
陣列下標的型別為size_t,size_t是一種機器相關的無符號型別,被設計得足夠大以便能表示記憶體中任意物件的大小,在頭檔案<cstddef>中,
在很多用到陣列名字的地方,編譯器都會自動地將其替換為一個指向陣列首元素的指標:
string nums[] = {"a", "b", "c"};
string *p = &nums[0]; // 指向nums的第一個元素
string *ps = nums; // 等價
在一些情況下,陣列的操作實際上是指標的操作,所以當使用陣列作為一個auto變數的初始值時,推斷得到的型別是指標而非陣列:
int ia[] = {0,1,2,3,4,5};
auto ia2(ia); // ia2是一個整型指標,指向ia的第一個元素
當使用decltype關鍵字時上述轉換不會發生:
decltype(ia) ia3 = {0,1,2,3,4,5};
ia3[4] = 10;
標準庫函式begin和end,與容器中的兩個同名成員功能類似,作用于陣列,
C風格字串
它不是一種型別,而是為了表達和使用字串而形成的一種約定俗成的寫法,按此習慣書寫的字串存放在字符陣列中并以空字符結束,
strlen(p) 回傳p的長度,空字符不計算在內
strcmp(p1, p2) 比較p1和p2,如果p1==p2,回傳0,如果p1>p2,回傳正值,否則回傳一個負值
strcat(p1, p2) 將p2附加到p1之后,回傳p1
strcpy(p1, p2) 將p2拷貝給p1,回傳p1
string物件轉換為C風格字串:str.c_str();
本來想把《STL原始碼剖析》中的vector實作寫出來,但是內容就太多了,所以現階段就只寫C++的基礎知識,后面再單獨寫其他深入的內容,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/69151.html
標籤:C++
上一篇:結題報告
下一篇:[Error] expected primary-expression before ']' token出現這樣的錯誤為什么

