最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

C/C++編程筆記:C語言如何實現(xiàn)動態(tài)字符串?簡單動態(tài)庫(源碼)!

2020-06-04 21:39 作者:C語言編程__Plus  | 我要投稿

在C語言中,字符串是以連續(xù)的字節(jié)流表示的,并且以 '\0' 結(jié)尾,C語言標(biāo)準(zhǔn)庫中也提供了很多函數(shù)來操作這種形式的字符串,比如,求字符串長度strlen( ),求子串strstr( ),字符串拷貝strcpy()等等,但是,這些函數(shù)并不安全,很可能給系統(tǒng)或應(yīng)用程序帶來嚴(yán)重的問題,如棧溢出等。


C語言字符串中并沒有記錄操作系統(tǒng)為其分配的長度,用戶必須自己將字符串長度保存在其他的變量中,很明顯如果操作不當(dāng)就會產(chǎn)生錯誤,如臭名昭著的緩沖區(qū)溢出。

其他語言中的字符串類型通常在存儲字符串本身時也保存了字符串長度,如Pascal,這樣做的好處是字符串也可以以空字符'\0'結(jié)尾,但也會產(chǎn)生緩沖區(qū)溢出錯誤,本文實現(xiàn)了一個簡單的動態(tài)字符串庫,首先考慮一下,采用什么樣的數(shù)據(jù)結(jié)構(gòu)可以避免緩沖區(qū)溢出問題呢,為簡化起見,我們定義“字符串”為內(nèi)存中無類型的字節(jié)流,因此可以避開本地化和Unicode等概念,首先定義數(shù)據(jù)結(jié)構(gòu)如下:



pstr 是指向字符串的指針,str_sz 是字符串長度,而 buf_sz則是包含該字符串的緩沖區(qū)長度。

接下來一個問題就是為字符串分配存儲空間,由于內(nèi)存分配可能失效,所以我們需要檢查內(nèi)存分配是否成功,一種可行的方法是在分配函數(shù)中返回錯誤碼,但是,這樣設(shè)計的API不太簡潔實用,另外一個可選方案是事先注冊一個回調(diào)函數(shù),在內(nèi)存分配失敗時再調(diào)用該函數(shù),但如果多個客戶程序同時申請內(nèi)存,該方法也會失效,C++中我們可以使用異常來處理這種情況,但是C不支持異常,所以該方法也不太現(xiàn)實。其實,某些其他的標(biāo)準(zhǔn)庫代碼也有類似的問題,如數(shù)學(xué)庫中某個函數(shù)對一個負(fù)數(shù)進行求根運算,返回結(jié)果本來是double,為了表明函數(shù)調(diào)用出錯,我們可以讓函數(shù)返回NaN(Nota Number),因此程序在需要檢查該函數(shù)調(diào)用是否出錯時可以檢查返回值。

我們也采用與此類似的方法,如果內(nèi)存分配出錯,那么動態(tài)字符串返回NaS(Not a String)狀態(tài),任何返回NaS的操作將維護該狀態(tài),因此程序只需要在必要的時候檢查其返回值,為了實現(xiàn)該效果,我們可以定義如下的宏,


接下來的問題是字符串指針可能指向不同的位置,例如,可以是在編譯時刻就確定的靜態(tài)區(qū),也可以棧中的某個位置,還可以只由malloc或realloc函數(shù)分配動態(tài)內(nèi)存區(qū)(堆區(qū)),只有在堆區(qū)分配的內(nèi)存才能夠被resize,即realloc(),并且需要顯式地free( ),因此我們需要記錄字符串指向區(qū)域的類型,我們選擇了 buf_sz的高位來保存該狀態(tài),基于以上想法,我們?nèi)缦露x內(nèi)存分配函數(shù):


有了以上的函數(shù),我們可以定義如下宏,以便將C風(fēng)格的字符串轉(zhuǎn)換為我們的動態(tài)字符串,


上述代碼中的宏S(C)使用了alloca在棧上分配空間,這意味著該空間不需要顯示的釋放,在函數(shù)退出時將自動被系統(tǒng)回收。

大多數(shù)時候,字符串分配在棧中,但是,有時候我們也需要將字符串保存在生命周期更長的結(jié)構(gòu)中,此時,我們就需要顯式地為字符串分配空間:


當(dāng)然,既然C語言標(biāo)準(zhǔn)庫使用以Null結(jié)尾的字符串,我們需要將動態(tài)字符串轉(zhuǎn)換成C風(fēng)格的字符串,如下:


當(dāng)然,上面的所講的內(nèi)容并沒有完全解決緩沖區(qū)溢出的問題,因此,我們可以定義一下的宏來進行邊界檢查,


接下來的任務(wù)是向動態(tài)字符串中追加新的C類型的字符串,


最后容易出現(xiàn)緩沖區(qū)溢出情況是格式化輸入,由于不知道輸入串長度,所以使用sprintf( ) 函數(shù)也比較容易出錯(本地化),snprintf( ) 能夠解決該問題,但是輸出緩沖區(qū)太小了,很容易被截斷,


最后,我們經(jīng)常在棧中分配格式化字符,以下函數(shù)可以將結(jié)果打印至屏幕會文件,


至此,動態(tài)字符串的大部分API已經(jīng)介紹完畢,使用上面所講的函數(shù)和宏將會大大減少緩沖區(qū)溢出的危險,因此推薦各位同學(xué)在實際需要中使用上述的函數(shù)和宏。(完)

學(xué)習(xí)C/C++編程知識,提升C/C++編程能力,歡迎關(guān)注UP一起來成長!

另外,UP在主頁上傳了一些學(xué)習(xí)C/C++編程的視頻教程,有興趣或者正在學(xué)習(xí)的小伙伴一定要去看一看哦!會對你有幫助的~

C/C++編程筆記:C語言如何實現(xiàn)動態(tài)字符串?簡單動態(tài)庫(源碼)!的評論 (共 條)

分享到微博請遵守國家法律
水富县| 邵东县| 拉萨市| 嘉荫县| 衢州市| 土默特右旗| 门头沟区| 思茅市| 汝南县| 韶关市| 岑溪市| 仁怀市| 凤阳县| 尚志市| 定陶县| 威海市| 江阴市| 大城县| 台北市| 桂东县| 鹰潭市| 三河市| 广汉市| 准格尔旗| 海口市| 福安市| 长子县| 永兴县| 奉化市| 曲周县| 石狮市| 禄劝| 洞头县| 句容市| 澄城县| 黄浦区| 托里县| 乡宁县| 兰溪市| 思南县| 佛坪县|