c语言模拟实现字符函数和内存函数

目录

  • strlen
  • strcpy
  • strcat
  • strcmp
  • strstr
  • strtok
  • strerror与perror
  • memcpy
  • memmove
  • memset
  • atoi

strlen

/// strlen
/// size_t strlen( const char *string );
/*
求的是字符串的长度即‘\0’前面字符的个数,不计算‘\0’
特别要注意的是strlen返回的数字为是无符号类型,比较的时候要注意强制类型、
转换
*/

 //循环
int my_strlen1(const char* s)
{
	assert(s);
	int count = 0;
	while (*s != '\0')
	{
		count++;
		s++;
	}

	return (unsigned)count;
}
// 递归

int my_strlen2(const char* s)
{
	if (*s == '\0')
		return 0;
	return 1 + my_strlen2(++s);
}

int main()
{
	char str1[] = "abcdefg";
	printf("%d\n", my_strlen2(str1));
	return 0;
}

strcpy

/// strcpy
//char* strcpy(char* strDestination, const char* strSource);
/*
目标空间必须足够大,源字符串必须以0结尾,目标空间可变
*/

char* my_strcpy(char* s1, const char* s2)
{
	assert(s1 && s2);
	char* ret = s1;
	while (*s1++ = *s2++)
	{
		;
	}
	return ret;
}
int main()
{
	char str1[20];
	char str2[] = "abcdefg";
	my_strcpy(str1, str2);
	printf("%s\n", str1);
	return 0;
}

strcat

/// strcat
/*
目标空间足够大且可变,源字符串必须以0结尾,会覆盖目标字符串末尾的0
*/

char* my_strcat(char* s1, const char* s2)
{
	// 找源字符串末尾0
	assert(s1 && s2);
	char* ret = s1;
	while (*s1 != '\0')
	{
		s1++;
	}
	while (*s1++ = *s2++)
	{
		;
	}
	return ret;
}
int main()
{
	char str1[20] = "123";
	char str2[] = "abcdefg";
	my_strcat(str1, str2);
	printf("%s\n", str1);
	return 0;
}

strcmp

/// strcmp
/*
对应字符比较,直到遇到‘\0’
*/

int my_strcmp(const char* s1, const char* s2)
{
	while(*s1)
	{
		if (*s1 != *s2)
			break;
		s1++;
		s2++;
	}
	return *s1 - *s2;
}
int main()
{
	char str1[] = "abc";
	char str2[] = "abcd";
	printf("%d\n", my_strcmp(str1, str2));
	return 0;
}

strstr

/// strstr 
/// char *strstr( const char *string, const char *strCharSet );

char* my_strstr(const char* s1, const char* s2)
{
	assert(s1 && s2);
	char* cur = s1;
	char* str2 = s2;
	while (cur)
	{
		s1 = cur;
		s2 = str2;
		while (*s1 == *s2)
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')
			return cur;
		cur++;
	}
	return NULL;
}
int main()
{
	char str1[] = "abbcacabcdabd";
	char str2[] = "abcd";
	printf("%s\n", my_strstr(str1, str2));
	return 0;
}

strtok

int main()
{
	char str1[] = "111@[email protected]. 555/666";
	char sep[] = "@. /";
	char* i = NULL;
	for (i = strtok(str1, sep); i != NULL; i = strtok(NULL, sep))
	{
		printf("%s\n", i);
	}
	return 0;
}

strerror与perror

int main()
{
	printf("%s\n", strerror(0));
	printf("%s\n", strerror(1));
	printf("%s\n", strerror(2));
	printf("%s\n", strerror(3));
	int* p = (int*)malloc(INT_MAX);//想堆区申请内存的
	if (p == NULL)
	{
		printf("%s\n", strerror(errno));// 第一种
		perror("Malloc"); // 第二种
		return 1;
	}
	return 0;
}

memcpy

/// memcpy
/*
memcpy会从source的位置开始向后复制num个字节的数据到destination的内存位置
这个函数在遇到0的时候并不会停下来
如果source和destination有任何重叠,复制的结构都是未定义的
*/
//void * memcpy ( void * destination, const void * source, size_t num );
void* my_memcpy(void* des, const void* src, size_t num)
{
	assert(des && src);
	void* ret = des;
	while (num--)
	{
		*(char*)des = *(char*)src;
		des = (char*)des + 1;
		src = (char*)src + 1;
	}
	return ret;
}
int main()
{
	int arr1[] = { 0,1,2,3,4,5,6,7,8,9 };
	int arr2[] = { 10,10,10,10,10,10,10 };
	my_memcpy(arr1+2, arr1, sizeof(int) * 4);
	Print(arr1, sizeof(arr1) / sizeof(int));
	return 0;
}

memmove

/*
和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
如果源空间和目标空间出现重叠,就得使用memmove函数处理
*/
//void * memmove ( void * destination, const void * source, size_t num );
void* my_memmove(void* des, const void* src, size_t num)
{
	//需要考虑从前往后考还是从后往前考
	void* ret = des;
	if (des > src)
	{
		// 从后往前
		while (num--)
		{
			*((char*)des + num) = *((char*)src + num);
		}
	}
	else
	{
		// 从前往后
		while (num--)
		{
			*(char*)des = *(char*)src;
			des = (char*)des + 1;
			src = (char*)src + 1;
		}
	}
	return ret;
}
int main()
{
	int arr1[] = { 0,1,2,3,4,5,6,7,8,9 };
	my_memmove(arr1 + 2, arr1, sizeof(int) * 4);
	return 0;
}

memset

int main()
{
	int arr[] = { 0x11111111,0x22222222,3,4,5 };
	memset(arr, 6, 20);//memset是以字节为单位来初始化内存单元的
	return 0;
}

atoi


//int my_atoi(const char* s)
//{
//	int n = 0;
//	while (*s)
//	{
//		n = n * 10 + *s - '0';
//		s++;
//	}
//	return n;
//}

// 空格
// 空字符
// 非数字字符
// 前面有空白字符
// 前面有+-
// 溢出
#include
#include
#include
#include
#include
enum Status
{
	VALUE,
	INVALUE
}status = INVALUE; // 非法

int my_atoi(const char* s)
{
	// 空指针
	assert(s);
	int flag = 1;

	// 空字符串
	if (*s == '\0')
	{
		// 这里要注意返回的所有数字都有可能为字符串里的值
		// 所以要判断返回的值是否合法
		// 需要设置一个全局变量标记状态
		return 0;
	}
	// 前面有空白字符
	while (isspace(*s))
	{
		s++;
	}
	// 正负号
	if (*s == '+')
	{
		flag = 1;
		s++;
	}
	else if (*s == '-')
	{
		flag = -1;
		s++;
	}
	long long n = 0;
	while (*s != '\0')
	{
		if (isdigit(*s))
		{
			// 可能会想数字计算出来后在乘flag,变成正或负
			// 但是下面有判断是否负数越界
			n = n * 10 + flag * (*s - '0');
			// 越界 比如"11111111111111111111"
			if (n<INT_MIN)
			{
				n = INT_MIN;
				break;
			}
			else if(n > INT_MAX)
			{
				n = INT_MAX;
				break;
			}
		}
		else
		{
			n = 0;
			break;
		}
		s++;
	}
	if (*s == '\0')
	{
		status = VALUE;
	}
	return (int)n;
}
int main()
{
	char a[20] = "     +1111111aa1111123456";
	int ret = my_atoi(a);
	if (status == VALUE)
	{
		printf("合法的:%d\n", ret);
	}
	else
	{
		printf("非法的%d\n", ret);
	}
	
	return 0;
}

你可能感兴趣的:(c/c++,c语言)