C語言字串函式歸納。
首先需要知道在c語言中本身並沒有字串型別,字串通常放在常量字串中或者字元陣列中
1.實現strlen
首先strlen函式的作用是求字串長度的。'\0’是它的結束標誌,strlen函式返回的是在字串中‘\0’前面出現的字元個數,strlen函式的返回值為size_t,是無符號的,它的實現有三種方式。
第一種用指標和計數器的方式。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int my_strlen(char* str) { int count=0; while(*str) { str++; count++; } return count; } int main() { char str[]="asdvssdvsdv"; printf("%d\n",my_strlen(str)); return 0; }
這是最簡單也是很容易理解的一種方式。
第二種遞迴的方式。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int my_strlen(char* str) { if(*str=='\0') return 0; else return 1+my_strlen(str+1); } int main() { char str[]="asdvssdvsdv"; printf("%d\n",my_strlen(str)); return 0; }
第三種是採用指標和指標的方式。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int my_strlen(char* str) { char* p=str; while(*p!='\0') p++; return p-str; } int main() { char str[]="asdvssdvsdv"; printf("%d\n",my_strlen(str)); return 0; }
2實現strcpy
首先應該知道它的作用是複製,char* strcpy(char* destination,const char* source)目標空間應該足夠大,以確保能存放源字串,源字串必須以‘\0’結束,會將源字串的‘\0’拷貝到目標空間。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<assert.h>
#include<algorithm>
using namespace std;
char* my_strcpy(char* dest,char* src)
{
char* ret=dest;
assert(dest!=NULL);
assert(src!=NULL);
while((*dest++==*src++)!='\0')
{;}
return ret;
}
int main()
{
char str1[]="hello";
char str2[]="world";
printf("%s\n",my_strcpy(str1,str2));
return 0;
}
assert是判斷指標有效性的函式。是把dest複製到原函式上面。迴圈寫成while(*dest++=*src++)明顯是錯誤的,不知什麼時候結束。迴圈寫成while(*src!='\0'){*dest++=*src++;}也是錯誤的,迴圈體結束後,dst末尾並沒有加上‘\0’.
2.實現strcat
該函式的作用是拼接函式,stract(str1,strr2),str2是源,str1是目標函式,是把源拼接在目標函式上,目標函式必須足夠大,能容納下源字串的內容。
#include<iostream>
#include<algorithm>
#include<assert.h>
#include<cstdio>
using namespace std;
char *my_strcat(char* dest,char *src)
{
char* ret=dest;
assert(dest!=NULL);
assert(src!=NULL);
while(*dest!='\0')
{
dest++;
}
while((*dest++=*src++))
{
;
}
return ret;
}
int main()
{
char str1[]="hello";
char str2[]="world";
my_strcat(str1,str2);
printf("%s\n",my_strcat(str1,str2));
return 0;
}
3.實現strcmp
該函式的作用是比較另個字串是否完全相同。此處用返回相關數值表示。返回0表示完全相同,返回1表示不相同。
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<assert.h>
using namespace std;
int my_strcmp(char* src,char* dst)
{
assert(src!=NULL);
assert(dst!=NULL);
while(*src==*dst)
{
if(*src=='\0')
return 0;
++src;
++dst;
}
if(*src>*dst)
return 1;
else
return -1;
}
int main()
{
char str1[]="hello";
char str2[]="hellv";
my_strcmp(str1,str2);
cout<<my_strcmp(str1,str2)<<endl;
return 0;
}
4.實現strchr
strchr 原型為extern char *strchr(const char *s,char c),可以查詢字串s中首次出現字元c的位置。此函式並不常用。
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<assert.h>
using namespace std;
char* my_strchr(char* str,char c)
{
assert(str!=NULL);
while(*str!='\0')
{
if(*str==(char)c)
{
return (char*)str;
}
str++;
}
return NULL;
}
int main()
{
char str[]="abcdefg";
char *p;
p=my_strchr(str,'f');
if(p==NULL)
{
cout<<"Not Find"<<endl;
}
else
{
cout<<"Find"<<endl;
cout<<p<<endl;
}
return 0;
}
5.實現strstr
strstr函式的作用是找字串的子串
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<assert.h>
using namespace std;
char* my_strstr(char* str1,char* str2)
{
assert(str1!=NULL);
assert(str2!=NULL);
char* start=(char*)str1;
char* substart=(char*)str2;
char* cp=(char*)str1;
while(*cp)
{
start=cp;
while(*start!='\0'&&*substart!='\0'&&*start==*substart)
{
start++;
substart++;
}
if(*substart=='\0')
return cp;
substart=(char*)str2;
cp++;
}
return NULL;
}
int main()
{
char str1[]="abbbcdefg";
char str2[]="bbcd";
cout<<my_strstr(str1,str2)<<endl;
return 0;
}
首先,根據strstr函式的實現方法得知函式需要傳進去的引數是兩個字串,而且這兩個字串都是不可更改的,這樣,我們可以利用const來修飾;而且函式返回的也是一個字串,那麼返回值型別也可以確定,這樣,我們可以寫出這樣一個函式的定義:char* my_strstr(const char* dest,const char* src){}。其中,dest指向的是目標字串,也就是你需要比較的字串,src指向的是源字串,也就是用來被比較的字串。找不到就可以返回一個空指標。
實現的思路也是比較簡單的,你可以建立兩個指標,通過遍歷的方式逐個訪問字串,並對這兩個指標一一比較。
////
舉例說明:給上倆個字串:
str1:abcdefg
str2:bcd
建立兩個指標:char *start=str1; char *substart=str2;
此時,start指向字元a,而substart指向字元b,對start和substart兩個指標解引用並進行比較,判斷是否相等,即*start=*substart;若是兩個相等,則兩個指標都向後移動一位,再解引用進行判斷;若是兩個不相等,那麼start向後移動一位,substart則將會重新指向str2的起始位置,兩個再次進行比較。重複這個過程,直到兩個字串其中一個或者是兩個都遇到‘\0’,遍歷結束。那麼在這裡你就可以採用迴圈的方法來做;迴圈的判斷條件就是(start!='\0' && substart!='\0' && *start==*substart)。
////
如果到這裡你覺得這個函式就算實現成功的話,那你可就掉到坑裡去了。我再舉個例子吧:
str1:abbbcdefg
str2:bbcd
這裡你繼續採用上面的方式做,你會得到不一樣的結果。
指標判斷,當start指向str1中的第一個b時,substart指向str2中的第一個b,兩個相等,再往後面遍歷,當start指向第三個b的時候,substart指向c,兩個不相等,那麼此時substart會返回並指向str2中的第一個b。
注意,此時start指向的還是str1中的第三個b,start並沒有發生移動,再採用如上的方式比較,從str1的第三個b開始,你再也找不到與str2相同的,那麼函式會返回一個 空,可是顯然第一個字串中包含你需要的查詢的字串。這樣,我們就需要通過某種方法來解決這個問題。
解決方法其實也是比較簡單的:當兩個字串比較的結果不相等時,我們知道substart,就是指向第二個字串的指標是返回到str2這個字串的起始位置的,而start這個指標並沒有發生任何的變動。再次比較也只能從這個位置繼續向後比較,那麼中間肯定就會有一些字元是沒有辦法比較的。所以,當兩個字元比較不相等時,start這個指標也需要向前返回,不過它回到的不是起始位置了,而是起始位置的下一個位置,這樣就可以避免重複而無用的比較。所以,我們需要在建立一個指標cp用來儲存起始位置,並讓start返回到起始位置的下一個位置。(此處為從別人部落格摘抄的,感覺寫的特比妙)
6.實現memcpy
mecmpy是記憶體的拷貝函式
這個函式的原型是 void* mecmpy(void* destination,const void* source,size_t num);函式mecmpy從source 的位置開始向後複製num個位元組的資料到destination的記憶體位置。注意這個函式在遇到'\0'是不會停下來的。如果source和destination有任何的重疊,複製的結果都是未定義的。
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
void* my_memcpy(void* dst,void* src,size_t count)
{
void* ret=dst;
while(count--)#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
void* my_memcpy(void* dst,void* src,size_t count)
{
void* ret=dst;
while(count--)
{
*(char* )dst=*(char* )src;
dst=(char*)dst+1;
src=(char*)src+1;
}
return ret;
}
int main()
{
float arr1[]={1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0};
float arr2[10];
int len=sizeof(arr1)/sizeof(arr1[0]);
my_memcpy(arr2,arr1,len);
return 0;
}
{
*(char* )dst=*(char* )src;
dst=(char*)dst+1;
src=(char*)src+1;
}
return ret;
}
int main()
{
float arr1[]={1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0};
float arr2[10];
int len=sizeof(arr1)/sizeof(arr1[0]);
my_memcpy(arr2,arr1,len);
return 0;
}
此函式和memcpy的差別就是memmove函式處理的源記憶體塊和目標記憶體塊是可以重疊的,如果源空間和目標空間出現重疊,就得使用memmove函式處理
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
void* memove(void* dst,const void* src,size_t count)
{
void* ret=dst;
if(dst<=src||(char*)dst>=((char*)src+count))
{
while(count--)
{
*(char *)dst=*(char *)src;
dst=(char*)dst+1;
src=(char*)src+1;
}
}
else
{
dst=(char*)dst+count-1;
src=(char*)src+count-1;
while(count--)
{
*(char*)dst=*(char*)src;
dst=(char*)dst-1;
src=(char*)src-1;
}
}
return ret;
}
int main()
{
char str1[]="hello";
char str2[]="world";
int len=strlen(str1);
memmove(str1,str2,len);
cout<<memove(str1,str2,len)<<endl;
return 0;
}
複製的是一個記憶體。