原文地址:http://www.51testing.com/html/72/n-221172.html
傳說常見的一個筆試題:不使用中間變量求const字符串長度,即實現求字符串長度庫函數strlen函數。函數接口聲明如下:int strlen(const char *p);
思路分析:
在字符串中通常可以利用最后一個結束符’\0’,但此處參數為const,只讀,那么我們不能打他的主意。
函數運行過程中不占用內存基本不可能,除非都使用了寄存器。“不使用中間變量”只是說程序員不能顯示的申請內存而已,即不能有局部變量或者動態內存申請。
如果函數自動申請棧內存或者使用寄存器存儲變量,或者使用立即數尋址即常量,那么就相當於“不使用中間變量”。
從函數原型看,返回值為int,那么在函數內部必定需要一個地方存儲這個值,要么是常數要么是寄存器。長度不為1時不能一次就求出來,說明必須有遞歸調 用,這樣遞歸時函數會自動申請棧內存,這樣就相當於程序員“不使用中間變量”了。中間返回的值通過寄存器自動保存,最后一次返回時拷貝到int中去。 C/C++中也有臨時對象的概念,都是程序在運行過程中由編譯器在棧中自動申請的對象,對程序員不可見,也相當於“不使用中間變量”
另外一個不申請任何變量的典型題目是:反轉字符串
這種問題都是利用常量,或者將變量的申請交給編譯器在遞歸過程中自動在棧中申請,也就是借刀殺人了。
無代碼,無真相;簡單的源碼如下:
#include <stdio.h> #include <string.h> #include <assert.h> 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) /* 使用了一個int型變量 */ { if(str==NULL) return 0; int len = 0; for(; *str++ != '\0'; ) { len++; } return len; }