🌈write in front :
🔍個人主頁 : @啊森要自信的主頁
??真正相信奇跡的家伙,本身和奇跡一樣了不起啊!
歡迎大家關注🔍點贊👍收藏??留言📝>希望看完我的文章對你有小小的幫助,如有錯誤,可以指出,讓我們一起探討學習交流,一起加油鴨。
文章目錄
- 📝前言
- 🌠 庫函數strcpy
- 🌉strcpy的模擬實現
- 🌠庫函數strcat
- 🌉strcat的模擬實現
- 🌠strcmp 的使?
- 🌉strcmp 模擬實現
- 🌠 strstr 的使?
- 🌉strstr 的模擬實現
- 🚩總結
📝前言
記上節,我們學了字符串strlen
的使用和三種模擬實現方法,本小節,阿森繼續和你一起學習4個字符串函數:strcpy
,strcat
,strcmp
,strstr
的使用和他的模擬實現方法,學習這些庫函數,可以更好的方便操作字符和字符串,文章干貨滿滿,接下來我們就學習一下這些函數吧!
🌠 庫函數strcpy
strcpy
函數是將源字符串拷貝到目標字符串中,覆蓋目標字符串原有內容。
char *strcpy(char *dest, const char *src);
dest:目標字符串,用于保存拷貝結果。
src:源字符串,將其內容拷貝到dest中。
返回值:返回目標字符串dest的指針。
注意點:
-
strcpy
函數會將src
字符串中的字符一個一個地復制到dest
字符串中,直到遇到字符串結束標志'\0'
為止。 -
src
字符串必須以'\0'
結束。 -
會將源字符串中的
'\0'
拷?到?標空間。 -
dest
字符串要有足夠的空間,不然會導致緩沖區溢出。
-
目標空間必須是可修改的
代碼:
int main()
{char arr1[20] = "xxxxxxxxx";char arr2[] = {'a', 'b', 'c','\0'};strcpy(arr1, arr2);printf("%s\n", arr1);return 0;
}
運行結果:
🌉strcpy的模擬實現
- 方法一
void my_strcpy(char* dest, char* src)
{while (*src != '\0'){*dest = *src;dest++;src++;}*dest = *src;
}
int main()
{char arr1[20] = { 0 };char arr2[] = "abcdef";my_strcpy(arr1, arr2);printf("arr1 after copy: %s\n", arr1);return 0;
}
分析: 使用
while
循環,循環條件是源字符串src
指針指向的字符不為'\0'
,每次循環體內,將src
指向字符復制到dest
指向位置,分別使dest
和src
指針后移,指向下一個字符位置,循環結束后,將字符串結束符'\0'
也復制到dest
指向位置
- 方法二
第一種方法缺陷太多了,比如沒有返回值,無法知道拷貝是否成功。
char* my_strcpy(char* dest, const char* src)
{assert(dest != NULL);assert(src != NULL);檢查dest和src參數是否為NULL,NULL參數會導致訪問異常。需要#include <assert.h>char* ret = dest;保存dest原始地址到ret變量,后面返回值使用。assert(dest && src);再次檢查dest和src是否合法,防御性編程。while (*dest++ = *src++){;}return ret;
}
while (*dest++ = *src++)
先一次賦值dest
和src
當前字符(*dest = *src),然后并使指針后(dest=dest+1,src=src+1),while
循環結束條件是當src
字符串末尾'\0'
字符被復制時結束,當src
指向\0,
此時\0
賦值給*dest
,符合while
循環結束條件,跳出循環.
🌠庫函數strcat
strcat
函數用于將源字符串src
追加到目標字符串dest
的結尾。
char *strcat(char *dest, const char *src);
dest - 目標字符串,必須有足夠的空間存儲追加后的結果字符串。
src - 源字符串。
返回值: 返回目標字符串dest的地址。
strcat
首先找到dest
字符串的結尾,即'\0'
字符的位置。從dest
字符串結尾開始,將src
字符串一個字符一個字符地復制過來。將src
字符串的結束'\0'
字符也復制到dest
后面。最后返回dest
地址。
關鍵點:
- 源字符串
src
必須以'\0'
結束。 - ?標字符串中也得有
\0
,否則沒辦法知道追加從哪?開始。 dest
必須有足夠的空間存儲追加后的結果字符串。- ?標空間必須可修改。
- 字符串??可不可以給??追加?
使用:
int main()
{char str1[20] = "Hello ";char str2[20] = "World";char str3[40];/* 復制str1到str3 */strcpy(str3, str1);/* 將str2追加到str3結尾 */strcat(str3, str2);printf("str3 = %s\n", str3);return 0;
}
輸出:
str3 = Hello World
🌉strcat的模擬實現
- strcat的模擬實現一
char* my_strcat(char* dest, const char* src)
{char* ret = dest;assert(dest && src);檢查參數是否合法。//1. 找到目標空間的\0使用while循環找到dest字符串的結束'\0'字符,dest指針指向字符串結束后的位置。while (*dest){dest++;}//2. 拷貝while (*dest++ = *src++){;}return ret;
}
while (*dest++ = *src++)先一次賦值
dest
和src
當前字符(*dest = *src),然后并使指針后(dest=dest+1,src=src+1),先讀取src
的一個字符將字符賦給dest
指向的位置,然后dest
和src
同時后移一個位置循環,當src
指向\0,
此時\0
賦值給*dest
,循環結束.
2.字符串??可不可以給??追加? 答案是:不能給自己追加。
char* my_strcat(char* dest, const char* src)
{char* ret = dest;assert(dest && src);//1. 找到目標空間的\0while (*dest){dest++;}//2. 拷貝while (*dest++ = *src++){;}return ret;
}int main()
{char arr1[20] = "hello";my_strcat(arr1, arr1);printf("%s\n", arr1);return 0;
}
運行代碼圖:
🌠strcmp 的使?
strcmp
用于比較兩個字符串是否相等,也就是比較字符串大小的函數。
函數原型:
int strcmp(const char *str1, const char *str2);
str1和str2是要比較的兩個字符串指針。
strcmp
比較字符串的大小,不是按字符串的長度進行比較,而是逐個字符地比較兩個字符串對應的每個字符的ASCII
碼值。(比較使用的是無符號字符值的ASCII碼順序。)
-
返回值:
-
如果
str1
和str2
完全相等,返回0
。 -
如果s
tr1
大于str2
(按ASCII
碼順序),返回一個大于0
的數。 -
如果
str1
小于str2
,返回一個小于0
的數。
-
-
strcmp()
函數是C標準庫string.h
頭文件中的函數。 -
字符串比較結束條件是遇到字符串末尾
'\0'
字符或者第一個不匹配字符。
字符串"cat" 和 "dog" 的比較:
'c'的ASCII碼是99, 'd'的ASCII碼是100,所以"cat"小于"dog"字符串"hello" 和 "hello world" 的比較:
前6個字符都相等,但第7個字符' '的ASCII碼小于'\0',所以"hello"小于"hello world"
例子:
#include <string.h>int main()
{char str1[] = "ahbyb";char str2[] = "asyzx"; int result = strcmp(str1, str2);if(result == 0)printf("Strings are equal\n");else if(result > 0) printf("str1 is greater than str2\n"); elseprintf("str1 is less than str2\n");return 0;
}
結果:
str1 is less than str2
🌉strcmp 模擬實現
int my_strcmp(const char* s1, const char* s2)
{while (*s1 == *s2){if (*s1 == '\0')return 0;s1++;s2++;}return *s1 - *s2;//if (*s1 > *s2)// return 1;//else// return -1;}
使用while
循環逐個比較s1
和s2
每個字符是否相等如果字符相等,繼續循環比較下一個字符, 如果遇到字符串結束符’\0’,表示兩個字符串完全匹配,直接返回0
,如果在循環中找到不匹配的字符,使用*s1 - *s2
返回兩個字符的ASCII
碼差值
🌠 strstr 的使?
strstr
用來查找一個字符串在另一個字符串中首次出現的位置。
strstr函數的原型:
char* strstr(const char* str1, const char* str2);
- str1: 主字符串,要在其中查找子字符串
- str2: 子字符串,要查找的字符串
strstr
函數可以用來在一個字符串中查找另一個字符串首次出現的位置,如果str2
不存在于str1
中,則返回NULL
;如果str2
存在于str1
中,則返回第一個匹配位置的指針。
strstr的比較原理是:
-
從
str1
字符串的起始位置開始,與str2
字符串進行字符匹配比較。 -
如果匹配失敗(當前字符不同),則
str1
指針后移一位,繼續匹配。 -
如果匹配成功(到達
str2
字符串結束符'\0'
),則匹配成功,返回str1
指針地址。 -
如果遍歷完
str1
仍未匹配成功,則返回NULL
。
例如:
char* p = strstr("hello world","world");
// p指向"world"子字符串在"hello world"中的位置
這里用一個圖來解釋strstr函數的工作原理:
+----------------------+
str1 => | h e l l o w o r l d| +----------------------+|V+-----------+
str2 => | w o r l d |+-----------+|V比較第一個字符'h'與'w',不匹配|V指針后移到下一個字符'e'|V比較'e'與'w',不匹配|V指針后移到下一個字符'l'| V比較'l'與'w',不匹配|V指針后移,依次比較直到匹配成功|V當str1指針指向'w'時,與str2第一個字符'w'匹配|V開始匹配后續字符,全部匹配成功|V返回str1指針地址,指向子字符串在主字符串中的位置
int main()
{char arr1[] = "abcegtbaab";char arr2[] = "cegtba";char* ret = strstr(arr1, arr2);if (ret != NULL)printf("%s\n", ret);elseprintf("找不到\n");return 0;
}
結果:
cegtbaab
當然也可以用圖展示:
strstr
從str1
起始位置開始,用str2
與str1
進行字符匹配比較。如果不匹配就后移str1
指針,匹配成功就返回str1
當前位置指針,上圖就是返回c
的地址。通過這種逐個匹配的方式找到子字符串在主字符串中的第一個匹配位置。
🌉strstr 的模擬實現
char* my_strstr(const char* str1, const char* str2)
{const char* cur = str1;//用cur記錄str1的位置const char* s1 = NULL;//使用assert檢查str1和str2是否為非空指針。const char* s2 = NULL;assert(str1 && str2);if (*str2 == '\0')//檢查str2是否為空字符串,如果為空直接返回str1。{return (char*)str1;}while (*cur)//使用cur指針遍歷str1。{ //每次遍歷:s1 = cur;//將cur賦值給s1,將str2賦值給s2,用于后續匹配s2 = str2;//當然,第幾次失敗后,重新回溯,重新開始匹配while (*s1 && *s2 && *s1 == *s2){s1++;//開始匹配s1和s2中的字符,同時遞增s1和s2。s2++;}if (*s2 == '\0')如果s1和s2匹配到結尾('\0'),表示找到了子串,返回cur。{return (char*)cur;}cur++;匹配失敗后,cur++繼續下次匹配。}return NULL;遍歷完str1沒有找到匹配,返回NULL。
}
時間復雜度為O(MN)
,其中M和N分別為主串和子串的長度。
若老鐵們有點蒙蒙的,可以結合下圖來理解:
🚩總結
這次阿森和你一起學習4個C語言中常用的基本字符操作函數,當然這只是一部分,還有很多,但阿森會慢慢和你一起學習。感謝你的收看,如果文章有錯誤,可以指出,我不勝感激,讓我們一起學習交流,如果文章可以給你一個小小幫助,可以給博主點一個小小的贊😘