关于字符串函数的介绍
求字符串长度
strlen函数
用于计算字符串的长度的函数,需要使用的库函数是string.h
函数声明
size_t strlen(const char *str)
函数模拟实现
#include<stdio.h>
#include<assert.h>
size_t my_strlen(const char* arr)
{
	assert(arr);
	int len = 0;
	while (*arr)
	{
		len++;
		arr++;
	}
	return len;
}
int main()
{
	char* arr = "asdf";
	printf("%d",my_strlen(arr));
	return 0;
}
#include<stdio.h>
#include<string.h>
int main()
{
	char* arr = "asdf";
	printf("%d", strlen(arr));
	return 0;
}

需要注意的是:计算的位置并不是随意的,他会计算到’\0’停止并且’\0’不计入字符总长度
 
 请看这个代码,为什么会出现这中结果呢?你不是说计算到‘\0’结束吗,现在没有’\0’,可是为什么会出现相同的结果呢???
 
 我们能看到内存中除了已经存好的字符之外全是’\0’,这就是为什么会是4,但是为什么会全是’\0’,因为这是c语言的规则,如果数组进行了初始化但是是未完全的初始化,那么其余的空间都将会被初始化为0
长度不受限制的字符串
strcpy()
使用的时候需要引用string.h头文件
 字符串拷贝,以’\0’字符为结束标志,拷贝长度不受限制,使用时需要引用库函数—string.h
函数定义
char *strcpy(char *dest, const char *src)
函数模拟实现
char* my_strcpy(char* des, const char* src)
{
	assert(des && src);
	char* res = des;
	while (*des++ = *src++);
	return res;
}
在实现的时候一定要注意将源字符串中的’\0’拷贝进去,不然会出错
 
strcat
使用的时候需要引用string.h头文件
 字符串连接函数
函数声明
char *strcat(char *dest, const char *src)
将后一个字符串放到前一个字符串的末尾,所以需要保证前一个字符串有’\0’结尾,并且写入的时候需要预留足够的空间
函数模拟实现
char* my_strcat(char* des, const char* arr)
{
	assert(des && arr);
	char* res = des;
	while (*des)des++;
	while (*des++ = *arr++);
	return res;
}

 特别需要强调的就是预留足够的空间
 如果将代码写成指针的形式,那就错了!!!
 因为指针没有足够的空间
#include<stdio.h>
#include<string.h>
#include<assert.h>
char* my_strcat(char* des, const char* arr)
{
	assert(des && arr);
	char* res = des;
	while (*des)des++;
	while (*des++ = *arr++);
	return res;
}
int main()
{
	char* arr = "hello ";
	char* arr2 = "world!";
	my_strcat(arr, arr2);
	puts(arr);
	return 0;
}
strcmp
使用的时候需要引用string.h的头文件
 字符串比较函数,比较到有结果或者结尾停止
函数声明
int strcmp ( const char * str1, const char * str2 );
此函数是使用字典序来进行比较大小的,如果a和b比较大小就是那a的ASCII码-b的ASCII码,然后进行返回(需要特殊说明的是,一般情况下返回的是不能于0的数)
函数模拟实现
#include<stdio.h>
#include<string.h>
#include<assert.h>
int my_strcmp(const char* arr1, const char* arr2)
{
	assert(arr1 && arr2);
	while (*arr1 || *arr2)
	{
		if (*arr1 != *arr2) return *arr1 - *arr2;
		arr1++;
		arr2++;
	}
	return 0;
}

字符长度受限
strncpy,strncat,strncmp
使用的时候需要引用string.h头文件
 这些函数与上面的使用方法相似,这里我们之介绍一个—strncpy
函数声明
char * strncpy ( char * destination, const char * source, size_t num );
当num小于source的长度–>拷贝都最后
 
当num大于source的长度–>在结尾的时候加上’\0’
 
字符查找
strstr
函数声明
char *strstr(const char *haystack, const char *needle)
使用的时候需要引用string.h头文件
 用于查找字符串中needle字符串第一次出现的位置,如果有—>返回位置

 如果没有—>返回NULL指针
 
strtok
函数声明
char *strtok(char *str, const char *delim)
分割字符串函数,delim是分隔符的数组
int main()
{
	char str[] = "asdf-asdfw.asdf-svs";
	char delim[5]="-.";
	
	//使用源字符串会改变源字符串,所以不能使用源字符串
	char arr[100];
	strcpy(arr,str);
	//char* ch = strtok(str, delim);
	for (char* ch = strtok(arr, delim);ch!=NULL;ch=strtok(NULL,delim))
	{
		puts(ch);
	}
	return 0;
}
第一个参数为NULL的时候,计算机中会有一个记录上一次到达的位置,会从这个位置开始向后搜索
 
strerror
使用的时候需要引用errno.h头文件
 当调用库函数的时候发生错误时,错误信息会记录到errno的全局变量中
#include<stdio.h>
#include<string.h>
#include<errno.h>
int main()
{
	//当调用库函数发生错误,noerror会记录发生错误的原因
	FILE* pf = fopen("en.txt", "r");
	if (pf == NULL)
	{
		printf("%s\n", strerror(errno));
	}
	return 0;
}

内存操作函数
memcpy
使用需要引用string.h头文件
 在字节的层面进行复制
函数声明
void *memcpy(void *str1, const void *str2, size_t n)
函数模拟实现
void* my_memcpy(void* des, const void* src, int n)
{
	assert(des && src);
	void* res = des;
	for (int i = 0; i < n; i++)
	{
		*((char*)des + i) = *((char*)src + i);
	}
	return res;
}

 当我们想将1,2,3,4,5复制成1,2,1,2,3
 但是结果却和我们想的不一样
 
 
 为了解决上面的覆盖的问题,就有了下面的函数
memmove
C 库函数 void memmove(void str1, const void str2, size_t n) 从 str2 复制 n 个字符到 str1,但是在重叠内存块这方面,memmove() 是比 memcpy() 更安全的方法。如果目标区域和源区域有重叠***的话,memmove() 能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中,复制后源区域的内容会被更改。如果目标区域与源区域没有重叠,则和 memcpy() 函数功能相同。
函数声明
void *memmove(void *str1, const void *str2, size_t n)
函数模拟实现
void* my_memmove(void* des, const void* src, int n)
{
	assert(des && src);
	void* res = des;
	if (des < src)
	{
		for (int i = 0; i < n; i++)
		{
			*((char*)des + i) = *((char*)src + i);
		}
	}
	else
	{
		while (n--)
		{
			*((char*)des + n) = *((char*)src + n);
		}
	}
	return res;
}
这样子的话是不是就是对了了呢
 
多多练习



















