C语言字符串库函数详解

C语言字符串库函数详解

1.strlen函数:求字符串长度

int main()
{
	char arr1[] = "abc";
	char arr2[] = { 'a', 'b', 'c' };
	int len1 = my_strlen(arr1);
	int len2 = strlen(arr2);
	printf("%d\n", len1);
	//输出3,字符串长度不包括"\0"
	printf("%d\n", len2);
	//输出随机值,因为字符串arr2没有'\0',strlen找不到终点
	return 0;
}

1.1 模拟实现strlen函数

int my_strlen(const char* str)//使用const让指针修饰的内容无法被改变
{
	int count = 0;
	assert(str != NULL);
	while(*str != '\0')
	{
		count++;
		str++;
	}
	return count;
}

1.2 关于strlen函数的1个习题

int main()
{
	const char*str1 = "abcdef";
	const char*str2 = "bbb";
	if (strlen(str2) - strlen(str1) > 0)
	{
		printf("str2>str1\n");
	}
	else
	{
		printf("srt1>str2\n");
	}
	return 0;
}

输出"str2>str1",因为strlen返回类型size_t是个无符号数,理论上是3-6=-3,但是-3会被解析为无符号数,所以答案是>

2.strcpy函数:字符串拷贝

	char arr[20] = { 0 };
	strcpy(arr,"hello");

//arr必须是个数组而不能是个字符串常量,只有可修改的destination才能承受拷贝来的字符串,所以此处必须声明为数组

	char arr2[] = { 'a', 'b', 'c' };
	strcpy(arr, arr2);

这里没有’\0’,而’\0’是strcpy的终止条件,所以此处会报错,拷贝找不到终止的位置

	char arr[2] = { 0 };
	strcpy(arr, "hello");

可以拷贝,但是拷贝完会出错,目标空间需要足够大才能承受我们拷贝过去的数据,此程序会报错

3.strcat函数:字符串追加

	char arr[20] = "hello ";
	strcat(arr,"world");
	printf("%s\n", arr);

要求目标要有足够大的空间用来追加那个想追加的字符串,所以此处arr声明的空间20比较大;

	char arr[20] = "hello \0####";
	strcat(arr, "world");
	printf("%s\n", arr);

用来测试world里面的\0是否会被拷贝来,测试结果是world里面的\0会被拷贝进来

3.1 strcat库函数的使用

int main()
{
	char arr[20] = "abcd";
	strcat(arr, arr);//错了,不能自己给自己追加,因为\0被改变了,找不到结束的标志\0了
}

需要注意strcat函数不能自己给自己追加,上面的代码会报错

3.2 strcat库函数的模拟实现
实现过程分为2个步骤:(1)找到目标字符串中的\0(2)把源字符串加上去,包括\0

char* my_strcat(char* dest,const char* src)//库函数中的返回类型是char*,是指向目标空间的地址
{
	char* ret = dest;
	assert(dest&&src);//两个都不能是空指针
	//1.找到目标字符串中的\0
	while (*dest)
	{
		dest++;
	}
	//while循环停下来的时候,dest指向'\0'
	//2.追加源字符串,包含'\0'
	while (*dest++= *src++)
	{
		;
	}
	return ret;//返回目标空间的起始地址
}

4.strcmp函数:字符串比较
比较2个字符串是否相等,注意strcmp比较的是对应字符的asc码值的大小,而不是比较字符串长度大小

4.1 strcmp函数的使用

int main()
{
	char* p = "abcdef";
	char* q = "abbb";
	int ret = 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;
}

标准规定:
第一个字符串大于第二个字符串,则返回大于0的数字
第一个字符串等于第二个字符串,则返回0
第一个字符串小于第二个字符串,则返回小于0的数字

4.2 strcmp函数的模拟实现
方法一:

int my_strcmp(const char* str1, const char* str2)
{
	while (*str1 == *str2)
	{
		if (*str1 == '\0')//此处考虑str1为'\0'的特殊情况
		{
			return 0;
		}
		str1++;
		str2++;
	}
	if (*str1 > *str2)
	{
		return 1;
	}
	else
	{
		return -1;
	}
}

方法二:由于库函数中仅仅返回正值、负值或者0,所以方法一中返回1、-1、0来模拟是不严谨的,方法二是对方法一的优化

int my_strcmp2(const char* str1, const char* str2)
{
	while (*str1 == *str2)
	{
		if (*str1 == '\0')
		{
			return 0;
		}
		str1++;
		str2++;
	}
	return *str1 - *str2;//此处不一定要返回1,0,-1;而是直接返回正数,0或负数
}

上面所说的strcpy,strcat,strcmp都是长度不受限制的字符串函数;而接下来要说的strncpy,strncat,strncmp都是长度受限制的字符串函数

5.strncpy函数:长度受限制的字符串拷贝

char * strncpy(char * destination, const char * source, size_t num);

拷贝num个字符从源字符串到目标空间。如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个
5.1 strncpy函数的使用

int main()
{
	char arr1[20] = "abcdef";
	char arr2[] = "qwer";
	strncpy(arr1, arr2, 2);
	printf("%s\n", arr1);//打印qwcdef
	return 0;
}
int main()
{
	char arr1[20] = "abcdefghi";
	char arr2[] = "qwer";
	strncpy(arr1, arr2, 6);//确实会拷贝6个过去,但最后2个字符是0和\0,qwer0\0
	printf("%s\n", arr1);//qwer
	return 0;
}

6.strncat函数:限制长度的字符串追加

6.1strncat函数的使用

int main()
{
	char arr1[20] = "hello ";
	char arr2[] = "world";
	strncat(arr1, arr2, 3);
	printf("%s\n", arr1);//hello wor\0,主动再末尾补上\0
	return 0;
}

追加字符数量是3,所以只在"hello “后面加上"wor”

int main()
{
	char arr1[20] = "hello ";
	char arr2[] = "world";
	strncat(arr1, arr2, 6);
	printf("%s\n", arr1);//hello world\0
	return 0;
}

追加字符数量为6,输出"hello world"

int main()
{
	char arr1[20] = "hello ";
	char arr2[] = "world";
	strncat(arr1, arr2, 10);
	printf("%s\n", arr1);//hello world\0
	return 0;
}

追加字符数量为10,仍然输出"hello world"

7.strncmp函数:比较2个字符串前num个字符是否相等

7.1 strncmp函数的使用

int main()
{
	char arr1[20] = "hello ";
	char arr2[] = "world";
	int ret=strncmp(arr1, arr2, 3);//比较arr1和arr2的前3个字符是否相等
	printf("%d\n", arr1);//hello world\0
	return 0;
}

8.strstr函数:字符串查找

8.1 strstr函数的使用

int main()
{
	char arr1[] = "abcdefabcdef";
	char arr2[] = "bcd";
	//在arr1中查找arr2
	char* ret = strstr(arr1, arr2);
	if (ret == NULL)
		printf("没找到\n");
	else
		printf("找到了,%s\n",ret);
}

返回str2在str1中第一次出现的位置,如果str1中没有str2,则返回空指针

8.2 strstr函数的模拟实现

char* my_strstr(const char*str1,const char*str2)
{
	assert(str1&&str2);
	const char* s1 = str1;
	const char* s2 = str2;
	const char *cp = str1;//cp指针用来标记str1开始查找的起始位置
	if (str2 == '\0')
		return (char*)str1;
	while (*cp)
	{
		s1 = cp;
		s2 = str2;
		while (*s1&&*s2&&(*s1 == *s2))
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')
		{
			return (char*)cp;
		}
		cp++;
	}

}

9.strtok函数:用来切割字符串
9.1 strtok函数的使用

int main()
{
	char arr[] = "abc@abcd.com";
	char* p = "@.";
	//p中可以放上所有的分隔符
	char temp[20] = { 0 };
	//strtok会把分隔符所在位置变成\0,再返回前面那个字符串的地址,切割这个字符串会被修改,所以会再创建一个该字符串的拷贝用于修改
	strcpy(temp, arr);
	char* ret = NULL;
	ret=strtok(temp, p);
	//strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
	ret=strtok(NULL, p);
	//strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
	ret=strtok(NULL, p);
	//下面一段循环是对上面的简化
	for (ret = strtok(temp, p); ret != NULL;ret=strtok(NULL,p))
	//当ret返回空指针跳出循环,传空指针时会从上一次记住的位置开始找,该函数具有记忆功能,该函数内部可能会有static变量
	{
		printf("%s\n", ret);
	}
	return 0;
}

10.strerror函数:翻译错误码
使用库函数调用失败时都会设置错误码,如C语言中的错误码是int errno,而strerror则会把错误码翻译成错误信息
10.1 strerror函数的使用

#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));
	//不同错误码对应不同错误信息
	FILE* pf = fopen("test.txt", "r");
	//打开文件,"r"表示read,读取
	if (pf == NULL)
	{
		printf("%s\n", strerror(errno));
		//翻译错误信息,即文件不存在----"No such file or dictinary"
		return 1;
	}
	fclose(pf);//关闭文件
	pf = NULL;
	return 0;
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值