字符串进阶(字符函数&内存函数)

字符函数

strlen()

求字符串长度

  • 字符串已经 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包含 '\0' )。
  • 参数指向的字符串必须要以 '\0' 结束。
  • 注意函数的返回值为size_t,是无符号的( 易错 )
  • 学会strlen函数的模拟实现
//strlen() 模拟
// 求字符串长度,必须以'\0'结尾
//size_t strlen( const char* str);
size_t my_strlen(const char* str)
{
	int count = 0;
	while (*str != '\0')
	{
		count++;
		str++;
	}
	return count;
}

strcpy()

拷贝字符串

  • 源字符串必须以 '\0' 结束。
  • 会将源字符串中的 '\0' 拷贝到目标空间。
  • 目标空间必须足够大,以确保能存放源字符串。
  • 目标空间必须可变。
  • 学会模拟实现
//strcpy() 模拟
// 字符串拷贝
//char* strcpy(char *destination,const char *source);
char* my_strcpy(char *destination, const char* source)
{
	assert(destination != NULL && source != NULL);
	char* strdes = destination;
	const char* strsou = source;
	while (*strsou != '\0')
	{
		*strdes = *strsou;
		strdes++;
		strsou++;
	}
	*strdes = '\0';
	return destination;
}

strcat()

连接字符串

  • 源字符串必须以 '\0' 结束。
  • 目标空间必须有足够的大,能容纳下源字符串的内容。
  • 目标空间必须可修改。
  • 字符串自己给自己追加,如何?
//strcat() 模拟
// 连接两个字符串,destination必须要有足够的空间
//char* strcat(char *destination,const char *source);
char* my_strcat(char* destination, const char* source)
{
	assert(destination != NULL && source != NULL && destination!=source);
	char* strdes = destination;
	const char* strsou = source;
	while (*strdes != '\0')
	{
		strdes++;
	}
	while (*strsou != '\0')
	{
		*strdes = *strsou;
		strdes++;
		strsou++;
	}
	*strdes = '\0';
	return destination;
}

strcmp()

比较字符串

  • 标准规定:
  • 第一个字符串大于第二个字符串,则返回大于0的数字
  • 第一个字符串等于第二个字符串,则返回0
  • 第一个字符串小于第二个字符串,则返回小于0的数字
//strcmp() 模拟
// 两个字符串比较
//int strcmp(const char*str1,const char*str2);
int my_strcmp(const char* str1, const char* str2)
{
	assert(str1 != NULL && str2 != NULL);
	while (*str1!='\0')
	{
		if (*str1 == *str2)
		{
			str1++;
			str2++;
		}
		else
			break;
	}
	return *str1 - *str2;
}

strstr()

查找字符串1中,第一个出现字符串2的位置,返回其指针

//strstr() 模拟
// 查找str1中第一个出现str2字符串的位置
//char * strstr ( const char *, const char * );
char* my_strstr(const char* str1, const char* str2)
{
	assert(str1 != NULL && str2 != NULL);
	const char* s1 = str1;
	const char* s2 = str2;
	while (*s1 != '\0'&& *s2 != '\0')
	{
		if (*s1 == *s2)
		{
			s2++;
			s1++;
		}
		else
		{
			s2 = str2;
			s1++;
		}
	}
	if (*s2 == '\0')
		return (s1 - strlen(str2));
	else
		return NULL;
}

strncpy()

  • 拷贝num个字符从源字符串到目标空间。
  • 如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。
char* my_strncpy( char *strDest, const char *strSource, size_t count )
{
	assert(strDest!=NULL && strSource!=NULL);
	char *pDest = strDest;
	int str_len = strlen(strSource);
	for(int i=0; i<count; ++i)
	{
		if(i < str_len)
			*pDest++ = *strSource++;
		else 
			*pDest++ = '\0';
	}
	return strDest;
}

strncat()

char* my_strncat( char *strDest, const char *strSource, size_t count )
{
	assert(strDest!=NULL && strSource!=NULL);
	char *pDest = strDest;
	while(*pDest != '\0')
		pDest++;
	int str_len = strlen(strSource);
	for(int i=0; i<str_len&&i<count; ++i)
	{
		*pDest++ = *strSource++;
	}
	*pDest = '\0';
	return strDest;
}

strncmp()

int my_strncmp( const char *string1, const char *string2, size_t count )
{
	assert(string1!=NULL && string2!=NULL);
	int res = 0;
	while(count-- != 0)
	{
		res = *string1 - *string2;
		if(res != 0)
			break;
		string1++;
		string2++;
	}
	if(res > 0)
		res = 1;
	else if(res < 0)
		res = -1;
	return res;
}

strtok()

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

int main()
{
	//char *p = "zhangsan\0qq.com";
	char p[] = "zhangsan@163.com";
	const char* sep = "@.";

	strtok(p, sep);
	char *res = strtok(NULL, sep);
	printf("%s\n", res);
}

strerror()

返回错误码,所对应的错误信息。

#include<stdio.h>
#incldue<errno.h>
//errno 
void main()
{
	FILE *fp = fopen("Test1.txt", "r");
	if(fp == NULL)
	{
		printf("errno = %d\n", errno);
		printf("err msg = %s\n", strerror(errno));
		printf("打开文件失败.\n");
		return;
	}
	printf("打开文件成功.\n");

	fclose(fp);
}

内存函数

memcpy()

拷贝source中的n个字节到destination()

  • 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。
  • 这个函数在遇到 '\0' 的时候并不会停下来。
  • 如果source和destination有任何的重叠,复制的结果都是未定义的。
//memcpy() 模拟
// 复制source中n个字节的内容到destination
// 如果source和destination有任何的重叠,复制的结果都是未定义的。
//void * memcpy ( void * destination, const void * source, size_t num ); 
void* my_memcpy(void* destination, const void* source, size_t num)
{
	assert(destination != NULL && source != NULL);
	char* strdes = (char*)destination;
	char* strsou = (char*)source;
	while (num--)
	{
		*strdes = *strsou;
		strdes++;
		strsou++;
	}
	return destination;
}

memmove()

拷贝source中的n个字节到destination()

  • 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。
  • 这个函数在遇到 '\0' 的时候并不会停下来。
  • source和destination可以存在重叠。
//memmove() 模拟
//复制source中n个字节的内容到destination
//如果source和destination有任何的重叠,复制的结果不会出错。
//void * memmove ( void * destination, const void * source, size_t num );
void* my_memmove(void* destination, const void* source, size_t num)
{
	assert(destination != NULL && source != NULL);
	char* strdes = (char*)destination;
	char* strsou = (char*)source;
	//destination在后,source在前,发生空间重叠,倒着复制
	if (strdes > strsou)
	{
		strdes = strdes + num - 1;
		strsou = strsou + num - 1;
		while (num--)
		{
			*strdes = *strsou;
			strdes--;
			strsou--;
		}
	}
	else
	{
		while (num--)
		{
			*strdes = *strsou;
			strdes++;
			strsou++;
		}
	}
	return destination;
}

memcpy()

比较从ptr1和ptr2指针开始的num个字节

int my_memcmp( const void *buf1, const void *buf2, size_t count )
{
	assert(buf1!=NULL && buf2!=NULL);
	const char *pf1 = (const char*)buf1;
	const char *pf2 = (const char *)buf2;

	int res = 0;
	while(count-- != 0)
	{
		res = *pf1 - *pf2;
		if(res != 0)
			break;
		pf1++;
		pf2++;
	}
	return res;
}

memset()

初始化dest指向的地址及其后n个字节;

void* my_memset( void *dest, int c, size_t count )
{
	assert(dest != NULL);
	char *pDest = (char *)dest;
	while(count-- != 0)
	{
		*pDest++ = c;
	}
	return dest;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值