類型名 | 定義 | 類型 | 初始化 | c++11新特性 |
---|---|---|---|---|
string | 可變長度的字符型序列 | 類 |
1.string str1; //默認初始化,str1是一個空字符串; 2.string str1(str2); //str1是str2的副本; 3.string str1 = str2; //str1是副本;等價於2形式; 4.string str("hello"); //str是字面值“hello”的副本; 5.string str = "hello"; //;str是字面值“hello”的副本;等價於4; 6.string str = {'h','e','\0'}; //等價於4,5; 7.string str(n,'c'); //把str初始化爲由連續n個字符'c'組成的字符串; |
1.cctype頭文件,兼容C語言的頭文件,其中含有一些字符處理函數; 2.使用基於範圍的for語句,處理每個字符: for(declaration : expression) { statement } 含義:declaration部分負責定義一個變量,該變量將被用於訪問序列中的基礎元素。每次迭代,declaration部分的變量會被初始化爲expression部分的下一個元素值。 3.使用範圍for語句改變字符串中的字符,需要用到引用,例如: for(auto & c : s) { c = toupper(c); }
|
vector<T> |
可變長度的T型 序列 |
類模板 (既不是類也不是函數) |
1.vector<T> s1; //默認初始化,s1是一個空vector,它潛在的元素是T類型; 2.vector<T> s1(s2); //s1是s2的副本; 3.vector<T> s1 = s2; //s1是副本;等價於2形式; 4.vector<T> s1{a,b,c,... }; //s1包含了初始值個數的元素,每個元素被賦予相應的初始值; 5.vector<T> s1 = {a,b,c,...}; //;等價於4; 6.vector<T> s1(n,val); //vec包含了n個重複的元素,每個值都是value; 7.vector<T> s1(n); //vec包含了n個重複的元素,每個值都是初始化值; *注意 ()、{}的使用不同: ()中的n代表個數;{}中的n代表內容。比如:vector<string> v5{"hello"};(√) vector<string> v6("hello");(×)不能用字符串字面值構建 vector 對象。 8.使用數組初始化 vector 對象 int int_arr[] = {0,1,2,3,4,5}; vector<int> ivec(begin(int_arr),end(int_arr)); |
1.頭文件vector,可運用vector的成員函數push_back向其中添加元素。push_back負責把一個值當成vector對象的尾元素“壓入push”到vector對象的“尾端(back)”。 v.empty(),如果v不含有任何元素,返回真;否則返回假。 v.size(),返回v中的元素個數。 支持 =、==、!=、<、<=、>、>= 操作 注意:只能對下標已經存在的元素執行索引。通過下表訪問不存在的元素的行爲會導致緩衝區溢出(buffer overflow)錯誤。 2.使用基於範圍的for語句,處理每個字符: for(declaration : expression) { statement } 含義:declaration部分負責定義一個變量,該變量將被用於訪問序列中的基礎元素。每次迭代,declaration部分的變量會被初始化爲expression部分的下一個元素值。 3.使用範圍for語句改變字符串中的字符,需要用到引用,例如: for(auto & c : s) { c = toupper(c); } |
一、舉例
1.使用基於範圍的for語句:
#include <iostream>
#include <string>
#include <cstring>
#include <vector>
using namespace std;
int main()
{
vector<int> a(10,2);
for(auto & temp : a)
{
temp *= 2;
}
for(auto temp : a)
{
cout<<temp<<"\t";
}
cout<<endl<<"------------------------------------------------------"<<endl;
vector<string> str{10,"hi"};
for(auto arr : str)
{
cout<<arr<<endl;
}
return 0;
}
2.從cin讀入一組詞並把它們存入一個vector對象,然後設法把所有詞都改寫爲大寫形式。輸出改變後的結果,每個詞佔一行。
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
vector<string> str;
string temp;
while(cin>>temp)
{
for(auto & c : temp)
{
c -= 32;
}
str.push_back(temp);
}
for(int i = 0;i < str.size();i++)
{
cout<<str[i]<<endl;
}
return 0;
}
注意:試想在while循環中,先執行str.push_back(temp),再執行基於範圍的for語句可以嗎?
答:不可以,因爲push,相當於是一個壓入棧的操作,會將內容壓入到向量中,那麼此時temp就爲空了,然後逐個去操作空內容,也就沒有了什麼意義。
3.讀入一組整數並把它們存入一個vector對象,將每對相鄰整數的和輸出出來。改寫你的程序,這次要求先輸出第一個和最後一個元素的和,接着輸出第二個和倒數第二個元素的和,以此類推。
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> a;
int temp;
while(cin>>temp)
{
a.push_back(temp);
}
for(int i = 0;i < a.size()/2;i++)
{
cout<<a[i] + a[a.size() - i - 1]<<endl;
}
if(a.size() % 2 == 1)
{
cout << a[a.size()/2]<<endl;
}
return 0;
}
二、迭代器(又稱遊標)
類 | 對象 | iter |
容器 | 迭代器對象(的地址) | *iter |
類似於指針類型,迭代器也提供了對對象的間接訪問。對string對象的字符和vector對象的元素的訪問機制:
- 下標運算符
- 迭代器(除vector之外,在標準庫中定義的幾種容器也可以使用迭代器,但是其中只有少數幾種也可以使用支持下標運算)
注意:string對象不屬於容器類型,但是string支持很多與容器類型類似的操作。vector支持下標運算符,這點和string一樣;string支持迭代器,這也和vector一樣。
1. 使用迭代器
和指針不一樣的是,獲取迭代器不是使用取地址符,有迭代器的類型同時擁有返回迭代器的成員。比如,這些類型都擁有名爲begin和end的成員,其中begin成員負責返回指向第一個元素(或第一個字符)的迭代器。end成員則負責返回指向容器(或string對象)“尾元素的下一個位置”的迭代器,也就是說,該迭代器只是的是容器的一個本不存在的“尾後(off the end)”元素。這樣的迭代器沒什麼實際含義,僅是個標記,表示我們已經處理完了容器中的所有元素。end成員返回的迭代器常被稱爲尾後迭代器或者稱爲尾迭代器。
auto b = v.begin(),e = v.end(); //b和e的類型相同
如果容器爲空,則begin和end返回的是同一個迭代器,都是尾後迭代器。
迭代器運算符
*iter //對iter進行解引用,返回迭代器iter指向的元素的引用 iter->men //對iter進行解引用,獲取指定元素中名爲men的成員。等效於(*iter).men ++iter //給iter加1,使其指向容器的下一個元素 iter++ --iter //給iter減1,使其指向容器的前一個元素 iter-- iter1==iter2 //比較兩個迭代器是否相等,當它們指向同一個容器的同一個元素或者都指向同同一個容器的超出末端的下一個位置時,它們相等 iter1!=iter2
舉例:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
vector<string> str;
string temp = "hello";
str.push_back(temp);
vector<string>::iterator str1;
str1 = str.begin();
cout<<(*str1)<<endl;
cout<<(*str1)[0]<<endl; //你猜猜輸出啥:h
return 0;
}
迭代器就是地址,如果想獲取其內容,需要對其解引用。
迭代器運算
幾點注意事項:
- 已知一個限制的 vector 對象,是不能在範圍 for 循環中向 vector 對象添加元素。
- 任何一種可能改變 vector 對象容量的操作,比如 push_back,都會使該vector對象的迭代器失效。
- 謹記,但凡是使用了迭代器的循環體,都不要向迭代器所屬的容器添加元素。
- 不允許使用一個數組爲另一個內置類型的數組賦初值。
- 不允許使用 vector 對象初始化數組,但是可以使用數組初始化vector對象。
eg1:
int int_arr[] = {0,1,2,3,4,5};
// ivec 有6個元素,分別是int_arr中對應元素的副本
vector<int> ivec(begin(int_arr),end(int_arr));
eg2:
vector<int> subVec(int_arr + 1,int_arr + 4);
//subVec是一個有3個元素的對象,分別是int_arr[1]、int_arr[2]、int_arr[3]
三、刪除元素
c.pop_back() | 刪除c中尾元素。若c爲空,則函數行爲未定義。函數返回void。 |
c.pop_front() |
刪除c中首元素。若c爲空,則函數行爲未定義。函數返回void。 |
c.erase(p) |
刪除迭代器p所指定的元素,返回一個紙箱被刪元素之後元素的迭代器,若p指向尾元素,則返回尾後(off-the-end)迭代器。若p是尾後迭代器,則函數行爲未定義。 |
c.erase(b,e) |
刪除迭代器b和e所指定範圍內的元素。返回一個指向最後一個被刪元素之後元素的迭代器,若e本身就是尾後迭代器,則函數也返回尾後迭代器。 |
c.clear() | 刪除c中的所有元素。返回void。 |
注意:
- pop_front和pop_back成員函數分別刪除首元素和尾元素的時候,不會返回該值,如果想保存該值,需要在彈出操作之前進行保存操作。
- 刪除多個元素方法有兩種:
1)使用erase(elem1,elem2)刪除一個範圍內的元素:
// 刪除兩個迭代器表示的範圍內的元素:[ , )
// 返回指向最後一個被刪元素之後位置的迭代器
elem1 = slist.erase(elem1,elem2);
#include <iostream>
#include <deque>
#include <algorithm>
using namespace std;
int main()
{
deque<int> que;
int temp;
while(cin>>temp)
{
que.push_back(temp);
}
sort(que.begin(),que.end());
for(int i = 0;i < que.size();i++)
{
cout<<que[i]<<"\t";
}
cout<<endl;
que.erase(que.begin());
for(int i = 0;i < que.size();i++)
{
cout<<que[i]<<"\t";
}
cout<<endl;
return 0;
}