一、STL 概述
STL——C++標(biāo)準(zhǔn)模板庫牡辽,定義了常用的數(shù)據(jù)結(jié)構(gòu)和算法粒氧。提供三種類型的組件:容器越除、迭代器和算法。
- 容器分為順序和關(guān)聯(lián)兩種:
- 順序容器:vector 外盯、list摘盆、deque、string等是一系列元素的有序集合
- 關(guān)聯(lián)容器:set饱苟、multiset孩擂、map、multimap包含查找元素的鍵值箱熬。
迭代器用于遍歷容器类垦。
算法庫包含四類:排序、不可變序坦弟、變序和數(shù)值算法护锤。
遍歷vector向量并統(tǒng)計其中元素之和的程序示例:
#include <vector>
#include <iostream>
#include <algorithm>
#include <numeric> //accumulate算法需要
using namespace std;
int main()
{
vector<int> v;
int i;
for (i = 0; i < 10; i ++)
v.push_back(i);
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
cout << *it <<" ";
cout<<endl;
cout<<accumulate(v.begin(),v.end(),0) <<endl;
return 0;
}
二雕旨、vector向量容器
vector可以像數(shù)組一樣隨機訪問元素厌处,而且有內(nèi)存自動管理功能线召,對元素的插入刪除可動態(tài)調(diào)整所占內(nèi)存。有三種創(chuàng)建方式:
- 不指定元素個數(shù):
vector<int> v;
- 創(chuàng)建時指定容器大小赤炒,下標(biāo)0~9,每個元素的值初始為0.0
vector<double> v(10);
- 創(chuàng)建有n個元素的vector亏较,每個元素有指定的初始值
vector<double> v(10, 8.6);
基本函數(shù)
begin():返回首元素位置的迭代器
end():返回最后一個元素的下一個位置的迭代器
size():返回向量的大小莺褒,即元素個數(shù)
empty():返回向量是否為空
push_back(): 在尾部追加元素
insert(): 在任意位置前插入一個新元素,就是占位于這個位置雪情,原來此位置及以后的元素后移一位
erase(): 刪除vector中迭代器所指的一個元素或一段區(qū)間中的所有元素
clear():一次性刪除vector中的所有元素
reverse():將向量中某段迭代器區(qū)間元素反向排列
sort():要求使用隨機訪問迭代器排序遵岩,默認按升序排。可自定義比較函數(shù)定義排序規(guī)則尘执。
#include <vector>
#include <iostream>
#include <algorithm>
#include <numeric> //accumulate算法需要
using namespace std;
//自定義比較函數(shù)使降序排序
bool cmp(const int &a, const int &b)
{
if (a != b) return a > b;
return a > b;
}
//使用迭代器訪問元素舍哄,迭代器的類型要與遍歷的vector對象的元素類型一致
void Print(vector<int> v)
{
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
cout << *it <<" ";
cout<<endl;
}
int main()
{
vector<int> v;
int i;
for (i = 0; i < 10; i ++)
v.push_back(i);
cout <<"初始時vector元素"<<endl;
Print(v);
v[6] = 12; //使用下標(biāo)賦值
cout << v[6]<<endl; //使用下標(biāo)訪問元素
v.insert(v.begin(), 11); //在最前面插入11
v.insert(v.end(), 13); //末尾追加13,效果同v.push_back(13)
v.insert(v.begin() + 2, 16); //在第二個位置插入16誊锭,即v[2] = 16
cout <<"插入后vector元素"<<endl;
Print(v);
v.erase(v.begin() + 2); //刪除v[2]
v.erase(v.begin() + 1, v.begin() + 4); //刪除v[1] ~ v[3]共3個元素
cout <<"刪除后vector元素"<<endl;
Print(v);
sort(v.begin(), v.end());
cout <<"排序后vector元素"<<endl;
Print(v);
sort(v.begin(), v.end(), cmp);
cout <<"降序排序后vector元素"<<endl;
Print(v);
reverse(v.begin(), v.end());
cout <<"反向排列后vector元素"<<endl;
Print(v);
cout << v.size() <<endl; //輸出向量大小
v.clear(); //清空向量
cout << v.empty() <<endl; //輸出向量是否為空
return 0;
}
auto關(guān)鍵字
auto是C++11新引入的類型說明符表悬,讓編譯器分析表達式所屬的類型,用于從初始化表達式中推斷出變量的數(shù)據(jù)類型丧靡。所以auto定義的變量必須要有初始值蟆沫。有以下好處:
- 可靠性:如果表達式的類型發(fā)生更改(包括函數(shù)返回值發(fā)生更改的情況),它也能工作温治。
- 性能:確保將不會進行轉(zhuǎn)換饭庞。
- 方便:不必擔(dān)心類型名稱拼寫困難和拼寫有誤。
- 效率高:代碼會變得更高效熬荆。
// auto a; // 錯誤但绕,沒有初始化表達式,無法推斷出a的類型
// auto int a = 10; // 錯誤惶看,auto不能與其他類型組合連用
// 1. 自動幫助推導(dǎo)類型
auto a = 10;
auto c = 'A';
auto s("hello");
// 2. 類型冗長
map<int, map<int,int> > map_;
map<int, map<int,int>>::const_iterator itr1 = map_.begin();
const auto itr2 = map_.begin();
auto ptr = []()
{
std::cout << "hello world" << std::endl;
};
return 0;
};
// 3. 使用模板技術(shù)時捏顺,如果某個變量的類型依賴于模板參數(shù), 不使用auto將很難確定變量的類型(使用auto后纬黎,將由編譯器自動進行確定)幅骄。
template <class T, class U>
void Multiply(T t, U u) //函數(shù)和模板參數(shù)不能被聲明為auto
{
auto v = t * u;
}
//4. 不能用于類型轉(zhuǎn)換或其他一些操作,如sizeof和typeid
int value = 123;
auto x2 = (auto)value; // 不能用 auto 轉(zhuǎn)換
auto x3 = static_cast<auto>(value); // 錯誤同上
//5. 定義在一個auto序列的變量必須始終能被推導(dǎo)成同一類型
auto x1 = 5, x2 = 5.0, x3='r'; //錯誤
三本今、string基本字符系列容器
string可理解為字符串類拆座,其對象的元素是字符。提供了增刪改查比較等多種函數(shù)冠息。
賦值兩種形式: 直接給字符串挪凑;賦字符指針
尾部追加字符/字符串: 用“+”或者s.append()。注意字符串要用“”逛艰。
inset():將一個字符插入到迭代器位置之前
erase():刪除迭代器所指的元素或一個區(qū)間中所有元素
length():返回字符串長度
empty():返回字符串是否為空
replace():替換string對象中的字符
find():查找字符串中的第一個字符元素或子串躏碳,返回下標(biāo)值或最大整數(shù)值,以下測試出的是64位
compare():字符串比較散怖,若比對方大返回1菇绵,小返回-1,相等返回0
reverse():反向排序string對象镇眷,需加頭文件algorithm
string對象也可作為vector的元素咬最,類似于字符串?dāng)?shù)組。
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
using namespace std;
int main()
{
//創(chuàng)建字符串對象欠动,直接賦值并輸出字符串長度
string s;
s = "hello, STL";
cout <<"hello, STL的長度為:" << s.length()<<endl;
//使用字符指針賦給字符串對象
char ch[100];
scanf("%s", ch); //scanf輸入速度比cin快得多永乌,但不支持string對象
s = ch; //整個字符數(shù)組賦給string對象
cout <<"輸入的字符串為:" << s << endl;
s = s + '1'; //直接用‘+’在尾部添加字符
s = s + "+-"; //尾部追加字符串要用 ""
s.append("***"); //尾部追加字符串
cout <<"追加后的字符串為:" << s << endl;
string::iterator it; //定義迭代器
it = s.begin();
s.insert(it + 1, '?'); //將'?'插入到s[1]
cout <<"插入‘?’后的字符串為:" << s << endl;
cout <<"首字符比‘a(chǎn)’大:" << s[0] - 'a' << endl;
s.erase(it + 2); //刪除s[2]
s.erase(it, it + 4); //刪除s[0] ~ s[3]共4個元素
cout <<"刪除后字符串為:" << s<< endl;
s = ""; //清空
cout <<"字符串是否為空"<<s.empty()<<endl;
s = "abc123456";
s.replace(3,3,"good"); //從第3個開始,將連續(xù)的3個字符替換為good
cout <<"替換后字符串為:" << s<< endl;
cout <<"字符串中第一個o的位置" <<s.find('o')<<endl;
cout <<"字符串中g(shù)ood的位置" <<s.find("good")<<endl;
cout <<"字符串中dog的位置翅雏,找不到則返回最大正整數(shù)值" <<s.find("dog")<<endl;
//字符串比較圈驼,比對方大則返回1,小返回-1枚荣,相等返回0
cout <<"與bcd比較:" <<s.compare("bcd")<<endl;
cout <<"與自己比較:" <<s.compare("abcgood456")<<endl;
cout <<"與aaaaa比較:" <<s.compare("aaaaa")<<endl;
s = "1234567";
reverse(s.begin(), s.end());
cout <<"翻轉(zhuǎn)后的字符串為:"<<s <<endl;
vector<string> v;
v.push_back("yeah");
v.push_back("nope");
v.push_back("great");
cout << v[2] <<endl;
cout << v[1][0] <<endl;
cout << v[0].length()<<endl;
return 0;
}
string 類型的數(shù)字化處理
分離讀入的數(shù)字的每位時碗脊,若用取余法效率較低,而且對于大數(shù)字也只能作為字符串處理輸入橄妆。string 對象與字符數(shù)組互操作
string s;
char ss[100];
scanf("%s", ss); //空格作為終止符不會被讀入
s = ss;
printf(s.c_str()); //用 printf 輸出字符串對象要用 c_str() 方法
cout<<endl;
printf("%s", ss);
-
string 對象與 sscanf 函數(shù)
C語言中 sscanf 用于將一個字符串按需要的方式分離出子串
string s1, s2, s3;
char sa[100], sb[100], sc[100];
sscanf("abc 123 pc", "%s %s %s", sa, sb, sc);
s1 = sa;
s2 = sb;
s3 = sc;
cout<<s1 <<" "<<s2<<" "<<s3<<endl;
int a, b, c;
sscanf("1 2 3", "%d %d %d", &a, &b, &c);
cout<<a <<" "<<b<<" "<<c<<endl;
sscanf("4,5$6", "%d,%d$%d", &a, &b, &c);
cout<<a <<" "<<b<<" "<<c<<endl;
- string 對象與數(shù)值相互轉(zhuǎn)換
#include <iostream>
#include <algorithm>
#include <string>
#include <sstream>
using namespace std;
//將數(shù)值轉(zhuǎn)化為string
string convertToString(double x)
{
ostringstream o;
if (o << x)
return o.str();
return "conversion error";
}
//將string轉(zhuǎn)換為數(shù)值
double convertFromString(const string &s)
{
istringstream i(s);
double x;
if (i >> x)
return x;
return 0; //若出錯
}
int main()
{
//將數(shù)值轉(zhuǎn)化為string的C方法
char b[10];
string a;
sprintf(b, "%d", 1975);
a = b;
cout<< a <<endl;
//將數(shù)值轉(zhuǎn)化為string的C++方法
string cc = convertToString(1976);
cout << cc<< endl;
//將string轉(zhuǎn)換為數(shù)值的C++方法
string dd = "2006";
int p = convertFromString(dd) + 2;
cout << p <<endl;
return 0;
}
實際上就是
ostringstream o;
int x = 123;
o << x;
cout<<o.str()<<endl;
istringstream i("456");
i >> x;
cout<<x<<endl;
//輸出123 456