字符及字符串函数

一.介绍内容

表示字符串和字符串I/O

求字符串长度:

strlen

长度不受限制的字符串函数:

strcpy,strcat,strcmp

长度受限制的字符串函数介绍:

strncpy,strncat,strncmp

字符串查找: strstr

字符操作 内存操作函数:

memcpy ,memmove

1表示字符串和字符串I/O

1.1字符串是以空字符(\0)为结尾的标志的char类型数组。
1.2字符串常量:用双引号括起来的内容称为字符串常量,双引号中的字符和编译器自动加入未尾的\0字符,作为字符串储存在内存中。

1.3在字符串面的声明中,用指定的字符串初始化数组,
而字符串多少空间。一种方法是用足够空间的数组储存字符串。在
const char ml[40]="Limit yourself to one line's worth."
const 表明不会更改这个字符串。
这种形式的初始化比标准的数组初始化形式简单得多。
const char ml[40]={'L','i','m','t',' ','y','h','o','\0'};
注意最后的空字符。没有这个空字符,这就不是一个字符串,而是一个字符数组。
在指定数组大小时,要确保数组的元素个数至少比字符串长度多1,(为了容纳空字符)。所有未被使用的元素都被自动初始化为(这重的0指的是char形式的空字符,不是数字字符0),

2求字符串长度

strlen

2.1 strlen 字符串已将'\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包 含 '\0' )。

#include<stdio.h>
#include<string.h>
int main()
{
    const char ml[40] = "hold on to your hats hackers.";
	printf("%d", strlen(ml));
	return 0;
}

 

 

#include<stdio.h>
#include<string.h>
int main()
{
	const char ml[40] = "hold on to your hats\0 hackers.";
	printf("%d", strlen(ml));
	return 0;
}

 

 

#include<stdio.h>
#include<string.h>
int main()
{
	const char arr[] = { 'h','o','l','d','t','o','y','o','u','r','h','t','a','s' }; 

	printf("%d", strlen(arr));
	return 0;
}

 

 

 

2.2模拟strlen的实现

#include<stdio.h>
#include<string.h>
int  my_strlen(char* str)
{
	if (*str != '\0')
		return 1 + my_strlen(str + 1);
	else
		return 0;
}
int main(void)
{
	char ml[40] = "hold on to your hats hackers.";
	int len = my_strlen(ml);
	printf("%d", len);
	return 0;
}

 

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<assert.h>
size_t my_strlen(const char* str)
{
	assert(str);
	const char* str1 = str;
	const char* end = str;
	while (*end != 0)
	{
		end ++;
	}
	return end - str1;
}
int main()
{
	char arr[] = "ABCDEFGH";
	int len = my_strlen(arr);
	printf("%d", len);
	return 0;
}

 

 

 

2.3注意\0的位置 

#include<stdio.h>
#include<string.h>
int main()
{
	const char arr[] = { 'h','o','l','d','t','o','y','o','u','r','h','t','a','s' }; 

	printf("%d", strlen(arr));
	return 0;
}

 

 

2.4 strlen的返回类型 

通过c Plus Plus官网查询我们知道是strlen的返回类型为size_t 本质类型为typedef unsigned int在实际应用中,我们知道字符串的长度不可能为负数。

#define _CRT_SECURE_NO_WARNINGS 1
#include<string.h>
#include<stdio.h>
int main()
{
	char arr1[] = "abc";//字符串长度为3;
	char arr2[] = "abcdefg"; //字符串长度为7;

	if (strlen(arr1) - strlen(arr2) > 0)//3-7=-4为一个负数,负数作为无符号数时是一个很大数,
		printf(">\n");
	else
		printf("<\n");
	return 0;
}

 

长度不受限制的字符串函数:strcpy,strcat,strcmp

3:strcpy

 

3.1源字符串必须以 '\0' 结束。
会将源字符串中的 '\0' 拷贝到目标空间。
目标空间必须足够大,以确保能存放源字符串。
目标空间必须可变。
学会模拟实现。
#define _CRT_SECURE_NO_WARNINGS 1
#include<string.h>
#include<stdio.h>
int main()
{
	char zf1[35] = "hello c languang";
	char zf2[40] = " ";
	strcpy(zf2, zf1);
	printf("%s", zf2);
	return 0;
}

 

 3.2拷贝源字符串时到\0结束

 

3.3目标空间的大小必须大于源字符串空间

#define _CRT_SECURE_NO_WARNINGS 1
#include<string.h>
#include<stdio.h>
int main()
{
	char arr1[] = "ABCDEFG";//空间大小为6
	char arr2[] = "HIJ ";//空间大小为3
	strcpy(arr2,arr1);
	printf("%s", arr2);
	return 0;
}

 

 

 

3.4目标空间必须可变。

错误示范

3.5 模拟实现strcpy

#define _CRT_SECURE_NO_WARNINGS 1
#include<string.h>
#include<stdio.h>
#include<assert.h>

char* my_strcpy(char* destination,const char* source)
{
	assert(destination&& source);
		while (*destination++ = *source++);
	
	return destination;
}
int main()
{
	char arr1[] = "ABCDEFG";//空间大小为6
	char arr3[20] = {0};
	//char arr2[] = "HIJ ";//空间大小为3
	//strcpy(arr2,arr1);
	//const char* p = "hello bcd";//常量字符串,不可以修改
	my_strcpy( arr3 ,arr1);

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

4:strcat

字符串追加函数

源字符串必须以 '\0' 结束。
目标空间必须有足够的大,能容纳下源字符串的内容。
目标空间必须可修改。

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
int main()
{
	char array1[40] = "ABCDEFGHIJKLMN\0xxxx";
	printf("追加前array1=%s\n", array1);

	char array2[] = "opqrstuvwxyz";
	strcat(array1, array2);

	printf("追加后array1=%s\n", array1);
	return 0;
}

 

 

  4.1模拟实现strcat

//模拟实现strcat
#include<stdio.h>
#include<string.h>
char* my_strcat(char* destination, const char* source)
{
	while (*destination != 0)
	{
		destination++;
	}
	while (*source != 0)
	{
		*destination++ = *source++;
	}
	*destination = *source;
	return destination;
}
int main()
{
	char array1[40] = "ABCDEFGHIJKLMN\0xxxx";
	printf("追加前array1=%s\n", array1);

	char array2[] = "opqrstuvwxyz";
	my_strcat(array1, array2);

	printf("追加后array1=%s\n", array1);
	return 0;
}

4.2自己给自己追加

#include<stdio.h>
#include<string.h>
int main()
{
	char array1[40] = "ABC";
	strcat(array1, array1);
	printf("追加后array1=%s\n", array1);
	return 0;
}

 

5.字符比较函数strcmp

 比较的是对应位置上字符的大小而非长度

#include<stdio.h>
#include<string.h>
int main()
{
	char array1[] = "ABCDEF";
	char array2[] = "ABCDEF";
	char array3[] = "abcdef";
	char array4[] = "ABCDEFG";
	char array5[] = "ABCDEH";
	char array6[] = "abcefgh";
	char array7[] = "abq";
	int ret1 = strcmp(array1, array2);
	printf("%d\n", ret1);//array1==array2  ret1=0;
	int ret2 = strcmp(array1, array3);
	printf("%d\n", ret2);//array1<array3 ret2=-1;
	//int ret2 = strcmp(array1, array5);
	int ret3= strcmp(array5, array1);
	printf("%d\n", ret3);//array5>array1  ret3=1;
	int ret5 = strcmp(array6, array7);
	printf("%d\n", ret5);

	return 0;
}

5.1模拟实现

#include<stdio.h>
#include<string.h>
int my_strcmp(char* str1, char* str2)
{
	while (*str1++ == *str2++)
	{
		if (*str1 == '\0' && *str2 == '\0')
			return 0;
	}
	if (*str1 > *str2)
		return 1;
	else
		return -1;

}
int main()
{
	char array1[] = "ABCDEQ";
	char array2[] = "ABCDEq";
	
	int ret5 = my_strcmp(array1, array2);
	printf("%d\n", ret5);

	return 0;
}

长度受限制的字符串函数介绍:strncpy,strncat,strncmp

6:strncpy

 6.1模拟实现strncpy函数

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>

char* my_strncpy(char* destination, const char* source, size_t num)
{
	char* str1 = destination;
	while (num && (*destination++ = *source++) != '\0')
	{
		num--;
	}
	if (num)
		while (--num)
			*destination++ = '\0';
	return str1;
}
int main()
{
	char array1[20] = "ABCDE";
	char array2[] = "abcde";

	char* a= my_strncpy(array1, array2,3);
	printf("%s\n", array1);

	return 0;
}

这里就不讲解拷贝长度大于源头字符串长度的情况,因为没有实际运用意义。
 

7. strncat
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>

//char* my_strncpy(char* destination, const char* source, size_t num)
//{
//	char* str1 = destination;
//	while (num && (*destination++ = *source++) != '\0')
//	{
//		num--;
//	}
//	if (num)
//		while (--num)
//			*destination++ = '\0';
//	return str1;
//}
int main()
{
	char arr1[20] = "hello ";
	char arr2[] = "world  ABC ";

	strncat(arr1, arr2,5);//array1空间足够大,不拷贝ABC
	printf("%s\n", arr1);

	return 0;
}

 

7.1模拟实现strncat

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
char* my_strncat(char* destination, const char* source, size_t num)
{
	char* str1 = destination;
	while (*destination++ != '\0');
	destination--;
	while(num--)
		{
		*destination++ = *source++;
		}
	return  str1;
}
int main()
{
	char arr1[20] = "hello ";
	char arr2[] = "world  ABC ";

	my_strncat(arr1, arr2,5);//array1空间足够大,不拷贝ABC
	printf("%s\n", arr1);

	return 0;
}

8:strncmp

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

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>

int main()
{
	char arr1[20] = "hello  ";
	char arr2[] = "hello world ";
	//比较arr1和arr2的前5个字符
	int ret=strncmp(arr1, arr2,5);
	printf("%d\n", ret);//相等  0
	int ret1 = strncmp(arr1, arr2, 8);
	printf("%d\n", ret1);//arr2大

	return 0;
}

9.strstr

判断一个字符串中是否包含寻找另一个字符串,如果包含返回字串第一次所在的起始位置,不存在返回NULL。
const char * strstr ( const char * str1, const char * str2 );
      char * strstr (       char * str1, const char * str2 );
定位子字符串

返回指向 str1 中第一次出现的 str2 的指针,如果 str2 不是 str1 的一部分,则返回空指针。
匹配过程不包括终止空字符,但它在那里停止。

参数

str1:要扫描的 C 字符串。

str2:包含要匹配的字符序列的 C 字符串。

返回值

指向 str2 中指定的整个字符序列中 str1 中第一个出现的指针,如果 str1 中不存在该序列,则为空指针。

#define _CRT_SECURE_NO_WARNINGS 1
#include<string.h>
#include<stdio.h>
int main()
{
	char arra1[] = "abcdefaaadef";
	char arra2[] = "def";
	char* pch = strstr(arra1, arra2);
	if (pch == NULL)
	{
		printf("不存在\n");
	}
	else
	{
		printf("%s", pch);
	}
	return 0;
}

9.0:模拟实现strstr

#define _CRT_SECURE_NO_WARNINGS 1
#include<string.h>
#include<stdio.h>

char* my_strstr(const char* str1, const char* str2)
{
	const char* s1 = str1;
	const char* s2 = str2;
	const char* cp = str1;
	while (*cp)
	{
		s1 = cp;
		s2 = str2;
		while (*s1 != '\0' && *s2 != '\0' && (*s1 == *s2))
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')
			 return (char*) cp;
		cp++;
	}
	return NULL;

}
int main()
{
	char arra1[] = "defqcrggedef";
	char arra2[] = "def";
	char* cp=my_strstr(arra1, arra2);
	if (cp== NULL)
	{
		printf("不存在\n");
	}
	else
	{
		printf("%s", cp);
	}
	return 0;
}

10.memcpy

函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。 这个函数在遇到 '\0' 的时候并不会停下来。 如果source和destination有任何的重叠,复制的结果都是未定义的。

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
int main()
{
	int array[] = { 1,1,1,1,1,1,1,1,1,1 };
	int array2[10] = { 0 };
	memcpy(array2, array, 20);
	for (int i = 0; i < 10; i++)
	{
		printf("%d  ", array2[i]);
	}
	return 0;
}

 

 

 

 

10.1模拟memcpy

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
#include<assert.h>

void* my_memcpy(void* dest, void* src, size_t num)
{
	void* ret = dest;
	assert(dest);
	assert(src);

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

	return ret;
}
int main()
{
	int array[] = { 1,1,1,1,1,1,1,1,1,1 };
	int array2[10] = { 0 };
	my_memcpy(array2, array, 20);
	for (int i = 0; i < 10; i++)
	{
		printf("%d  ", array2[i]);
	}

	
	return 0;
}

11.memmove

和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。 如果源空间和目标空间出现重叠,就得使用memmove函数处理。

 

模拟memmove


#include<stdio.h>
#include<assert.h>
void* my_memmove(void* dest, void* src, size_t num)
{
	void* ret = dest;
	assert(dest);
	assert(src);

	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;
}
int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	my_memmove(arr1 + 3, arr1, 28);
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr1[i]);
	}
	return 0;
}

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值