这篇笔记记录代码的分层,最后用结构体嵌套函数指针来实现层次化代码。
代码的分层:
作为一名驱动工程师,应该了解代码的层级架构,下面是应用代码,OS和驱动程序的整体关系:
当代码复杂后,必须要对代码进行一个分层,只有这样代码才会更合理。同时分层也有助于分工合作,不同层的人写不同层的代码。
层与层之间要通过函数来传递信息,当要传递的信息很多时候,就要用结构体来封装要传递的参数,函数中只需传递结构体指针即可。下面用一个例子来说明代码的层次化结构。
代码调用结果显示如下:
代码一共7个文件;
main.c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include "public.h"
#include "stu.h"
#include "tea.h"
#define STUNUM 2
#define TEANUM 2
Stu stu[STUNUM] = { {"张三",10000,90.1},{ "李四",10001,95.5 } };
Tea tea[TEANUM] = { { "老师1",100,1 },{ "老师2",101,2 } };
int main()
{
int select = 0;
while (1)
{
printf("学生:1\n");
printf("老师:2\n");
scanf("%d", &select);
if (1 == select)
{
Stu_initFun(STUNUM, stu);
}
else if (2 == select)
{
Tea_initFun(TEANUM, tea);
}
else
{
printf("输入非法,退出\n");
break;
}
while (1)
{
printf("1. 显示信息\n");
printf("2. 修改信息\n");
printf("3. 重新选择操作对象\n");
scanf("%d", &select);
if (1 == select)
printFun(); // 打印信息
else if (2 == select)
alterFun();
else
{
break;
}
}
}
return 0;
}
stu.h
#pragma once
#ifndef _STU_
#define _STU_
// 定义学生结构体
typedef struct Student
{
char name[20]; // 名字
int stuNum; // 学号
float score; // 成绩
}Stu;
// 初始化操作,向公共代码注册学生的信息
//
//
extern void Stu_initFun(int n, Stu buf[]);
static void Stu_print(int n, void *buf);
static void Stu_alter(int n, void *buf);
#endif
stu.c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include "stu.h"
#include "public.h"
static struct Register reg = { 0 }; // 初始化0
/* 功能:初始化操作,向“公共代码”注册学生的信息
* 注册信息是:学生结构体数组 和 操作学生数据的函数
* 参数:
* n: 学生结构体数组的元素个数
* buf: 数组首元素指针
*/
void Stu_initFun(int n, Stu buf[])
{
reg.n = n; //学生结构体数组大小
reg.buf = (void *)buf; // 学生数组首元素地址,公共代码不区分类型
reg.print = Stu_print; // 给公共代码传递学生的打印函数指针,让公共代码回调
reg.alter = Stu_alter; // 修改学生数据的函数指针,让公共代码回调。
registerFun(®); // 向公共代码注册:即传递结构体指针,将封装的结构体传递出去。
}
static void Stu_print(int n, void *buf)
{
int i = 0;
Stu *stu = (Stu *)buf;
for (i = 0; i < n; i++)
{
printf("%s,%d,%f\n", stu[i].name, stu[i].stuNum, stu[i].score);
}
}
static void Stu_alter(int n, void *buf)
{
int i = 0;
int stuNum;
Stu *stu = (Stu *)buf;
printf("输入学生学号:");
scanf("%d", &stuNum);
for (i = 0; i < n; i++)
{
if (stu[i].stuNum == stuNum)
{
printf("%s,%d,%f\n",stu[i].name,stu[i].stuNum,stu[i].score);
printf("输入新信息\n");
scanf("%s,%d,%f", stu[i].name, stu[i].stuNum, stu[i].score);
break;
}
}
tea.h
#pragma once
#ifndef _TEA_
#define _TEA_
typedef struct Teacher
{
char name[20]; // 名字
int teaNum; // 学号
int grade; // 级别
}Tea;
void Tea_initFun(int n, Tea buf[]);
static void Tea_print(int n, void *tea);
static void Tea_alter(int n, void *tea);
#endif
tea.c
#define _CRT_SECURE_NO_WARNINGS
#include "tea.h"
#include "public.h"
#include <stdio.h>
static struct Register reg = { 0 };
void Tea_initFun(int n, Tea buf[])
{
reg.n = n;
reg.buf = (void *)buf;
reg.print = Tea_print;
reg.alter = Tea_alter;
registerFun(®); // 与stu 同理,向public注册
}
static void Tea_print(int n, void *buf)
{
int i = 0;
Tea *tea = (Tea *)buf;
for (i = 0; i < n; i++)
{
printf("%s,%d,%d\n",tea[i].name,tea[i].teaNum,tea[i].grade);
}
}
static void Tea_alter(int n, void *buf)
{
int i = 0;
int teaNum;
Tea *tea = (Tea *)buf;
printf("输入教师号: ");
scanf("%d", &teaNum);
for (i = 0; i < n; i++)
{
if (tea[i].teaNum == teaNum)
{
printf("%s,%d,%f\n", tea[i].name, tea[i].teaNum, tea[i].grade);
printf("输入新信息:");
scanf("%s,%d,%f", tea[i].name, tea[i].teaNum, tea[i].grade);
break;
}
}
}
public.h
#pragma once
#ifndef _PUBLIC_
#define _PUBLIC_
struct Register
{
void *buf; // 数组的第一个元素
int n; // 数组的元素个数
void(*print)(); // 定义函数指针,用于指向打印函数
void(*alter)(); // 定义函数指针,用于指向修改函数
};
extern void registerFun(struct Register *reginfo);
extern void printFun(void);
extern void alterFun(void);
#endif
public.c
#pragma once
#include <stdio.h>
#include "public.h"
// 保存差异代码注册的reg 结构体,结构体里面保存了差异代码的函数指针
struct Register *regp = NULL;
extern void registerFun(struct Register *reginfo)
{
regp = reginfo;
}
extern void printFun(void)
{
// 通过注册的reg信息,调用差异代码的显示函数
// 如果注册的是“学生操作信息”,调用的就是学生的显示函数,
regp->print(regp->n, regp->buf);
}
extern void alterFun(void)
{
regp->alter(regp->n, regp->buf);
}