当前位置:学者斋 >

计算机 >C语言 >

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

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

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

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

strcpy , strncpy, memcpy。

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

字符串操作函数
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()字符串分割

  1. strcpy

strcpy函数的原型是:

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

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

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

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

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

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

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

其中一种实现方式:

[cpp] view plaincopychar* mystrcpy(char* dest,const char* src)

{

assert(dest!=NULL && src!=NULL);

char* temp=dest;

while((*temp++ = *src++ )!='')

{}

return dest;

}

  2. strncpy

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

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

实现方式:

[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++)!='')

{}

if(*(--temp)!='')

*temp='';

return dest;

}

[cpp] view plaincopy注意:刚开始我写strncpy的实现时,把while(i++ < len && (*temp++ = *src++)!='')写成了while( (*temp++ = *src++)!='' && i++ < len); 导致最后多复制了一个字符,明白为什么吧。。

  3. memcpy

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

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

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

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

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

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

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

  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会把虚表指针等全部置零,对类会产生破坏。

标签: 字符串 函数 语言
  • 文章版权属于文章作者所有,转载请注明 https://xuezhezhai.com/jsj/cyuyan/9mg2l.html