C语言字符串操作函数及常用的实现

字符串操作函数
 
atof() 将字符串转换成浮点数
atoi() 将字符串转换成整数
atol() 将字符串转换成长整型数
gcvt() 将浮点型数转换为字符串(四舍五入)
strtod() 将字符串转换成浮点数
strtol() 将字符串转换成长整型数
strtoul() 将字符串转换成无符号长整型数
toascii() 将整数转换成合法的ASCII码字符
tolower() 将大写字母转换为小写字母
toupper() 将小写字母转换为大写字母
index() 查找字符串并返回首次出现的位置
rindex() 查找字符串并返回最后一次出现的位置
strcasecmp() 判断字符串是否相等(忽略大小写)
strcat() 连接字符串
strcmp() 根据ASCII码比较字符串
strcoll() 根据环境变量LC_COLLATE来比较字符串
strcpy() 复制字符串
strcspn() 查找字符串并返回首次出现的位置
strchr() 查找字符串并返回首次出现该字符的地址
strdup() 复制字符串
strlen() 返回字符串长度
strncasecmp() 比较字符串的前n个字符
strncat() 拼接字符串(取前n个字符)
strncpy() 复制字符串(取前n个字符)
strpbrk() 定位字符串中第一个出现的指定字符
strrchr() 定位字符串中最后出现的指定字符
strspn() 返回从字符串开头连续包含特定字符的字符数目
strstr() 返回指定字符串第一次出现的地址
strtok() 字符串分割
 


面试官很喜欢让求职者写一些常用库函数的实现,有很多是和字符串相关的,有一些是关于内存拷贝的。一般,常会让写的函数有以下几个:

strcpy , strncpy, memcpy。

memset一般不会让去写,但这个函数也很有特点,有很多容易用错的地方。一并总结吧。

1.  strcpy

strcpy函数的原型是:

char * strcpy(char* dest, const char* src)

strcpy的实现经常要注意的细节是:

(1)判断地址是否为空,个人感觉可以使用断言

(2)参数只有两个地址,没有拷贝的长度。拷贝到'\0‘时就会终止,要保证最终dest末尾是'\0'。

(3)要保证目标字串的长度足够,能够容纳原串的长度。

(4)因为拷贝是dest会移动,而最终要返回的是拷贝后字符串的起始地址,因此要先保存dest的地址,便于最终返回。

          在实现这一点时,有两种方法。 char* temp=dest; 拷贝时移动dest返回temp,或者拷贝时移动temp返回dest,不知道哪个是对的。感觉两个都是没有问题的

 其中一种实现方式:

[cpp]  view plain copy
  1. char* mystrcpy(char* dest,const char* src)  
  2. {  
  3.     assert(dest!=NULL && src!=NULL);  
  4.   
  5.     char* temp=dest;  
  6.   
  7.     while((*temp++ = *src++ )!='\0')  
  8.     {}  
  9.   
  10.     return dest;  
  11. }  


2. strncpy

strncpy的功能和strcpy相似,只是它复制时多了一个终止条件。即是未遇到原串的'\0’,如果已经复制了n个字符(n为提供的参数长度),复制同样会终止。

strcpy的实现要注意的细节也基本适用于strncpy的实现。

 

实现方式:

[cpp]  view plain copy
  1. char* mystrncpy(char* dest, const char* src, int len)  
  2. {  
  3.     assert(dest!=NULL && src!=NULL);  
  4.   
  5.     char* temp=dest;  
  6.     int i=0;  
  7.   
  8.     while(i++ < len  && (*temp++ = *src++)!='\0')  
  9.     {}  
  10.   
  11.     if(*(--temp)!='\0')  
  12.         *temp='\0';  
  13.   
  14.     return dest;  
  15. }  
[cpp]  view plain copy
  1. 注意:刚开始我写strncpy的实现时,把while(i++ < len && (*temp++ = *src++)!='\0')写成了while( (*temp++ = *src++)!='\0' && i++ < len); 导致最后多复制了一个字符,明白为什么吧。。  

 

3. memcpy

memcpy和strncpy有些类似,但也有本质的不同。

(1)strncpy只能复制字符串,但memcpy对类型没有要求。

(2)strncpy有两个终止条件,memcpy只有一个终止条件,那就是复制n个字节。(n是memcpy的第三个参数)

(3)要特别注意目的地址和源地址重合的问题,拷贝前要加以判断。

(4)实现这个函数时一般要把原来的指针类型转换成char*,这样每次移动都是一个字节。

 

实现方式:(考虑了两个地址空间是否会有重叠)

[cpp]  view plain copy
  1. void* mymemcpy(void* dest, void* src, int len)  
  2. {  
  3.     int i=0;  
  4.     char* tempdest=(char*)dest;  
  5.     char* tempsrc=(char*)src;  
  6.   
  7.     if(tempdest<tempsrc || tempdest>(tempsrc+len-1))  
  8.     {  
  9.         while(i<len)  
  10.         {  
  11.             *tempdest++ = *tempsrc++;  
  12.             i++;  
  13.         }  
  14.     }  
  15.     else  
  16.     {  
  17.         tempdest+=len;  
  18.         tempsrc+=len;  
  19.         i=len;  
  20.         while(i>0)  
  21.         {  
  22.             *tempdest-- = *tempsrc--;  
  23.             i--;  
  24.         }  
  25.     }  
  26.     return dest;  
  27. }  

注意,memcpy是对内存的拷贝,对其他安全性不做考虑。用户在使用这个函数时要小心,比如用它来拷贝字符串(当然如果是字符串拷贝肯定是用strncpy)就要注意末尾的\0字符之类的。

4. memset

memset函数的原型是:

void *memset(void *s, int ch, size_t n)

作用是把s所指向的地址开始的n个字节的内容全部置位ch所指定的ASCII值。

一般经常用memset对某段内存空间置零。

 

经常会出现的一个问题:在C++中,为什么不提倡在构造函数中使用:memset(this,0,sizeof(*this))

原因: 在C++中,如果类中都是基本类型的数据成员并且没有虚函数和虚继承的话,使用memset这样用到没有太多影响。

如果有虚函数,memset会把虚表指针等全部置零,对类会产生破坏。

 



参考http://see.xidian.edu.cn/cpp/u/hs2/和http://blog.csdn.net/ydtbk/article/details/22697891








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值