【嵌入式C快捷键设计】表驱动法实现

表驱动法的优势

这种设计实现了数据驱动的编程模式,将配置信息(快捷键映射)与执行逻辑分离,是嵌入式系统中实用的设计模式。具有维护性好、代码复用高、拓展性好等优点。

表驱动法的原理

将程序逻辑从代码转移到数据,通过查询数据表来决定程序行为,而不是通过复杂的控制逻辑。

表驱动法的核心原理是:通过数据配置来代替硬编码的逻辑判断,利用函数指针机制实现动态调用。

案例实战

cpp 复制代码
#include <stdio.h>
#include <string.h>
#include <stdint.h>

// 类型定义
typedef int32_t (*T_SHORTCUT_CALLBACK)(void);

#define SHORTCUT_MAX_ID_LEN 20
#define SHORTCUT_END_STR "end"

// 快捷键列表结构体
typedef struct {
	char id[SHORTCUT_MAX_ID_LEN + 1];
	T_SHORTCUT_CALLBACK cb;
	const char *description;  // 添加描述信息便于演示
} T_SHORTCUT_LIST;

// 定义返回码
typedef enum {
	eMENU_RESULT_SUCCESS = 0,
	eMENU_RESULT_FAIL = -1
} menu_result_t;

// 模拟权限验证函数
int app_is_second_user_verify(void) {
	return 0; // 假设总是有权限
}


void app_menu_exit_flag_clear(void) {
	printf("清理菜单退出标志\n");
}

// 具体的快捷键处理函数
int32_t save_function(void) {
	printf("执行保存操作...\n");
	printf("文件保存成功!\n");
	return eMENU_RESULT_SUCCESS;
}

int32_t print_function(void) {
	printf("执行打印操作...\n");
	printf("文档打印完成!\n");
	return eMENU_RESULT_SUCCESS;
}

int32_t help_function(void) {
	printf("   显示帮助信息:\n");
	printf("   save  - 保存文件\n");
	printf("   print - 打印文档\n");
	printf("   help  - 显示帮助\n");
	printf("   time  - 显示时间\n");
	printf("   exit  - 退出程序\n");
	return eMENU_RESULT_SUCCESS;
}

int32_t time_function(void) {
	printf("  当前时间: 2024-01-01 12:00:00\n");
	return eMENU_RESULT_SUCCESS;
}

int32_t exit_function(void) {
	printf("  感谢使用,再见!\n");
	return eMENU_RESULT_SUCCESS;
}

// 快捷键映射表
static const T_SHORTCUT_LIST app_shortcut_list[] = {
	{"save",  save_function,  "保存文件"},
	{"print", print_function, "打印文档"},
	{"help",  help_function,  "显示帮助"},
	{"time",  time_function,  "显示时间"},
	{"exit",  exit_function,  "退出程序"},
	{SHORTCUT_END_STR, NULL, "结束标记"}  // 必须放在最后!
};

// 快捷键处理函数
int8_t app_shortcut_handle(const char *key_buff) {
	uint16_t i = 0;

	printf("\n   正在查找快捷键: '%s'\n", key_buff);

	while(1) {


		// 检查是否匹配当前快捷键
		if(strcmp(app_shortcut_list[i].id, key_buff) == 0) {
			printf("  找到匹配的快捷键: %s -> %s\n",
			       app_shortcut_list[i].id, app_shortcut_list[i].description);


			// 执行回调函数
			printf("  开始执行回调函数...\n");
			int32_t ret = app_shortcut_list[i].cb();

			printf("  函数执行结果: %d\n", ret);
			return ret;
		}
		// 检查是否到达列表末尾
		else if(strcmp(app_shortcut_list[i].id, SHORTCUT_END_STR) == 0) {
			printf("  未找到匹配的快捷键: '%s'\n", key_buff);
			printf("  可用命令: save, print, help, time, exit\n");
			return eMENU_RESULT_FAIL;
		}

		i++;
	}
}

// 显示欢迎信息
void show_welcome(void) {
	printf("=====================================\n");
	printf("  表驱动法快捷键演示程序\n");
	printf("=====================================\n");
	printf("这是一个演示表驱动法处理快捷键的示例\n");
	printf("使用 scanf 接收用户输入\n\n");
}

// 显示快捷键列表
void show_shortcut_list(void) {
	printf("  可用的快捷键列表:\n");
	printf("-----------------------------\n");

	int i = 0;
	while(strcmp(app_shortcut_list[i].id, SHORTCUT_END_STR) != 0) {
		printf("  %-8s - %s\n",
		       app_shortcut_list[i].id,
		       app_shortcut_list[i].description);
		i++;
	}
	printf("-----------------------------\n");
}

int main(void) {
	char input[SHORTCUT_MAX_ID_LEN + 1];

	show_welcome();
	show_shortcut_list();

	// 主循环
	while(1) {
		printf("\n    请输入快捷键 (输入 exit 退出): ");

		// 使用scanf接收输入
		if(scanf("%20s", input) != 1) {
			printf("  输入错误,请重新输入\n");
			while(getchar() != '\n'); // 清空输入缓冲区
			continue;
		}

		// 处理快捷键
		int8_t result = app_shortcut_handle(input);

		if(strcmp(input, "exit") == 0) {
			break; // 退出程序
		}

		if(result == eMENU_RESULT_FAIL) {
			printf("快捷键处理失败\n");
		}
	}

	printf("\n=====================================\n");
	printf("   程序正常结束\n");
	printf("=====================================\n");

	return 0;
}
  • typedef:用于定义新类型的关键字。

  • int32_t:函数的返回值类型,通常是一个32位有符号整数(需要包含stdint.h头文件)。

  • (*T_SHORTCUT_CALLBACK)T_SHORTCUT_CALLBACK是一个指针,指向函数。

  • (void):函数的参数列表,这里表示没有参数。

所以,这个定义之后,我们可以使用T_SHORTCUT_CALLBACK来声明一个函数指针变量,该变量可以指向任何返回值类型为int32_t且无参数的函数。

相关推荐
stormsha44 分钟前
Java 设计模式探秘饿汉式与懒汉式单例模式的深度解析
java·单例模式·设计模式·java-ee
f***45321 小时前
Spring Boot 经典九设计模式全览
java·spring boot·设计模式
The Last.H2 小时前
Educational Codeforces Round 185 (Rated for Div. 2)A-C
c语言·c++·算法
松涛和鸣4 小时前
DAY20 Optimizing VS Code for C/C++ Development on Ubuntu
linux·c语言·开发语言·c++·嵌入式硬件·ubuntu
unclecss4 小时前
从 0 到 1 手写 Linux 调试器:ptrace 系统调用与断点原理
linux·运维·服务器·c语言·ptrace
fashion 道格5 小时前
从地图导航到数据结构:解锁带权有向图的邻接链表奥秘
c语言·数据结构·链表
猿大叔~5 小时前
面试必问!Linux 下 C/C++ 内存对齐深度解析:从底层原理到实战避坑
linux·c语言·面试
C++ 老炮儿的技术栈6 小时前
用密码学安全随机数生成256位密钥
c语言·开发语言·c++·windows·安全·密码学·visual studio
swibyn6 小时前
【无标题】
c语言·素数
口袋物联7 小时前
设计模式之单例模式在 C 语言中的应用(含 Linux 内核实例)
c语言·单例模式·设计模式