最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

c++模擬實(shí)現(xiàn)string類詳情

 更新時(shí)間:2022年01月26日 10:41:50   作者:sasorit?  
這篇文章主要介紹了c++模擬實(shí)現(xiàn)string類詳情,string表示可變長(zhǎng)的字符序列,使用string類型必須首先包含string頭文件。作為標(biāo)準(zhǔn)庫的一部分,string定義在命名空間std中,下面進(jìn)入文章一起看看詳細(xì)內(nèi)容吧

一、string類簡(jiǎn)介

標(biāo)準(zhǔn)庫類型string表示可變長(zhǎng)的字符序列,使用string類型必須首先包含string頭文件。作為標(biāo)準(zhǔn)庫的一部分,string定義在命名空間std中。

二、模擬實(shí)現(xiàn)

成員變量

?? ?char* _str;
?? ?size_t _size;
?? ?size_t _capacity;?? ?//不包含最后做標(biāo)識(shí)的'\0'
?? ?static const size_t npos;

_str用來存儲(chǔ)字符串,_size表示字符串有效數(shù)據(jù)個(gè)數(shù),_capacity表示容量大小,其中不包含最后做標(biāo)識(shí)的‘\0’。

例如這樣一段代碼:string str(“hello”);

npos是一個(gè)靜態(tài)成員常量,值為-1,因?yàn)閟ize_t是無符號(hào)整數(shù)類型,所以它表示size_t類型的最大值。
當(dāng)npos用在做成員函數(shù)中l(wèi)en的參數(shù)時(shí),表示“直到字符串的結(jié)尾”,
例如用來刪除字符串中某一部分的函數(shù)erase(size_t pos = 0, size_t len = npos),如果沒傳參數(shù)len,那么就會(huì)從pos位置直接刪到最后。
當(dāng)作為返回值時(shí),npos通常表示不匹配,例如find函數(shù)返回npos,就意味著沒找到。

初始化string對(duì)象常用的幾種方式:

?? ?string s1("hello");?? ??? ? //默認(rèn)初始化,s1是一個(gè)空字符串
?? ?string s2 = s1; ? ? ? ? ?//s2是s1的副本
?? ?string s3 = "hello";
?? ?string s4(5, 'c'); ? ? ? //s4的內(nèi)容是ccccc

成員函數(shù)

構(gòu)造函數(shù):

 ?string(const char* str = "")
?? ??? ?:_size(strlen(str))
?? ??? ?,_capacity(_size)
?? ?{
?? ??? ?_str = new char[_capacity + 1];
?? ??? ?strcpy(_str, str);
?? ?}

這里需要注意的是參數(shù)列表的初始化順序與初始化列表列出的順序無關(guān),只與它在類中聲明順序有關(guān),由于我們聲明成員變量順序_size_capacity前面,所以這里_size也要在_capacity前面。
容量_capacity中不包含’\0’,所以申請(qǐng)空間時(shí)多申請(qǐng)一位。
重載一個(gè)用來初始化s4的構(gòu)造函數(shù)

 ?string(const size_t n, const char ch)
?? ??? ?:_size(n)
?? ??? ?, _capacity(_size)
?? ?{
?? ??? ?_str = new char[_capacity + 1];
?? ??? ?for (size_t i = 0; i < n; ++i)
?? ??? ?{
?? ??? ??? ?_str[i] = ch;
?? ??? ?}
?? ??? ?_str[_size] = '\0';
?? ?}

拷貝構(gòu)造:

?? ?string(const string& s)
?? ??? ?:_str(nullptr)
?? ?{
?? ??? ?string tmp(s._str);
?? ??? ?swap(tmp);
?? ?}

s._str去構(gòu)造臨時(shí)對(duì)象tmp,這里引用傳參s是s1的別名,tmp調(diào)用構(gòu)造函數(shù)開空間拷貝數(shù)據(jù),所以最后tmp和s1是一樣的數(shù)據(jù)一樣的大小,而tmp的空間是s2想要的,所以把他們交換。這樣s2就達(dá)到深拷貝的效果了。
tmp是局部對(duì)象,出函數(shù)作用域會(huì)調(diào)用析構(gòu)函數(shù),而s2的_str指向的位置是隨機(jī)值,把tmp和s2交換后tmp的_str就變成了隨機(jī)值,不能對(duì)一個(gè)隨機(jī)的位置進(jìn)行釋放,所以先在參數(shù)列表中把s2的_str指向nullptr。

另外還需要提供一個(gè)swap函數(shù)交換兩個(gè)對(duì)象:

?? ?void swap(string& s)
?? ?{
?? ??? ?::swap(_str, s._str);
?? ??? ?::swap(_size, s._size);
?? ??? ?::swap(_capacity, s._capacity);
?? ?}

賦值重載:
 

?? ?string& operator=(string s)
?? ?{
?? ??? ?swap(s);
?? ??? ?return *this;
?? ?}

string s1(“hello”);
string s2(“world”);
s2 = s1;

s1傳值傳參給s,調(diào)用拷貝構(gòu)造深拷貝,s和s1是一樣的,把s和s2交換,出函數(shù)作用域后形參s調(diào)用析構(gòu)函數(shù)釋放資源。

析構(gòu)函數(shù):

?? ?~string()
?? ?{
?? ??? ?delete[] _str;
?? ??? ?_str = nullptr;
?? ??? ?_size = _capacity = 0;
?? ?}

迭代器

迭代器是一個(gè)像指針一樣的東西,有可能是指針,也有可能不是指針。

begin()返回第一個(gè)有效數(shù)據(jù)位置的迭代器
end()返回最后一個(gè)有效數(shù)據(jù)的下一個(gè)位置的迭代器
vector/string這種底層用連續(xù)一段空間存儲(chǔ)數(shù)據(jù),支持[ ] + 下標(biāo)訪問,迭代器用原生指針即可。

普通迭代器:

?? ?typedef char* iterator;
?? ?
?? ?iterator begin()
?? ?{
?? ??? ?return _str;
?? ?}
?? ?
?? ?iterator end()
?? ?{
?? ??? ?return _str + _size;
?? ?}

const迭代器:

 ?typedef const char* const_iterator;
?? ?
?? ?const_iterator begin() const
?? ?{
?? ??? ?return _str;
?? ?}
?? ?
?? ?const_iterator end() const
?? ?{
?? ??? ?return _str + _size;
?? ?}

重載運(yùn)算符[ ]

也一樣提供非const版本和const版本

?char& operator[](size_t pos)
?? ?{
?? ??? ?assert(pos < _size);
?? ??? ?return _str[pos];
?? ?}
?? ?
?? ?const char& operator[](size_t pos) const
?? ?{
?? ??? ?assert(pos < _size);
?? ??? ?return _str[pos];
?? ?}

現(xiàn)在可以創(chuàng)建一個(gè)string對(duì)象并且遍歷了。

三、幾種常見函數(shù)

reserve()

reserve()函數(shù)用來修改字符串容量的大小。如果申請(qǐng)空間的newcapacity大于當(dāng)前的capacity,則分配新的存儲(chǔ)空間,并使capacity 等于或大于 newcapacity。如果newcapacity小于當(dāng)前容量,則是一個(gè)非綁定收縮請(qǐng)求。
從C++20起如果newcapacity小于或等于當(dāng)前容量,則沒有效果。

? ?void reserve(size_t n)
?? ?{
?? ??? ?if (n > _capacity)
?? ??? ?{
?? ??? ??? ?char* tmp = new char[n + 1];
?? ??? ??? ?strcpy(tmp, _str);
?? ??? ??? ?delete[] _str;
?? ??? ??? ?_str = tmp;
?? ??? ??? ?_capacity = n;
?? ??? ?}
?? ?}

resize()

resize()用來將字符串大小調(diào)整為n個(gè)字符的長(zhǎng)度。
如果 n 小于當(dāng)前字符串長(zhǎng)度,則將當(dāng)前size縮短為n。
如果 n 大于當(dāng)前字符串長(zhǎng)度,則通過在末尾插入所需數(shù)量的字符來擴(kuò)展當(dāng)前內(nèi)容,以達(dá)到 n 的大小。 如果指定了字符,則將新元素初始化為該字符,否則初始化為空字符。

?void resize(size_t n, char ch = '\0')
?? ?{
?? ??? ?if (n < _size)
?? ??? ?{
?? ??? ??? ?_str[n] = '\0';
?? ??? ??? ?_size = n;
?? ??? ?}
?? ??? ?else
?? ??? ?{
?? ??? ??? ?if (n > _capacity)
?? ??? ??? ?{
?? ??? ??? ??? ?reserve(n);
?? ??? ??? ?}
?? ??? ??? ?for (size_t i = _size; i < n; ++i)
?? ??? ??? ?{
?? ??? ??? ??? ?_str[i] = ch;
?? ??? ??? ?}
?? ??? ??? ?_size = n;
?? ??? ??? ?_str[_size] = '\0';
?? ??? ?}
?? ?}

push_back()

將給定字符加到字符串的末尾。

 ?void push_back(char ch)
?? ?{
?? ??? ?if (_size >= _capacity)
?? ??? ?{
?? ??? ??? ?size_t newcapacity = _capacity == 0 ? 4 : 2 * _capacity;
?? ??? ??? ?reserve(newcapacity);
?? ??? ?}
?? ??? ?_str[_size] = ch;
?? ??? ?++_size;
?? ??? ?_str[_size] = '\0';?? ?
?? ?}

append()

在字符串結(jié)尾添加字符串

 ?void append(const char* str)
?? ?{
?? ??? ?size_t len = strlen(str);
?? ??? ?if (_size + len > _capacity)
?? ??? ?{
?? ??? ??? ?reserve(_size + len);
?? ??? ?}
?? ??? ?strcpy(_str + _size, str);
?? ??? ?_size += len;
?? ?}

有了push_back()append()就很方便重載+=

重載+=

右操作數(shù)為字符:

? ?string& operator+=(char ch)
?? ?{
?? ??? ?push_back(ch);
?? ??? ?return *this;
?? ?}

右操作數(shù)為字符串:

?? ?string& operator+=(const char* str)
?? ?{
?? ??? ?append(str);
?? ??? ?return *this;
?? ?}

右操作數(shù)為對(duì)象:

?? ?string& operator+=(const string& s)
?? ?{
?? ??? ?*this += s._str;
?? ??? ?return *this;
?? ?}

insert()

在字符串任意位置插入一個(gè)字符或字符串。
push_back()append()都可以復(fù)用insert()

插入字符:

?? ?string& insert(size_t pos, char ch)
?? ?{
?? ??? ?assert(pos <= _size);
?? ??? ?if (_size == _capacity)
?? ??? ?{
?? ??? ??? ?size_t newcapacity = _capacity == 0 ? 4 : 2 * _capacity;
?? ??? ??? ?reserve(newcapacity);
?? ??? ?}
?? ??? ?for (size_t i = _size + 1; i > pos; --i)
?? ??? ?{
?? ??? ??? ?_str[i] = _str[i - 1];
?? ??? ?}
?? ??? ?_str[pos] = ch;
?? ??? ?++_size;
?? ??? ?return *this;
?? ?}

插入字符串:

?string& insert(size_t pos, const char* str)
?? ?{
?? ??? ?assert(pos <= _size);
?? ??? ?size_t len = strlen(str);
?? ??? ?if (len + _size > _capacity)
?? ??? ?{
?? ??? ??? ?reserve(len + _size);
?? ??? ?}
?? ??? ?for (size_t i = _size + len; i >= (pos + len); --i)
?? ??? ?{
?? ??? ??? ?_str[i] = _str[i - len];
?? ??? ?}
?? ??? ?for (size_t i = 0; i < len; ++i)
?? ??? ?{
?? ??? ??? ?_str[pos + i] = str[i];
?? ??? ?}
?? ??? ?_size += len;
?? ??? ?return *this;
?? ?}

erase()

刪除字符串的一部分,減少它的長(zhǎng)度,如果沒給參數(shù)len就會(huì)從pos位置直接刪到最后。

 ?string& erase(size_t pos = 0, size_t len = npos)
?? ?{
?? ??? ?assert(pos < _size);
?? ??? ?if (len >= (_size - pos))
?? ??? ?{
?? ??? ??? ?_str[pos] = '\0';
?? ??? ??? ?_size = pos;
?? ??? ?}
?? ??? ?else
?? ??? ?{
?? ??? ??? ?for (size_t i = pos + len; i <= _size; ++i)
?? ??? ??? ?{
?? ??? ??? ??? ?_str[i - len] = _str[i];
?? ??? ??? ?}
?? ??? ??? ?_size -= len;
?? ??? ?}
?? ??? ?return *this;
?? ?}

find()

查找從pos位置開始第一個(gè)給定字符或字符串。找到了返回對(duì)應(yīng)字符或子串第一個(gè)字符第一次出現(xiàn)的位置,沒找到返回npos。
查找字符:

?size_t find(char ch, size_t pos = 0)
?? ?{
?? ??? ?for (size_t i = pos; i < _size; ++i)
?? ??? ?{
?? ??? ??? ?if (_str[i] == ch)
?? ??? ??? ??? ?return i;
?? ??? ?}
?? ??? ?return npos;
?? ?}

查找字符串:

? ?size_t find(const char* sub, size_t pos = 0)
?? ?{
?? ??? ?const char* p = strstr(_str + pos, sub);
?? ??? ?if (p)
?? ??? ??? ?return p - _str;
?? ??? ?return npos;
?? ?}

四、操作符重載

流插入<<

?? ?ostream& operator<<(ostream& out, const string& s)
?? ?{
?? ??? ?for (size_t i = 0; i < s.size(); ++i)
?? ??? ?{
?? ??? ??? ?out << s[i];
?? ??? ?}
?? ??? ?return out;
?? ?}

流提取>>

?? ?istream& operator>>(istream& in, string& s)
?? ?{
?? ??? ?s.clear();
?? ??? ?char ch = in.get();
?? ??? ?while (ch != ' ' && ch != '\n')
?? ??? ?{
?? ??? ??? ?s += ch;
?? ??? ??? ?ch = in.get();
?? ??? ?}
?? ??? ?return in;
?? ?}

其他運(yùn)算符重載和一些簡(jiǎn)單的函數(shù)在完整代碼給出。

到此這篇關(guān)于c++模擬實(shí)現(xiàn)string類詳情的文章就介紹到這了,更多相關(guān)c++模擬實(shí)現(xiàn)string類 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 關(guān)于C++中由于字節(jié)對(duì)齊引起內(nèi)存問題定位分析

    關(guān)于C++中由于字節(jié)對(duì)齊引起內(nèi)存問題定位分析

    前幾天遇到一個(gè)稀奇古怪的問題,在創(chuàng)建對(duì)象的時(shí)候程序異常退出,查找代碼發(fā)現(xiàn)結(jié)構(gòu)體數(shù)組問題,最終把問題簡(jiǎn)化得到解決方法,下面小編把我的問題及解決方案分享到腳本之家平臺(tái)供大家參考下
    2021-06-06
  • Inline Hook(ring3)的簡(jiǎn)單C++實(shí)現(xiàn)方法

    Inline Hook(ring3)的簡(jiǎn)單C++實(shí)現(xiàn)方法

    這篇文章主要介紹了Inline Hook(ring3)的簡(jiǎn)單C++實(shí)現(xiàn)方法,需要的朋友可以參考下
    2014-08-08
  • Qt 使用Poppler實(shí)現(xiàn)pdf閱讀器的示例代碼

    Qt 使用Poppler實(shí)現(xiàn)pdf閱讀器的示例代碼

    下面小編就為大家分享一篇Qt 使用Poppler實(shí)現(xiàn)pdf閱讀器的示例代碼,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2018-01-01
  • C語言詳解如何實(shí)現(xiàn)帶頭雙向循環(huán)鏈表

    C語言詳解如何實(shí)現(xiàn)帶頭雙向循環(huán)鏈表

    帶頭雙向循環(huán)鏈表:結(jié)構(gòu)最復(fù)雜,一般用在單獨(dú)存儲(chǔ)數(shù)據(jù)。實(shí)際中使用的鏈表數(shù)據(jù)結(jié)構(gòu),都是帶頭雙向循環(huán)鏈表。另外這個(gè)結(jié)構(gòu)雖然結(jié)構(gòu)復(fù)雜,但是使用代碼實(shí)現(xiàn)以后會(huì)發(fā)現(xiàn)結(jié)構(gòu)會(huì)帶來很多優(yōu)勢(shì),實(shí)現(xiàn)反而簡(jiǎn)單
    2022-04-04
  • VSCode搭建C/C++編譯環(huán)境的詳細(xì)教程

    VSCode搭建C/C++編譯環(huán)境的詳細(xì)教程

    Visual Studio Code是一款免費(fèi)開源的現(xiàn)代化輕量級(jí)代碼編輯器,支持幾乎所有主流的開發(fā)語言的語法高亮、智能代碼補(bǔ)全、自定義熱鍵、括號(hào)匹配、代碼片段、代碼對(duì)比 Diff、GIT 等特性,這篇文章主要介紹了VSCode搭建C/C++編譯環(huán)境,需要的朋友可以參考下
    2020-05-05
  • C++中pair使用的示例代碼

    C++中pair使用的示例代碼

    本文主要介紹了C++中pair使用的示例代碼,用于存儲(chǔ)兩個(gè)不同類型的元素,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-02-02
  • C++基于EasyX實(shí)現(xiàn)簡(jiǎn)單掃雷游戲

    C++基于EasyX實(shí)現(xiàn)簡(jiǎn)單掃雷游戲

    這篇文章主要為大家詳細(xì)介紹了C++基于EasyX實(shí)現(xiàn)簡(jiǎn)單掃雷游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-02-02
  • C語言通過案例講解并發(fā)編程模型

    C語言通過案例講解并發(fā)編程模型

    所謂并發(fā)編程是指在一臺(tái)處理器上“同時(shí)”處理多個(gè)任務(wù)。并發(fā)是在同一實(shí)體上的多個(gè)事件。多個(gè)事件在同一時(shí)間間隔發(fā)生,下面我們根據(jù)樣例來理解
    2022-04-04
  • C++11 學(xué)習(xí)筆記之std::function和bind綁定器

    C++11 學(xué)習(xí)筆記之std::function和bind綁定器

    這篇文章主要介紹了C++11 學(xué)習(xí)筆記之std::function和bind綁定器,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-07-07
  • C++開放封閉原則示例解析

    C++開放封閉原則示例解析

    在如那就的設(shè)計(jì)模式中,不能修改,但可以擴(kuò)展的實(shí)現(xiàn)是一條十分重要的原則,它是開放-封閉原則(The Open-Clossed Principle,簡(jiǎn)稱OCP)或開-關(guān)閉原則
    2023-02-02

最新評(píng)論

牙克石市| 兴文县| 将乐县| 顺昌县| 鲁山县| 伊吾县| 稻城县| 恩施市| 工布江达县| 东阳市| 阿拉善盟| 曲麻莱县| 十堰市| 重庆市| 永福县| 腾冲县| 樟树市| 西昌市| 杭州市| 项城市| 瑞金市| 弥渡县| 永登县| 任丘市| 南江县| 夹江县| 黑水县| 昌黎县| 乌海市| 嘉荫县| 钟山县| 团风县| 东源县| 金阳县| 浦江县| 花莲市| 三原县| 瑞金市| 墨玉县| 忻州市| 阜新|