上节内容讲的3个函数是没有长度限制的,拷贝和追加的过程中会有溢出的风险。有没有优化的版本呢?答案是有的。

//有源字符串长度限制
strncopy
strncat
strncmp

strncopy

函数与上节内容讲的类似,唯一不同的地方就是有了长度限制,追加完,拷贝完自动在字符串末尾加\0。

int main()
{
	char ch[] = "************";
	char* ch1 = "abc";
	strncpy(ch, ch1, 2);
	printf("%s\n", ch);
	return 0;
}

如果 src 的长度小于 n,strncpy 会在复制完 src 的所有字符后,向 dest 中填充 ‘\0’ 直到总长度达到 n。但如果 src 的长度大于或等于 n,dest 中将不会自动添加终止符,此时 dest 可能不是一个以 ‘\0’ 结尾的有效 C 字符串。

strncat

字符串追加函数,但是这个函数可以自己给自己追加,因为它会自动在追加完n个数据后增加\0。

#include<string.h>//可以给自己追加内容,追加完自动在末尾加'\0'
int main()
{
	char ch1[20] = "abcd";
	char *ch2 = "efghz";
	strncat(ch1, ch1,4);
	printf("%s\n", ch1);
	return 0;
}

找到目标字符串的末尾:strncat 会首先找到 dest 中第一个 ‘\0’ 终止符的位置,从该位置开始追加 src 的内容。
追加字符:将 src 中的字符追加到 dest 的末尾,直到追加了 n 个字符或遇到 ‘\0’ 终止符。
自动添加终止符:无论 src 的长度如何,strncat 都会在追加完成后,在 dest 的末尾添加一个 ‘\0’ 终止符。因此,dest 始终是一个以 ‘\0’ 结尾的有效 C 字符串。

strncmp

比较函数,用于比较前n个数据的大小。

int main()
{
	const char* ch1 = "abcde";
	const char* ch2 = "abcdr";
	int r = strncmp(ch1, ch2,4);
	printf("%d\n", r);
	return 0;
}

逐字符比较:strncmp 会逐个比较 s1 和 s2 的字符,直到:
比较了 n 个字符;
遇到不相等的字符;
遇到 ‘\0’ 终止符。
终止条件:
如果在比较到第 n 个字符之前遇到了 ‘\0’ 终止符,则比较提前结束。例如,若 s1 是 “abc”,s2 是 “abcd”,当 n >= 4 时,strncmp(s1, s2, n) 会返回负值(因为 s1 的长度更短)。
如果比较了 n 个字符都相等,则返回 0。

strtok函数

作用:用来分离含有标记的字符串。
啥意思?1234@qq.com$$123
这个函数就会把特殊字符作为标记,将其左右的内容分离出来。
函数char * strtok ( char * str, const char * sep);

使用 strtok 函数时需注意以下要点:

  • sep 参数用于指定分隔符集合,其值为一个字符串
  • 第一个参数为待分割的字符串,其中包含零个或多个由 sep 中分隔符分割的标记
  • strtok 会查找字符串中的下一个标记,将其以 \0 结尾,并返回指向该标记的指针(注意:strtok 会修改原字符串,因此通常使用可修改的临时副本)
  • 当第一个参数非 NULL 时,函数将查找字符串中的第一个标记,并保存其在字符串中的位置
  • 当第一个参数为 NULL 时,函数将从上次保存的位置开始查找下一个标记
  • 若字符串中无更多标记,函数将返回 NULL 指针
    也就是说该函数的返回值是标记前的字符串的第一个字符的地址。
#include<string.h>
int main()
{
	char ch[] = "1780163243@qq.com";
	char buf[30] = { 0 };
	strcpy(buf, ch);
	
	char* p = "@ .";
	char* s = strtok(buf, p);//返回的是第一个标记符之前的第一个字符地址
	printf("%s\n", s);

	s = strtok(NULL, p);//字符指针重新赋值
	printf("%s\n", s);
	s = strtok(NULL, p);//字符指针重新赋值
	printf("%s\n", s);
	return 0;
}
#include<string.h>
int main()
{
	char ch[] = "1780163243@qq.com";
	char buf[30] = { 0 };
	strcpy(buf, ch);
	char* p = "@ .";
	char* r = NULL;
	for (r = strtok(buf, p); r != NULL;r=strtok(NULL,p))
	{
		printf("%s\n", r);//不存在标记,返回NULL
	}
	return 0;
}
//第一次返回1的地址,第二次返回q的地址,第三次返回c的地址,第四次返回NULL

这段代码也很好的诠释了上述内容。

strstr函数

这个函数的作用是第一个字符串里面找出第二个字符串,并返回其首位字符的位置。包含string.h

#include<string.h>
int main()
{
	char str[] = "this is a apple";
	char* ch;
	ch = strstr(str, "apple");
	strncpy(ch, "bbbb", 3);
	printf("%s\n", ch);
	return 0;
}

运行结果:bbble

模拟实现

在这里插入图片描述

char* my_strstr(const char* str1, const char* str2)
{
	const char* c = str1;
	const char* p1 = NULL;
	const char* p2 = NULL;
	if (*str2 == '\0')
	{
		return str1;
	}
	while (*c)
	{
		p1 = c;
		p2 = str2;
		while (*p1 == *p2 && *p2 && *p1)
		{
			p1++;
			p2++;
		}
		if (*p2 == '\0')
		{
			return c;
		}
		c++;
	}
	return NULL;

}
int main()
{
	char str[] = "this is a apple";
	char* ch;
	ch = my_strstr(str, "apple");
	printf("%s\n", ch);
	return 0;
}

思路定义三个指针,其中c指向开始遍历字符串的起始位置,交给p1,p2去便利,遍历成功返回c,否则返回NULL。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐