深入剖析C++中的string類

一,C語言的字符串

在C語言里,對字符串的處理一項都是一件比較痛苦的事情,因為通常在實現字符串的操作的時候都會用到最不容易駕馭的類型——指針。

比如下面這個例子:

//example 1:

char str[12] = "Hello";

char *p = str;

*p = ''h'';? //改變第一個字母

?

//example 2:

char *ptr = "Hello";

*ptr = ''h'';? //錯誤

?

第一個字符串時用數組開辟的,它是可以改變的變量。而第二個字符串則是一個常量,也就是字面值。ptr只是指向它的指針而已,而不能改變指向的內容。

看兩者的匯編即可明了:

char p[] = "Hello";
004114B8? mov???????? eax,dword ptr [string "Hello" (4166FCh)]
004114BD? mov???????? dword ptr [ebp-10h],eax
004114C0? mov???????? cx,word ptr ds:[416700h]
004114C7? mov???????? word ptr [ebp-0Ch],cx

char *ptr = "Hello";
004114CB? mov???????? dword ptr [ebp-1Ch],offset string "Hello" (4166FCh)

可見用數組和用指針是完全不相同的。

要想通過指針來改變常量是錯誤,正確的寫法應該是用const指針。

const char *ptr = "Hello";

?

?

二,初識string類

正是因為C風格字符串(以空字符結尾的字符數組)太過復雜難于掌握,不適合大程序的開發,所以C++標準庫定義了一種string類,定義在頭文件<string>。注意<string.h>和<cstring>都是錯誤的,這兩個頭文件主要定義C風格字符串操作的一些方法,譬如strlen(), strcpy()等。第一個是C的頭文件格式,而第二個是C++風格的頭文件,但是和<string.h>是一樣的,它的目的是為了和C兼容。

看下面例子:

//example 3:

string str("world");?? //可以用C風格字符串初始化

string words = "Hello";

string greet = words;

string? join = greet + words;? //可以像基本類型一樣操作

?

但是如果試圖把string類型的對象直接賦給C風格的字符串的話,編譯器會報錯的。

string var = "Olympic";

char *ptr = var;? //error!

?

但是實際應用中這個問題也難以避免,很多時候我們還是需要將string類型的轉化為char*來實現自定義的操作,C++標準庫也為了和之前用C寫的程序兼容,于是可以用string的c_str()函數。

string var = "Olympic";

char *ptr = var.c_str(); //還不能被編譯

?

或者通過const_cast去掉其const屬性亦可

char *ptr=const_cast<char *>(var.c_str()); //correct!

這樣就可以通過ptr修改其指向的地址空間內容

?

但是c_str()為了防止意外地修改string對象,返回的是const指針,所以上面這段代碼是不能被編譯的。正確的應該是用const指針。

string var = "Olympic";

const char *p =?var.c_str(); //Correct!

?

這個c_str()方法在C++IO流操作上也被廣泛應用。

在打開文件時,如果要指定文件名,可以用C風格的字符串。如果用到string類型的字符串作為文件名時,就必須調用c_str()方法將其轉換為一個C風格字符串。

//example 4:

string?? filename;? //定義文件名稱

cin >> filename;

ifstream.open(filename.c_str());? //要使用C風格字符串

?

三, 深入了解string類

對string有一定了解以后,我們可以來了解C++標準庫定義的一系列豐富的字符串操作,當然都是基于string類型。從某一種程度上來說,string就是一種字符容器。

標準庫為string定義了很多方法,包括構造、插入(insert)、替換(assign和replace)、比較(compare)、查找(find)、刪除(erase)、連接(append)以及對子串的操作(substr)。而每一種操作都有很多種重載。

比如插入,除了包括標準容器的插入方式以外,string類本身還有一些特有的插入方法。

//example 5:

//與標準容器相同的插入操作:

str.insert(iter, value) //在迭代器iter之前插入value, 返回新元素的迭代器

str.insert(iter, n, value); //在迭代器iter之前插入n個value,返回void

str.insert(iter, begin, end); //在迭代器iter之前插入迭代器begin和end標記范圍內的元素,返回void

//string類特有的插入方法:

str.insert(pos, n, ch); //在下標為pos的字符之前插入n個字符ch

str.insert(pos, str2); //在下標為pos的字符之前插入string類型的對象str2的副本

str.insert(pos1, str2, pos2, len); //在下標為pos1的z字符之前插入string類型str2中從下表為pos2開始的len個字符

str.insert(pos, cp); //在下標為pos的字符前插入字符指針cp指向的C風格字符串的副本

?

總之string是一種非常靈活的字符串類型,標準庫讓我們可以忽略內存管理和具體實現方式,我們只需要關注其接口就好。并且初學者在使用字符串的時候也應盡量使用這種類型,而不是C風格的字符串。

當然,無C語言學習經歷的人可以例外。


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

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

相關文章

Apple System: Error: ENFILE: file table overflow

2019獨角獸企業重金招聘Python工程師標準>>> 在MAC上跑nodejs&#xff0c;遇到了一個問題&#xff1a;file table overflow 主要意思就是說文件打開太多了&#xff0c;超過了限制&#xff0c;產生這個問題主要是蘋果操作系統的限制。 echo kern.maxfiles65536 | sud…

springboot的緩存技術

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 我門知道一個程序的瓶頸在于數據庫&#xff0c;我門也知道內存的速度是大大快于硬盤的速度的。當我門需要重復的獲取相同的數據的時候&a…

深度優先遍歷解決連通域求解問題-python實現

問題描述 在一個矩形網格中每一個格子的顏色或者為白色或者為黑色。任意或上、或下、或左、或右相鄰同為黑色的格子組成一個家族。家族中所有格子的數量反映家族的大小。要求找出最大家族的家族大小&#xff08;組成最大家族的格子的數量&#xff09;并統計出哪些點屬于哪一族。…

字符串進階

C風格字符串 1、字符串是用字符型數組存儲的&#xff0c;字符串要求其尾部以’\0’作為結束標志。如&#xff1a; char string[ ]”C programming language”; 用sizeof來測string長度為25個字節&#xff0c;而實際串本身長度(含空格)為24個字節&#xff0c;多出來的一個就是…

flask上傳excel文件,無須存儲,直接讀取內容

運行環境python3.6 import xlrd from flask import Flask, requestapp Flask(__name__)app.route("/", methods[POST, GET]) def filelist1():print(request.files)file request.files[file]print(file, type(file), file)print(file.filename) # 打印文件名f …

分布式 ID的 9 種生成方式

一、為什么要用分布式 ID&#xff1f; 在說分布式 ID 的具體實現之前&#xff0c;我們來簡單分析一下為什么用分布式 ID&#xff1f;分布式 ID 應該滿足哪些特征&#xff1f; 1、什么是分布式 ID&#xff1f; 拿 MySQL 數據庫舉個栗子&#xff1a; 在我們業務數據量不大的時…

spring boot Redis集成—RedisTemplate

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 Spring boot 基于Spring, Redis集成與Spring大同小異。 文章示例代碼均以前篇筆記為基礎增加修改&#xff0c;直接上代碼&#xff1a;…

QtCreator無法編輯源文件

在Qt Creator中新建工程&#xff0c;添加現有C源文件&#xff0c;有的源文件可以編輯&#xff0c;有的源文件編輯不了&#xff0c;發現無法編輯的源文件有一個共同特點&#xff0c;即其中都包含中文&#xff0c;且中文出現亂碼&#xff0c;于是&#xff0c;點擊Qt Creator菜單欄…

Unicode簡介和使用

一、Unicode簡介 在第一章中&#xff0c;我已經預告&#xff0c;C語言中在Microsoft Windows程序設計中扮演著重要角色的任何部分都會講述到&#xff0c;您也許在傳統文字模式程序設計中還尚未遇到過這些問題。寬字符集和Unicode差不多就是這樣的問題。 簡單地說&#xff0c;…

webpack4.x 模塊化淺析-CommonJS

先看下webpack官方文檔中對模塊的描述&#xff1a; 在模塊化編程中&#xff0c;開發者將程序分解成離散功能塊(discrete chunks of functionality)&#xff0c;并稱之為模塊。每個模塊具有比完整程序更小的接觸面&#xff0c;使得校驗、調試、測試輕而易舉。 精心編寫的模塊提供…

設計模式--抽象工廠(個人筆記)

一、抽象工廠的應用場景以及優缺點 1 應用場景&#xff1a; 如果系統需要多套的代碼解決方案&#xff0c;并且每套的代碼解決方案中又有很多相互關聯的產品類型&#xff0c;并且在系統中我們可以相互替換的使用一套產品的時候可以使用該模式&#xff0c;客戶端不需要依賴具體的…

利用阿里云OSS對文件進行存儲,上傳等操作

--pom.xml加入阿里OSS存儲依賴 <!--阿里云OSS存儲--> <dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>2.8.3</version> </dependency> --配置阿里云oss相關常量參數 /…

Java并發編程之ThreadGroup

ThreadGroup是Java提供的一種對線程進行分組管理的手段&#xff0c;可以對所有線程以組為單位進行操作&#xff0c;如設置優先級、守護線程等。 線程組也有父子的概念&#xff0c;如下圖&#xff1a; 線程組的創建 1 public class ThreadGroupCreator {2 3 public static v…

springboot 緩存ehcache的簡單使用

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 步驟&#xff1a; 1. pom文件中加 maven jar包&#xff1a; <!-- ehcache 緩存 --><dependency><groupId>net.sf.eh…

Spring boot + mybatis plus 快速構建項目,生成基本業務操作代碼。

---進行業務建表&#xff0c;這邊根據個人業務分析&#xff0c;不具體操作 --加入mybatis plus pom依賴 <!-- mybatis-plus 3.0.5--> <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId>&l…

給手機瀏覽器減負 輕裝上陣才能速度制勝

隨著手機瀏覽器的發展&#xff0c;瀏覽器已經變得臃腫不堪&#xff0c;各種“功能”系于一身&#xff0c;有廣告、社區、樂園等等&#xff0c;我們真的需要它們嗎&#xff1f;如何才能讓瀏覽器做到輕裝上陣&#xff0c;又能高效滿足我們需求呢&#xff1f; 過多“功能”的瀏覽器…

653. Two Sum IV - Input is a BST

題目來源&#xff1a; 自我感覺難度/真實難度&#xff1a; 題意&#xff1a; 分析&#xff1a; 自己的代碼&#xff1a; class Solution(object):def findTarget(self, root, k):""":type root: TreeNode:type k: int:rtype: bool"""Allself.InO…

解決 dubbo問題:Forbid consumer 192.xx.xx.1 access service com.xx.xx.xx.rpc.api.xx from registry 116.xx1

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 我的情況是&#xff1a; 原本我把服務放在A工程中&#xff0c;后來改到B工程中了&#xff0c;所以原來的服務不存在了&#xff0c;查不…

vue學習:7、路由跳轉

2019獨角獸企業重金招聘Python工程師標準>>> <body><div id"app"></div></body><script type"text/javascript">var Login {template: <div>我是登陸界面</div>};var Register {template: <div…

Spring Retry 重試機制實現及原理

概要 Spring實現了一套重試機制&#xff0c;功能簡單實用。Spring Retry是從Spring Batch獨立出來的一個功能&#xff0c;已經廣泛應用于Spring Batch,Spring Integration, Spring for Apache Hadoop等Spring項目。本文將講述如何使用Spring Retry及其實現原理。 背景 重試&…