c语言中常见的字符串操作函数,内存操作函数及其他函数详解

x33g5p2x  于2021-11-22 转载在 其他  
字(16.0k)|赞(0)|评价(0)|浏览(745)

strlen函数

strcpy()函数

strcmp()函数

strcat()函数

strchr

strrchr()函数

strncpy()函数

strncat

strncmp()函数

strstr()函数

strtoke()函数

模拟实现atoi()函数

1.函数原型:

模拟实现itoa()函数

模拟实现atof()函数

memcpy()函数

memcmp()函数

memset()函数

memchr()函数

memmove()函数

sqrt()函数

pow()函数

abs()函数

strlen函数

1.函数原型
size_t strlen(const char *string );

我们也可以打开MSDN查看他的原型

2.函数功能:求一个字符串指定string字符串的长度

3.strlen函数的实现:

实现的思想是这样的我们只要让一个指针指向字符串的起始位置,让他一直往后走直到遇到\0就停止在上述过程中用计数器count统计str走了多少步,count的值就是这个字符串的长度了

说明:
strlen() 函数计算的是字符串的实际长度,遇到第一个’\0’结束;
参数指向的字符串必须以 ’ \0 ‘结束
函数返回值一定是size_t ,是无符号的
如果你只定义没有给它赋初值,这个结果是不定的,它会从首地址一直找下去,直到遇到’\0’停止
sizeof返回的是变量声明后所占的内存数,不是实际长度,此外sizeof不是函数,仅仅是一个操作符,strlen()是函数
这是特别要注意的!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

代码实现:

#include<stdio.h>
#include<assert.h>
int my_strlen(const char* str)//我们只是要求一下他的长度并不会修改他所以加const保护字符串
{
	assert(str);//断言防止str为空指针
	int count = 0;
	while (*str!='\0')
	{
		str++;
		count++;//计数
	}
	return count;

}
int main()
{
	char arr[] = "abcd";
	int ret=my_strlen(arr);
	printf("%d", ret);
}

方法2:递归方法(重点,以后面试可能会问到)

#include<stdio.h>
#include<assert.h>
int my_strlen(const char* str)//我们只是要求一下他的长度并不会修改他所以加const保护字符串
{
	assert(str);//断言防止str为空指针
	if (*str)
	{
		return 1 + my_strlen(++str);
	}
	else
	{
		return 0;
	}

}
int main()
{
	char arr[] = "abcd";
	int ret=my_strlen(arr);
	printf("%d", ret);
}

方法3:指针减指针

#include<stdio.h>
#include<assert.h>
int my_strlen(const char* str)//我们只是要求一下他的长度并不会修改他所以加const保护字符串
{
	assert(str);//断言防止str为空指针
	const char* start = str;
	const char* end = str;
	while (*end != '\0')
	{
		end++;
	}
	return end - start;
}
int main()
{
	char arr[] = "abcdf";
	int ret=my_strlen(arr);
	printf("%d", ret);
}

strcpy()函数

1.函数原型:

2.函数功能:将参数str字符串拷贝到参数dest所指向的字符串的地址中.注入事项:strcpy拷贝的时候是要拷贝到'\0'才停止拷贝。所以一定要保证目的地空间足够大.我strcpy的脾气就是我要拷贝到‘\0'我才停止你空间足不足够我才不关心,我只负责拷贝其他的我不管。

说明:
 1.  源字符串必须以’\0’结束

  1. 会将源字符串的’\0’拷贝到目标空间

3.目标空间必须可变

  1. 如果参数dest所指的内存空间不够大,可能会造成缓冲溢出的错误情况,在编写程序时需特别留意,或者用strncpy()来取代
#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abc";
char *ret=strcpy(arr2, arr1);
printf(ret);

}

在这个实验中我们把arr1的内容拷贝到arr2中但是arr2中的空间只有4个字节而arr1是有7个字节,我们一起来看一下啊运行结果:

我们可以看到虽然字符串arr1被拷贝到arr2中去了但此时程序已经崩溃了。所以我们在使用strcpy时一定要确保目的地空间足够大。

3.代码实现:

#include<stdio.h>
#include<assert.h>
char* my_strcpy(char* dest, const char* src)
{
	assert(dest && src);//防止dest和src为空指针
	char* ret = dest;
	while (*src)
	{
		*dest = *src;
		dest++;
		src++;
	}
	*dest = *src;//将src中的’\0'拷贝到dest中
	return ret;
}
int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abv";
	char*ret=my_strcpy(arr1, arr2);
	printf(ret);
}

运行结果:

拷贝前:

拷贝后:

在上面这个版本上我们还可以进行改进:

#include<stdio.h>
#include<assert.h>
char* my_strcpy(char* dest, const char* src)
{
	assert(dest && src);//防止dest和src为空指针
	char* ret = dest;
	while (*dest++ = *src++)
		;
	return ret;
}
int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abv";
	char*ret=my_strcpy(arr1, arr2);
	printf(ret);
}

strcmp()函数

1.函数原型:

2.函数功能:

字符串进行比较

我们通过文档我们可以知道:如果第一个字符串小于第二个返回的是小于0的数如果第一个字符串等于第二个返回的·是0如果第一个字符串大于第二个字符串返 回的是大于0的数字

原型:strcmp(str1,str2);

功能:比较两个字符串,如果两个字符串相等,则返回0;若str1大于str2(对于大于的理解,是指从两个字符串的第一个字符开始比较,若两个字符相同,则继续比较,若发现两个字符不相等,且str1中该字符的ASCII码大于str2中的,则表示str1大于str2),返回一个正数(这个正数不一定是1);若str1小于str2,返回一个负数(不一定是-1);若字符串str1的长度大于str2,且str2的字符与str1前面的字符相同,则也相对于str1大于str2处理

区分大小写比较的,如果希望不区分大小写进行字符串比较,可以使用stricmp函数

首先判断第一个字符是否相等如果相等直接继续往后走直到两个不相等

3.代码实现:

#include<stdio.h>
int my_strcmp(const char* dest, const char* src)
{
            assert(dest&&src);
	while (*dest == *src)
	{
		if (*dest == '\0')//如果dest等于‘\0'说明这两个字符串相等相等返回0
		{
			return 0;
		}
		dest++;
		src++;
	}
	return *dest - *src;//说明这两个字符串不相等,返回他们第一不相等字符的差值
}
int main()
{
	char str1[] = "abcde";
	char str2[] = "abcdrq";
	int ret = my_strcmp(str1, str2);
	printf("%d", ret);
}

strcat()函数

1.函数声明原型

2.函数功能:字符串拼接函数

实现思路大致是:先找到dest’\0'的位置,然后从该位置将str中的内容向后面追加

追加前:

追加后:

我们也可以调试看到:

注意!

1.源字符串必须’\0’结束
2. 目标空间必须可修改
3.strcat() 会将参数src字符串复制到参数dest所指的字符串尾部
4.dest最后的结束字符’\0’会被覆盖掉,并在连接后的字符串的尾部再增加一个’\0’
5.dest与src所指的内存空间不能重叠,且dest要有足够的空间来容纳要复制的字符串
6.所以不能够自己给自己拷贝因为’\0'已经被覆盖了而strcat是要追加到‘\0'才停止追加!!!!!!!

代码实现:

#include<stdio.h>
#include<string.h>
#include<assert.h>
char* my_strcat(char* dest, const char* src)
{
	assert(dest && src);
	char* ret = dest;
	while (*dest)
	{
		dest++;//找到dest所指向的字符串'\0’的位置
	}
	while (*dest++ = *src++)
		;
	return ret;
}
int main()
{
	char str1[] = "abcded\0XXXXXXX";
	char str2[] = "abc";
	my_strcat(str1, str2);
	printf("%s", str1);

	return 0;
}

strchr

1.函数原型

2.函数功能:

功能:在str字符串中查找首次出现字符c的位置(从字符串的首地址开始查找)

原型2:strrchr(str,c);

功能2:在字符串str中从后向前开始查找字符c首次出现的位置

3.代码实现:

#include<stdio.h>
#include<assert.h>
char* my_strchr(const char* str, int ch)
{
	assert(str);
	char* ret = (char*)str;
	while (*ret)
	{
		if (*ret ==(char) ch)
		{
			return ret;
		}
		ret++;
	}
	return NULL;
}
int main()
{
	char str[] = "abcdefhfmg";
	char* tmp = my_strchr(str, '0');
	if (tmp == NULL)
	{
		printf("找不到");
		return 0;
	}
	printf("%c", *tmp);
}

strrchr()函数

1.函数原型:

2。函数功能:

查找一个字符c在一个字符串string最后一次出现的位置(也就是从字符串的右侧开始查找字符c首次出现的位置)并返回从字符串中的字符c所在的位置开始直到结束的所有字符,如果没有找到字符c则返回空指针即NULL

3.代码实现:

#include<stdio.h>
#include<assert.h>
char* my_strrchr(const char* str,int ch)
{
	assert(str);
	char* ret = NULL;
	while (*str)
	{
		if (*str == (char)ch)
		{
			ret = str;
		}
		str++;
	}
	return ret;

}
int main()
{
	char str[] = "abcdeabcef";
	char* tmp = my_strrchr(str, 'a');
	printf(tmp);
}

strncpy()函数

1.函数原型:

2.函数功能

功能:将字符串str2中的前n个字符复制到字符串str1的前n个字符中

注意:(1)不会清除str1中全部字符串,只会改变前n个字符串,

(2)n不能大于字符串str1、str2的长度

(3)但是如果使用strncpy_s便会清除str1中的全部字符串

说明:

  • 如果src字符串长度小于n,则拷贝完字符串后,在目标后追加0,直到num个
  • strncpy不会向dest追加’\0’
  • src和dest所指的内存区域不能重叠,且dest必须有足够的空间放置n个字符

3.代码实现

#include<stdio.h>
#include<assert.h>
#include<string.h>
char* my_strncpy(char* dest, const char* src, int n)
{
	assert(dest && src);
	char* tmp = dest;
	while ((n--) && (*dest++ = *src++));
	if (n > 0)
	{
		while (n--)
		{
			*dest++ = '\0';
		}
	}
	return tmp;
}
int main()
{
	char str1[] = "abcdeXXXXXXXXXXXX";
	char str2[] = "avcdf";
	char* ret =my_strncpy(str1, str2, 6);
	return 0;
}

虽然比strncpy要安全一点但还是要注意要保证目的地空间足够

strncat

1.函数原型:

函数功能:

该函数会将字符串src的开头拷贝n个字符到dest的尾部,dest要有足够的空间来容纳要拷贝的字符串,如果n大于src的长度,那么只会把src仅有的字符串内容追加到dest的尾部。strncat会将dest里面的‘\0’覆盖掉字符追加完毕后自动加一个‘\0'

也就相当于这样:

我们在上面那个长的字符串从下面这个字符串中追加2个字符那么结果将为:

通过调试我们也能够证明上面这个是对的:

如果追加3个字符那么结果和上面是一样的。大家可以做实验验证

注意!!!!!

  • strncat将会从字符串src的开头拷贝n个字符到dest字符串尾部
  • dest要有足够的空间来容纳要拷贝的字符串
  • 如果n大于字符串src的长度,那么仅将src全部追加到dest的尾部
  • strncat会将dest字符串最后的’\0’覆盖掉,字符追加完成后,再追加’\0’

代码实现:

#include<stdio.h>
#include<string.h>
#include<assert.h>
char* my_strncat(char* dest, const char* src, int n)
{
	assert(dest && src);
	char* ret = dest;
	while (*dest)
	{
		++dest;
	}
	for (int i = 0; i < n; i++)
	{
		if (*src)
		{
			*dest = *src;
			dest++;
			src++;
		}
		else
		{
			break;
		}
	
	}
	*dest = '\0';
	return ret;
}
int main()
{
	char str1[] = "abcde\0XXXXXX";
	char str2[] = "avbv";
	strncat(str1, str2, 2);
	return 0;

}

strncmp()函数

1.函数原型:

2.函数功能:strncmp的功能和strcmp的功能和相似,只不过多了一个参数用来确定比较的个数

3。代码实现:

#include<stdio.h>
#include<assert.h>
#include<string.h>
int my_strncmp(const char* dest, const char* src, int n)
{
	assert(dest && src);
	while ((n--) && (*dest) && (*src) && (*src == *dest))
	{
		src++;
		dest++;
	}
	return *dest - *src;
}
int main()
{
	char str1[] = "abcdef";
	char str2[] = "abcf";
	int ret = my_strncmp(str1, str2, 2);
	
	printf("%d", ret);
}

strstr()函数

函数原型:

2.函数功能:

在字符串中找子串原理是string中是否包含strcharset如果包含就返回第一个出现字符的地址,如果没有就返回空指针

3.代码实现。

#include<stdio.h>
#include<assert.h>
char* my_strstr(const char* dest, const char* src)
{
	assert(dest && src);
	if (!*src)
	{
		return (char*)dest;
	}
	const char* cur =dest;
	const char* s1;
	const char* s2;
	s1 = s2 = NULL;
	while (cur)
	{
		s1 = cur;
		s2 = src;
		while ((*s1) && (*s2) && (*s1 == *s2))
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')
		{
			return (char*)cur;
		}
		cur++;
	}
	return NULL;//找不到字串

}
int main()
{
	char str1[] = "abcdef";
	char str2[] = "bcdef";

	printf(my_strstr(str1, str2));
}

strtoke()函数

1.函数原型:

2.函数功能:

功能:根据分隔符将字符串分隔成一个个片段
返回值:返回下一个分割后的字符串指针,如果已无从分割则返回NULL
说明:
1.sep参数是个字符串,定义了用作分隔符的字符集合
2.第一个参数指定一个字符串,它包含了一个或者多个由sqp字符串中一个或者多个字符分割的标记
3.第一次调用时将字符串首地址传进去,之后调用不用传地址,内部会有static函数保存指向地址
4.分隔符不作为输出内容,只做分界符
5. 当strtok在参数s的字符串中发现到参数sep的分割字符时则会将该字符改为’\0’字符
6. 在第一次调用时,strtok必须赋予参数str字符串,往后的调用则将参数s设置成NULL
7.strtok会修改原字符串,所以必须放至栈上

代码实现:

char* strtok1(char* str, const char* sep)
{
	static int ret = 0;//这个静态变量也十分重要!当指针指向最后一个 字符串str 出现的 sep字符分隔符,
	//因为最后一段字符串并不会再出现sep中任何一个分隔符,所以字符串就不会打印,
	//那我们如何区分这种情况和str中就从来没有出现过sep字符的情况,我们设置一个静态变量,如果静态变量被修改过,就输出字符串,如果没修改过就返回空指针。
	static char* a = NULL;       //这里要用到静态变量,这样函数结束变量就不会销毁,a会记住上一次的地址
	if (str != NULL)               // 判断是否为NULL

	{
		a = str;
		ret = 0;
	}
	else
	{
		if (ret == 2)
			return NULL;
		a++;
	}
	char* first = a;
	while (*a)
	{
		const char* p = sep;
		while (*p)
		{
			if (*p == *a)
			{
				*a = '\0';
				ret = 1;
				return first;
			}
			p++;
		}
		a++;
		if (*a == '\0')
		{
			ret = 2;
			break;
		}

	}
	if (ret == 0)
		return NULL;
	else if(ret == 2)
		return first;
}

其实这里还有一些函数博主就不一 一实现就在这里简单的介绍一个就可以了

| 函数名称 | 函数原型 | 函数功能 |
| strerro | char*strerro(int errnom) |
1.返回错误码,所对应的错误信息

2使用库函数调用失败的时候,都会设置错误码并存储在errno中 |
|
strpbrk
| char* strpbrk(const char* str1, const char* str2) | 在字符串s1中寻找字符串s2中任何一个字符相匹配的第一个字符的位置,空字符NULL不包括在内 |
|
strcspn
| size_t strspn(const char* str1, const char* str2) |
功能:用来计算str1字符串开始部分不匹配str2字符串的字符个数

返回字符串str1开头部分不出现在字符串str2内的字符数目。 |
|
strspn
| size_t strspn(const char* str1, const char* str2) | 功能:用来计算str1字符串开始部分匹配str2字符串的字符个数
返回字符串str1开头连续包含字符串str2内的字符数目 |

| 函数名称 | 函数原型 | 函数功能 |
| atoi | int atoi(const char* str) |
功能:将字符串转换成整型

返回转换后的整型数。如果str不能转换成int或者str为空字符串,那么将返回0 |
| atof | double****atof(constcharstring***) | 将字符串转换成浮点型 |
| atol |
**long
atol(constcharstring)
| 将字符串转换成浮点型 |
| gcvt |
char***_gcvt(**double
value
*,intdigits,char***buffer)
| 将浮点型转成字符串 |
| itoa |
char
_itoa(**int
value***,char*****string,**intradix)**
| 将整型转换成字符串 |

                       

| 函数名称 | 函数原型 | 函数功能 |
| strtod | double****strtod(constcharnptr***,**charendptr) | 字符串转换成浮点型 |
| strtol |
**long
strtol(constcharnptr,char*****endptr,**intbase);
| 将字符串转换成长整型 |
| strtoul |
unsignedlongstrtoul(constcharnptr***,**char**endptr,**intbase***);
| 将字符串转换成无符号长整型 |
| toascii |
int**__toascii(**int
c***)**
| 将整型转成合法的ASSll码字符 |
| _itot_s | errno_t _itoa_s(int value, char buffer, size_t sizeInCharacters, int radix);
  | 将int转换成char
|
| _ttoi | | 可以将Cstring 转成整型 |

模拟实现atoi()函数

1.函数原型:

int atoi(const char* str)

2.函数功能

将字符串转换成整数

注意:

返回值:每个函数返回 int 值,此值由将输入字符作为数字解析而生成。 如果该输入无法转换为该类型的值,则atoi的返回值为 0。

工作原理:atoi通过全局变量来区分返回0的情况。
如果是非法输入,返回0,并把这个全局变量设为特殊标志;
如果输入是”0”,则返回0,不会设置全局变量。

使用该函数时要注意atoi返回的是int类型,注意输入str的范围不要超出int类型的范围。

3.函数实现:

#include<stdio.h>
#include<limits.h>
#include<assert.h>
#include<string.h>
#include<ctype.h>
int my_atoi(const char* str)
{
	assert(str);
	long long ret = 0;
	int flag = 1;
	if (!*str)
	{
		return 0;
	}
	while (isspace(*str))
	{
		str++;
	}
	if (*str == '+')
	{
		str++;
	}
	else if (*str == '-')
	{
		flag = -1;
		str++;
	}
	while (isdigit(*str))
	{
		ret = ret * 10 + *str - '0';
		if (ret > INT_MAX || ret < INT_MIN)//超出整型最大说明溢出了
		{
			return 0;
		}
		str++;
	}
	if (*str == '\0')
	{
		return (int)ret*flag;
	}
	return (int)flag*ret;
}
int main()
{
	int tmp = my_atoi("-123");
	printf("%d", tmp);
}

模拟实现itoa()函数

代码实现:

#include<stdio.h>
#include<assert.h>
void my_reverse(char* str)
{
	int right= strlen(str)-1;
	int left = 0;
	while (left <right)
	{
		char tmp = str[left];
		str[left] = str[right];
		str[right] = tmp;
		left++;
		right--;
	}
	
}
char* my_itoa(int num,char*str)
{
	assert(str);
	int flag = 1;
	int t = 0;
	if (num == 0)
	{
		str[t++] = '0';
		str[t] = '\0';
		return str;
	}
	if (num < 0)
	{
		flag = -1;
	
	}
	num *= flag;
	int i = 0;
	while (num != 0)
	{
		str[i] = '0' + num % 10;
		num /= 10;
		i++;
		str[i] = '\0';
	}
	if (flag == -1)
	{
		str[i] = '-';
		str[i + 1] = '\0';
	}
	my_reverse(str);
	return str;
}
int main()
{
	char str[10];
	char* tmp = my_itoa(-1346543, str);
	printf(tmp);
}

模拟实现atof()函数

1.函数原型
double****atof(constchar****string***)

2.函数功能

将字符串转成浮点数

3.代码实现

#include<stdio.h>
#include<assert.h>
#include<ctype.h>
double my_atof(const char* str)
{
	double ret = 0;
	int flag = 1;
	int count = 0;
	assert(str);
	while (isspace(*str))
	{
		str++;
	}
	while (*str)
	{
		if (count)
		{
			count = count * 10;
		}
		if (*str == '+')
		{
			str++;
		}
		else if (*str=='-')
		{
			str++;
			flag = -1;
		}
		else if (*str == '.')
		{
			count++;
			str++;
		}
		else if ((*str>='0')&&(*str<='9'))
		{
			ret = ret * 10 + (double)(*str - '0');
			str++;
		}
		else
		{
			return 0;
		}
	}
	return ret * flag / count;
}
int main()
{
	double tmp = my_atof("123.3abc");
	printf("%.2lf", tmp);

}

之前楼主遗漏了一些函数在这里补上

int isalnum(int c):检查字符是否为数字或字母;(0~9,a~z,A~Z) 
int isalpha(int c):检查字符是否为字母;(a~z, A~Z) 
int iscntrl(int c):检查字符是否为控制字符;(八进制000~037以及177的字符) 
int isdigit(int c):检查字符是否为十进制数字;(0~9) 
int isgraph(int c):检查字符是否为图形表示,依赖于使用语言的环境;0~9,a~z,A~Z,以及标点符号) 
int islower(int c):检查字符是否为小写的字母;(a~z) 
int isprint(int c):检查字符是否为可打印的;(数字、字母、标点符号、空白字符) 
int ispunct(int c):检查字符是否为标点符号;(! ” # $ % & ’ ( ) * + , - . / : ; < = > ? @ [ ] ^ _ ` { | } ~等) 
int isspace(int c):检查字符是否为空白字符;(TAB、换行、垂直TAB、换页、回车、空格) 
int isupper(int c):检查字符是否为大写字母;(A~Z) 
int isxdigit(int c):检查字符是否为十六进制数字;(0 1 2 3 4 5 6 7 8 9 A B C D E F a b c d e f) 

字符串转换函数:

int tolower(int c):转化字符为小写字母;

int toupper(int c):转化字符为大写字母;

关于字符串的函数就到此结束

下面博主介绍几个内存操作函数:

memcpy()函数

1.函数原型:
voidmemcpy(****voiddest,constvoidsrc***,**size_tcount)

2.函数功能

内存拷贝,可以拷贝任意类型****不考虑’\0’
功能:函数memcpy从src的位置开始向后复制count个字节的数据到dest的内存位置
说明:

  • 这个函数在遇到’\0’不会停下来
  • 如果src与dest任何的重叠,复制结果都是未定义的
  • 1.src和dest所指内存区域不能重叠

2.与strcpy相比,memcpy遇到‘\0’并不会结束,而是一定会拷贝完n个字节

3.memcpy可以拷贝任何数据类型的对象,可以指定拷贝的数据长度

4.如果dest本身就有数据,执行memcpy()后会覆盖原有的数据

5.dest和src都不一定时数组,任意的可读写的空间均可

6.如果要追加数据,则每次执行memcpy后,要将目标数组地址增加到所要追加数据的地址

 

原理如下:

3.代码实现:

#include<stdio.h>
#include<assert.h>
void* my_memcpy(void* dest, const void* src, int n)
{
	assert(dest && src);
	void* ret = dest;
	while (n--)
	{
		*(char*)dest = *(char*)src;
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}
	return ret;
}

int main()
{
	int arr1[10] = { 0 };
	int arr2[] = { 1,2,3,4,5 };
	my_memcpy(arr1, arr2, 20);
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr1[i]);
	}
	return 0;
}

 memcmp()函数

1.函数原型
int****memcmp(constvoid**buf1***,constvoidbuf2*,size_tcount)

2.函数功能

功能:比较内存区域buf1和buf2的前count个字节。注意该函数是按字节比较的
返回值:
当buf1 < buf2时,返回值<0
当buf1 = buf2时,返回值=0
当buf1 > buf2时,返回值>0

3.代码实现

#include<stdio.h>
#include<assert.h>
int my_memcmp(const void* str1, const void* str2, int num)
{
	if (num == 0)
	{
		return 0;
	}
	assert(str1 && str2);
	char* s1 = (char*)str1;
	char* s2 = (char*)str2;
	while ((num--)&&(*s1==*s2)&&*s1&&*s2)
	{
		s1++;
		s2++;
	}

	return *s1 - *s2;
}
int main()
{
	int arr1[10] = { 1,2,3,4,5 };
	int arr2[10] = { 5,2,3,5 };
	int tmp = my_memcmp(arr1, arr2, 0);
	printf("%d", tmp);
}

 memset()函数

1.函数原型
voidmemset(****voiddest,intc,size_tcount)

2.函数功能

功能:以str的起始位置开始的n个字节的内存区域用整数value进行填充
返回值:目标str内存起始地址
说明:按字节设置,进行赋值

1.memset用来对一段内存空间全部设置为某个字符,一般用在对定义的字符串进行初始化为‘ ’或‘/0’
2.如果用malloc分配的内存,一般只能使用memset来初始化
3.memset可以方便的清空一个结构类型的变量或数组,它可以一字节一字节地把整个数组设置为一个指定的值
4.当结构体类型中包含指针时,在用memset初始化时需要特别小心这是因为当用memset初始化为0时会把指针初始化为NULL

5.在使用memset给数组进行初始化时我们只能将数组中的每一个元素初始话为0或者-1,应为memset是一个字节一个字节进行初始化

3.代码实现

#include<stdio.h>
#include<assert.h>
void* my_memset(void* dest, int val, int num)
{
	assert(dest);
	char* s1 = (char*)dest;
	void* ret = dest;
	while (num--)
	{
		*s1 = (char)val;
		s1++;
	}
	return ret;
}
int main()
{
	int arr[10];
	my_memset(arr, 0, 40);
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
}

memchr()函数

1.函数原型
void* memchr(const char* ptr ,int value,sizez_t num)

2.函数功能

功能:从buf所指内存区域的前count个字节查找字符ch。
返回值:当第一次遇到字符ch时停止查找。如果成功,返回指向字符ch的指针;否则返回NULL

3.代码实现

void* my_memchr(const void* dest, int c, int num)
{
	assert(dest);
	char* ret = (char*)dest;
	while (num--)
	{
		if ((char)c == *ret)
		{
			return ret;
		}
		else
		{
			ret++;
		}
	}
	return NULL;
}

memmove()函数

1.函数原型
void*memmove(void dest,const voidsrc,int num)

2.函数功能

用于内存拷贝的函数,没有类型限制,但是memmove使用要考虑内存重叠问题

void * memmove(void * destination, const void * source, size_t num);

用于从src中拷贝num个任意类型的内容到dest,如果目标区域和源区域有重叠(并不是所有重叠情况都需要特殊处理),memmove能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区

3.代码实现

void *my_memove(void* dest, const void* src, int num)
{
	assert(dest && src);
	void* ret = dest;
	if(dest<src)
	{

	while (num--)
	{
		*(char*)dest = *(char*)src;
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}

        }
	else
	{
	while (num--)
	{
		*((char*)dest + num) = *((char*)src + num);
     }
   }
	return ret;
}

最后介绍几个数学函数

sqrt()函数

1.函数原型:
double***sqrt(**doublex*);**

2.函数功能

计算一个非负实数的平方根

实现原理:

牛顿迭代法是一种可以用来快速求解函数零点的方法。

为了叙述方便,我们用 CC 表示待求出平方根的那个整数。显然,CC 的平方根就是函数

y = f(x) = x^2 - C,y=f(x)=x 2 −C的零点。

牛顿迭代法的本质是借助泰勒级数,从初始值开始快速向零点逼近。我们任取一个 x0​ 作为初始值,在

每一步的迭代中,我们找到函数图像上的点 (x_i, f(x_i))(x i ,f(x i )),过该点作一条斜率为该点导数 f'(x_i)f ′(x i ) 的直线,与横轴的交点记为 x_{i+1}x i+1。x_{i+1}x i+1相较于 x_ix i​  而言距离零点更近。在经过多次迭代后,我们就可以得到一个距离零点非常接近的交点。下图给了从 x_0x 0开始迭代两次,得到 x_1x 1和 x_2x 2的过程。

代码实现:

int mySqrt(int x){
long tmp = x;
        while (tmp*tmp > x)
        {
            tmp = (tmp + x/tmp) / 2;
        }
        return (int)tmp;
    
    
}

pow()函数

1.函数原型
double***pow(**doublex*,doubley)**

2.函数功能

求a^b

原理:

代码实现

double myPow(double x, int n) {
        if(x == 1 || n == 0) 
        {
            return 1;
        }

        double tmp = 1;
        long count=n;
        if(n < 0){
            count = -count;
            x = 1/x;
        }

        while(count)
        {
            if(count & 1) 
            {
                tmp *= x;
            }
            x *= x;
               count>>= 1;
        }
        return tmp;
    }

abs()函数

1.函数原型:
int***abs(**intn*)**

2.函数功能

求绝对值

代码实现

#include<stdio.h>
int my_abs(int n)
{
	int tmp = n >> 31;
	return (n ^ tmp) - tmp;
}
int main()
{
	int tmp = my_abs(10);
	printf("%d", tmp);
}

最后博主在补充几个数学函数:

| 函数名称 | 函数原型 | 函数功能 |
| fabs() | double fabs(double x) | 求双精度的绝对值 |
| exp() | double exp(double x) | 求指数e^x的值 |
| log10() | double log 10 (double x) | 求log 10 x的值 |
| pow10(int p) | double pow10(int p) | 返回10^p的值 |
|  ceil | double ceil(double x) | 求不小于x的最小整数 |
| floor | double floor(double x) | 求不大于x的最大整数 |
| | | |
| | | |
| | | |
| | | |

博主水平有限如有错误一定要向博主指出,一起进步。前路昭然,你我共进!!!!

觉得写的不错的可以点个赞 谢谢

相关文章