字符串函数及内存函数C语言

字符函数及内存函数

  • 一.字符串函数函数
    • 1.strlen函数
    • 2.strcpy函数
    • 3.strcat函数
    • 4.strcmp函数
    • 5.strncpy函数
    • 6.strncat函数
    • 7.strncmp函数
    • 8.strstr函数
    • 9.strtok函数
    • 10.strerror函数
  • 二.内存函数
    • 1.memcpy函数
    • 2.memmove函数
    • 3.memcpy函数
    • 4.memset函数

一.字符串函数函数

1.strlen函数

size_t strlen ( const char * str );

作用: 计算字符串长度,返回的是字符串长度,无符号整数

  • strlen()函数以\0作为结束标志,返回的是\0之前的字符个数,不包含\0
  • 参数指向的字符串必须以\0结束
  • 参数的返回值是一个无符号整数,所以在做差比较时要切记,防止负数但数值很大的情况
  • strlen()函数模拟实现如下
//计数法
size_t my_strcopy(const char* str)
{
	
	assert(str != NULL);
	int count = 0;
	while (*str!='\0')
	{
		count++;
		str++;
	}
	return count;
}

2.strcpy函数

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

作用: 将源字符串拷贝到目标字符串中,返回的是目标字符串的地址

  • 源字符串必须以\0结尾
  • 会将源字符串中的\0拷贝到目标空间
  • 目标空间足够大,以确保能放下源字符串
  • 目标空间必须可变,不能是常量字符串,常量字符串不可变
  • strcpy()函数模拟如下
char* my_strcopy(char* dest, const char* src)
{
	assert(dest != NULL);
	assert(src != NULL);
	char* result = dest;
	while (*src!='\0')
	{
		*dest = *src;
		dest++;
		src++;
	}
	*dest = *src;
	return result;
}

3.strcat函数

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

作用: 将源字符串拼接到目标字符串的后面,返回的是目标字符串的地址

  • 源字符串必须以\0结束
  • 目标空间必须足够的大,能容纳的下源字符串
  • 目标空间必须可修改
  • 切记该函数不能自己追加自己
  • 模拟strcat()函数
char* my_strcat(char* dest, const char* src)
{
	assert(dest != NULL);
	assert(src != NULL);
	char* result = dest;
	while (*dest!='\0')
	{
		dest++;
	}
	while (*src != '\0')
	{
		*dest = *src;
		dest++;
		src++;
	}
	*dest = *src;
	return result;
}

4.strcmp函数

作用: 比较两个字符串的大小关系

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

  • 第一个数大于第二个数返回>0的数
  • 第一个数小于第二个数返回<0的数
  • 第一个数等于第二个数返回==0的数
  • 模拟strcmp函数
int my_strcmp(const char* s1,const char* s2)
{
	assert(s1 != NULL);
	assert(s2 != NULL);
	while (*s1==*s2)
	{
		if (*s1 == '\0')
		{
			return 0;
		}
		s1++;
		s2++;
	}
	if (*s1 - *s2 > 0)
	{
		return 1;
	}
	else {
		return -1;
	}

}

上面四种都是字符串长度不受限制的,下面介绍三种字符串长度受限制的

5.strncpy函数

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

  • 可见比strcpy只是多了一个num的参数
  • 此函数复制时,只会复制指定长度n个
  • 若n>要复制的字符串长度,那么后面会复制\0

6.strncat函数

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

  • 可见只是比strcat多了一个长度限制参数
  • 该函数会将指定长度num个字符拼接到目标函数后面,如果num>源字符串时,也只会拼接源字符串的长度个字符
  • 该函数拼接完后,会在末尾拼接一个\0

7.strncmp函数

int strncmp ( const char * str1, const char * str2, size_t num )

  • 该函数比strcmp函数多了一个参数num的长度限制
  • 该函数只会比较num个字符
  • 这num个字符相同就返回0,第一个字符大于第二个字符返回>0的数,第一个字符小于第二个字符返回<0的数

8.strstr函数

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

作用: 在一个字符串中查找指定子串存不存在,存在返回第一次出现的位置到结束的字符串

  • 模拟实现strstr函数
char* my_strstr(const char* s1, const char* s2)
{
	assert(s1 != NULL);
	assert(s2 != NULL);
	char* position = s1;
	char* move1 = s1;
	char* move2 = s2;

	while (*position!=NULL)
	{
		move1 = position;
		move2 = s2;
		while (*move1==*move2&&*move1!=NULL&&*move2!=NULL)
		{
			move1++;
			move2++;
		}
		if (*move2 == NULL)
		{
			return position;
		}
		position++;
	}
}

9.strtok函数

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

==作用:==将一个字符串按照特定的字符串进行分割

  • const char* sep这个参数是一个字符串,定义了分隔符的集合
  • 第一个参数是一个字符串,该字符串里面可以包含0个或多个分隔符字符
  • strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。注:
    strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容
    并且可修改。
  • 如果第一个参数不为NULL,那么该函数会找到该字符串中第一次出现该分隔符的位置,进行分割,并且记录下一次出现分隔符的位置
  • 如果第一个参数为NULL,那么该函数会从下一次被标记的位置开始,进行分割
  • 如果字符串中不存在更多的标记那么返回NULL

strtok函数的使用

int main()
{
	char s1[] = "LC@AI>Ming@666";
	char s2[] = { '@','>','\0' };
	char s3[30];
	strcpy(s3, s1);
	for (char* i = strtok(s3, s2);i != NULL;i = strtok(NULL,s2))
	{
		printf("%s\n", i);
	}
}

10.strerror函数

char * strerror ( int errnum )

==作用:==将程序中产生的错误码转为字符串,方便我们直到哪里有错

  • 库函数在执行的时候,发生了错误会将一个错误码存放在errno这个变量中errno是C语言提供的一个全局的变量
  • 参数为错误码,只要给一个错误码,就会返回当前错误码对应的错误信息
int main()
{
	FILE* pf = fopen("data.txt", "r");
	if (pf == NULL)
	{
		printf("%s\n", strerror(errno));
		//perror(字符串);自带打印
		return 1;
	}
	fclose(pf);
	return 0;
}
  • 这里我们在传错误码时,直接传errno,这个变量当程序发生错误时,会将错误存放在这个变量中
  • printf(“%s\n”, strerror(errno))这句代码可以用perror()这个函数替换,perror()里面可以传一个参数,以确保我们知道哪里出了问题,它自带打印
//这两句代码等价
printf("fopen:%s\n", strerror(errno));
perror("fopen");

二.内存函数

下面是几个常用的内存函数

1.memcpy函数

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

作用: 拷贝内存中的数据

  • 函数从source所指向的地址开始,复制num个字节数据到destination所指向的内存地址
  • 这个函数在遇到\0时并不会停下来,因为它可以复制所有类型数据,与\0无关,与内存有关
  • 如果source和destination有任何的重叠,复制的结果都是未定义的,即不能复制重叠部分的内容
  • memcpy函数模拟实现
void* my_memcpy(void* dest, const void* src,size_t num)
{
	assert(dest != NULL);
	assert(src != NULL);
	void* result = dest;
	while (num--)
	{
		*(char*)dest = *(char*)src;
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}
	return result;
}

2.memmove函数

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

作用: 拷贝内存中的数据

  • 和memcpy作用类似,但它可以拷贝重叠部分的内容,也可以拷贝不重叠部分的内容
  • 如果源空间和目标空间出现重叠,就得使用memmove函数处理,如果没有重叠,两者都可以
  • 模拟实现memmove函数
void* my_memmove(void* dest,const void* src,size_t num)
{
	assert(dest != NULL);
	assert(src != NULL);

	void* result = dest;

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

3.memcpy函数

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

作用: 两个数据进行比较,以内存字节为基准

  • 按照一个一个字节比较,如果这些字节都相等就返回0.如果第一个字节大返回>0的数,如果第一个字节小返回<0的数

4.memset函数

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

作用: 将ptr所指向的内存空间,按字节填充为value

  • 这里要注意是将内存空间里的字节里的值填充为value,并不是将数据直接填充为value

比如我执行下面代码

int main()
{
	int arr[] = { 1,2,3,4,5 };
	memset(arr, 1, 20);
	for (int i = 0;i < 5;i++)
	{
		printf("%d ", arr[i]);
	}
}

初学者看到,有可能会以为我是要将arr数组中的五个元素全部设置为1,但是实际上并不是,这样设置会将内存中每个字节都设置为1,结果是一个很大的数
字符串函数及内存函数C语言_第1张图片
而此时内存图如下:
在这里插入图片描述
可见该函数是以字节进行内存设置的,如果要将该数组全部填充为某一值(0除外),这个方法是不行的

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