《C++ primer plus》第十六章:string類和標准模板庫(一) 學習筆記


一、string類

1.string類的構造函數

//string類的構造函數
string(const char*s)

string(size_type n,char s) 將string初始化為n個s的字符串

string(const string& str,string size_type n)

string(const char* s,size_type n)

template<class Iter>
string (Iter begin,Iter end)
將string初始化為區間在[begin,end]內的字符,范圍包括begin,不包括end


#include <iostream>
#include <cstring>
int main()
{
using namespace std;
string one("goodday");
string two(20,'s');
string three(one);
three[0] = 'G';
string four = two + one;
char alls[] = "because I am batman!\n";
string five(alls,5); //如果超過alls的長度,人家愛那個復制請求數目的字符,將導致無用字符
string six(alls+4,alls+12);

string seven(&six[2],&six[7]);
//與string six 不同的是,six是類,six+2 不會和 alls一樣看成指針,所以需要用&six[2]
cout << "one: " << one << endl;
cout << "two: " << two << endl;
cout << "three: " << three << endl;
cout << "four: " << four << endl;
cout << "five: " << five << endl;
cout << "six: " << six << endl;
cout << "seven: " << seven << endl;
}

2.string類的輸入
(1)C-風格字符串的輸入有三種
char info[100];
cin >> info;
cin.get(info,100);
cin.getline(info,100);
//cin.getline()存在一個可選參數,用於指定那個字符為輸入的邊界
//默認為'\n'
//如cin.getline(info,100,':');



(2)string類的輸入有兩種
string str;
cin >> str;
getline(cin,str);
同cin.getline(),getline(cin,str,':')同樣有一個可選參數
(3)string類輸入函數的限制:
<1>最大長度有常量string::npos指定,一般為為unsigned int的最大值
<2>程序可以使用的內存量
(4)getline停止的三種情況
<1>文件尾,輸入流的eofbit被設置,fail()和eof()都將返回true
<2>分界字符,將其從輸入流中刪除,不保存它
<3>達到默認最大值,fail()將返回true

#include <iostream>
#include <fstream>
#include <cstring>
#include <cstdlib>
int main()
{
using namespace std;
ifstream fin;
fin.open("test.txt");
if(!fin){
cout << "file cannot be open\n";
exit(EXIT_FAILURE);
}
string item;
int count = 0;

getline(fin,item,':');
while(fin){
count++;
cout << count << ": " << item << endl;
getline(fin,item,':');
}
fin.close();
return 0;
}

/*
test.txt的內容
sardines:chocolate ice :pop corn:leeks:
cheese bat:olice iol:butter tifu:
*/

/*程序的輸出
1: sardines
2: chocolate ice
3: pop corn
4: leeks
5:
cheese bat
6: olice iol
7: butter tifu
8:
*/



(4)重載的find方法
<1>size_type find(const string& str,size_type pos = 0)const
從pos的位置開始查找字符串str,如果找到,則返回該字符串首次出現的首字符索引,否則,返回string::npos
<2>size_type find(const char* str,size_type pos = 0)const
<3>size_type find(const char* str,size_type pos = 0,size_type n)const
與<2>不同的是,該函數查找s的前n個字符組成的字符串
<4>size_type find(char ch,size_type pos = 0)const
<5>此外還有rfind(),find_first_of(),find_last_of(),find_first_not_of(),find_last_not_of()
rfind()與find()類似,只是從反向查找,得到的是最后字符或字符串出現的索引
(5)capacity()返回當前分配給字符串的內存塊的大小,reserve()則可以自己定義分配的內存塊
string hold;
cout << hold.capacity() << endl;
hold.reserve(100);
(6)如果有一個string類,但是需要C-風格字符串,如打開文件,此時可以用c_str()

string filename;
cout << "Enter the file name: ";
cin >> filename;
oftream outfile;
coutfile.open(filename.c_str());


(7)重載C函數以使用string對象
如果比較兩個字符串時不需要區分大小寫,可以重載C庫的stricmp()或_stricmp()

#include <iostream>
#include <cstring>
using namespace std;
inline bool stricmp(const string& left,const string& right){
return stricmp(left.c_str(),right.c_str()) == 0;
}
int main()
{
string a = "hold",b = "HOLD";
cout << (a == b) << endl;
cout << stricmp(a,b) << endl;
}




二、string模板類的深入分析
string類是基於下面的模板定義的
template <class charT,class trait = char_trait<charT>,class Allocator = allocator<charT> >
charT為存儲在字符串的類型,trait參數時一個類,Allocator參數時用於處理內存分配的類,默認的allocator<char>模板按標准方式使用new和delete
兩種預定義的具體化


typedef basic_string<char> string;
typedef basic_string<wchar_t> wstring;
此外,還可以通過定義trait類和使用basic_string模板來為其他類型創建一個string類


1.13種類型和1個常量

typedef traits                                      traits_type;
typedef typename traits::char_type value_type;
typedef Allocator allocator_type;
typedef typename Allocator::size_type size_type;
typedef typename Allocator::difference_type difference_type;
typedef typename Allocator::reference reference;
typedef typename Allocator::const_reference const_reference;
typedef typename Allocator::pointer pointer;
typedef typename Allocator::const_pointer const_pointer;

traits是一個將對應於某個具體類型(如char_traits<char>)的模板參數;traits_type將成為該具體類型的typedef。下述表示法:
typedef typename traits::char_type            value_type;
意味着char_type是traits表示的類中定義的一個類型名。關鍵字typename告訴編譯器:表達式traits::char_type是一種類型。例如,對於字符串具體化,value_type為char 。
size_type與size_of的用法相似,只是它根據存儲的類型返回字符串的長度。對於string具體化,將根據char返回字符串的長度,在這種情況下,size_type與size_of等效。size_type是一種無符號類型。
difference_type用於度量字符串中兩個元素之間的距離(單位為元素的長度)。通常,它是底層類型size_type有符號版本。
對於char具體化來說,pointer的類型為char * ,而reference的類型為char & 。不過,如果要為自己設計的類型創建具體化,則這些類型(pointer和reference)可以指向類,與基本指針和引用有相同的特征。
為將標准模板庫(STL)算法用於字符串,該模板定義了一些迭代器類型:


typedef (models random access iterator) iterator;
typedef (models random access iterator) const_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
該模板還定義了一個靜態常量:
static const size_type npos = -1;
由於size_type是無符號的,因此將-1賦給npos相當於將最大的無符號值賦給它,這個值比可能的最大數組索引大1。
2.一些sring的數據方法
(1)
begin()指向字符串的第一個字符的迭代器
end()超尾迭代器
rbegin()超尾的反轉迭代器
rend()第一個字符的反轉迭代器
size()元素個數
length()同size
capacity()分配的元素數,可能比實際上的字符數
max_size()字符串的最大長度
data()一個指向數組第一個元素的const charT*指針,當string本身被修改時,該指針無效
c_str()一個指向數組第一個元素的const charT*指針,當string本身被修改時,該指針無效
get-allocator()用於為字符串object分配內存的allocator對象的副本
注意:begin()和rend()返回的是迭代器,而data()和c_str()返回的是const charT指針,而且,c_str()以空值字符借宿,而data()只是確保實際的字符串字符是存在的
(2)其他
void resize(size_type n)如果n > npos,引發out_of_range異常,否則,將長度改為n,如果n < size(),則截短,若大於則使用charT(0)填充
void resize(size_type n,charT c)如果n > npos,引發out_of_range異常,否則,將長度改為n,如果n < size(),則截短,若大於則使用c填充
void reserve(size_type res_arg = 0)重置capacity,以前的指針,引用,迭代器都將無效
void clear()
bool empty()const
3.字符串的存取
(1)operator[]:執行速度比at()快
(2)at():執行邊界檢查,若pos>=size,則引發out_of_range()異常
4.字符串搜索
(1)find()
size_type find(const basic_string& str,size_type pos = 0)const
從第一個字符開始查找,若沒有找到,則返回npos
size_type find(const chatT* s,size_type pos = 0)const
從第一個字符開始查找,若沒有找到,則返回npos
size_type find(const chatT* s,size_type pos = 0,size_type n)const
從第一個字符開始查找s的前n個字符串,若沒有找到,則返回npos
size_type find(chatT c,size_type pos = 0)const
(2)rfind()用於搜索字符串最后一次出現的地方,該位置I位於pos之前(包括pos),若沒有,則返回npos
(3)find_first_of
與find類似,但是不是搜索整個字符串,而是字符串中的字符首次出現的位置
(4)find_last_of
與rfind類似,但是不是搜索整個字符串,而是字符串中的字符最后出現的位置
(5)find_first_not_of ,find_last_not_of 搜索不是位於字符串中的字符的位置
5.compare函數
int compare(const basic_string& str)const
int compare(size_type pos1,size_type n1,const basic_string&s str)const
第一個字符串從pos1開始的n1個字符和str比較
int compare(size_type pos1,size_type n1,const basic_string&s str,size_type pos2,size_type n2)const
第一個字符串從pos1開始的n1個字符和str從pos2開始的n2個字符開始比較
int compare(size_type pos1,size_type n1,const charT* s)const
int compare(size_type pos1,size_type n1,const charT* s,size_type pos2,size_type n2)const
6.字符串的修改
(1)append()可以插入string,字符串和單個字符
(2)assign()可以將整個字符串,字符串的一部分和相同字符的字符序列賦給string
string test,hold;
test.assign("good");//"good"
hold.assign(test,1,2);//"oo"
hold.assign(6,'&');//"&&&&&&"

(3)插入
insert()和append()一樣,但是,insert還可以接受一個指定插入位置的參數,這個參數可以使位置,也可以是迭代器
str.insert(3,"bad");
(4)清除 erase()
basic_string& erase(size_type pos = 0,size_type n = npos)
從pos開始刪除n個字符,默認為刪除到尾
iterator erase(iterator pos)刪除該位置的字符
iterator erase(iterator first,iterator last)
(5)替換 replace()
string test("Take a right turn at Main Street");
test.replace(7,5,"left");
被替換的字符串和用來替換的字符串不一定要相同長度
注意:可以用find()來找到replace()的位置
(6)copy
size_type copy(charT* s,size_type n,size_type pos =0)
不追加空字符,不檢查長度是否足夠,需要程序員自行檢查

#include <iostream>
#include <cstring>
using namespace std;
int main()
{
string a = "bad";
char b[4];
a.copy(b,3,0);
b[3] = '\0';//如果缺少追加空字符,將會有無法預料的后果
cout << b;
}


(7)swap()使用一個恆定時間的算法來交換兩個string的內容
(8)substr() 復制子字符串,要求從指定位置開始,並具有指定的長度。
basic_string substr(size_type _Off = 0,size_type _Count = npos) const;






注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com