【C语言进阶】 字符函数和字符串函数

目录

 

前言

求字符串长度

strlen

模拟实现strlen

方式一

方式二 

方式三 

长度不受限制的字符串函数

strcpy

模拟实现 strcpy

strcat

模拟实现strcat 

strcmp

​编辑模拟实现strcmp 

长度受限制的字符串函数介绍

strncpy

strncat

strncmp

字符串查找

strstr

模拟实现strstr

strtok

错误信息报告

strerror

字符操作

字符分类函数

字符转换

 tolower()

toupper()


 

前言

本篇博文将讲解重点介绍处理字符和字符串的库函数的使用和注意事项。

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

求字符串长度

strlen

用于求取一个字符串的长度,使用格式如下

size_t strlen ( const char * str );
说明:字符串已经把'\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包含 '\0' ),参数指向的字符串必须要以 '\0'结束

 易错点分析:注意函数的返回值为size_t,是无符号的。这句话怎么理解呢?请看以下代码

#include <stdio.h>
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;
}

 上述代码中, strlen(str2) = 3 ; strlen(str1) = 6 。按照一般道理说,此时strlen(str2)-strlen(str1)应该小于0,应该输出str2>str1。那么结果真的是这样吗?我们看一下运行结果

e64d3ff30f034b38956b8710671fee0d.png

结果却是str2<str1。这是什么原因造成的呢?

是因为:函数的返回值为size_t,strlen(str2)-strlen(str1) = -3,-3在内存中的存储为下图所示

e1188840ee0b49b19b16f87866bef1a9.png

模拟实现strlen

模拟实现strlen,只需要遍历字符串,遇到'\0'停止就好

方式一

int my_strlen(const char * str)
{
     int count = 0;
     while(*str)
 {
     count++;
     str++;
 }
 return count;
}

方式二 

int my_strlen(const char * str)
{
 if(*str == '\0')
 return 0;
 else
 return 1+my_strlen(str+1);
}

方式三 

int my_strlen(char *s)
{
       char *p = s;
       while(*p != ‘\0’ )
              p++;
       return p-s;
}

长度不受限制的字符串函数

何为长度不受限制呢?也就是说在作用于字符串时,没有长度限制,遇'\0'停止

strcpy

用于拷贝字符串,使用格式如下

char* strcpy(char * destination, const char * source );

说明:1、源字符串必须以 '\0' 结束。 2、会将源字符串中的 '\0' 拷贝到目标空间。 3、目标空间必须足够大,以确保能存放源字符串。 4、目标空间必须可变。

23b0876ebe7e4d4e8f72b61217db8ff8.png

模拟实现 strcpy

char *my_strcpy(char *dest, const char*src)
{ 
 char *ret = dest;//记录的dest的首地址
 assert(dest != NULL);//断言,防止空指针
 assert(src != NULL);
 while((*dest++ = *src++))//一步步遍历,直至遇\0结束
 {
     ;
 }
 return ret;//首地址
}

strcat

实现字符串追加,将source里的字符串追加到destination后面,格式如下

char * strcat ( char * destination, const char * source );

说明:

1、源字符串必须以 '\0' 结束。

2、目标空间必须有足够的大,能容纳下源字符串的内容。

3 、目标空间必须可修改。

4、字符串不可以自己给自己追加

7d0ff2c362244931aa4a57881cf1752f.png

模拟实现strcat 

 只需要遍历destination到\0,然后再用source对destination里的0及以后的元素进行一一替换就好,最后还要加上source里的\0;代码实现如下

char *my_strcat(char *dest, const char*src)
{
 char *ret = dest;//记录起始位置
 assert(dest != NULL);//防止dest为空指针
 assert(src != NULL);
 while(*dest)
 {
 dest++;//使dest遍历到\0的位置
 }
 while((*dest++ = *src++))//进行一一替换,先++,所以\0也进行了替换了
 {
 ;
 }
 return ret;
}

strcmp

对两个字符串进行大小比较,格式如下

int strcmp ( const char * str1, const char * str2 );

说明 :两字符串比较是一位一位进行比较的,实际比较的是它们的ascll值。

第一个字符串大于第二个字符串,则返回大于0的数字

第一个字符串等于第二个字符串,则返回0

第一个字符串小于第二个字符串,则返回小于0的数字

a30d47d2e833461abb35005a5eba1ce3.png
模拟实现strcmp 

只需要两个元素一个个进行遍历比较就好,最后返回相应的值就可以了,代码如下
 
//int my_strcmp(const char* str1, const char* str2)
//{
//	assert(str1 && str2);//断言,不为空
//
//	while (*str1 == *str2)//进行判断,是否相等
//	{
//		if (*str1 == '\0')//判断是否字符串遍历结束
//			return 0;
//
//		str1++;//遍历
//		str2++;
//	}
//
//	return (*str1 - *str2);//返回值
//}

长度受限制的字符串函数介绍

长度限制也就是说作用于字符串时,可以限制其长度,再任意处停止

strncpy

可以规定拷贝的字符个数,格式如下

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

说明:

1、拷贝num个字符从源字符串到目标空间。

2、如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。

171c067276d64dee9ccdda25f80156e1.png

strncat

可以规定追加的长度,格式如下

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

说明:source所指向的字符串追加到 destination所指向的字符串的结尾,直到 n 字符长度为止。

6f7282dac34b4166b603744354936634.png

strncmp

可以选择所需要比较的长度,格式如下

int strncmp ( const char * str1, const char * str2, size_t num );

说明 比较到出现另个字符不一样或者一个字符串结束或者num个字符全部比较完。

183406abe3754c56809e801b7d3cc6ab.png

 

字符串查找

strstr

寻找一个字符串中含目标字符串的地址,格式如下

char * strstr ( const char *str1, const char * str2);

说明:

1、函数搜索一个字符串在另一个字符串中的第一次出现。

2、找到所搜索的字符串,则该函数返回第一次匹配的字符串的地址;

3、如果未找到所搜索的字符串,则返回NULL

604a2314bb394dc3a856409031843297.png

 应用如下

#include <stdio.h>
#include <string.h>
main()
{
    char *s="GoldenGlobalView";
    char *l="lob";
    char *p;
    p=strstr(s,l);
    if(p)
        printf("%s",p);
    else
        printf("NotFound!");
    return 0;
}

模拟实现strstr

char* my_strstr(char *str1, char* str2)

实现strstr我们我们需要对两个字符串进行比较,那么对于str1,我们每次遍历都需要一个起点,而对于str1与str2进行遍历时,我们也各自需要指针进行遍历,逻辑如下

70b086d293624ac483c827047dd80a45.png

 代码实现如下

//char* my_strstr(char *str1, char* str2)
//{
//	char* cp = str1;
//	char* s1 = cp;
//	char* s2 = str2;
//
//	if (*str2 == '\0')
//		return str1;
//
//	while (*cp)
//	{
//		//开始匹配
//		s1 = cp;
//		s2 = str2;
//		while (*s1 && *s2 && *s1 == *s2)
//		{
//			s1++;
//			s2++;
//		}
//		if (*s2 == '\0')
//			return cp;
//
//		cp++;
//	}
//
//	return NULL;
//}

strtok

分解字符串为一组字符串。str为要分解的字符,sep为分隔符字符,搭配头文件#include<string.h>使用,格式如下:

char * strtok ( char * str, const char * sep );

说明:

1、sep参数是个字符串,定义了用作分隔符的字符集合  

2、第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标

3、strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注: strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容 并且可修改。)

4、strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串 中的位置。

5、strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标
记。
6、如果字符串中不存在更多的标记,则返回 NULL 指针记。
使用如下
//int main()
//{
//	char arr[] = "zpengwei@yeah.net@666#777";
//	char copy[30];
//	strcpy(copy, arr);
//
//	char sep[] = "@.#";
//	char* ret = NULL;
//	char* ret = strtok(copy, sep);
//	printf("%s\n", ret);
//	
//	ret = strtok(NULL, sep);//在同一个字符串中被保存的位置开始,查找下一个标
记。
//	printf("%s\n", ret);
//
//	ret = strtok(NULL, sep);
//	printf("%s\n", ret);

上述代码有很大的局限性,而且使用起来不方便,下面代码博主进行了一些优化,代码如下

//	char arr[] = "zpengwei@yeah.net@666#777";
//	char copy[30];
//	strcpy(copy, arr);
//
//	char sep[] = "@.#";
//	char* ret = NULL;
//
//	for (ret = strtok(copy, sep); ret != NULL; ret=strtok(NULL, sep))//循环进行
//	{
//		printf("%s\n", ret);
//	}

这样以来就不用管分割几次了,交给循环来实现就好

注意:需要注意的是,使用该函数进行字符串分割时,会破坏被分解字符串的完整,调用前和调用后的str已经不一样了。第一次分割之后,原字符串str是分割完成之后的第一个字符串,剩余的字符串存储在一个静态变量中,因此多线程同时访问该静态变量时,则会出现错误。

错误信息报告

库函数在执行时,发生了错位,就会产生错误码,产生的错误码会存放在errno这个变量中,errno时C语言提供的全局变量

strerror

使用sterror可以对错误码进行一个打印,应用代码如下

int main()
{
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d: %s\n", i, strerror(i));//
	}
	return 0;
}

运行结果如下 

74fd5da087294f6c9954d6afd16fe2c4.png

也可将其应用至文件处,用于找出错误,并指出错误原因,简单运用代码如下

//int main()
//{
//	FILE* pf = fopen("data.txt", "r");
//	if (pf == NULL)
//	{
//		printf("fopen: %s\n", strerror(errno));
//		perror("fopen");
//		//fopen: xxxxxx
//		return 1;
//	}
//	fclose(pf);
//	return 0;
//}

字符操作

字符分类函数

函数
如果他的参数符合下列条件就返回真
iscntrl
任何控制字符
isspace
空白字符:空格‘ ’,换页‘\f’,换行'\n',回车‘\r’,制表符'\t'或者垂直制表符'\v'
isdigit
十进制数字 0~9
isxdigit
十六进制数字,包括所有十进制数字,小写字母a~f,大写字母A~F
islower
小写字母a~z
isupper
大写字母A~Z
isalpha
字母a~z或A~Z
isalnum
字母或者数字,a~z,A~Z,0~9
ispunct
标点符号,任何不属于数字或者字母的图形字符(可打印)
isgraph
任何图形字符
isprint
任何可打印字符,包括图形字符和空白字符

字符转换

 tolower()

tolower()函数是把字符串都转化为小写字母。格式如下

int tolower ( int c );

使用如下

string str= "THIS IS A STRING";
for (int i=0; i <str.size(); i++)
   {
   str[i] = tolower(str[i]);
   }

toupper()

toupper()函数是把字符串都转化为大写字母。格式如下
int toupper ( int c );

使用如下

string str= "hahahahaha";
for (int i=0; i <str.size(); i++)
   str[i] = toupper(str[i]);

字符函数与字符串函数至此就讲解完毕了,请关注博主后续对内存函数的讲解。

记得三连哦!!!

 

 

 

  • 24
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 19
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

遇事问春风乄

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

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

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

打赏作者

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

抵扣说明:

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

余额充值