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

[c语言]认识string字符函数+内存函数 | 模拟实现|strlen strcpy strcat strcmp strstr strtok memcpy memmove memset memcmp

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

[c语言]认识string字符函数+内存函数 | 模拟实现|strlen strcpy strcat strcmp strstr strtok memcpy memmove memset memcmp

字符函数+内存函数的介绍 重点

求字符串长度

strlen

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

strcpy,strcat,strcmp

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

strncpy,strncat,strncmp

字符串查找

strstr,strtok

错误信息报告

strerror

内存操作函数

memcpy,memmove,memset,memcmp 函数介绍 strlen:返回字符串str的长度。

size_t strlen ( const char * str );

字符串的长度由终止空字符''决定:字符串的长度等于字符串开头和''之间的字符数==(不包括''本身)==。不可与sizeof函数混淆,如:char mystr[100]="test string";,sizeof(mystr)计算为100,strlen(mystr)计算为11。

注意:str指向的字符串必须以''结束,返回类型size_t是无符号整型

#include 
#include 
int main()
{
	char str1[] = "abcdef";
	char str2[] = "abc";
	if (strlen(str2) - strlen(str1) > 0)
		printf("str1str2n");
	return 0;
}

结果为str1 strcpy:复制字符串

char * strcpy ( char * destination, const char * source );

将source指向的字符串复制到destination指向的数组中,包括''(并在该点停止)。为避免溢出,destination指向的数组的大小应足够长,以包含与source相同的字符串(包括''),并且在内存中不应与source重叠。返回destination

strcat:连接字符串
char * strcat ( char * destination, const char * source );

将source字符串的副本追加到destination字符串。destination中==''被source的第一个字符覆盖==,''包含在由destination中的两个字符串连接而成的新字符串的末尾。destination和source不得重叠。返回destination注意:destination字符串必须以''结尾。

strcmp:比较两个字符串
int strcmp ( const char * str1, const char * str2 );

此函数一开始比较每个字符串的第一个字符。如果它们彼此相等,则继续比较下一对,直到字符不同或到达''。返回值:

返回值含义
<0第一个不匹配的字符在ptr1中的值小于ptr2中的值
0两个字符串的内容相等
>0第一个不匹配的字符在ptr1中的值大于ptr2中的值

(vs中返回值分别为-1,0,1)

strncpy,strncat,strncmp

这些带n的函数的参数部分分别在以上对应函数的参数后面多一个size_t num

strncpy:

拷贝num个字符从源字符串到目标空间。
如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。 strncat:

将源字符串中最开始的num个字符加上''追加到目标字符串。
如果源字符串的长度小于num,则仅复制''之前的内容。 strncmp:

比较字符串str1和字符串str2的至多num个字符。
此函数一开始比较每个字符串的第一个字符。如果它们彼此相等,则继续比较下一对,直到字符不同,或到达'',或者num个字符全部比较完。 strstr:找出子串

const char * strstr ( const char * str1, const char * str2 );
      char * strstr (       char * str1, const char * str2 );

返回str1中第一个出现str2的字符串的指针,如果str2不是str1的子串,则返回空指针。比对过程不包括'',但会在此停止。

例子:

int main()
{
    char str[] = "This is a simple string";
    char* pch = strstr(str, "simple");
    if (pch != NULL)
        printf("%s", pch);
    else
        printf("不是子串");
    return 0;
}

结果:simple string

strtok:拆分字符串
char * strtok ( char * str, const char * delimiters );

sep参数是个字符串,定义了用作分隔符的字符集合str参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记。strtok函数找到str中的下一个标记,并将其用''结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)str参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。str参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。如果字符串中不存在更多的标记,则返回 NULL 指针。

例子:

#include 
#include 
int main()
{
	const char* p = "/.";
	char arr[] = "csdn.net/CegghnnoR";
	char buf[50] = { 0 };
	strcpy(buf, arr);
	
	char* str = strtok(buf, p);
	printf("%sn", str);
	str = strtok(NULL, p);
	printf("%sn", str);
	str = strtok(NULL, p);
	printf("%sn", str);
	//开始返回NULL
	str = strtok(NULL, p);
	printf("%sn", str);
	return 0;
}

结果:csdn
net
CegghnnoR
(null)

strerror:获取错误消息
char * strerror ( int errnum );

c语言中规定了一些错误信息

errnum为错误码,返回一个指向这些错误信息字符串的指针。

相当于将错误码翻译成错误信息。

例子:

int main()
{
	//打开文件
	FILE* pf = fopen("test.txt", "r");
	if (NULL == pf)
	{
		//出错误的原因是什么
		printf("%sn", strerror(errno));
		return 0;
	}
	//读文件
	//...
	
	//关闭文件
	fclose(pf);
	pf = NULL;

	return 0;
}

结果:No such file or directory

errno是C语言提供的一个全局变量,可以直接使用,放在errno.h文件中的当库函数使用的时候,发生错误会把errno变量设置为本次执行库函数产生的错误码 字符 分类&转换 函数

头文件:ctype.h

函数参数符合下列条件则返回真
iscntrl任何控制字符
isspace空白字符:空格‘ ’,换页‘f’,换行’n’,回车‘r’,制表符’t’或者垂直制表符’v’
isdigit十进制数字 0~9
isxdigit十六进制数字,包括所有十进制数字,小写字母a~f,大写字母A~F
islower小写字母a~z
isupper大写字母A~Z
isalpha字母a~z或A~Z
isalnum字母或者数字,a~z,A~Z,0~9
ispunct标点符号,任何不属于数字或者字母的图形字符(可打印)
isgraph任何图形字符
isprint任何可打印字符,包括图形字符和空白字符
int tolower ( int c );//转小写
int toupper ( int c );//转大写
memcpy:复制内存块
void * memcpy ( void * destination, const void * source, size_t num );

从source指向的位置开始向后直接复制num个字节的值到destination指向的内存块。source指针和destination指针指向的对象的基本类型与此函数无关;结果是数据的二进制副本。该函数不检查source中是否有''——它总是精确复制num个字节。为避免溢出,destination和source参数指向的数组大小应至少为num字节,且不应重叠(重叠可使用memmove)。(vs中memcpy也可复制重叠内存块)返回destination

strcpy专用于拷贝字符串,而memcpy可以则拷贝各种类型的数据。

例子:

#include 
#include 
typedef struct stu
{
	char name[10];
	int age;
}stu;

//将arr1中的数据复制到arr2
int main()
{
	stu arr1[2] = { {"zhangsan",20},{"lisi",18} };
	stu arr2[10] = { 0 };
	memcpy(arr2, arr1, sizeof(arr1));
	for (int i = 0; i < 2; i++)
	{
		printf("%s %dn", arr1[i].name, arr1[i].age);
	}
}
memmove:移动内存块

具有memcpy的功能,并且源内存块和目标内存块可以重叠

例子:

#include 
#include 
int main()
{
	int arr[] = { 1,2,3,4,5,6 };
	int sz = sizeof(arr) / sizeof(arr[0]);
    //将arr开始后面四个元素拷贝到arr+2开始的内存块
	memmove(arr + 2, arr, 4 * sizeof(arr[0]));
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

结果:1 2 1 2 3 4

memcmp:比较两块内存
int memcmp ( const void * ptr1, const void * ptr2, size_t num );

分别对ptr1和ptr2指向的两块num字节内存进行逐字节比较。

注意:与strcmp不同,函数在找到空字符后不会停止比较。

返回值:

返回值含义
<0两个内存块中第一个不匹配的字节在ptr1中的值小于ptr2中的值
0两个内存块的内容相同
>0两个内存块中第一个不匹配的字节在ptr1中的值大于ptr2中的值

例子:

#include 
#include 
int main()
{
	char s1[] = "abcd";
	char s2[] = "abad";
	int n = memcmp(s1, s2, 4);
	if (n < 0)
		printf("s1s2");
	return 0;
}

结果:s1>s2

memset:填充内存块
void * memset ( void * ptr, int value, size_t num );

将ptr指向的内存块的num个字节设置为指定值value(解释为无符号字符)。

int main()
{
	char s[10] = { 0 };
    //将前五个字符设置成'x'
	memset(s, 'x', 5);
	printf("%s", s);
	return 0;
}

结果:xxxxx

也可以用于整型数组的初始化 模拟实现 strlen的模拟实现 方法1:计数器

int my_strlen(const char* str)
{
	assert(str);
	int count = 0;
	while (*str)
	{
		count++;
		str++;
	}
	return count;
}
方法2:递归
int my_strlen(const char* str)
{
	if (*str == '')
		return 0;
	else
		return 1 + my_strlen(str + 1);
}
方法3:指针
int my_strlen(char* s)
{
   char* p = s;
   while (*p != '')
   	p++;
   return p - s;
}
strcpy的模拟实现
char* my_strcpy(char* dest, const char* src)
{
	char* ret = dest;
	assert(dest && src);
	while (*dest++ = *src++)
	{
		;
	}
	return ret;
}
strcat的模拟实现
char* my_strcat(char* dest, const char* src)
{
	char* ret = dest;
	assert(dest && src);
	//找到目标空间中的
	while (*dest)
	{
		dest++;
	}
	//追加内容到目标空间
	while (*dest++ = *src++)
	{
		;
	}
	return ret;
}
strcmp的模拟实现
int my_strcmp(const char* str1, const char*str2)
{
	assert(str1 && str2);
	while (*str1 == *str2)
	{
		if (*str1 == '')
			return 0;
		
		str1++;
		str2++;
	}
	return *str1 - *str2;
}
strstr的模拟实现

定义三个指针变量cur,s1,s2

s1和s2相等则同时++不等则cur++,s1指向cur指向的元素,s2指向起始位置重复以上步骤,直到s2指向''(找到),或cur指向''(未找到)

char* my_strstr(const char* str, const char* substr)
{
	const char* s1 = str;
	const char* s2 = substr;
	const char* cur = str;
	//子串为,直接返回原字符串
	assert(str && substr);
	if (*substr == '')
	{
		return (char*)str;
	}
	while (*cur)
	{
		s1 = cur;
		s2 = substr;
		while (*s1 &&  *s2 && *s1 == *s2)
		{
			s1++;
			s2++;
		}
		if (*s2 == '')
			return (char*)cur;

		cur++;
	}
	return NULL;
}
memcpy的模拟实现
void* my_memcpy(void* dest, const void*src, size_t num)
{
	void* ret = dest;
	assert(dest && src);

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

	return ret;
}

使用void*类型可以接收任意类型参数指针向后移动需要先强制转换为char* memmove的模拟实现

要实现重叠空间拷贝,需分两种情况讨论:

如将红色部分拷贝到蓝色部分,应该从前向后拷贝,3->1,4->2,5->3,6->4,结果为3 4 5 6 5 6,如从后向前拷贝,则会变成5 6 5 6 5 6,因为3和4在被拷贝之前就被5和6覆盖掉了。如将蓝色部分拷贝到红色部分,应该从后向前拷贝,结果为1 2 1 2 3 4,如从前向后拷贝,则会变成1 2 1 2 1 2 。

故当源指针大于目标指针(源内存块在目标内存块之后),则从前向后拷贝,

源指针小于目标指针(源内存块在目标内存块之前),则从后向前拷贝。

void* my_memmove(void* dest, const void* src, size_t num)
{
	void* ret = dest;
	assert(dest && 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;
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/713811.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

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

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