亚洲免费av电影一区二区三区,日韩爱爱视频,51精品视频一区二区三区,91视频爱爱,日韩欧美在线播放视频,中文字幕少妇AV,亚洲电影中文字幕,久久久久亚洲av成人网址,久久综合视频网站,国产在线不卡免费播放

        ?

        淺談C語(yǔ)言字符串格式化

        2012-08-18 02:00:34彭秋生
        關(guān)鍵詞:格式化字符串調(diào)用

        雷 金, 彭秋生

        (湖南環(huán)境生物職業(yè)技術(shù)學(xué)院護(hù)理學(xué)院,湖南衡陽(yáng)421005)

        談起C語(yǔ)言,稍懂程序設(shè)計(jì)的人都不陌生.因?yàn)樵诒姸喑绦蛟O(shè)計(jì)語(yǔ)言中,C語(yǔ)言是基礎(chǔ).它功能強(qiáng)大,效率高,是目前眾多計(jì)算機(jī)語(yǔ)言中舉世公認(rèn)的優(yōu)秀的結(jié)構(gòu)程序設(shè)計(jì)語(yǔ)言之一.它既可以作為工作系統(tǒng)設(shè)計(jì)語(yǔ)言,編寫(xiě)系統(tǒng)應(yīng)用程序,如unix操作系統(tǒng);也可以作為應(yīng)用程序設(shè)計(jì)語(yǔ)言,編寫(xiě)不依賴計(jì)算機(jī)硬件的應(yīng)用程序.因此,它的應(yīng)用范圍廣泛,不僅僅是在軟件開(kāi)發(fā)上,而且各類科研都需要用到C語(yǔ)言.

        C語(yǔ)言的數(shù)據(jù)類型豐富,但基本的數(shù)據(jù)類型很少,僅僅包括:整型、浮點(diǎn)型和字符型等.對(duì)字符型數(shù)據(jù)的處理主要集中在字符型數(shù)組,也就是字符串的操作上.實(shí)際上,在普通的程序設(shè)計(jì)中,絕大部分的程序代碼都是在對(duì)字符串進(jìn)行處理,只有少數(shù)的程序代碼是對(duì)整數(shù)和單(雙)精度數(shù)據(jù)進(jìn)行操作.況且,如果沒(méi)有專門(mén)設(shè)計(jì)的處理器和系統(tǒng),大數(shù)值和高精度的數(shù)值計(jì)算也只有依靠字符串才能達(dá)到要求.因?yàn)檎秃透↑c(diǎn)型變量的最大值和精度都是有限的,只有字符串變量的長(zhǎng)度才是接近無(wú)限的(只要內(nèi)存足夠).由此可見(jiàn),高效的字符串處理和操作顯得尤其重要.

        C語(yǔ)言提供了大量的字符串操作函數(shù).在普通的教學(xué)過(guò)程中,介紹得最多的通常是字符串拷貝strcpy、字符串追加strcat,字符串比較strcmp,求字符串長(zhǎng)度strlen等函數(shù).但這幾個(gè)函數(shù)遠(yuǎn)遠(yuǎn)無(wú)法滿足我們的字符串處理要求.比如:我們需要一個(gè)20位的定長(zhǎng)序號(hào),使用上述函數(shù)的一個(gè)較為常見(jiàn)的實(shí)現(xiàn)如下:

        顯然,對(duì)于這類問(wèn)題,上述幾個(gè)函數(shù)處理起來(lái)顯得有點(diǎn)麻煩,但是這類問(wèn)題又具有普通性.這個(gè)時(shí)候,字符串格式化函數(shù)處理起來(lái)就方便得多.

        1 字符串格式化輸出

        最常見(jiàn)的是格式化輸出函數(shù)printf,但它是將數(shù)據(jù)格式化輸出到標(biāo)準(zhǔn)輸出設(shè)備,一般是顯示器.而大多數(shù)情況下,我們并不需要輸出到顯示設(shè)備,而是輸出到某一個(gè)指定的字符串變量.有沒(méi)有一個(gè)將數(shù)據(jù)格式化后輸入到字符串變量的函數(shù)呢?答案是肯定的.sprintf函數(shù)就能滿足我們的要求,它的用法和返回值與printf幾乎一模一樣,只是比后者多了一個(gè)字符串指針參數(shù).對(duì)兩個(gè)函數(shù)的原型進(jìn)行比較就很容易看出這一點(diǎn):

        相比改進(jìn)前的函數(shù),這次的代碼要簡(jiǎn)潔多了.事實(shí)上,除了printf和sprintf外,還有好幾個(gè)其它功能類似的函數(shù),如:?fprintf、snprintf、vsnprintf?、vprintf、vsprintf、vfprintf等,這類函數(shù)統(tǒng)稱為 printf類函數(shù),屬于格式化輸入輸出的一部分,均定義在頭文件 stdio.h中.

        sprintf函數(shù)功能強(qiáng)大,很多情況下可以用它來(lái)達(dá)到與 strcpy,strcat,strlen 同樣的效果.如:

        ① int nlength=sprintf(strDest,"%s",strSrc)

        將字符串strSrc拷貝至strDest,同時(shí)返回所拷貝字符串的長(zhǎng)度.顯然,這里既實(shí)現(xiàn)了數(shù)據(jù)拷貝,同時(shí)又返回出了字符串的長(zhǎng)度.

        ② int nlength = sprintf(strDest,"%s%s",strDest,strSrc)

        將字符串strDest和strSrc合并后,再賦給strD-est,效果與 strcat(strDest,strSrc)一致.

        函數(shù)sprintf的功能當(dāng)然不限于此,前文提到它與printf的功能幾乎是一樣的,唯一的區(qū)別就是sprintf將數(shù)據(jù)格式化后將結(jié)果賦給指定字符串變量.但是功能強(qiáng)大是以犧牲效率為代價(jià)的,sprintf功能強(qiáng)大,但效率卻與strcpy,strcat,strlen相差甚遠(yuǎn).

        2 sprintf工作原理及可變參數(shù)

        有時(shí)候不得不承認(rèn),printf類函數(shù)功能的確很強(qiáng)大.不僅能自動(dòng)識(shí)別格式化串format,還能自動(dòng)判斷參數(shù)的個(gè)數(shù)和類型.前者我們暫不討論,對(duì)于后者,說(shuō)起來(lái)其實(shí)一點(diǎn)也不神秘,就是C語(yǔ)言的可變參數(shù)在起作用.我們簡(jiǎn)單的來(lái)實(shí)現(xiàn)一下 sprintf函數(shù),如下:

        參數(shù) str,format稱為固定參數(shù),后面的“...”稱為可變參數(shù),在實(shí)際函數(shù)調(diào)用時(shí),可以用0個(gè)或多個(gè)實(shí)際參數(shù)來(lái)替換它.sprintf對(duì)于可變參數(shù)的處理流程采用了C語(yǔ)言中最通用的模式,如下:

        ①定義一個(gè)va_list變量ap,用來(lái)作為指向可變參數(shù)列表的指針.

        ②調(diào)用va_start宏初始化剛定義的va_list變量ap,使ap指向可變參數(shù)列表中第一個(gè)可變參數(shù)的地址.va_start宏的第二個(gè)參數(shù)必須是最后一個(gè)固定參數(shù)(非可變參數(shù))的地址,這里為format.

        ③調(diào)用vsprintf函數(shù)將可變參數(shù)按format格式化后,賦給str變量.

        ④最后調(diào)用va_end宏結(jié)束可變參數(shù)的獲取,釋放指針ap,使它不再指向參數(shù)列表.

        實(shí)際上,與C語(yǔ)言中用來(lái)可變參數(shù)相關(guān)的還有一個(gè)宏va_arg(ap,type),它的作用是獲取ap所指向的可變參數(shù)的值,并將它強(qiáng)制轉(zhuǎn)換為type類型后作為返回值返回,同時(shí)移動(dòng)指針ap指向下一個(gè)可變參數(shù)的地址,以便后續(xù)處理.在大多數(shù)處理程序中,需要循環(huán)調(diào)用va_arg來(lái)獲取可變參數(shù)的值,以便進(jìn)行相應(yīng)的處理,只是sprintf函數(shù)將這個(gè)處理過(guò)程放在了vsprintf函數(shù)中.顯然,vsprintf是sprintf的核心所在,sprintf僅僅是vsprintf封裝好的一個(gè)對(duì)外接口函數(shù),了解vsprintf的工作原理就顯得很重要.函數(shù)vsprintf原型如下:

        int vsprintf(char*str,const char*format,va_list arg);

        函數(shù)vsprintf實(shí)現(xiàn)起來(lái)比較復(fù)雜,這也是影響sprintf效率的原因之一.為了提高工作效率,vsprintf并不是在將所有可變參數(shù)arg取出,按格式化串format所規(guī)定的格式進(jìn)行組裝后,一次性將結(jié)果寫(xiě)入目標(biāo)串str,而是在對(duì)format串解析過(guò)程中,逐步取出可變參數(shù)值,將格式化的結(jié)果同步寫(xiě)入目標(biāo)串str.也就是說(shuō),函數(shù)vsprintf是一邊解析格式化串format,一邊將格式化結(jié)果寫(xiě)入目標(biāo)串的.這一點(diǎn)很重要,它決定了在sprintf函數(shù)中,除了第一個(gè)可變參數(shù)外,其它可變參數(shù)決不能與目標(biāo)參數(shù)相同,否則,會(huì)引起意想不到的結(jié)果.下面這種寫(xiě)法是錯(cuò)誤的:

        sprintf(strDest,"%s%s",strSrc,strDest)

        這樣的語(yǔ)句會(huì)產(chǎn)生什么樣的結(jié)果呢?sprintf先將strSrc的值寫(xiě)入目標(biāo)參數(shù)strDest,然后從最末參數(shù)strDest所指向的地址開(kāi)始取值追加到目標(biāo)參數(shù)strDest的后部,但此時(shí),strDest指向的內(nèi)容已被改變成了strSrc的值,因此strDest中會(huì)重復(fù)出現(xiàn)strSrc的值,這顯然不是我們想要的結(jié)果.

        我們用下面的代碼來(lái)驗(yàn)證一下:

        這段程序輸出的結(jié)果是:strDest=[world,world,world],很好地驗(yàn)證了我們的結(jié)論.

        3 構(gòu)造格式化輸出函數(shù)

        了解了sprintf函數(shù)的工作原理后,我們就可以構(gòu)造自己的格式化輸出函數(shù).

        首先看看spinrtf函數(shù)有什么地方可以改進(jìn)!我們發(fā)現(xiàn)strcpy,strcat等函數(shù)的返回值并不是整數(shù),而是一個(gè)指向目標(biāo)串的指針.這樣做的目的是為了便于函數(shù)的連續(xù)調(diào)用,如:

        strcpy(strDest,strcat(strSrc1,strSrc2));

        多個(gè)操作在同一條語(yǔ)句中完成,簡(jiǎn)潔又高效.對(duì)sprintf函數(shù)來(lái)說(shuō),這個(gè)特性是很容易滿足的,對(duì)它進(jìn)行稍微改進(jìn)就可以了.改造后函數(shù)如下:

        參數(shù)len是為了不丟棄原有返回值,特將其放入函數(shù)參數(shù)中返回的.但更多的時(shí)候,格式化后字符串的長(zhǎng)度并不受人關(guān)注,為了簡(jiǎn)化函數(shù)原型,方便函數(shù)調(diào)用,可以將字符串長(zhǎng)度參數(shù)去掉.去掉長(zhǎng)度參數(shù)的函數(shù)如下:

        若有時(shí)確實(shí)需要用到格式化后字符串的長(zhǎng)度,也可以采用如下方式獲取:

        strlen(mystr(strDest,format,para1,para2,…));

        改前文提到sprintf函數(shù)屬于格式化輸入輸出類的函數(shù),性能上不能與strcpy等同日而語(yǔ).因此,在系統(tǒng)核心模塊中,應(yīng)該避免多次使用sprintf,否則,可能會(huì)影響系統(tǒng)的系統(tǒng),形成系統(tǒng)瓶頸.很多系統(tǒng)提供的公共函數(shù)中一般不帶可變參數(shù),而是直接提供字符串形式的參數(shù).如:日志打印函數(shù) ErrLogPrt,假設(shè)原型如下:

        void LogPrt(const char* sErrMsg);

        對(duì)于疊加在系統(tǒng)上的某一個(gè)具體的應(yīng)用程序而言,性能上沒(méi)有核心模塊這么嚴(yán)格的要求.而且,當(dāng)程序出錯(cuò),我們希望日志越多、越清晰更好,更好能夠?qū)⑴c出錯(cuò)有關(guān)的信息全部打印出來(lái),如出錯(cuò)源文件名,源代碼行,以及相關(guān)的變量值等.當(dāng)然使用mystr可以做到這一點(diǎn),如下:

        char sErrMsg[2048];

        memset(sErrMsg,0,sizeof(sErrMsg));/* 初始化字符串*/

        mystr(sErrMsg,"查詢數(shù)據(jù)庫(kù)出錯(cuò),文件:%s,行號(hào):%ld,查詢序號(hào):%s,名稱:%s",

        __FILE__,__LINE__,nIndex,sName);

        LogPrt(sErrMsg);

        顯然,每次打印一個(gè)日志都要寫(xiě)多行代碼,顯得有些煩瑣.既然mystr能夠?qū)⒛繕?biāo)串的地址返回,為什么不直接使用返回值!我們改造一下:

        char sErrMsg[2048];

        memset(sErrMsg,0,sizeof(sErrMsg));

        LogPrt(mystr(sErrMsg,"查詢數(shù)據(jù)庫(kù)出錯(cuò),文件:%s,行號(hào):%ld,查詢序號(hào):%s,名稱:%s",

        __FILE__,__LINE__,nIndex,sName);

        代碼減少了一行,但改善程度極其有限,如果能再將sErrMsg變量去掉就好了,因?yàn)樗谶@里沒(méi)有起多少作用.那么,可以再將 mystr函數(shù)改進(jìn)一下:

        C語(yǔ)言函數(shù)內(nèi)部的局部變量,只在函數(shù)內(nèi)部起作用,在調(diào)用完函數(shù)后,其占用空間會(huì)自動(dòng)釋放,格式化后字符串的值無(wú)法獲取.因此,mystr函數(shù)內(nèi)部采用靜態(tài)局部變量,使其在整個(gè)應(yīng)用程序運(yùn)行過(guò)程中一直有效.

        除了返回值外,現(xiàn)在的函數(shù)跟printf函數(shù)用法完全一樣了.任何接解C語(yǔ)言的人,只要知道printf的用法,也就知道m(xù)ystr的用法.好了,現(xiàn)在的函數(shù)調(diào)用起來(lái)方便多了,一條語(yǔ)句就可以實(shí)現(xiàn)日志打印,如下:

        LogPrt(mystr("查詢數(shù)據(jù)庫(kù)出錯(cuò),文件:%s,行號(hào):%ld,查詢序號(hào):%s,名稱:%s",

        __FILE__,__LINE__,nIndex,sName);實(shí)際上,還可以通過(guò)宏定義的方式,將函數(shù)進(jìn)行進(jìn)一步封裝,放在頭文件中,以供其它源文件共用.也可以通過(guò)單獨(dú)編譯成函數(shù)庫(kù)的方式,源代碼可以直接調(diào)用該函數(shù),編譯時(shí)只需將庫(kù)鏈接過(guò)來(lái)即可.

        4 總結(jié)

        本文首先描述了格式式化輸出函數(shù)sprintf的用法,其次對(duì)該函數(shù)的實(shí)現(xiàn)原理和C語(yǔ)言可變參數(shù)的工作原理進(jìn)行了較為詳細(xì)的闡述,并在此基礎(chǔ)上,根據(jù)sprintf函數(shù)的工作原理構(gòu)造了一個(gè)方便通用的格式化輸出函數(shù)mystr.該函數(shù)的用法與大家熟悉的printf用法一致,非常容易掌握,為數(shù)據(jù)數(shù)據(jù)格式化操作提供了一條便捷有效的處理途徑.

        [1] 譚浩強(qiáng).C語(yǔ)言程序設(shè)計(jì)[M]北京:清華大學(xué)出版社,2010.

        [2] Eric Huss.The C Library Reference Guide.http://www.acm.uiuc.edu/webmonkeys/book/c_guide/.

        [3] c語(yǔ)言可變參數(shù)(va_start,va_end)(轉(zhuǎn)載)http://www.360doc.com/content/07/0423/16/3630_462811.shtml.

        猜你喜歡
        格式化字符串調(diào)用
        現(xiàn)代人守則:昏死之前請(qǐng)把手機(jī)格式化
        核電項(xiàng)目物項(xiàng)調(diào)用管理的應(yīng)用研究
        LabWindows/CVI下基于ActiveX技術(shù)的Excel調(diào)用
        基于系統(tǒng)調(diào)用的惡意軟件檢測(cè)技術(shù)研究
        格式化
        詩(shī)林(2016年5期)2016-10-25 07:51:39
        一種新的基于對(duì)稱性的字符串相似性處理算法
        利用RFC技術(shù)實(shí)現(xiàn)SAP系統(tǒng)接口通信
        依據(jù)字符串匹配的中文分詞模型研究
        一種針對(duì)Java中字符串的內(nèi)存管理方案
        国产丝袜在线福利观看| 久久天堂av综合合色| 日韩精品视频一区二区三区| 亚洲美国产亚洲av| 成人爽a毛片一区二区免费| 久久久精品电影| 日韩一级精品亚洲一区二区精品| 国产极品裸体av在线激情网| 精品视频一区二区三区在线观看| 无码丰满熟妇一区二区| 大肉大捧一进一出好爽视色大师| 免费人成年小说在线观看| 色欲国产精品一区成人精品| 无遮高潮国产免费观看韩国| 国产专区亚洲专区久久| 青青草在线免费视频播放| 亚洲春色在线视频| 日本一本久道| 日韩精品免费一区二区中文字幕 | 亚洲国产精品自拍成人| 久久久久成人精品无码中文字幕 | 日韩亚洲中文图片小说| 青青草视频国产在线观看 | 国产高清av在线播放| 骚片av蜜桃精品一区| 中文字幕无码人妻丝袜| 中文字幕人成乱码中文| 久久免费看的少妇一级特黄片 | 国产精品久久久久免费a∨不卡| 日韩精品成人一区二区在线观看| 久久精品国产亚洲av网站| 大ji巴好深好爽又大又粗视频| 欧美精品偷自拍另类在线观看| 国产在线观看精品一区二区三区| 偷拍视频这里只有精品| 精品人妻一区二区三区浪人在线| 色五月丁香五月综合五月4438| 免费黄色福利| 日本高清一区二区三区不卡| 亚洲熟女精品中文字幕| 亚洲精品午夜无码电影网|