C语言中10个字符串函数详解

目录

1.strlen

2.strcpy

3.strcat

4.strcmp

5.strncpy

6.strncat

7.strncmp

8.strstr

9.strtok

10.strerror

1.strlen

  • 基本结构:size_t strlen(const char *str);
  • 功能:用于计算字符串的长度;
  • 字符串已经 '0'作为结束标志,strlen函数返回的是在字符串中'\0'前面出现的字符个数;
  • 参数指向的字符串必须要以'0'结束;
  • 注意函数的返回值为size_t,是无符号的(易错);

(1)库函数用法

cs 复制代码
#include <string.h>
int main()
{
	char arr[] = "abc";
	char arr1[] = { 'a', 'b', 'c' };

	int len = strlen(arr);
	int len1 = strlen(arr);

	printf("%d\n", len);
	printf("%d\n", len1);  //随机值,arr1没得'\0'

	return 0;
}

(2)自定义函数 - 模拟实现strlen

可以分为三种写法:计数器版本、递归版本和指针减去指针版本。

cs 复制代码
//a.计算器版本
#include <assert.h>
int my_strlen(const char* str)   //str数组名表示数组第一个元素地址
{
	int count = 0;   //计数器
	assert(str != NULL);   //断言,确保str不是空指针

	while (*str != '\0')
	{
		count++;
		str++;
	}
	return count;
}

//b.递归版本
int my_strlen(char* str)
{
	if (*str != '\0')
		return 1 + my_strlen(str + 1);
	else
		return 0;
}

//c.指针减去指针的版本
int my_strlen(char* str)
{
	char* start = str;
	while (*str != '\0')
	{
		str++;
	}
	return str - start;
}

int main()
{
	char arr[] = "abc";
	int len = my_strlen(arr);
	printf("%d\n", len);

	return 0;
}

2.strcpy

  • 基本结构:char* strcpy(char *destination,const char *source );
  • 功能:用于字符串的复制;
  • 源字符串必须以'\0'结束;
  • 会将源字符串中的'0'拷贝到目标空间;
  • 目标空间必须足够大,以确保能存放源字符串;
  • 目标空间必须可变。

(1)库函数用法

cs 复制代码
int main()
{
	//a.正确用法
	char arr[20] = "#############";
	strcpy(arr, "hello");
	printf("%s\n", arr);

	//b.错位用法:源字符串中必须包括'\0'
	//char arr1[] = { 'a', 'b', 'c' };   //不行,拷贝的时候必须带'\0'
	//strcpy(arr, arr2);

	//c.错误用法:目标空间必须足够大,能放下源字符串
	//char arr[5] = "#####";
	//char *p = "hello word";
	//strcpy(arr, p);

	//d.错误用法:目标空间必须可变。
	//char* str = "###########";
	//char *p = "hello word";
	//strcpy(str, p);	

	return 0;
}

(2)模拟实现strcpy

cs 复制代码
#include <assert.h>

char* my_strcpy(char* dest, const char* src)
{
	char* start = dest; // 保存 dest 的初始值  
	assert(dest&&src != NULL);

	while ((*dest++ = *src++) != '\0')
	{
		// 复制字符,直到 '\0'  
	}
	return start; // 返回目标字符串的起始地址  
}

int main()
{
	char src[] = "Hello World!";
	char dest[50]; // 确保目标缓冲区足够大,以避免溢出  

	my_strcpy(dest, src);
	printf("Copied string: %s\n", dest);

	return 0;
}

3.strcat

  • 实现功能:字符串追加;
  • char* strcat(char*destination,const char*source );
  • 源字符串必须以'0'结束;
  • 目标空间必须有足够的大,能容纳下源字符串的内容;
  • 目标空间必须可修改。

(1)库函数

cs 复制代码
int main()
{
	//在hello后面加上word
	char arr[20] = "hello ";
	strcat(arr, "word");
	printf("%s\n", arr);

	return 0;
}

(2)模拟实现

cs 复制代码
#include <assert.h>
char* my_strcat(char* dest, const char* src)
{
	char* ret = dest;
	assert(dest && src != NULL);
	//a.找到目标字符串的'\0'
	while (*dest)
	{
		dest++;
	}
	//b.源数据追加过去,包含'\0'
	while (*dest++ = *src++)
	{
		;
	}
	return ret;  //返回目标空间的起始地址
}

int main()
{
	//在hello后面加上word
	char arr1[20] = "hello ";
	char arr2[] = "world";
	my_strcat(arr1, arr2);
	printf("%s\n", arr1);

	return 0;
}

4.strcmp

  • 实现功能:用来比较两个字符串大小(比较对应位置的ASII值);
  • 基本结构:int strcmp(const char* strl, const char* str2);
  • 比较到出现另个字符不一样或者一个字符串结束或者num个字符全部比较完。

(1)库函数

cs 复制代码
int main()
{
	int ret = strcmp("abbb", "abq");   //<0
	//int ret = strcmp("sit", "sit");
	printf("%d\n", ret);

	return 0;
}

(2)模拟实现

cs 复制代码
#include <assert.h>
int my_strcmp(const char* s1, const char* s2)
{
	assert(s1&&s2 != NULL);
	while (*s1 == *s2)
	{
		if (*s1 == '\0')
		{
		    return 0;
		}
		s1++;
		s2++;

	}

	a.第一种写法
	//if (*s1 > *s2)
	//{
	//	return 1;
	//}
	//else
	//{
	//	return -1;
	//}

	//b.第二种写法:只要返回的值满足体条件即可
	return *s1 - *s2;
}

int main()
{
	char* p = "abcdef";
	char* q = "abbb";
	int ret = my_strcmp(p, q);   

	if (ret > 0)
	{
		printf("p > q\n");
	}
	else if(ret < 0)
	{
		printf("p < q\n");
	}
	else
	{
	    printf("p == q\n");
	}

	return 0;
}

5.strncpy

基本结构:char* strncpy(char* destination, const char* source, size t num);

参数说明:

  • dest:目标字符串的指针,即要复制到的位置。该位置必须有足够的空间来容纳复制的字符以及可能的空字符\0(如果源字符串长度小于n)。
  • src:源字符串的指针,即要从中复制的字符串。
  • n:要复制的最大字符数(包括空字符\0,但实际上strncpy并不保证在复制n个字符后自动添加\0)。

功能:将源字符串src的前n个字符复制到目标字符串dest中。

cs 复制代码
int main()
{
	char arr1[10] = "aaaaaaaa";
	char arr2[] = "hhhh";
	strncpy(arr1, arr2, 2);
	printf("%s\n", arr1);   //hhaaaaaa

	return 0;
}

6.strncat

基本结构:char* strncat(char*destination, const char* source, size_t num)

参数说明:

  • dest:目标字符串的指针,即要将源字符串追加到的位置。该位置必须有足够的空间来容纳追加的字符以及额外的空字符\0
  • src:源字符串的指针,即要追加的字符串。
  • n:要追加的最大字符数。如果源字符串的长度小于n,则会将源字符串的全部字符追加到目标字符串中;如果源字符串的长度大于或等于n,则只会追加前n个字符。

功能:strncat函数将源字符串src的前n个字符追加到目标字符串dest的末尾,并在追加完成后在dest的末尾添加一个空字符\0。

cs 复制代码
int main()
{
	char arr1[10] = "hello ";
	char arr2[] = "word";
	strncat(arr1, arr2, 3);
	printf("%s\n", arr1);   //hello wor

	return 0;
}

7.strncmp

基本结构:int strncmp(const char* strl, const char* str2, size_t num );

参数说明:

  • str1:指向第一个要比较的字符串的指针。
  • str2:指向第二个要比较的字符串的指针。
  • n:要比较的字符数。

实现功能:strncmp函数逐个比较str1str2的前n个字符(或直到遇到第一个空字符\0,以先到者为准)。根据比较结果,函数返回一个整数,表示两个字符串在比较的前n个字符中的相对顺序。

返回值:

  • 如果str1str2的前n个字符完全相同(或者在比较过程中遇到了空字符\0),则strncmp返回0。
  • 如果str1在字典顺序上小于str2(即str1的第一个不同字符的ASCII值小于str2的对应字符),则strncmp返回一个负整数。
  • 如果str1在字典顺序上大于str2(即str1的第一个不同字符的ASCII值大于str2的对应字符),则strncmp返回一个正整数。
cs 复制代码
int main()
{
	char* p = "abcdef";
	char* q = "abcqwert";
	//int ret = strcmp(p, q);
	int ret = strncmp(p, q, 1);

	printf("%d\n", ret);
	return 0;
}

8.strstr

基本结构:char* strstr(const char*,const char*);

参数:

  • str1:被查找的字符串(目标字符串)。
  • str2:要查找的子字符串。

功能:用于判断一个字符串(str2)是否是另一个字符串(str1)的子串。如果str2是str1的子串,则函数返回str2在str1中首次出现的地址(即指向str1中str2首次出现位置的指针);如果str2不是str1的子串,则返回NULL。

(1)库函数

cs 复制代码
int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "bcd";

	在arr1中查找是否包含arr2数组
	char* ret = strstr(arr1, arr2);
	if (ret == NULL)
	{
		printf("没找到\n");
	}
	else
	{
		printf("找到了:%s\n", ret);
	}
	return 0;
}

(2)模拟实现

cs 复制代码
#include <assert.h>
char* my_strstr(const char* str1, const char* str2)
{
	assert(str1 && str2);
	const char* s1 = NULL;
	const char* s2 = NULL;
	char* cp = str1;
	while (*cp )
	{
		s1 = cp;
		s2 = str2;
		while (*s1 && *s2 && (*s1 == *s2))
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')   //找到了
		{
			return (char*)cp;
		}
		cp++;
	}
	return NULL;
}

int main()
{
	char arr1[] = "abbbbcdef";
	char arr2[] = "bbc";

	//在arr1中查找是否包含arr2数组
	char* ret = my_strstr(arr1, arr2);
	if (ret == NULL)
	{
		printf("没找到\n");
	}
	else
	{
		printf("找到了:%s\n", ret);
	}
	return 0;
}

9.strtok

  • 功能:切割一个字符串
  • 结构:char* strtok(char* str, const char* sep);
  • sep参数是个字符串,定义了用作分隔符的字符集合
  • 第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记。
  • strtok函数找到str中的下一个标记,并将其用\0结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)
  • strtok函数的第一个参数不为 NULL,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
  • strtok函数的第一个参数为 NULL,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
  • 如果字符串中不存在更多的标记,则返回NULL指针
cs 复制代码
int main()
{
	char arr[] = "3033433807@qq.com";
	char* p = "@.";
	char tmp[20] = { 0 };
	strcpy(tmp, arr);

	char* ret = NULL;

	(1)第一种写法:麻烦
	//ret = strtok(tmp, p);
	//printf("%s\n", ret);

	//ret = strtok(NULL, p);
	//printf("%s\n", ret);

	//ret = strtok(NULL, p);
	//printf("%s\n", ret);

	//第二种写法:简洁
	for (ret = strtok(tmp, p); ret != NULL; ret=strtok(NULL,p))
	{
		printf("%s\n", ret);
	}

	return 0;
}

10.strerror

  • 结构:char* strerror(int errnum );
  • 功能:返回错误码,所对应的错误信息。
  • 使用库函数,调用失败的时候,都会设置错误码
  • int errno - 全局变量
  • 和它对应的一个库函数:perror - 直接打印错误信息,没得错误码
cs 复制代码
#include <errno.h>
int main()
{
	//下面每个错误码,就会有对应的错误信息
	//printf("%s\n", strerror(0));   
	//printf("%s\n", strerror(1));
	//printf("%s\n", strerror(2));
	//printf("%s\n", strerror(3));
	//printf("%s\n", strerror(4));
	//printf("%s\n", strerror(5));

	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		//printf("%s\n", strerror(errno));
		perror("fopen");
		return 1;
	}

	return 0;
}
相关推荐
卡里笔记2 分钟前
C语言版2048小游戏
c语言
修己xj14 分钟前
一月存档,二月加载
学习
梵刹古音18 分钟前
【C语言】 循环结构
c语言·开发语言·算法
皮皮哎哟25 分钟前
冒泡排序与数组传递全解析 一维二维指针数组及二级指针应用指南
c语言·算法·冒泡排序·二维数组·指针数组·传参·二级指针
蒸蒸yyyyzwd28 分钟前
c网络编程学习笔记
c语言·网络·学习
驱动探索者36 分钟前
linux hwspinlock 学习
linux·运维·学习
烟花落o37 分钟前
贪吃蛇及相关知识点讲解
c语言·前端·游戏开发·贪吃蛇·编程学习
近津薪荼37 分钟前
优选算法——滑动窗口1(单调性)
c++·学习·算法
头发还没掉光光37 分钟前
Linux 高级 IO 深度解析:从 IO 本质到 epoll全面讲解
linux·服务器·c语言·c++
齐鲁九零1 小时前
【AI推荐】推荐适合学英语的美剧
学习