天天看點

C語言函數替代strlen,C語言實作strlen函數的幾種方法【轉】

今天偶然看到了一個實作strlen函數的方法,也實際練習了一下,挺有意義的,其實作的一些思想值得學習,記錄一下吧。我這裡除了寫兩個比較巧妙的遞歸實作之外,也寫了另外一種正常的方式。

傳說常見的一個筆試題:不使用中間變量求const字元串長度,即實作求字元串長度庫函數strlen函數。函數接口聲明如下:int

strlen(const char *p);

思路分析:

在字元串中通常可以利用最後一個結束符’\0’,但此處參數為const,隻讀,那麼我們不能打他的主意。

函數運作過程中不占用記憶體基本不可能,除非都使用了寄存器。“不使用中間變量”隻是說程式員不能顯示的申請記憶體而已,即不能有局部變量或者動态記憶體申請。

如果函數自動申請棧記憶體或者使用寄存器存儲變量,或者使用立即數尋址即常量,那麼就相當于“不使用中間變量”。

從函數原型看,傳回值為int,那麼在函數内部必定需要一個地方存儲這個值,要麼是常數要麼是寄存器。長度不為1時不能一次就求出來,說明必須有遞歸調用,這樣遞歸時函數會自動申請棧記憶體,這樣就相當于程式員“不使用中間變量”了。中間傳回的值通過寄存器自動儲存,最後一次傳回時拷貝到int中去。C/C++中也有臨時對象的概念,都是程式在運作過程中由編譯器在棧中自動申請的對象,對程式員不可見,也相當于“不使用中間變量”

另外一個不申請任何變量的典型題目是:反轉字元串

這種問題都是利用常量,或者将變量的申請交給編譯器在遞歸過程中自動在棧中申請,也就是借刀殺人了。

無代碼,無真相;簡單的源碼如下:

#include

#include

#include

int myStrlen(const char *str);

int myStrlen1(const char *str);

int myStrlen2(const char *str);

int main()

{

char

*str=NULL;

str = "Hello

Jay!";

printf("original strlen():%d\n",strlen(str));

printf("myStrlen():%d\n",myStrlen(str));

printf("myStrlen1():%d\n",myStrlen1(str));

printf("myStrlen2():%d\n",myStrlen2(str));

}

int myStrlen(const char

*str)

{

if ( (str ==

NULL) || (*str == '\0') ) {

return 0;

}

else

{

return myStrlen(str+1)+1;

}

}

int myStrlen1(const char *str)

{

assert(str

!= NULL);

return *str

? (myStrlen1(++str) + 1) : 0;

}

int myStrlen2(const char *str)

{

if(str==NULL) return 0;

int len =

0;

for(; *str++

!= '\0'; )

{

len++;

}

return

len;

}