C语言从头学51—多文件项目

       不论是从方便编辑还是方便阅读两个方面看,单个源码文件的长度总是会受到限制的。如何解决这个问题?多文件项目就是解决这个问题的钥匙,将两个、或多个源码文件一起编译,生成一个可执行文件,这种项目组织形式称为多文件项目。如何处理多文件项目,本文将以VS这一编译环境为基础,进行简要介绍。
1、自定义函数头文件
       自定义函数头文件由我们自己编辑,由头文件部分、全局变量的声明、全局结构体的声明、自定义函数的声明组成。自定义函数头文件的后缀使用".h"。
2、自定义函数实现文件
      包括:对自定义头文件的包含语句、全局变量赋初值、自定义函数实现。实现文件的后缀使用".c"。包含自定义函数头文件使用双引号,不使用尖括号。
      说明:如果程序代码不是太长,头文件和实现文件可以合二为一,统一放到头文件中即可。
3、主文件
      所谓主文件就是包含main函数的文件。主文件由头文件部分、主函数本体(含系统函数和自定义函数的调用)组成。在这个文件的头部,除了包含必须的系统头文件外,还要包含我们自定义函数文件。包含自定义函数文件的格式为:#include "自定义函数名"。主文件只能有一个,主文件的后缀为".c"。
4、防止重复加载
       由于主文件要包含自定义函数头文件,自定义函数文件中也会包含其它自定义函数文件,这就存在着一种可能性,有些自定义函数文件会被重复包含,或称重复加载;重复加载可能引起程序运行错误。防止重复加载的办法我们在学习预处理指令时已经学习过,只是没有实验的机会。具体方法是在自定义函数文件头部加一个语句:#Define 标记宏(仅有个名字即可);在准备包含它的文件头部,有关包含语句这样写:
       #ifndef  标记宏
          #include "自定义函数文件名"
       #endif
       当这个自定义函数文件已经加载过时,ifndef会发现这个宏,也就不再执行#include命令了;如没发现这个这个宏,说明还没有加载,则就会执行#include命令。这样就防止了重复加载。
 5、extern、static 说明符
       关于不同文件中全局变量的使用范围问题,前文已经介绍过这两个说明符,extern说明符是标明使用其它文件中全局变量的,static说明符是限制本文件中的全局变量不让其它文件使用的。
 6、举一个多文件项目的简单例子(VS2022编译环境),这个例子的文件组成如下:
       主文件:主文件名:myMain.c  功能:使用全局变量、全局结构体、调用自定义函数
       自定义函数头文件:mycalcu.h  功能:声明全局变量、结构体,声明自定义函数
       自定义函数实现文件:mycalcu.c 功能:实现自定义函数,为全局变量赋初值
       相关代码及注释如下:
a.主文件名:myMain.c

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#define COUNT 0 //记录包含语句被执行次数
#ifndef MYCALCU
  #include "mycalcu.h" //第一次包含
  #undef COUNT
  #define COUNT 1
#endif
#ifndef MYCALCU
  #include "mycalcu.h" //第二次包含
  #undef COUNT
  #define COUNT 2
#endif
extern myCount; //由于使用了include语句,在VS环境下,即使没有这个语句,
                //在主文件也能正常使用自定义函数文件中的全局变量
int main(void)
{
//查看头文件包含次数
	printf("mycalau.h被包含 %d 次。\n",COUNT); //运行结果:mycalau.h被包含 1 次。
	  //从运行结果可以看出,通过使用#ifndef...#endif检查设置在"mycalcu.h"中的宏MYCALCU
	  //是否存在,保证了"mycalcu.h"仅加载一次
//使用自定义头文件中声明的结构体
	struct Person p;
	strcpy(p.name, "王二");
	p.age = 25;
	strcpy(p.addr, "x市x区x街x路x号");
//调用自定义头文件中函数
	int x = 0, y = 0;
	while (1)
	{
	  printf("请输入x:\n");
	  if (0 == scanf("%d", &x))return 0;
	  printf("请输入y:\n");
	  if (0 == scanf("%d", &y))return 0;
	  mySum(x, y); //调用计算合计函数
	  myProd(x, y); //调用计算乘积函数
	  printf("已进行加法、乘法共 %d 次\n",myCount);
	  getchar(); //吸收输入数据时最后回车
	  printf("输入n结束,其它继续...\n");
	  char ch = getchar();
	  if (ch == 'n' || ch == 'N') break;
	}
	return 0;
}

b.自定义函数头文件 mycalcu.h

#include <stdio.h>
#define MYCALCU //定义标记宏(空宏)
void mySum(int, int); //声明计算合计函数
void myProd(int, int); //声明计算乘积函数
int myCount; //声明计数全局变量
struct Person //声明一个人员结构体
{
	char name[12];
	int age;
	char addr[128];
};

c.自定义函数实现文件 mycalcu.c

#include "mycalcu.h"
//全局变量赋初值
myCount = 0;
//实现计算合计函数
void mySum(int x, int y)
{
	printf("x+y=%d\n", x + y);
	myCount++;
}
//实现计算乘积函数
void myProd(int x, int y)
{
	printf("x*y=%d\n", x * y);
	myCount++;
}

//运行结果:
mycalau.h被包含 1 次。
请输入x:
5
请输入y:
10
x+y=15
x*y=50
已进行加法、乘法共 2 次
输入n结束,其它继续...

请输入x:
20
请输入y:
30
x+y=50
x*y=600
已进行加法、乘法共 4 次
输入n结束,其它继续...
n

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值