C Primer Plus(6) 中文版 第9章 函数 9.4 编译多源代码文件的程序

发布于:2023-01-11 ⋅ 阅读:(497) ⋅ 点赞:(0)

9.4 编译多源代码文件的程序
使用多个函数最简单的方法是把它们都放在同一个文件中,然后像编译只有一个函数的文件那样编译该文件即可。其他方法因操作系统而异。
9.4.1 UNIX
假定在UNIX系统中安装了UNIX C编译器cc(最初的cc已经提供,但是许多UNIX系统都给cc命令起了一个别名用作其他编译器指令,典型的是gcc或clang)。假设file1.c和file2.c是两个内含C函数的文件,下面的命令将编译两个文件并生成一个名为a.out的可执行文件:
cc file1.c file2.c 
另外,还生成了两个名为file1.o和file2.o的目标文件。如果后来改动了file1.c,而file2.c不变,可以使用以下命令编译第1个文件,并与第2个文件的目标代码合并:
cc file1.c file2.o
UNIX系统的make命令可自动管理多文件程序。
注意,OS X的Terminal工具可以打开UNIX命令行环境,但是必须先下载命令行编译器(GCC和Clang)。
9.4.2 Linux
假定Linux系统安装了GUN C编译器GCC。假设file1.c和file2.c是两个内含C函数的文件,下面的命令将编译两个文件并生成名为a.out的可执行文件:
gcc file1.c file2.c
另外,还生成了两个名为file1.o和file2.o的目标文件。如果后来改动了file1.c,而file2.c不变,可以使用以下命令编译第1个文件,并与第2个文件的目标代码合并:
gcc file1.c file2.o
9.4.3 DOS命令行编译器
绝大多数DOS命令行编译器的工作原理和UNIX的cc命令类似,只不过使用不同的名称而已。其中一个区别是,对象文件的扩展名是.obj,而不是.o。一些编译器生成的不是目标代码文件,而是汇编语句或其他特殊代码的中间文件。
9.4.4 Windows和苹果的IDE编译器
Windows和Macintosh系统使用的集成开发环境中的编译器是面向项目的。项目(project)描述的是特定程序使用的资源。资源包括代码文件。这种IDE中的编译器要创建项目来运行单文件程序。对于多文件程序,要使用相应的菜单命令,把源代码文件加入一个项目中。要确保所有的源代码文件都在项目列表中列出。许多IDE都不用在项目列表中列出头文件(即扩展名为.h的文件)因为项目只管理使用的源代码文件,源代码文件中的#include指令管理该文件中使用的头文件。但是,Xcode要在项目中添加头文件。
9.4.5 使用头文件
如果把main()放在第1个文件中,把函数定义放在第2个文件中,那么第1个文件仍然要使用函数原型。把函数原型放在头文件中,就不用在每次使用函数文件时都写出函数的原型。C标准库就是这样做的。你可以用自定义的函数文件。
另外,程序中经常用C预处理器定义符号常量。这种定义只存储了那些包含#define指定的文件。如果把程序的一个函数放进一个独立的文件中,你也可以使用#define指令访问每个文件。最直接的方法是在每个文件中再次输入指令,但是这个方法既耗时又容易出错。另外,还会有维护的问题:如果修改了#define定义的值,就必须在某个文件中修改。更好的做法是,把#define指令放进头文件,然后在每个源文件中使用#include指令包含该文件即可。
总之,把函数原型和已定义的字符常量放在头文件是一个良好呃编程习惯。
设计一个程序让用户指定酒店和入住天数,然后计算并显示总费用。同时,程序要实现一份菜单,允许用户反复输入数据,除非用户选择退出。
在UNIX和DOS环境中,#include "hotels.h"指令中的双引号表明被包含的文件位于当前目录中(通常是包含源代码的目录)。如果使用IDE,需要知道如何把头文件合并成一个项目。
/* usehotel.c -- room rate program */
/* compile with  Listing 9.10      */
#include <stdio.h>
#include "hotel.h" /* defines constants, declares functions */

int main(void)
{
    int nights;
    double hotel_rate;
    int code;
    
    while ((code = menu()) != QUIT)
    {
        switch(code)
        {
            case 1 : hotel_rate = HOTEL1;
                break;
            case 2 : hotel_rate = HOTEL2;
                break;
            case 3 : hotel_rate = HOTEL3;
                break;
            case 4 : hotel_rate = HOTEL4;
                break;
            default: hotel_rate = 0.0;
                printf("Oops!\n");
                break;
        }
        nights = getnights();
        showprice(hotel_rate, nights);
    }
    printf("Thank you and goodbye.\n");
    
    return 0;
}
/* hotel.c -- hotel management functions */
#include <stdio.h>
#include "hotel.h"
int menu(void)
{
    int code, status;
    
    printf("\n%s%s\n", STARS, STARS);
    printf("Enter the number of the desired hotel:\n");
    printf("1) Fairfield Arms           2) Hotel Olympic\n");
    printf("3) Chertworthy Plaza        4) The Stockton\n");
    printf("5) quit\n");
    printf("%s%s\n", STARS, STARS);
    while ((status = scanf("%d", &code)) != 1  ||
           (code < 1 || code > 5))
    {
        if (status != 1)
            scanf("%*s");   // dispose of non-integer input
        printf("Enter an integer from 1 to 5, please.\n");
    }
    
    return code;
}

int getnights(void)
{
    int nights;
    
    printf("How many nights are needed? ");
    while (scanf("%d", &nights) != 1)
    {
        scanf("%*s");       // dispose of non-integer input
        printf("Please enter an integer, such as 2.\n");
    }
    
    return nights;
}

void showprice(double rate, int nights)
{
    int n;
    double total = 0.0;
    double factor = 1.0;
    
    for (n = 1; n <= nights; n++, factor *= DISCOUNT)
        total += rate * factor;
    printf("The total cost will be $%0.2f.\n", total);

/* hotel.h -- constants and declarations for hotel.c */
#define QUIT       5
#define HOTEL1   180.00
#define HOTEL2   225.00
#define HOTEL3   255.00
#define HOTEL4   355.00
#define DISCOUNT   0.95
#define STARS "**********************************"

// shows list of choices
int menu(void);

// returns number of nights desired
int getnights(void);

// calculates price from rate, nights
// and displays result
void showprice(double rate, int nights);

/* 输出:

Microsoft Windows [版本 10.0.22000.795]
(c) Microsoft Corporation。保留所有权利。

C:\Users\22152>cd D:\BaiduNetdiskDownload\C Primer Plus\配套资源\C Primer Plus 配套资源整合-2021\C Primer Plus原书配套代码\Ch09

C:\Users\22152>d:

D:\BaiduNetdiskDownload\C Primer Plus\配套资源\C Primer Plus 配套资源整合-2021\C Primer Plus原书配套代码\Ch09>gcc hotel.c usehotel.c -o usehotel.exe

D:\BaiduNetdiskDownload\C Primer Plus\配套资源\C Primer Plus 配套资源整合-2021\C Primer Plus原书配套代码\Ch09>usehotel.exe

********************************************************************
Enter the number of the desired hotel:
1) Fairfield Arms           2) Hotel Olympic
3) Chertworthy Plaza        4) The Stockton
5) quit
********************************************************************
3
How many nights are needed? 1
The total cost will be $255.00.

********************************************************************
Enter the number of the desired hotel:
1) Fairfield Arms           2) Hotel Olympic
3) Chertworthy Plaza        4) The Stockton
5) quit
********************************************************************
4
How many nights are needed? 3
The total cost will be $1012.64.

********************************************************************
Enter the number of the desired hotel:
1) Fairfield Arms           2) Hotel Olympic
3) Chertworthy Plaza        4) The Stockton
5) quit
********************************************************************
5
Thank you and goodbye.

D:\BaiduNetdiskDownload\C Primer Plus\配套资源\C Primer Plus 配套资源整合-2021\C Primer Plus原书配套代码\Ch09>

*/

void showprice(double rate, int nights);
调用scanf( "%*s" )跳至下一个空白字符。注意,menu()函数是如何检查非数值输入和超出范围的数据:
while( (status = scanf( "%d", &code )) != 1 || (code < 1 || code > 5)) 
以上代码利用了C语言的两个规则:从左往右对逻辑表达式求值;一旦求值结果为假,立即停止求值。
用不同的函数处理不同的任务应检查数据的有效性。当然,首次编写可以暂不添加这一功能,只写一个简单的scanf()即可。待基本版本运行正常后,再逐步改善各模块。

本文含有隐藏内容,请 开通VIP 后查看