进阶C语言第三章-------《字符函数和内存函数》 完整思维导图+基本练习题+深入细节+通俗易懂+知识点+建议收藏

news2024/11/24 7:42:21

绪论

        书接上回,通过进阶指针你已经了解到了更多种指针类型,他们的用法及使用之处相当的关阔需要不断的积累经验来使用,这里我毛遂自荐一下我的指针练习希望对你有帮助,本章是一些关于字符串的函数介绍和自己实现,总体来说学会了这些函数可以对你在字符串类型的编程有很大的意义。

所以安全带系好,发车啦(建议电脑观看)。

        附:红色,部分为重点部分;蓝颜色为需要记忆的部分(不是死记硬背哈,多敲);黑色加粗或者其余颜色为次重点;黑色为描述需要

思维导图:

 

要XMind思维导图的话可以私信哈

目录

1.函数介绍

1.1strlen

1.2strcpy

1.3strcat

1.4strcmp

1.5 strncpy

1.6strncat

1.7strncmp

1.8strstr

1.8strtok

1.9strerror

1.10字符分类函数

1.11memcpy

1.12memmove

1.13memcmp

1.14memset


1.函数介绍

下面将介绍到如下库函数:

求字符串长度型:

strlen

字符串函数型:

strcpy  : copy :拷贝型

strcat   :catch:追加型

strcmp :compare:比较型

strncpy : 拷贝型 加num确定了拷贝的个数

strncat:同上确定了追加的个数

strncmp:同理

字符串查找型:

strstr 在str(前)字符串中查是否有str(后)

strtok:在str中找分隔符(token)

返回错误型:

strerror

内存函数型(与字符串功能类似):

memcpy

memmove

memset

memcmp

1.1strlen

知识点:

size_t strlen (const char * string)

这个函数是求字符串长度的,从所传递进来的地址开始以char * 的步长往后找 '\0'

最终返回无符号的\0前的共有的元素个数

细节(注意点):

因为strlen以'\0'为结束标志,所以在其算的字符串中必须得有'\0',否则将会算出一个随机值

练习:

char arr[] = "abce";
int ret = strlen(arr);
printf("%d\n",ret);//4

模拟实现strlen

1.2strcpy

知识点:

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

将source处的字符串拷贝到destination处的空间内

返回des的起始地址

细节:

  1. source内必须有\0来结束拷贝
  2. destination的空间必须要大于等于source拷贝过来所需的大小
  3. 在拷贝时source内的\0也会被拷贝过来
  4. destination处的空间必须是可修改的

练习:

char arr1[] = "xxxxxxxxxxxxxxxx";
char arr2[] = "abcdef";
printf("%s",strcpy(arr1,arr2));//strcpy返回的是arr1首元素的地址,所以最终将打印abcdef
//当如下时
char arr2[] = "ab\0cdef";
printf("%s",strcpy(arr1,arr2));//strcpy返回的是arr1首元素的地址,所以最终将打印ab \0看不到

模拟实现strcpy

1.3strcat

知识点:

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

其用法和strcpy有点类似,是将source内的数据追加到destination后面去

返回des的起始地址

细节:

  1. source内必须有\0停止
  2. destination必须有足够的空间放
  3. destination内也必须有\0否则无法进行拷贝
  4. destination必须可以被修改
  5. 不能自己给自己追加(因为是从\0开始追加所以\0会别取代,这样就无法停止)

练习:

char arr1[] = "hello ";
char arr2[] = "world";
//char *arr2 = "world";
printf("%s",strcat(arr1,arr2));//最终打印hello world

//从\0处开始,如果arr1 he\0llo  ->   heworld

strcat的模拟实现

1.4strcmp

知识点:

 int strcmp(const char * str1 , const char * str 2)

比较两个字符串的大小

返回值:

str1 > str2 返回大于0的数 
1 < 2 返回小于0的数
1 = 2 返回0

vs环境下1 > 2 返回 1  1 < 2 返回 -1   1=2 返回0

细节:

字符串的比较时是对应的一个个字符比较,并且比较的是对应的ASCII码值

练习:

strcmp的模拟实现

char arr1[] = "abcdef";
char arr2[] = "abq";
printf("%d",strcmp(arr1,arr2));//次处1 和 2 的前两个字符a b 的ASCII码相但是比到c 与 q 时 
                               //c 的ASCII码值小于 q的...  所以最终 1 < 2 返回负数

对于以上的函数没有对字符的限制(只到\0才停止),所以和scanf一样并不太安全所以需要

 #define _CRT_SECURE_NO_WARNINGS 1 来防止报错

以下是一些有字符个数限制的字符函数


1.5 strncpy

知识点:

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

其用法和strcpy几乎一致只是要对拷贝的字符个数有明确限制

同样返回des的起始地址

细节:

将指定的source的字符个数拷贝到destination处,当所需拷贝的字符超过source时后面用\0替代继续拷贝

练习:

模拟实现strncpy

char * my_strncpy(char * des ,const char * sour ,size_t count)
{
    assert(des && sour);
    char * tmp = des;
    while(count--)
    {
        if(*sour == '\0')
        {
            *des++ = '\0';
            continue;
        }
        else
        {        
            *des++ = *sour++;
        }
    }
}

//反之
char* my_strncpy(char* strDest, const char* strSource, size_t count)
{
	assert(strDest && strSource);
	char *ret = strDest;
	
    while(count--)
    {
		*strDest = *strSource ;
		if(*strSource != '\0')
		{
			strDest++;
			strSource++;
		}
	}

	return ret;
}

例子:

1.6strncat

知识点:

char * strncat(char * des , const char * sour ,size_t count)

同样用法相同,加上了限制的个数

同样返回des的起始地址

细节:

追加完后在最后补上一个\0

练习:

模拟实现strncat

char* my_strncat(char* des, const char* sour, size_t count)
{
    assert(des && sour);
    char* tmp = des;
    while (*des)
    {
        des++;
    }
    while (count--)
    {
        if (*sour == '\0')
            *des = '\0';

        *des++ = *sour++;
    }

    return tmp;
}

例子:

1.7strncmp

知识点:

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

用法相同,限制了比较个数

返回值还是相同:

str1 > str2 返回大于0的数 
1 < 2 返回小于0的数
1 = 2 返回0

vs环境下1 > 2 返回 1  1 < 2 返回 -1   1=2 返回0

练习:

模拟实现

int my_strncmp(const char* string1, const char* string2,size_t count)
{
	assert(string1 && string2);
	while (*string1 == *string2 && *string1 != '\0')//找到不相等的字符
	{
		if (!--count)//后置--时无法会继续往下走而导致string1 2 指向改变
		{
			break;
		}
		string1++;
		string2++;
	}

	if ((*string1 - *string2) == 0)
    {
        return 0;
    }

	else
    {
        return (*string1 - *string2) > 0 ? 1 : -1;
    }
    //vs环境下1大于2返回1 , 1<2 返回-1  1 = 2 返回 0
}

1.8strstr

知识点:

char *strstr( const char *string, const char *strCharSet );

在string字符串内寻找strcharset 

返回strcharset首次出现的位置

细节:

寻找时:

1.如果存在:返回找到strcharset的第一个元素的地址

2.如果不存在:返回NULL

3.如果strcharset 为空则则直接返回string的地址

练习:

模拟实现strstr

1.8strtok

知识点:

用来分割字符串的函数,char *strtok( char *strToken, const char *strDelimit );

strToken给定的一个字符串,strDelimit 传进的分隔符组

在strToken内找strDelimit 来进行分隔

返回本次分隔好后的字符串的首元素的地址

细节:

如何使用strtok:

代码展示:

 #define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[] = "ZhaoYKun@qq.com";
    char arr2[]= "@.";
	//char arr2[] = {'@','.','\0'};//效果相同
	printf("%s\n", strtok(arr1, arr2));//返回第一次分隔好的字符的首元素地址
	printf("%s\n", strtok(NULL, arr2));//当用NULL时表示从分隔好了,继续从下一个开始
	printf("%s\n", strtok(NULL, arr2));//同理
	printf("%s\n", strtok(NULL, arr2));//当后面没有后返回NULL


	return 0;
}

结果:

 总结来说就是:

  1. 首先传进要分隔的字符串,和分隔符组进行第一次分隔
  2. 其次要再次进行分隔(第一次分隔将返回首元素地址,和记录分隔后剩的字符地址),当传进NULL和分隔符组时表示继续分隔
  3. 最后若没有字符了就会返回NULL

1.9strerror

知识点:

char * strerror(int error)

strerror是返回错误码所对应的错误消息的首元素地址

错误码是:1、2、3、4、5组成无法直接看出错误所以需要strerror来翻译翻译成错误消息


当返回了错误码所对应的错误信息的首元素地址后直接打印出错误信息字符串

细节:

C语言中会将错误码放在一个变量中,这个变量是:errno

而若你要使用errno这个变量就需要引头文件  #include<errno.h>

练习:

使用方法:

没有创建test.txt文件

所以最后报错为:原因:当fopen没有找到该文件就会将对应的错误码存在errno变量中

 当有开文件(test.c)后就不会报错,

 附:

strerror这个函数他会返回一个地址再通过这个地址来打印错误信息,稍微有点麻烦了,所以库函数里还有个可以自行打印错误信息的函数 (perror)

 可以适当在perror内加上一些修饰词来修饰错误信息的如perror("error from");(即在对应错误信息前会打印你所自定义的信息 : )头文件:stdio.h

最终打印 error from : .....

   == 

1.10字符分类函数

知识点:

函数 

 int functio(int )

如果他的参数符合一下条件就返回真否则返回0(假)
iscntrl符合控制字符        
isspace空白字符:空格' ' 、换页'\f'、换行'\n'、回车'\r'、制标符'\t'或者崔志垂直制表符'\v'
isdigit十进制数字
isxdigit十六进制数字其中包括大小写字母a~f
islower小写字母
isupper大写字母
isalpha大小写字母·          
isalnum数字和大小写字母
ispunct标点符号;任何不属于数字或字母的图形字符
isgraph任何图形字符        

isprint

任何可打印字符、包括图形字符和空白字符

知识点:

细节:

练习

练习:

附:

  1. 空白字符:'  '空格符、 '\t'水平制表符、'\n' 换行符、'\v'  垂直制表符、'\f'换页符、'\r'  回车符
  2. 在ASCII码中0~31和127为33个 控制字符
  3. 图形字符:所有字符除了‘ ’空格
  4. 可打印字符:不包括控制字符的所有字符
  5. 控制字符:在ASCII码中0~31和127的共33个控制字符
 #define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<ctype.h>
int main()
{
	
	int i = 0; 
	char a[] = "abcde\nfg\nef";
	
//以下都是ture


	//int iscntrl(int c);//传进字符的ASCII码值
	while (!iscntrl(a[i]))//如果是控制字符返回非零的数,再!为假跳出循环
	{
		printf("%c", a[i++]);	

	}

	printf("\n"); i++;
	
	while (!isspace(a[i]))//从f开始//遇到空白字符就会返回非0的数,再同理...
	{
		printf("%c", a[i++]);
	}
	
	printf("\n");  

	if(isdigit('6')) //检查是不是字符数字0~9
		printf("isdigit");

	
	printf("\n");


	if(isxdigit('f'))//十六进制0~f

		printf("isxdigit");
	
	printf("\n");


	if (islower('z'))//为小写字母,返回非0的数

		printf("islower");

	printf("\n");


	if (isupper('A'))//大写字母

		printf("isupper");

	printf("\n");

	if (isalpha('A')&& isalpha('a'))//大小写都行

		printf("isalpha");


	printf("\n");

	if (isalnum('3' ) && isalnum('a'))//数字和大小写字母

		printf("isalnum");

	printf("\n");


	if (ispunct('@'))//除数字,字母的标点符号的图形字符

		printf("ispunct");
	printf("\n");

	if (isgraph('@'))//除了空格的可打印出的字符
	{
		printf("isgraph");
	}
	printf("\n");
	
	if (isprint('!'))//判断是不是可打印字符
	{
		printf("isgraph");
	}
	printf("\n");

	return 0;
}

字符转换函数:

toupper

tolower

isuppuer

islower

 #define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<ctype.h>
int main()
{
	if(isupper('A'))
		printf("A\n");
	if (islower('a'))
		printf("a\n");

	printf("%c\n", toupper('a'));
	
	printf("%c\n", tolower ('A'));


	return 0;
}

在字符字符串中找字符

const char *strchr(const char * str, int character)

const char *strrchr(const char * str, int character)

 #define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
int main()
{
	char arr[] = "abcdeafg";
	//printf("%s", strchr(arr, 'a'));//abcdeafg
	//找字符第一次的出现若存在返回第一次出现的地址,反之返回NULL
	printf("%s", strrchr(arr, 'a'));//afg
	//找字符最后一次出现若存在返回第出现的地址,反之返回NULL

	return 0;
}

以上是一些针对字符串的函数,而对于其他类型的函数就需要另外的函数来其作用

以下是一些处理内存相关的函数


1.11memcpy

知识点:

void *memcpy(void *des , const void * sour  size_t num  )

其用法和strncpy是一样的中num表示byte所以若是拷贝一个整形那就需要4byte,其余同理、

返回des的地址

细节:

  1. 其中num的byte是自己定义的所以在使用的使用也要把握好所要拷贝类型所占的大小
  2. 在拷贝的过程中你必须保证有足够的空间来放

练习:

使用

 #define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
int main()
{
    int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };
    int arr1[10] = { 0 };
    memcpy(arr1, arr, 20);//拷贝5个int 4 * 5 = 20 byte
    for(int i = 0; i<10 ; i++)
    printf("%d ", arr1[i]);//0123400000
    return 0;

}

模拟实现memcpy

1.12memmove

总体来说和memcpy几乎一样的用法但有些许不同:memcpy和memmove的区别

1.13memcmp

知识点:

int memcmp(const void * ptr1,const void * ptr2 , size_t num);

比较内存中的内容大小(步长char)

其返回比较其内存内容后的比较结果

若ptr1小于ptr2返回小于0的数(vs是-1)

1 > 2返回大于0的数(vs是1)

若相等返回0

细节:

具体使用如下:

int arr1[] = {1,4,7};

int arr2[]= {1,4,2};

int ret = memcmp(arr1,arr2,sizeof(arr1));

此时在内存arr1、arr2内容如下

arr1:01 00 00 00 04 00 00 00 07 00 00 00 

arr2:01 00 00 00 04 00 00 00 02 00 00 00;

memcmp会根据你给的num(单位byte来比较逐字节的比较 01 和 01 比较 当比较到不同时就会返回一个值)

使用最终因为07 > 02 所以会返回一个大于0的数

练习:

练习使用

int main()
{
	int arr1[] = { 1,4,7 };

	int arr2[] = { 1,4,2 };

	int ret = memcmp(arr1, arr2,sizeof(arr1));

	printf("%d", ret);

	return 0;
}

模拟实现memcmp

1.14memset

知识点:

//void *memset( void *dest, int c, size_t count );

//count的大小是byte,会一个个字节的改变内存中的内容

细节:

对于整形数组时要注意,count是以一个个byte来进行改变的

当我们要将整形数组内容全部改成1时,不能写成memset(arr,1,20);

练习:

使用举例:将hello world 改成 xxxxx yyyyy

int main()
{
	char arr[] = "hello world";


	//void *memset( void *dest, int c, size_t count );
	memset(arr, 'x', 5);//count的大小是byte,会一个个字节的改变
	printf("%s\n", arr);
	memset(arr + 6, 'y', 5);
	printf("%s\n", arr);
    return 0;
}

模拟实现memset

本章完。预知后事如何,暂听下回分说。

持续更新大量C语言细致内容,三连关注哈

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

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

相关文章

数据结构与算法基础-学习-11-线性表之链栈的初始化、判断非空、压栈、获取栈长度、弹栈、获取栈顶元素

一、个人理解链栈相较于顺序栈不存在上溢&#xff08;数据满&#xff09;的情况&#xff0c;除非内存不足&#xff0c;但存储密度会低于顺序栈&#xff0c;因为会多存一个指针域&#xff0c;其他逻辑和顺序表一致。总结如下&#xff1a;头指针指向栈顶。链栈没有头节点直接就是…

智慧校园应用系统建设方案

系统简介 建设“智慧校园”的核心是创新新形势下高校发展理念、推进高校建设转型、变革高校管理行为方式&#xff1b;建设“智慧校园”的目的是推进信息化进入高校、服务管理、惠及师生&#xff1b;建设“智慧”的目标是实现 “信息采集、数据整合、信息促管、信息育人、信息联…

linux之echo使用技巧

参考文章&#xff1a;linux基本功系列-echo命令实战一、echo 命令是什么&#xff1f;作用&#xff1a; echo命令能将指定文本显示在Linux命令行上&#xff0c;或者通过重定向符写入到指定的文件中。语 法&#xff1a;echo [-ne][字符串] / echo [–help][–version]补充说明&am…

VMware安装CentOS7

个人简介&#xff1a;云计算网络运维专业人员&#xff0c;了解运维知识&#xff0c;掌握TCP/IP协议&#xff0c;每天分享网络运维知识与技能。个人爱好: 编程&#xff0c;打篮球&#xff0c;计算机知识个人名言&#xff1a;海不辞水&#xff0c;故能成其大&#xff1b;山不辞石…

Java+Python+HanLP自然语言处理包实现解析文本分词

目录 需要安装 Python部分 Java部分 需要安装 HanLP官网Api教程 https://bbs.hanlp.com/t/hanlp2-1-restful-api/53 首先需要电脑安装Python环境并配置环境变量&#xff08;网上搜就可以一大堆教程&#xff09;&#xff0c;建议Python版本3 然后根据HanLP官网教程安装hanl…

「JVM 原理使用」 实际开发中的应用

Class 文件格式、执行引擎主要以 Class 文件描述了存储格式、类何时加载、如何连接、VM 如何执行字节码指令&#xff0c;这些动作基本都是 JVM 直接控制&#xff0c;用户代码无法干预和改变&#xff1b; 用户可以干预的只有字节码生成、类加载器两部分&#xff0c;而这两部分的…

Android 面试 基础知识汇总

Android常用的设计模式HTTP和HTTPS的区别TCP/UDP的区别

PendingIntent兼容安卓12 的一个问题

这是我第一次遇到这个问题&#xff0c;反正我也是第一次做完整的安卓app&#xff0c;很多个第一次。我之前做的那个老旧手机做桌面摆件的app&#xff0c;因为原来的“无干预”版本无法使用&#xff0c;所以又用回了“和风版”&#xff0c;但这个版本很久没用了&#xff0c;有些…

实用机器学习-学习笔记

文章目录9.1模型调参9.1.1思考与总结9.1.2 基线baseline9.1.3SGD ADAM9.1.4 训练代价9.1.5 AUTOML9.1.6 要多次调参管理9.1.7复现实验的困难9.1模型调参 9.1.1思考与总结 1了解了baseline和调参基本原则 2了解了adams和sgd的优劣 3了解了训练树和神经网络的基本代价 4了解了a…

【蓝桥杯集训2】差分专题(3 / 4)

目录 差分模板 1、一维差分 2、二维差分 3729. 改变数组元素 - 差分 区间修改 100. 增减序列 - 差分模板 1、一维差分 活动 - AcWing 给a数组 [l,r] 区间的每个数c&#xff0c;只需要给其差分数组b做如下操作即可 b[l]c; b[r1]-c; 差分数组 a[]是b[]的前缀和数组 如果…

倒计时100天 | DBF深圳国际户外运动博览会5月一起狂飙初夏

狂飙初夏的大型户外运动嘉年华即将登场&#xff01;2023年5月26日至28日&#xff0c;第四届DBF深圳国际户外运动博览会&#xff08;简称DBF深圳户外展&#xff09;将于深圳国际会展中心&#xff08;宝安&#xff09;举办。本届展会展览面积超过7万平方米&#xff0c;预计将吸引…

保姆级Vue3+Vite项目实战黑白模式切换

写在前面注&#xff1a;本文首发掘金签约专栏&#xff0c;此为文章同步&#xff01;本文为 Vue3Vite 项目实战系列教程文章第四篇&#xff0c;系列文章建议从头观看效果更佳&#xff0c;大家可关注专栏防走失&#xff01;点个赞再看有助于全文完整阅读&#xff01;此系列文章主…

C/C++【内存管理】

✨个人主页&#xff1a; Yohifo &#x1f389;所属专栏&#xff1a; C修行之路 &#x1f38a;每篇一句&#xff1a; 图片来源 Love is a choice. It is a conscious commitment. It is something you choose to make work every day with a person who has chosen the same thi…

商城系统必备营销工具(五)——积分商城

做商城&#xff0c;流量必不可少&#xff0c;日活跃度也很重要。现在各大APP、网站、小程序和微商城&#xff0c;基本都在为了巩固流量做积分商城&#xff0c;虽然已经随处可见&#xff0c;但很多企业商家却并没有将积分商城运作起来&#xff0c;积分商城也没有人浏览兑换商品。…

跟ChatGPT,聊聊ChatGPT

不仅“上知天文、下知地理”&#xff0c;似乎还能对答如流、出口成诗&#xff0c;甚至还能写剧本、编音乐、写代码——最近&#xff0c;一款名叫ChatGPT的人工智能聊天机器人火爆全球。由此&#xff0c;一系列关于新一代技术变革、人工智能替代人力、巨头企业扎堆入局AI的讨论在…

Multi Paxos

basic paxos 是用于确定且只能确定一个值&#xff0c;“只确定一个值有什么用&#xff1f;这可解决不了我面临的问题,例如每个用户都要多次保存数据.” 你心中可能有这样的疑问。 原simple paxos论文里有提到一连串个instance of paxos [4] 但没有提出 multi paxos的概念&…

ChatGPT国内镜像站试用,聊天、Python代码生成。

ChatGPT国内镜像站试用&#xff0c;聊天、Python代码生成。 (本文获得CSDN质量评分【91】)【学习的细节是欢悦的历程】Python 官网&#xff1a;https://www.python.org/ Free&#xff1a;大咖免费“圣经”教程《 python 完全自学教程》&#xff0c;不仅仅是基础那么简单…… …

前端开发:关于diff算法详解

前言 前端开发中&#xff0c;关于JS原生的内容和前端算法相关的内容一直都是前端工作中的核心&#xff0c;不管是在实际的前端业务开发还是前端求职面试&#xff0c;都是非常重要且必备的内容。那么本篇博文来分享一个关于前端开发中必备内容&#xff1a;diff算法&#xff0c;d…

ChatGPT背后的技术可以给数据治理带来哪些神奇的效果?_光点科技

最近&#xff0c;由美国人工智能研究室OpenAI开发的全新“聊天机器人”ChatGPT火了。作为一款人工智能语言模型&#xff0c;它不仅能和人展开互动&#xff0c;还可以写文章、制定方案、创作诗歌&#xff0c;甚至编写代码、检查漏洞样样精通&#xff0c;上线仅两个月全球活跃用户…

Python雪花代码

前言 用python画个雪花玩玩&#xff0c;源码在文末公众号哈。 雪花类 class Snow(): #雪花类 def __init__(self): self.r 6 #雪花的半径 self.x ra.randint(-1000,1000) #雪花的横坐标 self.y ra.randint(-500,5…