字符串函数(C语言 详细)

一、strlen

1.定义与运用

求字符串长度,统计的是’/0‘之前字符出现的个数一个汉字为两个字符
在这里插入图片描述

头文件为<string.h>

#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[] = "abcdef";//a b c d e f \0
	printf("%d\n", strlen(arr1));//6
	char arr2[] = "abc\0def";
	printf("%d\n", strlen(arr2));
	char arr3[] = { 'a','b','c' };
	printf("%d\n", strlen(arr3));//15  不确定值  因为没有'\0',不知道在什么时候停止 
    strlen("abc") - strlen("abcdef") > 0 ? printf(">") : printf("<");
	//size_t的类型为unsigned int(无符号整型),-3作为一个无符号整数依然>0
}

2.模拟实现

assert可以大致这样理解

if(条件为真)
执行程序
else
终止程序&&报错

下面直接上代码

//指针减指针
size_t my_strlen(const char* str)//const不是必须的 
//但因为传的是指针可能会被误操作修改,加const可以及时报错提醒
{
    assert(str);
	const char* start = str;//这里限制的是*start
	//如果为char*const end限制的才是end   所以后面end可以++
	const char* end = str;
	while (*end != '\0')
	{
		end++;
	}
	return end - start;
}
int main()
{
    char arr[] = "abcdef";
	int len = my_strlen(arr);
	printf("%d", len);
}

strlen是在参与的时候用unsigned int运算,并没有改变变量本身的类型。

二、strcpy

1.定义与运用

在这里插入图片描述

destination指的是目的地,source指的是需要拷贝的源头,两个都是指针
先上代码块

#include<stdio.h>
#include<string.h>
int main()
{
	char arr[10] = {0};
	const char* p = "abc\0def";
	strcpy(arr, p);
	printf("%s\n", arr);//输出abc
}

注意:
1.源字符串必须以’\0’结束。
2.会将源字符串中的’\0’拷贝到目标空间。
3.目标空间必须足够大,以确保能存放字符串。
4.目标空间必须可变。

错误示范(目标空间必须足够大,以确保能存放字符串)。

#include<stdio.h>
#include<string.h>
int main()
 {
	char arr[3] = { 0 };
	char arr3[] = "abcdef";
	strcpy(arr, arr3);
	printf("%s\n", arr);
}

在这里插入图片描述

错误示范(目标空间必须可变)。

#include<stdio.h>
#include<string.h>
int main()
 {
	char* p = "hello horld";//常量字符串
	char arr2[] = "abcdef";
	strcpy(p, arr2);
	printf("%s\n", p);
	return 0;
}

在这里插入图片描述

2.模拟实现

#include<stdio.h>
#include<string.h>
#include<assert.h>//头文件必须声明在最前面
char* my_strcpy(char* dest, const char* src)//此处加const保证arr2不被改掉
{
	assert(dest);
	assert(src);//保证两个指针的有效性(不为空)
	char* ret = dest;
	while (*dest++ = *src++)//在循环里面写的好处
	//可以保证最后将'\0'拷贝进去而循环刚好停止
	{
		;
	}
	return ret;
}
int main()
 {
	char arr1[20] = "abc";
	char arr2[] = "hello world";
	my_strcpy(arr1, arr2);
	printf("%s\n", arr1);
	//printf("%s\n", my_strcpy(arr1, arr2));//也可以这样写   两个结果一样
}

三、strcat

1.定义与运用

头文件#include<string.h>
在这里插入图片描述

stract为字符串追加函数,返回类型和参数类型与strcpy一样,把源头的数据追加到目标后面去。
先上代码

#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[20] = "hello \0xxxxxxxxx";
	char arr2[] = "world";
	strcat(arr1, arr2);
	printf("%s\n", arr1);
	return 0;
}

在这里插入图片描述
由此可见strcat追加时会覆盖掉原来的’\0’,并且把source源头的’\0’也追加过去。
注意:
1.源字符串必须以’\0’结束(追加的终点),目标字符串必须以’\0’结束(destination必须有’\0’以找到地方且为第一个’\0’)
2.目标空间必须足够大,能够容纳下source的内容。
3.目标空间必须可修改。
其实聪明的大家早已发现以上三点都是与strcpy是大同小异的
4.字符串不能自己给自己追加!!!
这个我们放到模拟实现里面来讲。

2.模拟实现

主要思路:
1.找到目标空间中的’\0’
2.拷贝源头数据到’\0’以后的空间

char* my_strcat(char* dest, const char* src)
{
	//1.找到目标空间中的'\0'
	char* cur = dest;
	while (*cur != '\0')
	{
		cur++;
	}
	//2.拷贝源头数据到'\0'之后的空间,方法类似strcpy
	while (*cur++ = *src++)
	{
		;
	}
	//因为dest用的是cur代替其原值没有改变,而src加了const
	return dest;
}
int main()
{
	char arr1[20] = "hello \0xxxxxxxxx";
	char arr2[] = "world";
	my_strcat(arr1, arr2);
	printf("%s\n", arr1);
	return 0;
}
//字符串不能自己给自己追加!!!
//此时因为src拷贝过去时直接覆盖了被拷贝的源字符串的'\0',使得cur永远找不到'\0',陷入死循环。

四、strcmp

1.定义与运用

头文件#include<string.h>
在这里插入图片描述
strcmp比较的是对应为之上字符的大小,而非长度。
1.设arr1=abcdef,arr2=abq。因为a=a,b=b,c<q。所以arr1<arr2。
2.设arr3=abc,arr4=abcd。因为’\0’小于d。所以arr3<arr4.
3.设arr5=abc,arr6=abc。因为’\0’小于d。所以arr5=arr6.

#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abq";
	printf("%d", strcmp(arr1, arr2));//-1
	char arr3[] = "abc";
	char arr4[] = "abc";
	printf("%d", strcmp(arr3, arr4));//0
	char arr5[] = "abcd";
	char arr6[] = "abc";
	printf("%d\n", strcmp(arr5, arr6));//1
	return 0;
}

2.模拟实现

int my_strcmp(const char* s1, const char* s2)
{
	assert(s1 && s2);
	while (*s1 == *s2)
	{
		if (*s1 == '\0')
		{
			return 0;
		}
		s1++;
		s2++;
	}
	//或者下面这几行代码可以直接替换为 return*s1-*s2;
	if (*s1 > *s2)
		return 1;
	else
		return -1;
		
}
int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abq";
	printf("%d\n", my_strcmp(arr1, arr2));
	char arr3[] = "abc";
	char arr4[] = "abc";
	printf("%d\n", my_strcmp(arr3, arr4));
	char arr5[] = "abcd";
	char arr6[] = "abc";
	printf("%d\n", my_strcmp(arr5, arr6));
	return 0;
}

以上四个函数都是长度不受限制的字符串函数,主要基于’\0’操作的。下面介绍三个相似的函数,但是是基于长度实现的。(由于相似度高,此处就不再给出模拟实现)

五、strncpy

1.定义与运用

#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[20] = "abcdef";
	char arr2[] = "xxxx";
	strncpy(arr1, arr2, 2);
	printf("%s\n", arr1);//xxcdef
	return 0;
}

如果此时将strncpy的最后一个参数改为8,此时已经超过arr2原本的长度。这是会将arr2中的四个字符拷贝过去后剩余拷贝成’\0’。

六、strncat

1.定义与运用

在这里插入图片描述
同与strcat不同的是,多的一个size_t num指向追加的字节数
这里我们给一个例子

#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[20] = "abcdef\0qqqqqq";
	char arr2[] = "xyz";
	strncat(arr1, arr2, 2);
	printf("%s\n", arr1);//abcdefxy
	return 0;
}

在这里插入图片描述

值得注意的是,此时我们追加的是xy这个字符串其实就是”xy\0“,并且覆盖了源字符串的的’\0’。而且strncat此时可以实现自己跟自己追加

在这里插入图片描述

七、strncmp

定义与运用

在这里插入图片描述
在这里插入图片描述

同与strcat不同的是,多的一个size_t num指向比较的前num个字节
运用示例:

#include<stdio.h>
#include<string.h>
int main()
{
	int ret = strncmp("abcdef", "abc", 4);
	printf("%d", ret);//1
	return 0;
}

八、strstr

定义与运用

在这里插入图片描述

在一个字符串中查找另一个字符串是否存在
存在:返回子串第一次出现的位置
不存在:返回NULL
下面做两个简单示例:

#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "bcq";
	char* p = strstr(arr1, arr2);//在arr1里面找arr2
	if (p == NULL)
	{
		printf("不存在\n");
	}
	else
	{
		printf("%s\n", p);
	}
	return 0;
}//不存在
int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "bcd";
	char* p = strstr(arr1, arr2);//在arr1里面找arr2
	if (p == NULL)
	{
		printf("不存在\n");
	}
	else
	{
		printf("%s\n", p);
	}
	return 0;
}//bcdef

模拟实现

	char* my_strstr(const char* str1, const char* str2)//只是查找字符串并不修改加const
{
	const char* s1 = str1;
	const char* s2 = str2;
	const char* p1 = str1;
	const char* p2 = str2;//需要预留一个指针记录开始的位置,在比较过程中失败时能找到原起始比较的位置。
	if (str1 == NULL || str2 == NULL)
	{
		return NULL;
	}
	if (str2 == '\0')
	{
		return str1;
	}
	while (*p1!='\0')
	{
		while (str2 == str1)
		{
			str1++;
			str2++;
		}
		if (str2 == '\0')
		{
			return p1;
		}
		else
		{
			p1++;
			str1 = p1;
			str2 = p2;
		}
	}
	if (str1 == '\0' )
	{
		return NULL;
	}
}
int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "bcd";
	char* p = strstr(arr1, arr2);//在arr1里面找arr2
	if (p == NULL)
	{
		printf("不存在\n");
	}
	else
	{
		printf("%s\n", p);
	}
	return 0;
}

九、strtok

定义与运用

在这里插入图片描述
1.delimiters参数是个字符串,定义了用作分隔符的字符集合
2.第一个参数指定一个字符串,它包含了0个过着多个由delimiters字符串中一个或者多个分隔符分割的标记。
3.strtok函数找到str中的下一个标记,并将其用’\0’结尾,返回一个指向这个标记的指针。(注意:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)
4.strtok函数的第一个参数不为NULL,函数将找到str中的第一个标记,strtok函数将保存它在字符串中的位置。
5.strtok函数的第一个参数为NULL,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
6.如果字符串中不存在更多的标记,则返回NULL指针。
7.如果delimiters字符串有多个字符时,无需注意其顺序。

#include<stdio.h>
#include<string.h>
int main()
{
	char arr[] = "qinghua912@boke.com";
	char buf[200] = { 0 };
	strcpy(buf, arr);
	const char* p = "@.";
	char* str = strtok(buf, p);
	printf("%s\n", str);//qinghua912
	str = strtok(NULL, p);
	printf("%s\n", str);//boke
	str = strtok(NULL, p);
	printf("%s\n", str);//com

}

上面写的方式主要是为了便于理解,下面给大家提供一个比较常见的用法。

#include<stdio.h>
#include<string.h>
int main()
{
	char arr[] = "qinghua912@boke.com";
	char buf[200] = { 0 };
	strcpy(buf, arr);
	const char* p = "@.";
	char* str = NULL;
	for (str = strtok(buf, p); str != NULL; str = strtok(NULL, p))
	{
		printf("%s\n",str);
	}
}

此种方法不用刻意观察其字符串分多少次了。

十、strerror

定义与运用

在这里插入图片描述

把错误码转换成错误信息
比如上网时有时无法打开网页会弹出”404“,此时的”404“就是错误码。
该函数较为简单,此处直接上运行结果。

在这里插入图片描述
或者可以用错误码的表示
#include<errno.h>

#include<stdio.h>
#include<string.h>
#include<errno.h>
//错误码记录到错误变量中
int main(){
FILE*pf=(fopen("test.txt","r");
if(pf==NULL)
{
    printf("%s\n",strerror(errno));
    return 1;
}
//读文件(但是此时没有这个文件,会报错误码)
fclose(pf);
pf=NULL;
return 0;
}

总结

本篇主要介绍了十种常用字符串函数的用法以及部分重要的字符串函数模拟实现,如果大家发现问题,可以留言博主会及时改正。
最后感谢大家的观看,如果觉得有参考价值的话希望可以奖励博主一个三连。

  • 12
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 13
    评论
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值