最近看C,看到strcmp函數,對它的實作原型不很清楚,于是到網上搜。網上算法一大堆,看了很多代碼後自己做了一下總結
strcmp函數是C/C++中基本的函數,它對兩個字元串進行比較,然後傳回比較結果,函數形式如下:
int strcmp(const char* str1, const char* str2);
其中str1和str2可以是字元串常量或者字元串變量,傳回值為整形。傳回結果如下規定:
① str1小于str2,傳回負值或者-1(VC傳回-1);
② str1等于str2,傳回0;
③ str1大于str2,傳回正值或者1(VC傳回1);
strcmp函數實際上是對字元的ASCII碼進行比較,實作原理如下:首先比較兩個串的第一個字元,若不相等,則停止比較并得出兩個ASCII碼大小比較的結果;如果相等就接着 比較第二個字元然後第三個字元等等。無論兩個字元串是什麼樣,strcmp函數最多比較到其中一個字元串遇到結束符'/0'為止,就能得出結果。strcmp算法的可以有多種,不過我覺的可以把這麼多算法分為兩種,一種是利用減法運算判斷結果,另一種是利用比較運算(==)得出結果。
減法運算的實作的代碼如下:
int strcmp(const char* str1, const char* str2)
{
int ret = 0;
while(!(ret=*(unsigned char*)str1-*(unsigned char*)str2) && *str1)
{
str1++;
str2++
}
if (ret < 0)
return -1;
else if (ret > 0)
return 1;
return 0;
}
這個函數要注意一下幾點
①使用*(unsigned char*)str1而不是用*str1。這是因為傳入的參數為有符号數,有符号字元值的範圍是-128~127,無符号字元值的範圍是0~255,而字元串的ASCII沒有負值,若不轉化為無符号數這回在減法實作時出現錯誤。
例如 str1的值為1,str2的值為255。
作為無符号數計算時ret = -254,結果為負值,正确
作為有符号數計算時ret = 2,結果為正值,錯誤
②While循環中ret=*(unsigned char*)str1-*(unsigned char*)str2) && *str1,最後與上str1也可以換成str2,因為前面已經做了相減,無論哪個先為‘\0’都會退出。因為最後與上str1是為了判斷str1是否結束,即是否為‘\0’。
③這個函數沒有判斷參數為NULL時的情況,是以當傳入NULL時程式會崩潰。網上看别人說商業化代碼都會在調用strcmp前先判斷是否為NULL,是以可以不用判斷NULL;我在VC6上測試string.h中的strcmp(NULL,NULL),程式也會崩潰。這裡可以根據實際情況來決定。
若要判斷NULL按下面方法更改代碼,可以在這個函數最前面加入斷言
assert((NULL != str1) && (NULL != str2))
但要注意斷言assert 是僅在Debug 版本起作用的宏,是在Debug時做的無害測試。若想在Release 版也可
以判斷NULL,那我們必須用别的代碼來判斷。
可以在程式前面加入if判斷
if ((NULL != str1) && (NULL != str2))
{
return 0;
}
我用CFree 5測試sting.h中的strcmp(NULL,NULL),程式傳回值為0(strcmp(NULL,str1)崩潰),這裡我們可以傳回其他的值如 -2。
我們也可以在函數前面加入while判斷
while ((NULL != str1) && (NULL != str2))
//strcmp實作代碼
利用while就可以把每個字元都進行判斷。
利用比較運算(==)算法如下
while ((*str1) && (*str1 == *str2))
str2++;
if (*(unsigned char*)str1 > *(unsigned char*)str2)
else if (*(unsigned char*)str1 < *(unsigned char*)str2)
else
return 0;
}
函數注意點和上面一樣,有一點要注意不要為了簡潔而寫成下面
int strcmp(const char *str1,const char *str2)
while ((*str1) && (*str1++ == *str2++)) //這裡++會引起錯誤
NULL;
}
當str1為abcd,st2為abfd時,由于判斷到第三個字元時while推出,而str指針又加了1,str都指向第四個字元輸出結果為0,顯然這是錯誤的。
這個函數也可以用for來實作
int strcmp(const char *str1, const char *str2)
for ( ; *str1 == *str2; str1++, str2++)
{
if (*str1 == '\0')
//如果隻傳回正負的話可以用 return *(unsigned char*)str1 - *(unsigned char*)str2;
}
轉載連結:http://blog.csdn.net/wgenek/article/details/7257435