描述:C语言中对于字符串类型并未定义,但存在许多有关字符串的库函数。

例如:strstr(在原串中匹配子串)strcpy(将原串内容拷贝到目标串中),strncpy(原串内容拷贝到目标串---可控拷贝数), strcmp(比较两个字符串的内容),strcat(字符串的追加)等等,我们可以自己编写程序实现以上功能的函数,而不调用库函数。可以对照库函数进行学习,提高自身的编程能力。

1、模拟strcpy函数(复制字符串)

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

char * my_strcpy(char *dest, const char *src)
{
	assert(dest);//判断指针有效性
	assert(src);
	char *ret = dest;
	while (*dest++ = *src++)
		;
	return ret;
}

int main()
{
	char arr[] = "hello world!";
	char src[20];
	printf("%s\n",my_strcpy(src, arr));
	system("pause");
	return 0;
}

2、模拟实现strncpy函数(字符串复制-----可控复制字节数量)

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

char *my_strncpy(char *dest, const char *src, size_t count)
{
	assert(dest);
	assert(src);
	char *ret = dest;
	while (count--)//count为要复制的字节数
	{
		*dest++ = *src++;
	}
	*dest = '\0';//字符串最后要加上'\0'
	return ret;
}

int main()
{
	char arr[] = "abcdef";
	char str[10];
	my_strncpy(str, arr, 4);
	printf("%s\n", str);
	system("pause");
	return 0;
}

3、模拟strcmp函数(比较两个字符/字符串大小)

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

int my_strcmp(const char *dest, const char *src)
{
	assert(dest);
	assert(dest);
	int ret = 0;
	while( (*(unsigned char*)dest == *(unsigned char*)src) && *dest)//注意此处需要强制类型转换,转换成无符号的char型,否则会出错
	{
		dest++;
		src++;
	}
	if (*(unsigned char*)dest == '\0')
		 ret = 0;//*dest为0时,表示比较完了,两个字符串相等,返回0
	else
		ret = *(unsigned char*)dest - *(unsigned char*)src;//两个字符串不等返回两个字符串的差(强制转换类型)
	return ret;
}

int main()
{
	char arr[] = "abcde";
	char src[] = "adcde";
	int var;
	var = my_strcmp(arr, src);
	printf("%d\n", var);
	system("pause");
	return 0;
}

4、模拟实现strncmp函数(字符串比较------可控比较字节数量)

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

int my_strncmp(const char *str1, const char *str2,size_t count)
{
	assert(str1);
	assert(str2);
	int ret;
	while (count--)
	{
		if (*(unsigned char*)str1 == *(unsigned char*)str2)//注意此处需要强制类型转换,转换成无符号的char型
			str1++, str2++;
	}
	if (count == 0)//count=0表示比较完成,两个字符串相等
		ret = 0;
	else
		ret = *(unsigned char*)str1 - *(unsigned char*)str2;//注意此处需要强制类型转换
	return ret;
}

int main()
{
	char arr1[] = "cdabctr";
	char arr2[] = "cdabfe";
	int len = sizeof(arr1) / sizeof(arr1[0]);
	printf("%d\n", my_strncmp(arr1, arr2, len));
	system("pause");
	return 0;
}

5、模拟strcat函数(追加/合并字符串)

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

char * my_strcat(char *dest, const char *src)
{
	assert(dest);
	assert(src);
	char *ret = dest;
	while (*ret)//数组ret自加,直到'\0'停止
		ret++;
	while (*ret++ = *src++)//src第一个元素替换'\0',其余元素追加到ret中
		; 
	return (dest);
}

int main()
{
	char arr[30] = "hello";
	char src[] = " to world!";
	printf("%s\n",my_strcat(arr, src));
	system("pause");
	return 0;
}

6、模拟实现strncat函数(字符串追加-------可控追加字节数量)

#define _CRT_SECURE_NO_WARNINGS//使用scanf时需要加在头文件(VS2013中)
#include<stdio.h>
#include<assert.h>
#include<string.h>
#include<stdlib.h>

char *my_strncat(char *dest,char *src,int count)
{
	assert(dest);
	assert(src);
	char *ret = dest;
	while (*dest)    //数组dest自加,直到'\0'停止
		dest++;
	while (count--)  //src第一个元素替换'\0',其余元素追加到dest中
		*dest++ = *src++;
	*dest = '\0';    //字符串后加上'\0'
	return ret;
}

int main()
{
	char arr[30] = "hello";  //注意此处定义数组大小要充分大,可以存放两个数组
	char str[] = " to world!";
	int len;
	printf("请输入追加长度>");
	scanf("%d", &len);
	my_strncat(arr,str,len);
	printf("%s\n", arr);
	system("pause");
	return 0;
}

7、模拟实现strstr函数(判断一个字符串是不是另一个字符串的子字符串

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

char *my_strstr(const char *str1,const char *str2)
{
	assert(str1);
	assert(str2);
	char *p = (char *)str1;
	if (*str2=='\0')//如果str2为空,返回str1
		return((char *)str1);
	while (*p)
	{
		char *p1 = p;
		char *p2 = (char *)str2;
		while (*p2 && *p1 && (*p1 == *p2))//注意p1,p2为'\0'时也要停止循环
		{
			p1++;
			p2++;
		}
		if (*p2 == '\0')//成功匹配p2中每一个字符,返回p(子字符串开始处)
			return p;
		p++;//p1和p2匹配没成功,p1指向下一个字符,重新与p2进行匹配
	}
	return NULL;
}

int main()
{
	char arr[20] = "abccdefgh";
	char str[20] = "cdefg";
	char *ret=my_strstr(arr, str);
	printf("%s\n", ret);
	system("pause");
	return 0;
}

上述程序运行结果为:cdefgh

8、模拟实现memset函数(内存赋值或数据重置-----可控赋值字节数量)

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
//memset作用是在一段内存块中填充某个给定的值,它对较大的结构体或数组进行清零操作的一种最快方法
void *my_memset(void *dest, int c, size_t count)
{
	assert(dest);
	char *p = (char *)dest;
	while (count--)
	{
		*p++ = c;
	}
	return dest;
}

int main()
{
	char arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };//memset是按字节赋值
	int len = sizeof(arr) / sizeof(arr[0]);
	int i;
	my_memset(arr, 0, len);
	for (i = 0; i < len; i++)
	{
		printf("%d ",arr[i]);
	}
	system("pause");
	return 0;
}

9、模拟实现memcmp函数(内存中的内容比较大小-----可控比较字节数量)

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

int my_memcmp(const void *p1, const void *p2, size_t count)
{
	assert(p1);
	assert(p2);
	int ret = 0;
	unsigned char *dest = (unsigned char *)p1;
	unsigned char *src = (unsigned char *)p2;
	while (count--)
	{
		if (*(unsigned char *)dest == *(unsigned char *)src)
		{
			dest++; 
			src++;
		}
	}
	if (count == 0)
		ret = 0;
	else
		ret = *(unsigned char *)dest - *(unsigned char *)src;;
	return ret;
}
int my_memcmp(const void *s1,const void *s2,size_t count)  
{  
    int res = 0;  
    const unsigned char *p1 =(const unsigned char *)s1;//注意是unsigned char *  
    const unsigned char *p2 =(const unsigned char *)s2;   
    for(p1 ,p2;count > 0;p1++,p2++,count--)  
        if((res =*p1 - *p2) != 0)   //不相当则结束比较  
            break;  
    return res;  
} 

int main()
{
	char arr[10] = "abcdefg";//memset是按字节进行比较的
	char str[10] = "abcdfd";
	int len = sizeof(arr) / sizeof(arr[0]);
	printf("%d\n", my_memcmp(arr, str, len));
	system("pause");
	return 0;
}