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

1、strcpy():复制字符串

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

3、strcat():连接字符串

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

5、strcmp():字符串比大小

6、strlen():字符串长度

7、strset():字符串重置

9、memset():内存重置

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

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

12、strstr()、strchr():查找后一个字符出现的地址

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)
{
    if (pre == nullptr || next == nullptr)  //空指针直接返回
    {
        return nullptr;
    }
    if (pre == next)                       // 两者相等也无需拷贝了
        return pre;
 
    while ((*pre++ = *next++) != '\0');    // 依次赋值给主字符数组
    return pre;
}
    上面程序实现了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():字符串比大小
     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()、strchr():查找后一个字符出现的地址
  strstr()和strchr()都是查找第二个参数第一次出现在第一个字符数组的位置,前者是查找字符数组,而后者是字符。但是注意返回,返回的是参数出现的地址,需要赋给char*指针来存储,而不是一个索引。

char nzArr[10] ="ababcde",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'
参考: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

原文:https://blog.csdn.net/MOU_IT/article/details/88975116 
 

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值