C语言字符与字符串的库函数

本章重点介绍字符和字符串的库函数使用,C语言本身是没有字符串类型的,字符串通常存放在常量字符串或字符数组中。字符串常量适用于那些对它不做修改的字符串函数。

1.strlen:求字符串的长度(不包括  '\0' )

size_t strlen(const char * str);

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

>>参数指向的字符串必须要以 '\0' 结束。

>>注意函数返回值是size_t 是无符号的(重点)。

>>学会模拟实现strlen.

 程序如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
	char* str1 = "hello world";
	char* str2 = "world";
	if (strlen(str1) > strlen(str2))
		printf("str1>str2\n");
	else
		printf("str1<str2\n");
	system("pause");
	return 0;
}

结果:str1字符要比str2字符多,所以if判断语句为真;

 现在我们来模拟实现这个strlen这个函数:

方式1:

int My_strlen(const char* str)
{
    assert(str);
	size_t count = 0;
	while (*str)
	{
		count++;
		str++;
	}
	return count;
}

这个方法创建了一个count变量来计数大小;

2.strcpy:这个函数是拷贝字符串

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

>>字符串必须以'\0'结束。

>>会将源字符串中的'\0'拷贝到目标空间。

>>目标空间必须足够大,以确保能存放源字符串。

>>目标空间必须可变。

>>学会模拟实现strcpy

 模拟实现:

char* my_strcpy(char* dest, const char* str)
{
	assert(dest);
	assert(str);
	char* ret = dest;
	while (*str)
	{
		*dest++ = *str;
	}
	*dest = *str;
	return ret;
}

3.strcat:将source所指向的字符串追加到destination所指向的字符串后,简称:追加!

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

>>源字符必须以'\0'结束。

>>目标空间必须足够大,能容纳下源字符串的内容。

>>目标空间必须可修改。

>>字符串自己给自己追加,如何?

模拟实现strcat:

char* my_strcat(char* dest, const char* str)
{
	assert(dest);
	assert(str);
	char* ret = dest;
	while (*dest!='\0')
	{
		dest++;
	}
	while (*dest++ = *str++)
	{
		;
	}
	return ret;
}

//如果自己给自己追加,会陷入死循环,会报错!

4.strcmp:比较两个字符串是否相等,如果相等则返回0

int strcmp(const char* str1,const char* str2);

>>标准规定:

>>第一个字符串大于第二个字符串,则返回大于0的数字;

>>第一个字符串等于第二个字符串,则返回0;

>>第一个字符串小于第二个字符串,则返回小于0的数字;

>>那么如何判断两个字符串?

模拟实现strcmp:

int my_strcmp(char* str1, const char* str2)
{
	assert(str1&&str2);
	while (*str1 == *str2)
	{
		if (*str1 == '\0')
			return 0;//相等
		str1++;
		str2++;
	}
	return (*str1 - *str2);
}

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

长度受限制的字符串函数(相对于安全一些):strncpy、strncat、strncmp;

5.strncpy:将source所指向的字符串中num个字符拷贝到destination所指向的字符串中

char* strncpy(char* destination,const char* source,size_t num);

>>拷贝num个字符从源字符串到目标空间;

>>如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,自到num个;

模拟实现strncpy:

char* my_strncpy(char* dest, const char* str, size_t num)
{
	assert(dest && str);
	char* ret = dest;
	while (num && (*dest++ = *str++))//将src字符串中的num个字符拷贝到cp中
	{
		num--;
	}
	while (num)//若num人大于0,则将cp中接下来的num个字符置为'\0'
	{
		*dest++ = '\0';
		num--;
	}
	return ret;
}

6.strncat:在destination所指向的字符串末尾加上num个source所指向的字符串的字符

char* strncat(char* destination,const char* source,size_t num);

模拟实现strncat:

char* my_strncat(char* str1, const char* str2, size_t num)
{
	assert(str1 && str2);
	char* ret = str1;
	while (*str1)//cp遍历str1至'\0'
	{
		str1++;
	}
	while (num--)//将str2中num个字符拷贝到str1中,若num大于str2字符串长度,则将str1之后的一个字符置为'\0'
	{
		*str1++ = *str2++;
		if (*str2 == '\0')
			return ret;
	}
	*str1 = '\0';
	return ret;
}

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

模拟实现strncmp:

int my_strncmp(const char* str1, const char* str2, size_t num)
{
	assert(str1 && str2);
	while (*str1 == *str2 && num)//str1与str2相等或num不为0是进入循环
	{
		str1++;
		str2++;
		num--;
		if (*str2 == '\0' || num == 0)//num等于0或str2与str1已比较完成说明二者相同,返回0
			return 0;
	}
	if (*str1 > *str2)
		return 1;
	else
		return -1;
}

8.strstr :判断str2是否在str1中出现,即str2是否为str1的子串,若是,则返回str2在str1中首次出现的字符地址,否则返回NULL

模拟实现strstr:

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

 9.strtok:切割字符串

char* strtok(char* str,const char* sep);

>>sep参数是个字符串,定义了用作分隔的字符集合;

>>第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔分割的标记。

>>strtok函数找到str中的下一个标记,并将其用\0结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改)

>>strtok函数的第一个参数不为NULL,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。

>>strtok函数第一个参数为NULL;函数将在同一个字符串中被保存的位置开始,查找下一个标记。

>>如果字符串中不存在更多的标记,则返回NULL指针;

#include <stdio.h>
#include <stdlib.h>
#include<string.h>
int main()
{
	char str[] = "3414597751@qq.com";
	char* sep = "@.";
	char tmp[30];
	char* cp = NULL;
	strcpy(tmp, str);//将str拷贝一份到tmp中,避免strtok将str中的数据修改
	for (cp = strtok(tmp, sep); cp; cp = strtok(NULL, sep))
	{
		printf("%s\n", cp);
	}
	system("pause");
	return 0;
}

运行结果:

10.strerror:返回错误码所对应的错误信息

char* strerror(int errnum);      返回错误码,所对应的错误信息!

>> strerror函数的应用在判断一些操作的错误类型时能起到很好的效果,比如在程序未达到预期的效果时,可以通过strerror来判断错误的原因,比如:想打开text.txt文件时,没有达到预期效果,可以调用该函数来查找原因。
C语言的库函数,在执行失败的时候,都会设置错误码!

//0   1  2  3  4  5  6  7  8

#include <stdio.h>
#include <stdlib.h>
#include<string.h>
int main()
{
	printf("%s\n", strerror(0));
	printf("%s\n", strerror(1));
	printf("%s\n", strerror(2));
	printf("%s\n", strerror(3));
	system("pause");
	return 0;
}

运行结果:

 看看strerror函数如何使用的:

#include <stdio.h>
#include <stdlib.h>
#include<string.h>
int main()
{
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		printf("文件打开失败:%s\n", strerror(errno));//errno->是C语言设置的一个全局的错误码存放的变量
		system("pause");
		return 1;
	}
	system("pause");
	return 0;
}

运行结果:

11.memcpy:

void* memcpy(void* destination,const void*source,size_t num);

>>函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。

>>这个函数在遇到'\0'的时候并不会停下来。

>>如果source和destination有任何的重叠,复制的结果都是未定义的。

模拟实现memcpy:

void* My_memcpy(void* dest, const void* str, size_t num)
{
	assert(dest&&str);
	void* ret = dest;
	while (num--)
	{
		*(char*)dest = *(char*)str;
		dest = (char*)dest + 1;
		str = (char*)str + 1;
	}
	return ret;
}

memcpy函数是不用来处理重叠的内存之间的数据拷贝的

使用memmove函数来实现,重叠内存之间的数据拷贝

12.memmove:

void* memmove(void* destination,const void* source,size_t num);

>>和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。

>>如果源空间和目标空间出现重叠,就得使用memmove函数处理。

memmove的原理实现过程,如何做到不重叠的方式!

模拟实现memmove:

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;
}

注意:memmove函数的模拟实现要小心指针所指向内容(数组)被覆盖的问题。

12.memcmp:

int memcmp(const void* ptr1,const void* ptr2,size_t num);

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

>>返回值如下:

 12.memset:——memory   set  内存设置

 

 

总结:

字符和字符串的库函数的模拟实现部分到此结束了,感谢您的阅读!!!如果这部内容对你有所帮助的话,记得給我(点赞、收藏、关注)谢谢!后续会持续更新!!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值