C語言中與字符串有關函數討論以及安全性能問題

一、strlen函數

strlen(const char *s)

strlen函數結果是得到字符串長度的數值,寫出一個最基本用法的代碼。

    char s1[] = "123456";///假設s1代碼長度爲6
    printf("strlen = %lu\n",strlen(s1));

strlen代碼代碼演示結果
一般到這裏,大部分初學者都認爲,存入數組裏的是6個字符長度。但是真的是這樣嗎? 我們再接着加入一條語句用來測試該字符串所得到的空間是多少?

printf("sizeof = %lu\n",sizeof(s1));///用來觀察s1分得了多少空間

結果是非常amazing啊!
測試數組長度
???
爲什麼s1的長度是7???
這裏就要引入了字符串數組的一些性質。還是以s1爲例,把s1輸入數組中,輸入結束時,程序會自動給數組的最後一位加上’\0’的符號,用來表示當數組輸入結束。
所以’\0’其實也是佔了一個位置,於是就有了我們看到sizeof(s1)=7。

以上我們是使用數組來定義的,現在改用指針定義,看看有沒有什麼不同。

    char* s1 = "123456";
    printf("strlen = %lu\n",strlen(s1));
    printf("sizeof = %lu\n",sizeof(s1));///結果爲4,是指針s1大小爲4

廢話不多說,直接上實驗結果圖。
結果也是非常amazing啊~
指針實驗
這裏我們可以看到,sizeof(s1)的值爲4。細心的同學會看到指針部分的代碼片段中有一個註釋,解釋了指針的大小爲4。使用指針定義時,s1是指向字符串中的’1’的位置,於是就有了4的出現。

以下函數中的,以指針舉例,有不明白的地方再返回看看。

二、strcmp函數

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

比較兩個字符串,返回:

  • 0:s1 == s2
  • 1: s1 > s2
  • -1: s1 < s2

同樣,我們看一下他的用法。

	char *s1 = "abc";
   	char *s2 = "bbc";
   	char *s3 = "abc";
   	printf("s1:s2 = %d\n",strcmp(s1,s2));///比較字符串s
   	printf("s1:s3 =  %d\n",strcmp(s1,s3));///字符串s1=s3
   	printf("s2:s3 =  %d\n",strcmp(s2,s3));///字符串s2>s3

1.第一條輸出語句,s1和s2相比較,‘a’的ASCII碼(十進制,97)在’b’(十進制,98)前面,所以s1 < s2,得到的結果是-1。
2.第二條輸出語句,s1和s3相比較,兩個字符串是相同的,得到的結果是0。
3.第三條輸出語句,s2和s3相比較,‘b’的ASCII碼(十進制,98)在’a’(十進制,97)前面,所以s2 > s3,得到的結果是1。
在這裏插入圖片描述

三、strcpy函數

 char* strcpy( char *restrict dst, const char *restrict src );

作用是把src的字符串複製到dst中,並返回dst
簡單的用法:

	char *src = "abc";
    char *dst = (char *)malloc(strlen(src)+1);///複製包含結束標誌的字符串
    printf("dst = %s",strcpy(dst,src));

上代碼運行圖
在這裏插入圖片描述
這裏說一下爲什麼使用malloc創建空間時需要加一,在strlen中解釋過了,字符串賦值的時候會自動加上一個’\0’作爲結束標誌,所以需要多創建一個空間。

四、strcat函數

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

即把s2拷貝到s1後面,接成一個長的字符串,並返回s1(s1必須要具有足夠的空間)

	char src[] = "abc";
    char dst[] = "Hello";
    printf("dst = %s",strcat(src,dst));

這裏使用數組表達的更清楚,所以不用指針寫。
看看運行結果怎麼樣。
在這裏插入圖片描述
此處我們看到了程序把dst裏的內容放置在了src後面的,組合成了一新的數組。
strcat
圖示可以看出,src字符串的第一個字符’a’,放到了dst的結束標誌符的位置。可以得出一個等價式:dst[strlen(dst)] = src[0]。

五、strchr函數

char * strchr( const char* s, int c );

即查找指針s所指向的字符串(從左往右查找)裏,c字符第一次出現的位置,返回指針。

char * strrchr( const char* s, int c );

即查找指針s所指向的字符串(從右往左查找)裏,c字符第一次出現的位置,返回指針。

以上指針返回NULL表示沒有找到。
口說無憑,上代碼:

    char *s = "Hello";
    printf("%s\n",strchr(s,'l'));

上運行結果:
運行結果
結果也是非常amazing啊,指針p所在的位置剛好是字符串中第一次出現’l’的地方。

舉一反三:
如果我要是想查找到第二個’l’咋辦?使用strchr是一種辦法,使用的條件下比較特殊。接下來介紹一種技巧,從左到右查找第二個相同的字符:

    char *s = "Hello";
    char *p = strchr(s,'l');
    p = strchr(p+1,'l');
    printf("%s\n",p);

第一次查找’l’指針所到的位置是2(0、1、2,共計移動三次),那麼接下來找’l’,則從位置3開始找起,對應代碼裏的p+1。

六、strstr函數

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

在字符串中尋找一個字符串(不忽略大小寫)

    char *s1 = "HELLO123hello";
    char *s2 = "hello";
    printf("%s\n",strstr(s1,s2));

在這裏插入圖片描述

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

在字符串中尋找一個字符串(忽略大小寫)

char *s1 = "HELLO123hello";
char *s2 = "hello";
printf("%s\n",strcasestr(s1,s2));

在這裏插入圖片描述

那麼接下來有一個問題來了,如果使用strcpy和strcat函數導致數組越界怎麼辦?
給大家舉個例子:
s1 = {“123456”};

s2 = {“123”};

這種情況下我們使用strcpy和strcat函數,肯定會出現報錯的情況,但是又不想大面積更改代碼。建議看看下面的內容。

安全版本

反思:使用strcpy和strcat都有可能出現數組內存不夠導致越界的情況發生,於是就有了下面的安全版本的誕生。儘可能的使用安全版本

char* strncpy( char* restrict dst, const char* restrict src, size_t n );

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

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

這裏的strncmp函數,表示爲比較兩個字符串的內容。n:比較字符串前n個字符。

舉個栗子:

 *s1 = {"abcde"};
 *s2 = {"abcdef123"}

如果是正常使用strcmp函數,會出現報錯的情況。
現在改用strncmp方式,最後多加入一個參數n。(strncmp(s1,s2,n),此時n的數值爲min(strlen(s1),strlen(s2)),即此時n取值爲s1的字符串長度,max = 5,min = 1。理論上是可以取0,但是沒有什麼實際的意義,反而佔用計算機程序資源)

寫在最後:如果你覺得這篇文章寫得不錯或對你有幫助,就點個贊吧~~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章