C语言字符串函数和内存操作函数

目录

前言

一、最常用的字符串操作函数

1.strlen函数

2.strcpy函数 

3.strcat函数

4.strcmp函数

二、字符串查找函数

1.strstr函数

2.strtok函数 

三、报错函数

strerror函数

四、内存操作函数

1.memset函数

2.memcpy函数

3.memmove函数

4.memcmp函数


前言

在编写程序时,为了更加方便的对字符串进行操作,我们会用到字符串操作函数。本文带大家认识一些常用的字符串函数和内存操作函数,以及他们的底层代码。了解了他们的逻辑之后以后用起来就能更加的得心应手了。


 注:下文中的size_t的意思是无符号整形。const表示被修饰的指针不能被解引用修改(上传到函数的字符串本身不需要被修改时使用)。

一、最常用的字符串操作函数

1.strlen函数

函数格式

size_t strlen ( const char * str );

函数作用

计算字符串长度

strlen和sizeof的区别

1.strlen是一个函数,需要头文件      sizeof是一个字符串,可以直接使用

2.strlen只能计算字符串的长度                          sizeof可以计算表达式大小

3.strlen不会算入字符串中最后一个'\0'大小       sizeof会算入'\0'大小

strlen的基本逻辑是使用一个指针,向后移动并且计数,遇到'\0'之后停止计数 。

代码实现

size_t my_strlen(const char* star)
{
	assert(star);//assert函数断言确定star不是空指针,需要头文件
	char* end=star;
	while (*end)
	{
		end++;
	}
	return end - star;
}

2.strcpy函数 

函数格式

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

 函数作用

 拷贝字符串

 strcpy注意事项

1.源字符串必须'\0' 结束

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

3.目标空间必须足够大,以确保能存放源字符串。
4.目标空间必须可变

strcpy函数的基本逻辑是把源头指针解引用后赋值给目的地指针,将源头指针和目的地指针逐个向后移,直到遇到'\0'之后停止。由于会把'\0'传过去,虽然不会把目的地的字符串全部覆盖,但由于'\0',下次打印时,后面空间不会被访问,于是就实现了拷贝的功能。

 代码实现

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

3.strcat函数

函数格式

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

函数作用

把两个字符串相连

 strcat注意事项

1.源字符串必须'\0' 结束

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

3.目标空间必须可修改。

strcat的基本逻辑是,首先让目标函数指针找到结尾的'\0',之后把源头的字符串从'\0'开始拷贝,后者逻辑基本和strcpy相同。 

代码实现

char* my_strcat(char* dest,const char* src)
{
	char* s1 = dest;
	while (*s1)
	{
		s1++;
	}
	while (*s1++ = *src++)
	{
		;
	}
	return dest;
}

注:不可以让一个函数即是目的地又是源头,在目的地中找到'\0'后,对目的地地址解引用之后改变当中的内容,第一次循环就会把'\0'去除,由于目的地和源头在同一个地址,之后就不再有'\0'这个结束符号了,造成死循环。 

4.strcmp函数

函数格式

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

函数作用

比较两个字符串是否相同

strcmp注意事项

第一个字符串大于第二个字符串,则返回大于 0 的数字
第一个字符串等于第二个字符串,则返回 0(要特别注意,相等返回0,和真假无关)
第一个字符串小于第二个字符串,则返回小于 0 的数字

strcmp基本逻辑,逐个比较字符串的ASSIC大小 ,找到一个不相等就返回,不再看后面的字符。

代码实现

int my_strcmp(const char* str1,const char* str2)
{

	assert(str1);
	assert(str2);
	while (*str1 == *str2)
	{
		if (*str1 != '\0')
		{
			str1++;
			str2++;
		}
		else
			return 0;
	}
	return *str1 - *str2;
}

注: strcpy,strcat,strcmp都有返回值而不是void类型,其目的是可以在printf中直接输入这个函数进行使用。(如下代码)

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

int main()
{
	char str1[20] = "############";
	char str2[] = "abcde";
	printf("%s", my_strcpy(str1, str2));
	return 0;
}

如果函数返回类型变成void ,会有如下报错:

C语言字符串函数和内存操作函数_第1张图片

C语言字符串函数和内存操作函数_第2张图片

二、字符串查找函数

1.strstr函数

函数格式

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

函数作用 

strstr的作用是在第一个字符串中找是否有第二个字符串,如果有返回从相等同位置开始的地址,如果不存在,返回空指针。 

代码实现 

char* my_strstr(const char* str1,const char* str2)
{
	assert(str1);
	assert(str2);
	if (*str2 == '\0')
		return str1;//如果要比较的字符串是‘\0’,返回原数组地址,C语言语法规定
	char* p=str1;//创建每次向后移动一个字节的指针
	char* s1 = str1;//创建遍历str1和str2的指针
	char* s2 = str2;
	while (*p)
	{
		//放在循环内,便于每次比较不成立时下次循环让两个指针在应有的位置
		s1 = p;//s1到达遍历到的那个位置
		s2 = str2;//s2到str2开头
		while (*s1!='\0'&&*s2!='\0' && *s1 == *s2)
		{
			//同时遍历两个数组,判断是否相等
			s1++;
			s2++;
		}
		if (*s2 == '\0')//如果遍历到了‘\0’,说明相等
			return (char*)p;
		p++;
	}
	return NULL;
}

2.strtok函数 

函数格式

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

函数作用 

strok的作用是找到第二个字符串在第一个字符串中的位置,并且把它改为'\0',通过循环可以把分开的字符串依次打印出来。由于此函数会修改原字符传,所以一般对已经备份过的字符串进行操作。 

strtok注意事项 

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

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

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

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

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

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

 函数使用方法演示

int main()
{
	char arr[] = "[email protected]";
	char buf[200] = { 0 };
	strcpy(buf, arr);//备份字符串
	const char* p = "@.";
	char* str = NULL;
	//第一次使用buf的地址,由于此函数会记住第一次结束后的位置,所以之后用NULL指针
	for (str=strtok(buf, p); str!=NULL; str=strtok(NULL, p))
	{
		printf("%s\n", str);
	}

	return 0;
}

三、报错函数

strerror函数

函数格式

char * strerror ( int errnum );
//errnum是报错后返回的错误数字

了解函数作用前须知

1.在C语言中,存在着自身规定的报错数字,例如,平日里在网上看见的网页404就是一个报错数字。每个报错数字有自己的意义。

2.C语言中存在errno的全局变量,在代码程序出现错误时,系统会自动为errno这个全局变量赋值报错数字。使用这个变量之前,需要用头文件

函数作用

strerror可以把报错数字翻译成英文,便于调试人员处理问题。(如下图)

C语言字符串函数和内存操作函数_第3张图片

 函数使用方法演示

#include
int main()
{
	FILE* pf = fopen("test.txt", "r");//打开一个文件
	if (pf == NULL)//如果不存在这个文件,pf会被置为空指针
	{
		printf("%s\n", strerror(errno));
		return 1;
	}
	fclose(pf);//关闭文件
	pf = NULL;//pf置为空释放空间
	return 0;
}

 项目文件夹下没有test.txt这个文件

C语言字符串函数和内存操作函数_第4张图片

C语言字符串函数和内存操作函数_第5张图片

  项目文件夹下有test.txt这个文件,报错信息消失

C语言字符串函数和内存操作函数_第6张图片

C语言字符串函数和内存操作函数_第7张图片

printf("%s\n", strerror(errno));

可以替换

perror(" ");//在引号中打入文字会在报错信息前输出(如下图)

C语言字符串函数和内存操作函数_第8张图片

 

四、内存操作函数

1.memset函数

函数格式

void * memset ( void * ptr, int value, size_t num );

函数作用

ptr为要开辟地址开头位置的指针,memset会把ptr后的内存都初始化为value的值(用ASSIC码表示),num为初始化内存大小的字节数。

 函数使用方法演示

#include
#include
int main()
{
	char str[10];
	memset(str,'a',8);
    return 0;
}

 运行过后,str处内存会被修改为如下图:

C语言字符串函数和内存操作函数_第9张图片

2.memcpy函数

函数格式

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

函数作用

将source处的数据逐个字节拷贝到destination处,和strcpy不同,memcpy可以拷贝任何类型的数据,而strcpy只能拷贝字符串。

注意事项

1.函数memcpysource的位置开始向后复制num个字节的数据到destination的内存位置。

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

3.如果sourcedestination有任何的重叠,复制的结果都是未定义的。

3.memmove函数

函数格式

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

函数作用

和memcpy类似,但是memmove可以拷贝重叠的数据

#include 
#include 
int main()
{
	char str[] = "memmove can be very useful......";
	memmove(str + 20, str + 15, 11);
	puts(str);
	return 0;
}

4.memcmp函数

函数格式

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

函数作用

比较从 ptr1ptr2指针开始的num 个字节 ,可以比较 任何数据
返回值如下表:

C语言字符串函数和内存操作函数_第10张图片

 

你可能感兴趣的:(C语言,c语言)