字符串相关知识

1.字符串长度:strlen

求字符串长度时,遇到“\0”就停下,前面所经过的字符数,就是字符串的长度,不包括“\0”

注意:该函数的返回值为无符号整数。

例子:

int main()
{
	const char *str1 = "abcdef";
	const char *str2 = "nnn";
	if (strlen(str2) - strlen(str1) > 0)
	{
		printf("str2 > str1");
	}
	else
	{
		printf("str2 < str1");
	}
	return 0;
}

上述代码输出为什么呢?
在这里插入图片描述
因为返回值无符号数,无符号数-无符号数永远是大于等于0的,所以输出了if分支的语句。

 
2.长度无约束字符串拷贝:strcpy

source字符串必须以“\0”结尾
source字符串中的“\0”也会拷贝给目标字符串
目标字符串必须可变,空间足够大(可容纳source字符串进行拷贝)

 
3.长度无约束字符串拼接:strcat

source字符串必须以“\0”结尾
source字符串中的“\0”也会拷贝给目标字符串
目标字符串必须可变,空间足够大(可容纳source字符串进行追加拷贝)

 
4.长度无约束字符串比较:strcmp

以字符的ascii码进行比较,从左往右,只要有一个不相等(碰到了就停下),就意味着有大小
第一个大于第二个,返回大于0的数字
第一个等于第二个,返回0
第一个小于第二个,返回小于0的数字

 
5.长度有约束字符串拷贝:strncpy

定义: char *strncpy(char *dst, const char *src, size_t num);
将num个字符拷贝到dst当中
若src字符串小于num,拷贝完src字符串之后,在dst后面追加0,直到num个。
\0也要拷贝到dst当中

 
6.长度有约束字符串拼接:strncat

定义:char *strnat(char *dst, const char *src, size_t num);
将num个字符追加拷贝到dst当中
若src字符串小于num,追加完src字符串之后,不追加0,拼接结束。

 
7.长度有约束字符串比较:strncmp

定义:int strncmp(const char *str1, const char *str2, size_t num);
这里的比较和无约束字符串一样,只不过对比较的字符长度进行了限制。

 
8.strstr:判定一个字符串是否为另一个字符串的子串,若为子串,返回该子串出现的第一个位置到母串的结尾,否则返回为空。

定义:char *strstr( const char *str1, const char * str2);

一个比较有意思的练习:求该字符串是否是另一个字符串旋转之后的结果。
见这一篇文章的第三个方法:字符串旋转,只需要将后面的判定方法改为strstr,若输出不为null,则str2一定是str1的旋转的结果。

 
9.strtok:字符串切割,根据特定的分隔符(集合),进行字符串切割

char *strtok( char *str, const char *sep)
子串截取:
1.函数内部使用static局部变量,来保存历史字符串的剩余子串
2.采用对分隔符进行设置\0 的策略进行子串划分
3.strtok进行子串截取的时候,采用的策略是截取有效字符串
4.分割的时候,strtok会自动进行分隔符隔离

模拟strtok函数实现:

int main()
{
	char str1[40] = "abc,  | dea|bcde, TRYSLOKI";
	printf("%s\n",my_strtok(str1, ", |"));
	printf("%s\n", my_strtok(NULL, ", |"));
	printf("%s\n", my_strtok(NULL, ", |"));
	printf("%s\n", my_strtok(NULL, ", |"));
	printf("%s\n", my_strtok(NULL, ", |"));
	printf("%s\n", my_strtok(NULL, ", |"));
	printf("%s\n", my_strtok(NULL, ", |"));
	return 0;
}

char *my_strtok(char *str1, const char *sep)
{
	static char *temp = NULL;//保存上次不为分隔符的字符
	if (str1 == NULL && (str1 = temp) == NULL)//判定传输str1是否为NULL,若为NULL,将上一个保存的temp地址赋给str1
	{
		return NULL;
	}
	char *s = NULL;//返回值
	const char *t = NULL;
	int flag = 1;//记录第一次不为空的地址
	int index = 0;//若有切割符,发生变化
	for (; *str1 != '\0'; str1++)
	{
		t = sep;
		for (; *t != '\0'; t++)
		{
			if (*str1 == *t)
			{
				*str1 = NULL;//置空
				index = 1;//有切割符,发生变化
				break;
			}
		}
		if (*str1 != NULL && flag == 1)//每一次调用的第一次不为空的地址
		{
			s = str1;//返回值指向这个起始地址
			flag = 0;
		}
		if (*str1 != NULL && flag == 0 && index==1)//将切割符走完,且后面出现不为空的字符,前面已经出现过切割符
		{
			temp = str1;//temp保存str1此时的地址,作为下次传入null时的输入地址
			return s;//返回第一次不为空的地址
		}
	}
	temp = str1;//里面没有切割符,直接令temp等于最后的地址
	return s;//返回起始地址
}

 
10.strerror:将错误码转换为字符串形式,方便查找错误

错误码:一般是表示,用户在调用C标准库函数的时候,如果调用库函数的时候,出错了,C语言中 有一个全局变量errno,就会被设置(默认为0,如果被设置了,就是非0)
就是用来表明详细的错误原因(库函数调用说明C错误)
头文件为 <errno.h>

 
11.memcpy:字节拷贝函数

定义:void *memcpy(void *dst, const void *src, size_t num);
从src中复制num个字节到dst的内存位置
若src中的字节数小于num,拷贝到src最后一个字节就会停止
若dst中的字节数小于num个,会对后面的字节进行拷贝,直到src中的最后一个字节

 
12.memmove:字节拷贝。

memmove内存拷贝,如果发生内存重叠,memmove能够保证使src在被覆盖之前拷贝到dst当中,拷贝之后,src也会发生变化。
若无内存重叠,memcopy和memmove功能相同。
定义:void *memmove(void *dst, const void *src, size_t num);

 
 
解决内存重叠的问题:
通过一定的判定,来进行决策,是从右向左拷贝,还是从左向右拷贝。
在这里插入图片描述
若src向src+1拷贝整个字节,就会出现这样的情况,这样就发生的内存重叠,达不到我们预期的结果。
在这里插入图片描述
在这里插入图片描述

达到预期结果,也可以进行模拟这个函数。
有内存重叠时,进行拷贝时,使用memmove函数更好。

 
13.memset:内存赋值函数

定义:void *memset(void *dst, int value, size_t num);
按照字节为单位进行赋值,把每个字节赋值为value
可对数组进行清0操作,但若想赋特定的值,一定要注意使用,因为memset是按照每个字节进行运算的。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值