天天看點

模拟strcpy庫函數的實作(超詳細)前言一、簡介二、模拟實作strcpy三、傳回值四、完整代碼總結

⭐部落格首頁:️CS semi首頁

⭐歡迎關注:點贊收藏+留言

⭐系列專欄:C語言初階

⭐代碼倉庫:C Advanced

家人們更新不易,你們的點贊和關注對我而言十分重要,友友們麻煩多多點贊+關注,你們的支援是我創作最大的動力,歡迎友友們私信提問,家人們不要忘記點贊收藏+關注哦!!!

文章目錄

  • 前言
  • 一、簡介
    • 1.認識strcpy
    • 2.應用strcpy
    • 3.監視分析
  • 二、模拟實作strcpy
    • 1.初步實作
    • 2.輸入空指針
    • 3.assert
    • 4.這階段完整代碼
  • 三、傳回值
    • 1.傳回類型
    • 2.const
  • 四、完整代碼
  • 總結

前言

strcpy函數其實大家并不陌生,但是每次用的時候要麼就複制到字元串的地方不對,要麼就出現錯誤,那到底該怎麼用這個函數呢?接下來我将詳細給大家講解strcpy這個函數的本質和用法!

一、簡介

1.認識strcpy

再認識這個函數之前,我先放一張圖檔供大家了解一下:

模拟strcpy庫函數的實作(超詳細)前言一、簡介二、模拟實作strcpy三、傳回值四、完整代碼總結

在MSDN中查一下這個函數,發現是從後面的數組複制一份複制到前面的數組,那當然,大家夥可能會問了,為什麼有一個const被圈出來了,這個const很熟悉呀,之前見到過了,大家夥繼續往後看,在文中我會跟大家詳細解說一下這個const與指針配套起來的用法。

2.應用strcpy

先帶大家看一看運用一下strcpy的奇效。

#include<stdio.h>
#include<string.h>
int main() {
	char arr1[20] = "****************";
	char arr2[] = "hello";
	strcpy(arr1, arr2);
	printf("%s\n", arr1);	
	return 0;
}
           
模拟strcpy庫函數的實作(超詳細)前言一、簡介二、模拟實作strcpy三、傳回值四、完整代碼總結

看,運用了這個函數以後感覺是在是太友善了,能把arr2中的“hello\0”全部複制到arr1[20]裡面去,唉,大家可能會問了,螢幕上顯示的是hello啊,沒有那個’\0’,大家繼續往下面看,就立馬能夠了解了。

3.監視分析

先上幾張圖檔讓大家了解了解。

1.将*賦到arr1數組中。
模拟strcpy庫函數的實作(超詳細)前言一、簡介二、模拟實作strcpy三、傳回值四、完整代碼總結
2.将hello+’0’賦到arr2數組中。
模拟strcpy庫函數的實作(超詳細)前言一、簡介二、模拟實作strcpy三、傳回值四、完整代碼總結
3.進行複制的操作。
模拟strcpy庫函數的實作(超詳細)前言一、簡介二、模拟實作strcpy三、傳回值四、完整代碼總結
4.原理圖
模拟strcpy庫函數的實作(超詳細)前言一、簡介二、模拟實作strcpy三、傳回值四、完整代碼總結
利用螢幕看strcpy函數能夠看到它的本質就是将後面數組裡面的字元串+‘、0’拷貝到前面的數組中,但是為什麼會有\0呢,這個很簡單,arr[]={a,b,c,d}與arr[]="abc"是有本質的差別的,後者多一個\0,大家可以去看看我以後寫的關于數組的區分的部落格哦!

二、模拟實作strcpy

1.初步實作

先上個代碼:

代碼1:這個代碼很好了解,就先取數組的首位址并交換再往後加加,直到最後一個元素進行交換完退出循環。
#include<stdio.h>
//#include<string.h>
void my_strcpy(char* dest, char* src) {
	while (*src != '\0'){
		*dest++ = *src++;
	}           
	*dest = *src;   //拷貝\0
}
int main() {
	char arr1[20] = "****************";
	char arr2[] = "hello";
	my_strcpy(arr1, arr2);
	printf("%s\n", arr1);
	return 0;
}
           
代碼2:這個代碼可以把\0直接列印出來,不需要最後一步加上交換一次\0。
#include<stdio.h>
//#include<string.h>
void my_strcpy(char* dest, char* src) {
	while (*dest++ = *src++) {
		;
	}           
}
int main() {
	char arr1[20] = "****************";
	char arr2[] = "hello";
	my_strcpy(arr1, arr2);
	printf("%s\n", arr1);
	return 0;
}
           

但這代碼實作的看似沒什麼問題,可是也隐藏着一個很大的問題,數組是我已經定義好了的,但是,如果是在主函數裡面輸入NULL(空指針)呢?那讓我們先來看看。

2.輸入空指針

模拟strcpy庫函數的實作(超詳細)前言一、簡介二、模拟實作strcpy三、傳回值四、完整代碼總結

輸入空指針後,編譯器立馬就報錯了,是以,這是肯定不行的!那怎麼解決呢?接下來上一串代碼!

子函數裡加了先判斷輸入的兩個指針元素存不存在空指針,有空指針那就不進行後續操作。
#include<stdio.h>
//#include<string.h>
void my_strcpy(char* dest, char* src) {
	if (src == NULL || dest == NULL)
	{
		return;
	}
	while (*dest++ = *src++) {
		;
	}           
}
int main() {
	char arr1[20] = "****************";
	char* p = NULL;
	my_strcpy(arr1, p);
	printf("%s\n", arr1);
	return 0;
}
           
模拟strcpy庫函數的實作(超詳細)前言一、簡介二、模拟實作strcpy三、傳回值四、完整代碼總結

大家想一個問題,如果一個程式員喝了點小酒醉了,隻看到了這個程式可以直接運作,很開心的到老闆那裡邀功,老闆說,你這做的啥!為什麼導緻程式員犯錯了呢,很簡單,機器沒有報錯,程式員以為是對的,是以,接下來引進一個新的函數為“斷言’(assert)函數。

3.assert

assert中可以放一個表達式,表達式的結果如果為假,就報錯,如果為真那就正常運作

實作代碼:

#include<assert.h>
#include<stdio.h>
//#include<string.h>
void my_strcpy(char* dest, char* src) {
	/*if (src == NULL || dest == NULL)
	{
		return;
	}*/
	assert(src != NULL);
	assert(dest != NULL);

	while (*dest++ = *src++) {
		;
	}           
}
int main() {
	char arr1[20] = "****************";
	char* p = NULL;
	my_strcpy(arr1, p);
	printf("%s\n", arr1);
	return 0;
}

           
模拟strcpy庫函數的實作(超詳細)前言一、簡介二、模拟實作strcpy三、傳回值四、完整代碼總結

很明顯,這個程式報錯了,而且給你标注了哪裡出錯了,是不是很友善快捷,當然,頭檔案不要漏掉。

4.這階段完整代碼

這一階段的完整代碼如下:
#include<assert.h>
#include<stdio.h>
//#include<string.h>
void my_strcpy(char* dest, char* src)
{
	assert(dest && src);//斷言指針的有效性
	while (*dest++ = *src++)
	{
		;
	}
}

int main()
{
	//strcpy - 字元串拷貝
	//char arr1[20] = "xxxxxxxxxxx";
	//char arr2[] =   "hello";
	//my_strcpy(arr1, arr2);
	//printf("%s\n", arr1);
	char arr3[20] = {0};
	char* p = NULL;
	my_strcpy(arr3, p);

	return 0;
}
           

三、傳回值

大家如果細心看那張strcpy的圖,會發現兩個小問題,這strcpy是有傳回值的呀,還有那個const怎麼一直沒有解決呢?接下來,我們開始解決問題!

1.傳回類型

模拟strcpy庫函數的實作(超詳細)前言一、簡介二、模拟實作strcpy三、傳回值四、完整代碼總結

那接下來修改一下這個代碼吧!

#include<assert.h>
#include<stdio.h>
//#include<string.h>
char* my_strcpy(char* dest, char* src)
{
	assert(dest && src);
	char* ret = dest;
	while (*dest++ = *src++)
	{
		;
	}
	return ret;
}

int main()
{
	char arr1[20] = "*************";
	char arr2[] = "hello";
	printf("%s\n", my_strcpy(arr1, arr2));  //鍊式通路
	return 0;
}
           

這樣就有傳回值了!

2.const

接下來到了最激動人心的時刻,久久困擾的const該怎麼做呢?下面且聽我分析。
大家先來看看這張圖檔,生動形象的解釋了const。
模拟strcpy庫函數的實作(超詳細)前言一、簡介二、模拟實作strcpy三、傳回值四、完整代碼總結
情況一:const 在的左邊:const int p 與 int const * p 一樣哦~
//const放在* 的左邊,const修飾的是指針指向的内容,表示指針指向的内容,不能通過指針來改變了; 但是指針變量本身可以修改
int num = 0;
int n = 1000;
const int* p = &num;
 *p = 20;//err
 p = &n;//ok
           
情況二:const 在*的右邊:int * const p
const放在*的右邊,const修飾的指針變量本身,表示指針變量本身的内容不能被修改,但是指針指向的内容,可以通過指針來改變。
int* const p = &num;
*p = 20;//ok
 p = &n;//err
           

到這裡就完美解決了strcpy函數的問題。

四、完整代碼

#include<assert.h>
#include<stdio.h>
//#include<string.h>
char* my_strcpy(char* dest, const char* src)
{
	assert(dest && src);
	char* ret = dest;
	while (*dest++ = *src++)
	{
		;
	}
	return ret;
}

int main()
{
	char arr1[20] = "*************";
	char arr2[] = "hello";
	printf("%s\n", my_strcpy(arr1, arr2));  //鍊式通路
	return 0;
}
           

總結

模拟strcpy函數讓我們大家深刻了解了這個函數的原理以及用法,最好的一點是讓我們了解了assert和const的使用,一舉三得!!!!

客官都閱讀到這邊了,碼字不易,求個三連支援!

繼續閱讀