【C++修行之道】string類的使用

目錄

一.C語言中的字符串

二、標準庫中的string類 (了解)

2.1 string類(了解)

2.2 幫助文檔閱讀

三、 string類的常用接口說明

3.1?string類對象的常見構造?

3.2?string類對象的容量操作

3.3?string類對象的訪問及遍歷操作

字符串類的簡單實現

3.4?string類對象的修改操作

3.5 string類非成員函數

3.6 vs和g++下string結構的說明

四、string操作的代碼示例


一.C語言中的字符串

C語言中,字符串是以'\0'結尾的一些字符的集合,為了操作方便,C標準庫中提供了一些str系列的庫函數, 但是這些庫函數與字符串是分離開的,不太符合OOP的思想,而且底層空間需要用戶自己管理,稍不留神可 能還會越界訪問。

二、標準庫中的string(了解)

2.1 string(了解)

1. 字符串是表示字符序列的類

2. 標準的字符串類提供了對此類對象的支持,其接口類似于標準字符容器的接口,但添加了專門用于操作單字節字符字符串的設計特性。

3. string類是使用char(即作為它的字符類型,使用它的默認char_traits和分配器類型(關于模板的更多信息,請參閱basic_string)。

4. string類是basic_string模板類的一個實例,它使用char來實例化basic_string模板類,用char_traits 和allocator作為basic_string的默認參數(根于更多的模板信息請參考basic_string)。

5. 注意,這個類獨立于所使用的編碼來處理字節:如果用來處理多字節或變長字符(如UTF-8)的序列,這個類的所有成員(如長度或大小)以及它的迭代器,將仍然按照字節(而不是實際編碼的字符)來操作。

C++中對于string的定義是:typedef basic_string string;

  • 使用 typedef 關鍵字將 basic_string 類定義為一個新的類型 string
  • 這意味著,以后在代碼中提到 string 時,其實是在引用 basic_string 類。

也就是說C++中的string類是一個泛型類,由模板而實例化的一個標準類,本質上不是一個標準數據類型。

至于為什么不直接用String標準數據類型而用類是因為編碼

每個國家的語言不同 比如說英語使用26個英文字母基本就能表述所有的單詞 但是對于中文的字符呢?就要用其他編碼方式啊(比如說utf-8)

總結:

  1. string是表示字符串的字符串類
  2. 該類的接口與常規容器的接口基本相同,再添加了一些專門用來操作string的常規操作。
  3. string在底層實際是:basic_string模板類的別名,typedef basic_string<char, char_traits, allocator>?string;
  4. 不能操作多字節或者變長字符的序列。
  5. 在使用string類時,必須包含#include頭文件以及using namespace std

2.2 幫助文檔閱讀

(1) empty string constructor (default constructor)

????????Constructs an?empty?string, with a?length?of zero characters.

(2) copy constructor

????????Constructs a copy of?str.

(3) substring constructor

????????Copies the portion of?str?that begins at the character position?pos?and spans?len?characters ????????(or until the end of?str, if either?str?is too short or if?len?is?string::npos).

(4) from c-string

????????Copies the null-terminated character sequence (C-string) pointed by?s.

(5) from buffer

????????Copies the first?n?characters from the array of characters pointed by?s.

(6) fill constructor

????????Fills the string with?n?consecutive copies of character?c.

(7) range constructor

????????Copies the sequence of characters in the range?[first,last), in the same order.

(1) 空字符串構造函數(默認構造函數) ??????

????????構造一個空字符串,長度為零個字符。

(2) 拷貝構造函數 ????????

????????構造一個 str 的副本。

(3) 子字符串構造函數 ????????

????????復制 str 從字符位置 pos 開始并跨越 len 個字符的部分

????????(如果 str 太短或 len 是 string::npos,則復制到 str 的末尾)。

(4) 從 C 風格字符串構造 ????????

????????復制由 s 指向的以 null 結尾的字符序列(C 字符串)。

(5) 從字符串序列構造 ????????

????????復制由 s 指向的字符數組中的前 n 個字符。?

(6) 填充構造函數 ???????

????????用 n 個字符 c 的連續副本填充字符串。

(7) 范圍構造函數 ????????

????????復制范圍 [first,last) 中的字符序列,順序保持不變。

三、 string類的常用接口說明

3.1?string類對象的常見構造?

構造函數函數名稱功能說明
string()空字符串構造函數(重點)構造空的 string 類對象,即空字符串
string(const char* s)從 C-string 構造(重點)用 C-string 來構造 string 類對象
string(size_t n, char c)填充構造函數string 類對象中包含 n 個字符 c
string(const string& s)拷貝構造函數(重點)用一個已有的 string 對象 s 構造新的 string 對象
void test01()
{// 常用string s1;string s2("hello world");string s3(s2);// 不常用, 了解string s4(s2, 3, 5);string s5(s2, 3);string s6(s2, 3, 30);string s7("hello world", 5);string s8(10, 'x');cout << s1 << endl;cout << s2 << endl;cout << s3 << endl;cout << s4 << endl;cout << s5 << endl;cout << s6 << endl;cout << s7 << endl;cout << s8 << endl;cin >> s1;cout << s1 << endl;
}

3.2?string類對象的容量操作

函數名稱功能說明
size(重點)返回字符串有效字符長度
length返回字符串有效字符長度
capacity返回空間總大小
empty(重點)檢測字符串是否為空串,若為空返回 true,否則返回 false
clear(重點)清空有效字符
reserve(重點)為字符串預留空間
resize(重點)將有效字符的個數改為 n 個,多出的空間用指定字符填充

注意:

1. size()與length()方法底層實現原理完全相同,引入size()的原因是為了與其他容器的接口保持一

致,一般情況下基本都是用size()。

2. clear()只是將string中有效字符清空,不改變底層空間大小。

3. resize(size_t n) 與 resize(size_t n, char c)都是將字符串中有效字符個數改變到n個,不同的是當字 符個數增多時:resize(n)用0來填充多出的元素空間,resize(size_t n, char c)用字符c來填充多出的 元素空間。注意:resize在改變元素個數時,如果是將元素個數增多,可能會改變底層容量的大小,如果是將元素個數減少,底層空間總大小不變。

4. reserve(size_t res_arg=0):為string預留空間,不改變有效元素個數,當reserve的參數小于 string的底層空間總大小時,reserver不會改變容量大小。

3.3?string類對象的訪問及遍歷操作

函數名稱功能說明
operator[](重點)返回 pos 位置的字符,用于 const string 類對象的調用
beginendbegin 獲取一個字符的迭代器,end 獲取最后一個字符下一個位置的迭代器
rbeginrendrbegin 獲取一個反向迭代器指向最后一個字符,rend 獲取一個反向迭代器指向第一個字符前一個位置
范圍 forC++11 支持更簡潔的范圍 for 新遍歷方式

字符串類的簡單實現

class String
{
public:// 引用返回// 1.減少拷貝// 2.修改返回對象char& operator[](size_t i){assert(i < _size)return _str[i];}
private:char* _str;size_t _size;size_t _capacity;
};

其中operator[]操作符重載允許通過下標訪問和修改字符串中的字符。通過返回字符的引用,可以避免不必要的拷貝并直接修改字符串內容,同時通過assert保證了安全性。

void test02()
{string s1("hello world");cout << s1.size() << endl;// 不計算'\0'// cout << s1.length() << endl;// 訪問每個字符并令其++for (size_t i = 0; i < s1.size(); i++){s1[i]++;}cout << endl;s1[0] = 'x';// 越界會被檢查// s1[20];// 訪問每個字符for (size_t i = 0; i < s1.size(); i++){cout << s1.operator[](i) << " ";cout << s1[i] << " ";}cout << endl;const string s2("hello world");// const 不能修改// s2[0] = 'x';
}

通過重載的 operator[] 訪問和修改字符串中的字符,同時也演示了對常量字符串對象進行修改時的限制。代碼還包含了越界訪問檢查,通過 assert 保證安全性。

3.4?string類對象的修改操作

函數名稱功能說明
push_back在字符串末尾插入字符?c
append在字符串末尾追加一個字符串
operator+=在字符串末尾追加字符串?str(重點)
c_str返回 C 格式字符串(重點),用于與其他 C/C++ 函數交互,返回的字符串是臨時的,不應被修改
find?+?npos從字符串?pos?位置開始往后找字符?c,返回該字符在字符串中的位置,找不到時返回?string::npos(重點)
rfind從字符串?pos?位置開始往前找字符?c,返回該字符在字符串中的位置(注意:rfind?通常用于查找子字符串,而非單個字符?c?的向前查找,對于單個字符,直接使用?find?從末尾開始查找即可)
substr在字符串中從?pos?位置開始,截取?n?個字符,然后將其返回

注意:

1. 在string尾部追加字符時,s.push_back(c) / s.append(1, c) / s += 'c'三種的實現方式差不多,一般情況下string類的+=操作用的比較多,+=操作不僅可以連接單個字符,還可以連接字符串。

2. 對string操作時,如果能夠大概預估到放多少字符,可以先通過reserve把空間預留好。

void test03()
{// 構造string s1("hello world");// 隱式類型轉換string s2 = "hello world";const string& s3 = "hello world";// 引用的臨時對象, 臨時對象具有常性string s4("hello world");push_back(s4);push_back("hello world");
}

3.5 string類非成員函數

函數/運算符功能說明
operator+字符串連接運算符,但盡量少用,因為傳值返回導致深拷貝,效率低
operator>>?(重點)輸入運算符重載,用于從輸入流中提取字符串到字符串對象中
operator<<?(重點)輸出運算符重載,用于將字符串對象的內容發送到輸出流中
getline?(重點)從輸入流中獲取一行字符串,直到遇到換行符('\n'),不包括換行符
relational operators?(重點)大小比較運算符重載,包括?<<=>>===!=,用于比較兩個字符串對象的大小

上面的幾個接口大家了解一下,下面的OJ題目中會有一些體現他們的使用。string類中還有一些其他的 操作,這里不一一列舉,大家在需要用到時不明白了查文檔即可。

3.6 vs和g++下string結構的說明

注意:下述結構是在32位平臺下進行驗證,32位平臺下指針占4個字節。

vsstring的結構

string總共占28個字節,內部結構稍微復雜一點,先是有一個聯合體,聯合體用來定義string中字

符串的存儲空間

  • 當字符串長度小于16時,使用內部固定的字符數組來存放
  • 當字符串長度大于等于16時,從堆上開辟空間
union _Bxty
{ // storage for small buffer or pointer to larger onevalue_type _Buf[_BUF_SIZE];pointer _Ptr;char _Alias[_BUF_SIZE]; // to permit aliasing
} _Bx;

這種設計也是有一定道理的,大多數情況下字符串的長度都小于16,那string對象創建好之后,內

部已經有了16個字符數組的固定空間,不需要通過堆創建,效率高。

其次:還有一個size_t字段保存字符串長度,一個size_t字段保存從堆上開辟空間總的容量

最后:還有一個指針做一些其他事情。

故總共占16+4+4+4=28個字節。

g++string的結構

G++下,string是通過寫時拷貝實現的,string對象總共占4個字節,內部只包含了一個指針,該指

針將來指向一塊堆空間,內部包含了如下字段:

  • 空間總大小
  • 字符串有效長度
  • 引用計數
struct _Rep_base
{size_type _M_length;size_type _M_capacity;_Atomic_word _M_refcount;
};
  • 指向堆空間的指針,用來存儲字符串。

四、string操作的代碼示例

void test04()
{string s1("hello world");// 遍歷方式1: 下標 + []for (size_t i = 0; i < s1.size(); i++){cout << s1[i] << " ";}cout << endl;// 遍歷方式2: 迭代器string::iterator it1 = s1.begin();while (it1 != s1.end()){*it1 += 3;cout << *it1 << " ";++it1;}cout << endl;// 遍歷方式3: 范圍for// 底層實現方式都是迭代器實現for (auto e : s1){e++;cout << e << " ";}cout << endl;//cout << typeid(it1).name() << endl;/*list<int> lt1;lt1.push_back(1);lt1.push_back(2);lt1.push_back(3);list<int>::iterator it = lt1.begin();while (it != lt1.end()){cout << *it << " ";++it;}cout << endl;for (auto e : lt1){cout << e << " ";}cout << endl;*/
}

//template<class T>
//struct ListNode
//{
//	ListNode <T>* _next;
//	ListNode <T>* _prev;
//	T _data;
//};
//
//template<class T>
//class list
//{
//private:
//	ListNode<T>* _head;
//};void test05()
{const string s1("hello world");//string::const_iterator it1 = s1.begin();auto it1 = s1.begin();while (it1 != s1.end()){// 指向的內容不能修改// *it1 += 3;cout << *it1 << " ";++it1;// const_iterator 本身可以++}cout << endl;/*string::iterator it1 = s1.begin();while (it1 != s1.end()){*it1 += 3;cout << *it1 << " ";++it1;}cout << endl;*/
}

void test06()
{const string s1("hello world");//string::const_iterator it1 = s1.begin();auto it1 = s1.begin();while (it1 != s1.end()){// 不能修改//*it1 += 3;cout << *it1 << " ";++it1;}cout << endl;//string::const_reverse_iterator cit1 = s1.rbegin();auto cit1 = s1.rbegin();while (cit1 != s1.rend()){// 不能修改//*cit1 += 3;cout << *cit1 << " ";++cit1;}cout << endl;string s2("hello world");string::reverse_iterator it2 = s2.rbegin();//auto it2 = s2.rbegin();while (it2 != s2.rend()){//*it2 += 3;cout << *it2 << " ";++it2;}cout << endl;
}

void test07()
{string s1("hello world");cout << s1 << endl;// s1按字典序排序// 排序一部分sort(s1.begin(), s1.end());// 第一個和最后一個參與排序sort(++s1.begin(), --s1.end());// 前五個排序  [0, 5)// sort(s1.begin(), s1.begin() + 5);cout << s1 << endl;
}

void test08()
{string s1("hello world");cout << s1 << endl;s1.push_back('x');cout << s1 << endl;s1.append(" yyyy!!");cout << s1 << endl;s1 += 'y';s1 += "zzzzz";cout << s1 << endl;
}

void test09()
{string s1("hello world");cout << s1 << endl;s1.assign("111111");cout << s1 << endl;// 慎用, 因為效率不高 -> O(N)// 實踐中需求也不高string s2("hello world");s2.insert(0, "xxxx");cout << s2 << endl;char ch = 'z';s2.insert(0, 1, ch);s2.insert(0, 1, 'y');cout << s2 << endl;// 沒有這個版本的頭插// s2.insert(0, 'y');// cout << s2 << endl;s2.insert(s2.begin(), 'y');cout << s2 << endl;s2.insert(s2.begin(), s1.begin(), s1.end());cout << s2 << endl;
}

void test10()
{string s1("hello world");cout << s1 << endl;// 效率不高, 慎用, 和inset類似s1.erase(0,1);// 頭刪cout << s1 << endl;// s1.erase(5);s1.erase(5,100);cout << s1 << endl;string s2("hello world");s2.replace(5, 1, "%20");// 字符串的替換cout << s2 << endl;// 不建議這樣使用,因為要挪動數據string s3("hello world hello char");for (size_t i = 0; i < s3.size();){if (s3[i] == ' '){s3.replace(i, 1, "%20");i += 3;}else {i++;}}cout << s3 << endl;string s4("hello world hello double");string s5;for (auto ch : s4){if (ch != ' '){s5 += ch;}else {s5 += "%20";}}cout << s5 << endl;
}

今天就先到這了!!!、

看到這里了還不給博主扣個:
?? 點贊??收藏 ?? 關注!

你們的點贊就是博主更新最大的動力!
有問題可以評論或者私信呢秒回哦。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/43223.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/43223.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/43223.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【論文閱讀筆記】ASPS: Augmented Segment Anything Model for Polyp Segmentation

1.論文介紹 ASPS: Augmented Segment Anything Model for Polyp Segmentation ASPS&#xff1a;用于息肉分割的擴展SAM模型 2024年 arxiv Paper Code 2.摘要 息肉分割在結直腸癌診斷中起著至關重要的作用。最近&#xff0c;Segment Anything Model(SAM)的出現利用其在大規模…

視頻壓縮軟件哪個壓縮最小,視頻用什么軟件壓縮最小

在數字媒體時代&#xff0c;視頻內容的生產與分享已成為生活常態。但隨之而來的問題就是&#xff0c;大視頻文件占用過多存儲空間&#xff0c;上傳和分享也變得不便。本文將為你揭示如何將視頻壓縮到最小&#xff0c;同時保持畫質清晰。讓我們一起探索吧&#xff01; 下載并文件…

剪輯抽幀技巧有哪些 剪輯抽幀怎么做視頻 剪輯抽幀補幀怎么操作 剪輯抽幀有什么用 視頻剪輯哪個軟件好用在哪里學

打破視頻節奏&#xff0c;讓作品告別平庸。抽幀剪輯可以改變視頻敘事節奏&#xff0c;人為制造沖突、轉折、卡頓的效果。這種剪輯方式&#xff0c;不僅可以推進劇情發展&#xff0c;還能吸引觀眾的注意力&#xff0c;有效防止觀影疲勞。有關剪輯抽幀技巧有哪些&#xff0c;剪輯…

python中 is 的意義和用法

在Python中&#xff0c;is 是一個關鍵字&#xff0c;用于比較兩個對象的身份&#xff08;即它們是否是同一個對象&#xff09;。如果兩個對象是同一個對象&#xff0c;is 將返回 True&#xff1b;否則返回 False。這與比較兩個對象的值是否相等的 操作符不同。 基本用法 a …

JavaScript——continue語句

目錄 任務描述 相關知識 continue語句 編程要求 任務描述 本關任務&#xff1a;計算數組中所有正數或者所有負數的和。 相關知識 上一實訓介紹了關鍵字break的使用&#xff0c;continue是一個和break含義十分接近的關鍵字&#xff0c;本關將詳細剖析continue的用法。 co…

Typora篇-忍痛開啟

語雀專業會員即將到期, 我看著99元的學費款, 我決定重新用回Typora。 雖然里面有一些文件但是我還是舍不得?_? 99元巨款。 下面開啟我的Typora整活歷程&#xff0c; 大家有什么好用的插件快捷方式一起來分享啊。

MyBatis框架學習筆記(二):原生API 的調用 和 注解的使用

1 MyBatis原生API 1.1 原生API 快速入門需求 在筆記一案例的基礎上將增刪改查&#xff0c;使用 MyBatis 原生的 API 完成&#xff0c;就是直接通過SqlSession 接口的方法來完成 1.2 原生API 快速入門-代碼實現 創建 src\test\java\com\hspedu\mapper\MyBatisNativeTest.jav…

uni-app 封裝http請求

1.引言 前面一篇文章寫了使用Pinia進行全局狀態管理。 這篇文章主要介紹一下封裝http請求&#xff0c;發送數據請求到服務端進行數據的獲取。 感謝&#xff1a; 1.yudao-mall-uniapp: 芋道商城&#xff0c;基于 Vue Uniapp 實現&#xff0c;支持分銷、拼團、砍價、秒殺、優…

實用性提升百分之一百!!!【ONLYOFFICE 8.1版本】全方位深度性能測評

目錄 【ONLYOFFICE 8.1 版本】全方位深度性能測評 一、界面與用戶體驗 二、文字處理功能 表格處理功能 演示文稿功能 協作與共享功能 性能與穩定性 總結 【ONLYOFFICE 8.1 版本】全方位深度性能測評 在當今數字化辦公的時代&#xff0c;辦公軟件的選擇對于提高工作效率和…

selenium處理cookie問題實戰

1. cookie獲取不完整 需要進入的資損平臺(web)首頁&#xff0c;才會出現有效的ctoken等信息 1.1. 原因說明 未進入指定頁面而獲取的 cookie 與進入頁面后獲取的 cookie 可能會有一些差異&#xff0c;這取決于網站的具體實現和 cookie 的設置方式。 通常情況下&#xff0c;一些…

x-mind沒有配置文件,可以自己創建文件修改內存

x-mind.ini 是 XMind 配置文件&#xff0c;用于自定義啟動選項。以下是一個完整的 x-mind.ini 文件示例。此配置假設你正在使用 Windows 系統并希望配置一些常見的啟動參數&#xff1a; -startup plugins/org.eclipse.equinox.launcher_1.5.0.v20180512-1130.jar --launcher.l…

query和params的區別是什么

query 和 params 是 Vue Router 中傳遞路由參數的兩種不同方式。它們的主要區別在于 URL 結構和獲取參數的方法。 1. params params 是用來傳遞路由路徑中的動態參數。這些參數在路由路徑中以冒號 (:) 表示。 路由配置&#xff1a; {path: /interviewApplication/:backpack…

NCCL源碼詳解6:通信拓撲識別感知構建 物理拓撲xml文件 ncclTopoGetSystem() 視頻教程

Nvidia NCCL如何構建物理拓撲 視頻教程在這&#xff1a; 2.2 NCCL源碼分析&#xff1a;物理拓撲識別感知xml通信topo構建 ncclTopoGetSystem()_嗶哩嗶哩_bilibili 一、ncclTopoGetSystem()拓撲構建 1.1 ncclTopoGetSystem()拓撲構建核心邏輯&#xff1a; 1、 嘗試從文件加…

【解決Windows11系統Windows Hello不能使用的問題】

提示&#xff1a;文章寫完后&#xff0c;目錄可以自動生成&#xff0c;如何生成可參考右邊的幫助文檔 文章目錄 前言一、Windows Hello是什么&#xff1f;二、使用步驟1.購買一個攝像頭2.開始配置 三、異常解決1.內置管理員不能使用2.沒找到合適的攝像頭3.攝像頭需要專用驅動4.…

原創作品——教育課程界面設計

教育行業UI界面設計需直觀易懂&#xff0c;確保學習者能迅速上手&#xff0c;減少認知負擔。布局清晰&#xff0c;導航便捷&#xff0c;功能按鈕和圖標設計應符合教育場景&#xff0c;直接支持學習目標的達成&#xff0c;促進高效學習體驗。 通過豐富的互動元素&#xff08;如拖…

博途通訊筆記1:1200與1200之間S7通訊

目錄 一、添加子網連接二、創建PUT GET三、各個參數的意義 一、添加子網連接 二、創建PUT GET 三、各個參數的意義

代碼隨想錄(day1)二分法

if語句的基本語法 if 要判斷的條件: 條件成立的時候&#xff0c;要做的事舉例&#xff1a; if nums[middle]<target:leftmiddle1 while語句的基本語法&#xff1a; while 判斷條件(condition)&#xff1a;執行語句(statements)舉例&#xff1a; while left<right:midd…

docker安裝mysql8.0.23

拉取鏡像 docker pull mysql:8.0.23 創建掛載文件 mkdir -p /home/docker/mysql/conf mkdir -p /home/docker/mysql/data mkdir -p /home/docker/mysql/logcd /home/docker/mysql/conf touch my.cnf#授權 chmod 777 -R /home/docker/mysql/conf chmod 777 -R /home/docker/m…

C++類的成員:靜態成員變量、靜態成員函數、非靜態成員變量、非靜態成員函數

(1) 類的成員 A.What&#xff08;什么是類的成員&#xff09; 是組成類的基本構建&#xff0c;包含數據成員、靜態成員和 成員函數 B.Which&#xff08;類的成員有哪些&#xff09; 數據成員&#xff1a; 用于存儲與類的對象相關的數據&#xff0c;例如整數、浮點數、字符串、…

2通道音頻ADC解碼芯片ES7243L、ES7243E、ES7243,用于低成本實現模擬麥克風轉換為IIS數字話筒

前言&#xff1a; 音頻解碼芯片某創參考價格&#xff1a; ES7243L 500&#xff1a;&#xffe5;1.36 / 個 ES7243E 500&#xff1a;&#xffe5;1.66 / 個 ES7243 500&#xff1a; &#xffe5;1.91 / 個 其中ES7243L工作電壓為1.8V&#xff0c;與其他兩款的3.3V工作電壓不同&…