C语言中的字符串处理函数

1、strcpy():复制字符串(不安全)

2、strncpy():复制n个字符串(安全)

3、strcat():连接字符串(不安全)

4、strncat():连接n个字符串(安全)

5、strcmp():字符串比较,C语言中字符串比较不能用=

6、strlen():字符串长度

7、strset():字符串重置

9、memset():内存重置

10、memcpy():内存复制(不安全)

11、memmove():内存复制(安全) 

12、strstr():字符串中查询字符串函数,若找到返回位置,否则返回Null    

13、strchr():字符串中查询字符的函数,若找到返回位置,否则返回Null 

14、strtok():分解字符串为一组字符串,使用方法如下


1、strcpy():复制字符串(不安全)

  • 原型:char *strcpy(char *dest, const char *src);
  • 功能:把src所指由'\0'结束的字符串复制到dest所指的数组中。
  • 说明:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。
  • 返回:指向dest的指针。

    注意:当src串长度>dest串长度时,程序仍会将整个src串复制到dest区域,可是dest数组已发生溢出。因此会导致dest栈空间溢出以致产生崩溃异常。当达到最大尺寸时,它只是停止复制字符。

char* myStrcpy(char* pre, const char* next)
{
    char out = pre;
    if (pre == nullptr || next == nullptr)  //空指针直接返回
    {
        return nullptr;
    }
    if (pre == next)                       // 两者相等也无需拷贝了
        return pre;

    while ((*pre++ = *next++) != '\0');    // 依次赋值给主字符数组
    return out;
}

    上面程序实现了strcpy的程序,实现很简单依次赋值给朱字符数组即可,当遇到next指向字符串结束字符’\0’后,完成赋值并且停止赋值。这样新赋值的’\0’就成了字符数组表示的字符串结尾符,哪怕主字符串pre比next长也会戛然而止。字符串判断不管字符数组存了啥,它只认到’\0’前的数是它的主体核心部分。strcpy没有检查长度会溢出,推荐使用strncpy

2、strncpy():复制n个字符串(安全)

  • 原型:char * strncpy(char*dest, char *src, size_t n);
  • 功能:将字符串src中最多n个字符复制到字符数组dest中(它并不像strcpy一样遇到NULL才停止复制,而是等凑够n个字符才开始复制),
  • 返回:指向dest的指针。

    说明:如果n > dest串长度,dest栈空间溢出。否则:
  1)src串长度<=dest串长度,(这里的串长度包含串尾NULL字符)
      如果n=(0, src串长度),src的前n个字符复制到dest中。但是由于没有NULL字符,所以直接访问dest串会发生栈溢出的异常情况。
      如果n = src串长度,与strcpy一致。
      如果n = dest串长度,[0,src串长度]处存放src字串,(src串长度, dest串长度]处存放NULL。
  2)src串长度>dest串长度
      如果n =dest串长度,则dest串没有NULL字符,会导致输出会有乱码。

char *strncpy(char *strDest , const char *strSrc , int n)
{
	assert((strDest != NULL) && (strSrc != NULL));
	char *address = strDest;
	while(n-- > 0)
		*strDest++ = *strSrc++;
	return address;
}

3、strcat():连接字符串(不安全)

  • 函数原型:char* strcat(char* des, char* src)
  • 函数功能:把src所指向的字符添加到dest结尾处(覆盖原dest结尾处的'\0'),并添加新的'\0'。
  • 说明:des 和 src 所指内存区域不可以重叠且 des 必须有足够的空间来容纳 src 的字符串。
  • 返回值:指向des的指针

    strcat函数常见的错误就是数组越界,即两个字符串连接后,长度超过第一个字符串数组定义的长度,导致越界。

char* myStrcat(char* pre, const char* next)
{
    if (pre == nullptr || next == nullptr) // 如果有一个为空指针,直接返回pre
        return pre;
    char* tmp_ptr = pre + strlen(pre); //strlen计算字符数,需要包含都文件string.h,当然也可以自己实现
    while ( (*tmp_ptr++ = *next++) != '\0'); // 依次接着赋值
    return pre;
}

由于strcat也容易造成缓冲区溢出,因此推荐使用strncat.

4、strncat():连接n个字符串(安全)

    strncat把src所指向的字符的前n个字符添加到dest结尾处(覆盖原dest结尾处的'\0'),并添加新的'\0'。src和dest所指内存区域不可以重叠,并且dest必须有足够的空间来容纳src的前n个字符串,返回指向dest的指针。

char *strncat(char *dest,const char *str,int n)
{
	assert((dest!=NULL)&&(str!=NULL));
	char *cp=dest; 
	while(*cp!='\0') ++cp;
 
	while(n&&(*cp++=*str++)!='\0')
	{
		--n;
	} 
	return dest;
}

    由于这四个函数都可能造成缓冲区溢出,在VS2015中已经禁用这几个函数。

5、strcmp():字符串比较,C语言中字符串比较不能用=

     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'为止,就能得出结果。代码实现如下(参考):

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;
}

6、strlen():字符串长度

  strlen()用于计算字符数组长度,到字符串结束符’\0’即停止。如:

char nzArr[] = "abcdef";
int nLen = strlen(nzArr);    //结果为6,并不是100,和分配数组内存大小无关,不包含'/0'
int nLen = sizeof(nzArr);    //结果为7,包括'/0'

7、strset():字符串重置

   strset()用于设定字符数组全为某一字符,如果存在‘\0’结束符,遇结束符停止赋值。

char nzArr[100]="abcd";
strset(nzArr,'g');  //nzArr结果为“gggg”,如果未初始化,则100个空间都为'g'

9、memset():内存重置

 memset()与strset()类似,赋值字符数组指定字符,但可以指定个数。

char nzArr[100]="abcd";
memset(nzArr,'g',sizeof(nzArr));  //nzArr中全为g,该函数是空间操作,不遇'\0'停止,输出g后会出现乱码

10、memcpy():内存复制(不安全)

    memcpy()由src指向地址为起始地址的连续n个字节的数据复制到以destin指向地址为起始地址的空间内。 

  • 函数原型为:void *memcpy(void*dest, const void *src, size_t n);
  • 函数返回一个指向dest的指针。

    函数实现:

void* memcpy(void* dest, const void* src, size_t n)
{
    char*      d = (char*) dest;
    const char*  s = (const char*) src;
    while(n-–)
       *d++ = *s++;
    return dest;
}

    strcpy和memcpy主要有以下3方面的区别。

  • 复制的内容不同。strcpy只能复制字符串,而memcpy可以复制任意内容,例如字符数组、整型、结构体、类等。
  • 复制的方法不同。strcpy不需要指定长度,它遇到被复制字符的串结束符"\0"才结束,所以容易溢出。memcpy则是根据其第3个参数决定复制的长度。
  • 用途不同。通常在复制字符串时用strcpy,而需要复制其他类型数据时则一般用memcpy。
#include<stdio.h>
#include<string.h>
int main(){
  char*s="Golden Global View";
  chard[20];
  clrscr();
  memcpy(d,s,strlen(s));
  d[strlen(s)]='\0';      //因为从d[0]开始复制,总长度为strlen(s),d[strlen(s)]置为结束符
  printf("%s",d);
  getchar();
  return0;
}
输出结果:GoldenGlobal View

11、memmove():内存复制(安全) 

    memcpy与memmove的目的都是将N个字节的源内存地址的内容拷贝到目标内存地址中。但当源内存和目标内存存在重叠时,memcpy会出现错误,而memmove能正确地实施拷贝,但这也增加了一点点开销。memmove的处理措施:

  • (1)当源内存的首地址等于目标内存的首地址时,不进行任何拷贝
  • (2)当源内存的首地址大于目标内存的首地址时,实行正向拷贝
  • (3)当源内存的首地址小于目标内存的首地址时,实行反向拷贝
  • 函数原型:void* memmove(void* dest, const void* src, size_t n)
  • 返回值:函数返回一个指向dest的指针。

    函数实现:

void* memmove(void* dest, const void* src, size_t n)
{
    char*     d  = (char*) dest;
    const char*  s = (const char*) src;
  
    if (s>d)
    {
         // start at beginning of s
         while (n--)
            *d++ = *s++;
    }
    else if (s<d)
    {
        // start at end of s
        d = d+n-1;
        s = s+n-1;
  
        while (n--)
           *d-- = *s--;
    }
    return dest;
}

12、strstr():字符串中查询字符串函数,若找到返回位置,否则返回Null    

char *strchr(const char *s, int c)
{
    if(s == NULL)
    {
        return NULL;
    }
    while(*s != '\0')
    {
        if(*s == (char)c )
        {
            return (char *)s;
        }
        s++;
    }
    return NULL;
}

13、strchr():字符串中查询字符的函数,若找到返回位置,否则返回Null 

char *strstr(char*str, char *subStr)
{
    while (*str != '\0') {
       char *p = str;
       char *q = subStr;
       char *res = NULL;
       if (*p == *q) {
           res = p;
           while (*q != '\0' && *p == *q){
               p++;
               q++;
           }
           if (*q =='\0')
               return res;
       }
       str++;
    }
}
char nzArr[10] = "ababcde";
char nzBuf[10] = "abc";
char* nzCount  = (char*)malloc(sizeof(char)*10);
char* nzCount1 = (char*)malloc(sizeof(char)*10);//结果分配空间

memset(nzCount, 0, sizeof(nzCount));   //赋初值
memset(nzCount1, 0, sizeof(nzCount1)); //防止未匹配到指定字符或字符数组,而成为野指针
nzCount = strstr(nzArr, nzBuf);        //返回为'abcde'
nzCount1 = strstr(nzArr, 'c');         //返回为'cc'

    strstr()和strchr()都是查找第二个参数第一次出现在第一个字符数组的位置,前者是查找字符数组,而后者是字符。但是注意返回,返回的是参数出现的地址,需要赋给char*指针来存储,而不是一个索引。 

14、strtok():分解字符串为一组字符串,使用方法如下:

#include <string.h>
#include <stdio.h> 
int main () 
{
   char str[80] = "This is - www.runoob.com - website";
   const char s[2] = "-";
   char *token;
   token = strtok(str, s);   
   while( token != NULL ) 
   {
      printf( "%s\n", token );    
      token = strtok(NULL, s);
   }   
   return(0);
}

参考:https://blog.csdn.net/FX677588/article/details/76702319

          https://blog.csdn.net/lanzhihui_10086/article/details/39828901

          https://blog.csdn.net/wgenek/article/details/7257435

         https://blog.csdn.net/fx677588/article/details/53102634

         https://www.cnblogs.com/kekec/archive/2011/07/22/2114107.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值