深入了解一些字符串函数,内存函数

Posted 小写丶H

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深入了解一些字符串函数,内存函数相关的知识,希望对你有一定的参考价值。

今天我们彻底了解一下字符串函数 strlen,strcpy,strcmp,strcat,strstr,strtok,strerror等,以及内存函数memcpy,memmove,memset,memcmp等。

字符串函数(1-5含自定义的)

我们知道c语言中是没有字符串类型的,字符串通常放在常量字符串中 或者 字符数组中。

char s1[]="abc";      //结尾有'\\0' ;	字符串常量适用于那些对它不做修改的字符串函数
char s2[]={'a','b','c'}; //结尾没有'\\0'

当使用一些库函数的时候,如果我们能了解它们的内部,那么我们便一定可以熟练掌握运用它们。

1.strlen()

求字符串长度函数.

Get the length of a string.

size_t strlen( const char *string );

API里提供的例子:

#include <string.h>
#include <stdio.h>
#include <conio.h>
#include <dos.h>

void main( void )
{
   char buffer[61] = "How long am I?";
   int  len;
   //库函数
   len = strlen( buffer ); 
   printf( "'%s' is %d characters long\\n", buffer, len );
}

自己定义的my_strlen():

//有三种形式
#include <stdio.h>
//1.计数器
int my_strlen(const char* str)
{
	int count = 0;
	while (*str != '\\0')
	{
		count++;
		str++;
	}
	return count;
}
//2.递归(字符过长时,不建议使用,容易栈溢出)
int my_strlen(const char* str)
{
	if('\\0'==*str)
	{
		return 0;
	}
	else
	{
		return 1+my_strlen(str+1);
	}
}
//3.指针-指针(得到中间元素个数)
int my_strlen(const char *str)
{
	char *p = str;
	while (*p != '\\0')
	{
		p++;
	}
	return p - str;
}

int main()
{
	char str[] = "abcdef";
	printf("%d\\n",my_strlen(str));
	return 0;
}

2.strcpy()

拷贝字符串.

Copy a string.

char *strcpy( char *strDestination, const char *strSource );

API里提供的例子:

#include <string.h>
#include <stdio.h>

void main( void )
{
   char string[80];
   strcpy( string, "Hello world from " );
   printf( "String = %s\\n", string );
}

自己定义的my_strcpy():

char* my_strcpy(char* str1,const char* str2)
{
	char* ret= str1;
	assert(str1);
	assert(str2);
	while (*str1++ = *str2++)
	{
		;
	}
	return ret;
}
int main()
{
	char str1[] = "abcdef";
	char str2[] = "aaaaa";
	printf("%s\\n", my_strcpy(str1, str2));
	return 0;
}

3.strcmp()

两个字符串比较大小

Compare strings.

int strcmp( const char *string1, const char *string2 );

例子:

void main( void )
{
	char str1[] = "abcdef";
	char str2[] = "aeaaa";
	int ret = strcmp(str1, str2);

	if (ret > 0)
	{
		printf("str1>str2\\n");
	}
	else if (ret < 0)
	{
		printf("str1<str2\\n");
	}
	else
	{
		printf("str1=str2\\n");
	}
	return 0;
}

自己定义的my_strcmp():

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

int main()
{
	char str1[] = "abcdef";
	char str2[] = "aeaaa";
	int ret = my_strcmp(str1, str2);

	if (ret > 0)
	{
		printf("str1>str2\\n");
	}
	else if (ret < 0)
	{
		printf("str1<str2\\n");
	}
	else
	{
		printf("str1=str2\\n");
	}
	return 0;
}

4.strcat()

连接两个字符串.

Append a string.

char *strcat( char *strDestination, const char *strSource );

例子:

int main()
{
	char arr1[20] = "hello ";
	char arr2[] = "world";
	printf("%s\\n", strcat(arr1, arr2));
	
	return 0;
}

自己定义的my_strcat():

char *my_strcat(char *str1, const char *str2)
{
	assert(str1&&str2);
	char *ret = str1;
	while (*str1)
	{
		str1++;
	}
	while (*str1 ++= *str2++)
	{
		;
	}
	return ret;
}

int main()
{
	char str1[20] = "abcdef";
	char str2[] = "aeaaa";
	printf("%s\\n",my_strcat(str1, str2));
	return 0;
}

5.strstr()

比较字符串

Find a substring.

char *strstr( const char *string, const char *strCharSet );

例子:

int main()
{
	char str1[20] = "abcaadef";
	char str2[] = "aa";
	
	char* ret = strstr(str1, str2);
	if (NULL == ret)
	{
		printf("没找到!");
	}
	else
	{
		printf("找到了在:%s\\n", ret);
	}

	return 0;
}

自己定义的my_strstr():

char *my_strstr(const char *str1, const char *str2)
{
	assert(str1&&str2);
	const char *ret = str1;
	const char *s1 = NULL;
	const char *s2 = NULL;

	if ('\\0' == *str2)
	{
		return (char*)str1;
	}

	while (*ret)
	{
		s1 = ret;
		s2 = str2;
		while (*s1&*s2&(*s1 == *s2))
		{
			s1++;
			s2++;
		}
		if ('\\0' == *s2)
		{
			return (char*)ret;
		}
		ret++;
	}
	return NULL;
}

int main()
{
	char str1[20] = "abcaadef";
	char str2[] = "aa";

	char* ret = my_strstr(str1, str2);
	if (NULL == ret)
	{
		printf("没找到!");
	}
	else
	{
		printf("找到了在:%s\\n", ret);
	}

	return 0;
}

6.strtok()

Find the next token in a string.

char *strtok( char *strToken, const char *strDelimit );

int main()
{
	char arr[] = "lh.love. yty";
	char* p = ". ";//切割符,(不能是'\\0')
	char* ret = NULL;

	for (ret = strtok(arr, p); ret != NULL; ret=strtok(NULL, p))
	{
		printf("%s\\n", ret);
	}

	return 0;
}

在这里插入图片描述

7.strerror()

(获取系统错误消息(strerror)或打印用户提供的错误消息(_strerror)。)
Get a system error message (strerror) or prints a user-supplied error message (_strerror).

char *strerror( int errnum );

int main()
{
	printf("%s\\n", strerror(0));
	printf("%s\\n", strerror(1));
	printf("%s\\n", strerror(2));
	printf("%s\\n", strerror(3));
	printf("%s\\n", strerror(4));
	printf("%s\\n", strerror(5));
	
	return 0;
}

在这里插入图片描述

int main()
{
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		//errno,c语言定义的一个全局变量,把系统的报错信息存在此
		//直接使用errno
		printf("%s\\n", strerror(errno));
		return 1;
	}
	
	fclose(pf);
	pf = NULL;
	
	return 0;
}

在这里插入图片描述

受限制大小的字符串

1.strncpy()

Copy characters of one string to another.

char *strncpy( char *strDest, const char *strSource, size_t count );

例子:

int main()
{
	char arr1[20] = "aaabbbccc";
	char arr2[] = "qwer";
	strncpy(arr1, arr2, 4);//操作的是字节

	printf("%s\\n", arr1);
	return 0;
}

在这里插入图片描述

2.strncmp()

Compare characters of two strings.

int strncmp( const char *string1, const char *string2, size_t count );

例子:

int main()
{
	char* p = "aqcdef";
	char* q = "abcqwert";
	
	int ret = strncmp(p, q, 4);//操作的是字节
	
	if (ret > 0)
	{
		printf("p > q\\n");
	}
	else if (ret < 0)
	{
		printf("p < q\\n");
	}
	else
	{
		printf("p == q\\n");
	}

	return 0;
}

在这里插入图片描述

3.strncat()

Append characters of a string.

char *strncat( char *strDest, const char *strSource, size_t count );

例子:

int  main()
{
	char arr1[20] = "aaabbb ";
	char arr2[] = "ccc";

	strncat(arr1, arr2, 3);//操作的是字节
	printf("%s\\n", arr1);

	return 0;
}

在这里插入图片描述

内存操作函数

1.memcpy()

在缓冲区之间复制字符。
Copies characters between buffers.

void *memcpy( void *dest, const void *src, size_t count );

void *my_memcpy(void* arr1, const void* arr2, size_t count)
{
	assert(arr1&&arr2);
	char* ret = arr1;

	while (count--)
	{
		//*((char*)dest)++ = *((char*)src)++;
		*(char*)arr1 = *(char*)arr2;
		arr1 = (char*)arr1 + 1;
		arr2 = (char*)arr2 + 1;
	}

	return ret;
}

int main()
{
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[10] = { 0 };
	my_memcpy(arr2, arr1, 20);
	int i = 0;
	for (i = 0; i < (sizeof(arr2) / sizeof(arr2[0])); i++)
	{
		printf("%d ", arr2[i]);
	}

	return 0;
}

在这里插入图片描述
假如我们要arr1把下标0-4处的值拷到自身arr1+2处呢?

int main()
{
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };

	my_memcpy(arr1+2, arr1, 20);
	int i = 0;
	for (i = 0; i < (sizeof(arr1) / sizeof(arr1[0])); i++)
	{
		printf("%d ", arr1[i]);
	}

	return 0;
}

在这里插入图片描述
所以!!memcpy函数应该拷贝不重叠的内存!!
但是细心的朋友会发现,在vs编译器下,调用memcpy,可以拷贝重叠的内存,(我们调用的是my_memcpy)。其实这是vs对memcpy的优化。我们还是把他认为拷贝不重叠的内存比较好。因为在其他编译器下就可能行不通了。
那我们拷贝重叠的内存怎么办?所以出现了下面的memmove()。

2.memmove()

将一个缓冲区移动到另一个缓冲区。

Moves one buffer to another.

void *memmove( void *dest, const void *src, size_t count );

可以处理内存重叠的情况

例子:

int main()
{
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
	memmove(arr1, arr1+2, 20);
	int i=0;
	for (i = 0; i < (sizeof(arr1) / sizeof(arr1[0])C语言进阶笔记深入了解进阶指针

C语言进阶笔记深入了解进阶指针

C语言进阶笔记深入了解进阶指针

c语言深入浅出,玩爆常见字符串,内存操作库函数(爆肝最长时间之作)

超详细的C进阶教程!字符串及内存函数的使用及其模拟实现

对Promise的一些深入了解