1. 程式人生 > 其它 >與字串與記憶體相關的庫函式

與字串與記憶體相關的庫函式

技術標籤:學習過程

本次部落格寫的是關於幾個庫函式的實現的使用,這些函式都是提前包含在標準庫中的,不需要我們自己定義,我們要學的是關於它們的使用。
在使用庫函式是應當注意兩點問題:

  1. 要包含庫函式所在的標頭檔案
  2. 要注意引數合法性檢驗
    這兩點問題在下面我們會提到。

引數合法性檢驗

當使用庫函式時,要注意引數的合法性檢驗,以免傳入錯誤引數而導致BUG的出現。
引數合法性檢驗的兩種風格:

1.if else;

2.assert (表示式);斷言,寫一個表示式,如果表示式為真,斷言沒有任何效果,程式碼繼續執行;如果表示式為假,程式就會直接崩潰。使用的時候要包含<assert.h>標頭檔案。

引數合法性判定的注意事項:

1.一般拿引數和空指標判定,雖然沒啥卵用,但是聊勝於無。(有些合法性檢驗沒啥用,但是必須寫,要讓別人知道你有引數合法性檢驗這個意識)。

2.判定的時候有兩種風格,該怎麼選?

assert:是一種比較嚴厲的處理方式,一旦觸發,程式就會崩潰,如果當前場景是比較嚴重的問題,適合使用assert;例如:伺服器啟動,載入資料發現數據丟失了;在進行金錢結算的時候出現的問題等等。

if:如果當前場景沒那麼嚴重的問題,就不應該使用assert,而應該使用if,來自行定義問題處理方式。

字串函式

   下面介紹一些關於字串操作的庫函式,使用這些庫函式會大大提高我們寫程式碼的效率,將許多複雜的迴圈和過程在這些這些庫函式裡實現,這些庫函式同時需要包含標頭檔案 <string.h>,

下面將來一一介紹

1. strlen
描述:

C 庫函式 size_t strlen(const char *str) 計算字串 str 的長度,直到空結束字元,但不包括空結束字元。
宣告:

下面是 strlen() 函式的宣告。

size_t strlen(const char *str)

引數:

str -- 要計算長度的字串。

返回值:

該函式返回字串的長度。
例項:

下面的例項演示了 strlen() 函式的用法。

#include <stdio.h>
#include <string.h>

int main ()
{
   char str[50];
   int
len; strcpy(str, "This is runoob.com"); len = strlen(str); printf("|%s| 的長度是 |%d|\n", str, len); return(0); }

讓我們編譯並執行上面的程式,這將產生以下結果:

|This is runoob.com| 的長度是 |18|

模擬strlen的實現

int my_strlen(const char * str)
{
int count = 0;
while(*str)
{
count++;
str++;
}
return count;
}
//不能建立臨時變數計數器
int my_strlen(const char * str)
{
if(*str == '\0')
return 0;
else
return 1+my_strlen(str+1);
}
//指標-指標的方式
int my_strlen(char *s)
{
char *p = s;
while(*p != ‘\0)
p++;
return p-s;
}

2.  strcpy()
描述:

C 庫函式 char *strcpy(char *dest, const char *src) 把 src 所指向的字串複製到 dest。

需要注意的是如果目標陣列 dest 不夠大,而源字串的長度又太長,可能會造成緩衝溢位的情況。
宣告

下面是 strcpy() 函式的宣告。

char *strcpy(char *dest, const char *src)

引數:

dest -- 指向用於儲存複製內容的目標陣列。
src -- 要複製的字串。

返回值:

該函式返回一個指向最終的目標字串 dest 的指標。
例項

下面的例項演示了 strcpy() 函式的用法。
例項:

#include <stdio.h>
#include <string.h>
 
int main()
{
   char src[40];
   char dest[100];
  
   memset(dest, '\0', sizeof(dest));
   strcpy(src, "This is runoob.com");
   strcpy(dest, src);
 
   printf("最終的目標字串: %s\n", dest);
   
   return(0);
}

讓我們編譯並執行上面的程式,這將產生以下結果:

最終的目標字串: This is runoob.com

```c

****模擬實現strcpy:****
/1.引數順序
//2.函式的功能,停止條件
//3.assert
//4.const修飾指標
//5.函式返回值
//6.題目出自《高質量C/C++程式設計》書籍最後的試題部分
char *my_strcpy(char *dest, const char*src)
{
char *ret = dest;
assert(dest != NULL);
assert(src != NULL);
while((*dest++ = *src++))
{
;
}
return ret;
}

3.  strncpy()
描述:

C 庫函式 char *strncpy(char *dest, const char *src, size_t n) 把 src 所指向的字串複製到 dest,最多複製 n 個字元。當 src 的長度小於 n 時,dest 的剩餘部分將用空位元組填充。
宣告

下面是 strncpy() 函式的宣告。

char *strncpy(char *dest, const char *src, size_t n)

引數:

dest -- 指向用於儲存複製內容的目標陣列。
src -- 要複製的字串。
n -- 要從源中複製的字元數。

返回值:

該函式返回最終複製的字串。
例項:

下面的例項演示了 strncpy() 函式的用法。在這裡,我們使用函式 memset() 來清除記憶體位置。
例項:

#include <stdio.h>
#include <string.h>
 
int main()
{
   char src[40];
   char dest[12];
  
   memset(dest, '\0', sizeof(dest));
   strcpy(src, "This is runoob.com");
   strncpy(dest, src, 10);
 
   printf("最終的目標字串: %s\n", dest);
   
   return(0);
}

讓我們編譯並執行上面的程式,這將產生以下結果:

最終的目標字串: This is ru

模擬實現strncpy

char* Strncpy(char* destination, const char* source, size_t num)
{
  assert(destination != NULL);
  assert(source != NULL);
  size_t i = 0;
  while(i < num && source[i] != '\0')
  {
    destination[i] = source[i];
    i++;
  }
  if(i == num)
  {
    return destination;
  }
  if(source[i] == '\0')
  {
    for(; i < num; i++)
    {
      destination[i] = '\0';
    }
    return destination;
  }
}

4. strcat()

描述:

C 庫函式 char *strcat(char *dest, const char *src) 把 src 所指向的字串追加到 dest 所指向的字串的結尾。
宣告

下面是 strcat() 函式的宣告。

char *strcat(char *dest, const char *src)

引數:

dest -- 指向目標陣列,該陣列包含了一個 C 字串,且足夠容納追加後的字串。
src -- 指向要追加的字串,該字串不會覆蓋目標字串。

返回值

該函式返回一個指向最終的目標字串 dest 的指標。
例項:

下面的例項演示了 strcat() 函式的用法。
例項

#include <stdio.h>
#include <string.h>
 
int main ()
{
   char src[50], dest[50];
 
   strcpy(src,  "This is source");
   strcpy(dest, "This is destination");
 
   strcat(dest, src);
 
   printf("最終的目標字串: |%s|", dest);
   
   return(0);
}

讓我們編譯並執行上面的程式,這將產生以下結果:

最終的目標字串: |This is destinationThis is source|

模擬實現strcat

char *my_strcat(char *dest, const char*src)
{
char *ret = dest;
assert(dest != NULL);
assert(src != NULL);
while(*dest)
{
dest++;
}
while((*dest++ = *src++))
{
;
}
return ret;
}

5.  strncat(
描述:

C 庫函式 char *strncat(char *dest, const char *src, size_t n) 把 src 所指向的字串追加到 dest 所指向的字串的結尾,直到 n 字元長度為止。
宣告:

下面是 strncat() 函式的宣告。

char *strncat(char *dest, const char *src, size_t n)

引數:

dest -- 指向目標陣列,該陣列包含了一個 C 字串,且足夠容納追加後的字串,包括額外的空字元。
src -- 要追加的字串。
n -- 要追加的最大字元數。

返回值:

該函式返回一個指向最終的目標字串 dest 的指標。
例項:

下面的例項演示了 strncat() 函式的用法。

#include <stdio.h>
#include <string.h>

int main ()
{
   char src[50], dest[50];

   strcpy(src,  "This is source");
   strcpy(dest, "This is destination");

   strncat(dest, src, 15);

   printf("最終的目標字串: |%s|", dest);
   
   return(0);
}

讓我們編譯並執行上面的程式,這將產生以下結果:

最終的目標字串: |This is destinationThis is source|

模擬實現strncat

char* Strncat(char* destination, const char* source, size_t num)
{
  assert(destination != NULL);
  assert(source != NULL);
  size_t i = 0;
  while(destination[i] != '\0')
  {
    i++;
  }
  size_t j = 0;
  while(j < num && source[j] != '\0')
  {
    destination[i] = source[j];
    j++;
    i++;
  }
  destination[i] = '\0';
  return destination;
}

6.  strcmp()
描述:

C 庫函式 int strcmp(const char *str1, const char *str2) 把 str1 所指向的字串和 str2 所指向的字串進行比較。
宣告

下面是 strcmp() 函式的宣告。

int strcmp(const char *str1, const char *str2)

引數:

str1 -- 要進行比較的第一個字串。
str2 -- 要進行比較的第二個字串。

返回值:

該函式返回值如下:

如果返回值小於 0,則表示 str1 小於 str2。
如果返回值大於 0,則表示 str1 大於 str2。
如果返回值等於 0,則表示 str1 等於 str2。

例項:

下面的例項演示了 strcmp() 函式的用法。
例項

#include <stdio.h>
#include <string.h>
 
int main ()
{
   char str1[15];
   char str2[15];
   int ret;
 
 
   strcpy(str1, "abcdef");
   strcpy(str2, "ABCDEF");
 
   ret = strcmp(str1, str2);
 
   if(ret < 0)
   {
      printf("str1 小於 str2");
   }
   else if(ret > 0) 
   {
      printf("str1 大於 str2");
   }
   else 
   {
      printf("str1 等於 str2");
   }
   
   return(0);
}

讓我們編譯並執行上面的程式,這將產生以下結果:

str1 大於 str2

模擬實現strcmp

int my_strcmp (const char * src, const char * dst)
{
int ret = 0 ;
assert(src != NULL);
assert(dest != NULL);
while( ! (ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst)
++src, ++dst;
if ( ret < 0 )
ret = -1 ;
else if ( ret > 0 )
ret = 1 ;
return( ret );
}

7.  strncmp()
描述:

C 庫函式 int strncmp(const char *str1, const char *str2, size_t n) 把 str1 和 str2 進行比較,最多比較前 n 個位元組。
宣告

下面是 strncmp() 函式的宣告。

int strncmp(const char *str1, const char *str2, size_t n)

引數:

str1 -- 要進行比較的第一個字串。
str2 -- 要進行比較的第二個字串。
n -- 要比較的最大字元數。

返回值:

該函式返回值如下:

如果返回值 < 0,則表示 str1 小於 str2。
如果返回值 > 0,則表示 str2 小於 str1。
如果返回值 = 0,則表示 str1 等於 str2。

例項:

下面的例項演示了 strncmp() 函式的用法。

#include <stdio.h>
#include <string.h>

int main ()
{
   char str1[15];
   char str2[15];
   int ret;


   strcpy(str1, "abcdef");
   strcpy(str2, "ABCDEF");

   ret = strncmp(str1, str2, 4);

   if(ret < 0)
   {
      printf("str1 小於 str2");
   }
   else if(ret > 0) 
   {
      printf("str2 小於 str1");
   }
   else 
   {
      printf("str1 等於 str2");
   }
   
   return(0);
}

讓我們編譯並執行上面的程式,這將產生以下結果:

str2 小於 str1

模擬實現strncmp

int Strncmp(const char* str1, const char* str2, size_t num)
{
  assert(str1 != NULL);
  assert(str2 != NULL);
  size_t i = 0;
  while(str1[i] == str2[i] && i < num && str1[i] != '\0' && str2[i] != '\0')
  {
    i++;
  }
  if(i == num)
  {
    return 0;
  }
  if(str1[i] == '\0' && str2[i] == '\0')
  {
    return 0;
  }
  if(str1[i] > str2[i])
  {
    return 1;
  }
  if(str1[i] < str2[i])
  {
    return -1;
  }
}

8. strsr
描述:

C 庫函式 char *strstr(const char *haystack, const char *needle) 在字串 haystack 中查詢第一次出現字串 needle 的位置,不包含終止符 ‘\0’。
宣告

下面是 strstr() 函式的宣告。

char *strstr(const char *haystack, const char *needle)

引數:

haystack -- 要被檢索的 C 字串。
needle -- 在 haystack 字串內要搜尋的小字串。

返回值:

該函式返回在 haystack 中第一次出現 needle 字串的位置,如果未找到則返回 null。
例項:

下面的例項演示了 strstr() 函式的用法。
例項

#include <stdio.h>
#include <string.h>
 
 
int main()
{
   const char haystack[20] = "RUNOOB";
   const char needle[10] = "NOOB";
   char *ret;
 
   ret = strstr(haystack, needle);
 
   printf("子字串是: %s\n", ret);
   
   return(0);
}

讓我們編譯並執行上面的程式,這將產生以下結果:

子字串是: NOOB

模擬實現strstr

char *my_strstr(const char* str1, const char* str2 )
{
assert(str1);
assert(str2);
char *cp = (char*)str1;
char *substr = (char *)str2;
char *s1 = NULL;
if(*str2 == '\0')
return NULL;
while(*cp)
{
s1 = cp;
substr = str2;
while(*s1 && *substr && (*s1 == *substr))
{
s1++;
substr++;
}
if(*substr == '\0')
   return cp;
 cp++;
}
}

9. strtok
描述:

C 庫函式 char *strtok(char *str, const char *delim) 分解字串 str 為一組字串,delim 為分隔符。
宣告

下面是 strtok() 函式的宣告。

char *strtok(char *str, const char *delim)

引數:

str -- 要被分解成一組小字串的字串。
delim -- 包含分隔符的 C 字串。

返回值:

該函式返回被分解的第一個子字串,如果沒有可檢索的字串,則返回一個空指標。
例項:

下面的例項演示了 strtok() 函式的用法。
例項

#include <string.h>
#include <stdio.h>
 
int main () {
   char str[80] = "This is - www.runoob.com - website";
   const char s[2] = "-";
   char *token;
   
   /* 獲取第一個子字串 */
   token = strtok(str, s);
   
   /* 繼續獲取其他的子字串 */
   while( token != NULL ) {
      printf( "%s\n", token );
    
      token = strtok(NULL, s);
   }
   
   return(0);
}

讓我們編譯並執行上面的程式,這將產生以下結果:

This is 
 www.runoob.com 
 website