栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C语言字符函数和字符串函数

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C语言字符函数和字符串函数

字符函数和字符串函数
  • 前言
  • 1.求字符串长度
    • strlen
      • 注意(返回size_t为unsigned int)
      • 代码示例
      • 解释
  • 2.不受长度限制的字符串函数,以‘’作为结束标志
    • 1.strcpy
    • 2.strcat
      • my_strcat的实现
      • bug分析
    • 3.strcmp
      • my_strcmp的实现代码
  • 3.长度受限制的字符串函数
    • 1.strncpy
    • 2.strncat
      • 定义时的源码
    • 3.strncmp
      • 解释
  • 4.字符串查找
    • 1.strstr
      • my_strstr的实现
      • 代码一
      • 代码一的bug分析与解决1
      • 代码一的bug分析与解决2
      • 代码一完全修复后的代码
      • 代码二(strstr源码)
      • 遗留问题
    • 2.strtok
      • 1.概念图
  • 5.错误信息报告
      • 1.概念图
      • 2.代码示例一
      • 代码示例二
  • 6.字符操作
    • 字符操作分类函数(判断性质)
    • 字符操作转换函数
      • 代码
    • 和字符串操作函数的区别
    • 1.memcpy(内存拷贝)
      • 适用对象
      • my_memcpy的实现
        • Bug代码一
        • bug修复
      • 数组间的整体调换
        • 错误代码
        • 错误代码结果
    • 2.memmove
      • 基本解释
      • 代码示例
      • 输出结果
      • memcpy和memmove
      • my_memmove的实现
    • 3.memset-内存设置函数
      • 代码
    • 4.memcmp
      • 示例图

前言

C语言本身没有字符串类型,字符串要么放到字符数组里面,要么就放到一个常量字符串中,常量字符串适用于那些对它不做修改的字符串函数。(如果它能成为字符串,那么说明他的末尾一定放了一个‘’)

1.求字符串长度 strlen 注意(返回size_t为unsigned int)

代码示例

解释

两个无符号数相减得到的结果依然为无符号数。

2.不受长度限制的字符串函数,以‘’作为结束标志 1.strcpy

2.strcat

my_strcat的实现 bug分析


3.strcmp my_strcmp的实现代码
my_strcmp1(const char* str1, const char* str2)
{
	while (*str1>=''&&*str2>='')
	{
		if (*str1 > *str2)
			return 1;
		if (*str1 < *str2)
			return -1;
		if (*str1 == *str2)
		{
			if (*str1 != '')
			{
				str1++;
				str2++;
			}
			else
				return 0;
		}
	}
}
my_strcmp2(const char* str1, const char* str2)
{
	while (*str1 == *str2)
	{
		if (*str1== '')
			return 0;
		str1++;
		str2++;
	}
	if (*str1 > *str2)
		return 1;
	else
		return -1;
}
main()
{
	char arr1[30] = "hello";
	char arr2[] = "hello";
	int ret=my_strcmp(arr1, arr2);
	printf("%dn", ret);
}
3.长度受限制的字符串函数 1.strncpy

2.strncat 定义时的源码

3.strncmp 解释


4.字符串查找 1.strstr my_strstr的实现 代码一
char* my_strstr(const char* p1, const char* p2)
{
	assert(p1&&p2);
	if (*p2 == '')
		return p1;
	while (*p1 != '')
	{
		while (*p1 != *p2)
		{
			p1++;
			if (*p1 == '')
				return NULL;
		}
		char* rem = p1;
		while (*++p1 == *++p2);
		if (*p2 == '' || *(p2 - 1) == '')
			return rem;
	}
	return NULL;
}
main()
{
	char arr1[30] = "abcdef";
	char arr2[] = "abd";
	//int ret=my_strcmp(arr1, arr2);
	char* ret=my_strstr(arr1,arr2);
	if (ret == NULL)
	printf("找不到n");
	else
		printf("%sn",ret);

}
代码一的bug分析与解决1

这个代码是查找在arr1中是否包含arr2的所有字符,而不是查找子串。如果不满足条件

	if (*p2 == '' || *(p2 - 1) == '')

代表arr2部分存在于arr1中而不是全部,那么p2已经跨过了前面的相同字符,这时再探究arr2是否为arr1的子串时,需要对p2进行初始化。

代码一的bug分析与解决2

如果arr1是abbbc,arr2是bbc,那么尽管修复了bug1,但是仍然输出“找不到”。这是因为bug1是没有初始化p2,但是p1仍然需要初始化。

代码一完全修复后的代码
char* my_strstr(const char* p1, const char* p2)
{
	assert(p1&&p2);
	if (*p2 == '')
		return p1;
	char* rem2 = p2;
	while (*p1 != '')
	{
		while (*p1 != *p2)
		{
			p1++;
			if (*p1 == '')
				return NULL;
		}
		char* rem1 = p1;
		while (*++p1 == *++p2);
		if (*p2 == '' || *(p2 - 1) == '')
			return rem1;
		else
		{
			p2 = rem2;
			p1 = rem1 + 1;
		}
	}
	return NULL;
}
main()
{
	char arr1[30] = "abbbcg";
	char arr2[] = "bbg";
	char* ret=my_strstr(arr1,arr2);
	if (ret == NULL)
	printf("找不到n");
	else
		printf("%sn",ret);
}
代码二(strstr源码)

遗留问题

数据库里面的tmp算法。(待补充)

2.strtok 1.概念图


5.错误信息报告 1.概念图

2.代码示例一

代码示例二
#include
#include
main()
{
	//errno是一个全局的错误码变量
	//当C语言的库函数在执行的过程中,发生了错误,就会把对应的错误码赋值到errno中
	//打开文件
	FILE* pf=fopen("test.txt","r");// test.txt-打开文件的名称	r-读文件
	if (pf==NULL)//打开文件失败,返回空指针
		printf("%sn", strerror(errno));
	else
		printf("open file successn");
	printf("%sn",pf);
}
6.字符操作 字符操作分类函数(判断性质)

字符操作转换函数 图

代码
main()
{
	char ch = tolower('A');//tolower的参数如果是大写,则返回值转小写。如果参数是小写,则返回值仍为这个小写
	putchar(ch);
	char sh = toupper('a');
	putchar(sh);
	char arr[] = "I Am A Student";
	int i = 0;
	for (;i 

# 7.内存操作函数

和字符串操作函数的区别

函数:strcpy strcat strcmp strcpy strcat strcmp,它们的操作对象都是字符串(和‘’打交道)
那么如果现在要操作数组(浮点型和整形的数组)

1.memcpy(内存拷贝) 图

适用对象

整型,浮点型,字符型,结构体,字符串,数组。

my_memcpy的实现 Bug代码一


bug1在于强转的类型的优先级低于++的优先级,所以会先执行++,但是指针的类型为void*,所以执行++的步长不能确定。

bug修复


改为 ((char)dest)++ = ((char)src)++;

数组间的整体调换


命题:把前五个元素1,2,3,4,5换到3,4,5,6,7的位置上。

错误代码
void* my_memcpy(void* dest,const void* src,size_t num)
{
	char* rem = dest;
	for (int i = 0; i < num; i++)
	{
		 *((char*)dest)++ = *((char*)src)++;
	}
	return rem;
}
main()
{
	int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
	my_memcpy(arr+2,arr,20);
	for (int i = 0; i < sizeof(arr)/sizeof(arr[0]); i++)
		printf("%d  ", arr[i]);
}
错误代码结果

2.memmove 基本解释

处理内存重叠的情况。(也可处理不重叠),memmove函数很强大。

代码示例
main()
{
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	memmove(arr+2,arr,20);
	for (int i = 0; i < sizeof(arr)/sizeof(arr[0]); i++)
		printf("%d  ", arr[i]);
}
输出结果

memcpy和memmove

两个库函数都可实现同样的功能,都可处理重叠与不重叠的两种情况。超额完成标准。

my_memmove的实现
void my_memmove(void* dest, const void* src, int num)
{	
	if (dest < src)
	{
		//src整体从前向后move
		while (num--)
		{
			*(char*)dest = *(char*)src;
			*((char*)src)++;
			*((char*)dest)++;
		}
	}
	else
	{
		while (num--)
			//src整体从后向前move
		*((char*)dest+num )= *((char*)src+num);
	}
}
main()
{
	int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	my_memmove(arr, arr, 20);
	for (int i = 0; i < sizeof(arr)/sizeof(arr[0]); i++)
		printf("%d  ", arr[i]);
}
3.memset-内存设置函数 图

代码

4.memcmp 图

示例图


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/396460.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号