- 相關(guān)推薦
C語言字符串操作函數(shù)及常用的實現(xiàn)
面試官很喜歡讓求職者寫一些常用庫函數(shù)的實現(xiàn),有很多是和字符串相關(guān)的,有一些是關(guān)于內(nèi)存拷貝的。一般,常會讓寫的函數(shù)有以下幾個:
strcpy , strncpy, memcpy。
memset一般不會讓去寫,但這個函數(shù)也很有特點,有很多容易用錯的地方。一并總結(jié)吧。
字符串操作函數(shù) |
|
atof() | 將字符串轉(zhuǎn)換成浮點數(shù) |
atoi() | 將字符串轉(zhuǎn)換成整數(shù) |
atol() | 將字符串轉(zhuǎn)換成長整型數(shù) |
gcvt() | 將浮點型數(shù)轉(zhuǎn)換為字符串(四舍五入) |
strtod() | 將字符串轉(zhuǎn)換成浮點數(shù) |
strtol() | 將字符串轉(zhuǎn)換成長整型數(shù) |
strtoul() | 將字符串轉(zhuǎn)換成無符號長整型數(shù) |
toascii() | 將整數(shù)轉(zhuǎn)換成合法的ASCII碼字符 |
tolower() | 將大寫字母轉(zhuǎn)換為小寫字母 |
toupper() | 將小寫字母轉(zhuǎn)換為大寫字母 |
index() | 查找字符串并返回首次出現(xiàn)的位置 |
rindex() | 查找字符串并返回最后一次出現(xiàn)的位置 |
strcasecmp() | 判斷字符串是否相等(忽略大小寫) |
strcat() | 連接字符串 |
strcmp() | 根據(jù)ASCII碼比較字符串 |
strcoll() | 根據(jù)環(huán)境變量LC_COLLATE來比較字符串 |
strcpy() | 復制字符串 |
strcspn() | 查找字符串并返回首次出現(xiàn)的位置 |
strchr() | 查找字符串并返回首次出現(xiàn)該字符的地址 |
strdup() | 復制字符串 |
strlen() | 返回字符串長度 |
strncasecmp() | 比較字符串的前n個字符 |
strncat() | 拼接字符串(取前n個字符) |
strncpy() | 復制字符串(取前n個字符) |
strpbrk() | 定位字符串中第一個出現(xiàn)的指定字符 |
strrchr() | 定位字符串中最后出現(xiàn)的指定字符 |
strspn() | 返回從字符串開頭連續(xù)包含特定字符的字符數(shù)目 |
strstr() | 返回指定字符串第一次出現(xiàn)的地址 |
strtok() | 字符串分割 |
1. strcpy
strcpy函數(shù)的原型是:
char * strcpy(char* dest, const char* src)
strcpy的實現(xiàn)經(jīng)常要注意的細節(jié)是:
(1)判斷地址是否為空,個人感覺可以使用斷言
(2)參數(shù)只有兩個地址,沒有拷貝的長度?截惖'\0‘時就會終止,要保證最終dest末尾是'\0'。
(3)要保證目標字串的長度足夠,能夠容納原串的長度。
(4)因為拷貝是dest會移動,而最終要返回的是拷貝后字符串的起始地址,因此要先保存dest的地址,便于最終返回。
在實現(xiàn)這一點時,有兩種方法。 char* temp=dest; 拷貝時移動dest返回temp,或者拷貝時移動temp返回dest,不知道哪個是對的。感覺兩個都是沒有問題的
其中一種實現(xiàn)方式:
[cpp] view plaincopychar* mystrcpy(char* dest,const char* src)
{
assert(dest!=NULL && src!=NULL);
char* temp=dest;
while((*temp++ = *src++ )!='\0')
{}
return dest;
}
2. strncpy
strncpy的功能和strcpy相似,只是它復制時多了一個終止條件。即是未遇到原串的'\0’,如果已經(jīng)復制了n個字符(n為提供的參數(shù)長度),復制同樣會終止。
strcpy的實現(xiàn)要注意的細節(jié)也基本適用于strncpy的實現(xiàn)。
實現(xiàn)方式:
[cpp] view plaincopychar* mystrncpy(char* dest, const char* src, int len)
{
assert(dest!=NULL && src!=NULL);
char* temp=dest;
int i=0;
while(i++ < len && (*temp++ = *src++)!='\0')
{}
if(*(--temp)!='\0')
*temp='\0';
return dest;
}
[cpp] view plaincopy注意:剛開始我寫strncpy的實現(xiàn)時,把while(i++ < len && (*temp++ = *src++)!='\0')寫成了while( (*temp++ = *src++)!='\0' && i++ < len); 導致最后多復制了一個字符,明白為什么吧。。
3. memcpy
memcpy和strncpy有些類似,但也有本質(zhì)的不同。
(1)strncpy只能復制字符串,但memcpy對類型沒有要求。
(2)strncpy有兩個終止條件,memcpy只有一個終止條件,那就是復制n個字節(jié)。(n是memcpy的第三個參數(shù))
(3)要特別注意目的地址和源地址重合的問題,拷貝前要加以判斷。
(4)實現(xiàn)這個函數(shù)時一般要把原來的指針類型轉(zhuǎn)換成char*,這樣每次移動都是一個字節(jié)。
實現(xiàn)方式:(考慮了兩個地址空間是否會有重疊)
[cpp] view plaincopyvoid* mymemcpy(void* dest, void* src, int len)
{
int i=0;
char* tempdest=(char*)dest;
char* tempsrc=(char*)src;
if(tempdest(tempsrc+len-1))
{
while(i
{
*tempdest++ = *tempsrc++;
i++;
}
}
else
{
tempdest+=len;
tempsrc+=len;
i=len;
while(i>0)
{
*tempdest-- = *tempsrc--;
i--;
}
}
return dest;
}
注意,memcpy是對內(nèi)存的拷貝,對其他安全性不做考慮。用戶在使用這個函數(shù)時要小心,比如用它來拷貝字符串(當然如果是字符串拷貝肯定是用strncpy)就要注意末尾的\0字符之類的。
4. memset
memset函數(shù)的原型是:
void *memset(void *s, int ch, size_t n)
作用是把s所指向的地址開始的n個字節(jié)的內(nèi)容全部置位ch所指定的ASCII值。
一般經(jīng)常用memset對某段內(nèi)存空間置零。
經(jīng)常會出現(xiàn)的一個問題:在C++中,為什么不提倡在構(gòu)造函數(shù)中使用:memset(this,0,sizeof(*this))
原因: 在C++中,如果類中都是基本類型的數(shù)據(jù)成員并且沒有虛函數(shù)和虛繼承的話,使用memset這樣用到?jīng)]有太多影響。
如果有虛函數(shù),memset會把虛表指針等全部置零,對類會產(chǎn)生破壞。
【C語言字符串操作函數(shù)及常用的實現(xiàn)】相關(guān)文章:
C語言中返回字符串函數(shù)的實現(xiàn)方法09-19
C語言之字符串處理函數(shù)08-31
php的字符串常用函數(shù)06-15
C語言程序的實現(xiàn)09-27
C語言的底層操作08-23
C語言字符串知識點07-27
c語言數(shù)學函數(shù)的介紹10-20
C語言函數(shù)遞歸教程09-25