【C语言】常见字符串函数总结及模拟实现

目录

**

strlen strcpy strncpy strcat strncat strcmp strstr strrev

**


strlen

size_t strlen( const char* string )

功能:计算字符串中\0之前的字符的个数,不包括\0。

返回值:字符串中字符的个数。

  • 参数指向的字符串必须要以’ \0 '结束
  • strlen函数返回的是在字符串中’ \0 ‘前面出现的字符个数(不包含’ \0 ')
  • 函数的返回值为size_t,是无符号整型(unsigned int)

模拟实现

#include<stdio.h>
#include<assert.h>

//count计数法
unsigned int my_strlen(const char* string)
{
    //断言,保证指针的有效性,防止野指针
    assert(string!=NULL);
	unsigned int count = 0;
	while(*string)
	{
		count++;
		string++;
	}
	return count;
}

//递归法
unsigned int my_strlen(const char* string)
{
    assert(string!=NULL);
	if (*string)
		return 1 + my_strlen(string + 1);
	else
		return 0;
}

//指针-指针法
unsigned int my_strlen(const char* string)
{
    assert(string!=NULL);
	//const修饰的安全的指针交给一个不安全的char*的指针是要强制类型转换
	char* tmp = (char*)string;
	while (*string)
	{
		string++;
	}
	return string - tmp;
}

int main()
{
	char arr[] = "abcdef";
	printf("%d\n", my_strlen(arr));
	return 0;
}

在这里插入图片描述

strcpy

char* strcpy(char* destination,const char* source)

功能:拷贝源字符串的内容到目的地字符串。

返回值:目的地字符串的首字符地址。

  • 源字符串必须以’ \0 '结束
  • 会将源字符串中的’ \0 '也拷贝到目标空间
  • 目标空间必须足够大,以确保能存放源字符串
  • 目标空间必须可变(不能为常量字符串)

模拟实现

#include<stdio.h>
#include<assert.h>

char* my_strcpy(char* dest, const char* src)
{
    //断言,保证指针的有效性,防止野指针
	assert(dest != NULL);
	assert(src != NULL);
	//先保存好目的地字符串首元素地址,最后要返回它
	char* tmp = dest;
	while (*dest++ = *src++)
	{
		;
	}
	return tmp;
}

int main()
{
	char arr1[] = "abcdefg";
	char arr2[] = "hijklmn";
	printf("arr1=%s\n", my_strcpy(arr1, arr2));
	return 0;
}

在这里插入图片描述

strncpy

char *strncpy( char *strDest, const char *strSource, size_t count );

功能:从头开始,拷贝源字符串的n个字符到目的地字符串。

返回值:返回源头字符串的首元素地址。

  • 暴力拷贝n个,无所谓越界
  • 最后不会自动加上’ \0 ’

模拟实现

#include<stdio.h>
#include<assert.h>

char* my_strncpy(char* dest, const char* src, size_t n)
{
	//断言,保证指针的有效性
	assert(dest != NULL);
	assert(src != NULL);
	//先保存好目的地字符串首元素地址,最后要返回它
	char* tmp = dest;
	//开始拷贝
	while (n--)
	{
		*dest++ = *src++;//自增最后才进行
	}
	//返回目的地字符串首元素地址
	return tmp;
}

int main()
{
	char arr1[10] = "abcde";
	char arr2[5] = "fgh";
	printf("%s\n", my_strncpy(arr1,arr2,3));
	return 0;
}

在这里插入图片描述

strcat

char* strcat( char* strDestination, const char* strSource )

功能:拼接字符串。

返回值:目的地字符串的首元素地址。

  • 源字符串必须以 ‘\0’ 结束(最后’ \0 '也会拼接上去)
  • 从目的地字符串’ \0 ‘的位置开始拼接(覆盖目的地字符串的’ \0 ')
  • 目标空间必须可修改(不能为常量字符串)
  • 目标空间必须有足够的大,能容纳下源字符串的内容

模拟实现

#include<stdio.h>
#include<assert.h>

char* my_strcat(char* dest, const char* src)
{
	//先保存好目的地字符串首元素地址,最后要返回它
	char* tmp = dest;
	//断言,保证指针的有效性,防止野指针
	assert(dest != NULL);
	assert(src != NULL);
	//找到dest字符串中'\0'的地址
	while (*dest)
	{
		dest++;
	}
	//开始拼接
	while (*dest++ = *src++)//自增最后才进行
	{
		;
	}
	return tmp;
}

int main()
{
	char arr1[30] = "abcdefg";
	char arr2[] = "hijklmn";
	printf("arr1=%s\n", my_strcat(arr1, arr2));
	return 0;
}

在这里插入图片描述

strncat

char *strncat( char *strDest, const char *strSource, size_t count );

功能:指定拼接n个拼字符

返回值:目的地字符串的首元素地址。

  • 从目的地字符串最后的’ \0 ‘位置开始拷贝,拷贝完成后不会自动追加’ \0 ’
  • 目的地字符串的空间必须大于源头字符串
  • 目的地字符串剩余的空间必须大于等于n+1(防止目的地字符串被越界拷贝)
  • n不能大于源头字符串的大小(防止源头字符串被越界访问)

模拟实现

#include<stdio.h>
#include<assert.h>

char* my_strncat(char* dest, const char* src, size_t n)
{
	//断言,保证指针的有效性
	assert(dest != NULL);
	assert(src != NULL);
	//防止源头字符串越界访问(怎么防止目的地字符串被越界拷贝我还没想出来...)
	assert(n < sizeof(src));
	//记录源头字符串的首元素地址,最后返回它
	char* tmp = dest;
	//寻找源头字符串'\0'的位置
	while (*dest++)//自增最后才进行
	{
	}
	//开始拼接
	while (n--)
	{
		*dest = *src;
	}
	return tmp;
}

int main()
{
	//测试
	char arr1[8] = "abcde";
	char arr2[3] = "fgh";
	printf("%s\n", my_strncat(arr1,arr2,2));
	return 0;
}

在这里插入图片描述

strcmp

int strcmp( const char* string1, const char* string2 )

功能:比较到出现字符不一样或者一个字符串结束或者num个字符全部比较完。

返回值:若str1>str2返回一个大于零的数字;若str1=str2返回0;若str1<str2返回一个小于零的数字。

  • 从头开始一个字符一个字符的比较,若两个字符相等有两种情况1.两个字符都为’ \0 ‘结果返回0;2.相同的非’ \0 '字符那就继续下一个字符的比较。
  • 若比较到两个字符不同,则对应字符ASCLL编码大的所在的字符串更大。

模拟实现

#include<stdio.h>
#include<assert.h>

int my_strcmp(const char* str1, const char* str2)
{
	//断言,判断指针的有效性,防止野指针
	assert(str1 != NULL);
	assert(str2 != NULL);
	while (*str1==*str2)
	{
		if (*str1 == '\0')//相等的情况
		{
			return 0;
		}
		str1++;
		str2++;
	}
	if (*str1 > *str2)
		return 1;
	else
		return -1;
}

int main()
{
	char arr1[] = "abcd";
	char arr2[] = "abcz";
	printf("%d\n", my_strcmp(arr1, arr2));
	return 0;
}

在这里插入图片描述

strstr

char* strstr( const char* string1, const char* string2 );

功能:在string1中查找是否有string2子串。

返回值:若找到了,返回子串的首元素地址;若没找到,返回空指针。

#include<stdio.h>
#include<assert.h>

char* my_strstr(const char* str1, const char* str2)//const修饰的安全的指针,在赋值给不安全的指针变量和作为返回值时要进行相应的强制类型转换
{
    //断言,判断指针的有效性,防止野指针
	assert(str1 != NULL);
	assert(str2 != NULL);
	char* cur = (char*)str1;
	//当需要查找的字符串为空字符串时,返回这个空字符串
	if (*str2 == '\0')
	{
		return (char*)str2;
	}
	while (*cur)
	{
		//记录匹配的位置
		char* s1 = cur;
		char* s2 = (char*)str2;
		//开始匹配
		while ((*s1 != '\0') && (*s2 != '\0') && (*s1 == *s2))
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')//匹配成功的情况
		{
			return cur;
		}
		if (*s1 == '\0')
		{
			return NULL;//匹配失败的一种情况,尽早退出(例如abc  abcdef)
		}
		cur++;
	}
	return NULL;//匹配失败,找不到子串
}

int main()
{
	char arr1[] = "abbbcdef";
	char arr2[] = "bbc";
	char* ret = my_strstr(arr1, arr2);
	if (ret != NULL)
		printf("找到了:%s\n", ret);
	else
		printf("子串不存在\n");
	return 0;
}

在这里插入图片描述

strrev

char* strrev( char *string );

功能:把字符串string的字符内容顺序颠倒。(逆序)

返回值:返回逆序后的字符串的首元素地址。

模拟实现

#include<stdio.h>
#include<string.h>
#include<assert.h>

//令left指向最左边的元素,right指向最右边的元素,交换两个位置元素的值之后left++,right- -,逐渐靠近,直到letf>=right为止。
char* my_strrev(char* string)
{
	assert(string != NULL);//断言,保证指针的有效性,防止野指针
	char* tmp1 = string;//记住该字符串的首元素地址,最后返回
	char* left = string;//left为最左边元素地址
	char* right = string + strlen(string) - 1;//right为最右边元素地址('\0'前面的那个)
	while (left < right)
	{
		//开始交换两头的字符
		char tmp2 = *left;
		*left = *right;
		*right = tmp2;
		left++;
		right--;
	}
	return tmp1;
}

int main()
{
	char arr[] = "abcdef";
	printf("%s\n", my_strrev(arr));
	return 0;
}

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值