C语言进阶第六课-----------字符分类函数和内存的开辟

本文主要是介绍C语言进阶第六课-----------字符分类函数和内存的开辟,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

作者前言

🎂 ✨✨✨✨✨✨🍧🍧🍧🍧🍧🍧🍧🎂
​🎂 作者介绍: 🎂🎂
🎂 🎉🎉🎉🎉🎉🎉🎉 🎂
🎂作者id:老秦包你会, 🎂
简单介绍:🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂
喜欢学习C语言和python等编程语言,是一位爱分享的博主,有兴趣的小可爱可以来互讨 🎂🎂🎂🎂🎂🎂🎂🎂
🎂个人主页::小小页面🎂
🎂gitee页面:秦大大🎂
🎂🎂🎂🎂🎂🎂🎂🎂
🎂 一个爱分享的小博主 欢迎小可爱们前来借鉴🎂


字符和内存

  • **作者前言**
  • 字符分类函数
    • iscntrl
    • isspace
    • isdigit
    • isxdigit
    • islower
    • isupper
    • isalpha
    • isalnum
    • ispunct
    • isgraph
    • isprint
  • 字符转换
    • toupper
    • tolower
  • 内存相关函数
    • memcpy
    • memove
    • memset
    • memcmp
  • 总结

字符分类函数

iscntrl

在这里插入图片描述
判断对应的ASCII值所对应的字符是否为控制字符
在ASCII码中,第0~31号及第127号(共33个)是控制字符或通讯专用字符,
如果 c 确实是控制字符,则与零(即 true)不同的值。否则为零(即假)。(是控制字符返回非0,不是就返回0)

#include<stdio.h>
#include<string.h>
#include<ctype.h>
int main()
{int i = 0; for (i = 0; i < 50; i++){if (iscntrl(i))printf(" %d %c:是控制字符\n", i, i + 1);elseprintf("%d %c:不是控制字符\n", i, i + 1);}return 0;
}

isspace

判断是否为空白字符
空白字符:空格‘ ’,换页‘\f’,换行’\n’,回车‘\r’,制表符’\t’或者垂直制表符’\v’
在这里插入图片描述
如果 c 确实是一个空格字符。返回非0(true), 否则为零(即假)。
在这里插入图片描述

#include<stdio.h>
#include<string.h>
#include<ctype.h>
int main()
{int i = 9;printf("%d", isspace(i));return 0;
}

isdigit

判断字符是否是0-9

#include<stdio.h>
#include<string.h>
#include<ctype.h>
int main()
{int ch;ch = getchar();if (isdigit(ch)){printf("%c是数字", ch);}else{printf("NO");}return 0;
}

在这里插入图片描述
十进制数字是以下任意一种: 0 1 2 3 4 5 6 7 8 9 有

isxdigit

判断字符是否为十六进制的字母(包含大小写)和数字
十六进制数字是以下任意一种: 0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F
在这里插入图片描述
是十六进制数就返回非0的数字,否则就返回0;

#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<stdlib.h>
int main()
{int i = 48;for (; i < 128; i++){if (isxdigit(i)){printf("%c\n", i);}}return 0;
}

在这里插入图片描述

islower

在这里插入图片描述
小写字母是以下任意字母:a b c d e f g h i j k l m n o p q r s t u v w x y z。
如果是小写字母就返回非0的数字,否则就返回0

#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<stdlib.h>
int main()
{int i = 97;for (; i <= 122; i++){if (islower(i)){printf("%c\n", i);}}return 0;
}

isupper

判断字符是否是大写字母
在这里插入图片描述
大写字母为以下任意字母:A B C D E F G H I J K L M N O P Q R S T U V W X Y Z。
如果是大写字母就返回非0的数字,否则就返回0

#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<stdlib.h>
int main()
{int i = 65;for (; i <= 95; i++){if (isupper(i)){printf("%c\n", i);}}return 0;
}

isalpha

判断字符是否为字母(包含大小写)
在这里插入图片描述
如果是字母就返回非0的数字,否则就返回0

#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<stdlib.h>
int main()
{int i = 65;for (; i <= 122; i++){if (isalpha(i)){printf("%c\n", i);}}return 0;
}

isalnum

判断字符是否是字母或者数字
如果是字母或者是数字就返回非0的数字,否则就返回0
在这里插入图片描述

#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<stdlib.h>
int main()
{int i = 48;for (; i <= 122; i++){if (isalnum(i)){printf("%c\n", i);}}return 0;
}

ispunct

在这里插入图片描述
检查字符是否为标点字符
如果是标点字符就返回非0的数字,否则就返回0
在这里插入图片描述

#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<stdlib.h>
int main()
{printf("%d", ispunct('"'));return 0;
}

isgraph

在这里插入图片描述
判断字符是否具有图形表示
具有图形表示的字符是除空格字符 (’ ') 之外的所有可以打印的字符(由 isprint 确定)。

#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<stdlib.h>
int main()
{char arr[] = "abcdefg k";char* pa = arr;while (*pa){if (isgraph(*pa)){printf("%c", *pa);}pa++;}return 0;
}

isprint

在这里插入图片描述
检查 c 是否为可打印字符
可打印字符是在显示器上占据打印位置的字符(这与控制字符相反,使用 iscntrl 检查)。

#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<stdlib.h>
int main()
{char arr[] = "abcdefg k";char* pa = arr;while (*pa){if (isprint(*pa)){printf("%c", *pa);}pa++;}return 0;
}

注意这里空格也是符合条件的

字符转换

前面我们只是理解了判断字符,如果要转换字符也有对应的库函数

toupper

在这里插入图片描述
小写字母是以下任意字母:a b c d e f g h i j k l m n o p q r s t u v w x y z,分别翻译为:A B C D E F G H I J K L M N O P Q R S T U V W X Y Z。

#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<stdlib.h>
int main()
{int i = 97;for (; i <= 122; i++){printf("%c\n", toupper(i));}return 0;
}

如果是小写就转换,不是就不转换

tolower

同理这个函数就是把大写转换成小写

#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<stdlib.h>
int main()
{int i = 65;for (; i <= 90; i++){printf("%c\n", tolower(i));}printf("%c\n", tolower('a'));return 0;
}

如果是大写就转换,不是就不转换

内存相关函数

memcpy

前面我们已经学习过了strcpy,这个函数只适合于字符串拷贝,如果要拷贝整数数组,浮点型数组就会没办法,但是memcpy就可以解决

在这里插入图片描述
这个函数有三个参数,一个是目标空间,一个是起始地址,以及要拷贝的字节总大小
如果看过我模拟出来的qsrot函数就会明白,这里为啥要拷贝字节总大小,我们只把对应的字节大小进行拷贝过去

include<stdio.h>int main()
{int arr[20] = { 1,2,3,4,5,6,7,8,9 };int arr1[10] = { 0 };memcpy(arr1, arr, sizeof(int) * 9);int i = 0;for (i = 0; i < 10; i++){printf("%d ", arr[i]);}return 0;
}

如果我们要模拟实现出来

#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<stdlib.h>
#include<assert.h>void* my_memcpy(void* destintion, const void* soured, size_t num)
{//不为空assert(destintion && soured);//一个一个字节进行拷贝,要使用char*, 加1访问一个字节const char* su = soured;char* de = destintion;while (num){*de++ = *su++;num--;}return destintion;
}int main()
{char arr[20] = "abcd\0f";char arr1[10] = { 0 };my_memcpy(arr1, arr, sizeof(arr[0]) * 10);int i = 0;for (i = 0; i < 10; i++){printf("%c ", arr1[i]);}return 0;
}

如果当我们使用这个模拟函数进行自身部分的拷贝就会发现,和库函数memcpy有差异

#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<stdlib.h>
#include<assert.h>
int main()
{int arr[20] = {1,2,3,4,5,6,7,8,9};memcpy( arr + 2, arr, sizeof(arr[0]) * 5);int i = 0;for (i = 0; i < 10; i++){printf("%d ", arr[i]);}return 0;
}

库函数的结果
在这里插入图片描述
我们模拟函数的结果:
在这里插入图片描述
可以看出两者的差异
看到这里就会有疑问,是不是模拟错了?
其实标准值规定,memcpy来实现不重叠的内存拷贝,而重叠的内存拷贝一般不使用memcpy而是使用memmove,就好比我们考试只需考60分,90分就要其他人去考吧,而我们却发现memcpy连重叠的拷贝也能做到,这就是超预期了,而我们模拟出来的函数只是具备了拷贝不重叠的内存拷贝功能,vs的库函数memcpy两者具备,但是在一些编译器里就会不一定两种功能都有。

memove

在这里插入图片描述
从这里可以看出memmove函数的参数和memcpy是一样的,所以memove函数具备了memcpy的所有功能

#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<stdlib.h>
#include<assert.h>
int main()
{int arr[] = { 1,2,3,4,5,6,7,8,9 };int arr1[10] = { 0 };memmove(arr1, arr, sizeof(arr[0]) * 9);return 0;
}

我们来模拟一下
在这里插入图片描述
如果模拟这个函数很容易就会把memcpy的功能加上重叠的功能,重叠的方法很多人就会想到我要重新开辟一块临时空间存放和arr一样的,然后进行一一的拷贝,然后再覆盖原来的arr,这个方法是可行的,但是这样很麻烦,那有没有在一个数组内就可以进行拷贝呢?答案是有的
如上图
如果我们要3-7拷贝到1-5的位置上去,我们可以先把3拷贝到1然后依次往下,就可以解决原来数字被覆盖的问题,
如果我们要把1-5拷贝到5-9的位置我们就先拷贝5到9的位置上去,往后依次往前

#include<stdio.h>
void* my_memmove(void* arr1, const void* arr, size_t num)
{char* pa1 = arr1;const char* pa = arr;// 后往前拷贝if (pa1 > pa){pa1 += num - 1;pa += num - 1;while (num){*pa1 = *pa;pa1--;pa--;num--;}}else{//前往后拷贝while (num){*pa1 = *pa;pa1++;pa++;num--;}}return arr1;
}int main()
{int arr[] = { 1,2,3,4,5,6,7,8,9 };int arr1[10] = { 0 };my_memmove(arr, arr + 2, sizeof(arr[0]) * 5);return 0;
}

这里我们要注意一下数组arr的第n个元素的地址是arr+(n - 1)

memset

在这里插入图片描述
填充内存块
把从ptr开始的num个字节填充为value

#include<stdio.h>
#include<string.h>
int main()
{char arr[] = "abcdefg";memset(arr, 't', 5);printf("%s", arr);return 0;
}

结果为:
在这里插入图片描述
所以我们可以认为memset是以字节为单位的进行设置的,如果不相信,下面为例

#include<stdio.h>
#include<string.h>
int main()
{int arr[10] = { 0 };memset(arr, 1, 40);int i = 0;for (i = 0; i < 10; i++){printf("%d ", arr[i]);}return 0;
}

结果为:
在这里插入图片描述
在这里插入图片描述
这里就是arr里面 存储的内存,我们的想法是把arr每个元素设置成1,而结果却不对,memset是以字节为单位进行设置的,需要注意一下,在vs是小端存储(高阶数存放在低地址) 结果为01010101
如果我们要模拟实现就是

#include<stdio.h>
#include<string.h>
void* my_memset(void* ptr, int value, size_t num)
{char* pr = ptr;while (num){*pr = value;pr++;num--;}return ptr;
}int main()
{char arr[] = "abcdefghij";int arr1[5] = { 0 };my_memset(arr, '0', sizeof(arr[0]) * 5);return 0;
}

memcmp

在这里插入图片描述
比较两个内存块的内容

#include<stdio.h>
#include<string.h>
int main()
{int arr1[] = { 1,2,3,4,5,6,7,8,9 };// 数组的存储方式:01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 06 00 00 00 07 00 00 00 08 00 00 00 09 00 00 00int arr[] = { 1,2,3,6 };// 数组的存储方式:01 00 00 00 02 00 00 00 03 00 00 00 06 00 00 00printf("%d", memcmp(arr, arr1, 16));return 0;
}

在这里插入图片描述
简单的理解,和strcmp的比较方式是一样的,一旦匹配到不相等的内存就会返回
如果不相信还有一个例子

#include<stdio.h>
#include<string.h>
int main()
{int arr1[] = { 1,2,3,4,5,6,7,8,9 };// 数组的存储方式:01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 06 00 00 00 07 00 00 00 08 00 00 00 09 00 00 00int arr[] = { 1,2,3,0x11223301};// 数组的存储方式:01 00 00 00 02 00 00 00 03 00 00 00 01 33 22 11printf("%d", memcmp(arr, arr1, 16));return 0;
}

我们来模拟一下

#include<stdio.h>
#include<string.h>
int my_memcmp(const void* ptr1, const void* ptr2, size_t num)
{while (num){if (*((char*)ptr1) == *((char*)ptr2)){ptr1 = (char*)ptr1 + 1;ptr2 = (char*)ptr2 + 1;}else{return *((char*)ptr1) - *((char*)ptr2);}}return 0;}
int main()
{int arr[] = { 1,2,3,4,5,6,7,8,9 };int arr1[] = { 1,2,3,4,5,0x11223306 };int num = my_memcmp(arr1, arr, 6);printf("%d", num);return 0;
}

总结

到这里字符串相关的函数就学习完了,有不懂的可以私聊我

这篇关于C语言进阶第六课-----------字符分类函数和内存的开辟的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/216576

相关文章

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

基于人工智能的图像分类系统

目录 引言项目背景环境准备 硬件要求软件安装与配置系统设计 系统架构关键技术代码示例 数据预处理模型训练模型预测应用场景结论 1. 引言 图像分类是计算机视觉中的一个重要任务,目标是自动识别图像中的对象类别。通过卷积神经网络(CNN)等深度学习技术,我们可以构建高效的图像分类系统,广泛应用于自动驾驶、医疗影像诊断、监控分析等领域。本文将介绍如何构建一个基于人工智能的图像分类系统,包括环境

NameNode内存生产配置

Hadoop2.x 系列,配置 NameNode 内存 NameNode 内存默认 2000m ,如果服务器内存 4G , NameNode 内存可以配置 3g 。在 hadoop-env.sh 文件中配置如下。 HADOOP_NAMENODE_OPTS=-Xmx3072m Hadoop3.x 系列,配置 Nam

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

认识、理解、分类——acm之搜索

普通搜索方法有两种:1、广度优先搜索;2、深度优先搜索; 更多搜索方法: 3、双向广度优先搜索; 4、启发式搜索(包括A*算法等); 搜索通常会用到的知识点:状态压缩(位压缩,利用hash思想压缩)。

hdu1171(母函数或多重背包)

题意:把物品分成两份,使得价值最接近 可以用背包,或者是母函数来解,母函数(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v) 其中指数为价值,每一项的数目为(该物品数+1)个 代码如下: #include<iostream>#include<algorithm>

科研绘图系列:R语言扩展物种堆积图(Extended Stacked Barplot)

介绍 R语言的扩展物种堆积图是一种数据可视化工具,它不仅展示了物种的堆积结果,还整合了不同样本分组之间的差异性分析结果。这种图形表示方法能够直观地比较不同物种在各个分组中的显著性差异,为研究者提供了一种有效的数据解读方式。 加载R包 knitr::opts_chunk$set(warning = F, message = F)library(tidyverse)library(phyl

透彻!驯服大型语言模型(LLMs)的五种方法,及具体方法选择思路

引言 随着时间的发展,大型语言模型不再停留在演示阶段而是逐步面向生产系统的应用,随着人们期望的不断增加,目标也发生了巨大的变化。在短短的几个月的时间里,人们对大模型的认识已经从对其zero-shot能力感到惊讶,转变为考虑改进模型质量、提高模型可用性。 「大语言模型(LLMs)其实就是利用高容量的模型架构(例如Transformer)对海量的、多种多样的数据分布进行建模得到,它包含了大量的先验

[MySQL表的增删改查-进阶]

🌈个人主页:努力学编程’ ⛅个人推荐: c语言从初阶到进阶 JavaEE详解 数据结构 ⚡学好数据结构,刷题刻不容缓:点击一起刷题 🌙心灵鸡汤:总有人要赢,为什么不能是我呢 💻💻💻数据库约束 🔭🔭🔭约束类型 not null: 指示某列不能存储 NULL 值unique: 保证某列的每行必须有唯一的值default: 规定没有给列赋值时的默认值.primary key:

【Linux 从基础到进阶】Ansible自动化运维工具使用

Ansible自动化运维工具使用 Ansible 是一款开源的自动化运维工具,采用无代理架构(agentless),基于 SSH 连接进行管理,具有简单易用、灵活强大、可扩展性高等特点。它广泛用于服务器管理、应用部署、配置管理等任务。本文将介绍 Ansible 的安装、基本使用方法及一些实际运维场景中的应用,旨在帮助运维人员快速上手并熟练运用 Ansible。 1. Ansible的核心概念