• 13_C++_编译过程_递归函数_面向接口


    编译过程

    include的区别

    1. include后面接" " → \rightarrow file1.c所在的当前目录找file1.h,如果找不到系统指定的目录检索
    2. include后面接< > → \rightarrow 表示系统直接系统指定的目录检索
    3. #include <>常用于包含库函数的头文件;#include ""常用于包含自定义的头文件

    宏定义

    宏常量

    #define num 100在预编译时将宏名替换成字符串的过程称为**“宏展开”。宏定义,只在宏定义的文件**中起作用。
    注意事项:

    1. 宏定义不作语法检查,只有在编译被宏展开后的源程序才会报错
    2. 宏名有效范围为从定义到本源文件结束,可以用#undef命令终止宏定义的作用域
    3. 宏定义中可以引用已定义的宏名

    宏函数

    #define SUM(x,y) (( x )+( y ))
    void test(){
    	
    	//仅仅只是做文本替换 下例替换为 int ret = ((10)+(20));
    	//不进行计算
    	int ret = SUM(10, 20);
    	printf("ret:%d\n",ret);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    注意事项:

    1. 宏的名字中不能有空格,但是在替换的字符串中可以有空格
    2. 括号括住每一个参数,并括住宏的整体定义
    3. 假如在程序中只使用一次对程序的运行时间没有太大提高

    条件编译

    作用 → \rightarrow 防止文件被重复引用
    条件编译的三个基本类型

    #ifndef _SOMEFILE_H
    #define _SOMEFILE_H
    
    //需要声明的变量、函数
    //宏定义
    //结构体
    
    #endif
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    一些特殊的预定宏

    名字意义
    __FILE__宏所在文件的源文件名 → \rightarrow 打印的是绝对路径
    __LINE__宏所在行的行号
    __DATE__代码编译的日期
    __TIME__代码编译的时间

    静态库的封装和使用

    库的概念

    1. 库可以简单看成一组目标文件的集合,将这些目标文件经过压缩打包之后形成的一个文件
    2. 像在Windows这样的平台上,最常用的c语言库是由集成开发环境所附带的运行库,这些库一般由编译厂商提供;

    windows下静态库创建和使用

    案例:配置一个简单的静态库

    Step1:在VS中创建新项目,写静态库的.c源文件和.h头文件

    .c源文件:

    #include
    #include
    #include
    
    void welcome() 
    {
    	printf("Hello World!!!\n");
    	return 0;
    }
    
    void printMessages() 
    {
    	printf("The date is %s, and the time is %s.\n", __DATE__, __TIME__);
    	return 0;
    }
    
    int valueSum(int a, int b) 
    {
    	return a + b;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    .h头文件

    #pragma once
    
    
    // 欢迎函数,输出“Hello World”到屏幕上
    void welcome();
    
    // 打印编译过程的时间和日期信息
    void printMessages();
    
    // 进行两数相加的运算
    int valueSum(int a, int b);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    Step2:生成静态库

    右键解决方案的名字 → \rightarrow 属性 → \rightarrow 常规 → \rightarrow 配置类型(下拉菜单) → \rightarrow 选择静态库(.lib) → \rightarrow 返回到代码编写界面 → \rightarrow 点击生成按钮 → \rightarrow 当生成\StaticLib\x64\Debug\StaticLib.lib时,生成成功

    Step3:检查静态库是否生成

    鼠标点击.c源文件 → \rightarrow 右键 → \rightarrow 打开所在的文件夹 → \rightarrow 进入x64文件 → \rightarrow 进入debug文件 → \rightarrow 当出现**.lib**文件后,说明静态库生成

    Step4:调用静态库

    查看这个文章:

    使用VS生成本地静态库文件以及静态库文件的使用

    在新建的解决方案中增加main.c文件,写入以下代码:

    #include
    #include
    #include
    #include"StaticLib.h"
    
    int main() 
    {
    	welcome();
    	printMessages();
    	printf("%d\n", valueSum(5, 8));
    	system("pause");
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    编译后的结果是:

    Hello World!!!
    The date is Aug  1 2022, and the time is 13:01:13.
    13
    请按任意键继续. . .
    
    • 1
    • 2
    • 3
    • 4

    静态库和动态库的优缺点

    静态库

    优点 → \rightarrow 生成的exe程序中包含了静态库中的内容,与静态库无瓜葛
    缺点 → \rightarrow 浪费资源,更新发布比较麻烦

    动态库

    优点 → \rightarrow 运行阶段才去链接函数

    动态库的封装和使用

    查看这个文章:

    VS生成和使用动态库(.dll)

    具体代码与静态库的一样。

    动态库封装细节

    __declspec(dllexport)】动态链接库中定义有两种函数:导出函数(export function)和内部函数(internal function)。 导出函数可以被其它模块调用,内部函数在定义它们的DLL程序内部使用。
    【动态库的lib文件和静态库的lib文件的区别】对一个DLL文件来说,其引入库文件(.lib)包含该DLL导出的函数变量的符号名,而.dll文件包含该DLL实际的函数和数据。

    递归函数

    递归函数就是直接或间接调用自身的函数。
    注意:必须要有结束的条件,否则会死循环

    递归函数案例1——逆序打印字符数组

    int reverse1(char *str){
    	if (str == NULL)
    	{
    		return -1;
    	}
    	if (*str == '\0') // 函数递归调用结束条件
    	{
    		return 0;
    	}	
    	reverse1(str + 1);
    	printf("%c", *str);
    	return 0;
    }
    char buf[1024] = { 0 };  //全局变量
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    递归案例2——斐波那契数列

    #include
    #include
    #include
    
    int Fibonacci(int ss) 
    {
    	if ((ss == 1) || (ss == 2) )
    	{
    		return 1;
    	}
    	return Fibonacci(ss - 1) + Fibonacci(ss - 2);
    
    }
    
    
    void test(int s) 
    {
    	for (int i=0;i<s;i++)
    	{
    		if (i == 0) 
    		{
    			continue;
    		}
    		int res = Fibonacci(i);
    		printf("%d\n", res);
    	}
    	
    }
    
    
    int main() 
    {
    	test(20);
    
    	system("pause");
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    生成的结果是:

    1
    1
    2
    3
    5
    8
    13
    21
    34
    55
    89
    144
    233
    377
    610
    987
    1597
    2584
    4181
    请按任意键继续. . .
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    面向接口

    背景:一般的企业信息系统都有成熟的框架。
    软件框架一般不发生变化,能自由的集成第三方厂商的产品。
    要求在企业信息系统框架中集成第三方厂商的游戏功能产品。
    软件设计要求:能够满足用户需求,完成的产品可以与用户完美对接。

    1. 抽象游戏中玩家结构体设计(struct Player)
    2. 框架接口设计(playGame)
      初始化游戏
      核心功能战斗
      查看玩家信息
      结束游戏
    3. 游戏厂商1入围(GameCompany1)
      游戏厂商2入围(GameCompany2)
    4. 框架接口分文件编写
  • 相关阅读:
    安装mongodb数据库
    Spring Boot 的文件配置
    探索AI视觉技术新应用,夸克扫描王首推“离线模式”端侧AI算法提升隐私安全
    数字孪生论文阅读笔记【1】
    实时通信的方式——WebRTC
    用C++11 make_shared替代shared_ptr
    JAVA基础 - URI、URL和URN的区别
    MES管理系统功能模块之质量管理
    CentOS7.8安装配置OpenLDAP
    Github 2024-03-12开源项目日报 Top10
  • 原文地址:https://blog.csdn.net/m0_48948682/article/details/126097947