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

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

周立功《程序設計與數據結構》:字符串函數

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

本文為程序設計基礎,本文為1.8.2 字符串常量第三點:字符串函數。

>>>>

1.字符串函數

標準C提供了一個操作字符串的接口string.h,其中的很多函數是有特殊用途的,下面將詳細介紹通過string.h導出的最重要的函數原型。

strlen()函數

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

size_t strlen(const char *s);

//前置條件:s是一個以null結尾的字符串

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

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

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

2 {

3 if(strlen(string) > size)

4 strlen[size] = '\0';

5 }

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

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

strcat()函數

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

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

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

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

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

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

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

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

strcmp()函數和strncmp()函數

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

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

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

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

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

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

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

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

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

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

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

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

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

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

strcpy()函數

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

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

pts2 = pts1;

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

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

//前置條件:s2是一個以null結尾的字符串,s1數組有足夠的空間容納s2的一個副本

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

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

strncpy()函數

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

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

該函數將s2指向的字符串拷貝至s1指向的位置,拷貝的字符不超過n,其返回值為s1。該函數不會拷貝空字符后面的字符,如果源字符串中的字符數少于n,則目標字符串就以拷貝的空字符結尾。如果源字符串有n個或超過n個字符,就不拷貝空字符,所以拷貝的副本中不一定有空字符。基于此,一般會將n設置比目標數組大小少1,然后將數組最后一個元素設置為空字符。

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

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

typedef char *striing;

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

int strlen(string cStr);

int strlen(char cStr[]);

int strlen(char *cStr);

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

溢出問題

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

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

    關注

    1

    文章

    567

    瀏覽量

    20443
  • C語言編程
    +關注

    關注

    6

    文章

    90

    瀏覽量

    21073
  • 數據結構
    +關注

    關注

    3

    文章

    569

    瀏覽量

    40063
  • 程序設計
    +關注

    關注

    3

    文章

    261

    瀏覽量

    30339
  • 周立功
    +關注

    關注

    38

    文章

    130

    瀏覽量

    37528

原文標題:周立功:字符真正價值在于形成字符序列——字符串函數

文章出處:【微信號:ZLG_zhiyuan,微信公眾號:ZLG致遠電子】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    程序設計數據結構立功數十年心血力作

    為了將實際開發(fā)過程中總結的有價值的技術應用分享給大家,立功及其團隊整理出《程序設計數據結構》這本書,其內容如同培訓講師的教案,是
    發(fā)表于 05-26 10:06 ?29次閱讀

    立功程序設計數據結構”:深度解剖動態(tài)分布內存的free()函數與realloc()函數

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

    立功教你學C語言編程與程序設計:這樣寫函數指針數組最好用

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

    新書創(chuàng)作談:立功教授數十年之心血力作《程序設計數據結構

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

    【完整資料】《程序設計數據結構立功數十年心血力作

    ,是立功和團隊的讀書筆記和程序設計實踐的心得?!?b class='flag-5'>程序設計與數據結構》重點闡述了三大方向內容。C語言學習中的痛點:針對當前工程師在C語言學習
    發(fā)表于 05-16 16:43

    程序設計數據結構》【完整資料】分享!

    現象,甚至成為一位閱讀程序者。 為了將實際開發(fā)過程中總結的有價值的技術應用分享給大家,立功及其團隊整理出《程序設計數據結構》這本書,其內
    發(fā)表于 08-31 16:20

    字符串函數測試學習工程

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

    新書創(chuàng)作談:立功教授數十年之心血力作《程序設計數據結構

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

    程序設計數據結構》——框架與重用

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

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

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

    LabVIEW的常用字符串操作教程免費下載

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

    字符串函數重寫練習

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

    MySQL替換字符串函數REPLACE

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

    oracle中拼接字符串函數

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

    labview中常用的字符串函數有哪些?

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