C语言:字符串函数详解!

目录

字符函数和字符串函数

1.strlen函数

2.strcpy函数

3.strncat函数

4.strcmp

5.strstr函数

6.KMP算法:

KMP算法的基本步骤:


字符函数和字符串函数

C语言中对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的,字符串通常放在 常量字符串中或者字符数组 中。 字符串常量 适用于那些对它不做修改的字符串函数

1.strlen函数

size_t strlen ( const char * str );

字符串已经 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包含 '\0' )。

参数指向的字符串必须要以 '\0' 结束。

注意函数的返回值为size_t,是无符号的( 易错 )

如果想要了解strlen函数的模拟实现可以点击下方链接:

http://t.csdnimg.cn/pbe7t

2.strcpy函数

在C语言中,strcpy函数是一个非常常用的字符串操作函数,用于复制一个字符串到另一个字符串中。这个函数位于string.h头文件中,其标准声明如下:

char* strcpy(char * destination, const char * source ); 

参数说明:

  • destination: 这是指向目标字符串的指针,即你希望复制源字符串内容存放的位置。这个区域必须足够大,以便容纳源字符串以及结尾的空字符\0
  • source: 这是指向源字符串的指针,即你要复制的字符串内容。

功能:

strcpy函数会将source指向的字符串(包括结束的空字符\0)完整地复制到destination指向的内存区域中。如果destination之前已经存储有字符串,那么这些内容会被覆盖。

注意事项

  1. 安全性strcpy函数不会检查目标缓冲区的大小,如果源字符串过长可能会导致缓冲区溢出,引发运行时错误或安全漏洞。因此,在实际开发中,推荐使用更安全的替代函数,如strncpystrcpy_s(某些编译器或库中提供)。
  2. 空字符strcpy会复制源字符串中的所有字符,直到遇到空字符\0为止,因此,源字符串必须是有效的C字符串(以\0结尾)。
  3. 内存重叠:如果destinationsource指向的内存区域有重叠,strcpy的行为是未定义的,可能会导致数据损坏或程序崩溃。
#include <stdio.h>
#include <string.h>

int main() 
{
    char destination[50];
    const char source[] = "Hello, World!";
    
    strcpy(destination, source);
    printf("%s\n", destination);
    return 0;
}

3.strncat函数

strncat函数用于将一个字符串添加到另一个字符串的末尾。

char *strncat(char *dest, const char *src, size_t n);

  • dest: 是目标字符串,需要有足够的空间来存储源字符串和它自己原有的内容。
  • src: 是要追加的源字符串。
  • n: 指定从源字符串中拷贝的最大字符数(不包括结束的空字符\0)。
#include <stdio.h>
#include <string.h>

int main()
{
    char str1[50] = "Hello, ";
    char str2[] = "World!";
    strncat(str1, str2, strlen(str2)); // 注意:strlen(str2)防止了越界
    printf("%s\n", str1); // 输出: Hello, World!
    return 0;
}

4.strcmp

strcmp函数用于比较两个字符串是否相等。它返回一个整数值来表示两个字符串的比较结果,原型也在string.h中定义。

int strcmp(const char *s1, const char *s2);
  • s1s2: 分别是要比较的两个字符串。
  • 如果s1小于s2(按照字典序),函数返回负值。
  • 如果s1等于s2,返回0。
  • 如果s1大于s2,返回正值。
#include <stdio.h>
#include <string.h>

int main() {
    char str1[] = "apple";
    char str2[] = "banana";
    char str3[] = "Apple";

    if(strcmp(str1, str2) < 0) 
    printf("%s comes before %s.\n", str1, str2); // apple comes before banana.
    if(strcmp(str1, str3) == 0) 
    printf("%s equals to %s.\n", str3); // 不执行,因为不相等。
    return 0;
}

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 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 arr1[20] = "zhangsan";
	//char arr2[] =   "zhangsanfeng";
	char arr1[] = "abcq";
	char arr2[] = "abcq";
	//abcdef
	//abq
	//
	//两个字符串比较相等,应该使用strcmp
	int ret = my_strcmp(arr1, arr2);
	if (ret < 0)
		printf("<\n");
	else if (ret == 0)
		printf("==\n");
	else
		printf(">\n");

	//比较一下两个字符串是否相等
	//arr1是数组名,数组名是数组首元素的地址
	//arr2是数组名,数组名是数组首元素的地址
	/*if (arr1 == arr2)
	{
		printf("==\n");
	}
	else
	{
		printf("!=\n");
	}*/

	return 0;
}

5.strstr函数

strstr()函数是C语言标准库中的一个非常实用的字符串处理函数,位于string.h头文件中。它的主要功能是在一个较大的字符串(haystack)中查找一个较小的子字符串(needle),并返回子字符串第一次出现的位置的指针。如果没有找到子字符串,则返回NULL

char *strstr(const char *haystack, const char *needle);

参数说明

  • haystack: 这是一个指向源字符串(被搜索的字符串)的指针,即要在其中查找子字符串的大字符串。
  • needle: 这是一个指向子字符串的指针,即想要在haystack中查找的字符串。

返回值

  • 如果needlehaystack中被找到,函数返回一个指向haystackneedle首次出现位置的指针。
  • 如果没有找到needle,函数返回NULL

注意事项

  • strstr()不区分大小写,若需要区分大小写查找,需自行实现或先转换字符串。
  • 搜索时,haystack可以包含空字符,needle也可以为空字符串,但haystack不能是NULL
  • 返回的指针指向haystack内部,因此修改haystack内容会影响返回的指针的有效性。
#include <stdio.h>
#include <string.h>

int main() 
{
    char str[] = "Hello, this is a simple example.";
    const char target[] = "simple";

    char *result = strstr(str, target);

    if(result != NULL)
    {
        printf("Substring found at position: %td\n", result - str);
    } 
    else 
    {
        printf("Substring not found.\n");
    }

    return 0;
}

在这个例子中,strstr()函数查找字符串"simple"`在"Hello, this is a simple example."中的位置,并打印出子字符串首次出现的偏移位。

strstr函数的模拟实现:

char* my_strstr(const char* str1, const char* str2)
{
	assert(str1 && str2);
	const char* s1 = str1;
	const char* s2 = str2;
	const char* p = str1;

	while (*p)
	{
		s1 = p;
		s2 = str2;
		while (*s1!='\0' && *s2!='\0' && *s1 == *s2)
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')
		{
			return (char*)p;
		}
		p++;
	}
	return NULL;
}

int main()
{
	//char email[] = "zpw@bitejiuyeke.com";
	//char substr[] = "bitejiuyeke";
	//char* ret = my_strstr(email, substr);
	char arr1[] = "abcdef";
	char arr2[] = "def";
	char* ret = my_strstr(arr1, arr2);

	if (ret == NULL)
	{
		printf("子串不存在\n");
	}
	else
	{
		printf("%s\n", ret);
	}
	return 0;
}

对于这个函数我们还可以通过数据结构中的KMP算法来实现:

该算法是一种改进的字符串搜索算法,目的是在文本串(常称为S)中查找模式串(常称为P)是否存在,如果存在则返回模式串在文本串中的起始位置,否则返回未找到。KMP算法的核心思想是利用已知的匹配信息,避免重复比较,从而减少不必要的回溯操作,提高搜索效率。

6.KMP算法:

KMP算法的基本步骤:

  1. 前缀表(Next数组)的构建

    • 为了实现高效搜索,KMP算法首先预处理模式串P,构造一个辅助数组next[](也称为部分匹配表或失配表),该数组记录了模式串中各位置前缀与后缀的最长公共长度。具体构建方法如下:
      • next[0] = -1 初始化。
      • 当模式串中第i位置的字符与第j位置的字符相同时,next[i] = next[j] + 1,否则尝试j回溯。
      • 直到找到一个合适的j使得P[0...j]与P[i-j]相同或j=-1为止。
    • next[i]的含义是当P[0...i-1]与S的某段匹配失败时,P应跳过的字符数,即P中最大公共前后缀长度。
  2. 匹配过程

    • 初始化文本串指针i指向第一个字符,模式串指针j指向第一个字符。
    • 当i<s且j<s且字符匹配时,i++, j++。
    • 如果j到达P末尾,匹配成功,返回i-j。
    • 若不匹配,j回溯,根据next[j]值更新j。
      • 如果next[j]=-1,i++, j=0(模式串从头开始比较)
      • 否则j=next[j],i不动(模式串向后跳到最长公共前后缀处)
#include <stdio.h>
#include<string.h>
// 构建Next数组
void getNext(const char p[], int next[]) 
{
    int i = 0, j = -1;
    next[0] = -1;
    while (i < strlen(p)) 
	{
        if (j == -1 || p[i] == p[j]) 
		{
            i++;
            j++;
            next[i] = j;
        } 
		else 
		{
            j = next[j];
        }
    }
}

// KMP匹配函数
int KMPMatch(const char s[], const char p[]) 
{
    int i = 0, j = 0;
    int slen = strlen(s), plen = strlen(p);
    int next[plen + 1]; // 存储Next数组

    getNext(p, next); // 根据模式串p构建Next数组

    while (i < slen && j < plen) 
	{
        if (j == -1 || s[i] == p[j]) 
		{ // 当字符匹配或j为-1时
            i++;
            j++;
        } 
		else 
		{
            j = next[j]; // 失配时,根据Next数组调整j
        }
    }

    if (j == plen) 
	{
        return i - j; // 匹配成功,返回起始位置
    } 
	else 
	{
        return -1; // 匹配失败
    }
}

int main() 
{
    char text[] = "hello world, welcome to the world of programming";
    char pattern[] = "world";
    int index = KMPMatch(text, pattern);

    if (index != -1) 
	{
        printf("语句所在位置: %d\n", index);
    } 
	else 
	{
        printf("没有找到语句\n");
    }

    return 0;
}

这段代码首先定义了两个函数:getNext用于生成模式串P的Next数组,KMPMatch用于进行KMP匹配。在main函数中,定义了文本串s和模式串p,调用KMPMatch函数进行匹配,并输出匹配结果。如果找到模式串,则输出其在文本串中的起始位置,否则输出“Pattern not found.”。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值