C语言字符串函数

目录

一.strlen---求字符串长度

(1)strlen函数介绍

(2)自己动手实现strlen函数的三种方法

1.计数器的方法

2.递归

3.指针-指针

(3)注意strlen的返回值类型

二.strcpy---长度不受限制的字符串函数

(1)strcp函数介绍

(2)自己动手实现strcpy函数

(3)注意事项

三.strcat---长度不受限制的字符串函数

(1)strcat介绍

(2)自己动手实现strstr函数

(3)注意事项

四.strcmp---长度受限制的字符串函数

(1)strcmp函数介绍

(2)自己动手实现strcmp函数

(3)注意事项

五.strncpy---长度受限制的字符串函数

(1)strncpy函数介绍

六.strncat---长度受限制的字符串函数

(1)strncat介绍

七.strncmp---长度受限制的字符串函数

(1)strncmp介绍

八.strstr-查找字符串

(1)strstr函数介绍

(2)自己动手实现strcmp函数


一.strlen---求字符串长度

(1)strlen函数介绍

举例

    int len = strlen("abcdef");

不妨先模拟一下这个字符串的内存布局:

C语言字符串函数_第1张图片

"abcdef"字符串是以'\0'作结尾的("abcdef"是有7个字符串)

strlen函数会计算'\0'之前的字符串,,然后计算个数,以size_t(unsigned int)的形式返回出去

下面打印出它的返回值

 我们看下错误写法

char arr[] = { 'a','b', 'c', 'd', 'e', 'f' };       

int len=strlen(arr); 

 我们先看下结果

   

 为什么是19,而不是6呢?

事实上,arr数组这种创建方式不以'\0'结尾,那为什么在19停止了呢?这个随机值,可能从头往后数数了19个,才发现了'\0'

不妨画图假设看看!!('x'为任意字符)

C语言字符串函数_第2张图片

 (2)自己动手实现strlen函数的三种方法

1.计数器的方法

int my_strlen(char* str) {
    int count = 0;
    while (*str!='\0')
    {
        count++;
        str++;
    }
    return count;
}

2.递归

int my_strlen(char *str) {
    if (*str!='\0')
    {
        return 1 + my_strlen(str + 1);
    }
    else {
        return 0;
    }
}

 3.指针-指针

int my_strlen(char* str) {
    int count = 0;
    while (*str!='\0')
    {
        count++;
        str++;
    }
    return count;
}

实现代码

int main() {
    char arr[] = "bit";
    int len = my_strlen(arr);    //arr是数组,数组传参,传过去的不是整个数组,而是第一个元素的地址
    printf("len=%d\n", len);
    return 0;
}

(3)注意strlen的返回值类型

int main() {
    //  3                   -       6  =-3(3)
    if (strlen("abc")-strlen("abcdef")>0)
    {
        printf("正\n");
    }
    else
    {
        printf("负\n");
    }
    return 0;
}

上述代码会返回,由于strlen返回类型是size_t=unsigned int,所以以上3-6=-3中的-3会转换成正3

二.strcpy---长度不受限制的字符串函数

(1)strcp函数介绍

源字符串必须以'\0'结束

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

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

目标空间必须可变

举例

char arr1[]="abcdefghi";

char arr2[]="bit";

strcpy(arr1,arr2);//第一个参数是目的地,第二个参数是源头

printf("%s\n", arr1);

 看下内存布局

 C语言字符串函数_第3张图片

 可以看出,拷贝过去的时候'\0'也过去了!!

 打印出arr1 

(2)自己动手实现strcpy函数

char* my_strcpy(char* dest, const char* src) {
	assert(dest != NULL);
	assert(src != NULL);
	char* ret = 	dest;
	//拷贝src指向的字符串到dest指向的空间,包含'\0'
	while (*dest++ = *src++)
	{

	}
	//返回目的空间的起始地址
	return ret;
}

 代码实现

int main() {
	char arr1[] = "abcdefghi";
	char arr2[] = "bit";
	my_strcpy(arr1, arr2);	//第一个参数目的地,第二个源头
	printf("%s\n", arr1);
	return 0;
}

(3)注意事项

下面arr2后面不是以'\0'结尾,而strcpy需要'\0',这样可能会存在越界访问,这样是错误

int main() {
    char arr1[] = "abcdefghi";
    //错误的写法
    char arr2[] = { 'b','i','t' };
    strcpy(arr1,arr2);    //第一个参数目的地,第二个源头
    printf("%s\n", arr1);
    return 0;
}

下面arr1指针指向的是常量字符串,常量字符串不能被改,运行会导致程序崩溃

int main() {
    char *arr1 = "abcdefghi";
    char arr2[] = "bit";
    my_strcpy(arr1, arr2);    //第一个参数目的地,第二个源头
    printf("%s\n", arr1);
    return 0;
}

 下面arr1字符串比arr2字符串小,使用函数,函数会发现目的地arr1大小不足,导致程序崩溃

int main() {
    char arr1[] = "bit";
    char arr2[] = "abcdefghi";
    strcpy(arr1,arr2);    //第一个参数目的地,第二个源头
    printf("%s\n", arr1);
    return 0;
}

长度不受限制,只受'\0'的限制, arr[5]的空间不够,但是也让"hello world"字符串拷贝过去了!!会导致代码的不安全

 int main() {
    char arr1[5] = "abc";
    char arr2[] = "hello world";
    strcpy(arr1, arr2);        //没拷贝斜杠0 
    printf("%s", arr1);
    return 0;
}

三.strcat---长度不受限制的字符串函数

(1)strcat介绍

字符串拼接

原字符串必须有'\0'

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

目标空间可修改

举例:

    char arr1[30] = "hello";        //arr1数组的创建需要足够大
    char arr2[] = "world";           //arr2后面需要有'\0'

    strcat(arr1, arr2);//第一个参数目的地,第二个源头

    printf("%s\n", arr1);

打印出结果 

用以下代码看看运行后的内存布局:

    char arr1[30] = "hello\0xxxxxxxxx";
    char arr2[] = "world";

    strcat(arr1, arr2);//第一个参数目的地,第二个源头

    printf("%s\n", arr1);


                 strcat使用之前                             arr1                             strcat使用后

C语言字符串函数_第4张图片            C语言字符串函数_第5张图片

 从上面可以看出,原头的'\0'也跟着拼接了上去.而且目的地后面的'\0'被覆盖掉了!!

(2)自己动手实现strstr函数

char* my_strcat(char*dest, const char*src) {
	assert(dest&&src);
	char* ret = dest;
	//1.找到目的字符串的'\0'
	while (*dest != '\0')
	{
		dest++;
	}
	//2.追加
	while (*dest++ = *src++)
	{

	}
	return dest;
}

代码实现

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

(3)注意事项

 目标空间不够大,造成越界访问

    char arr1[] = "hello";  
    char arr1[30] = "hello\0xxxxxxxxx";

    strcat(arr1, arr2);

自己给自己追加的错误

    char arr1[30] = "hello";
    strcat(arr1, arr1);

四.strcmp---长度受限制的字符串函数

(1)strcmp函数介绍

字符串比较函数

标准规定:

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

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

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

在Vs2017的编译环境下,

大于是返回1,等于是0,小于是-1

字符串比较的是字符的ASCII码

举例:

    char* p1 = "abcdef";        
    char* p2 = "abcdeg";        
    int ret = strcmp(p1, p2);
    printf("%d\n", ret);

由于p1和p2前面"abcde"相等,所以比较"f"和"g",由于"f"的ASCII值小于"g"的值,所以返回的是-1

    char* p1 = "abcdef";
    char* p2 = "abcd";
    int ret = strcmp(p1, p2);
    printf("%d\n", ret);

由于p1和p2前面"abcd"相等,p2后面'\0'跟p1的'e'进行比较,e大于'\0',所以返回值是1

 (2)自己动手实现strcmp函数

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

代码实现

int main() {
	char* p1 = "abc";
	char* p2 = "abcd";
	int ret = my_strcmp(p1, p2);
	printf("ret=%d\n", ret);
	return 0;
}

(3)注意事项

linux系统返回的是ASCII的差值

动手实现一个函数,模拟linux系统下,strcmp的返回值

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

int main() {
	char* p1 = "abc";
	char* p2 = "abcd";
	int ret = my_strcmp(p1, p2);
	printf("ret=%d\n", ret);
	return 0;
}

两个常量字符串不能用==来做比较,因为这比的是两个字符串的首地址

    //错误比较
    //if ("abcdef"=="abcdeg")

五.strncpy---长度受限制的字符串函数

(1)strncpy函数介绍

使用跟strcpy相似,增加第三个参数,第三个就是指定拷贝的字符个数

举例:

    char arr1[5] = "abc";
    char arr2[] = "hello world";
    strcnpy(arr1, arr2,4);        //没拷贝斜杠0 
    printf("%s", arr1);

内存布局:


                        使用前                                                                         使用后

C语言字符串函数_第6张图片         C语言字符串函数_第7张图片

可以看到,'\0'没有被增加上去 

 测试下另一段代码

    char arr1[10] = "abcdef";
    char arr2[] = "abc";
    strncpy(arr1, arr2,6);       
    printf("%s", arr1);

 内存布局:


                        使用前                                                                使用后

C语言字符串函数_第8张图片                      C语言字符串函数_第9张图片

 可以看到,"abc"拷贝过去后,剩余的部分用了'\0'进行的代替.

六.strncat---长度受限制的字符串函数

(1)strncat介绍

也是跟strcat类似,增加第三个参数,,第三个就是指定追加的个数

    //char arr1[30] = "hello\0xxxxxxxxxxxxx";

    //char arr1[30] = "hello";
    char arr2[] = "world";
    strncat(arr1, arr2, 3);
    printf("%s",arr1);

内存布局:


                        使用前                                                                        使用后                

C语言字符串函数_第10张图片C语言字符串函数_第11张图片

 追加成功!!

测试下另一段代码 

    char arr1[30] = "hello\0xxxxxxx";
    char arr2[] = "world";
    strncat(arr1, arr2, 3);
    printf("%s",arr1);

内存布局:


                              使用前                                                              使用后

C语言字符串函数_第12张图片    C语言字符串函数_第13张图片

 可以看到,追加过去后,后面会增加'\0'。

七.strncmp---长度受限制的字符串函数

(1)strncmp介绍

举例:

也是跟strcmp类似,增加第三个参数,,第三个就是指定比较字符的个数

    const char* p1 = "abcdef";
    const char* p2 = "abcdqwe";
    int ret=strncmp(p1, p2, 5);
    printf("%d\n", ret);

打印出来 

八.strstr-查找字符串

(1)strstr函数介绍

第一个参数是被查找的字符串,第二个参数是要查找的子串

举例:

    char* p1 = "defsda";
    char* p2 = "def";
    char* ret=strstr(p1, p2);
    if (ret == NULL)
        printf("子串不存在");
    else
        printf("%s\n", ret);

 输出:

可以看到,输出的是def字符串+后面的字符串

测试下另一段代码:

    char* p1 = "defsdefss";//这个字符有两个子串def
    char* p2 = "def";
    char* ret=strstr(p1, p2);
    if (ret == NULL)
        printf("子串不存在");
    else
        printf("%s\n", ret);

 输出

 可以看出,strstr这个函数查找的是第一个子串!!

 (2)自己动手实现strcmp函数

//strstr-查找字符串
char* my_strstr(const char* p1,const char* p2) {
	assert(p1!=NULL);
	assert(p2 != NULL);
	char* s1 = NULL;
	char* s2 = NULL;
	char* cur = (char*)p1;
	if (*p2=='\0')
	{
		return (char*)p1;
	}
	while (*cur)
	{
		s1 = cur;
		s2 = (char*)p2;
		while ((*s1!='\0')&&(*s2!='\0')&&(*s1==*s2))
		{
			s1++;
			s2++;	
		}
		if (*s2=='\0')
		{
			return cur;
		}
		if (*s1=='\0')
		{
			return NULL;
		}
		cur++;
	}
	return NULL;//找不到子串
}

代码实现

int main() {
	char* p1 = "defsdefss";
	char* p2 = "def";
	char* ret = my_strstr(p1, p2);
	if (ret == NULL)
		printf("子串不存在");
	else
		printf("%s\n", ret);
	return 0;
}

你可能感兴趣的:(C语言,c语言,c++,数据结构,开发语言,算法)