C:字符函数与字符串函数-学习笔记

news2024/9/21 17:59:20

目录

1、字符分类函数

2、字符转换函数

3、字符串函数

4、strlen 函数的使用与模拟实现

4.1 strlen函数的使用

4.2 strlen函数的模拟实现


1、字符分类函数

C语言中有一系列的函数是专门做字符分类的,也就是一个字符是属于什么类型的字符的。 这些函数的使用都需要包含一个头文件是 ctype.h

函数如果他的参数符合下列条件就返回真(非零值)
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任何可打印字符,包括图形字符和空白字符

由于字符分类函数较多,且这些函数的使用方式也都相同,因此在这里小编就只对其中某一些进行介绍来帮助大家简单了解一下这些函数的使用方式,如果想要对它们有更详细的了解,可以进入c++官网查看,点击上面表格中函数名即可!

我们怎么判断输入的字符是小写字符还是大写字符呢?这里就可以使用到 islowerisupper 这两姐妹了。

我们来看cplusplus  对妹妹 islower 的介绍:

从上图中我们能得到什么信息呢?islower的作用是判断输入字符是否为小写字母,并通过返回值告诉我们结果,如果是小写字母,则返回值为非零值,如果不是小写字母,则返回值是0。

接下来小编将用代码来带大家深入了解islower的作用及使用方式。

#include <stdio.h>
#include <ctype.h>
int main()
{
	int ret = islower('A');
	printf("%d\n", ret);
	return 0;
}

由于A不是小写字母,所以我们得到的返回值是0。

那我们可以怎么使用 islower 这个函数呢?

#include <stdio.h>
#include <ctype.h>
int main()
{
	int ret = islower('A');
	//printf("%d\n", ret);
	if (ret)
		printf("小写");
	else
		printf("大写");
	return 0;
}

为什么这么写呢?如果Islower判断的字符是大写,则会返回0,0为假,则执行else语句。 

如果输入的是小写字母

如果我们想判断是否为数字字符该怎么办,可以使用 isdigit 函数

#include <stdio.h>
#include <ctype.h>
int main()
{
	int ret = isdigit('x');
	printf("%d\n", ret);
	return 0;
}

如果它是数字字符的话,会返回非零值,如果是数字字符的话,会返回0,我们来判断一下

其它的字符分类函数使用方式皆是如此,因此就不一一介绍了。

这些函数也是可以组合使用的,可以根据个人情况来使用。

练习:写一个函数,将字符串中的小写字符转大写,其它字符不变。

字符串"Hello China“,将里面的小写字符都转为大写。

int main()
{
	char arr[20] = "Hello China";
	//下标i         01234567……  
	//遍历数组arr
	int i = 0;
	while (arr[i])//这里条件是arr[i]是因为字符串末尾有\0,当遍历到\0的时候,0为假,循环结束
	{
		if (islower(arr[i]))
		{
			//小写字母与大写字母的ASCLL值对应位置相差32
			//a-97 A-65
			arr[i] = arr[i] - 32;
		}
		i++;
	}
	printf("%s\n", arr);
	return 0;
}

这里就完成了,这也就是islower函数的具体应用。

不过呢!接下来我们将学习两个函数来帮助我们进行大小写字母的转换

2、字符转换函数

C语言提供了两个字符转换函数:

int tolower(int c);//将参数传进去的大写字母转小写
int toupper(int c);//将参数传进去的小写字母转大写

在前面我们的那道例题中,我们将小写转大写是借助了ASCLL值大小写字母相差32的特点来转换的,但是有了字符转换函数,我们就可以直接使用toupper函数了。

int main()
{
    char arr[20] = "Hello China";
    int i = 0;
    while (arr[i])
    {
        if (islower(arr[i]))
        {
            arr[i] = toupper(arr[i]);
        }
        i++;
    }
    printf("%s\n", arr);
    return 0;
}

到这里我们也就介绍清楚字符分类函数和字符转换函数了。关于这些函数,只有多多练习,才能够掌握的更加牢靠。

3、字符串函数

字符串函数有strlen,strcpy,strcat,strcmp,strncpy,strncat,strncmp,strstr,strtok,strerr共十个函数,我们将这十个函数分为四类。

接下来会分别介绍。这些函数所需要的头文件是string.h

4、strlen函数的使用与模拟实现

4.1 strlen函数的使用

sizt_t strlen(const char* str);

关于strlen函数,想必大家应该不会很陌生吧!虽然没有系统的介绍过这个函数,但是这个函数在小编前面的文章中也是多次出现,算是老熟人了。这次会带大家详细了解一下这个函数。

该函数的类型是size_t,参数是字符串str,返回值是字符串的长度。

那么该函数该怎么使用呢?

#include <stdio.h>
#include <string.h>
int main()
{
	char arr[] = "abcdef";
	size_t len = strlen(arr);
	printf("%zd\n", len);
	return 0;
}

我们可以得到字符数组arr的长度通过strlen函数

对于size_t类型的数据,打印使用 %zd 占位符。

这就是strlen函数的作用,它可以求一个字符串长度,并返回一个值来表示。

strlen函数的工作原理是什么呢?

我们知道字符串"abcdef"中放着a b c d e f \0字符

arr是数组名,数组名表示首元素地址,也就是说我们从首元素地址开始传字符给strlen;

因此这里strlen(arr)统计的是从首元素到 \0之前的字符个数,所以这里返回的结果是6。

所以我们可以知道strlen函数的工作原理是—从给定的起始位置开始,向后统计\0之前的字符个数。

这里为什么说是从给定的起始位置开始统计呢?

我们可以来测试一下

int main()
{
	char arr[] = "abcdef";
	size_t len = strlen(arr+1);
	printf("%zd\n", len);
	return 0;
}

arr表示的是数组首元素地址,那么arr+1则表示第二个元素的地址。

我们可以看到此时返回的结果就是5,所以说起始位置很重要。strlen函数统计字符串的长度是从给定的起始位置开始统计,直到遇到'\0'。

注意:strlen函数的返回值位size_t,是无符号的

来看下面这个例子,该代码的输出结果是什么?

int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abc";
	if (strlen(arr2) - strlen(arr1) > 0)
		printf(">\n");
	else
		printf("<\n");
	return 0;
}

上面例子中,我们可以知道字符串arr1的长度是6,字符串arr2的长度是3,根据数学上来说,该代码最后输出的应该是 < 号,来看一下结果

 这里为什么会输出 > 号呢?

这是因为strlen(arr2) 的返回值是size_t, strlen(arr1)的返回值也是size_t,这样我们得到的结果也是size_t类型,从数学上3 - 6 我们得到的是-3,size_t是无符号类型

-3的原码是:10000000000000000000000000000011

反码是:       111111111111111111111111111111111100

补码是:       111111111111111111111111111111111101

由于size_t是无符号类型,所以当我们把-3存入内存中的时候,-3的补码的首位就不会被认为是符号位,既然如此,111111111111111111111111111111111101就是一个非常大的正数。这个数肯定会大于0,所以最终打印出来的结果是 > 

我们如何才能比较这两个的大小呢?

直接将两个数进行相比即可 if (strlen(arr2) >  strlen(arr1) )

如果非要相减进行比较,就可以使用强制类型转换,将它两转换成int类型。

4.2 strlen函数的模拟实现

int main()
{
	char arr[] = "abcdef";
	size_t len = my_strlen(arr);
	return 0;
}

关于这个返回类型为什么使用size_t,可能有些人会有些疑惑,这里统一说一下,由于strlen函数是求字符串函数的长度的,返回值用来表示字符串的长度,既然是表示长度的,那么就不可能会是负数,因此,这里使用size_t会更加合适。

size_t my_strlen(const char* str)

这里我们不希望str能够改变所要求长度的字符串,因此使用const修饰一下。

接下来使用两种方式来模拟实现strlen函数。

1- 计数器

#include <stdio.h>
#include <string.h>
#include <assert.h>
size_t my_strlen(const char* str)
{
	size_t count = 0;
	assert(str != NULL);//防止是空指针
	while (*str)//这里*str作为条件是因为最终会读取到\0终止循环
	{
		count++;
		str++;
	}
	return count;
}
int main()
{
	char arr[] = "abcdef";
	size_t len = my_strlen(arr);
	printf("%zd\n", len);
	return 0;
}

 2- 指针- 指针

#include <stdio.h>
#include <string.h>
#include <assert.h>
size_t my_strlen(const char* str)
{ 
    char* start = str;// 记录字符串的起始位置
    assert(str != NULL);
 
    while (*str)
    {
        str++;
    }
    return str - start; // 通过当前指针位置减去起始位置得到字符串的长度
}
int main()
{
    char arr[] = "abcdef";
    size_t len = my_strlen(arr);
    printf("%zd\n", len);
    return 0;
}

3-递归

关于递归,我们首先想到的便是大事化小

那什么叫大事化小呢?

代码实现:

#include <stdio.h>
#include <string.h>
#include <assert.h>
size_t my_strlen(const char* str)
{ 
    if (*str == '\0')//如果开始就是\0,则说明该字符串长度为0
        return 0;
    else
        1 + my_strlen(str + 1);
}
int main()
{
    char arr[] = "abcdef";
    size_t len = my_strlen(arr);
    printf("%zd\n", len);
    return 0;
}

 结语:本篇文章到这里就结束了,下一篇文章将会介绍完所有的字符串函数,期待大家的到来!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2127372.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue(10)——自定义指令

自定义指令 自定义指令&#xff1a;可以封装一些dom操作&#xff0c;扩展额外功能。 全局注册-语法&#xff1a; Vue.directive(指令名,{ "inserted"(el){ inserted指指令所绑定的元素被添加到页面时自动调用 //可以对el标签扩展额外功能 el.focus() } }) 局部…

基于python+django+vue+MySQL的酒店推荐系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】pythondjangovueMySQL的酒店推…

NLP中文本生成任务

文本生成任务 1.生成式任务2.自回归模型实现3.Encoder-Decoder结构3.1Attention机制出现3.2Attention思想3.3soft - Attention3.4hard - Attention3.5Teacher Forcing3.6详解Mask Attention3.6.1通过Mask控制训练方式 4.生成式任务评价指标5.生成式任务常见问题5.1采样策略5.2指…

深入解析Java内存模型:从堆到栈的全面剖析

在Java程序运行的背后&#xff0c;JVM&#xff08;Java Virtual Machine&#xff0c;Java虚拟机&#xff09;负责管理和分配内存。理解Java的内存模型&#xff08;Java Memory Model, JMM&#xff09;是编写高效、稳定程序的关键&#xff0c;尤其在并发编程中&#xff0c;内存管…

rose 聊开源—2 如何快速上手一个开源项目

在前面的一篇开源项目系列中&#xff0c;主要介绍了目前开源项目蓬勃发展的态势&#xff0c;并且拥有一个开源项目&#xff0c;对我们个人履历、职业发展等都有非常多的好处。 这一次就来跟大家分享一下&#xff0c;面对一个开源项目&#xff0c;我们应该如何上手&#xff0c;快…

【Android笔记】Android Studio打包 提示Invalid keystore format

前言 Android项目通过Android Studio生产签名文件进行打包。提示 com.android.ide.common.signing.KeytoolException: Failed to read key hocsdn from store "/Users/ho/TestProject/app/ho_developer.jks": Invalid keystore format 不合法的签名文件格式&#…

在职研生活学习--20240907

开学第一天 9月7日&#xff0c;中南大学商学院迎来了一支充满活力的队伍——2024级MBA新生集体整装待发&#xff0c;我们满怀期待地登上了前往长沙望城柏乐园的大巴&#xff0c;准备开启一场为期两天一夜的素质拓展与团队建设之旅。 迎新幼儿园PPT 出发 抵达柏乐园&#xff0c;…

Android生成Java AIDL

AIDL:Android Interface Definition Language AIDL是为了实现进程间通信而设计的Android接口语言 Android进程间通信有多种方式&#xff0c;Binder机制是其中最常见的一种 AIDL的本质就是基于对Binder的运用从而实现进程间通信 这篇博文从实战出发&#xff0c;用一个尽可能…

openssl的使用

1、编译 Github下载&#xff1a;https://github.com/openssl/openssl 官网下载&#xff1a;https://openssl-library.org/source/index.html 官网历史版本&#xff1a;https://www.openssl.org/source/old/ 1.1 Windows下编译 我的文章&#xff1a;OPC UA使用 Openssl库编译…

Golang | Leetcode Golang题解之第398题随机数索引

题目&#xff1a; 题解&#xff1a; type Solution []intfunc Constructor(nums []int) Solution {return nums }func (nums Solution) Pick(target int) (ans int) {cnt : 0for i, num : range nums {if num target {cnt // 第 cnt 次遇到 targetif rand.Intn(cnt) 0 {ans …

移动跨平台框架Flutter详细介绍和学习线路分享

Flutter是一款移动应用程序SDK&#xff0c;一份代码可以同时生成iOS和Android两个高性能、高保真的应用程序。 Flutter目标是使开发人员能够交付在不同平台上都感觉自然流畅的高性能应用程序。我们兼容滚动行为、排版、图标等方面的差异。 在全世界&#xff0c;Flutter正在被越…

基于SpringBoot+Vue+MySQL的滑雪场管理系统

系统展示 用户前台界面 管理员后台界面 系统背景 在快速发展的冰雪运动热潮下&#xff0c;为了提升滑雪场的管理效率与顾客体验&#xff0c;我们设计并实现了一套基于SpringBoot后端框架、Vue前端框架以及MySQL数据库的滑雪场管理系统。该系统旨在通过数字化手段&#xff0c;优…

(pandas读取DataFrame列报错)raise KeyError(key) from err KeyError: (‘name‘, ‘age‘)

&#xff08;pandas读取DataFrame列报错&#xff09;raise KeyError(key) from err KeyError: (‘name‘, ‘age‘) 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页&#xff0c;我是博主英杰&#xff0c;211科班出身&#xff0c;就职于医疗科技公司&…

瑞吉外卖—读写分离

文章目录 1. 概述2. MySQL主从复制2.1 介绍2.1 配置2.1.1 前置条件2.1.2 主库Master2.1.3 从库Slave 3. 读写分离案例3.1 背景3.2 Sharding-JDBC介绍3.3 入门案例 1. 概述 读写分离、主从复制。就是dml操作在主库、query操作在备份的从库。分担压力&#xff0c;减轻单点故障。…

标准库标头 <barrier>(C++20)学习

此头文件是线程支持库的一部分。 类模板 std::barrier 提供一种线程协调机制&#xff0c;阻塞已知大小的线程组直至该组中的所有线程到达该屏障。不同于 std::latch&#xff0c;屏障是可重用的&#xff1a;一旦到达的线程组被解除阻塞&#xff0c;即可重用同一屏障。与 std::l…

django自用教程

编程软件: pycharm django介绍:django是Pythonweb的一个框架&#xff0c;是用来构建网站的工具。 要想使用django&#xff0c;首先需要下载django模块&#xff0c;通过使用以下代码实现: pip install django 安装完成后&#xff0c;在django的目录下有一个文件django-admin&am…

Docker启动Mysql镜像报错问题?

docker中启动mysql镜像报错如下&#xff1a;ls: cannot access /docker-entrypoint-initdb.d/: Operation not permitted 百度上查到了很多解决方案&#xff0c;也咨询了很多大佬&#xff0c;加权限&#xff0c;改用户&#xff0c;均无果。最终在阿里巴巴上找到了解决方案&…

【有啥问啥】深入理解数据结构 Merkle 树:数据完整性保障的基石

深入理解 Merkle 树&#xff1a;数据完整性保障的基石 在当今的分布式系统和区块链应用中&#xff0c;数据的完整性验证变得至关重要。随着区块链技术、分布式存储系统&#xff08;如 IPFS&#xff09;、以及版本控制系统&#xff08;如 Git&#xff09;的大规模应用&#xff…

【Linux】文件权限与类型全解:你的文件安全指南

欢迎来到 CILMY23 的博客 &#x1f3c6;本篇主题为&#xff1a;文件权限与类型全解&#xff1a;你的文件安全指南 &#x1f3c6;个人主页&#xff1a;CILMY23-CSDN博客 &#x1f3c6;系列专栏&#xff1a;Python | C | C语言 | 数据结构与算法 | 贪心算法 | Linux | 算法专题…

kubectl 命令介绍以及使用

文章目录 kubectl 基本命令查看集群信息管理命名空间操作节点 操作 Pods查看 Pods 状态创建和删除 Pods调试 Pods 操作 Deployments创建 Deployment更新 Deployment回滚 Deployment 操作 Services暴露服务查看服务状态 更多 kubectl 命令资源描述资源过滤日志查看配置上下文和切…