字符串函数和内存函数的实现

本文详细介绍了C语言中常用的字符串处理函数,包括strlen用于计算字符串长度,strcpy和strcat用于字符串复制和连接,strcmp用于比较字符串,strstr用于查找子字符串,strtok用于分割字符串,以及内存操作函数memcpy和memmove用于数据复制,最后提到了memcmp用于比较内存区域。每个函数都附带了注意事项和简单的模拟实现,帮助理解其工作原理。
摘要由CSDN通过智能技术生成

一. strlen函数
参数类型:
size_t strlen ( const char * str );
注意事项:
1. 字符串已经 ‘\0’ 作为结束标志,strlen函数返回的是在字符串中 ‘\0’ 前面出现的字符个数(不包含 ‘\0’ )。
2.参数指向的字符串必须要以 ‘\0’ 结束。
3.注意函数的返回值为size_t,是无符号的( 易错 )

#include <stdio.h>
int main()
 {
   const char*str1 = "abcdef"; 
   const char*str2 = "bbb"; 
      if(strlen(str2)-strlen(str1)>0) 
     { printf("str2>str1\n"); }  
          else
        {
            printf("srt1>str2\n");
        }
            return 0;
 }        

在这里插入图片描述
因为strlen点的返回值是size_t (unsigned int),所以两个返回值相减依旧是unsigned int 型,是一个无符号的整数,也就是大于零。

strlen函数的模拟实现:

int main()
{
	  char arr[] = "panzii666";
	  char* parr = arr;
	  int count = 0;
	  while (*parr != '\0')
	  {
		  ++parr;
		  count++;
	  }
	  printf("%d", count);
	  return 0;
}

二.strcpy函数
参数类型:
char* strcpy(char * destination, const char * source );
注意事项:
1.源字符串必须以 ‘\0’ 结束。
2.会将源字符串中的 ‘\0’ 拷贝到目标空间。
3.目标空间必须足够大,以确保能存放源字符串。目标空间必须可变。

char* my_strcpy(char* dest,char* src)
{
    char* ret = dest;
    while(*src != '\0')
    {
        *dest = *src;
        dest++;
        src++;
    }
    *dest = *src;
    return ret;
}
int main()
{
     char arr1[20] = "panzii666";
     char arr2[10] = "xxxxx";
     char*ret= my_strcpy(arr1,arr2);
     printf("%s", arr1);
     return 0;
}

三.strcat函数
参数类型:
char * strcat ( char * destination, const char * source );
注意事项:
1.源字符串必须以 ‘\0’ 结束。
2.目标空间必须有足够的大,能容纳下源字符串的内容。目标空间必须可修改。
3.自己给自己追加如何?
答案:trcat函数在执行追加操作时需要依赖null字符来确定字符串的末尾位置,否则它就无法正确地将字符串追加到目标字符串的末尾。

如果你试图将一个字符串追加到自身,那么源字符串的末尾将不再是null字符,而是源字符串的最后一个字符。这将导致strcat函数无法正确判断目标字符串的末尾位置,可能会导致错误的结果或者内存溢出。

strcat 函数的模拟:

char* my_strcat(char* dest, char* src)
{
    assert(dest && src);
    char* ret = dest;
    while (*dest != '\0')
    {
        dest++;
    }
    while (*src != '\0')
    {
        *dest = *src;
        dest++;
        src++;
    }
         *dest = *src;
         return ret;
}
int main()
{
        char arr1[20] = "panzii666";
         char arr2[10] = "xxxxx";
         my_strcat(arr1, arr2);
         printf("%s", arr1);
         return 0;
}

四.strcmp函数
参数类型:
int strcmp ( const char * str1, const char * str2 );
注意事项:
1.第一个字符串大于第二个字符串,则返回大于0的数字
第一个字符串等于第二个字符串,则返回0
第一个字符串小于第二个字符串,则返回小于0的数字
strcmp函数的模拟:

int my_strcmp(char* arr1, char* arr2)
{
    while (*arr1==*arr2)
    {
        if (*arr1 == '\0')
            return 0;
        arr1++;
        arr2++;
    }
    if (*arr1 > *arr2)
        return 1;
    else
        return -1;
          
}
int main()
{
    char arr1[20] = "panzii666";
    char arr2[10] = "xxxxx";
    int ret= my_strcmp(arr1, arr2);
    printf("%d", ret);
    return 0;
}

五.strstr函数
参数类型:
char * strstr ( const char *str1, const char * str2);
注意事项:
1.这是一个查找字符串的函数,在第一个字符串中查找第二个字符串,并且返回第一次找到完整的第二个字符串的首地址。
a b b b c d e f
b b c
模拟实现strstr函数:

char* my_strstr(char* arr1,char* arr2)
{
	char* s1 = arr1;
	char* cp = s1;
	char* s2 = arr2;
	while (*cp)
	{
		s1 = cp;
		s2 = arr2;
		while(*s1 && *s2 && *s1 == *s2)
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')
			return cp;
		cp++;
	}
	return NULL;
}
int main()
{
	  char arr1[] = "abbbcdef";
	  char arr2[] = "bbc";
	  char* ret=my_strstr(arr1, arr2);
	  printf("%s", ret);
	   return 0;
}

六.strtok函数
参数类型:
char * strtok ( char * str, const char * sep );
注意事项:
sep参数是个字符串,定义了用作分隔符的字符集合
第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记。
strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)
strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
如果字符串中不存在更多的标记,则返回 NULL 指针。
1.

#include <stdio.h>
#include <string.h>
int main ()
{
  char str[] ="- This, a sample string."; 
   char * pch;  
   printf ("Splitting string \"%s\" into tokens:\n",str); 
    pch = strtok (str," ,.-"); 
     while (pch != NULL)
 {
    printf ("%s\n",pch);  
      pch = strtok (NULL, " ,.-"); } 
       return 0;
}
#include <stdio.h>
int main()
{
   char *p = "zhangpengwei@bitedu.tech"; const char* sep = ".@"; char arr[30]; char *str = NULL;
 strcpy(arr, p);//将数据拷贝一份,处理arr数组的内容
 for(str=strtok(arr, sep); str != NULL; str=strtok(NULL, sep))
 {
 printf("%s\n", str);
 }
}

这个for循环在这里用的非常的妙,将一段重复的代码用for循环完美解决。
七.内存函数memcpy
参数类型:
void * memcpy ( void * destination, const void * source, size_t num );
注意事项:
1.函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。
2.这个函数在遇到 ‘\0’ 的时候并不会停下来。
3.如果source和destination有任何的重叠,复制的结果都是未定义的。
4.memcpy也可以实现memmove的功能,不过是在源地址在目标地址之后用这个函数才可以实现。

void * memcpy ( void * destination, const void * source, size_t num );
#include<stdio.h>
void* my_memcpy(void* dest, const void* src, size_t num){
    void* ret = dest;
    while (num--)
    {
        *((char*)dest) = *((char*)src);
        dest = ++(char*)dest;
        src = ++(char*)src;
    }
     return ret;
}
int main()
{
    int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
    int arr2[20] = { 0 };
    my_memcpy(arr2, arr1, 40);//这里40代表字节,而不是个数

    for (int i = 0; i < 20; i++)
    {
        printf("%d ", arr2[i]);
    }
    return 0;
}

八. 内存函数memmove
参数类型:
void * memmove ( void * destination, const void * source, size_t num );
注意事项:
1.和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。如果源空间和目标空间出现重叠,就得使用memmove函数处理。

如图:
从后往前
 前:1 2 5 6 7 8 9 8 9 10
 后:1 2 1 2 3 4 5 8 9 10
从前往后:
 前:1 2 3 4 5 6 7 8 9 10
 后:1 2 1 2 3 4 5 8 9 10
#include<string.h>
void* my_memmove(void* dest, const void* src, size_t num)
{
    void* ret = dest;
    if (src > dest)
    {
        void* ret = dest;
                while (num--)
                {
                    *((char*)dest) = *((char*)src);
                    dest = ++(char*)dest;
                    src = ++(char*)src;
                }
                 return ret;
    }
    else if(src < dest)
    {
        void* ret = dest;
        while (num--)
        {
            *((char*)dest + num) = *((char*)src + num); 
        }
    }
    else
    {
        return 0;
    }
    return ret;
}
int main()
{
    int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
      my_memmove(arr , arr+2, 20);从前往后
    //my_memmove(arr+2, arr,  20);从后往前
    for (int i = 0; i < 10; i++)
    {
        printf("%d ", arr[i]);
    }
    return 0;
}

这张图分为三种情况:
在这里插入图片描述
九.内存函数 memcpy
类型参数:
int memcmp ( const void * ptr1, const void * ptr2, size_t num );
注意事项:
1.比较从ptr1和ptr2指针开始的num个字节
2.返回值如下:第一个字符串>第二个字符串 >0的数字
第一个字符串<第二个字符串 <0的数字
第一个字符串=第二个字符串 0

#include <stdio.h>
#include <string.h>
int main ()
{
  char buffer1[] = "DWgaOtP12df0";  char buffer2[] = "DWGAOTP12DF0";
  int n;
  n=memcmp ( buffer1, buffer2, sizeof(buffer1) );
  if (n>0) 
  printf ("'%s' is greater than '%s'.\n",buffer1,buffer2);  
  else if (n<0) 
  printf ("'%s' is less than '%s'.\n",buffer1,buffer2);  
  else printf ("'%s' is the same as '%s'.\n",buffer1,buffer2);
  return 0;
}

希望对大家有所帮助,大家多多支持我吧!谢谢!

评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值