千家信息网

怎么组织构建多文件C语言程序

发表于:2025-11-06 作者:千家信息网编辑
千家信息网最后更新 2025年11月06日,这篇文章主要讲解了"怎么组织构建多文件C语言程序",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"怎么组织构建多文件C语言程序"吧!包含项目头文件位于第二
千家信息网最后更新 2025年11月06日怎么组织构建多文件C语言程序

这篇文章主要讲解了"怎么组织构建多文件C语言程序",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"怎么组织构建多文件C语言程序"吧!

包含项目头文件

位于第二部分中的 /* 01 项目包含文件 */ 的源代码如下:

/* main.c - 喵呜喵呜流式编解码器 */.../* 01 项目包含文件 */#include "main.h"#include "mmecode.h"#include "mmdecode.h"

#include 是 C 语言的预处理命令,它会将该文件名的文件内容拷贝到当前文件中。如果程序员在头文件名称周围使用双引号(""),编译器将会在当前目录寻找该文件。如果文件被尖括号包围(<>),编译器将在一组预定义的目录中查找该文件。

main.h 文件中包含了 main.c 文件中用到的定义和类型定义。我喜欢尽可能多将声明放在头文件里,以便我在我的程序的其他位置使用这些定义。

头文件 mmencode.h 和 mmdecode.h 几乎相同,因此我以 mmencode.h 为例来分析。

/* mmencode.h - 喵呜喵呜流编解码器 */  #ifndef _MMENCODE_H#define _MMENCODE_H  #include   int mm_encode(FILE *src, FILE *dst);  #endif /* _MMENCODE_H */

#ifdef#define#endif 指令统称为 "防护" 指令。其可以防止 C 编译器在一个文件中多次包含同一文件。如果编译器在一个文件中发现多个定义/原型/声明,它将会产生警告。因此这些防护措施是必要的。

在这些防护内部,只有两个东西:#include 指令和函数原型声明。我在这里包含了 stdio.h 头文件,以便于能在函数原型中使用 FILE 定义。函数原型也可以被包含在其他 C 文件中,以便于在文件的命名空间中创建它。你可以将每个文件视为一个独立的命名空间,其中的变量和函数不能被另一个文件中的函数或者变量使用。

编写头文件很复杂,并且在大型项目中很难管理它。不要忘记使用防护。

喵呜喵呜编码的最终实现

该程序的功能是按照字节进行 MeowMeow 字符串的编解码,事实上这是该项目中最简单的部分。截止目前我所做的工作便是支持允许在适当的位置调用此函数:解析命令行,确定要使用的操作,并打开将要操作的文件。下面的循环是编码的过程:

/* mmencode.c - 喵呜喵呜流式编解码器 */...   while (!feof(src)) {      if (!fgets(buf, sizeof(buf), src))       break;      for(i=0; i> 4;       fputs(tbl[hi], dst);       fputs(tbl[lo], dst);     }   }

简单的说,当文件中还有数据块时( feof(3) ),该循环读取(feof(3) )文件中的一个数据块。然后将读入的内容的每个字节分成两个 hilo半字节nibble。半字节是半个字节,即 4 个位。这里的奥妙之处在于可以用 4 个位来编码 16 个值。我将 hilo 用作 16 个字符串查找表 tbl 的索引,表中包含了用半字节编码的 MeowMeow 字符串。这些字符串使用 fputs(3) 函数写入目标 FILE 流,然后我们继续处理缓存区的下一个字节。

该表使用 table.h 中的宏定义进行初始化,在没有特殊原因(比如:要展示包含了另一个项目的本地头文件)时,我喜欢使用宏来进行初始化。我将在未来的文章中进一步探讨原因。

喵呜喵呜解码的实现

我承认在开始工作前花了一些时间。解码的循环与编码类似:读取 MeowMeow 字符串到缓冲区,将编码从字符串转换为字节

 /* mmdecode.c - 喵呜喵呜流式编解码器 */ ... int mm_decode(FILE *src, FILE *dst) {   if (!src || !dst) {     errno = EINVAL;     return -1;   }   return stupid_decode(src, dst); }

这不符合你的期望吗?

在这里,我通过外部公开的 mm_decode() 函数公开了 stupid_decode() 函数细节。我上面所说的"外部"是指在这个文件之外。因为 stupid_decode() 函数不在该头文件中,因此无法在其他文件中调用它。

当我们想发布一个可靠的公共接口时,有时候会这样做,但是我们还没有完全使用函数解决问题。在本例中,我编写了一个 I/O 密集型函数,该函数每次从源中读取 8 个字节,然后解码获得 1 个字节写入目标流中。较好的实现是一次处理多于 8 个字节的缓冲区。更好的实现还可以通过缓冲区输出字节,进而减少目标流中单字节的写入次数。

/* mmdecode.c - 喵呜喵呜流式编解码器 */...int stupid_decode(FILE *src, FILE *dst){  char           buf[9];  decoded_byte_t byte;  int            i;      while (!feof(src)) {    if (!fgets(buf, sizeof(buf), src))      break;    byte.field.f0 = isupper(buf[0]);    byte.field.f1 = isupper(buf[1]);    byte.field.f2 = isupper(buf[2]);    byte.field.f3 = isupper(buf[3]);    byte.field.f4 = isupper(buf[4]);    byte.field.f5 = isupper(buf[5]);    byte.field.f6 = isupper(buf[6]);    byte.field.f7 = isupper(buf[7]);          fputc(byte.value, dst);  }  return 0;}

我并没有使用编码器中使用的位移方法,而是创建了一个名为 decoded_byte_t 的自定义数据结构。

/* mmdecode.c - 喵呜喵呜流式编解码器 */... typedef struct {  unsigned char f7:1;  unsigned char f6:1;  unsigned char f5:1;  unsigned char f4:1;  unsigned char f3:1;  unsigned char f2:1;  unsigned char f1:1;  unsigned char f0:1;} fields_t;  typedef union {  fields_t      field;  unsigned char value;} decoded_byte_t;

初次看到代码时可能会感到有点儿复杂,但不要放弃。decoded_byte_t 被定义为 fields_tunsigned char联合。可以将联合中的命名成员看作同一内存区域的别名。在这种情况下,valuefield 指向相同的 8 位内存区域。将 field.f0 设置为 1 也将会设置 value 中的最低有效位。

虽然 unsigned char 并不神秘,但是对 fields_t 的类型定义(typedef)也许看起来有些陌生。现代 C 编译器允许程序员在结构体中指定单个位字段的值。字段所在的类型是一个无符号整数类型,并在成员标识符后紧跟一个冒号和一个整数,该整数指定了位字段的长度。

这种数据结构使得按字段名称访问字节中的每个位变得简单,并可以通过联合中的 value 字段访问组合后的值。我们依赖编译器生成正确的移位指令来访问字段,这可以在调试时为你节省不少时间。

最后,因为 stupid_decode() 函数一次仅从源 FILE 流中读取 8 个字节,所以它效率并不高。通常我们尝试最小化读写次数,以提高性能和降低调用系统调用的开销。请记住:少量的读取/写入大的块比大量的读取/写入小的块好得多。

感谢各位的阅读,以上就是"怎么组织构建多文件C语言程序"的内容了,经过本文的学习后,相信大家对怎么组织构建多文件C语言程序这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!

文件 字节 函数 程序 编码 字段 字符 字符串 编译器 解码器 项目 编译 语言 语言程序 个位 内容 原型 指令 数据 类型 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 电脑上数据库软件不可用 2小网络安全答题 软件开发企业年会奖项设置 论文设计一个数据库系统 为什么会出现无法连接文件服务器 武汉数据库防篡改 网络安全应承担的责任 我的世界手机联机电脑服务器 网络安全相关文献论文 有关网络安全教育手抄报资料 保险相关的软件开发 宿迁数据库审计设备 北京专业软件开发收费报价表 web服务器 管理 中国联通网络技术岗位 怎么去网络安全科技馆 数据库有哪三类安全性约束 山西一对一网络技术开发哪家好 酒店利用网络技术异军突起 解析超大xml存到数据库 像素工厂怎么建造服务器 小鹏汽车仿真软件开发 阴阳师手游服务器连接失败怎么办 龙华网络安全运维哪个品牌好 穿越火线测试服的服务器在哪 网络安全工具套装裙穿搭 在职消防救援人员子女信息数据库 广平网络安全活动 ibm服务器 客服 用c 连接数据库做用户登录
0