C语言:字符串函数(strcpy,strcat,strcmp,strstr)简介

本文详细介绍了C语言中的四个字符串处理函数:strcpy用于字符串复制,strcat用于字符串追加,strcmp用于字符串比较,strstr用于查找子串。分别讲解了函数的原理、使用方法和模拟实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1.strcpy函数

1.1简介strcpy函数

1.2strcpy函数的使用和模拟实现

1.2.1strcpy函数使用:

1.2.2strcpy函数的模拟实现

2.strcat函数

2.1strcat函数简介

2.2strcat函数的使用和模拟实现

2.2.1strcat函数的使用

2.2.2strcat函数的模拟实现

3.strcmp函数

3.1简介strcmp函数

3.2strcmp函数使用及原理和模拟实现

3.2.1strcmp函数的使用及原理

3.2.2strcmp函数的模拟实现

4.strstr函数

4.1简介strstr函数

4.2strstr函数使用及原理和模拟实现

4.2.1strstr函数的使用

4.2.2ststr函数的模拟实现


 

 

1.strcpy函数

1.1简介strcpy函数

fb10c71e8f6729936112203b57bd11b7.png

根据官网上的介绍,strcpy函数有2个参数,第一个参数是destnation(意思是字符串的粘贴地),第二个参数是source(意思是字符串的复制地)。

这个函数有几个注意事项:

1.源字符串必须以‘\0’结尾。                                                                                                                2.strcpy函数会将‘\0’拷贝到目标空间。                                                                                              3.目标空间必须可修改而且要足够大。

1.2strcpy函数的使用和模拟实现

1.2.1strcpy函数使用:

int main()
{
	char arr1[] = "**********";
	char arr2[] = "abcd";
	printf("%s\n", strcpy(arr1, arr2));
	return 0;
}

输出结果是:

84dd7e716c120114ec2862d02ae5d8f9.png

我们发现arr1中的后面的x并没有被打印出来,说明strcpy函数会将源字符串的'\0'也复制到目标字符串中,以达到覆盖的效果。

1.2.2strcpy函数的模拟实现

字符串函数返回的值都是char*类型的地址。再根据strcpy函数的两个参数可以对该函数进行下列模拟:

char* my_strcpy(char* dest, const char* src)
{
	char* ret = dest;
	assert(dest != NULL);
	assert(src != NULL);
	while ((*dest++ = *src++))
	{
		;
	}
	return ret;
}


int main()
{
	char arr1[] = "**********";
	char arr2[] = "abcd";
	printf("%s\n", my_strcpy(arr1, arr2));
	return 0;
}

 

2.strcat函数

2.1strcat函数简介

d46d9f999409ed7e50cfd5b4d8e398e2.png

strcat函数(string concatenation function)作用是将源字符串的内容转移到目标字符串的后面。这种方式不会破坏目标字符串,相当于只给目标字符串添加了一个源字符串。

strcat函数注意事项:

1.源字符串必须以'\0'结尾。                                                                                                                2.目标字符串也必须有'\0',要不然不知道从哪个位置开始追加。                                                      3.目标字符串必须要有足够空间,并且可修改。

2.2strcat函数的使用和模拟实现

2.2.1strcat函数的使用

像之前所说,strcat是在目标字符串后面追加源字符串,所以不会像strcpy函数那样起到覆盖的效果,代码如下:

int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "xxxxxx";
	printf("%s\n",strcat(arr2,arr1));
	return 0;
}

输出结果是:

82f01a1a8435059e86b672c8f5c58a49.png

2.2.2strcat函数的模拟实现

char* my_strcat(char*dest,const char*src)
{
	assert(dest != NULL);
	assert(src != NULL);
	char* ret = dest;
	while (*dest)
	{
		dest++;
	}
	dest++;
	while ((*dest++=*src++))
	{
		;
	}
	return ret;
}


int main()
{
	char arr1[] = "abcdef";
	char arr2[100] = "xxxxxx";
	printf("%s\n",strcat(arr2,arr1));
	printf("%s\n", my_strcat(arr2, arr1));
	return 0;
}

模拟实现大致与strcpy函数相似,只是在复制粘贴工作之前增加了一个找目标字符串'\0'的工作(这样才能保证追加在源字符串的后面)。

模拟strcat函数和strcat函数效果对比结果如下:

55171c80419f6d0fc2f235f25868c483.png

 

3.strcmp函数

3.1简介strcmp函数

5cb2fef8b766c43356bd0b8c151270d2.png

411a7196cfeeca1238b936461c71c0a0.png

strcmp函数是比较两个字符串的函数,根据cplusplus官网上的信息,strcmp函数有两个参数(两个参数都是const char*类型的,将字符串的首元素地址传参过去),返回的是一个整型值。

当左边的字符串小于右边字符串时,返回值是负数。                                                                        当左边的字符串等于右边字符串时,返回值是0。                                                                            当左边的字符串大于右边字符串时,返回值是正数。 

3.2strcmp函数使用及原理和模拟实现

3.2.1strcmp函数的使用及原理

字符串大小比较的原理是:从字符串第一个元素开始比较,如果正在比较的元素的Asc||码值相同就进入下一个元素的比较;如果正在比较的元素的码值不同,则停止比较,Asc||码值大的元素对应的字符串就更大。

比如:"abcdefg"<"abcq"

我们写代码来验证一下:

fe673409a823453e57f26e83e6e7b276.png

除了比大小之外,strcmp函数还能判断输入的字符串是不是你想要的字符串以此来达到一定的效果。比如:如果输入 "Jay Chou",就输出"好帅";而输入其他字符串则无效,可以用下面这段代码来进行:

int main()
{
	
	while (1)
	{
		char c[] = "0";
		printf("请输入字符串:");
		gets(c);
		if (strcmp(c, "Jay Chou") == 0)
		{
			printf("好帅\n");
		}
		else
		{
			;
		}
	}
	return 0;
}

bf131e6044cb36b31813d99e8c36af57.png

用strcmp比较,当输出结果为0,就说明两个字符串完全一致。

3.2.2strcmp函数的模拟实现

根据前面介绍的strcmp函数比较的原理,我们大致知道了这个函数是逐字符进行比较的。所以我们可以写出以下代码来:

int my_strcmp(const char*str1,const char*str2)
{
	while (*str1 == *str2)
	{
		if (*str1 == '\0')
		{
			return 0;
		}
		str1++;
		str2++;
	}
	return *str1 - *str2;
	
}

然后我们在主函数中进行测试:

int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abcdef";
	int ret1 = strcmp(arr1,arr2);
	int ret2 = my_strcmp(arr1, arr2);
	printf("%d\n",ret1);
	printf("%d\n",ret2);
	return 0;
}

测试结果如下:

df7c7448948827e3a1a46c3ca4b9eca2.png

9f008d67d871a6f1db8b82845641dd9c.png

d87aa75942fd6ea9605f123c2cb66e35.png

因为函数返回值只对正负有要求,所以我们很好地完成了模拟任务。

 

4.strstr函数

4.1简介strstr函数

4202e8e01c030439e00db00751e9748b.png

Returns a pointer to the first occurrence of str2 in str1, or a null pointer if str2 is not part of str1.
(函数返回字符串str2在字符串str1中第⼀次出现的位置)。
The matching process does not include the terminating null-characters, but it stops there.(字符
串的⽐较匹配不包含 \0 字符,以 \0 作为结束标志)。
 

4.2strstr函数使用及原理和模拟实现

4.2.1strstr函数的使用

先看下面这一段代码:
 

int main()
{
	char arr1[] = "abcdefghi";
	char arr2[] = "cde";
	char*ret= strstr(arr1, arr2); 
	printf("%s\n",ret);
	return 0;
}

打印结果是:

d39b4b11d52f663a2e5310af3568c397.png

更加印证了strstr函数的作用是找到目标字符串在源字符串中的位置,并从该位置继续向后打印直到遇见'\0'为止。

如果在源字符串中找不到目标字符串,那么系统将会返回一个(NULL)指针。

4.2.2ststr函数的模拟实现

模拟实现的本质在于:通过指针比较目标字符串是否在源字符串中出现过,那么我们使用的就是地址的解引用。

我们先假设有这样两个字符串:arr1="abbbcdef" , arr2="bbc". 按照我们原有的思路,先移动arr1的指针直到与arr2的首字符相等的时候开始匹配。但是,当arr1,arr2的指针同时移动:arr1指针从第一个b开始移动到到第三个b,arr2的指针到c的时候发现并不匹配,这个时候按理说不能直接判断为匹配失败,而是要让arr1的指针从第二个b开始,arr2的指针从第一个b开始进行下一轮的匹配,但是此时两个指针都不在原有的位置上了,这是解决此问题的一个最大的麻烦。

如下图:

7caa2678eaed40bab2bb323f09fb013c.png

左图是起始位置在abbbcdefg 的检测过程,右图是左边检测失败后应当进行的从abbbcdefg 开始的检测过程。而因为指针位置错乱了所以导致在常规思路下检测无法正常进行。

所以要想正常地进行检测,除了str1和str2以外,我们必须要有一个专门的指针记录源字符串开始匹配的位置,还要有一个移动指针指向arr2,当需要重新检测的时候再用str2赋值即可。

 完整代码如下:

char* my_strstr(const char*str1,const char*str2)
{
	 char* s1 = NULL;
	 char* s2 = NULL;
	 char* current = str1;


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


int main()
{
	char arr1[] = "abcdefghi";
	char arr2[] = "cde";
	char*ret1= strstr(arr1, arr2); 
	char* ret2 = my_strstr(arr1,arr2);
	printf("%s\n",ret1);
	printf("%s\n", ret2);
	return 0;
}

两种函数输出结果比较为:

d39fc7e4bd7d538ebf5a3b309fbdcfc4.png

 


感谢观看,有任何错误请批评指出

 

<think>首先,用户的问题是:“我想了解 strcpy 函数的使用及其相关编程知识 请问strcpy 函数在 C 语言中的使用方法及注意事项”。这基于系统级指令,我需要遵循所有规则。 系统级指令: 1. 所有行内数学表达式使用 $...$ 格式。但在这个问题中,strcpy字符串函数,不涉及数学表达式,所以可能不需要。 2. 独立公式使用 $$...$$ 并单独成段。同样,这里可能不适用。 3. LaTeX 语法正确。 4. 使用中文回答。 5. 生成相关问题。 6. 回答中引用的段落末尾自然地添加引用标识,例如 [^1]。 用户可见层: - 回答结构清晰,帮助用户逐步解决问题。 - 尽量保证回答真实可靠。 参考站内引用: - 引用[1]: C++中strcpy函数的使用注意事项。提到了问题代码和注意事项。 - 引用[2]: C语言strcpy函数详解。包括原型、使用示例。 - 引用[3]: strcpy功能、使用示例和注意事项。 - 引用[4]: 目标空间必须可修改,源字符串可以是常量。 这些引用是关于 strcpy 函数的,所以我需要整合这些信息来回答。 回答结构: 1. **介绍 strcpy 函数**:简要说明其用途。 2. **使用方法**:包括原型、头文件、参数解释。 3. **示例代码**:提供简单示例。 4. **注意事项**:列出常见错误和如何避免。 5. **相关问题**:生成相关问题。 使用中文回答。 确保回答真实可靠:strcpy 是标准 C 库函数,用于字符串复制。常见问题包括缓冲区溢出,因为不检查目标大小。 添加引用标识:在引用内容末尾添加,如 [^1]。 生成相关问题:在回答末尾添加“相关问题”部分。 现在,构建回答大纲: - **开头**:解释 strcpy 函数。 - **使用方法**: - 原型:char *strcpy(char *dest, const char *src); - 头文件:<string.h> - 参数:dest 是目标字符串,src 是源字符串。 - **示例**:提供一个代码示例,展示如何安全使用(考虑缓冲区大小)。 - **注意事项**: - 目标缓冲区必须足够大。 - 目标空间必须可修改。 - 避免缓冲区溢出(提到 strncpy 作为更安全的替代)。 - 源字符串必须以 '\0' 结尾。 - **结尾**:总结重要点。 - **相关问题**:生成 3-5 个相关问题。 在注意事项中,引用提供的引用: - 引用[1] 提到问题代码和注意事项。 - 引用[2] 提供原型和示例。 - 引用[3] 有示例和注意事项。 - 引用[4] 强调目标空间可修改。 所以,在回答中,自然地添加引用标识。 例如: - 在讨论注意事项时,说“目标空间必须可修改,否则会导致未定义行为 [^4]”。 最后,生成相关问题: 1. 如何避免 strcpy 导致的缓冲区溢出? 2. strcpy 和 strncpy 有什么区别? 3. 在 C++ 中,推荐使用什么替代 strcpy? 4. strcpy 函数在什么场景下常用? 5. 如何实现自定义的 strcpy 函数? 确保使用中文。</think>### strcpy 函数在 C 语言中的使用方法及注意事项 strcpy 函数是 C 语言标准库中的一个字符串复制函数,用于将源字符串复制到目标字符串中。它在处理字符串操作时非常常见,但如果不正确使用,可能导致缓冲区溢出、内存损坏等严重问题。下面我将逐步解释其使用方法、提供示例代码,并详细说明注意事项,以帮助您安全高效地使用该函数。回答基于 C 语言标准库,并结合可靠编程实践。 #### 1. strcpy 函数的基本介绍 strcpy 函数的原型定义为: ```c char *strcpy(char *dest, const char *src); ``` - **功能**:将源字符串 `src`(包括终止的空字符 `'\0'`)复制到目标字符串 `dest` 中。 - **返回值**:返回目标字符串的指针 `dest`。 - **头文件**:必须包含 `<string.h>` 头文件才能使用该函数。 - **工作原理**:strcpy 会从 `src` 的开头开始复制字符,直到遇到 `'\0'` 为止,然后将 `'\0'` 也复制到 `dest` 中。如果 `src` 长度超过 `dest` 的缓冲区大小,会导致未定义行为(如缓冲区溢出)。 #### 2. 使用方法及示例代码 strcpy 的使用非常简单,但需要确保目标缓冲区足够大。以下是一个基础示例,展示如何安全使用 strcpy 函数。 ```c #include <stdio.h> #include <string.h> // 必须包含此头文件 int main() { char src[] = "Hello, C!"; // 源字符串 char dest[20]; // 目标缓冲区,大小必须足够容纳源字符串 + '\0' // 使用 strcpy 复制字符串 strcpy(dest, src); printf("源字符串: %s\n", src); printf("目标字符串: %s\n", dest); // 输出: Hello, C! return 0; } ``` - **解释**: - 在这个示例中,`src` 是源字符串,长度为 10(包括 `'\0'`),`dest` 被声明为大小为 20 的字符数组,确保有足够空间避免溢出。 - 复制后,`dest` 包含完整的 "Hello, C!" 字符串,并以 `'\0'` 结尾。 - **关键点**:目标缓冲区 `dest` 必须预先分配足够内存,且必须是可修改的内存区域(如数组或动态分配的内存)。如果 `dest` 指向常量字符串或只读内存,会导致运行时错误 [^4]。 #### 3. 注意事项 strcpy 函数虽然简单,但错误使用会引发严重安全问题。以下是常见注意事项,基于实际编程经验: 1. **目标缓冲区大小必须足够**:strcpy 不会检查目标缓冲区的大小。如果 `src` 的长度超过 `dest` 的容量,会导致缓冲区溢出,可能覆盖相邻内存,引发崩溃或安全漏洞(如栈溢出攻击)。 - **安全建议**:使用 `strncpy` 函数作为替代,它可以指定最大复制长度。例如: ```c char dest[10]; strncpy(dest, src, sizeof(dest) - 1); // 复制最多 9 个字符 dest[sizeof(dest) - 1] = '\0'; // 手动添加终止符 ``` 这样能防止溢出,但需手动处理 `'\0'` [^1][^2]。 2. **目标空间必须可修改**:`dest` 必须指向可写的内存区域。如果 `dest` 是常量字符串(如 `char *dest = "constant"`),尝试复制会导致未定义行为(例如程序崩溃)。 - **错误示例**: ```c char *dest = "read-only"; // 指向常量字符串 strcpy(dest, "new"); // 运行时错误:目标不可修改 ``` 正确做法是使用字符数组或动态分配内存(如 `malloc`)[^4]。 3. **源字符串必须以 '\0' 结尾**:strcpy 依赖 `src` 的 `'\0'` 终止符来确定复制结束位置。如果 `src` 不是以 `'\0'` 结尾的字符串(如未初始化的字符数组),复制会继续直到遇到随机 `'\0'`,导致内存越界访问。 - **安全建议**:确保 `src` 是合法的 C 字符串。例如,初始化源字符串:`char src[] = "valid";`。 4. **避免使用在动态内存中未检查大小**:当 `dest` 是动态分配的内存时,必须确保分配的大小足够。否则,复制大字符串会引发堆溢出。 - **示例错误**: ```c char *dest = malloc(5); // 只分配 5 字节 strcpy(dest, "overflow"); // src 长度 9,导致溢出 ``` 解决方案:使用 `strncpy` 或手动计算长度。 5. **性能考虑**:strcpy 是高效函数,时间复杂度为 $O(n)$(n 为字符串长度),但在高安全要求场景(如网络编程),建议使用更安全的函数如 `snprintf` 或 C11 的 `strcpy_s`(如果编译器支持)[^1][^3]。 总结来说,strcpy 是一个基础但危险的函数。使用时务必: - 检查目标缓冲区大小。 - 确保目标空间可修改。 - 优先使用安全替代品(如 `strncpy`)在关键代码中。 通过遵循这些注意事项,您可以避免常见错误,编写更健壮的 C 程序 [^1][^2][^3][^4]。 ####
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值