如何删除字符串尾部指定個數的字符呢?我們還是以字符串”abc efg hijk lmn”為例,删除尾部4個字符串,得到新的字符串内容為”abc efg hijk”。我們通過觀察删除字符的操作前後字符在内存中的存儲情況有什麼區别。下面圖1表示删除之前的字符存儲情況,圖2表示删除之後的狀态,紅色标示的字符為待删除的内容
圖1
圖2
比較圖1和圖2中的數據,圖2中的紅色内容被“删除”了,或者說是新的字符串已經不再包含所有12-15中的字符。如何讓這個新字符串不再包含這些内容呢?根據字符串可以視為一系列内存中的字符,直到含有一個特殊字符’\0’,即表示這個字符串結束了。也就是說在将字符串結束符’\0’設置在特定位置就可以改變這個字符串的長度,我們再以上面的例子進行說明,删除字符串末尾的後4個字符
圖3
圖3中綠色單元格所對應的内存位置之前所有的數據就是我們删除尾部4個字符後想要的結果,在這個圖3中可以清晰地看到,删除字符串末尾4個字符,實際執行的操作就是将字符串末尾倒數第4個位置的字符值設置為字符串終止符’\0’,這樣做的話,’\0’字符之後的内容與這個字符串已經沒有關系了。
圖4
圖4中的代碼第53行創建一個變量lenOfSt,表示字符串st的原始長度,現在需要删除字符串末尾4個字符(最右端字符” lmn”),通過第54行代碼16 – 4計算出字符串終止符’\0’相對字符串起始地址的偏移量為12,那麼st[12]就是字符’\0’的新位置,圖3中綠色單元格所對應的内存位置,之後将這個地址所對應的内存單元設置為’\0’字符,完成字符串尾部删除4個字符的功能。
和其它内置類型的*操作符相比,字符串也可以定義類似的功能,但需要重新定義下它的含義為一個字符串的重複拼接操作。比如字符串“Oh, yeah! ”,這個字符串的長度為10,最後一位字符為空格,重複4次進行拼接後,其結果為“Oh, yeah! Oh, yeah! Oh, yeah! Oh, yeah! ”新生成的字符串長度變為了40。代碼其實是通過字符串拼接和循環語句就可以實現,重複的次數就是要拼接原字符串的個數,比如本例中重複次數為4,每一次循環操作都是從原字符串的第一個字符開始,直到最後一個字符。代碼實現為:
圖5
圖5第57行代碼初始化一個字符串ts,長度為10,第58行代碼定義了存放新生成的字符串的字符數組,數組大小為41。即4個長度為10的字符串占用的空間大小為40,還有一個存儲字符串終止符’\0’的1個位置,因此整個存放生成的新的重複字符串的數組大小為41。
代碼第60行代碼初始化字符指針pts4指向ts4數組的首地址,第61-69行代碼為整個for循環語句,它是一個兩層嵌套循環語句:外層循環語句控制重複字符串的次數,内層循環實現對原字符串從0至最後一個字符的複制功能。
本例中需要注意的地方在于兩個指針pts4和pts的初始化位置,pts4指針的初始化對應第60行代碼,位于外層循環語句之外,但遞增的位置在第67行,也就是說,在整個循環中pts4的指針是一直處于遞增狀态;但是對于指針pts來說,它的初始化位置是在第65行,位于外層循環語句體内,即每一次外層循環就會将指針pts設置為ts字符串的首地址,在内層循環中複制内容時pts都是從字符串ts的首地址開始,直至遇到’\0’便終止内層循環,内層循環執行完畢一次,就會複制一個字符串ts到目标ts4地址内存中。
字符串分割操作是指将字符串按照指定的字符分割為多個字符串。以字符串“abc efg hijk lmn”為例,采用空格字符進行分割後,形成4個字符串“abc”,”efg”,”hijk”和”lmn”。我們還是通過字符在内存中的存儲狀态來分析如何對字符串進分割,原始字符串在内存中的表示為:
圖6
圖6為原始字符串在内存中的表示方式,一共含有16個字符和一個字符串終止符’\0’,如果将原始字符串采用空格字符進行分割,那麼将會得到如下圖所示的4個字符串:
圖7
圖7中連續的綠色單元格所表示的為一個分割後的獨立字符串,即采用空格分割後,我們可以得到4個對應的字符串,這隻是分析後所期望得到的結果。而實際上,我們如何将這些綠色單元格中的數據表示為一個合法的字符串呢?結合字符串定義,他首先需要一個内存中的起始地址,之後還需要一個字符串終止符’\0’。結合本實例來說的話,第一個字符串”abc”的首地址就是字符’a’所對應的地址,字符’c’之後的空格的位置上設置為字符串終止符’\0’就可以正确的表示第一個字符串“abc”了。依照此方法,同樣可以表示出第二個”efg”和”hijl”字符串,而最後一個字符串隻需要表示出它的’l’字符所對應的地址就可以了,原字符串的終止符就是新生成的最後一個字符串”lmn”的終止符。整個構建完成之後,各個字符在内存中的表示變為了下圖所示
圖8
如何通過代碼實現呢?分為兩個步驟進行操作,第一個步驟是先将原字符串中的空格字符轉換為字符串終止符’\0’,第二個步驟是獲取每一個字符串的首地址,輸出其對應的字符串即可。第一個步驟隻需要使用一個循環語句,依次訪問字符串中的每一個字符,判斷這個字符是否為空格,如果為空格,直接将這個位置的字符設置為字符’\0’,如下代碼所示
圖9
執行完空格字符轉為終止字符之後,原來的字符串在内存中的存儲方式變為了圖8所示的狀态,接下來需要輸出這些字符串内容。因為現在内存中存在多個字符串,無法使用數組首地址spt變量輸出全部字符串,spt變量現在隻表示一個字符串”abc”,因此,在輸出對應的字符串時,需要計算出每個字符串的首地址在哪裡。
圖10
在計算每一個字符串的首地址時,我們首先限定了字符串首地址查詢地址的範圍,即首地址為spt數組的首地址,最大地址為spt sizeof(spt)所對應的地址,即原字符串中’\0’字符所存在的地址。之前我們介紹過sizeof操作符的用法,但是,它的操作數為數組名稱還是第一次使用,它的含義是計算這個數組的大小,對于圖9中第91行代碼的用法,其對應的代碼可以視為:
char spt[] = {‘a’,’b’,’c’,’ ‘,’e’,’f’,’g’,’ ‘, ‘h’, ‘I’, ‘j’, ‘k’, ‘ ‘, ‘l’, ‘m’, ‘n’, ‘\0’};
sizeof(spt)的數值為17,這個值比字符串spt的長度值大1(多出一個字符’\0’的位置)。
設置了字符串地址的範圍之後,我們需要給出這個字符串對應的首地址是什麼以及這個字符串在什麼情況下進行輸出。對于字符串首地址問題,圖10中的代碼中第103行,将word字符指針指向了pspt指針,此時pspt指針指向pst數組的首地址,也就是說word指針指向了pst字符串的首地址,代碼中第107行,表示的是更新word指針指向的内容,更新的前提條件為第105行代碼中*pspt為’\0’字符時,即pspt指向一個字符串終止符’\0’時,才會更新word指針的内容,再次之前的前一句代碼第106行輸出了當前word指針所指向的内容,執行完第107行代碼後,word的指針變為了新的字符串對應的首地址。代碼104-110代碼循環執行完成之後便可以輸出所有的分割後的字符串。
至此為止,我們已經實現了字符串幾個常用的操作,每一個操作的基本思路就是分析原字符串和對應的目标字符串,找出從原字符串到目标字符串轉換的方法,通過操作内存中的數據即可。C語言标準庫中提供了更為廣泛的字符串操作函數,比如strlen可以計算字符串長度,strcat可以進行字符串拼接操作等,實際項目中盡可能的采用C語言标準庫中已有的函數,可以保證代碼的質量和效率,本文中實現的字符串操作功能主要是為了,在C語言标準庫中沒有對應的函數可以解決問題時,我們應該如何通過自己的分析去解決字符串問題,從而實現自己想要的字符串操作功能。
,更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!