椋鸟C语言笔记#22:回调函数、泛式编程、qsort

第28篇 sw放样特征矩形-圆-矩形学习笔记 本例演示三轮廓放样:先画中心对齐的100×100矩形草图,再在偏移100的基准面上绘制圆,最后在另一基准面画矩形。通过依次选择三个轮廓并正确设置连接点,实现矩形→圆→矩形的平滑过渡,注意连接点位置避免扭曲。 阅读详情

萌新的学习笔记,写错了恳请斧正。


目录

回调函数

泛式编程

qsort

qsort是什么

比较函数怎么写

使用qsort排序各种数据

模仿qsort写一个万能冒泡排序


回调函数

当一个函数a的参数含有函数指针时,这个函数指针在使用时所指向的函数b(被该函数调用的函数)就是回调函数。注意回调函数并不是由函数a决定调用的函数,而是在调用函数a时决定使用的函数。

比方说,上一篇笔记中的计算器如果不用转移表实现,也可以这样:

#include <stdio.h>

int add(int a, int b)
{
    return a + b;
}
int sub(int a, int b)
{
    return a - b;
}
int mul(int a, int b)
{
    return a * b;
}
int div(int a, int b)
{
    return a / b;
}
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("************************");
        printf("**1:add**2:sub**********");      
        printf("**3:mul**4:div**0:exit**");         
        printf("************************");
        printf("请选择:");
        scanf("%d", &input);
        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);
    return 0;
}

上方的calc函数的参数就是函数指针,在实际调用calc函数时提供的指针指向的函数就是回调函数

泛式编程

泛式编程就是在编程的时候尽量减少对特定数据类型的依赖。

比方说我们要写一个冒泡排序的函数,如下:

void sortofup(int s[], int n)
{
	_Bool flag = true;
	while (flag)
	{
		flag = false;
		for (int i = 0; i < n - 1; i++)
			if (s[i] > s[i + 1])
			{
				s[i] ^= s[i + 1];
				s[i + 1] ^= s[i];
				s[i] ^= s[i + 1];
				flag = true;
			}
	}
}

上面就是对一个长度为n的数组的冒泡排序的实现

但是这个数组只能是整型数组。如果我们需要对浮点型数组排序,就需要再写一个浮点型数组的冒泡排序;如果我们要对长整型数组排序,就需要再写一个长整型数组的冒泡排序。这就十分死板。

而在库函数中,有一个函数叫qsort,它能对任意类型的数据进行快速排序,十分灵活

这就是泛式编程的应用,那么具体是怎么实现的呢?不急,待会讲。

qsort

qsort是什么

qsort是stdlib.h(或search.h)头文件中定义的一种排序函数

qsort没有返回值(void),而其参数有4个:

  1. void* base:指向需要排序的数组的首元素的指针base(注意前面笔记讲过void*类型的参数可以接受任意类型的指针传参,但是使用时需要先强制类型转换)
  2. size_t num:需要排序的数据的数量
  3. size_t width:需要排序的数据中每个数据占多少字节
  4. int (*compare)(void*, void*):一个函数指针compare,指向一个返回值为整型参数为两个泛型指针变量的函数。这就是比较函数。
比较函数怎么写

在使用qsort时,我们需要排序某种类型的数据,就先写一个对该类型数据的比较函数。这个函数的参数是两个泛型指针,返回值是整型,而返回值的正负或零代表了比较的结果是大于小于或等于(第一个参数更大时返回正数则递增排序,反之则为递减排序,如果有其他比较排序规则也可以自行添加,比如奇偶交叉等)。比方说,比较两个整型数据,我们可以这么写:

int Comp_int(const void* a, const void* b)
{
    int ia = *(int*)a;
    int ib = *(int*)b;
	if (ia > ib)
        return 1;
    if (ia < ib)
        return -1;
    else
        return 0;
}

上方代码我们将a与b强制类型转换为整型指针并解引用,这样我们就得到了整型a与b的值,并可以加以比较。

注意如果指针传参时我们不希望原值被改变,无论函数中有没有会对原值产生影响的内容,我们都最好在参数前加一个const进行限制,这是一个好习惯。 

我们也可以进一步根据实际情况简化比较函数:

int Comp_int(void* a, void* b)
{
	return *(int*)a - *(int*)b;
}
使用qsort排序各种数据
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>

struct Stu
{
	char Name[20];
	short ID;
};

int Comp_int(void* a, void* b)
{
	return *(int*)a - *(int*)b;
}

int Comp_flt(void* a, void* b)
{
	int c = 0;
	if ((c = *(float*)a - *(float*)b) == 0)
		return 0;
	return c > 0 ? 1 : -1;
}

int Comp_struct_by_ID(void* a, void* b)
{
	return ((struct Stu*)a)->ID - ((struct Stu*)b)->ID;
}

int main()
{
    //@@@@@排序整型数组并打印@@@@@
	int arr_int[] = { 2,5,78,3,31,6,7865,34,1,7,8,132,4,7,5 };
	size_t len_int = sizeof arr_int / sizeof arr_int[0];
	qsort(arr_int, len_int, sizeof arr_int[0], Comp_int);
	for (int i = 0; i < len_int; i++)
		printf("%d ", arr_int[i]);
	printf("\n");

    //@@@@@排序浮点型数组并打印@@@@@
	float arr_flt[] = { 12.5,3.5,6.2,9,1.1,98.2,0.4,-9.3,14.7 };
	size_t len_flt = sizeof arr_flt / sizeof arr_flt[0];
	qsort(arr_flt, len_flt, sizeof arr_flt[0], Comp_flt);
	for (int i = 0; i < len_flt; i++)
		printf("%.2f ", arr_flt[i]);
	printf("\n");

    //@@@@@排序结构体数组并打印@@@@@
	struct Stu arr_struct[] = { {"zhangsan",2},{"lisi",1},{"wangwu",3} };
	size_t len_struct = sizeof arr_struct / sizeof arr_struct[0];
        //按id排序
	qsort(arr_struct, len_struct, sizeof arr_struct[0], Comp_struct_by_ID);
	for (int i = 0; i < len_struct; i++)
		printf("%s %hd ", arr_struct[i].Name, arr_struct[i].ID);
	printf("\n");
        //按首字母排序
	qsort(arr_struct, len_struct, sizeof arr_struct[0], strcmp);
	for (int i = 0; i < len_struct; i++)
		printf("%s %hd ", arr_struct[i].Name, arr_struct[i].ID);
	printf("\n");


	return 0;
}

上方代码按首字母排序的strcmp函数后面笔记会讲,是string.h提供的函数

模仿qsort写一个万能冒泡排序

我们可以模仿qsort来实现一个万能的冒泡排序

只需要做三件事:

  • 将其中比较数据大小的地方替换为比较函数的函数指针
  • 将指针变成char*类型(只占一个字节),然后利用数据数量与数据长度来定位指定数据
  • 将交换数据的地方处理为逐字节替换(利用第二点的定位)

具体实现如下:

#include <stdio.h>
#include <stdbool.h>
#include <string.h>

struct Stu
{
	char Name[20];
	short ID;
};

int Comp_int(void* a, void* b)
{
	return *(int*)a - *(int*)b;
}

int Comp_flt(void* a, void* b)
{
	int c = 0;
	if ((c = *(float*)a - *(float*)b) == 0)
		return 0;
	return c > 0 ? 1 : -1;
}

int Comp_struct_by_ID(void* a, void* b)
{
	return ((struct Stu*)a)->ID - ((struct Stu*)b)->ID;
}

 
void bsort(void* base, size_t count, size_t size, int(*comp_f)(void*, void*))
{
	int flag = 1;
	for (int k = 0; k < count; k++)
	{
		flag = 1;
		for (int i = 0; i < count - k - 1; i++)
		{
			if (comp_f((char*)base + size * i, (char*)base + size * (i + 1)) > 0)
			{
				for (int j = 0; j < size; j++)
				{
					char* a = (char*)base + size * i + j;
					char* b = (char*)base + size * (i + 1) + j;
					char c;
					c = *a, *a = *b, *b = c;
				}
				flag = 0;
			}
		}
		if (flag)
			break;
	}
}


int main()
{
	int arr_int[] = { 2,5,78,3,31,6,7865,34,1,7,8,132,4,7,5 };
	size_t len_int = sizeof arr_int / sizeof arr_int[0];
	bsort(arr_int, len_int, sizeof arr_int[0], Comp_int);
	for (int i = 0; i < len_int; i++)
		printf("%d ", arr_int[i]);
	printf("\n");

	float arr_flt[] = { 12.5,3.5,6.2,9,1.1,98.2,0.4,-9.3,14.7 };
	size_t len_flt = sizeof arr_flt / sizeof arr_flt[0];
	bsort(arr_flt, len_flt, sizeof arr_flt[0], Comp_flt);
	for (int i = 0; i < len_flt; i++)
		printf("%.2f ", arr_flt[i]);
	printf("\n");

	struct Stu arr_struct[] = { {"zhangsan",2},{"lisi",1},{"wangwu",3} };
	size_t len_struct = sizeof arr_struct / sizeof arr_struct[0];
	bsort(arr_struct, len_struct, sizeof arr_struct[0], Comp_struct_by_ID);
	for (int i = 0; i < len_struct; i++)
		printf("%s %hd ", arr_struct[i].Name, arr_struct[i].ID);
	printf("\n");
	bsort(arr_struct, len_struct, sizeof arr_struct[0], strcmp);
	for (int i = 0; i < len_struct; i++)
		printf("%s %hd ", arr_struct[i].Name, arr_struct[i].ID);
	printf("\n");

	return 0;
}

KEPServerEX中,别名映射(Alias Mapping)数据标签重命名机制 目录核心机制应用场景配置步骤技术特性与参考内容的差异KEPServerEX中,别名映射(Alias Mapping) 是一种数据标签重命名机制,主要用于简化复杂标签路径的调用或实现跨系统兼容。其核心逻辑和功能如下:路径抽象 将设备层级结构中的完整标签路径(如 Channel1.Device1.Tag1)映射为简短别名(如 TempSensor1),降低客户端调用的复杂度。动态绑定 别名与实际标签实时关联,数据更新和读写操作通过别名直接传递到底层物理标签,无需修改客户端配置。多对一映射支持多个别名指向 阅读详情

相关推荐

方差分析ANOVA、T检验、卡方检验的区别

T检验和ANOVA都是用来看样本之间均值是否相等,但是两者又有什么区别呢? 卡方检验是用来看分类变量之间有没有相关性。 自变量X类型 自变量X组数 因变量Y类型 分析方法 离散(类别) 仅仅2组 连续(均值) t检验 离散(类别) 2组及以上 连续(均值) ANOVA 离散(类别) 2组及以上 离散(类别) 卡方检验 进一步细分 方差分析 从理论上讲,方差分析有两个前提条件,一是因变量Y需要满足正态性要求,二是满足方差齐检验。 方差不齐时可使用‘非参数检验’,同时还可使用wel

itslifeng的博客 4万+

MySQL建库建表操作学习笔记

SQL(Structured Query Language,结构化查询语言)是用于在关系型数据库上执行数据操作、数据检索以及数据维护的标准语言。:用于定义对数据库对象(库、表、列、索引)的操作,如 CREATE、DROP、ALTER、RENAME、TRUNCATE 等。保存可变长度的字符串(可包含字母、数字以及特殊字 符)。:用于定义对数据库记录的操作,如 INSERT、DELETE、UPDATE、SELECT 等。:用于定义对数据库、表、字段、用户的访问权限和安全级别,如 GRANT、REVOKE 等。

Eternitycai的博客 224

Delft3D从入门到实践:安装、编译与首次模拟指南

本文为Delft3D初学者提供了一份详尽的从零开始指南。内容涵盖软件获取、许可证申请、图形界面安装、核心计算内核的编译环境搭建与编译步骤,以及最终整合运行首个水动力模拟的全流程。重点解决了Windows系统下Delft3D安装与编译的常见问题,帮助用户快速上手这一开源水动力与泥沙输运模拟工具。

weixin_29303701的博客 538

选型笔记:Type‑C 扩展坞方案评估|DP1.4 转 HDMI2.0 桥接芯片 GSV2201S@ACP

本文记录 GSV2201S 这款 DP1.4a 转 HDMI2.0 桥接芯片评估,梳理视频、HDCP、PD 集成能力,总结 Type‑C 转接 Dongle、扩展坞方案的适配边界,以及差分走线、PD 时序、HDCP 握手等高频调试问题,为 C 口视频转接方案选型提供参考。

ACP广源盛的博客 221

Win10下YOLOv8环境搭建避坑指南:从CUDA 11.6到cuDNN配置全流程

本文详细介绍了在Windows 10系统下搭建YOLOv8环境的完整流程,包括CUDA 11.6和cuDNN的配置步骤,以及常见问题的解决方案。通过硬件准备、软件安装、环境验证和性能优化等环节,帮助开发者高效完成YOLOv8环境配置,提升目标检测项目的开发效率。

defi6farmer的博客 224

虚拟机安装Centos8.5

Centos8.5

weixin_63604047的博客 957

新概念英语第一册 · 词法笔记

以《新概念英语第一册》为范围,梳理 10 类词性中的 8 类:名词的数与所有格、冠词、代词、形容词副词比较级、数词与时间、介词、动词四类与 have 的四种用法、情态动词与不定式,附易错 TOP12 与课次顺序。

Ep流苏的博客 203

手把手教你绕过Incapsula reese84防护:从JS反混淆到动态Token生成全流程

本文深入解析了以Incapsula reese84为代表的现代Web客户端挑战防护机制,详细介绍了从JS反混淆、算法逆向到动态Token生成的全流程实战方法。文章系统阐述了如何通过模拟浏览器指纹、移植关键算法或嵌入JS引擎来构建自动化应对策略,并提供了稳健的令牌管理与系统架构设计思路,帮助开发者在合规前提下提升自动化工具的适应性。

jenkins8butler的博客 518

2026小红书小工具怎么制作:纯前端 ZIP 打包、沙箱限制与笔记挂载流程

小红书小工具制作的核心不是复杂开发,而是把需求压缩成纯前端轻交互,并按平台要求完成 ZIP 交付。适合做的方向是测试、计算器、生成器、学习小测和记录工具;不适合做的方向是账号体系、云端数据、支付和远程接口。制作时先确认沙箱限制,再整理输入、计算、输出链路,最后通过 Builder Hub 提交审核并挂载笔记。在需求简单、素材较少的情况下,十几分钟做出一个可用的小工具是现实路径,袋马就是一个选择。

qq_39308835的博客 285

AI辅助需求分析与提示词生成

文章标题 《AI辅助需求分析与提示词生成》 关键词 人工智能 需求分析 提示词生成 深度学习 机器学习 强化学习 数学模型 系统架构

AI天才研究院 1213

【华为OD机试真题】390、AI面板识别 | 机试真题+思路参考+代码解析(C++、Java、Py、C语言、JS)

题目描述 >AI识别到面板上有N(1 ≤ N ≤ 100)个指示灯,灯大小一样,任意两个之间无重叠。   由于AI识别误差,每次别到的指示灯位置可能有差异,以4个坐标值描述AI识别的指示灯的大小和位置(左上角x1,y1,右下角x2,y2),   请输出先行后列排序的指示灯的编号,排序规则:   1、每次在尚未排序的灯中挑选最高的灯作为的基准灯   2、找出和基准灯属于同一行所有的灯进行排序。两个灯高低偏差不超过灯半径算同一行(即两个灯坐标的差 ≤ 灯高度的一半)

KJ.JK 1804

闪光灯笔记

主体后常亮补光,相机快门速度两秒,相机固定在三脚架上,让主体保持不动,按下快门之后主体周围晃动灯棒。特点:人物清晰,背景车流灯光拖在人物身后,氛围感强,就是 A7R3 + 神牛外帘同步的目标效果。总时长 = 8÷10=0.8s 👉 A7R3 相机:M 档,快门 1s,f/8,ISO100。上图:前帘同步,车向前行驶,光轨跑到车头前面,看着很怪。例:6 次,4Hz → 6÷4=1.5s → 相机快门设置≥1.5s,推荐 2s。缺点(慢速快门拍运动物体):闪光先把人定住,之后人物继续移动,在传感器上,

oDianZi1234567的博客 276

SPI 总线信号完整性与时序一致性测试

SPI总线测试的核心目标是验证其电气与时序行为是否满足芯片规格要求,确保通信可靠性

硬核科技 328

【Linux】APT 本地 deb 安装与 `-f` 参数总结笔记

apt install ./xx.deb 可自动解析并安装依赖,无需 -f;-f 仅用于修复已损坏的依赖状态,非首次安装时必需。apt install -f 可单独运行,修复 broken dependencies。两者职责不同:前者是安装与依赖解决,后者是故障修复。完全离线时需提前准备依赖包或本地源。

hknaruto的专栏 211

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

排序算法深度笔记(下):非比较类排序的线性突破与工程边界

排序算法时间复杂度额外空间复杂度稳定性是否基于比较选择排序O(N^2)(O(1))不稳定是冒泡排序O(N^2)(O(1))稳定是插入排序O(N^2)(O(1))稳定是归并排序O(N\log N)(O(N))稳定是快速排序O(N\log N)O(log N)不稳定是堆排序O(N\log N)O(1)不稳定是计数排序(O(N + M))O(M))稳定否基数排序O(N)稳定否桶排序平均O(N) / 最坏O(N^2)

2401_87069538的博客 567

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

【LTE L3 笔记 10】LTE物理信道-PUCCH、PUSCH

课程来源:B站《【2022】华为HCIA-LTE无线工程师认证学习中级视频》笔记为个人整理,含课件截图,仅供学习交流。

lyouhuan的博客 179

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

邓明 Agent 系统面试-意图识别学习笔记

不要只是做意图识别而不做测评,就好像要评估 RAG 准确性,在接口服务要测试响应时延,超时控制等等,这里也要关注意图识别准确率,如果面试官认为项目指标太高是在吹牛,关键就是回答因为 Agent 解决的是特定领域的意图识别,识别场景单一,另外就是因为用户输入相对简单。意图识别影响 prompt/spec 的加载,意图识别影响上下文组织,意图识别影响工具选择,意图识别影响 prompt 建议,意图识别得到的意图不是让模型随机生成而是候选类别里去做选择。2.意图识别的原因,以及意图识别得到的是什么?

m0_57222081的博客 215

【LTE L3 笔记 05】LTE同步信号

课程来源:B站《【2022】华为HCIA-LTE无线工程师认证学习中级视频》笔记为个人整理,含课件截图,仅供学习交流。

lyouhuan的博客 115

Java 多态 学习笔记

多态是面向对象编程的重要特性,指同一操作作用于不同对象时产生不同行为。其核心在于“父类引用指向子类对象”,结合方法重写实现运行时动态绑定。多态使代码更灵活、可扩展,如用Person p = new Student();统一处理各类人员注册,无需修改调用逻辑。但多态无法直接调用子类特有方法,需通过instanceof判断并强制转换。编译时看左边(类型),运行时看右边(实际对象),实现解耦与维护便利。

AA_AA114514的博客 358

硬件选型笔记:HDMI2.0 转 DP1.4 主动桥接方案 GSV2125D@ACP 评估

本文记录 GSV2125D HDMI2.0 转 DP1.4 主动桥芯片规格与工程调试问题,适合便携屏、HDMI 转 DP 转接器、图像采集板前期方案评估,重点关注 DP 链路训练、EDID、HDCP 兼容性边界。

ACP广源盛的博客 290

Arduino-MEGA-ESP单片机理论课笔记-06温湿度-07时间-延时定时-2026

本文解析了DHT11温湿度传感器的Arduino代码,逐行讲解了库引入、引脚定义、传感器初始化及数据读取流程。重点说明了delay(1000)导致阻塞的问题,并提出使用millis()实现非阻塞定时,将采样间隔改为2秒,提升程序响应性。同时建议增加isnan()错误检测、优化串口输出格式,确保数据稳定可靠。

zhangrelay的专栏 336

#SQLite 数据库笔记一:(概念 / 终端指令 / SQL 语句 / C 编程 / 回调函数)

数据库 = 数据的仓库,假设数据是海量。能力说明存储数据持久化保存,程序退出数据还在统计数据、分组、排序数据管理增、删、改、查(CRUD)嵌入式设备上也会用数据库(单片机网关、路由器、工业 HMI 都常见),因为 sqlite 体积小、无需服务进程、单文件即可。数据库 = 库 > 表 > 记录(行) > 字段(列)sqlite3 = 开源、C 写的、单文件、免安装、最多 2T 的嵌入式关系型数据库。

lwq20051110的博客 203

【学习笔记】51单片机 模块化编程

模块化编程:把各个模块的代码放在不同的c文件里,在.h文件里提供外部可调用函数的声明,在其他.c文件想使用其中的代码时,只需要#include"xxx.h"文件即可。传统方式编程:所有的函数均放在main.c中,若使用的模块比较多,则一个文件内会有很多的代码,不利于代码组织和管理,而且很影响编程者的思路。使用LCD602液晶屏作为调试窗口,提供类似printf函数的功能,可实时观察单片机内部数据的变换情况,便于调试和演示。使用到的.h文件必须要放在编译器可寻找到的地方(工程文件夹根目录,安全目录,自定义)

2601_96469072的博客 226

本地笔记的持久化:选区锚点、条目关联与内容升级时的迁移

离线典籍类应用里,读者产生的数据常常被当作附属功能处理:选中一句话、写两句理解,看起来只是往数据库里插一行。真正麻烦的是这些数据必须与正文长期对齐——正文会随内容包升级而变动,而用户写下的东西不能跟着失效。本文以一款纯本地运行的鸿蒙知识库为例,记录实现侧几个容易踩坑的取舍,与检索链路无关。

m0_61869851的博客 192

【论文阅读笔记】Score Centering 如何稳定存在训练-推理不匹配的强化学习

大语言模型强化学习里,负责生成 rollout 的 sampler 和负责计算梯度的 trainer 往往不是完全同一个数值系统,二者之间存在训练-推理不匹配(training-inference mismatch,TIM)

iiiiii11的博客 482

正则表达式学习笔记 02:基础语法

正则表达式是描述字符匹配规则的迷你语言,由普通字符和元字符组成。普通字符直接匹配自身,而元字符如.、*、+、^、$等具有特殊含义,用于控制匹配模式。常见功能包括任意字符匹配、字符类、预定义类(如\d)、量词、位置锚点、分组与捕获、环视断言及反向引用。需注意,若要匹配元字符本身,必须使用转义符\。例如,\.可匹配字面点号。

菜鸟的专栏 179
上一篇: 椋鸟C语言笔记#21:函数指针、函数指针数组(转移表)、typedef及其必要性
下一篇: 椋鸟C语言笔记#23:字符函数、字符串函数
椋鸟Starling
博客等级 码龄3年 447粉丝 57原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

打赏作者

椋鸟Starling

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

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

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

打赏作者

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

抵扣说明:

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

余额充值