广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C语言头文件<string.h>函数详解
  • 780
分享到

C语言头文件<string.h>函数详解

2024-04-02 19:04:59 780人浏览 八月长安
摘要

目录1. strlen —— 求字符串长度1.1 strlen 的声明与用处1.2 strlen 的用法 1.3 strlen 的模拟实现2. st

1. strlen —— 求字符串长度

1.1 strlen 的声明与用处

strlen ,我们有一些英语基础的话不难通过字面意思来知道这个函数是干嘛用的,str 表 string ,字符串的意思,len 表 length ,长度的意思。也就是说,strlen 是求字符串长度的函数。我们通过 cplusplus 这个网站来观察 strlen 的函数声明以及各个参数的意义。

我们翻译可以知道,strlen 所求的字符串长度是字符串结束标志之前的字符个数。即我们假设有字符串 "hello world" ,那么所求的字符串长度就是 '\0' 之前的所有字符个数,也就是 11 。那么这个字符串长度是通过返回值返回的,所以我们要知道所求的字符串长度是多少就必须定义一个变量来接收返回值。那么参数部分当然就是字符串的首地址了。

1.2 strlen 的用法

#include <stdio.h>
#include <string.h>
 
int main()
{
	char str1[] = "hello world";
	char* str2 = "hello world";
 
	int len1 = strlen(str1);//数组名表首元素地址
	int len2 = strlen(str2);//str2 指针变量存放的也是首元素地址
 
	printf("%d\n", len1);
	printf("%d\n", len2);
 
	//这种写法也可以输出长度
	//printf("%d\n", strlen(str1));
	//printf("%d\n", strlen(str2));
 
	return 0;
}

我们要注意的一点是,strlen 的返回值是一个 size_t 类型,即无符号整数。 它的意义在于求长度时是不可能求出负数的,所以一定程度上优化了内存(使用有符号整形的话会浪费掉用来存储负数的空间)。

 1.3 strlen 的模拟实现

我们上面已经分析过 strlen 的原理了,那么现在我们用自己所学过的只是来“创造”一个属于自己的 strlen 函数。

#include <stdio.h>
#include <assert.h>
unsigned int my_strlen(const char* str)//我们不改变字符串的内容,所以用 const 来进行修饰
{
	assert(str);//避免是一个空指针
	unsigned int count = 0;
	while (*str)
	{
		count++;
		str++;
	}
	return count;
}
int main()
{
	char str1[] = "hello world";
	char* str2 = "hello world";
 
	int ret1 = my_strlen(str1);
	int ret2 = my_strlen(str2);
 
	printf("%d\n", ret1);
	printf("%d\n", ret2);
 
	return 0;
}

2. strcpy —— 字符串拷贝

2.1 strcpy 的声明与用处

我们对其字面翻译进行理解,str 表 string ,即字符串,cpy 表 copy ,即拷贝。也就是 strcpy 这个函数是用来进行字符串拷贝的。那我们通过 cplusplus 这个网站来观察 strcpy 的声明以及各个参数的意义。

我们翻译过来就可以知道 strcpy 的功能,拷贝 source 指针指向的字符串至 destination 指针指向的数组当中,拷贝的内容包含字符串终止符。并且 destination 指针指向的数组必须有足够大的空间容纳拷贝之后的内容。 

由此我们知道, strcpy 需要两个参数,一个是数组,一个是字符串。并且数组的空间必须足够大。返回值是返回数组拷贝之前的地址。这么做的意义是防止拷贝之前的内容丢失。

2.2 strcpy 的用法

#include <stdio.h>
#include <string.h>
 
int main()
{
	char dest[20] = "row your boat";
	char src[] = "hello world";
	strcpy(dest, src);
	printf("%s\n", dest);
	return 0;
}

这是 strcpy 最最常用的用法,我们只需要记住一点即可:拷贝过去的内容是包含 '\0' 的。也就是说即使我拷贝过去的字符串长度没有数组原来的字符串长度长,但是我包含 '\0' 了,在 C 语言的角度来说 '\0' 之后的内容就不算从头往后看的字符串内容了。

2.3 strcpy 的模拟实现

#include <stdio.h>
#include <assert.h>
 
char* my_strcpy(char* dest, const char* src)//dest 指向的数组空间是要被改变的,但是 src 指向的字符串不需要改变
{
	assert(dest && src);//防止其中某个是无效指针
	char* ret = dest;
	while (*dest++ = *src++)
		;	//注意 while 循环执行了空语句
 
	return ret;
}
int main()
{
	char dest[30] = "gently down the stream";
	char src[] = "life is but a dream";
 
	my_strcpy(dest, src);
	printf("%s\n", dest);
	return 0;
}

3. strcmp —— 字符串比较

3.1 strcmp 的声明与用处

也是一样,我们可以通过字面翻译来大致了解这个函数是干嘛用的。str 表 string ,即字符串,cmp 表 compare ,即比较。我们同样通过 cplusplus 这个网站观察这个函数的声明以及各个参数的意义。

我们翻译即可知道这个函数的原理。其原理就是:都是从两个字符串的第一个字符开始比较,如果这两个字符相等,那么这两个字符串都会进行下一对字符比较,直到两个字符不相等,然后进行比较大小。如果第一个字符小于第二个字符,就会返回一个小于 0 的整数,等于则返回 0 ,大于则返回一个大于 0 的整数。

其两个参数都是要比较的字符串。为了方便理解,我们通过画图的形式来理解。

 3.2 strcmp 的用法

#include <stdio.h>
#include <string.h>
 
int main()
{
	char* str1 = "abbbcd";
	char* str2 = "abbbdd";
	int ret = strcmp(str1, str2);
	if (ret > 0)
		printf("str1 > str2\n");
	else if (ret < 0)
		printf("str1 < str2\n");
	else
		printf("str1 == str2\n");
	return 0;
}

 3.3 strcmp 的模拟实现

#include <stdio.h>
#include <assert.h>
 
int my_strcmp(const char* str1, const char* str2)//两个字符串的内容都不需要修改,用 const 修饰
{
	assert(str1 && str2);//防止是无效指针
 
	while (*str1 == *str2)//如果相等则进入循环
	{
		if (*str1 == '\0')//*str1 == '\0' 了并且进入循环了,说明两个字符串比较完成了,没有不相等的字符
			return 0;
		str1++;
		str2++;
	}
	return *str1 - *str2;//两个字符的差作为返回值
}
int main()
{
	char* str1 = "abbbcd";
	char* str2 = "abbbdd";
	int ret = my_strcmp(str1, str2);
	if (ret > 0)
		printf("str1 > str2\n");
	else if (ret < 0)
		printf("str1 < str2\n");
	else
		printf("str1 == str2\n");
	return 0;
}

4. strcat —— 字符串追加

4.1 strcat 的声明与用处

 我们通过 cplusplus 这个网站来观察 strcat 的声明以及各个参数的意义。

翻译一下即可直到 strcat 函数的用法:将 source 指针指向的字符串追加到 destination 指针指向数组并且有足够大的空间(本人尝试追加到字符串,但是失败了),其追加的位置是 destination 指针指向的字符串的 '\0' 处,即从这个位置拷贝。需要注意的是,追加的 '\0' 的位置第一个 '\0' 的位置。

4.2 strcat 的用法 

#include <stdio.h>
#include <string.h>
 
int main()
{
	char str1[50] = "row row row your boat,";
	char* str2 = "gently down the stream";
	strcat(str1, str2);
	printf("%s\n", str1);
	return 0;
}

4.3 strcat 的模拟实现 

#include <stdio.h>
#include <assert.h>
 
char* my_strcat(char* dest, const char* src)//src 指向的字符串是不改变内容的,所以用 const 修饰
{
	assert(dest && src);//确保两个指针有效
	char* ret = dest;
	while (*dest)
		dest++;//先找到 dest 指向的数组的第一个 '\0' 的位置
	while (*dest++ = *src++)//拷贝
		;
	return ret;
}
int main()
{
	char str1[50] = "row row row your boat,";
	char* str2 = "gently down the stream";
	my_strcat(str1, str2);
	printf("%s\n", str1);
	return 0;
}

5. strncpy —— 长度受限制的字符串拷贝

5.1 strncpy 的声明与用处

strncpy 与 strcpy 的区别就是 strncpy 多了一个参数。这个参数是一个无符号的整数,即可以自定义拷贝多少个字节的内容。这就大大的方便了我们的使用,提高了 C 语言的灵活性。

5.2 strncpy 的用法

#include <stdio.h>
#include <string.h>
 
int main()
{
	char str1[20] = "row your boat";
	char str2[] = "hello world";
	strncpy(str1, str2, 3);//我们从 str2 中拷贝三个字节的内容到 str1 去
	printf("%s\n", str1);
	return 0;
}
 

 

 我们可以看到输出的结果非常奇怪,这是因为当我们只拷贝三个字节的内容时,strncpy 是不会在后面补 '\0' 的(即要多少内容就拷多少内容),这就导致了我们能够看到 str1 数组里面拷贝之前的内容。

5.3 strncpy 的模拟实现

#include <stdio.h>
#include <assert.h>
 
char* my_strncpy(char* dest, const char* src, unsigned int num)
{
	assert(dest && src);//确保两个指针有效
	char* ret = dest;
 
	while (num--)//拷贝几个字节
	{
		*dest = *src;
		dest++;
		src++;
	}
 
	return ret;
}
int main()
{
	char str1[20] = "row your boat";
	char str2[] = "hello world";
	my_strncpy(str1, str2, 3);
	printf("%s\n", str1);
	return 0;
}

6. strncmp —— 长度受限制的字符串比较

6.1 strncmp 的声明与用处

strncmp 与 strcmp 的功能是一模一样的,原理也就是一模一样的。也就是说掌握了 strcmp 就能够掌握 strncmp 。strncmp 只是相较于 strcmp 多了一个参数,这个参数是一个无符号整数,代表的是字节。即我们想要比对多少字节。我们通过 cplusplus 这个网站可以观察这个函数的声明以及各个参数的意义。

6.2 strncmp 的用法

#include <stdio.h>
#include <string.h>
 
int main()
{
	char* str1 = "abbbcd";
	char* str2 = "abbbdd";
	int ret=strncmp(str1, str2,3);//我们只想比较字符串的前三个字节
	if (ret > 0)
		printf("str1 > str2\n");
	else if (ret < 0)
		printf("str1 < str2\n");
	else
		printf("str1 == str2\n");
	return 0;
}

6.3 strncmp 的模拟实现

#include <stdio.h>
#include <assert.h>
 
int my_strncmp(const char* str1, const char* str2, unsigned int num)//两个字符串的内容都不需要变,所以用 const 修饰
{
	assert(str1 && str2);
	while (num-- && *str1 == *str2)
	{
		if (*str1 == '\0')
			return 0;
		str1++;
		str2++;
	}
	return *str1 - *str2;
}
int main()
{
	char* str1 = "abbbcd";
	char* str2 = "abbbdd";
	int ret = my_strncmp(str1, str2, 3);//我们只想比较字符串的前三个字节
	if (ret > 0)
		printf("str1 > str2\n");
	else if (ret < 0)
		printf("str1 < str2\n");
	else
		printf("str1 == str2\n");
	return 0;
}

7. strncat —— 长度受限制的字符串追加

7.1 strncat 的声明与用处

同理,掌握了 strcat 就能掌握 strncat 。strncat 其参数多了一个无符号整形的参数,其意义代表字节数。即我们可以自定义想要追加多少个字符至另一个字符串的后面。我们可以通过 cplusplus 这个网站观察 strncat 的声明以及各个参数的意义。

7.2 strncat 的用法

#include <stdio.h>
#include <string.h>
 
int main()
{
	char str1[50] = "row row row your boat,";
	char str2[] = "gently down the stream";
	strncat(str1, str2, 6);//我们只想追加 6 个字节的字符到 str1 中
	printf("%s\n", str1);
	return 0;
}

 在这里如果我们注意观察的话,就会发现一个问题。我们追加过去的 6 个字节的字符并不包含 '\0' ,但是在最后输出打印的时候好像在字符串尾又被赋予了 '\0' 。那么这就不得不提及 strncat 的特性,即 strncat 会在要追加的字符串后面补 '\0' 。

 7.3 strncat 的模拟实现

#include <stdio.h>
#include <assert.h>
 
char* my_strncat(char* dest, const char* src, unsigned int num)//str2 中的字符串不需要被修改,所以用 const 修饰
{
	assert(dest && src);//确保两个指针是有效指针
	char* ret = dest;//记录返回值
 
	while (*dest)//先找到 dest 指向的 '\0' 的位置
		dest++;
	while (num-- && (*dest++ = *src++) )//拷贝限制的字节数
		;
	*dest = '\0';
 
	return ret;
 
}
int main()
{
	char str1[50] = "row row row your boat,";
	char str2[] = "gently down the stream";
	my_strncat(str1, str2, 8);
	printf("%s\n", str1);
	return 0;
}

小结

我们上面介绍了许多长度不受限制的字符串函数和长度受限制的字符串函数。那么受限制和不受限制有什么区别呢? 首先不受限制的字符串函数的灵活性是比较低的,因为只能操作整个字符串。但是受限制的字符串函数的灵活性是比较高的,可以自定义操作的字符个数。并且,长度受限制的字符串函数相对于长度不受限制的字符串函数来说是比较安全的。注意是受限制的相对于不受限制的比较安全。

8. strstr —— 字符串查找

8.1 strstr 的声明与用处

strstr 通过字面翻译过来就是两个字符串。那么其意义是在其中一个字符串里面查找另外一个字符串。我们可以通过 cplusplus 这个网站来观察 strstr 的声明以及各个参数的意义。

我们翻译一下即可知道 strstr 的某些原理。如果在字符串 1 里面查找到了字符串 2 ,那么就返回字符串 2 出现在字符串 1 中的首地址。如果没有找到字符串,就返回一个空指针。

8.2 strstr 的用法

#include <stdio.h>
#include <string.h>
 
int main()
{
	char* str1 = "row row row your boat,gently down the stream";
	char* str2 = "row your boat";
	char* ret = strstr(str1, str2);//在 str1 中查找 str2 
	printf("%s\n", ret);
	return 0;
}

可以看到返回值是返回 str2 第一次出现在 str1 中的首地址。 

8.3 strstr 的模拟实现

#include <stdio.h>
#include <assert.h>
 
char* my_strstr(const char* str1, const char* str2)//不需要改变其内容,用 const 修饰
{
	assert(str1 && str2);//避免是无效指针
	const char* s1 = str1;
	const char* s2 = str2;
	const char* cp = str1;//这个指针变量是至关重要的
	while (*cp)
	{
		s1 = cp;
		s2 = str2;
 
		//在 str1 中查找 str2 的核心循环
		while (*s1 && *s2 && *s1 == *s2)
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')//查找完成
			return (char*)cp;
 
		cp++;
	}
	return NULL;
}
int main()
{
	char* str1 = "row row row your boat,gently down the stream";
	char* str2 = "row your boat";
	char* ret = my_strstr(str1, str2);
	printf("%s\n", ret);
	return 0;
}

我们来通过画图来详解一下思路。 

 9. strtok —— 字符串切割

9.1 strtok 的声明与用处

对于这个函数,我们只要了解了基本的使用方法即可。我们通过 cplusplus 这个网站来观察 strtok 的声明以及各个参数的意义。

这段英文的篇幅太长了,我来解释一下核心部分:我们提供两个参数给 strtok ,一个是字符串,一个是要切割的标记。如果在这个字符串当中出现了这个标记,那么这个位置将被修改为 '\0' ,并且返回这个标记之前的字符串地址。如果要进行二次传参,那么只需要传一个空指针即可。

9.2 strtok 的用法

#include <stdio.h>
#include <string.h>
 
int main()
{
	char* str1 = "row@row~row%your^boat,gently@down~the^stream";
	char* str2 = "@~%^";
 
	//将 str1 拷贝至 tmp 数组,这样不会丢失 str1 的原始数据
	char tmp[50] = { 0 };
	strcpy(tmp, str1);
 
	char* ret = NULL;
	for (ret = strtok(tmp, str2); ret != NULL; ret = strtok(NULL, str2))
	{
		printf("%s ", ret);
	}
	return 0;
}

10. strerror —— 错误码解析

10.1 strerror 的声明与用处

我们需要普及的一个点是,在 C 语言中,程序发生错误的时候,是有一个隐藏的全局变量 errno 的,这个变量是一个整数的,譬如 0 ,1,2,3,....等都代表不同的错误信息,而 strerror 的作用就是翻译这个错误码。我们可以通过 cplusplus 这个网站来观察 strerror 的声明以及各个参数的意义。 

10.2 strerror 的用法

#include <stdio.h>
#include <string.h>
 
int main()
{
	FILE* p;
	p = fopen("test.txt", "r");//在我们的工程目录下并没有 test.txt 这个文件
	if (p == NULL)//那么打不开 p 就是一个空指针
	{
		printf("%s\n", strerror(errno));//这里就会解释为什么是空指针的原因
	}
	return 0;
}

 到此这篇关于C语言头文件<string.h>函数详解的文章就介绍到这了,更多相关C语言头文件<string.h>函数详解内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: C语言头文件<string.h>函数详解

本文链接: https://www.lsjlt.com/news/164464.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C语言头文件<string.h>函数详解
    目录1. strlen —— 求字符串长度1.1 strlen 的声明与用处1.2 strlen 的用法 1.3 strlen 的模拟实现2. st...
    99+
    2022-11-13
  • 仿写C语言string.h头文件检验字符串函数
    目录c语言string.h头文件字符串检验函数仿写strlen字符串求长度strcmp / strncmp字符串比较strchr / strrchr 字符串中查找字符ch第一个出现的...
    99+
    2022-11-12
  • 怎么仿写C语言string.h头文件检验字符串函数
    这篇文章主要讲解了“怎么仿写C语言string.h头文件检验字符串函数”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么仿写C语言string.h头文件检验字符串函数”吧!c语言string...
    99+
    2023-06-25
  • C语言文件操作之fread函数详解
    目录前言一、fread 函数二、缓冲区受限的情况 ( 循环读取文件 | feof 函数判定文件读取完毕 )三、处理乱码问题四、记录读取的字节个数五、读取到 0 字节的情况六、读取完毕...
    99+
    2022-11-13
  • C语言lseek()函数详解
     头文件: #include <sys/types.h> #include <unistd.h> 函数原型: off_t lseek(in...
    99+
    2022-11-12
  • C语言memset函数详解
    目录一、memset函数原型:二、使用memset函数三、给int类型赋值为1四、扒开内存五、memset给变量赋值总结在c语言中,使用变量前,需要先对变量的值进行初始化。数组在内存...
    99+
    2022-11-12
  • 详解C语言之函数
    目录函数的调用函数调用方式函数嵌套调用递归调用内部函数与外部函数内部函数外部函数局部变量与全局变量局部变量全局变量总结函数的调用 函数调用方式 函数语句调用 函数表...
    99+
    2022-11-12
  • C++头文件algorithm中的函数功能详解
    目录1. 不修改内容的序列操作(1)all_of(2)any_of(3)none_of(6)find_if(7)find_if_not(8)find_end(10)adjacent_...
    99+
    2022-11-12
  • 一文详解C语言中文件相关函数的使用
    目录一、文件和流1、程序文件2、数据文件3、流二、文件组成三、文件的打开和关闭1、文件的打开fopen2、文件关闭fclose四、文件的顺序读写1、使用fputc和fgetc写入/读...
    99+
    2022-11-13
  • C语言实现随机读写文件的函数详解
    目录1.fseek2.ftell3.rewind总结在上一篇博客中,我详细讲解了如何使用C语言顺序读写文件。所谓顺序读写,就是按照顺序,挨个挨个的读或者写,换句话说,我必须先读第一个...
    99+
    2023-05-14
    C语言随机读写文件 C语言读写文件 C语言 文件
  • C语言中scanf函数详解
    scanf函数是C语言中用于从标准输入流中读取数据的函数。它的原型如下:```cint scanf(const char *form...
    99+
    2023-09-13
    C语言
  • C语言之qsort函数详解
    目录一.qsort函数原型二.qsort常见的几种比较函数1.int类型的排序2.double类型的排序3.char类型的排序4.字符串的排序:1.按首字母排序2.按字符串长度排序:...
    99+
    2022-11-12
  • C语言函数指针详解
    目录Introduction函数指针 Function PointersExercise 1:qsort中的函数指针Exercise 2:总结Introduction 上一个lab的...
    99+
    2022-11-12
  • C语言函数栈帧详解
    目录前言一.函数栈帧是什么?二、栈帧准备知识1.内存分区2.什么是栈?三、详解栈帧创建与销毁全过程调用函数之前:将传入函数的值放入栈中函数执行:1.保护当前ebp2.创建所需调用函数...
    99+
    2022-11-12
  • C语言strcpy库函数详解
    目录C语言strcpy库函数的讲解附1:MSDN关于strcpy库函数的简介思路:总结 C语言strcpy库函数的讲解 附1:MSDN关于strcpy库函数的简介 思路: 1.从上...
    99+
    2022-11-12
  • C 语言回调函数详解
    回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。1. 什么是回调函数?...
    99+
    2023-06-03
  • C语言文件操作详解
    目录一、什么是文件二、文件缓冲区三、文件指针四、文件的打开和关闭。总结一、什么是文件 在程序设计中,我们一般谈的文件有两种:程序文件、数据文件。 程序文件: 包括源程序文件(后缀为....
    99+
    2022-11-12
  • 详解C语言fscanf函数读取文件教程及源码
    目录第一部分:问题和结论fscanf 函数的原型是:第二部分:实验代码实验代码:fscanf 函数用于格式化读入文件中数据,可以大大提高读取文件的效率。这次笔者将最近使用该函数的一些...
    99+
    2022-11-13
  • C语言的递归函数详解
    目录函数递归什么是递归?递归的俩个必要条件代码引例1栈溢出(Stack Overflow)合理使用递归代码引例3代码引例4解释要合理使用递归总结函数递归 程序调用自身的编程技巧称为递...
    99+
    2022-11-12
  • C语言strtod()函数案例详解
    前言 网上有很多关于strtod()函数的文章,不过大部分都是用strtod()函数转换一个字符 char *str = "111.11"; char *target; doub...
    99+
    2022-11-12
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作