链表反转作业
利用3个辅助指针,实现链表反转
提供返回链表节点个数 函数
示例
reverseLinkList(struct LinkNode* pHeader) //反转链表
{
if (pHeader == NULL)
{
return
}
struct LinkNode* pPre = NULL
struct LinkNode* pCurrent = pHeader->next
struct LinkNode* nextNode =NULL
while (pCurrent != NULL)
{
nextNode = pCurrent->next
pCurrent->next =pPre
pPre = pCurrent
pCurrent =nextNode
}
pHeader->next = pPre
}
int sizeLinkList(struct LinkNode* pHeader) //返回链表节点个数
{
if (pHeader == NULL)
{
return -1
}
struct LinkNode* pCurrent = pHeader->next
int num = 0
while (pCurrent != NULL)
{
num++
pCurrent = pCurrent->next
}
return num
}
回调函数作业-实现对任意数据类型数组进行排序
利用选择排序实现大框架
对比功能交还给用户指定
利用回调函数技术来实现对比
示例
void selectSort(void * pAddr,int eleSize,int len,int (*myCompare)(void *,void *))
{
char* temp = malloc(eleSize)
for (size_t i = 0
{
int minOrMax = i
for (size_t j = i+1
{
//定义出j元素的地址
char* pJ =(char*)pAddr + eleSize * j
char* pMinOrMax = (char*)pAddr + eleSize * minOrMax
//if(pAddr[j]<pAddr[minOrMax])
if (myCompare(pJ,pMinOrMax))
{
minOrMax = j
}
}
if (i != minOrMax)
{
//交换i和minOrMin 下标元素
char* pI = (char*)pAddr + i * eleSize
char* pMinOrMax = (char*)pAddr + eleSize * minOrMax
memcpy(temp, pI, eleSize)
memcpy(pI, pMinOrMax, eleSize)
memcpy(pMinOrMax, temp, eleSize)
}
}
if (temp != NULL)
{
free(temp)
temp = NULL
}
}
int myCompareInt(void * data1,void *data2)
{
int* num1 = data1
int* num2 = data2
if (*num1 > *num2)//从大到小排序
{
return 1
}
return 0
}
void test01()
{
int arr[] = { 10,30,20,40,50,60 }
int len = sizeof(arr) / sizeof(int)
selectSort(arr, sizeof(int), len, myCompareInt)
for (size_t i = 0
{
printf("%d\n", arr[i])
}
}
struct Person
{
char name[64]
int age
}
int myCompareStruct(void* data1, void* data2)
{
struct Person* p1 = data1
struct Person* p2 = data2
if (p1->age < p2->age)
{
return 1
}
return 0
}
void test02()
{
struct Person pArray[] =
{
{"aaa",10},{"bbb",30},{"ccc",20},{"ddd",40}
}
int len = sizeof(pArray) / sizeof(struct Person)
selectSort(pArray, sizeof (struct Person), len, myCompareStruct)
for (size_t i = 0
{
printf("name = %s age = %d\n”, pArray[i].name, pArray[i].age)
}
}
int main(void)
{
test01()
test02()
system("pause")
return EXIT_SUCCESS
}
预处理指令
头文件 #include
<> “”区别
<> 包含系统头
“” 包含自定义头
宏
宏常量
不重视作用域
没有数据类型
利用 #undef 卸载宏
宏函数
将频繁、短小函数写成宏函数
优点:以空间换时间
条件编译
#ifdef #else #endif 测试存在
#ifndef #else #endif 测试不存在
#if #else #endif 自定义条件编译
特殊宏
__FILE__ 宏所在文件路径
__LINE__ 宏所在行
__DATE__ 宏编译日期
__TIME__ 宏编译时间
示例
# define MAX 1024
#define DEBUG
#ifdef DEBUG
void func()
{
printf("DEBUG版本发布\n");
}
#else
void func()
{
printf("Release版本发布\n");
}
#endif
#if 0
#else
#endif
void doWork(char* p)
{
if (p == NULL)
{
printf("文件:%s 第 %d 行出错了\n", __FILE__, __LINE__);
printf("日期: %s\n", __DATE__);
printf("时间:%s\n", __TIME__);
}
return;
}
void test02()
{
doWork(NULL);
}
int main(void)
{
printf("MAX = %d\n", MAX);
func();
test02();
system("pause");
return EXIT_SUCCESS;
}
静态库配置
右键项目->属性 ->常规->配置类型 ->静态库
生成项目 生成.lib文件
将.lib和 .h交给用户
测试

动态库配置
静态库优缺点
1. 静态库对库函数的链接是放在编译时期完成的,静态库在程序的链接阶段被复制到了程序中,跟程序的运行没有任何关系。
好处 在于二者之间没有关联了,程序在运行时与函数库再无瓜葛,移植方便。
坏处1 在于浪费空间和资源,所有相关的目标文件与牵扯到的函数库被链接合成一个可执行文件。
坏处2 静态链接对程序的更新、部署也比较麻烦。
动态库
针对空间浪费和更新困难两个问题,最简单的办法就是把程序的模块相互分隔开来,形成独立的文件,
把链接过程推迟到了运行时再进行。
====================================================
1. 右键项目->属性 ->常规->配置类型 ->动态库 .dll
2. 生成项目 生成 .lib .dll
静态库中生成的.lib和动态库生成的.lib是不同的。
动态库中的.lib只会放变量的声明和 导出函数的声明,函数实现体放在.dll中
3. 导出函数/外部函数 : __declspec(dllexport)int mySub(int a, int b);
4. 测试
#pragma comment( lib,"./mydll.lib")

递归函数
普通函数调用流程


递归函数调用流程


本质:函数自身调用自身
注意事项:递归函数必须有结束条件,函数有出口
案例1 利用递归实现字符串逆序遍历

void reversePrint(char *p)
{
if (*p == '\0')
{
return;
}
reversePrint(p + 1);
printf("%c\n", *p);
}
void test01()
{
char* str = "abcdefg";
reversePrint(str);
}
int main(void)
{
test01();
system("pause");
return EXIT_SUCCESS;
}
案例2 斐波那契数列
int fibonacci(int pos)
{
if (pos == 1 || pos == 2)
{
return 1;
}
return fibonacci(pos - 1) + fibonacci(pos - 2);
}
void test02()
{
//斐波那契数列
// 1 1 2 3 5 8 13 ....
printf("第10位数字为多少 %d\n", fibonacci(10));
}
面向接口封装案例
案例背景
一般的企业信息系统都有成熟的框架。软件框架一般不发生变化,能自由的集成第三方厂商的产品。
案例需求
要求在企业信息系统框架中集成第三方厂商的游戏功能产品。软件设计要求:能够满足用户需求,完成的产品可以与用户完美对接。
案例要求
1)能支持多个厂商的游戏功能产品入围
2)能够实现第三方产品和用户产品的对接
3)系统整体框架不轻易发生改变
编程提示
1)抽象游戏中玩家结构体设计(struct Player)
2)框架接口设计(playGame)
a) 初始化游戏
b) 核心功能战斗
c) 查看玩家信息
d) 结束游戏
3) a) 游戏厂商1入围(GameCompany1)
b) 游戏厂商2入围(GameCompany2)
4)框架接口分文件编写
案例实现
1. 甲乙两方设计接口
2. 甲方实现代码
typedef void(*INIT_GAME)(void** player, char* name);
typedef int(*FIGHT_GAME)(void* player, int gameDiff);
typedef void(*PRINT_GAME)(void* player);
typedef void(*EXIT_GAME)(void* player);
void playerGame(INIT_GAME init, FIGHT_GAME fight, PRINT_GAME printGame, EXIT_GAME exitGame)
{
void* player = NULL;
printf("请输入姓名 \n");
char userName[64];
scanf("%s", userName);
init(&player, userName);
int diff = -1;
printf("请选择游戏难度: \n");
printf("1/简单\n");
printf("2/中等\n");
printf("3/困难\n");
scanf("%d", &diff);
int ret = fight(player, diff);
if (ret == 0)
{
printf("defeat\n");
}
else
{
printf("victory,player info is as following: \n");
printGame(player);
}
exitGame(player);
}
int main(void)
{
system("pause");
return EXIT_SUCCESS;
}
乙方实现代码
乙方头文件内容
struct Player
{
char name[64];
int level;
int exp;
};
void INIT_GAME_COM1(void** player, char* name);
int FIGHT_GAME_COM1 (void* player, int gameDiff);
void PRINT_GAME_COM1 (void* player);
void EXIT_GAME_COM1 (void* player);
int isWin(int winRate, int diff);
乙方实现
#include "gameCompany1.h"
void INIT_GAME_COM1(void** player, char* name)
{
struct Player* player1 = malloc(sizeof(struct Player));
if (player1 == NULL)
{
printf("初始化失\n");
return;
}
*player = player1;
strcpy(player1->name, name);
player1->level = 0;
player1->exp = 0;
}
int FIGHT_GAME_COM1(void* player, int gameDiff)
{
struct Player* player1 = player;
int addExp = 0;
switch (gameDiff)
{
case 1:
addExp = isWin(90, 1);
break;
case 2:
addExp = isWin(50, 2);
break;
case 3:
addExp = isWin(30, 3);
break;
default:
break;
}
player1->exp += addExp;
player1->level = player1->exp / 10;
if (addExp == 0)
{
return 0;
}
else
{
return 1;
}
}
int isWin(int winRate, int diff)
{
int random = rand() % 100 + 1;
if (random <= winRate)
{
return diff * 10;
}
else
{
return 0;
}
}
void PRINT_GAME_COM1(void* player)
{
struct Player* player1 = player;
printf("玩家<%s> -----当前等级:<%d>级----当前经验:<%d>\n", player1->name, player1->level, player1->exp);
}
void EXIT_GAME_COM1(void* player)
{
if (player == NULL)
{
return;
}
free(player);
player == NULL;
}
接口对接
甲方加入乙方的头文件
int main(void)
{
srand((unsigned int)time(NULL));
playGame(INIT_GAME_COM1, FIGHT_GAME_COM1, PRINT_GAME_COM1, EXIT_GAME_COM1);
system("pause");
return EXIT_SUCCESS;
}