模块化编程(C语言)

1.什么是模块化编程

模块化编程就是我们一个复杂的项目分成很多模块,比如一个单片机项目,就可能分为:主函数模块,液晶显示和数码管显示模块,时间延时模块,温度传感器模块等。
而一个程序工程包含多个源文件(.c 文件和 .h 文件),每个 .c 文件可以被称为一个模块,每一个模块都有其各自的功能,而每一个.h文件则是声明该模块,相当于功能说明书 模块化编程在嵌入式中是必须要掌握的技能。

2.模块化编程的好处

开发C程序时,当代码量较大功能较复杂时,单一文件程序会使得文件非常巨大,代码量非常大,成千上万行的代码在一个文件中不便于修改和维护,因此需要将不同的功能模块放在不同的文件中。
并且在团队合作开发的时候,需要模块化开发。每个人负责一部分功能的开发,而你所负责的模块,你需要将你负责的模块功能写好,封装好,之后形成一个.c与.h ,然后交付给项目组长,组长则负责整体框架(main)的编写与各个模块的组合调试,最后各个模块的组合,形成了整个工程。
由此可见,模块化可以有效的提高团队开发的分工协作效率。对于整个项目开发有着很大的好处

3.模块化开发过程如下

1)创建.c文件(xxx.c)
2)在.c文件内定义需要的函数
3)创建.h文件,文件名要与.c文件一致
4)在.h文件中声明在.c中定义的函数
5)在main.c文件中包含.h文件,在main函数直接调用自定义的函数

4.模块化的具体代码实现

4.1 举一个简单的例子
在这里插入图片描述
1)hello.h

// 也可以省略 extern,不过为了程序可读性,建议都写上

#ifndef _HELLO_H_//如果一个文件包含了此头文件多次,使用这种方法,即在第一次编译时没有定义xxx的宏,执行了下面的所有,第二次再遇到编译此文件时xxx已经被定义,就不会再编译
 // 使用条件编译可以避免重复编译
 // 需要注意的是要使用#ifndef语句
#define _HELLO_H_

extern int add(int a, int b);
extern int jiecheng(int n);
extern int sum(int x);
extern int qiupingfanghe(int n);

#endif

函数后面的分号(;)不要忘了。

#ifndef XXX 表示如果没有定义 xxx 则执行后面的语句 如果已经定义则不执行,

#define xxx 定义一个预处理宏定义,

#endif 表示条件命令的结束

我们这里#ifndef HELLO_H #define HELLO_H 表示如果没有定义hello.h这个头文件,则定义hello.h 并且后面的语句都有效,直到#endif 结束命令为止。

附:c语言中条件编译相关的预编译指令
在这里插入图片描述

2)hello.c

#include "stdio.h"
#include "hello.h"

void printC()
{
    printf("hello,欢迎!\n");
}

//加法函数
int add(int a, int b)
{
    return a + b;
}

//阶乘函数
int jiecheng(int n)
{
    if (n <= 0)
    {
        return 1;
    }

    int result = 1;
    for (int i = 1; i <= n; i++)
    {
        result *= i;
    }
    return result;
}

//求和函数
int sum(int n)
{
    int i, sum = 0;
    for (i = 1; i <= n; i++)
    {
        sum = sum + i;
    }
    return sum;
}

//求平方和函数
int qiupingfanghe(int n)
{
    int i, s = 0;
    for (i = 1; i <= n; i++)
    {
        s += (i * i);
    }
    return s;
}

hello.c文件中引入了hello.h这个头文件,于是在这个hello.c文件中就可以使用这些在头文件中定义的内容,编译代码时只需要指定hello.c,编译器会根据#include "hello.h"找到这个头文件,注意hello.h和hello.c要存放在同一个目录下。
hello.h和hello.c便构成了一个模块。
3)main.c

#include "stdio.h"
#include "hello.h"

int main()
{
	int a, b, n, x;

	printC();
	printf("请输入:\n");
	scanf_s("%d%d%d%d", &a, &b, &n, &x);

	printf("输出的值:%d\n", add(a, b));
	printf("输出的值:%d\n", jiecheng(n));
	printf("输出的值:%d\n", sum(x));
	printf("输出的值:%d\n", qiupingfanghe(n));

	return 0;
}

头文件存放的位置有两种情况:
情况1:存放在系统(IDE/0s等)提供的专门的目录下,系统头文件(比如stdio.h)都是放在了这些专门的目录下。
情况2:放在c工程项目自己所在的目录下,我们自己写的头文件,都放在了我们自己的c工程项目所在的文件夹。

<>和" "的区别

  1. 使用<>包含头文件时,编译器会直接到系统提供的专门目录找头文件,包含系统头文件时,都是用<>,因为系统头文件.
    是直接放在了这个专门的目录下。
  2. 使用"“包含头文件时,”“比<>多一个步骤,
    第一步:编译器首先到c工程项目所在文件夹下找
    第二步:找不到时再到系统专门的目录下找。
    包含自己写的头文件时,我们都是用”“的方式,因为自己写的头文件,都放在了c工程项目所在的文件夹下。这也说明了include<stdio.h>,是可以改写成include"stdio.h”。

使用<>包含自己写的hello.h时, 为什么有错?
<>方式只会到系统的专门目录找,而我自己写的头文件放在了c工程项目所在文件夹,根本找不到。
换""方式时,编译器会先到c工程项目所在目录下找,找不到再到系统专门目录下找,我们自己写的都放在c工程项目所在目录,因此肯定能找到自己写的hello.h头文件。

另外include不仅仅能包含.h类型的头文件,理论上它可以包含任意类型的文件,例如包含一个.c文件等,但我们通常都用于包含.h类型的头文件。

注:程序中引入了 #include "stdio.h"头文件,是因为我们使用了printf scanf 语句进行数据的打印与获取,而printf和scanf语句的定义则是在stdio.h中,用户只需要负责调用即可。

编译运行结果是:
在这里插入图片描述
4.2 多模块编程
在这里插入图片描述
1)hello.h文件

// 也可以省略 extern,不过为了程序可读性,建议都写上

#ifndef _HELLO_H_
#define _HELLO_H_

extern int add(int a, int b);
extern int jiecheng(int n);
extern int sum(int x);
extern int qiupingfanghe(int n);

#endif

2)hello.c文件

#include "stdio.h"//包含了标准输入输出头文件,
#include "hello.h"
#include "world.h"

//加法函数
int add(int a, int b)
{
    printC();//用到了world.c文件中定义的函数
    return a + b;
}

//阶乘函数
int jiecheng(int n)
{
    if (n <= 0)
    {
        return 1;
    }

    int result = 1;
    for (int i = 1; i <= n; i++)
    {
        result *= i;
    }
    return result;
}

//求和函数
int sum(int n)
{
    int i, sum = 0;
    for (i = 1; i <= n; i++)
    {
        sum = sum + i;
    }
    return sum;
}

//求平方和函数
int qiupingfanghe(int n)
{
    int i, s = 0;
    for (i = 1; i <= n; i++)
    {
        s += (i * i);
    }
    return s;
}

因为hello.c文件用到了printC函数,而它是被定义在world模块里,因此需要添加world模块才能使用我们定义的函数,所以就有了#include “world.h”
3)world.h文件

#ifndef _WORLD_H_
#define _WORLD_H_

extern void printC();

#endif

4)world.c文件

#include "stdio.h"
#include "world.h"

void printC()
{
    printf("hello,欢迎!\n");
}

5)main.c文件

#include "stdio.h"
#include "hello.h"

int main()
{
	int a, b, n, x;

	printf("请输入:\n");
	scanf_s("%d%d%d%d", &a, &b, &n, &x);

	printf("输出的值:%d\n", add(a, b));
	printf("输出的值:%d\n", jiecheng(n));
	printf("输出的值:%d\n", sum(x));
	printf("输出的值:%d\n", qiupingfanghe(n));

	return 0;
}

编译运行结果是:
在这里插入图片描述

注意事项

  1. “.h”文件中不可以定义变量 在.h中只能声明,不能定义
extern a;//正确
c=1;//错误
  1. 模块内不想被外部引用的函数和全局变量需在“.c”文件头冠以static关键字声明。 这样这些函数和变量只会在当前.c文件中起到作用,一来可以避免函数名的重复;二来可以保护内部的实现数据,防止被破坏。
static a=1;
static void printC();
  1. 模块中有需要被访问的变量,必须是全局变量,而且要在.h文件中声明。
  2. 函数声明时,extern可有可无,但是变量的声明必须要有,否则编译时不能识别。.

常见错误

  1. 假如没有引入#include "hello.h"头文件,就会出现警告,如图所示:
    在这里插入图片描述
  2. 假如引入的是#include “hello.c”,就会出现错误,如图所示:
    在这里插入图片描述
  3. 假如没有引入#include "stdio.h"头文件,就会出现未定义的警告,如图所示:
    在这里插入图片描述
  • 7
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值