0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

周立功《程序設(shè)計(jì)與數(shù)據(jù)結(jié)構(gòu)》:字符串函數(shù)

AGk5_ZLG_zhiyua ? 來源:未知 ? 作者:電子大兵 ? 2017-09-05 09:18 ? 次閱讀

本文為程序設(shè)計(jì)基礎(chǔ),本文為1.8.2 字符串常量第三點(diǎn):字符串函數(shù)。

>>>>

1.字符串函數(shù)

標(biāo)準(zhǔn)C提供了一個(gè)操作字符串的接口string.h,其中的很多函數(shù)是有特殊用途的,下面將詳細(xì)介紹通過string.h導(dǎo)出的最重要的函數(shù)原型。

strlen()函數(shù)

strlen()函數(shù)用于統(tǒng)計(jì)字符串的長度,其函數(shù)原型如下:

size_t strlen(const char *s);

//前置條件:s是一個(gè)以null結(jié)尾的字符串

//后置條件:返回值為s中的字符個(gè)數(shù)(不包括null字符)

下面的函數(shù)可以縮短字符串的長度,其中用到了strlen()。即:

1 void fit(char *string, unsigned int size)

2 {

3 if(strlen(string) > size)

4 strlen[size] = '\0';

5 }

由于該函數(shù)要改變字符串,因此函數(shù)在聲明形參string時(shí)沒有使用const限定符。當(dāng)然,也可以調(diào)用strlen(s)確定字符串s的長度,或用if語句比較兩個(gè)字符串是否相等。即:

if(strcmp(s1, s2) == 0) …

strcat()函數(shù)

用于拼接字符串的strcat()函數(shù)接受兩個(gè)字符串作為參數(shù),其函數(shù)原型如下:

char *strcat(char *s1, char const *s2);

//前置條件:s2是一個(gè)以null結(jié)尾的字符串,s1數(shù)組的末尾還有足夠的空間容納s2的一個(gè)副本

//后置條件:s2被連接到s1中,且返回值是一個(gè)指針,該指針指向s1數(shù)組的第一個(gè)字符

該函數(shù)將第2個(gè)字符串的備份附加在第1個(gè)字符串末尾,s2字符串的第1個(gè)字符將覆蓋s1字符串末尾的空字符,并將拼接后的新字符串作為第1個(gè)字符串返回,第2個(gè)字符串不變。strcat()函數(shù)的類型是char *(即指向char的指針),strcat()函數(shù)返回第1個(gè)參數(shù),即拼接第2個(gè)字符串后的第1個(gè)字符串的地址。

由于strcat()函數(shù)無法檢查第1個(gè)數(shù)組是否能夠容納第2個(gè)字符串,如果分配給第1個(gè)數(shù)組的空間不夠大,那么多出來的字符溢出到相鄰存儲單元時(shí)就會出問題,當(dāng)然也可以用strlen()查看第1個(gè)數(shù)組的長度。注意,要給拼接后的字符串長度加1才夠空間存放末尾的空字符?;蛘哂胹trncat(),該函數(shù)的第3個(gè)參數(shù)指定了添加的最大字符數(shù),其函數(shù)原型如下:

char *strncat(char *s1, char const *s2, size_t n);

該函數(shù)將s2字符串中的n個(gè)字符拷貝到s1字符串末尾,s2字符串中的第1個(gè)字符將覆蓋s1字符串末尾的空字符。不會拷貝s2字符串中的空字符和其后的字符,并在拷貝字符的末尾添加一個(gè)空字符,該函數(shù)返回s1。

strcmp()函數(shù)和strncmp()函數(shù)

strcmp()函數(shù)要比較的是字符串的內(nèi)容,不是字符串的地址,其函數(shù)原型如下:

int strcmp(char const *s1, char const *s2);

//前置條件:s1和s2都是以null結(jié)尾的字符串

//后置條件:返回值為0,表示s1=s2;

// 返回值小于0,表示s1在詞典順序上位于s2之前;

// 返回值大于0,表示s1在詞典順序上位于s2之后

如果s1字符串在機(jī)器排序序列中位于s2字符串的后面,該函數(shù)返回一個(gè)正數(shù);如果兩個(gè)字符串相等,則返回0;如果s1字符串在機(jī)器排序序列中位于s2字符串的前面,則返回一個(gè)負(fù)數(shù)。strcmp()函數(shù)比較的是字符串("hello")不是字符('q'),所以其參數(shù)應(yīng)該是字符串。由于char的類型實(shí)際上是整數(shù)類型,因此可以使用關(guān)系運(yùn)算符比較字符。如果兩個(gè)字符串開始的幾個(gè)字符都相同會怎樣?strcmp()會依次比較每個(gè)字符,直到發(fā)現(xiàn)第1對不同的字符為止,然后返回相應(yīng)的值。比如,"apples"和"apple"只有最后一對字符不一樣("apples"的s和"apple"的空字符),由于空字符在ASCII中排第1,字符s一定在它后面,所以strcmp()返回一個(gè)正數(shù)。

最后一個(gè)例子,strcmp()比較所有的字符,不只是字母。與其說該函數(shù)按字母順序進(jìn)行比較,還不如說是按機(jī)器排序序列進(jìn)行比較,即根據(jù)字符的數(shù)值(ASCII值)進(jìn)行比較,在ASCII中,大寫字母在小寫字母前面,因此strcmp("Z", "a")返回的是負(fù)值。

在大多數(shù)情況下,strcmp()返回的具體值并不重要,只在意該值是0還是非0,即比較兩個(gè)值是否相等,或按字母排序字符串,此時(shí)需要知道比較的結(jié)果是正、負(fù)或0。假設(shè)word是存儲在char類型數(shù)組中的字符串,ch是char類型的變量。即:

if(strcmp(word, "hello") == 0) puts("bye")

if(ch == 'q' ) puts("bye")

盡管如此,不要使用ch或'q'作為strcmp()的參數(shù)。

strcmp()比較兩個(gè)字符串中的字符,直到發(fā)現(xiàn)不同的字符為止,這一過程可能會持續(xù)到字符串的末尾。而strcmp()在比較兩個(gè)字符串時(shí),可以比較字符不同的地方,也可以只比較第3個(gè)參數(shù)指定的字符數(shù)。其函數(shù)原型如下:

int strncmp(char const *s1, char const *s2, size_t n);

strcpy()函數(shù)

strcpy()函數(shù)有兩個(gè)屬性,第一,strcpy()的返回值類型為char *,該函數(shù)返回的是第1個(gè)參數(shù)的值,即一個(gè)字符的地址。第二,第1個(gè)參數(shù)不必指向數(shù)組的開始,這個(gè)屬性可用于拷貝數(shù)組的一部分。注意,strcpy()將源字符串中的空字符也拷貝在內(nèi)。

如果pts1和pts2都是指向字符串的指針,那么下面語句拷貝的是字符串的地址,而不是字符串本身。即:

pts2 = pts1;

如果希望拷貝整個(gè)字符串,可以使用strcpy()函數(shù)。其函數(shù)原型如下:

char *strcpy(char *s1, char const *s2);

//前置條件:s2是一個(gè)以null結(jié)尾的字符串,s1數(shù)組有足夠的空間容納s2的一個(gè)副本

//后置條件:s2被復(fù)制到s1,且返回值是一個(gè)指針,該指針指向s1數(shù)組的第一個(gè)字符

該函數(shù)將s2指向的字符串(包括空字符)拷貝至s1指向的位置,返回s1。即strcpy()接受2個(gè)字符串指針作為參數(shù),可以將指向源字符串的第2個(gè)指針聲明為指針、數(shù)組名或字符串常量,而指向源字符串副本的第1個(gè)指針應(yīng)指向一個(gè)數(shù)據(jù)對象,比如,數(shù)組,且對象要有足夠的空間存儲字符串的副本,通常將拷貝出來的字符串稱為目標(biāo)字符串。注意,聲明數(shù)組將分配存儲數(shù)據(jù)的空間,而聲明指針只分配存儲一個(gè)地址的空間。

strncpy()函數(shù)

strcpy()和strcat()都有同樣的問題,它們不能檢查目標(biāo)空間是否能容納源字符串的副本,因此拷貝字符串使用strncpy()更安全,該函數(shù)的第3個(gè)參數(shù)指明可拷貝的最大字符數(shù)。其函數(shù)原型如下:

char *strncpy(char *s1, char const *s2, size_t n);

該函數(shù)將s2指向的字符串拷貝至s1指向的位置,拷貝的字符不超過n,其返回值為s1。該函數(shù)不會拷貝空字符后面的字符,如果源字符串中的字符數(shù)少于n,則目標(biāo)字符串就以拷貝的空字符結(jié)尾。如果源字符串有n個(gè)或超過n個(gè)字符,就不拷貝空字符,所以拷貝的副本中不一定有空字符?;诖耍话銜設(shè)置比目標(biāo)數(shù)組大小少1,然后將數(shù)組最后一個(gè)元素設(shè)置為空字符。

這樣做的目的將確保存儲的是一個(gè)字符串,如果目標(biāo)空間能夠容納源字符串的副本,那么從源字符串拷貝的空字符便是該副本的結(jié)尾;如果目標(biāo)空間裝不下副本,則將副本最后一個(gè)元素設(shè)置為空字符。

盡管C語言允許將字符串作為一個(gè)字符數(shù)組或一個(gè)指向字符的指針,但是從更抽象的角度理解字符串將會更有意義。如果你想訪問字符串中的單個(gè)字符,則需要注意它的表現(xiàn)形式。如果將字符串當(dāng)作一個(gè)整體來看待的話,那么就可以忽略其表現(xiàn)的細(xì)節(jié),而寫出更容易理解的程序。比如:

typedef char *striing;

其目的是強(qiáng)調(diào)字符串是一個(gè)在概念上完全不同的類型,雖然string與char *類型完全相同,但它們傳遞的信息卻是不同的。如果將一個(gè)變量定義為char *類型,其底層的表示方法是指針;如果將一個(gè)變量定義為string類型,就會將該字符串作為整體看待。這樣一來,在聲明函數(shù)的形參時(shí),無論是將字符串作為數(shù)組、指針或抽象數(shù)據(jù)類型,它們都是可以互換的,其聲明方法如下:

int strlen(string cStr);

int strlen(char cStr[]);

int strlen(char *cStr);

雖然標(biāo)準(zhǔn)C提供的string.h接口提供了一系列的字符串操作函數(shù),它允許在函數(shù)調(diào)用時(shí)將字符串作為一個(gè)整體對待,但這些函數(shù)同樣要求我們了解底層的表示,即函數(shù)將分配內(nèi)存的任務(wù)留給了用戶,特別是檢測緩沖區(qū)溢出的條件。當(dāng)使用這個(gè)接口時(shí),用戶要為每個(gè)字符串的存儲負(fù)責(zé)。這種分配方式不僅增加了程序員的負(fù)擔(dān),也間接使得編碼中的錯(cuò)誤增多了。

溢出問題

使用gets()函數(shù)從標(biāo)準(zhǔn)輸入讀入字符串容易導(dǎo)致緩沖區(qū)溢出,而誤用strcpy()和strcat()同樣如此。因?yàn)槭褂媚承┖瘮?shù)可能造成攻擊者用格式化字符串攻擊的方法訪問內(nèi)存,甚至能夠注入代碼,所以C11版本加入了strcat_s()和strcpy_s()函數(shù),如果發(fā)生緩沖區(qū)溢出,它們會返回錯(cuò)誤。printf()、fprintf()和snprintf()這些函數(shù)都接受格式化字符串作為參數(shù),避免這類攻擊的一種簡單方法是不要將用戶提供的格式化字符串傳給這些函數(shù)。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • 字符串
    +關(guān)注

    關(guān)注

    1

    文章

    575

    瀏覽量

    20468
  • C語言編程
    +關(guān)注

    關(guān)注

    6

    文章

    90

    瀏覽量

    21082
  • 數(shù)據(jù)結(jié)構(gòu)

    關(guān)注

    3

    文章

    569

    瀏覽量

    40072
  • 程序設(shè)計(jì)
    +關(guān)注

    關(guān)注

    3

    文章

    261

    瀏覽量

    30352
  • 周立功
    +關(guān)注

    關(guān)注

    38

    文章

    130

    瀏覽量

    37555

原文標(biāo)題:周立功:字符真正價(jià)值在于形成字符序列——字符串函數(shù)

文章出處:【微信號:ZLG_zhiyuan,微信公眾號:ZLG致遠(yuǎn)電子】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    程序設(shè)計(jì)數(shù)據(jù)結(jié)構(gòu)立功數(shù)十年心血力作

    為了將實(shí)際開發(fā)過程中總結(jié)的有價(jià)值的技術(shù)應(yīng)用分享給大家,立功及其團(tuán)隊(duì)整理出《程序設(shè)計(jì)數(shù)據(jù)結(jié)構(gòu)》這本書,其內(nèi)容如同培訓(xùn)講師的教案,是
    發(fā)表于 05-26 10:06 ?29次閱讀

    立功程序設(shè)計(jì)數(shù)據(jù)結(jié)構(gòu)”:深度解剖動態(tài)分布內(nèi)存的free()函數(shù)與realloc()函數(shù)

    立功教授數(shù)年之心血之作《程序設(shè)計(jì)數(shù)據(jù)結(jié)構(gòu)》,書本內(nèi)容公開后,在電子行業(yè)掀起一片學(xué)習(xí)熱潮。
    的頭像 發(fā)表于 08-25 14:22 ?1.5w次閱讀

    立功教你學(xué)C語言編程與程序設(shè)計(jì):這樣寫函數(shù)指針數(shù)組最好用

    立功教授數(shù)年之心血之作《程序設(shè)計(jì)數(shù)據(jù)結(jié)構(gòu)》以及《面向AMetal框架與接口的編程(上)》,電子版已無償性分享到電子工程師與高校群體,在公眾號回復(fù)【編程】即可在線閱讀。
    的頭像 發(fā)表于 08-31 14:06 ?6827次閱讀
    <b class='flag-5'>周</b><b class='flag-5'>立功</b>教你學(xué)C語言編程與<b class='flag-5'>程序設(shè)計(jì)</b>:這樣寫<b class='flag-5'>函數(shù)</b>指針數(shù)組最好用

    新書創(chuàng)作談:立功教授數(shù)十年之心血力作《程序設(shè)計(jì)數(shù)據(jù)結(jié)構(gòu)

    ` 近日,立功教授公開了數(shù)十年之心血力作《程序設(shè)計(jì)數(shù)據(jù)結(jié)構(gòu)》,此書在4月28日落筆,電子版已無償性分享到電子工程師與高校群體,在致遠(yuǎn)電子公眾號后臺回復(fù)關(guān)鍵字【
    發(fā)表于 05-15 18:04

    【完整資料】《程序設(shè)計(jì)數(shù)據(jù)結(jié)構(gòu)立功數(shù)十年心血力作

    ,是立功和團(tuán)隊(duì)的讀書筆記和程序設(shè)計(jì)實(shí)踐的心得?!?b class='flag-5'>程序設(shè)計(jì)與數(shù)據(jù)結(jié)構(gòu)》重點(diǎn)闡述了三大方向內(nèi)容。C語言學(xué)習(xí)中的痛點(diǎn):針對當(dāng)前工程師在C語言學(xué)習(xí)
    發(fā)表于 05-16 16:43

    程序設(shè)計(jì)數(shù)據(jù)結(jié)構(gòu)》【完整資料】分享!

    現(xiàn)象,甚至成為一位閱讀程序者。 為了將實(shí)際開發(fā)過程中總結(jié)的有價(jià)值的技術(shù)應(yīng)用分享給大家,立功及其團(tuán)隊(duì)整理出《程序設(shè)計(jì)數(shù)據(jù)結(jié)構(gòu)》這本書,其內(nèi)
    發(fā)表于 08-31 16:20

    字符串函數(shù)測試學(xué)習(xí)工程

    字符串函數(shù)測試學(xué)習(xí)工程
    發(fā)表于 07-01 16:38 ?6次下載

    新書創(chuàng)作談:立功教授數(shù)十年之心血力作《程序設(shè)計(jì)數(shù)據(jù)結(jié)構(gòu)

    近日,立功教授公開了數(shù)十年之心血力作《程序設(shè)計(jì)數(shù)據(jù)結(jié)構(gòu)》,此書在4月28日落筆,電子版已無償性分享到電子工程師與高校群體,在致遠(yuǎn)電子公眾號后臺回復(fù)關(guān)鍵字【
    發(fā)表于 05-08 09:32 ?2004次閱讀

    程序設(shè)計(jì)數(shù)據(jù)結(jié)構(gòu)》——框架與重用

    立功教授數(shù)年之心血之作《程序設(shè)計(jì)數(shù)據(jù)結(jié)構(gòu)》以及《面向AMetal框架與接口的編程(上)》,電子版已無償性分享到電子工程師與高校群體,在公眾號回復(fù)【編程】即可在線閱讀。書本內(nèi)容公開后
    的頭像 發(fā)表于 10-10 10:55 ?5452次閱讀
    《<b class='flag-5'>程序設(shè)計(jì)</b>與<b class='flag-5'>數(shù)據(jù)結(jié)構(gòu)</b>》——框架與重用

    基于STM32單片機(jī)發(fā)送字符串函數(shù)

    最近由于要調(diào)試一個(gè)SMS發(fā)送短信的模塊,該模塊需要發(fā)送一系列AT指令,且需要字符串發(fā)送,但是STM32官方給的usart.c中并沒有直接發(fā)送字符串函數(shù),因此寫了一個(gè)發(fā)送字符串
    發(fā)表于 01-04 15:05 ?4852次閱讀

    LabVIEW的常用字符串操作教程免費(fèi)下載

    字符串操作與信息的保存和顯示密不可分,而字符串操作運(yùn)用也是LabⅥEW程序設(shè)計(jì)的一個(gè)難點(diǎn),因此熟練使用字符串操作函數(shù)是使用LabⅥEW進(jìn)行編
    發(fā)表于 08-21 14:51 ?25次下載
    LabVIEW的常用<b class='flag-5'>字符串</b>操作教程免費(fèi)下載

    字符串函數(shù)重寫練習(xí)

    字符串函數(shù)重寫練習(xí):字符串比較、字符串拼接、字符串查找、字符串拷貝、內(nèi)存比較、內(nèi)存拷貝、內(nèi)存初始
    的頭像 發(fā)表于 05-05 15:02 ?1950次閱讀

    MySQL替換字符串函數(shù)REPLACE

    MySQL是目前非常流行的開源數(shù)據(jù)庫管理系統(tǒng)之一,它具有強(qiáng)大的功能和性能。其中之一的字符串函數(shù)REPLACE,可以用于替換字符串中的指定字符
    的頭像 發(fā)表于 11-30 10:44 ?1430次閱讀

    oracle中拼接字符串函數(shù)

    在Oracle中,我們可以使用 CONCAT 函數(shù)來拼接字符串。CONCAT 函數(shù)接受兩個(gè)參數(shù),它將這兩個(gè)參數(shù)連接起來并返回相應(yīng)的字符串結(jié)果。 語法示例: CONCAT(string1
    的頭像 發(fā)表于 12-06 09:49 ?2748次閱讀

    labview中常用的字符串函數(shù)有哪些?

    ) : 功能:該函數(shù)用于返回字符串所包含的字符個(gè)數(shù)。 應(yīng)用場景:常用于需要計(jì)算字符串長度的場景,如文件命名、數(shù)據(jù)處理等。 連接
    的頭像 發(fā)表于 09-04 15:43 ?423次閱讀