拿捏指针(三)

0f3a2b8bed084b1488aef3e7406bf5b9.jpeg

✨✨欢迎👍👍点赞☕️☕️收藏✍✍评论

个人主页:秋邱'博客

所属栏目:C语言

(感谢您的光临,您的光临蓬荜生辉)

 前言

在这之前我们学习了《拿捏指针(一)》,《拿捏指针(二)》没看过的可以去看看哟,接下里我们将指针最后一篇,《拿捏指针(三)》,看完直接捏爆指针。

函数

前面我们已经学过了指针函数,接下里学指针数组,回调函数。

我们先来看看下面这串代码。

计算器

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int Add(int x ,int y)
{return x + y;
}
int Sub(int x, int y)
{return x = y;
}
int Mul(int x, int y)
{return x * y;
}
int Div(int x, int y)
{return x / y;
}
int main()
{int x, y;int ret = 0;int input = 0;do{printf("************************\n");printf("***** 1.Add  2.Sub *****\n");printf("***** 3.Mul  4.Div *****\n");printf("*******  0.exit  *******\n");printf("************************\n");printf("请选择:");scanf("%d", &input);switch (input){case 1:printf("输入操作数:");scanf("%d %d", &x, &y);ret = Add(x, y);printf("ret = %d\n", ret);break;case 2:printf("输入操作数:");scanf("%d %d", &x, &y);ret = Sub(x, y);printf("ret = %d\n", ret);break;case 3:printf("输入操作数:");scanf("%d %d", &x, &y);ret = Mul(x, y);printf("ret = %d\n", ret);break;case 4:printf("输⼊操作数:");scanf("%d %d", &x, &y);ret = Div(x, y);printf("ret = %d\n", ret);case 0:printf("退出程序\n");break;default:printf("输入错误\n");}} while (input);
}

虽然我们实现了这个计算器,但是它太过于累赘了,这是我们就可以用函数指针数组。

函数指针数组

数组是⼀个存放相同类型数据的存储空间,我们已经学习了指针数组,那要把函数的地址存到⼀个数组中,那这个数组就叫函数指针数组

其实在《拿捏指针(二)》的模拟二维数组里面,我们已经用过函数指针数组了。

定义的格式

int (*p[3])();

 p先和 [] 结合,说明parr1是数组,是 int (*)() 类型的函数指针。

我们现在对上面的代码进行,更改用函数指针数组的方式。

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int Add(int x ,int y)
{return x + y;
}
int Sub(int x, int y)
{return x = y;
}
int Mul(int x, int y)
{return x * y;
}
int Div(int x, int y)
{return x / y;
}
int main()
{int x, y;int ret = 0;int input = 0;int(*p[5])(int x, int y) = { 0, Add, Sub, Mul, Div };do{printf("************************\n");printf("***** 1.Add  2.Sub *****\n");printf("***** 3.Mul  4.Div *****\n");printf("*******  0.exit  *******\n");printf("************************\n");printf("请选择:");scanf("%d", &input);if ((input <= 4 && input >= 1)){printf("输⼊操作数:" );scanf("%d %d", &x, &y);ret = (*p[input])(x, y);printf("ret = %d\n", ret);}else if (input == 0){printf("退出计算器\n");}else{printf("输⼊有误\n" );        }} while (input);}

回调函数

回调函数是一个函数,它作为参数传递给另一个函数,在特定事件发生时被调用。这种机制允许我们将代码模块化,并在需要的时候进行调用。回调函数常用于事件处理、异步编程、并发编程等场景。

int Add(int x ,int y)
{return x + y;
}
int Sub(int x, int y)
{return x = y;
}
int Mul(int x, int y)
{return x * y;
}
int Div(int x, int y)
{return x / y;
}
void calc(int(*pf)(int, int))//回调函数
{int ret = 0;int x, y;printf("输⼊操作数:");scanf("%d %d", &x, &y);ret = pf(x, y);printf("ret = %d\n", ret);
}
int main()
{int input = 1;do{printf("************************\n");printf("***** 1.Add  2.Sub *****\n");printf("***** 3.Mul  4.Div *****\n");printf("*******  0.exit  *******\n");printf("************************\n");switch (input){case 1:calc(Add);//调用函数break;case 2:calc(Sub);//调用函数break;case 3:calc(Mul);//调用函数break;case 4:calc(Div);//调用函数break;case 0:printf("退出程序\n");break;default:printf("选择错误\n");break;}} while (input);}

qsort()函数

冒泡排序

什么事冒泡排序呢?

冒泡排序是一种简单直观的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢"浮"到数列的顶端。

动图演示 

我们就用c语言来实现它。

void Swap(int* arr, int sz)
{for (int i = 0; i < sz -1; i++){for (int j = 0; j < sz - i -1; j++){if (arr[j] > arr[j + 1]){int tmp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = tmp;}}}
}
int main()
{int arr[10] = { 3,6,8,1,9,4,2,7,10,5 };int sz = sizeof(arr) / sizeof(arr[0]);Swap(arr,sz);for (int i = 0; i < sz; i++){printf("%d ", arr[i]);}return 0;
}

 输出结果:


 1 2 3 4 5 6 7 8 9 10

这就是冒泡排序的C语言的实现方式,但是它的局限性太多了,比如你要用字符串呢,这就很难实现,所以我们可以用一个函数就是qsort()。

qsort()函数举例

我们先来看看qsort()的声明

void qsort (void* base, size_t num, size_t size,int (*compar)(const void*,const void*));

base       指向数组中要排序的第一个对象的指针,转换为void*。

num       基数指向的数组中元素的个数。Sizet是一个无符号整型。

size        数组中每个元素的字节大小。Size t是一个无符号整型。

compar 指向比较两个元素的函数的指针。这个函数被qsort反复调用以比较两个元素。应遵                循以下原型:Int compare (const void* p1, const void* p2)。

 下面我们来对它进行使用

排序整型数据

//整形数据结构
int int_arr(const void* p1, const void* p2)
{return (*(int*)p1 - *(int*)p2);
}
int main()
{int arr[10] = { 3,6,8,1,9,4,2,7,10,5 };int sz = sizeof(arr) / sizeof(arr[0]);qsort(arr,sz,sizeof(arr),int_arr);for (int i = 0; i < sz; i++){printf("%d ", arr[i]);}return 0;
}

排序结构数据

#define _CRT_SECURE_NO_WARNINGS#include<stdio.h>
#include<string.h>//strcmp函数的头文件
#include<stdlib.h>//qsort函数的头文件
struct people {char name[20];int age;
};
//数据结构名字比较
int cmp_name(const void* e1, const void* e2)
{return strcmp(((struct people*)e1)->name, ((struct people*)e2)->name);
}//打印
void Print(struct people* p1,int sz)
{for (int i = 0; i < sz; i++){/*printf("%s %d\n", p1[i].name, p1[i].age);//另一种打印方式*/printf("%s %d\n", (p1 + i)->name, (p1 + i)->age);}printf("\n");
}
//数据结构年龄比较
int cmp_age(const void* e1, const void* e2)
{return ((struct people*)e1)->age - ((struct people*)e2)->age;
}
int main()
{struct people s[] = { {"tangsan",20},{"lisi",10},{"zhaowu",40},{"laoliu",5} };int sz = sizeof(s) / sizeof(s[0]);qsort(s, sz, sizeof(s[0]), cmp_name);printf("按名字排序\n");Print(s, sz);qsort(s, sz, sizeof(s[0]), cmp_age);printf("按年龄排序\n");Print(s,sz);return 0;
}

输出结果:

按名字排序
laoliu 5
lisi 10
tangsan 20
zhaowu 40

按年龄排序
laoliu 5
lisi 10
tangsan 20
zhaowu 40

 

qsort()的模拟

上面我们已经知道了qsort函数的定义和使用,现在我们就来模拟一下qsort函数。

//实现qsort函数
void Swap(char* p1, char* p2,size_t width)
{int i = 0;for (i = 0; i < width; i++){char tmp = *p1;*p1 = *p2;*p2 = tmp;p1++;p2++;}
}
int bubbl_sort(void* base, size_t num,size_t width,int cmp (const void*p1 ,const void* p2))
{for (int i = 0; i < num - 1; i++){for (int j = 0; j < num - 1 - i; j++){if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0){Swap((char*)base + j * width, (char*)base + (j + 1) * width,width);}}}
}
int int_cmp(const void* p1, const void* p2)
{return *(char*)p1 - *(char*)p2;
}int main()
{int base[10] = {2, 7, 3, 8, 1, 9, 1, 5, 6, 0};int sz = sizeof(base) / sizeof(base[0]);bubbl_sort(base,sz,sizeof(base[0]),int_cmp );for (int i = 0; i < sizeof(base) / sizeof(base[0]); i++){printf("%d ", base[i]);}printf("\n");return 0;
}

我们这里展现int型的排序。 

sizeof和strlen的对⽐

sizeof

前面我们也已经讲过了sizeof,现在我们再来简单的回顾一下,sizeof是一个操作符,用来计算类型的大小,单位是字节。

注意:
sizeof只与类型有关,跟内容没什么关系

int main()
{int a = 10;printf("%d\n", sizeof(a));printf("%d\n", sizeof a);printf("%d\n", sizeof(int));return 0;
}

输出结果:

4

4

strlen

strlen 是C语⾔库函数,功能是求字符串⻓度。函数原型如下:

size_t strlen ( const char * str );

统计的是从 strlen 函数的参数 str 中这个地址开始向后,\0 之前字符串中字符的个数。 strlen 函数会⼀直向后找 \0 字符,直到找到为⽌,所以可能存在越界查找。

int main()
{char arr1[3] = { 'a', 'b', 'c' };char arr2[] = "abc";printf("arr1=%d\n", strlen(arr1));printf("arr2=%d\n", strlen(arr2));
}

输出结果:

arr1=(随机值,直到遇到\0后停下来)

arr2=3

char arr1[3] = { 'a', 'b', 'c' ,\0"};

这时只需要在后面手动改加上/0就可以了。

结尾 

我们指针以及全部将完了,感谢各位观众老爷的点赞,评论,收藏和关注。

 

 

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

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

相关文章

重学SpringBoot3-函数式Web

更多SpringBoot3内容请关注我的专栏&#xff1a;《SpringBoot3》 期待您的点赞&#x1f44d;收藏⭐评论✍ 重学SpringBoot3-函数式Web 函数式Web编程简介RouterFunctionRequestPredicateServerRequestServerResponse 好处示例结论 随着响应式编程范式的兴起和 Java 函数式编程能…

Spring之@Value注解

前言 Value注解在Spring的依赖注入中占据重要地位,这里对Value注解的作用进行演示以及扩展 作用 注入字符串注入属性注入bean其他 代码准备 创建两个普通的bean Component public class ValueComponent { } Component public class Foo {private String sign;public Foo…

day-24 不同路径

思路&#xff1a;动态规划&#xff0c;因为只能向下或向右移动&#xff0c;所以第一行和第一列的路径数皆为1&#xff0c;其余位置的路径数dp[i][j]dp[i-1][j]dp[i][j-1] 最后返回dp[m-1][n-1]即可 code: class Solution {public int uniquePaths(int m, int n) {int dp[][]n…

【通用知识】HttpServletRequest接口方法

一、前端知识概述 说明&#xff1a; 1、Headers和Payload为前端传给后端的请求头和请求参数信息。Preview和Response为后端返回的数据。 2、Payload标签内为前端传给后端的参数。其中&#xff0c;Query String Parameters中为问号传参&#xff0c;对应后端RequestParam方式&…

MNN createRuntime(二)

系列文章目录 MNN createFromBuffer&#xff08;一&#xff09; MNN createRuntime&#xff08;二&#xff09; MNN createSession 之 Schedule&#xff08;三&#xff09; MNN createSession 之创建流水线后端&#xff08;四&#xff09; MNN Session::resize 之流水线编码&am…

C# Onnx Yolov9 Detect 物体检测

目录 介绍 效果 项目 模型信息 代码 下载 C# Onnx Yolov9 Detect 物体检测 介绍 yolov9 github地址&#xff1a;https://github.com/WongKinYiu/yolov9 Implementation of paper - YOLOv9: Learning What You Want to Learn Using Programmable Gradient Information …

软件工程-第6章 面向对象方法UML

UML是一种图形化语言&#xff0c;简称画图。 6.1 表达客观事物的术语 6.2 表达关系的术语 1.关联 表达关联语义相关术语&#xff1a;关联名、导航、角色、可见性、多重性、限定符、聚合、组合。 2.泛化 3.细化 6.3 组织信息的一种通用机制-包 6.4 模型表达工具 一个用况图包含6…

Springboot+Redis:实现缓存 减少对数据库的压力

&#x1f389;&#x1f389;欢迎光临&#xff0c;终于等到你啦&#x1f389;&#x1f389; &#x1f3c5;我是苏泽&#xff0c;一位对技术充满热情的探索者和分享者。&#x1f680;&#x1f680; &#x1f31f;持续更新的专栏Redis实战与进阶 本专栏讲解Redis从原理到实践 …

【Vue3】走进Pinia,学习Pinia,使用Pinia

&#x1f497;&#x1f497;&#x1f497;欢迎来到我的博客&#xff0c;你将找到有关如何使用技术解决问题的文章&#xff0c;也会找到某个技术的学习路线。无论你是何种职业&#xff0c;我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章&#xff0c;也欢…

杰发科技AC7801——读取Flash数据做CRC校验

查看Keil的编译结果发现总共6160个字节。计算结果如下&#xff0c; 代码如下 #include "ac780x_crc.h" #include "ac780x.h" #include "ac780x_debugout.h" #include "string.h" #include "ac780x_eflash.h"#define TestSi…

html5cssjs代码 026 canvas示例

html5&css&js代码 026 canvas示例 一、代码二、解释 这段HTML代码定义了一个页面&#xff0c;其中包含一个容器和一个canvas元素。通过JavaScript代码&#xff0c;使用canvas绘制了一个矩形、一个填充了颜色的矩形、一个文本以及一个圆形。 一、代码 <!DOCTYPE ht…

nodejs基于vue超市信息管理系统flask-django-php

互联网的快速发展&#xff0c;使世界各地的各种组织的管理方式发生了根本性的变化&#xff0c;我国政府、企业等组织在上个世纪90年代就已开始考虑使用互联网来管理信息。由于以前的种种因素&#xff0c;比如网络的普及率不高&#xff0c;用户对它的认知度不够&#xff0c;以及…

Zenlayer如何将万台设备监控从Zabbix迁移到Flashcat

作为全球首家以超连接为核心的云服务商&#xff0c;Zenlayer 致力于将云计算、内容服务和边缘技术融合&#xff0c;为客户提供全面的解决方案。通过构建可靠的网络架构和高效的数据传输&#xff0c;Zenlayer 帮助客户实现更快速、更可靠的连接&#xff0c;提升用户体验和业务效…

局域网内监控别人电脑屏幕

想要在局域网内可以监控他人的屏幕的方法&#xff0c;无疑是使用一款&#xff0c;屏幕监控软件了。 什么是局域网屏幕监控软件&#xff1f; 局域网屏幕监控软件是一种专门用于监控局域网内电脑屏幕活动的软件工具。它通常集成在局域网监控系统中&#xff0c;能够实时捕捉和记…

使用Java JDBC连接数据库

在Java应用程序中&#xff0c;与数据库交互是一个常见的任务。Java数据库连接&#xff08;JDBC&#xff09;是一种用于在Java应用程序和数据库之间建立连接并执行SQL查询的标准API。通过JDBC&#xff0c;您可以轻松地执行各种数据库操作&#xff0c;如插入、更新、删除和查询数…

2024蓝桥杯每日一题(递归)

备战2024年蓝桥杯 -- 每日一题 Python大学A组 试题一&#xff1a;有序分数 试题二&#xff1a;正则问题 试题三&#xff1a;带分数 试题四&#xff1a;约数之和 试题五&#xff1a;分形之城 试题一&#xff1a;有序分数 【题目描述】 【输入格…

AI换脸软件rope最新更新的蓝宝石中文版下载

rope换脸软件蓝宝石版下载地址&#xff1a;点击下载 最近AI软件非常的火爆&#xff0c;今天就给大家带来一个可以AI替换人脸的工具rope&#xff0c;得益于机器学习技术的不断发展&#xff0c;rope经过深度神经网络的无数次迭代优化&#xff0c;最终得出的模型可以自动学习和识…

Linux调试器-gdb的使用

. 个人主页&#xff1a;晓风飞 专栏&#xff1a;数据结构|Linux|C语言 路漫漫其修远兮&#xff0c;吾将上下而求索 文章目录 gdb简单基础指令Linux调试器-gdb使用背景调试准备工作写一个简单的myprocess.c程序makefile程序debug模式运行修改后的Makefile程序 调试(gdb)listruni…

Excalidraw:绘制图形的新利器

title: Excalidraw&#xff1a;绘制图形的新利器 date: 2024/3/19 17:18:08 updated: 2024/3/19 17:18:08 tags: 绘图工具多人协作数据安全简洁设计浏览器访问Docker部署插件扩展 摘要&#xff1a; Excalidraw是一款简洁设计、直观易用的绘图应用&#xff0c;用户可以通过它创…

【IJCAI】CostFormer即插即用的MVS高效代价体聚合Transformer,FaceChain团队出品

一、论文题目&#xff1a; CostFormer: Cost Transformer for Cost Aggregation in Multi-view Stereo&#xff0c;https://arxiv.org/abs/2305.10320 二、论文简介&#xff1a; 多视角立体是三维重建的一种重要实现方式&#xff0c;该方式会从一系列同一场景但不同视角的二维…