【C語言】字符串函數strcpystrcatstrcmpstrstr的使?和模擬實現

  🌈write in front :

🔍個人主頁 : @啊森要自信的主頁

??真正相信奇跡的家伙,本身和奇跡一樣了不起啊!

歡迎大家關注🔍點贊👍收藏??留言📝>希望看完我的文章對你有小小的幫助,如有錯誤,可以指出,讓我們一起探討學習交流,一起加油鴨。 請添加圖片描述

文章目錄

  • 📝前言
  • 🌠 庫函數strcpy
    • 🌉strcpy的模擬實現
  • 🌠庫函數strcat
    • 🌉strcat的模擬實現
  • 🌠strcmp 的使?
    • 🌉strcmp 模擬實現
  • 🌠 strstr 的使?
    • 🌉strstr 的模擬實現
  • 🚩總結


📝前言

記上節,我們學了字符串strlen的使用和三種模擬實現方法,本小節,阿森繼續和你一起學習4個字符串函數:strcpystrcatstrcmpstrstr的使用和他的模擬實現方法,學習這些庫函數,可以更好的方便操作字符和字符串,文章干貨滿滿,接下來我們就學習一下這些函數吧!


🌠 庫函數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的模擬實現

  1. 方法一
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指向位置,分別使destsrc指針后移,指向下一個字符位置,循環結束后,將字符串結束符'\0'也復制到dest指向位置

  1. 方法二
    第一種方法缺陷太多了,比如沒有返回值,無法知道拷貝是否成功。
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++)
先一次賦值destsrc當前字符(*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的模擬實現

  1. 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++)先一次賦值destsrc當前字符(*dest = *src),然后并使指針后(dest=dest+1,src=src+1),先讀取src的一個字符將字符賦給dest指向的位置,然后destsrc同時后移一個位置循環,當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碼順序。)

  • 返回值:

    • 如果str1str2完全相等,返回0

    • 如果str1大于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循環逐個比較s1s2每個字符是否相等如果字符相等,繼續循環比較下一個字符, 如果遇到字符串結束符’\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的比較原理是:

  1. str1字符串的起始位置開始,與str2字符串進行字符匹配比較。

  2. 如果匹配失敗(當前字符不同),則str1指針后移一位,繼續匹配。

  3. 如果匹配成功(到達str2字符串結束符'\0'),則匹配成功,返回str1指針地址。

  4. 如果遍歷完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

當然也可以用圖展示:
在這里插入圖片描述

strstrstr1起始位置開始,用str2str1進行字符匹配比較。如果不匹配就后移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語言中常用的基本字符操作函數,當然這只是一部分,還有很多,但阿森會慢慢和你一起學習。感謝你的收看,如果文章有錯誤,可以指出,我不勝感激,讓我們一起學習交流,如果文章可以給你一個小小幫助,可以給博主點一個小小的贊😘
請添加圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/211956.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/211956.shtml
英文地址,請注明出處:http://en.pswp.cn/news/211956.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

OCSP檢查數字證書狀態詳解

文章目錄 1. OCSP 的基本原理2. OCSP 的工作流程3. OCSP 的優勢和不足4. OCSP Stapling5. OCSP 配置 OCSP&#xff08;Online Certificate Status Protocol&#xff09;是一種用于檢查數字證書狀態的協議。它提供了一種實時查詢證書狀態的方式&#xff0c;以確定證書是否被吊銷…

prototype、__proto__、constructor、原型、原型鏈

結論&#xff1a; __proto__和constructor屬性是對象所獨有的&#xff1b; prototype屬性是函數所獨有的&#xff0c;由于函數也是一種對象&#xff0c;所以函數也擁有__proto__和constructor屬性&#xff1b;__proto__屬性的作用就是當訪問一個對象的屬性時&#xff0c;如果該…

C++ 多態性(Polymorphism)和 虛函數(Virtual Functions)

在 C 中&#xff0c;多態性&#xff08;Polymorphism&#xff09;是面向對象編程的一個重要概念&#xff0c;它允許通過基類指針或引用來調用派生類對象的特定方法。虛函數&#xff08;Virtual Functions&#xff09;是實現多態性的一種機制&#xff0c;通過在基類中聲明虛函數…

InputStream和OutputStream速通

InputStream和OutputStream 輸入流&#xff08;InputStream&#xff09;&#xff1a; InputStream是抽象類&#xff0c;用于從各種數據源&#xff08;如文件、網絡連接、內存等&#xff09;讀取字節流。常見的子類包括FileInputStream、ByteArrayInputStream和SocketInputStrea…

電源小白入門學習1——電源系統架構和相關指標

電源小白入門學習1——電源系統架構和相關指標 電源系統架構電源系統的指標及測量方法電源的效率電源的靜態電流輸出電壓調整率紋波測量的注意事項動態負載測試 在開始本期內容之氣&#xff0c;我先簡單介紹一下我們電源小白學習系列內容&#xff1a;首先我是一個嵌入式小白&am…

【InsCode】新的代碼管理工具inscode教程它和Git以及SVN的區別

InsCode 實踐分享 InsCodeGitSVN類型代碼管理工具分布式版本控制系統集中式版本控制系統分支管理支持強大的分支管理功能&#xff0c;包括創建、合并和刪除分支支持分支管理&#xff0c;操作簡單快捷支持分支管理&#xff0c;但操作相對復雜代碼托管提供代碼托管功能&#xff…

在VSCode中運行Python腳本文件時如何傳參

以下實驗所處的操作系統環境說明&#xff1a; OS版本MacOSMonterey 12.1VSCodeOctober 2023 (version 1.84.2) 一、背景 在 VSCode 中寫好 Python 腳本后&#xff0c;如果要運行起來&#xff0c;可以怎么做呢&#xff1f; 一般有以下幾種方式&#xff1a; 1、直接在 VSCode…

sentinel整合nacos配置中心持久化

在網上找了很多的資料&#xff0c;發現sentinel整合nacos持久化的博文和視頻大多數都只有改造限流部分的教程&#xff0c;并且都需要修改前端&#xff0c;略顯麻煩&#xff0c;至于剩下的熔斷、熱點流控、授權的更是沒有相關的改造教程&#xff0c;最后在知乎的看到一篇文章后讓…

百科詞條可以刪除嗎?如何刪除自己的百度百科?

近日&#xff0c;小馬識途營銷顧問接到不少客戶刪除自己百科詞條的咨詢&#xff0c;有不少人自己并沒有去建立百科詞條&#xff0c;但是網上已經有了&#xff0c;有的信息不正確&#xff0c;甚至有的信息是負能量的&#xff0c;對當事人自己造成一定的困擾&#xff0c;所以尋求…

pytorch學習4-簡易卷積實現

系列文章目錄 pytorch學習1-數據加載以及Tensorboard可視化工具pytorch學習2-Transforms主要方法使用pytorch學習3-torchvisin和Dataloader的使用pytorch學習4-簡易卷積實現pytorch學習5-最大池化層的使用pytorch學習6-非線性變換&#xff08;ReLU和sigmoid&#xff09;pytorc…

【鴻蒙學習網絡】

鴻蒙技術學習相關學習資料 官方文檔&#xff1a;華為官方提供了鴻蒙開發者文檔&#xff0c;包括開發指南、API參考和示例代碼等。您可以訪問華為開發者中心網站&#xff08;https://developer.harmonyos.com/&#xff09;獲取最新的官方文檔和教程。在 線 課 程 &#xff1a; …

PbootCMS 前臺RCE漏洞復現

0x01 產品簡介 PbootCMS是全新內核且永久開源免費的PHP企業網站開發建設管理系統,是一套高效、簡潔、 強悍的可免費商用的PHP CMS源碼,能夠滿足各類企業網站開發建設的需要 0x02 漏洞概述 PbootCMS v<=3.1.6版本中存在模板注入,攻擊者可構造特定的鏈接利用該漏洞,執行…

線程及實現方式

一、線程 線程是一個基本的CPU執行單元&#xff0c;也是程序執行流的最小單位。引入線程之后&#xff0c;不僅是進程之間可以并發&#xff0c;進程內的各線程之間也可以并發&#xff0c;從而進一步提升了系統的并發度&#xff0c;使得一個進程內也可以并發處理各種任務&#x…

c語言的內存函數

memcpy函數 1.調用形式void*memcpy(void*p1,void*p2,int n)&#xff0c;表示從第二個位置復制n個字節到第一個位置&#xff0c;而指針類型為void的原因是他可以復制整型字符型甚至指針結構體類型的數據 2.在遇到\0的時候不會停下來&#xff0c;因為函數執行拷貝靠字節數&…

【Hive】——安裝部署

1 MetaData&#xff08;元數據&#xff09; 2 MetaStore &#xff08;元數據服務&#xff09; 3 MetaStore配置方式 3.1 內嵌模式 3.2 本地模式 3.3 遠程模式 4 安裝前準備 <!-- 整合hive --><property><name>hadoop.proxyuser.root.hosts</name><v…

Java+Swing: 主界面組件布局 整理9

說明&#xff1a;這篇博客是在上一篇的基礎上的&#xff0c;因為上一篇已經將界面的框架搭好了&#xff0c;這篇主要是將里面的組件完善。 分為三個部分&#xff0c;北邊的組件、中間的組件、南邊的組件 // 放置北邊的組件layoutNorth(contentPane);// 放置中間的 Jtablelayou…

Tair(3):Tair入門demo

新建一個maven項目 1 導入依賴 <dependency><groupId>com.taobao.tair</groupId><artifactId>tair-client</artifactId><version>2.3.5</version></dependency><dependency><groupId>com.alibaba</groupId>…

計算日期到天數轉換

根據輸入的日期&#xff0c;計算是這一年的第幾天。 保證年份為4位數且日期合法。 輸入描述&#xff1a;輸入一行&#xff0c;空格分割&#xff0c;分別是年&#xff0c;月&#xff0c;日 輸出描述&#xff1a;輸出是這一年的第幾天 輸入&#xff1a;2012 12 31 輸出&#xff…

Python計時器

制作一個簡單的Python計時器 在本教程中&#xff0c;我們將學習如何使用Python制作一個基礎的計時器。這個計時器將能夠開始計時、暫停、繼續和重置時間。 設計思路 為了建立一個計時器&#xff0c;我們需要定義一個能夠跟蹤時間的變量&#xff0c;并且定期更新顯示的時間。…

Linux權限(用戶角色+文件權限屬性)

Linux權限 文章目錄 Linux權限一.文件權限1.快速掌握修改權限的方法&#xff08;修改文件權限屬性&#xff09;2.對比權限的有無&#xff0c;以及具體的體現3.修改權限的第二套方法&#xff08;修改用戶角色&#xff09;4.文件類型&#xff08;Linux下一切皆文件&#xff09; 二…