字符函数和字符串函数(1)


前言

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


一、校验参数

在工作开始前,首先要校验参数的合法性,使用if或者assert都可以,但必须要有这种意识。典型的是检验空指针。
以后在实际工作中,这两个的使用情况要具体问题具体分析
if和assert是两种不同的处理问题的态度,if相对比较温和,而assert就比较激烈。
1.在某次请求中,发现数据有问题,应当采用比较温和的方式,如果出现情况不至于影响到其他的请求处理,让咱们的代码能够具有一定的容错能力。
2.启动服务器过程中,发现服务器重载的数据有问题,加载的数据有问题很可能会影响到所有请求的计算过程,应当使用激烈的方式。
对常见问题分级的话:
1.FATAL:最高级别(致命的),遇到这种问题,应让程序立即崩溃。
2.ERROR:稍微低一点(错误),遇到这类问题,一般不会让程序崩溃,应该及时的提供报警信息。
3.WARNING:级别更低(警告),一般是一定时间内数量积攒到一定的值,此时也要及时通知。
4.INFO:级别最低,一般可以不视为问题。
5.NOTICE
6.DEBUG
7.TRACE…
进行判定时,里面要判定,外面也要判定,多人协作时,创建一个函数的人,在函数内部,入口部分要判定参数合法。调用函数的人也要判定参数合法。双重判定,双重保证。

二、strlen(求字符串长度)

size_t strlen(const char* str)

1.字符串已经’\0’作为结束标志,strlen函数返回的是在字符串中’\0’前面出现的字符个数(不包含’\0’)。
2.参数指向的字符必须要以’\0’结束。
3.注意函数的返回值为size_t,是无符号的。
size_t是一个typedef,相当于typedef unsigned long size_t;size_t一般都是一个8个字节的无符号整数,在标准库中用来表示“个数”,但其实引入size_t是一个不太明智的选择,size_t是无符号。所以尤其是在进行size_t之间相减的时候,非常容易溢出。例如1-2就会产生一个非常大的整数。
4.使用strlen必须是针对字符串。
代码如下(示例):

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
size_t myStrlen(const char* str) {
//主要有两种方式校验
//此处的校验只能校验空指针,不能校验野指针
//如果str不为空,而是一个其他的无效指针,从语法层面是无法识别的
	if (str == NULL) {
		return 0;
	}
//assert是一个断言,是一个宏
	assert(str != NULL);
//以上是两种校验的方法
	size_t size = 0;
	while (str[size] != '\0') {
		size++;
	}
	return size;
}
int main() {
	char* p = "abcd";
	printf("%d\n", myStrlen(p));
	system("pause");
	return 0;
}

三、strcpy(字符串复制)

在这里插入图片描述
代码如下(示例):

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
//只需要把src中的每个字节都赋值给dest即可
char* myStrcpy(char* dest, const char* src) {
	assert(dest != NULL);
	assert(src != NULL);
	int i = 0;
	while (src[i] != '\0') {
		dest[i] = src[i];
		i++;
	}
	dest[i] = '\0';
	return dest;
}
int main() {
	char dest[1024] = { 0 };
	char src[]= "hello";
	myStrcpy(dest, src);
	printf("%s\n", dest);
	system("pause");
	return 0;
}

假如主函数中对于dest的定义为
char* dest="xxxxxxxxx"这种是字符串常量,所属的内存区域是只读的。(这是由操作系统决定的)。
一个进程跑起来后,这个进程的内存空间整体来说可以大概分为这么几个区域
在这里插入图片描述
strcpy属于注意事项比较多的函数,C标准库中的字符串函数,都是dest在前,src在后,而C++标准库中的函数,是src在前,dest在后。


四、strcat

这个字符串函数的作用是把src所指向的字符串(包括“\0”)复制到dest所指向的字符串后面(删除*dest原来末尾的“\0”)。
别的语言进行字符串拼接,基本都是+。
例如:
a=“xxx”;
b=“yyy”;
a+b=>“xxxyyy”
同时要求dest指向的内存空间要足够的大,能够容纳拼接之后的结果。

在这里插入图片描述

代码如下(示例):

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
char* myStrcat(char* dest, const char* src) {
	assert(dest != NULL);
	assert(src != NULL);
	//1.找到dest的结束位置
	int destTail = 0;
	while (dest[destTail] != '\0') {
		destTail++;
	}
	//循环结束的时候,destTail变量就指向了dest的\0位置
	//2.把数据拷贝过来
	int i = 0;
	while (src[i] != '\0') {
		dest[destTail + i] = src[i];
		i++;
	}
	//3.把destTail最后的位置设为\0.
	dest[destTail + i] = '\0';
	return dest;
}
int main() {
	char dest[1024] = "hello ";
	char src[] = "world";
	myStrcat(dest, src);
	printf("%s\n", dest);
	system("pause");
	return 0;
}

结果:
在这里插入图片描述

五、strcmp(比较两个字符串的大小)

什么叫字符串的大小关系,字符串比较大小,规则有很多种,最常见的一种是字典序。从A到Z比较大小,A小Z大。我们之前最常用的是用strcmp比较字符串的相等。
strcmp就是按照字典序比较。
strcmp(a,b)
a<b => <0的整数
a>b => >0的整数
a==b => 0
同时需要说明,标准只是约定返回小于0或者大于0的数字,到底是不是-1,+1都不确定
在这里插入图片描述

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
int myStrcmp(const char* str1, const char* str2) {
	assert(str1 != NULL);
	assert(str2 != NULL);
	//依次比较每个字符之间的大小关系
	const char* p1 = str1;
	const char* p2 = str2;
	while (*p1 != '\0' && *p2 != '\0') {
		//比较p1和p2指向的字符的大小关系
		if (*p1 < *p2) {
			return -1;
		}
		else if (*p1 > *p2) {
			return 1;
		}
		else {
			//相等就比较下一个字符
			p1++;
			p2++;
		}
	}
	//假设p1初始指向的字符串是“abcd”
	//假设p2初始指向的字符串是“ab”
	//此时循环结束的时候p1还没到末尾,p2已经到末尾了
	//需要比较这个情况下的大小关系
	return *p1 - *p2;
}
int main() {
	char str1[] = "abcde";
	char str2[] = "abc";
	int ret = myStrcmp(str1, str2);
	if (ret > 0) {
		printf("str1>str2\n");
	}
	else if (ret < 0) {
		printf("str1<str2\n");
	}
	else {
		printf("str1=str2\n");
	}
	system("pause");
	return 0;
}

在这里插入图片描述

六、strncpy(将指定长度的字符串复制到字符数组)

strncpy诞生的目的,是为了避免dest空间不够的情况。假设dest总的空间为100,此时strncpy的num这个参数就可以填成99,就可以保证复制操作不会触发内存访问越界。实际开发中我们需要的结果是把字符串完整的拷贝过去,通过strncpy,限制长度,确实能够防止内存越界,但是很可能就只拷贝了一半(很有可能这也是一个bug)
strncpy的注意事项:
1.当num比src长的时候,会在后面额外补充上\0
2.当num比src短的时候,就只拷贝src的前num个字符(不会拷贝\0)
3.num的数值,必须要保证dest能够容纳下(要考虑\0)的情况
4.无论触发strncpy的哪种情况,都建议把dest初始化为全0。

七、strncmp(指定比较size个字符)

str1:abcde
str2:abcxy
size:3
视为str1和str2相等。
strncmp可以 用于判定某个字符串是否以另一个字符串开头

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dhdhdhdhg

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值