C 语言高级编程指南:回调函数与设计模式
C 语言高级编程指南:回调函数与设计模式
目录
- 回调函数详解
- C语言中的设计模式
- 高级回调函数应用
- 内存管理与安全
- 多线程环境下的设计模式
回调函数详解
1. 什么是回调函数?
回调函数(Callback Function)是一个通过函数指针调用的函数。它允许将函数作为参数传递给另一个函数,实现了一种松耦合的编程方式。
2. 回调函数的基本语法
// 定义回调函数类型
typedef void (*callback_t)(int);// 接受回调函数作为参数的函数
void process_with_callback(callback_t callback) {// 执行一些操作callback(42); // 调用回调函数
}// 回调函数的实现
void my_callback(int value) {printf("回调函数被调用,参数值:%d\n", value);
}// 使用示例
int main() {process_with_callback(my_callback);return 0;
}
3. 回调函数的应用场景
3.1 事件处理
typedef struct {void (*onClick)(void);void (*onDoubleClick)(void);
} ButtonCallbacks;typedef struct {ButtonCallbacks callbacks;char* label;
} Button;void button_click(Button* btn) {if (btn->callbacks.onClick) {btn->callbacks.onClick();}
}
3.2 数据处理
// 通用数组处理函数
void process_array(int* array, size_t size, void (*processor)(int*)) {for (size_t i = 0; i < size; i++) {processor(&array[i]);}
}// 具体的处理函数
void double_value(int* value) {*value *= 2;
}void square_value(int* value) {*value = (*value) * (*value);
}
4. 回调函数进阶技巧
4.1 带上下文的回调
typedef void (*callback_with_context_t)(void* context, int value);void process_with_context(callback_with_context_t callback, void* context) {callback(context, 42);
}typedef struct {int multiplier;
} ProcessContext;void process_callback(void* context, int value) {ProcessContext* ctx = (ProcessContext*)context;printf("结果:%d\n", value * ctx->multiplier);
}
C语言中的设计模式
设计模式概述
设计模式是软件开发中常见问题的典型解决方案。在C语言中,尽管没有面向对象的特性,我们仍然可以通过结构体和函数指针来实现这些模式。以下是最常用的几种设计模式及其实现。
1. 单例模式(Singleton Pattern)
单例模式确保一个类只有一个实例,并提供一个全局访问点。
图解单例模式
代码实现
typedef struct {int data;
} Singleton;static Singleton* instance = NULL;Singleton* get_instance() {if (instance == NULL) {instance = (Singleton*)malloc(sizeof(Singleton));instance->data = 0;}return instance;
}
2. 观察者模式(Observer Pattern)
观察者模式定义了对象之间的一对多依赖关系,使得当一个对象改变状态时,所有依赖于它的对象都会得到通知并自动更新。
图解观察者模式
代码实现
#define MAX_OBSERVERS 10typedef struct {void (*update)(void* self, int data);
} Observer;typedef struct {Observer* observers[MAX_OBSERVERS];int observer_count;int data;
} Subject;void subject_attach(Subject* subject, Observer* observer) {if (subject->observer_count < MAX_OBSERVERS) {subject->observers[subject->observer_count++] = observer;}
}void subject_notify(Subject* subject) {for (int i = 0; i < subject->observer_count; i++) {subject->observers[i]->update(subject->observers[i], subject->data);}
}
3. 策略模式(Strategy Pattern)
策略模式定义了一系列算法,并使这些算法可以相互替换。策略模式使算法可以独立于使用它的客户端而变化。
图解策略模式
代码实现
typedef int (*Strategy)(int, int);int add_strategy(int a, int b) { return a + b; }
int subtract_strategy(int a, int b) { return a - b; }
int multiply_strategy(int a, int b) { return a * b; }typedef struct {Strategy strategy;
} Context;void set_strategy(Context* context, Strategy strategy) {context->strategy = strategy;
}int execute_strategy(Context* context, int a, int b) {return context->strategy(a, b);
}
4. 工厂模式(Factory Pattern)
工厂模式提供了一种封装对象创建逻辑的方法,让客户端代码与具体类的实现解耦。
图解工厂模式
代码实现
typedef struct {void (*process)(void);
} Product;typedef struct {void (*process)(void);
} ConcreteProductA;typedef struct {void (*process)(void);
} ConcreteProductB;Product* create_product(char type) {switch(type) {case 'A':return (Product*)malloc(sizeof(ConcreteProductA));case 'B':return (Product*)malloc(sizeof(ConcreteProductB));default:return NULL;}
}
5. 命令模式(Command Pattern)
命令模式将请求封装成对象,从而使你可以用不同的请求对客户端参数化,实现请求的排队、记录日志等功能。
图解命令模式
代码实现
6. 适配器模式(Adapter Pattern)
适配器模式允许将一个类的接口转换成客户端期望的另一个接口,使得原本不兼容的类可以一起工作。
图解适配器模式
代码实现
// 被适配者
typedef struct {void (*specificRequest)(void);
} Adaptee;void adaptee_specific_request(void) {printf("被适配者的特殊请求\n");
}// 目标接口
typedef struct {void (*request)(void);
} Target;// 适配器
typedef struct {Target target;Adaptee* adaptee;
} Adapter;void adapter_request(void* self) {Adapter* adapter = (Adapter*)self;// 转换调用adapter->adaptee->specificRequest();
}Adapter* create_adapter(Adaptee* adaptee) {Adapter* adapter = malloc(sizeof(Adapter));adapter->adaptee = adaptee;adapter->target.request = adapter_request;return adapter;
}
7. 组合模式(Composite Pattern)
组合模式允许你将对象组合成树形结构来表示"部分-整体"的层次结构,使得客户端可以统一处理单个对象和组合对象。
图解组合模式
代码实现
typedef struct Component {void (*operation)(struct Component*);void (*add)(struct Component*, struct Component*);void (*remove)(struct Component*, struct Component*);struct Component* (*getChild)(struct Component*, int);struct Component** children;int childCount;
} Component;// 叶子节点
void leaf_operation(Component* self) {printf("叶子节点操作\n");
}// 组合节点
void composite_operation(Component* self) {printf("组合节点操作\n");for (int i = 0; i < self->childCount; i++) {self->children[i]->operation(self->children[i]);}
}void composite_add(Component* self, Component* child) {self->children[self->childCount++] = child;
}
设计模式的选择与应用
何时使用哪种设计模式?
设计模式最佳实践
-
选择原则
- 优先考虑简单解决方案
- 确保模式能解决实际问题
- 考虑维护成本和团队理解成本
-
实现建议
- 保持接口简单明确
- 注意内存管理
- 考虑线程安全性
- 提供完整的错误处理
-
常见应用场景
- 注意事项
- 避免过度设计
- 保持代码可测试性
- 考虑性能影响
- 确保线程安全
typedef struct {void (*execute)(void);
} Command;typedef struct {Command* command;
} Invoker;void invoker_set_command(Invoker* invoker, Command* command) {invoker->command = command;
}void invoker_execute_command(Invoker* invoker) {if (invoker->command) {invoker->command->execute();}
}
最佳实践与注意事项
1. 回调函数注意事项
- 始终检查回调函数指针是否为 NULL
- 注意回调函数的生命周期管理
- 避免回调函数中的循环引用
- 合理使用上下文(context)传递数据
2. 设计模式使用建议
- 根据实际需求选择合适的设计模式
- 避免过度设计
- 注意内存管理和资源释放
- 保持代码的可维护性和可读性
实战示例:结合回调函数和观察者模式
#include <stdio.h>
#include <stdlib.h>// 观察者接口
typedef struct Observer {void (*update)(struct Observer* self, void* data);void* context;
} Observer;// 主题(Subject)
typedef struct {Observer* observers[10];int count;int data;
} Subject;// 初始化主题
void subject_init(Subject* subject) {subject->count = 0;subject->data = 0;
}// 添加观察者
void subject_attach(Subject* subject, Observer* observer) {if (subject->count < 10) {subject->observers[subject->count++] = observer;}
}// 通知所有观察者
void subject_notify(Subject* subject) {for (int i = 0; i < subject->count; i++) {subject->observers[i]->update(subject->observers[i], &subject->data);}
}// 具体观察者实现
void console_observer_update(Observer* self, void* data) {int* value = (int*)data;printf("控制台观察者收到更新:%d\n", *value);
}void file_observer_update(Observer* self, void* data) {int* value = (int*)data;printf("文件观察者收到更新:%d\n", *value);
}int main() {// 创建主题Subject subject;subject_init(&subject);// 创建观察者Observer console_observer = { console_observer_update, NULL };Observer file_observer = { file_observer_update, NULL };// 注册观察者subject_attach(&subject, &console_observer);subject_attach(&subject, &file_observer);// 更新数据并通知subject.data = 42;subject_notify(&subject);return 0;
}
总结
本指南详细介绍了 C 语言中的回调函数机制和常用设计模式。通过合理运用这些技术,可以编写出更加灵活、可维护的代码。建议读者多加练习,在实际项目中灵活运用这些概念。
进一步学习建议
- 尝试实现更多的设计模式
- 在实际项目中运用回调函数
- 练习内存管理和错误处理
- 研究标准库中的回调函数应用
记住:设计模式是工具而非目标,应该根据实际需求选择合适的模式,避免过度设计。
高级回调函数应用
1. 异步回调实现
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>typedef struct {void (*callback)(void* data);void* data;
} AsyncTask;void* async_worker(void* arg) {AsyncTask* task = (AsyncTask*)arg;// 模拟耗时操作sleep(2);// 执行回调task->callback(task->data);free(task);return NULL;
}void execute_async(void (*callback)(void* data), void* data) {AsyncTask* task = malloc(sizeof(AsyncTask));task->callback = callback;task->data = data;pthread_t thread;pthread_create(&thread, NULL, async_worker, task);pthread_detach(thread);
}// 使用示例
void on_complete(void* data) {printf("异步任务完成,结果:%d\n", *(int*)data);
}int main() {int* value = malloc(sizeof(int));*value = 42;execute_async(on_complete, value);printf("主线程继续执行...\n");sleep(3); // 等待异步任务完成return 0;
}
2. 链式回调
typedef struct ChainCallback {void (*func)(void* data, struct ChainCallback* next);struct ChainCallback* next;void* data;
} ChainCallback;void execute_chain(ChainCallback* chain) {if (chain) {chain->func(chain->data, chain->next);}
}// 示例回调函数
void step1(void* data, ChainCallback* next) {printf("步骤1完成\n");if (next) execute_chain(next);
}void step2(void* data, ChainCallback* next) {printf("步骤2完成\n");if (next) execute_chain(next);
}
3. 事件循环与回调队列
#include <stdio.h>
#include <stdlib.h>#define MAX_CALLBACKS 100typedef struct {void (*func)(void* data);void* data;
} CallbackItem;typedef struct {CallbackItem items[MAX_CALLBACKS];int head;int tail;
} CallbackQueue;void queue_init(CallbackQueue* queue) {queue->head = queue->tail = 0;
}void queue_push(CallbackQueue* queue, void (*func)(void*), void* data) {if ((queue->tail + 1) % MAX_CALLBACKS != queue->head) {queue->items[queue->tail].func = func;queue->items[queue->tail].data = data;queue->tail = (queue->tail + 1) % MAX_CALLBACKS;}
}int queue_pop(CallbackQueue* queue, CallbackItem* item) {if (queue->head != queue->tail) {*item = queue->items[queue->head];queue->head = (queue->head + 1) % MAX_CALLBACKS;return 1;}return 0;
}void event_loop(CallbackQueue* queue) {CallbackItem item;while (1) {if (queue_pop(queue, &item)) {item.func(item.data);}// 可以添加适当的延时}
}
内存管理与安全
1. 回调函数的内存安全
typedef struct {void* data;size_t data_size;void (*cleanup)(void* data);
} SafeCallback;void safe_callback_init(SafeCallback* cb, void* data, size_t size, void (*cleanup)(void*)) {cb->data = malloc(size);memcpy(cb->data, data, size);cb->data_size = size;cb->cleanup = cleanup;
}void safe_callback_execute(SafeCallback* cb, void (*func)(void*)) {if (cb && func) {func(cb->data);}
}void safe_callback_cleanup(SafeCallback* cb) {if (cb) {if (cb->cleanup) {cb->cleanup(cb->data);} else {free(cb->data);}cb->data = NULL;cb->data_size = 0;}
}
2. 引用计数与生命周期管理
typedef struct {int ref_count;void* data;void (*destructor)(void*);
} RefCounted;RefCounted* ref_counted_create(void* data, void (*destructor)(void*)) {RefCounted* rc = malloc(sizeof(RefCounted));rc->ref_count = 1;rc->data = data;rc->destructor = destructor;return rc;
}void ref_counted_acquire(RefCounted* rc) {if (rc) {__atomic_add_fetch(&rc->ref_count, 1, __ATOMIC_SEQ_CST);}
}void ref_counted_release(RefCounted* rc) {if (rc) {if (__atomic_sub_fetch(&rc->ref_count, 1, __ATOMIC_SEQ_CST) == 0) {if (rc->destructor) {rc->destructor(rc->data);}free(rc);}}
}
多线程环境下的设计模式
1. 线程安全的单例模式
#include <pthread.h>typedef struct {int data;
} Singleton;static Singleton* volatile instance = NULL;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;Singleton* get_thread_safe_instance() {Singleton* tmp = instance;if (tmp == NULL) {pthread_mutex_lock(&mutex);tmp = instance;if (tmp == NULL) {tmp = malloc(sizeof(Singleton));tmp->data = 0;instance = tmp;}pthread_mutex_unlock(&mutex);}return instance;
}
2. 生产者-消费者模式
#include <pthread.h>#define BUFFER_SIZE 10typedef struct {void* buffer[BUFFER_SIZE];int count;int in;int out;pthread_mutex_t mutex;pthread_cond_t not_full;pthread_cond_t not_empty;
} BoundedBuffer;void buffer_init(BoundedBuffer* bb) {bb->count = 0;bb->in = 0;bb->out = 0;pthread_mutex_init(&bb->mutex, NULL);pthread_cond_init(&bb->not_full, NULL);pthread_cond_init(&bb->not_empty, NULL);
}void buffer_put(BoundedBuffer* bb, void* item) {pthread_mutex_lock(&bb->mutex);while (bb->count == BUFFER_SIZE) {pthread_cond_wait(&bb->not_full, &bb->mutex);}bb->buffer[bb->in] = item;bb->in = (bb->in + 1) % BUFFER_SIZE;bb->count++;pthread_cond_signal(&bb->not_empty);pthread_mutex_unlock(&bb->mutex);
}void* buffer_get(BoundedBuffer* bb) {pthread_mutex_lock(&bb->mutex);while (bb->count == 0) {pthread_cond_wait(&bb->not_empty, &bb->mutex);}void* item = bb->buffer[bb->out];bb->out = (bb->out + 1) % BUFFER_SIZE;bb->count--;pthread_cond_signal(&bb->not_full);pthread_mutex_unlock(&bb->mutex);return item;
}
3. 线程池模式
typedef struct {void (*function)(void* arg);void* arg;
} Task;typedef struct {Task* tasks;int task_capacity;int task_count;int head;int tail;pthread_t* threads;int thread_count;pthread_mutex_t lock;pthread_cond_t not_empty;pthread_cond_t not_full;int shutdown;
} ThreadPool;ThreadPool* thread_pool_create(int thread_count, int task_capacity) {ThreadPool* pool = malloc(sizeof(ThreadPool));pool->tasks = malloc(sizeof(Task) * task_capacity);pool->task_capacity = task_capacity;pool->task_count = 0;pool->head = 0;pool->tail = 0;pool->threads = malloc(sizeof(pthread_t) * thread_count);pool->thread_count = thread_count;pthread_mutex_init(&pool->lock, NULL);pthread_cond_init(&pool->not_empty, NULL);pthread_cond_init(&pool->not_full, NULL);pool->shutdown = 0;// 创建工作线程for (int i = 0; i < thread_count; i++) {pthread_create(&pool->threads[i], NULL, worker_thread, pool);}return pool;
}void thread_pool_submit(ThreadPool* pool, void (*function)(void*), void* arg) {pthread_mutex_lock(&pool->lock);while (pool->task_count == pool->task_capacity && !pool->shutdown) {pthread_cond_wait(&pool->not_full, &pool->lock);}if (pool->shutdown) {pthread_mutex_unlock(&pool->lock);return;}Task task = {function, arg};pool->tasks[pool->tail] = task;pool->tail = (pool->tail + 1) % pool->task_capacity;pool->task_count++;pthread_cond_signal(&pool->not_empty);pthread_mutex_unlock(&pool->lock);
}
实用技巧与最佳实践
- 异步编程模式
- 使用回调函数处理异步操作
- 实现事件驱动架构
- 处理超时和错误情况
- 内存管理策略
- 使用智能指针模式
- 实现资源获取即初始化(RAII)
- 处理内存泄漏和悬挂指针
- 线程安全考虑
- 正确使用互斥锁和条件变量
- 避免死锁
- 使用原子操作
- 实现线程安全的数据结构
- 错误处理
- 实现统一的错误处理机制
- 使用错误回调
- 合理处理异常情况
- 性能优化
- 减少锁竞争
- 使用无锁数据结构
- 优化内存分配
- 实现高效的缓存策略
调试技巧
- 使用断言验证invariants
- 实现日志系统
- 添加性能计数器
- 使用条件编译进行调试
记住:设计模式是工具而非目标,应该根据实际需求选择合适的模式,避免过度设计。在实际应用中,需要权衡性能、可维护性和复杂度,选择最适合的解决方案。
相关文章:
C 语言高级编程指南:回调函数与设计模式
C 语言高级编程指南:回调函数与设计模式 目录 回调函数详解C语言中的设计模式高级回调函数应用内存管理与安全多线程环境下的设计模式 回调函数详解 1. 什么是回调函数? 回调函数(Callback Function)是一个通过函数指针调用的…...
SeaTunnel系列之:Apache SeaTunnel编译和安装
Apache SeaTunnel编译 Prepare编译克隆源代码本地安装子项目从源代码构建 SeaTunnel构建子模块安装 JetBrains IDEA Scala 插件安装 JetBrains IDEA Lombok 插件代码风格运行简单示例不仅如此 安装下载 SeaTunnel 发布包下载连接器插件从源代码构建 SeaTunnel 运行 SeaTunnel 在…...
zk基础—5.Curator的使用与剖析二
大纲 1.基于Curator进行基本的zk数据操作 2.基于Curator实现集群元数据管理 3.基于Curator实现HA主备自动切换 4.基于Curator实现Leader选举 5.基于Curator实现分布式Barrier 6.基于Curator实现分布式计数器 7.基于Curator实现zk的节点和子节点监听机制 8.基于Curator创…...
bge-m3+deepseek-v2-16b+离线语音能力实现离线文档向量化问答语音版
ollama run deepseek-v2:16b ollama pull bge-m3 1、离线听写效果的大幅度提升。50M 1.3G(每次初始化都会很慢)---优化到首次初始化使用0延迟响应。 2、文档问答历史问题处理与优化,文档问答离线策略讨论与参数暴露。 3、离线大模型答复中断…...
[leetcode]3123. 最短路径中的边(Dijkstra+反向搜索找边)
题目链接 题意 给定n个点的无向图 给定一个edges{u,v,w}数组 表示u到v有一条边权为w的无向边 返回一个bool数组ans,ans[i]1表示edges[i]在任意一条0到n-1的最短路中 思路 先Dijkstra找出最短路再从n-1出发 反向搜索 当前点i,邻接点j,边权…...
构建macOS命令速查手册:基于Flask的轻量级Web应用实践
构建macOS命令速查手册:基于Flask的轻量级Web应用实践 一、项目概述 本文介绍一个基于Flask框架开发的macOS命令速查Web应用。该应用通过结构化的命令数据存储和响应式前端设计,为用户提供便捷的命令查询体验,具备以下特点: 六…...
中国移动启动数字乡村“五新升级”:年底前,行政村5G覆盖达95%
大湾区经济网品牌观察报道,近日,在国家全面推进乡村振兴的战略背景下,中国移动近日发布数字乡村升级行动计划,以“AI大模型数智化平台”为核心引擎,围绕“五新升级”构建“两个新型”信息服务体系。 一、数字基建筑基&…...
借助mcpo在open-webui中使用mcp
open-webui前几天发布了0.6版本,我立即进行了升级。新版本中一个重要功能是通过mcpo方式支持了mcp server。本文将介绍mcpo是什么,以及如何在open-webui中使用它。同时,我也会分享几个在接入过程中遇到的问题及解决方案。 首先来介绍mcpo&…...
Mysql的备份还原
MySQL日志 日志类型 MySQL有几个不同的日志文件,可以帮助你找出mysqld内部发生的事情: 日志文件记入文件中的信息类型错误日志记录启动、运行或停止时出现的问题。查询日志记录建立的客户端连接和执行的语句。二进制日志记录所有更改数据的语句。主要用…...
测试:正交法设计测试用例
目录 一、什么是正交法 二、利用正交表设计测试用例 正交法设计测试用例的步骤 一、什么是正交法 正交法的目的是为了减少测试用例的数量,让尽可能少的用例覆盖两两组合。认识正交表。 最简单的正交表是L4(2^3),含意如下: “L”代表正…...
zk基础—5.Curator的使用与剖析一
大纲 1.基于Curator进行基本的zk数据操作 2.基于Curator实现集群元数据管理 3.基于Curator实现HA主备自动切换 4.基于Curator实现Leader选举 5.基于Curator实现分布式Barrier 6.基于Curator实现分布式计数器 7.基于Curator实现zk的节点和子节点监听机制 8.基于Curator创…...
VSCode中结合DeepSeek使用Cline插件的感受
前言 听网上有传言说AI智能插件Cline非常的好用,而且相对Cursor而言还是免费的,捆绑的大模型选择也比较的广泛。所以,特意安装试用了一下。 我的采用IDE是VSCode,捆绑的大模型是最近比较火的DeepSeek。总体使用下来感觉非常的棒。…...
安卓开发工程师-Java 常用数据结构
1. Java 中的数组和集合有什么区别? 数组: 长度固定:一旦声明,长度不能改变。类型单一:只能存储相同类型的元素。存储效率高:底层是连续的内存空间,访问速度快。示例代码: int[] …...
thinkphp8.0上传图片到阿里云对象存储(oss)
1、开通oss,并获取accessKeyId、accessKeySecret <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><tit…...
Angular 2 模板语法详解
Angular 2 模板语法详解 引言 Angular 2 作为一款强大的前端框架,以其组件化的开发模式和高效的性能被众多开发者所青睐。模板语法是Angular 2中用于定义组件UI的关键部分。本文将详细介绍Angular 2的模板语法,帮助开发者更好地理解和运用这一功能。 模板语法概述 Angula…...
进行性核上性麻痹护理攻略:多维度守护健康
日常起居护理 保证患者居住环境安全,清除地面障碍物,避免患者跌倒。家具摆放固定且合理,方便患者活动。为患者准备宽松、舒适、易于穿脱的衣物,减轻穿衣时的困难。在饮食上,提供富含营养、易于吞咽的食物,…...
MessageQueue --- RabbitMQ WorkQueue
MessageQueue --- RabbitMQ WorkQueue 什么是WorkQueue如何分发RoundRobinFair dispatch (Prefetch) --- 能者多劳 什么是WorkQueue Work queues,任务模型。简单来说就是让多个消费者绑定到一个队列,共同消费队列中的消息。当消息处理比较耗时的时候&…...
Redis内存碎片详解!
目录 一、 什么是内存碎片?🤔二、 为什么 Redis 会有内存碎片呢?🤷♀️三、 如何查看 Redis 内存碎片的信息?🔍四、 如何清理 Redis 内存碎片?🧹五、总结📝 dz…...
如何使用 Nginx 代理 Easysearch 服务
Nginx 是一个高性能的 HTTP 服务器和反向代理服务器,广泛用于负载均衡、缓存、SSL 终端和服务代理等场景。本篇将尝试使用 Nginx 代理 Easysearch 服务,方法同样适用于 Elasticsearch 和 Opensearch。 测试环境 Easysearch 集群版本为 1.10.0ÿ…...
用python输出OLED字模库的符号
提示:博主是小白,如有不足,望海涵和指出 在单片机上练习使用OLED显示屏时,可以看到有个OLED字模库 本文用python将这些字符打印出来,代码如下(本文只适用与128*64的OLED,如果是其它OLED…...
【java】Class.newInstance()
在 Java 中,Class.newInstance()是一个用于创建类的新实例的方法。它调用类的无参构造函数来创建对象。然而,从 Java 9 开始,Class.newInstance()方法已经被标记为废弃,推荐使用其他替代方法。 Class.newInstance()的使用 Class.…...
Apache Arrow 使用
下述操作参考 Building Arrow C — Apache Arrow v20.0.0.dev267 安装依赖组件 sudo apt-get install \build-essential \ninja-build \cmake 下载源码 git clone --recursive --shallow-submodules gitgithub.com:apache/arrow.git 配置 创建build目录并且进入 mkdir a…...
第二届图像处理与人工智能国际学术会议(ICIPAI2025)
重要信息 时间:2025年4月18日-20日 地点:吉林-长春(线上线下结合) 官网:www.icipai.org 简介(部分) 主题 其他 图像处理与人工智能(Image Processing & Artificial Intell…...
Kafka 消息堆积的原因有哪些?
Kafka 产生消息堆积的本质原因是: ⚠️ “消费速度 < 生产速度”,也就是:写入太快,处理太慢。 下面我从实际场景出发,帮你梳理出常见的几种堆积情况,结合原因和例子,便于你对号入座排查问题 …...
解决cline等免费使用deepseek模型的问题
OpenAI、OpenRouter、Claude等都无法在国内免费正常使用,cline作为在vscode中应对cursor比较好的替代方案,怎么使用免费Deepseek,最核心的是在点击模型名称打开配置以下几项: 1、打开VSCode左侧的Cline\Roo Cline插件面板 2、点…...
ROS多设备交互
ROS多设备连接同一个Master:ROS Master多设备连接-CSDN博客 在多个PC端连接同一个ROS Master后,接下来就可以实现不同设备之间的话题交流,Master主机端启动不同PC端的功能包等功能了 尽管多个PC端拥有不同的ROS工作空间,但是只要…...
浅谈 MVVM 模式
MVVM(Model-View-ViewModel) 是一种软件架构设计模式,旨在将用户界面(UI)与业务逻辑分离,从而提高代码的可维护性和可测试性。它在现代前端开发和桌面应用开发中得到了广泛应用,尤其是在构建复杂…...
flutter点击事件教程
在 Flutter 中,处理点击事件是非常常见的操作。Flutter 提供了多种方式来实现用户交互,比如按钮点击、手势检测等。下面是一个详细的教程,帮助你理解如何在 Flutter 中实现点击事件。 一、使用 onPressed 实现按钮点击事件 Flutter 提供了 E…...
[SAP SD] 常用事务码
在SAP系统中,事务码(Transaction Code)是一个具有特定功能的代码标识符,用于快速调用和执行SAP系统内的各种业务模块的功能 /NT-code: 关闭当前业务窗口,退回到SAP初始界面,进入对应的T-Code窗口 /OT-code: 新建SAP GUI窗口&…...
【 <二> 丹方改良:Spring 时代的 JavaWeb】之 Spring Boot 的未来:从微服务到云原生的演进
<前文回顾> 点击此处查看 合集 https://blog.csdn.net/foyodesigner/category_12907601.html?fromshareblogcolumn&sharetypeblogcolumn&sharerId12907601&sharereferPC&sharesourceFoyoDesigner&sharefromfrom_link <今日更新> 一、引子&…...
保留格式地一键翻译英文ppt
我手头上有一个贝叶斯推断的英文ppt,假如我想翻译成中文,整合起来进行pre,你会怎么做? 1,复制粘贴型: 在翻译软件与源文件ppt之间不断流转,效率太低 2,office ppt自带翻译插入整合…...
晶晨S905L3S/S905L3SB_安卓9.0_10秒开机_通刷-线刷固件包
晶晨S905L3S/S905L3SB_安卓9.0_10秒开机_通刷-线刷固件包 线刷方法:(新手参考借鉴一下) 使用晶晨刷机工具USB_Burning_Tool进行刷机;请使用Amlogic USB Burning Tool v2.2.5或v2.2.7(晶晨线刷烧录工具v2.2…...
Android Transition转场动效使用全解析
Transition的使用和原理 项目效果 1. 简述 Android 4.4.2 中引入了 Transition 过渡动画,不过功能比较简单。在 Android 5.0 的 Material Design 中引入更完整和强大的 Transition 框架。通过Transition可以实现: 同一个页面中的场景过渡动画Activit…...
第九章Python语言高阶加强-面向对象篇
目录 一.初始对象 二.成员方法 1.成员变量和成员方法 三.类和对象 四.构造方法 五.其他内置方法(魔术方法) 1.__str__字符串方法 2.__lt__小于符号比较方法 3.__le__小于等于比较符号方法 4.__eq__比较运算符实现方法 六.封装 七.继承 1.继承…...
AI重构SEO关键词智能布局
内容概要 随着人工智能技术在搜索引擎优化领域的深入发展,AI驱动的关键词智能布局正在重塑传统SEO策略的核心逻辑。通过整合自然语言处理、深度学习与语义分析技术,现代SEO系统已形成包含智能分词、意图解码、动态优化的三维技术框架,使关键…...
言同数字:法新社AFP海外新闻媒体发稿成功案例——出海品牌背书必备
作者:言同数字全球传播团队 一、品牌困境:当中国技术遇上海外认知壁垒 案例背景: 某中国光伏储能企业(应保密要求匿名,代号"GreenTech"),其家用储能系统在欧洲市场遭遇࿱…...
第三章 react redux的学习之redux和react-redux,@reduxjs/toolkit依赖结合使用
redux系列文章目录 第一章 简单学习redux,单个reducer 第二章 简单学习redux,多个reducer 第四章 react-redux,reduxjs/toolkit依赖,学习 第五章 两张图告诉你redux常使用的api有哪些 前言 前面两章,我们是只使用的redux的依赖。 本章…...
【HTML】纯前端网页小游戏-戳破彩泡
分享一个简单有趣的网页小游戏 - 彩色泡泡爆破。玩家需要点击屏幕上随机出现的彩色泡泡来得分。 <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-wi…...
【Python使用】嘿马云课堂web完整实战项目第3篇:增加数据,修改数据【附代码文档】
教程总体简介:项目概述 项目背景 项目的功能构架 项目的技术架构 CMS 什么是CMS CMS需求分析与工程搭建 静态门户工程搭建 SSI服务端包含技术 页面预览开发 4 添加“页面预览”链接 页面发布 需求分析 技术方案 测试 环境搭建 数据字典 服务端 前端 数据模型 页面原…...
数据结构【栈和队列附顺序表应用算法】
栈和队列和顺序表应用算法练习 1.栈1.1概念与结构1.2栈的实现 2.队列2.1概念与结构2.2队列的实现 3.附(顺序表应用算法)3.1移除元素3.2删除有序数组中的重复项3.3合并两个有序数组 1.栈 1.1概念与结构 栈:⼀种特殊的线性表,其只…...
Redis数据结构之String
目录 1.概述2.常见操作2.1 SET/GET2.2 MSET/MGET/MSETNX2.3 GETRANGE/SETRANGE2.4 INCR(BY)/DECR(BY)2.5 STRLEN2.6 APPEND2.7 GETSET 3.小结 1.概述 String是最常用的数据类型,一个key对应一个value。String是二进制安全的,可以包含任何数据࿰…...
Maven 远程仓库推送方法
步骤 1:配置 pom.xml 中的远程仓库地址 在项目的 pom.xml 文件中添加 distributionManagement 配置,指定远程仓库的 URL。 xml 复制 <project>...<distributionManagement><!-- 快照版本仓库 --><snapshotRepository><id…...
uname
在 C 语言中,uname 函数用于获取当前操作系统的相关信息。 它是 POSIX 标准的一部分,定义在 <sys/utsname.h> 头文件中。 通过调用 uname 函数,可以获取系统名称、节点名称(主机名)、操作系统版本、机器硬件架构…...
【无标题】object,wait,notifyAll
在 Java 中,Object类提供了wait()方法,用于线程间的协作和同步。wait()方法使得当前线程暂停执行,并释放当前对象的锁,直到其他线程调用该对象的notify()或notifyAll()方法将其唤醒。这是实现线程间通信和同步的重要机制之一。 w…...
【Vue】 核心特性实战解析:computed、watch、条件渲染与列表渲染
目录 一、计算属性(computed) ✅ 示例: 计算属性-methods实现:在插值模块里,实现函数的调用功能 计算属性-computed的实现: 计算属性-简写: ✅ 特点: ⚠️ 与 methods 的区别…...
精品可编辑PPT | 基于湖仓一体构建数据中台架构大数据湖数据仓库一体化中台解决方案
本文介绍了基于湖仓一体构建数据中台架构的技术创新与实践。它详细阐述了数据湖、数据仓库和数据中台的概念,分析了三者的区别与协作关系,指出数据湖可存储大规模结构化和非结构化数据,数据仓库用于高效存储和快速查询以支持决策,…...
基于Python网络爬虫的智能音乐可视化系统(源码+lw+部署文档+讲解),源码可白嫖!
摘要 时代在飞速进步,每个行业都在努力发展现在先进技术,通过这些先进的技术来提高自己的水平和优势,智能音乐可视化系统当然不能排除在外。我本次开发的基于网络爬虫的智能音乐可视化系统是在实际应用和软件工程的开发原理之上,…...
基于STM32与应变片的协作机械臂力反馈控制系统设计与实现----2.2 机械臂控制系统硬件架构设计
2.2 机械臂控制系统硬件架构设计 一、总体架构拓扑 1.1 典型三级硬件架构 #mermaid-svg-MWmxD3zX6bu4iFCv {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-MWmxD3zX6bu4iFCv .error-icon{fill:#552222;}#mermaid-s…...
在线记事本——支持Markdown
项目地址 https://github.com/Anyuersuper/CloudNotebook 百度网盘 通过网盘分享的文件:CloudNotebook-master.zip 链接: https://pan.baidu.com/s/1kd2qNvm0eXc6_7oYDR769A?pwdyuer 提取码: yuer 📝 云笔记 (Cloud Notebook) 云笔记是一个简洁、安全…...
DDPM 做了什么
本博客主要侧重点在于HOW也就是DDPM怎么做的而不是WHY为什么要这样做 那么第一个问题DDPM做了一件什么事:这个算法通过逐渐向原图像添加噪声来破坏图像,然后再学习如何从噪声成恢复图像。 第二件事如何做到的:通过训练一个网络,…...