文章目錄
- 前言
- 一、Strcpy庫函式是什么?
- 二、Strcpy的用法
- 三、My_Strcpy的實作
- 1.“前菜”
- 2.實作 My_Strcpy 函式
- Ⅰ.“復制程序”的優化
- Ⅱ.“函式內部”的優化
- Ⅲ.“函式形參”的優化
- Ⅳ.“函式回傳型別”的優化
- 四、完成 My_Strcpy函式
- 五、感謝大家支持!!!
前言
通過對C語言中 Strcpy 庫函式的自我實作,探索程式的 優化之美 ,探索程式的 奧秘!
一、Strcpy庫函式是什么?

Strcpy庫函式作用:實作字串的復制
strcpy ( char * destination, const char * source );
實作原理: 將想要復制的字串地址放在strcpy函式括號的后面,而將復制的字串的目的地放在括號前面,它們通過傳址的方式,實作字串的復制
通過上面簡單的了解,不妨發現, 復制字串實則可以通過一個一個的字符交換實作復制 ,那我們現在就可以實踐實作自定義函式實作Strcpy函式了
二、Strcpy的用法
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[20] = "xxxxxxxxxx";
char arr2[] = "hello";
strcpy(arr1,arr2); //1.目標空間的起始地址, 2.原空間的起始地址
printf("%s\n", arr1);
return 0;
}

這里列印的是已經復制過去的字串
可能有同學要問:“那 arr1陣列 里 剩下的 x呢?”
在這里可以觀察到:Strcpy 是將 arr2 里的 “hello” 復制到 arr1 中
( 而且是從首元素一個一個覆寫的復制過去 )
本質:是將 arr2 里的 “h e l l o \0” 去覆寫 arr1 里前幾個 “x”
也就是說:列印 已完成復制的 arr1 時 ,printf 會列印到 “\0” 前的所有字符,("\0" 為字串的結束識別符號) ,所以會列印到 “\0” 就截止列印
這也就是為什么不會列印后面剩下的“x”了
當我們解決完這個小插曲后,也就基本了解到 Strcpy 的作業原理了
接下來就讓我們用自己的語言去實作它吧!
三、My_Strcpy的實作
1.“前菜”
先準備好實作 My_Strcpy 的程式吧
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[20] = "xxxxxxxxxx";
char arr2[] = "hello";
My_Strcpy(arr1,arr2); //1.目標空間的起始地址, 2.原空間的起始地址
printf("%s\n", arr1);
return 0;
}
2.實作 My_Strcpy 函式
Ⅰ.“復制程序”的優化
此處忽略“前菜”
直接開始 自定義函式部分
void My_strlen(char* dest,char* src) //dest指標接收目標陣列的首元素地址;
//src指標接收要復制的陣列首元素地址
{
while(*src != '\0')
{
*dest = *src;
dest++;
src++;
} //但是這樣設定回圈條件的話,是不會把'\0'也給復制的
//所以得加多一條陳述句
*dest = *src; //因為上面回圈已經讓地址到'\0'的地方
//只是回圈條件為假,所以不執行
//所以可以承接上面++后的地址,執行一次,即可把'\0'也復制
}
但是有沒有什么辦法將’\0’也整合在回圈里呢?
如果你也有這樣的想法
那恭喜你
開始步入“程式之美”
— 優化
那接下來,讓我們開始 “優化” 吧!!
為了可以“一步到位”,我們可以嘗試把 回圈內的條件先整合起來
void My_strlen(char* dest,char* src)
{
while(*src != '\0')
{
*dest++ = *src++; //跟之前意思一樣
//先復制,然后地址++,然后解參考 復制
}
*dest++ = *src++;
}
開始“一步到位”吧
void My_strlen(char* dest,char* src)
{
while(*dest++ = *src++)
{
; //上面的條件,既可以先復制
} //當復制'\0'后,條件判斷為假,又可以退出回圈
} //這樣不就能做到“一步到位”、“一石二鳥”了嗎!
看到這里
是不是可以感受到 “程式” 所帶給人“醍醐灌頂”的感覺了呢?
接下來
還有更 “妙” 的呢!!
Ⅱ.“函式內部”的優化
為了保證函式的可實行性
我們要判斷傳過來的是否為空指標
這就是 “優化” 的第二個點啦~
此判斷操作,我們可以用 “assert()” – 斷言 這個庫函式
【這里不細致展開】
那我們就可以用此來判斷傳過來的兩個指標是否為空指標
從而確保函式的可執行性和正確性~
void my_strcpy(char*dest , const char*src)
{
//判斷傳過來的 是否為空指標
assert( src != NULL);//斷言----需要引頭檔案 <assert.h>
// 如果 != 則 為真--則不會報錯,
//如果為假(即 指標為 空指標)--則會報錯
assert( dest != NULL);
while (*dest++ = *src++)
{
;
}
}
加上 assert 還有一個好處就是:如果為空指標,程式也可以快速給出出錯的位置 (這就是 if 陳述句所做不到的)
就像下面一樣:

這樣的程式用起來誰不放心呢~
Ⅲ.“函式形參”的優化
通過回看前面 “Strcpy庫函式是什么” 的章節時
我們不難發現
我們的 My_Strcpy 函式 與 Strcpy庫函式 對比起來
還是有 “不同的”
說明我們還有 “優化” 的空間哦!

不難發現
對比我們的 My_Strcpy 函式 的形參部分
這里的 “形參” 部分多了 “const” 來修飾
我們此刻就要開始思考–為什么要這樣做呢
【PS:要做到這種 勤加思考 的習慣,才是一個優秀的程式標配哦~】
這樣做可以保證 在復制的程序中,保護“復制的內容”不會在復制的 程序中而被改變
【PS:這里暫時不細談“const運算子在指標中的應用”!】
如果大家覺得這篇文章寫得不錯、覺得通俗易懂
可以多多點贊、轉發、收藏哦!
本作者會盡快出這方面相關的內容哦!!
回歸正題
在 * 前 加上 ‘const’
表示 * source (對應回 My_Strcpy 中的 ’ * src ’ ) 即 * source這個指標 解參考后所對應的內容 具有 常屬性,在復制的程序中, source的值不會被改變*
只有當 source的地址發生改變,即 source所對應的內容也發生改變時,它的值才會發生改變
這也就可以有效避免如下的問題
void My_strlen(char* dest,const char* src) 
{
while( *src++ = *dest++)
{
; //復制的時候,放錯位置的情況
}
}
發生上述問題時,程式就會自動報錯,保護了程式


因為此時 *src 具有常屬性
相當于賦值的時候,常量不能放在等號的左邊一個道理
把src指向的內容拷貝放進dest 指向的空間中
從 本質上講,就是希望dest指向的內容被修改,src指向的內容不被修改
這也就是我們所”優化”的另一個點啦~
Ⅳ.“函式回傳型別”的優化
再次對照 Strcpy庫函式
我們又不難發現,Strcpy庫函式 的回傳型別竟然是 char*
這不
“優化” 又來了~~

Strcpy這個庫函式,其實回傳的是目標空間的起始地址
那我們就可以做如下 “優化”
#include <stdio.h>
#include <string.h>
char* my_strcpy(char*dest , const char*src)
{
char * ret = dest; //先保存起始地址下來
assert(*src != NULL)
assert(*dest != NULL);
while (*dest++ = *src++)
{
;
}
return ret; //內容改變了,但地址沒變--也就依舊可以使用了
}
int main()
{
char arr1[20] = "xxxxxxxxxx";
char arr2[] = "hello";
printf("%s\n", My_Strcpy(arr1,arr2)); //這里就可以 “鏈式訪問”
//即【函式的回傳值 為 printf的引數】
//這樣就可以很快的查看 目標空間內容是什么
return 0;
}
使用 char * 回傳型別,可以更快地查看 目標空間內容是什么啦~~
四、完成 My_Strcpy函式
綜上,
我們就成功的將 My_Strcpy函式 ,所有可以優化的點都有優化好啦~
換句話說:我們成功的復刻了 Strcpy函式
是不是頓時感覺自己棒棒噠!!
但這只是**“小巫見大巫”**,起到為各位同學 “拋磚引玉” 的作用,希望同學們也可以 借此文章對個人思想有所啟發哦!
程式世界之大,
還有更多未知的等待你們
去探索,
去發現,
去找到屬于你們豁然開朗的那一刻哦~
五、感謝大家支持!!!
【如果你覺得本文對你有幫助,可以點點贊 支持一下喲~】
【如果你有更好的想法,也可以在下方評論喲,相互學習,相互進步!】
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/380846.html
標籤:其他
上一篇:Kotlin:如何在一行代碼中實體化一個類并實作一個介面?
下一篇:數字影像相關(Digital Image Correlation, DIC)中的非線性優化方法(FA-GN與IC-GN)
