字符串函数和内存函数详解(1)

本文将通过函数原型、用法、模拟实现等多个方面全面讲解字符串的库函数

字符串函数和内存函数详解(1)_第1张图片

1.strlen

1.1函数用法

strlen函数用来计算字符串的长度,它会从接收到字符的地址开始读取直到遇到'\0',每读取一个非'\0'的字符长度+1,最后返回一个size_t(无符号)类型的数

strlen函数原型:

字符串函数和内存函数详解(1)_第2张图片

返回类型为size_t,参数是一个字符指针用来接收字符的地址

1.2具体实现

#include
#include //记得加上头文件

int main()
{
	char arr[] = "abcedf";
	size_t len = strlen(arr);
	printf("%zd", len); //结果为6

	return 0;
}

1.3模拟实现

这里总结了三种strlen函数模拟实现的方法,分别为:计数器、指针-指针和递归

计数器

size_t my_strlen1(const char* arr) //计数器
{
	size_t count = 0;
	while (*arr++ != '\0')
	{
		count++;
	}
	return count;
}

递归

size_t my_strlen(const char* arr)
{
	if (*arr != '\0')
	{
		return 1 + my_strlen(++arr);
	}
	else
	{
		return 0;
	}
}

每次递归都判断以下arr指针是否指向'\0',如果是则返回0,不是则指向下一个字符进行判断并且长度+1

指针-指针

size_t my_strlen2(const char* arr)
{
	char* p = arr;
	while (*arr != '\0')
	{
		arr++;
	}

	return arr - p;
}

指针-指针用来计算两个指针之间元素的个数,先让p指向字符串的首地址,之后通过while循环使arr指向'\0',最后返回arr - p

2.strcpy

2.1函数用法

strcpy函数用来拷贝字符串将源数组中的字符串拷贝到目标数组中,但需要注意以下几点:

  • 目标数组可能没有'\0',所以strcpy再拷贝时会将源数组的'\0'也拷贝过去,也就是说源数组中必须有'\0'
  • 目标数组的空间必须足够大,确保其在被拷贝后能存放的下字符串
  • 目标数组必须可变,不能是常量字符串

strcpy函数原型:

返回类型为char*,destination用来接收目标数组的地址,source用来接收源数组的地址

2.2具体实现

#include
#include

int main()
{
	char arr1[20] = { 0 }; //目标数组空间确保能存放源数组
	char arr2[] = "abcdef";
	strcpy(arr1, arr2);
	printf("%s", arr1); //结果为abcdef

	return 0;
}

2.3模拟实现

#include 
#include

char* my_strcpy( char* des, const char*src)
{
	assert(des && src); //断言判断des和src是否时空指针
	char* ret = des; //将des的首地址赋给ret用来最后返回,因为des在++后不再指向首地址
	while (*des++ = *src++) //依次将字符赋给des直到'\0'循环终止
	{
		;
	}
	return ret;
}

int main()
{
	char arr1[] = "abcdef";
	char arr2[20] = { 0 };
	char* ret = my_strcpy(arr2, arr1);

	printf("%s", ret);
	return 0;
}

3.strcat

3.1函数用法

strcat函数用来追加字符串,将源数组加到目标数组的末尾,即从目标数组的'\0'位置处开始追加;和strcpy函数需要注意的点一样:

  • 源数组必须有'\0'
  • 目标数组的空间必须足够大
  • 目标数组必须可变,不能是常量字符串

strcat函数原型:

字符串函数和内存函数详解(1)_第3张图片

返回类型为char*,destination用来接收目标数组的地址,source用来接收源数组的地址

3.2具体实现

#include
#include

int main()
{
	char arr1[20] = "abc"; //目标空间必须足够大
	char arr2[] = "def";
	strcat(arr1, arr2);
	printf("%s", arr1); //结果为abcdef

	return 0;
}

3.3模拟实现

#include
#include

char* my_strcat(char* des, const char* src)
{
	assert(des && src); //断言判断des和src是否为空指针
	char* ret = des;
	while (*des != '\0') //先找到目标数组'\0'的位置
	{
		des++;
	}
	while (*des++ = *src++) //从目标数组的'\0'位置处开始依次将源数组拷贝到目标数组
	{
		;
	}
	return ret;
}

int main()
{
	char arr1[20] = "abc";
	char arr2[] = "def";
	char* ret = my_strcat(arr1, arr2);

	printf("%s", ret);
	return 0;
}


4.strcmp

4.1函数用法

strcmp函数用来比较字符串,从两个字符串的第一个字符开始依次比较它们的ASCII码值,只要出现一个字符大于另一个字符就停止比较,此时较大字符所在的字符串大于另一个字符串

strcmp函数原型:

字符串函数和内存函数详解(1)_第4张图片

str1和str2分别接收要比较的两个数组的地址,返回类型为int,str1>str2则返回一个大于0的数,str1

4.2具体实现

#include
#include

int main()
{
	char arr1[] = "abcfff";
	char arr2[] = "abczz";
	int cmp = my_strcmp(arr1, arr2);
	if (cmp > 0)
	{
		printf(">");    
	}
	else              
	{
		printf("<="); //结果为<=,因为f

4.3模拟实现

#include
#include

int my_strcmp(const char* str1, const char* str2)
{
	assert(str1 && str2);
	while (*str1++ == *str2++) //依次比较两字符串的字符
	{
		if (*str1 == '\0' && *str2 == '\0')
		{
			return 0; //若两字符串的字符一直到'\0'都相等,则相等,返回0
		}
	}
	return *str1 - *str2; //*str1大返回大于0的数,否则返回小于0的数
}

int main()
{
	char arr1[] = "abcfff";
	char arr2[] = "abczz";

	int cmp = my_strcmp(arr1, arr2);
	if (cmp > 0)
	{
		printf(">");
	}
	else
	{
		printf("<=");
	}
	return 0;
}

5.strncpy

5.1函数用法

strncpy函数原型:

这里相较于strcpy多了一个参数num

用法:和strcpy用法相同,但它是将源数组的前num个字符拷贝到目标数组中

5.2具体实现

#include

int main()
{
	char arr1[] = "abcdef";
	char arr2[20] = { 0 };
	size_t num = 3;

	strncpy(arr2, arr1, num); //将arr1的前三个字符拷贝到arr2中
	printf("%s", arr2);  //结果为abc
	
	return 0;
}

5.3模拟实现

和strcpy的模拟实现类似,只不过要加一条对n的判断以确保只拷贝前n个字符

#include
#include

char* my_strncpy(char* des, const char* src, size_t n)
{
	assert(des && src);
	char* ret = des;

	while (*des++ = *src++)
	{
		n--;
		if (n == 0)  
		{
			return ret;
		}
	}
}

int main()
{
	char arr1[] = "abcedf";
	char arr2[20] = { 0 };
	size_t num = 3;

	char* r = my_strncpy(arr2, arr1, num);

	printf("%s", r);
	return 0;
}

6.strncat

6.1函数用法

strncat函数原型:

用法:和strncat函数用法相同,但它是将数组的前num个字符追加到目标数组的'\0'处

6.2具体实现

#include
#include

int main()
{
	char arr1[20] = "abc\0xxx";
	char arr2[] = "defghi";
	size_t num = 3;

	strncat(arr1, arr2, num); //加完后会自动将\0加上
	printf("%s", arr1);
	return 0;
}

在arr1的'\0'处将def加上后会自动加一个'\0'以构成一个完整的字符串

字符串函数和内存函数详解(1)_第5张图片

6.2模拟实现

和strcat的模拟实现类似,只不过要加一条对n的判断以确保只追加前n个字符

#include
#include

char* my_strncat(char* des, const char* src, size_t n)
{
	char* ret = des;
	while (*des != '\0')
	{
		des++;
	}
	while (*des++ = *src++)
	{
		n--;
		if (n == 0)
		{
			*des = '\0';
			return ret;
		}
	}
}

int main()
{
	char arr1[20] = "abc";
	char arr2[] = "defghi";
	size_t num = 3;

	char* ret = my_strncat(arr1, arr2, num);

	printf("%s", ret);
	return 0;
}

7.strncmp

7.1函数用法

strncmp函数原型:

用法:和strcmp用法相同,但它只比较两个字符串前num个字符

7.1具体实现

#include
#include

int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abcdzz";
	size_t num = 0;

	int cmp = strncmp(arr1, arr2, num);
	if (cmp > 0)
	{
		printf(">");
	}
	else
	{
		printf("<=");
	}

	return 0;
}

7.3模拟实现

#include
#include

int my_strncmp(const char* str1, const char* str2, size_t n)
{
	assert(str1 && str2);
	while (*str1 == *str2)
	{
		n--;
		if (n == 0)
		{
			return 0; //当前n个字符相同,返回0
		}
	}
	return *str1 - *str2; //出现字符不相同时,跳出上面循环,返回*str1 - *str2
//前者大,返回大于0的值,后者大,返回小于0的值

}

int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abcdzz";
	size_t num = 3;

	int cmp = my_strncmp(arr1, arr2, num);
	if (cmp > 0)
	{
		printf(">");
	}
	else
	{
		printf("<=");
	}

	return 0;
}

以上为7个字符串库函数的讲解,后续会对剩余的字符串库函数和内存函数进行讲解

你可能感兴趣的:(C语言知识点,算法,c语言,开发语言)