栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C primer plus编程题答案(下)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C primer plus编程题答案(下)

C primer plus编程题答案下

C primer plus编程题答案下
  • C primer plus编程题答案下
    • 第十二章 存储类别,链接和存储
    • 第十三章 文件输入输出
    • 第十四章 结构和其他数据形式
    • 第十五章 位操作
    • 第十六章 C预处理和C库
    • 第十七章 高级数据表示

第十二章 存储类别,链接和存储
  1. 不使用全局变量,重写程序清单 12.4。

    #include 
    int critic(void);
    int main(void)
    {
        int units;
    
        printf("How many pounds to a firkin of butter?n");
        scanf("%d", &units);
        while (units != 56)
            units = critic();
        printf("You must have looked it up!n");
    
        return 0;
    }
    
    int critic(void)
    {
        int answer;
    
        printf("No luck, my friend. Try again.n");
        scanf("%d", &answer);
    
        return answer;
    }
    
    
  2. 在美国,通常以英里/加仑来计算油耗;在欧洲,以升/100 公里来计 算。下面是程序的一部分,提示用户选择计算模式(美制或公制),然后接 收数据并计算油耗。

// pe12-2b.c

// 与 pe12-2a.c 一起编译

#include   
#include "pe12-2a.h" 
int main(void)  
{ 
    int mode; 
 	printf("Enter 0 for metric mode, 1 for US mode: "); 
    scanf("%d", &mode); 
    while (mode >= 0) 
    { 
        set_mode(mode ); 
        get_info();  
        show_info();  
        printf("Enter 0 for metric mode, 1 for US mode");  
        printf(" (-1 to quit): ");  
        scanf("%d", &mode); 
    } 
    printf("Done.n");  
    return 0; 
}

下面是是一些输出示例:

Enter 0 for metric mode, 1 for US mode: 0 

Enter distance traveled in kilometers: 600 

Enter fuel consumed in liters: 78.8 

Fuel consumption is 13.13 liters per 100 km. 

Enter 0 for metric mode, 1 for US mode (-1 to quit): 1 

Enter distance traveled in miles: 434 

Enter fuel consumed in gallons: 12.7 

Fuel consumption is 34.2 miles per gallon. 

Enter 0 for metric mode, 1 for US mode (-1 to quit): 3  

Invalid mode specified. Mode 1(US) used. 

Enter distance traveled in miles: 388 

Enter fuel consumed in gallons: 15.3 

Fuel consumption is 25.4 miles per gallon. 

Enter 0 for metric mode, 1 for US mode (-1 to quit): -1 

Done. 

​ 如果用户输入了不正确的模式,程序向用户给出提示消息并使用上一次 输入的正确模式。请提供 pe12-2a.h 头文件和 pe12-2a.c 源文件。源代码文件 应定义 3 个具有文件作用域、内部链接的变量。一个表示模式、一个表示距 离、一个表示消耗的燃料。get_info()函数根据用户输入的模式提示用户输入 相应数据,并将其储存到文件作用域变量中。show_info()函数根据设置的模 式计算并显示油耗。可以假设用户输入的都是数值数据。

//pe12-2b.c

#include 
static int last_mode;
static double distance;
static double fuel;

void set_mode(int mode)
{
    if (mode != 0 && mode != 1)
    {
        printf("Invalid mode specified. Mode %s used.n",
                last_mode == 0 ? "0 (metric)" : "1 (US)");
    }
    else
        last_mode = mode;
}

void get_info(void)
{
        printf("Enter distance traveled in %s: ",
            last_mode == 0 ? "kilometers" : "miles");
        scanf("%lf", &distance);
        printf("Enter fuel consumed in %s: ",
            last_mode == 0 ? "liters" : "gallons");
        scanf("%lf", &fuel);
}

void show_info(void)
{
    printf("Fuel consumption is ");
    if (last_mode == 0)
        printf("%.2f liters per 100 km.n", fuel / distance * 100);
    else
        printf("%.1f miles per gallon.n", distance / fuel);
}


//pe12-2a.h

#include"pe12-2b.c"
void set_mode(int mode);
void get_info(void);
void show_info(void);

  1. 重新设计编程练习 2,要求只使用自动变量。该程序提供的用户界面 不变,即提示用户输入模式等。但是,函数调用要作相应变化。

    //pe12-3a.c
    #include
    #include"pe12-3a.h"
    void get_info(int mode);
    int main(void)
    {
        int mode;
    
        printf("Enter 0 for metric mode, 1 for US mode: ");
        scanf("%d", &mode);
        while (mode >= 0)
        {
            get_info(mode);
            printf("Enter 0 for metric mode, 1 for US mode");
            printf(" (-1 to quit): ");
            scanf("%d", &mode);
        }
        printf("Done.n");
    
        return 0;
    }
    
    //pe12-3b.c
    #include
    int set_mode(int mode);
    void show_info(double * distance, double * fuel, int mode);
    
    int set_mode(int mode)
    {
        int last_mode = 0;
        if (mode != 0 && mode != 1)
        {
            printf("Invalid mode specified. Mode %s used.n",
                    last_mode == 0 ? "0 (metric)" : "1 (US)");
        }
        else
            last_mode = mode;
    
        return last_mode;
    }
    
    void get_info(int mode)
    {
        double * p1, * p2;
        double distance, fuel;
    
        printf("Enter distance traveled in %s: ",
                set_mode(mode) == 0 ? "kilometers" : "miles");
        scanf("%lf", &distance);
        printf("Enter fuel consumed in %s: ",
                set_mode(mode) == 0 ? "liters" : "gallons");
        scanf("%lf", &fuel);
        p1 = &distance;
        p2 = &fuel;
        show_info(p1, p2, mode);
    }
    
    void show_info(double * distance, double * fuel, int mode)
    {
        printf("Fuel consumption is ");
        if (set_mode(mode) == 0)
            printf("%.2f liters per 100 km.n", *fuel / *distance * 100);
        else
            printf("%.1f miles per gallon.n", *distance / *fuel);
    }
    
    //pe12-3a.h
    
    #include"pe12-3b.c"
    
    int set_mode(int mode);
    void get_info(int);
    void show_info(double*,double*,int);
    
    
  2. 在一个循环中编写并测试一个函数,该函数返回它被调用的次数。

    #include 
    #define TIMES 20
    void called_count(void);
    static int count;
    int main(void)
    {
        int i;
    
        for (i = 0; i < TIMES; i++)
            called_count();
        printf("The times is %d.n", count);
    }
    
    void called_count(void)
    {
        count++;
    }
    
  3. 编写一个程序,生成 100 个 1~10 范围内的随机数,并以降序排列 (可以把第 11 章的排序算法稍加改动,便可用于整数排序,这里仅对整数 排序)。

    #include 
    #include 
    #include 
    #define SIZE 100
    void print_ar(int ar[], int n);			//打印数组元素的函数
    int main(void)
    {
        int i, j, temp;
        int digit[SIZE];
        srand((unsigned int)time(0));
        for (i = 0; i < SIZE; i++)
        {
            digit[i] = rand() % 10 + 1;
        }
        printf("The original numbers:n");
        print_ar(digit, SIZE);
        for (j = 0; j < SIZE - 1; j++)
            for (i = j + 1; i < SIZE; i++)
                if (digit[j] < digit[i])
                {
                    temp = digit[i];
                    digit[i] = digit[j];
                    digit[j] = temp;
                }
        printf("nThe numbers in reverse order:n");
        print_ar(digit, SIZE);
    }
    
    void print_ar(int ar[], int n)
    {
        int i;
        for (i = 0; i < n; i++)
        {
            printf("%3d", ar[i]);
            if (i % 10 == 9)
                printf("n");
        }
    }
    
  4. 编写一个程序,生成 1000 个 1~10 范围内的随机数。不用保存或打印 这些数字,仅打印每个数出现的次数。用 10 个不同的种子值运行,生成的 数字出现的次数是否相同?可以使用本章自定义的函数或 ANSI C 的 rand() 和 srand()函数,它们的格式相同。这是一个测试特定随机数生成器随机性 的方法。

    #include 
    #include 
    #define SIZE 1000
    #define SIZE_N 10
    #define SIZE_S 10
    int main(void)
    {
        int i, j;
        int count[SIZE_N];			//各随机数出现次数的数组
        
        unsigned int seed[SIZE_S] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    
        for (j = 0; j < SIZE_S; j++)
        {
            for (i = 0; i < SIZE_N; i++)
                count[i] = 0;
            srand(seed[j]);
            printf("seed = %d:n", seed[j]);
            for (i = 0; i < SIZE; i++)
                count[rand() % 10]++;
            for (i = 0; i < SIZE_N; i++)
            {
                printf("%d:%-5d  ", i + 1, count[i]);
                if (i == 4)
                    printf("n");
            }
            printf("n");
        }
    
        return 0;
    }
            
    
  5. 编写一个程序,按照程序清单 12.13 输出示例后面讨论的内容,修改 该程序。使其输出类似:

Enter the number of sets; enter q to stop : 18 

How many sides and how many dice? 6 3  

Here are 18 sets of 3 6-sided throws. 

12 10 6 9 8 14 8 15 9 14 12 17 11 7 10 13 8 14 

How many sets? Enter q to stop: q
#include 
#include 
#include 
void roll_count(int sets, int sides, int dice);
int main(void)
{
    int sets;
    int sides, dice;

    srand((unsigned int)time(0));
    printf("Enter the number of sets; enter q to stop: ");
    while (scanf("%d", &sets) == 1)
    {
        printf("How many sides and how many dice? ");
        scanf("%d%d", &sides, &dice);
        printf("Here are %d sets of %d %d-sided throws.n",
                sets, dice, sides);
        roll_count(sets, sides, dice);
        printf("How many sets? Enter q to stop: ");
    }
    printf("Bye.n");
}

void roll_count(int sets, int sides, int dice)
{
    int i, j;
    int roll;

    if (sides < 2)
    {
        printf("Need at least 2 sides.n");
        return;
    }
    if (dice < 1)
    {
        printf("Need at least 1 die.n");
        return;
    }
    srand((unsigned int)time(0));
    for (i = 0; i < sets; i++)
    {
        roll = 0;
        for (j = 0; j < dice; j++)
            roll += rand() % sides + 1;
        printf("%d ", roll);
    }
    printf("n");
}



8.下面是程序的一部分:

// pe12-8.c
#include  
int * make_array(int elem, int val);
void show_array(const int ar [], int n); 
int main(void)
{
	int * pa; 
    int size; 
    int value; 
    printf("Enter the number of elements: "); 
    while (scanf("%d", &size) == 1&& size > 0)
	{ 
        printf("Enter the initialization value:"); 
        scanf("%d", &value);
		pa = make_array(size, value);
		if (pa)
		{
			show_array(pa, size);
			free(pa);
		}
		printf("Enter the number of elements (<1 to quit): ");
	}
	printf("Done.n");

	return 0;
}

​ 提供 make_array()和 show_array()函数的定义,完成该程序。 make_array() 函数接受两个参数,第 1 个参数是 int 类型数组的元素个数,第 2 个参数是要赋给每个元素的值。该函数调用 malloc()创建一个大小合适的 数组,将其每个元素设置为指定的值,并返回一个指向该数组的指针。 show_array()函数显示数组的内容,一行显示 8 个数。

#include 
#include 
int * make_array(int elem, int val);
void show_array(const int ar [], int n);
int main(void)
{
    int * pa;
    int size;
    int value;

    printf("Enter the number of elements: ");
    while (scanf("%d", &size) == 1 && size > 0)
    {
        printf("Enter the initialization value: ");
        scanf("%d", &value);
        pa = make_array(size, value);
        if (pa)
        {
            show_array(pa, size);
            free(pa);
        }
        printf("Enter the number of elements (<1 to quit): ");
    }
    printf("Done.n");
    return 0;
}

int * make_array(int elem, int val)
{
    int * pt;
    int i;
    
    pt = (int *)malloc(elem * sizeof(int));
    for (i = 0; i < elem; i++)
        pt[i] = val;

    return pt;
}

void show_array(const int ar [], int n)
{
    int i;
    
    for (i = 0; i < n; i++)
    {
        printf("%d ", ar[i]);
        if (i % 8 == 7)
            printf("n");
    }
    printf("n");
}
  1. 编写一个符合以下描述的函数。首先,询问用户需要输入多少个单 词。然后,接收用户输入的单词,并显示出来,使用 malloc()并回答第 1 个 问 题(即要输入多少个单词),创建一个动态数组,该数组内含相应的指向 char 的指针(注意,由于数组的每个元素都是指向 char 的指针,所以用于 储存 malloc()返回值的指针应该是一个指向指针的指针,且它所指向的指针 指向 char)。在读取字符串时,该程序应该把单词读入一个临时的 char 数 组,使用 malloc()分配足够的存储空间来储存单词,并把地址存入该指针数 组 (该数组中每个元素都是指向 char 的指针)。然后,从临时数组中把单词拷 贝到动态分配的存储空间中。因此,有一个字符指针数组,每个指针都指向 一个对象,该对象的大小正好能容纳被储存的特定单词。下面是该程序的一 个运行示例:
How many words do you wish to enter? 5
Enter 5 words now:
I enjoyed doing this exerise
Here are your words:
enjoyed
doing
this
exercise
#include 
#include 
#include 
#define SIZE 40
char * * mal_ar(int n);
int main(void)
{
    int words, i;
    char * * st;
    
    printf("How many words do you wish to enter? ");
    scanf("%d", &words);
    getchar();					//滤掉回车
    printf("Enter %d words now:n", words);
    st = mal_ar(words);
    printf("Here are your words:n");
    for (i = 0; i < words; i++)
    {
        puts(st[i]);
        free(st[i]);	//释放每个指针指向的内存
    }
    free(st);			//释放指针数组

    return 0;
}

char * * mal_ar(int n)
{
    char * * pt;
    int i, j;
    char ch;

    //给n个指针分配动态内存空间,返回指针的指针
    pt = (char * *)malloc(n * sizeof(char *));
    for (i = 0; i < n; i++)
    {
        //给每个指针指向的地址分配内存空间
        pt[i] = (char *)malloc(SIZE * sizeof(char));
        //可以仅用scanf("%s", pt[i]);
        while (isspace(ch = getchar()))				//处理单词之前的空格符
            continue;
        pt[i][0] = ch;								//单词首字符
        j = 1;
        while (!isspace(pt[i][j] = getchar()))
            j++;
        pt[i][j] = '';							//将末尾的空格替换为'
    }

    return pt;
}
第十三章 文件输入输出
  1. 修改程序清单 13.1 中的程序,要求提示用户输入文件名,并读取用户 输入的信息,不使用命令行参数。

    #include 
    #include 
    #include 
    #define SIZE 40
    char * s_gets(char * st, int n);
    int main(void)
    {
        char name[SIZE];
        char ch;
        unsigned long count = 0;
        FILE * fp;
    
        printf("Enter the file name: ");
        s_gets(name, SIZE);
        if ((fp = fopen(name, "r")) == NULL)
        {
            printf("Can't open %sn", name);
            exit(EXIT_FAILURE);
        }
        while ((ch = getc(fp)) != EOF)
        {
            putc(ch, stdout);
            count++;
        }
        fclose(fp);
        printf("nFile %s has %lu charactersn", name, count);
    
        return 0;
    }
    
    //自定义读取文件名的函数
    char * s_gets(char * st, int n)
    {
        char * find;
        char * ret_val;
    
        ret_val = fgets(st, n, stdin);
        if (ret_val)
        {
            find = strchr(st, 'n');	//查找换行符
            if (find)
                *find = '';			//替换为空字符
            else
                while (getchar() != 'n')
                    continue;
        }
    
        return ret_val;
    }
    
    
  2. 编写一个文件拷贝程序,该程序通过命令行获取原始文件名和拷贝文 件名。尽量使用标准 I/O 和二进制模式。

    #include 
    #include 
    #define SIZE 256
    int main(int argc, char * argv[])
    {
        FILE * fs;		//原始文件指针
        FILE * fa;		//目标文件指针
        char temp[SIZE];
        size_t bytes;
    
        //检查命令行参数
        if (argc < 3)
        {
            fprintf(stderr, "Usage: %s filenamen", argv[0]);
            exit(EXIT_FAILURE);
        }
    
        //以读模式打开原始文件
        if ((fs = fopen(argv[1], "rb")) == NULL)
        {
            fprintf(stderr, "I couldn't open the file "%s"n", argv[1]);
            exit(EXIT_FAILURE);
        }
        
        //以读写模式打开目标文件
        if ((fa = fopen(argv[2], "wb")) == NULL)
        {
            fprintf(stderr, "I couldn't open the file "%s"n", argv[2]);
            exit(EXIT_FAILURE);
        }
    
        //拷贝数据
        {
            while ((bytes = fread(temp, sizeof(char), SIZE, fs)) > 0)
                fwrite(temp, sizeof(char), bytes, fa);
        }
    
        fclose(fs);
        fclose(fa);
    
        return 0;
    }
    
    
    
    
  3. 编写一个文件拷贝程序,提示用户输入文本文件名,并以该文件名作 为原始文件名和输出文件名。该程序要使用 ctype.h 中的 toupper()函数,在 写入到输出文件时把所有文本转换成大写。使用标准 I/O 和文本模式。

    #include 
    #include 
    #include 
    #define SIZE 40
    char * s_gets(char * st, int n);
    
    int main(void)
    {
        FILE * fs;			//原始文件指针
        FILE * ft;			//目标文件指针
        char name_s[SIZE];
        char name_t[SIZE];
        char ch;
    
        //输入原始文件和目标文件名
        fprintf(stdout, "Please enter the source file name:n");
        s_gets(name_s, SIZE);
        fprintf(stdout, "Please enter the target file name:n");
        s_gets(name_t, SIZE);
    
        //打开原始文件和目标文件
        if ((fs = fopen(name_s, "r")) == NULL)
            fprintf(stderr, "Could not open the %sn", name_s);
        if ((ft = fopen(name_t, "w")) == NULL)
            fprintf(stderr, "Could not open the %sn", name_t);
    
        //拷贝数据
        while ((ch = getc(fs)) != EOF)
            putc(toupper(ch), ft);
    
        fclose(fs);
        fclose(ft);
    
        return 0;
    }
    
    
    
    //自定义读取文件名的函数
    char * s_gets(char * st, int n)
    {
        char * find;
        char * ret_val;
    
        ret_val = fgets(st, n, stdin);
        if (ret_val)
        {
            find = strchr(st, 'n');	//查找换行符
            if (find)
                *find = '';			//替换为空字符
            else
                while (getchar() != 'n')
                    continue;			//处理多余输入
        }
    
        return ret_val;
    }
    
    
  4. 编写一个程序,按顺序在屏幕上显示命令行中列出的所有文件。使用 argc 控制循环。

    #include 
    
    int main(int argc, char *argv[])
    {
    	int ch;
    	int ct;
    	errno_t err;			//fopen_s()返回该类型(int)
    	FILE * fp;
    	char file[4096];
    
    	for (ct = 1; ct < argc; ct++)
    	{
    		//打开文件失败
    		if (err = fopen_s(&fp, argv[ct], "r") != 0)
    		{
    			printf("打开 %s 文件失败...n", argv[ct]);
    			continue;	//注意for () 使用continue ct 会递增
    		}
    
    		printf("%d) 文件 %s : nn", ct, argv[ct]);
    		while (fgets(file, 256, fp) != NULL)
    		{
    			fputs(file, stdout);
    		}
    		printf("nn");
    		fclose(fp);		//别忘了关闭文件呦
    	}
    
    	printf("nn程序完结!n");
    	while (ch = getchar())		//防止突然退出
    	{
    		continue;
    	}
    
    	return 0;
    }
    
    
  5. 修改程序清单 13.5 中的程序,用命令行界面代替交互式界面。

    //命令行参数argv[1]代表目标文件名,后面几个为源文件名
    //该程序把多个源文件加到源文件末尾
    #include 
    #include 
    #include 
    #define BUFSIZE 4096
    #define SLEN 81
    void append(FILE * source, FILE * dest);
    char * s_gets(char * st, int n);
    
    int main(int argc, char * argv[])
    {
        FILE * fs, * fa;		//fs指向源文件,fa指向目标文件
        int i;
        int files = 0;
        char ch;
    
        if (argc < 3)
        {
            fprintf(stderr, "Usage: %s filenamen", argv[0]);
            exit(EXIT_FAILURE);
        }
        if ((fa = fopen(argv[1], "a+")) == NULL)
        {
            fprintf(stderr, "Could not open %s.n", argv[1]);
            exit(EXIT_FAILURE);
        }
        if (setvbuf(fa, NULL, _IOFBF, BUFSIZE) != 0)
        {
            fputs("Can't creat output buffern", stderr);
            exit(EXIT_FAILURE);
        }
        for (i = 2; i < argc; i++)
        {
            if (strcmp(argv[1], argv[i]) == 0)
            {
                fputs("Can't append file to itselfn", stderr);
            }
            else if ((fs = fopen(argv[i], "r")) == NULL)
            {
                fprintf(stderr, "Could not open %s.n", argv[i]);
            }
            else
            {
                if (setvbuf(fs, NULL, _IOFBF, BUFSIZE) != 0)
                {
                    fputs("Can't creat input buffern", stderr);
                    continue;
                }
                append(fs, fa);
                if (ferror(fs) != 0)
                    fprintf(stderr, "Error in reading file %s.n", argv[i]);
                if (ferror(fa) != 0)
                    fprintf(stderr, "Error in writing file %s.n", argv[1]);
                fclose(fs);
                printf("File %s appended.n", argv[i]);
            }
        }
        printf("%s contents:n", argv[1]);
        rewind(fa);
        while ((ch = getc(fa)) != EOF)
            putchar(ch);
        puts("Done displaying.");
        fclose(fa);
    
        return 0;
    }
    
    //附加文件的函数
    void append(FILE * source, FILE * dest)
    {
        size_t bytes;
        static char temp[BUFSIZE];
    
        while ((bytes = fread(temp, sizeof(char), BUFSIZE, source)) > 0)
            fwrite(temp, sizeof(char), bytes, dest);
    }
    
    //自定义读取文件名的函数
    char * s_gets(char * st, int n)
    {
        char * find;
        char * ret_val;
    
        ret_val = fgets(st, n, stdin);
        if (ret_val)
        {
            find = strchr(st, 'n');	 		//查找换行符
            if (find)
                *find = '';					//替换为空字符
            else
                while (getchar() != 'n')
                    continue;					//处理多余输入
        }
    
        return ret_val;
    }
    
    
  6. 使用命令行参数的程序依赖于用户的内存如何正确地使用它们。重写 程序清单 13.2 中的程序,不使用命令行参数,而是提示用户输入所需信息。

    #include 
    #include 
    #include 
    #define SIZE 40
    char * s_gets(char * st, int n);
    
    int main(void)
    {
        FILE * fs, * fa;		//fs指向源文件,fa指向目标文件
        char ch;
        char name_source[SIZE];
        char name_dest[SIZE];
        int count = 0;
    
        //输入源文件和目标文件名
        fprintf(stdout, "Please enter the source file name:n");
        s_gets(name_source, SIZE);
        fprintf(stdout, "Please enter the destination file name:n");
        s_gets(name_dest, SIZE);
        
        //打开源文件和目标文件
        if ((fs = fopen(name_source, "r")) == NULL)
        {
            fprintf(stderr, "Could not open the %sn", name_source);
            exit(EXIT_FAILURE);
        }
        if ((fa = fopen(name_dest, "w")) == NULL)
        {
            fprintf(stderr, "Could not open the %sn", name_dest);
            exit(EXIT_FAILURE);
        }
    
        //将源文件每3个字符的第1个字符输出到目标文件
        while ((ch = getc(fs)) != EOF)
        {
            if (count++ %3 == 0)
                putc(ch, fa);
        }
    
        //收尾工作
        if (fclose(fs) != 0 || fclose(fa) != 0)
            fprintf(stderr, "Error in closing filesn");
    
        return 0;
    }
    
    
    //自定义读取文件名的函数
    char * s_gets(char * st, int n)
    {
        char * find;
        char * ret_val;
    
        ret_val = fgets(st, n, stdin);
        if (ret_val)
        {
            find = strchr(st, 'n');	 		//查找换行符
            if (find)
                *find = '';			//替换为空字符
            else
                while (getchar() != 'n')
                    continue;		//处理多余输入
        }
    
        return ret_val;
    }
    
    
  7. 编写一个程序打开两个文件。可以使用命令行参数或提示用户输入文 件名。

a. 该程序以这样的顺序打印:打印第 1 个文件的第 1 行,第 2 个文件的 第 1 行,第 1 个文件的第 2 行,第 2 个文件的第 2 行,以此类推,打印到行 数较多文件的最后一行。 

b. 修改该程序,把行号相同的行打印成一行。
//a.c

#include 
#include 
#include 
#define SIZE 40
#define SLEN 81
char * s_gets(char * st, int n);

int main(void)
{
    FILE * f1, * f2;
    char st[SLEN];
    char name_f1[SIZE];
    char name_f2[SIZE];
    char * ret_val1;
    char * ret_val2;
    int count = 0;

    //依次输入两个文件的文件名
    fprintf(stdout, "Please enter the first file name:n");
    s_gets(name_f1, SIZE);
    fprintf(stdout, "Please enter the second file name:n");
    s_gets(name_f2, SIZE);

    //依次输入两个文件
    if ((f1 = fopen(name_f1, "r")) == NULL)
    {
        fprintf(stderr, "Could not open the %sn", name_f1);
        exit(EXIT_FAILURE);
    }
    if ((f2 = fopen(name_f2, "r")) == NULL)
    {
        fprintf(stderr, "Could not open the %sn", name_f2);
        exit(EXIT_FAILURE);
    }

    do
    {
        if ((ret_val1 = fgets(st, SLEN, f1)) != NULL)
        {
            fputs(st, stdout);

        }
        if ((ret_val2 = fgets(st, SLEN, f2)) != NULL)
        {
            fputs(st, stdout);
        }
    }
    while (ret_val1 != NULL || ret_val2 != NULL);

    fclose(f1);
    fclose(f2);

    return 0;
}

//自定义读取文件名的函数
char * s_gets(char * st, int n)
{
    char * find;
    char * ret_val;

    ret_val = fgets(st, n, stdin);
    if (ret_val)
    {
        find = strchr(st, 'n');	 		//查找换行符
        if (find)
            *find = '';			//替换为空字符
        else
            while (getchar() != 'n')
                continue;		//处理多余输入
    }

    return ret_val;
}

//b.c
#include 
#include 
#include 
#define SIZE 40
#define SLEN 81
char * s_gets(char * st, int n);

int main(void)
{
    FILE * f1, * f2;
    char name_f1[SIZE];
    char name_f2[SIZE];
    char ch1, ch2;

    //依次输入两个文件的文件名
    fprintf(stdout, "Please enter the first file name:n");
    s_gets(name_f1, SIZE);
    fprintf(stdout, "Please enter the second file name:n");
    s_gets(name_f2, SIZE);

    //依次输入两个文件
    if ((f1 = fopen(name_f1, "r")) == NULL)
    {
        fprintf(stderr, "Could not open the %sn", name_f1);
        exit(EXIT_FAILURE);
    }
    if ((f2 = fopen(name_f2, "r")) == NULL)
    {
        fprintf(stderr, "Could not open the %sn", name_f2);
        exit(EXIT_FAILURE);
    }

    do
    {
        while ((ch1 = getc(f1)) != EOF && ch1 != 'n')
        {
            putchar(ch1);
        }
        while ((ch2 = getc(f2)) != EOF && ch2 != 'n')
        {
            putchar(ch2);
        }
        putchar('n');
    }
    while (ch1 != EOF || ch2 != EOF);

    fclose(f1);
    fclose(f2);

    return 0;
}

//自定义读取文件名的函数
char * s_gets(char * st, int n)
{
    char * find;
    char * ret_val;

    ret_val = fgets(st, n, stdin);
    if (ret_val)
    {
        find = strchr(st, 'n');	 		//查找换行符
        if (find)
            *find = '';					//替换为空字符
        else
            while (getchar() != 'n')
                continue;					//处理多余输入
    }

    return ret_val;
}

  1. 编写一个程序,以一个字符和任意文件名作为命令行参数。如果字符 后面没有参数,该程序读取标准输入;否则,程序依次打开每个文件并报告 每个文件中该字符出现的次数。文件名和字符本身也要一同报告。程序应包 957 含错误检查,以确定参数数量是否正确和是否能打开文件。如果无法打开文 件,程序应报告这一情况,然后继续处理下一个文件。

    #include 
    #include 
    int main(int argc, char * argv[])
    {
        int i;
        char ch;
        FILE * fp;
        int count = 0;
    
        if (argc < 2)
        {
            fprintf(stderr, "the wrong number of arguments.");
            exit(EXIT_FAILURE);
        }
    
        if (argc == 2)
        {
            printf("Input some texts:n");
            while ((ch = getchar()) != EOF)
            {
                if (ch == argv[1][0])
                    count++;
            }
            printf("the "%s" in your input: %d times.",
                argv[1], count);
        }
    
        else
        {
            for (i = 2; i < argc; i++)
            {
                count = 0;
                if ((fp = fopen(argv[i], "r")) == NULL)
                {
                    fprintf(stderr, "Could not open the %s.", argv[i]);
                    continue;
                }
                while ((ch = getc(fp)) != EOF)
                {
                    if (ch == argv[1][0])
                        count++;
                }
                fprintf(stdout, "the "%s" in %s: %d times.n",
                    argv[1], argv[i], count);
            }
        }
    
        return 0;
    }
    
    
  2. 修改程序清单 13.3 中的程序,从 1 开始,根据加入列表的顺序为每个 单词编号。当程序下次运行时,确保新的单词编号接着上次的编号开始。

    #include 
    #include 
    #include 
    #define MAX 41
    int main(void)
    {
        FILE * fp;
        char words[MAX];
        char name[MAX];
        int count = 0;
    
        printf("Please input the file name:n");
        gets(name);
        if ((fp = fopen(name, "a+")) == NULL)
        {
            fprintf(stderr, "can't open "%s" file.n", name);
            exit(EXIT_FAILURE);
        }
    
        puts("Enter words to add to the file; press the #");
        puts("key at the beginning of a line to terminate.");
        while ((fscanf(stdin, "%40s", words) == 1) && (words[0] != '#'))
            fprintf(fp, "%sn", words);
        puts("File contents:");
        rewind(fp);
        while (fscanf(fp, "%s", words) != EOF)
        {
            count++;
            fprintf(stdout, "%d. %sn", count, words);
        }
        puts("Done!");
        if (fclose(fp) != 0)
            fprintf(stderr, "Error closing filen");
    
        return 0;
    }
    
  3. 编写一个程序打开一个文本文件,通过交互方式获得文件名。通过 一个循环,提示用户输入一个文件位置。然后该程序打印从该位置开始到下 一个换行符之前的内容。用户输入负数或非数值字符可以结束输入循环。

    #include 
    #include 
    #define LEN 41
    int main(void)
    {
        char name[LEN];
        char words[LEN];
        FILE * fp;
        long offset;			//偏移量
        
        printf("Please input the file name:n");
        gets(name);
        if ((fp = fopen(name, "r")) == NULL)
        {
            fprintf(stderr, "can't open "%s" file.n", name);
            exit(EXIT_FAILURE);
        }
        printf("Please input a position in the file (negative number or "
            "Non numeric character to quit):n");
        while (scanf("%ld", &offset) == 1 && offset > 0)
        {
            getchar();
            fseek(fp, offset, SEEK_SET);
            fscanf(fp, "%40s", words);
            fprintf(stdout, "%sn", words);
            printf("Please input a position in the file (negative number orn"
            "Non numeric character to quit):n");
        }
        fclose(fp);
    
        return 0;
    }
    
    
        
    
  4. 编写一个程序,接受两个命令行参数。第 1 个参数是一个字符串, 第 2 个参数是一个文件名。然后该程序查找该文件,打印文件中包含该字符串 的所有行。因为该任务是面向行而不是面向字符的,所以要使用 fgets()而不 是 getc()。使用标准 C 库函数 strstr()(11.5.7 节简要介绍过)在每一行中查 找指定字符串。假设文件中的所有行都不超过 255 个字符。

    #include 
    #include 
    #include 
    #define SIZE 256
    int main(int argc, char * argv[])
    {
        FILE * fp;
        char words[SIZE];
    
        if (argc < 3)
        {
            fprintf(stderr, "Wrong number of arguments.n");
            exit(EXIT_FAILURE);
        }
        if ((fp = fopen(argv[2], "r")) == NULL)
        {
            fprintf(stderr, "Could not open %s.", argv[2]);
            exit(EXIT_FAILURE);
        }
        while (fgets(words, SIZE, fp) != NULL)
        {
            if (strstr(words, argv[1]) != NULL)
                fputs(words, stdout);
                //printf("成功n");//yanzheng
        }
    
        if (fclose(fp) != 0)
            fprintf(stderr, "Error for closing file.n");
    
        return 0;
    }
    
    
    
    
    
  5. 创建一个文本文件,内含 20 行,每行 30 个整数。这些整数都在 0~ 9 之间,用空格分开。该文件是用数字表示一张图片,0~9 表示逐渐增加的 灰度。编写一个程序,把文件中的内容读入一个 20×30 的 int 数组中。一种 把这些数字转换为图片的粗略方法是:该程序使用数组中的值初始化一个 20×31 的字符数组,用值 0 对应空格字符,1 对应点字符,以此类推。数字 越大表示字符所占的空间越大。例如,用#表示 9。每行的最后一个字符 (第 31 个)是空字符,这样该数组包含了 20 个字符串。最后,程序显示最 终的图片 (即,打印所有的字符串),并将结果储存在文本文件中。例如,下面是开 始的数据:

     0 0 9 0 0 0 0 0 0 0 0 0 5 8 9 9 8 5 2 0 0 0 0 0 0 0 0 0 0 0
     0 0 0 0 9 0 0 0 0 0 0 0 5 8 9 9 8 5 5 2 0 0 0 0 0 0 0 0 0 0 
     0 0 0 0 0 0 0 0 0 0 0 0 5 8 1 9 8 5 4 5 2 0 0 0 0 0 0 0 0 0 
     0 0 0 0 9 0 0 0 0 0 0 0 5 8 9 9 8 5 0 4 5 2 0 0 0 0 0 0 0 0
     0 0 9 0 0 0 0 0 0 0 0 0 5 8 9 9 8 5 0 0 4 5 2 0 0 0 0 0 0 0
     0 0 0 0 0 0 0 0 0 0 0 0 5 8 9 1 8 5 0 0 0 4 5 2 0 0 0 0 0 0
     0 0 0 0 0 0 0 0 0 0 0 0 5 8 9 9 8 5 0 0 0 0 4 5 2 0 0 0 0 0
     5 5 5 5 5 5 5 5 5 5 5 5 5 8 9 9 8 5 5 5 5 5 5 5 5 5 5 5 5 5
     8 8 8 8 8 8 8 8 8 8 8 8 5 8 9 9 8 5 8 8 8 8 8 8 8 8 8 8 8 8
     9 9 9 9 0 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 3 9 9 9 9 9 9 9
     8 8 8 8 8 8 8 8 8 8 8 8 5 8 9 9 8 5 8 8 8 8 8 8 8 8 8 8 8 8
     5 5 5 5 5 5 5 5 5 5 5 5 5 8 9 9 8 5 5 5 5 5 5 5 5 5 5 5 5 5
     0 0 0 0 0 0 0 0 0 0 0 0 5 8 9 9 8 5 0 0 0 0 0 0 0 0 0 0 0 0
     0 0 0 0 0 0 0 0 0 0 0 0 5 8 9 9 8 5 0 0 0 0 6 6 0 0 0 0 0 0
     0 0 0 0 2 2 0 0 0 0 0 0 5 8 9 9 8 5 0 0 5 6 0 0 6 5 0 0 0 0
     0 0 0 0 3 3 0 0 0 0 0 0 5 8 9 9 8 5 0 5 6 1 1 1 1 6 5 0 0 0
     0 0 0 0 4 4 0 0 0 0 0 0 5 8 9 9 8 5 0 0 5 6 0 0 6 5 0 0 0 0
     0 0 0 0 5 5 0 0 0 0 0 0 5 8 9 9 8 5 0 0 0 0 6 6 0 0 0 0 0 0
     0 0 0 0 0 0 0 0 0 0 0 0 5 8 9 9 8 5 0 0 0 0 0 0 0 0 0 0 0 0
     0 0 0 0 0 0 0 0 0 0 0 0 5 8 9 9 8 5 0 0 0 0 0 0 0 0 0 0 0 0 
    

    根据以上描述选择特定的输出字符,最终输出如下:

    #include 
    #include 
    #define LEN 40
    #define ROW 20
    #define COL 30
    int main(void)
    {
        FILE * fs, * fd;				//fs指向源文件,fd指向目标文件
        char name[LEN];
        char digit[ROW][COL];
        char result[ROW][COL + 1];
        char ch[] = {" .':~*= %#"};		//数字字符对应的符号
        int i, j;
    
        printf("Please enter the source file name:n");
        gets(name);
        //打开源文件
        if ((fs = fopen(name, "r")) == NULL)
        {
            fprintf(stderr, "Could not open %s.", name);
            exit(EXIT_FAILURE);
        }
        //将文件内容读入 20 * 30 的int数组中
        //并且转化成相应符号放入 20 * 31 的字符数组中
        for (i = 0; i < ROW; i++)
        {
            for (j = 0; j < COL; j++)
            {
                fscanf(fs, "%d", &digit[i][j]);
                result[i][j] = ch[digit[i][j]];
            }
            result[i][j] = '';
        }
        printf("Enter the destination file name:n");
        gets(name);
        //打开目标文件
        if ((fd = fopen(name, "w")) == NULL)
        {
            fprintf(stderr, "Could not open %s.", name);
            exit(EXIT_FAILURE);
        }
        //将结果打印出来并写入目标文件
        for (i = 0; i < ROW; i++)
        {
            fprintf(stdout, "%sn", result[i]);
            fprintf(fd, "%sn", result[i]);
        }
        //关闭文件
        if (fclose(fs) != 0 || fclose(fd) != 0)
            fprintf(stderr, "Error for closing file.n");
    
        return 0;
    }
    
    
  6. 用变长数组(VLA)代替标准数组,完成编程练习 12。

    # include 
    # include 
    
    # define FNAME "1.txt"
    # define FARGS "2.txt"
    # define STR " .':~*=&%#"
    
    int main(void)
    {
    
    	FILE * fp , * ft;
    	int ar[20][30] ;
    	char st[20][31] ;
    
    	if (!(fp = fopen(FNAME, "r")))
    	{
    
    		fprintf(stderr , "Can't open file %s.n" ,FNAME) ;
    		exit(EXIT_FAILURE);
    	}
    
    	if (!(ft = fopen(FARGS , "w")))
    	{
    
    		fprintf(stderr , "Can't open file %s.n" ,FARGS);
    		exit(EXIT_FAILURE);
    	}
    
    	// 读取文件中的内容到整型数组
    	for (int i = 0 ; i < 20 ; i++)
    		for (int j = 0 ; j < 30 ; j++)
    			//这样做是为了确保fscanf()正确读到1个数,而不受空格和其他字符影响
    			while (fscanf(fp ,"%d" , &ar[i][j]) != 1)
    				fscanf(fp ,"%*c");
    
    	// 初始化字符串数组
    	for (int j ,i = 0 ; i < 20 ; i++)
    	{
    
    		for ( j = 0 ; j < 30 ; j++)
    			st[i][j] = *(STR + ar[i][j]);
    		st[i][j] = '' ;
    		fprintf(ft ,"%sn" ,st[i] );
    	}
    
    	if (fclose(fp) || fclose(ft))
    	{
    
    		fprintf(stderr , "Clossing error .n");
    		exit(EXIT_FAILURE);
    	}
    
    	return 0 ;
    }
    
    
  7. 数字图像,尤其是从宇宙飞船发回的数字图像,可能会包含一些失 真。为编程练习 12 添加消除失真的函数。该函数把每个值与它上下左右相 邻的值作比较,如果该值与其周围相邻值的差都大于 1,则用所有相邻值的 平均值(四舍五入为整数)代替该值。注意,与边界上的点相邻的点少于 4 个,所以做特殊处理。

    #include 
    #include 
    #include 
    #define LEN 40
    #define ROW 20
    #define COL 30
    int main(void)
    {
        FILE * fs, * fd;				//fs指向源文件,fd指向目标文件
        char name[LEN];
        char dig[ROW][COL];
        char res[ROW][COL + 1];
        char ch[] = {" .':~*= %#"};		//数字字符对应的符号
        int i, j;
    
        printf("Please enter the source file name:n");
        gets(name);
        //打开源文件
        if ((fs = fopen(name, "r")) == NULL)
        {
            fprintf(stderr, "Could not open %s.", name);
            exit(EXIT_FAILURE);
        }
        //将文件内容读入 20 * 30 的int数组中
        //并且转化成相应符号放入 20 * 31 的字符数组中
        for (i = 0; i < ROW; i++)
        {
            for (j = 0; j < COL; j++)
            {
                fscanf(fs, "%d", &dig[i][j]);
            }
        }
        for (i = 0; i < ROW; i++)
        {
            for (j = 0; j < COL; j++)
            {
                if ((i == 0 && j == 0) || (i == 0 && j == 29)
                    ||(i == 19 && j == 0) || (i == 19 && j == 29))
                    ;
                else if (i == 0) {
                    if ((abs(dig[i][j] - dig[i][j - 1]) > 1) && (abs(dig[i][j] - dig[i][j + 1]) > 1) &&
                        (abs(dig[i][j] - dig[i + 1][j]) > 1))
                        dig[i][j] = (dig[i][j - 1] + dig[i][j + 1] + dig[i + 1][j]) / 3.0 + 0.5;
                }
                else if (j == 0) {
                    if ((abs(dig[i][j] - dig[i - 1][j]) > 1) && (abs(dig[i][j] - dig[i][j + 1]) > 1) &&
                        (abs(dig[i][j] - dig[i + 1][j]) > 1))
                        dig[i][j] = (dig[i - 1][j] + dig[i][j + 1] + dig[i + 1][j]) / 3.0 + 0.5;
                }
    
                else if (i == 19) {
                    if ((abs(dig[i][j] - dig[i][j - 1]) > 1) && abs((dig[i][j] - dig[i][j + 1]) > 1) &&
                        (abs(dig[i][j] - dig[i - 1][j]) > 1))
                        dig[i][j] = (dig[i - 1][j] + dig[i][j - 1] + dig[i][j + 1]) / 3.0 + 0.5;
                }
    
                else if (j == 29) {
                    if ((abs(dig[i][j] - dig[i][j - 1]) > 1) && (abs(dig[i][j] - dig[i + 1][j]) > 1) &&
                        (abs(dig[i][j] - dig[i - 1][j]) > 1))
                        dig[i][j] = (dig[i - 1][j] + dig[i][j - 1] + dig[i + 1][j]) / 3.0 + 0.5;
                }
                
                else {
                    if ((abs(dig[i][j] - dig[i][j - 1]) > 1) && (abs(dig[i][j] - dig[i][j + 1]) > 1) &&
                        (abs(dig[i][j] - dig[i - 1][j]) > 1) && (abs(dig[i][j] - dig[i + 1][j]) > 1))
                        dig[i][j] = (dig[i - 1][j] + dig[i + 1][j] + dig[i][j - 1] + dig[i][j + 1]) / 4.0 + 0.5;
                }
            }
        }
    
        for (i = 0; i < ROW; i++)
        {
            for (j = 0; j < COL; j++)
            {
                res[i][j] = ch[dig[i][j]];
            }
            res[i][j] = '';
        }
        printf("Enter the destination file name:n");
        gets(name);
        //打开目标文件
        if ((fd = fopen(name, "w")) == NULL)
        {
            fprintf(stderr, "Could not open %s.n", name);
            exit(EXIT_FAILURE);
        }
        //将结果打印出来并写入目标文件
        for (i = 0; i < ROW; i++)
        {
            fprintf(stdout, "%sn", res[i]);
            fprintf(fd, "%sn", res[i]);
        }
        //关闭文件
        if (fclose(fs) != 0 || fclose(fd) != 0)
            fprintf(stderr, "Error for closing file.n");
    
        return 0;
    }
    
第十四章 结构和其他数据形式
  1. 重新编写复习题 5,用月份名的拼写代替月份号(别忘了使用 strcmp())。在一个简单的程序中测试该函数。

    #include 
    #include 
    #include 
    #define NAMELEN 10
    #define ABBLEN 4
    #define MONTHS 12
    char * s_gets(char * st, int n);
    int get_days(char * st);
    
    struct month {
        char name[NAMELEN];
        char abbrev[ABBLEN];
        int days;
        int monumb;
    };
    
    struct month months[12] = {
        {"january", "jan", 31, 1},
        {"february", "feb", 28, 2},
        {"march", "mar", 31, 3},
        {"april", "apr", 30, 4},
        {"may", "may", 31, 5},
        {"june", "jun", 30, 6},
        {"july", "jul", 31, 7},
        {"august", "aug", 31, 8},
        {"september", "sep", 30, 9},
        {"october", "oct", 31, 10},
        {"november", "nov", 30, 11},
        {"december", "dec", 31, 12}
    };
    
    int main(void)
    {
        char st[NAMELEN];
    
        printf("Please input the month name (empty line to quit):n");
        while (s_gets(st, NAMELEN) != NULL && st[0] != '')
        {
            if (get_days(st) == 0)
                printf("The month name is wrong.n");
            else
            printf("The days untill %s: %dn", st, get_days(st));
            printf("Next input (empty line to quit):n");
        }
    
        printf("Bye.n");
        return 0;
    }
    
    
    int get_days(char * st)
    {
        int total = 0;
        int i = 0;
        int count;
    
        while (st[i])
        {
            st[i] = tolower(st[i]);
            i++;
        }
    
        for (i = 0; i < MONTHS; i++)
        {
            if (strcmp(st, months[i].name) == 0)
                break;
        }
        if (i < MONTHS)
        {
            for (count = 0; count <= i; count++)
                total += months[count].days;
        }
    
        return total;
    }
    
    char * s_gets(char * st, int n)
    {
        char * ret_val;
        char * find;
    
        ret_val = fgets(st, n, stdin);
        if (ret_val)
        {
            find = strchr(st, 'n');
            if (find)
                *find = '';
            else
                while (getchar() != 'n')
                    continue;
        }
    
        return ret_val;
    }
    
    
  2. 编写一个函数,提示用户输入日、月和年。月份可以是月份号、月份 名或月份名缩写。然后该程序应返回一年中到用户指定日子(包括这一天) 的总天数。

    #include 
    #include 
    #include 
    #define NAMELEN 10
    #define ABBLEN 4
    #define MONTHS 12
    
    struct month {
        char name[NAMELEN];
        char abbrev[ABBLEN];
        int days;
        int monumb;
    };
    
    struct month months[MONTHS] = {
        {"january", "jan", 31, 1},
        {"february", "feb", 28, 2},
        {"march", "mar", 31, 3},
        {"april", "apr", 30, 4},
        {"may", "may", 31, 5},
        {"june", "jun", 30, 6},
        {"july", "jul", 31, 7},
        {"august", "aug", 31, 8},
        {"september", "sep", 30, 9},
        {"october", "oct", 31, 10},
        {"november", "nov", 30, 11},
        {"december", "dec", 31, 12}
    };
    
    int get_res(void);
    void get_years(void);
    int get_months(void);
    int get_days(int);
    
    int main(void)
    {
        int total_days;
    
        total_days = get_res();
        printf("The number of days before the specified day ");
        printf("is %dn", total_days);
        return 0;
    }
    
    //得到结果的函数
    int get_res(void)
    {
        int n_months;
        int n_days;
        int i;
        int total = 0;
    
        get_years();
        n_months = get_months();
        n_days = get_days(n_months);
    
        for (i = 0; i < n_months - 1; i++)
        {
            total += months[i].days;
        }
        total += n_days;
    
        return total;
    }
    
    //输入并处理年数
    void get_years(void)
    {
        int n_years;
    
        printf("Please input a particular year: ");
        while (scanf("%d", &n_years) != 1)
        {
            while (getchar() != 'n')
                continue;
            printf("Please input a integer: ");
        }
        if (n_years % 4 == 0)
            months[1].days = 29;
        else
            months[1].days = 28;
    }
    
    //输入并处理月份
    int get_months(void)
    {
        int n_months;
    
        printf("Input the month: ");
        while (scanf("%d", &n_months) != 1 || (n_months < 0 || n_months > 12))
        {
            while (getchar() != 'n')
                continue;
            printf("Please input a integer from 1 to 12: ");
        }
    
        return n_months;
    }
    
    //输入并处理天数
    int get_days(int n)
    {
        int n_days;
    
        printf("Input the days: ");
        while (scanf("%d", &n_days) != 1 ||
            (n_days < 1 || n_days > months[n - 1].days))
        {
            while (getchar() != 'n')
                continue;
            printf("Please input a integer from 1 to %d: ",
                months[n - 1].days);
        }
    
        return n_days;
    }
    
    
  3. 修改程序清单 14.2 中的图书目录程序,使其按照输入图书的顺序输出 图书的信息,然后按照标题字母的声明输出图书的信息,最后按照价格的升 序输出图书的信息。

    #include 
    #include 
    #define MAXTITL 40
    #define MAXAUTL 40
    #define MAXBKS 100
    
    struct book {
        char title[MAXTITL];
        char author[MAXAUTL];
        float value;
    };
    
    void sort_by_input(const struct book library[], int n);
    void sort_by_title(struct book library[], int n);
    void sort_by_price(struct book library[], int n);
    char * s_gets(char * st, int n);
    
    int main(void)
    {
        static struct book library[MAXBKS];
        int count = 0;
    
        printf("Please enter the book title (empty line to stop):n");
        while (count < MAXBKS && s_gets(library[count].title, MAXTITL) != NULL
            && library[count].title[0] != '')
        {
            printf("Now enter the author.n");
            s_gets(library[count].author, MAXTITL);
            printf("Now enter the value.n");
            scanf("%f", &library[count++].value);
            while (getchar() != 'n')
                continue;
            if (count < MAXBKS)
                printf("Enter the next title.n");
        }
    
        if (count > 0)
        {
            printf("The list of books in order of your input:n");
            sort_by_input(library, count);
            printf("The list of books in order of title:n");
            sort_by_title(library, count);
            printf("The list of books in order of price:n");
            sort_by_price(library, count);
        }
        
        return 0;
    }
    
    void sort_by_input(const struct book library[], int n)
    {
        int i;
    
        for (i = 0; i < n; i++)
            printf("%s by %s: $%.2fn", library[i].title,
                library[i].author, library[i].value);
        printf("n");
    }
    
    void sort_by_title(struct book library[], int n)
    {
        int i, j;
        struct book temp;
        
        for (i = 0; i < n - 1; i++)
        {
            for (j = i + 1; j < n; j++)
                if (strcmp(library[i].title, library[j].title) > 0)
                {
                    temp = library[i];
                    library[i] = library[j];
                    library[j] = temp;
                }
        }
        for (i = 0; i < n; i++)
            printf("%s by %s: $%.2fn", library[i].title,
                library[i].author, library[i].value);
        printf("n");
    }
    
    void sort_by_price(struct book library[], int n)
    {
        int i, j;
        struct book temp;
        
        for (i = 0; i < n - 1; i++)
        {
            for (j = i + 1; j < n; j++)
                if (library[i].value > library[j].value)
                {
                    temp = library[i];
                    library[i] = library[j];
                    library[j] = temp;
                }
        }
        for (i = 0; i < n; i++)
            printf("%s by %s: $%.2fn", library[i].title,
                library[i].author, library[i].value);
        printf("n");
    }
    
    char * s_gets(char * st, int n)
    {
        char * ret_val;
        char * find;
    
        ret_val = fgets(st, n, stdin);
        if (ret_val)
        {
            find = strchr(st, 'n');
            if (find)
                *find = '';
            else
                while (getchar() != 'n')
                    continue;
        }
    
        return ret_val;
    }
    
  4. 编写一个程序,创建一个有两个成员的结构模板: a.第 1 个成员是社会保险号,第 2 个成员是一个有 3 个成员的结构,第 1 个成员代表名,第 2 个成员代表中间名,第 3 个成员表示姓。创建并初始 化一个内含 5 个该类型结构的数组。该程序以下面的格式打印数据:

Dribble, Flossie M.–– 302039823

如果有中间名,只打印它的第 1 个字母,后面加一个点(.);如果没有 中间名,则不用打印点。编写一个程序进行打印,把结构数组传递给这个函 数。

b.修改 a 部分,传递结构的值而不是结构的地址。

a.

#include 
#define SSN 20
#define LEN 10

struct names {
    char last_name[LEN];
    char mid_name[LEN];
    char fir_name[LEN];
};

struct person {
    char number[SSN];
    struct names name;
};

void print_info(struct person info[], int n);

int main(void)
{
    struct person info[5] = {
        {"B51414029", {"Jie", "Yu", "Zha"}},
        {"B51414010", {"Xiang", "Xiang", "Pan"}},
        {"B51414025", {"Jie", "Wen", "Jiang"}},
        {"B51414031", {"Ming", "Cheng", "Liu"}},
        {"B51414044", {"Qiang", " ", "Sha"}}
    };

    print_info(info, 5);

    return 0;
}

void print_info(struct person info[], int n)
{
    int i;

    for (i = 0; i < n; i++)
    {
        printf("%s, %s %c%c -- %s", info[i].name.last_name,
        info[i].name.fir_name, info[i].name.mid_name[0],
        (info[i].name.mid_name[0] == ' ') ? ' ': '.', info[i].number);
        printf("n");
    }
}

b.

#include 
#define SSN 20
#define LEN 10

struct names {
    char last_name[LEN];
    char mid_name[LEN];
    char fir_name[LEN];
};

struct person {
    char number[SSN];
    struct names name;
};

void print_info(struct person info);

int main(void)
{
    int index;

    struct person info[5] = {
        {"B51414029", {"Jie", "Yu", "Zha"}},
        {"B51414010", {"Xiang", "Xiang", "Pan"}},
        {"B51414025", {"Jie", "Wen", "Jiang"}},
        {"B51414031", {"Ming", "Cheng", "Liu"}},
        {"B51414044", {"Qiang", " ", "Sha"}}
    };

    for (index = 0; index < 5; index++)
        print_info(info[index]);

    return 0;
}

void print_info(struct person info)
{
    printf("%s, %s %c%c -- %s", info.name.last_name,
    info.name.fir_name, info.name.mid_name[0],
    (info.name.mid_name[0] == ' ') ? ' ': '.', info.number);
    printf("n");
    
}

  1. 编写一个程序满足下面的要求。
a.外部定义一个有两个成员的结构模板 name:一个字符串储存名,一个 字符串储存姓。 

b.外部定义一个有 3 个成员的结构模板 student:一个 name 类型的结 构,一个 grade 数组储存 3 个浮点型分数,一个变量储存 3 个分数平均数。

 c.在 main()函数中声明一个内含 CSIZE(CSIZE = 4)个 student 类型结构 的数组,并初始化这些结构的名字部分。用函数执行 g、e、f 和 g 中描述的 任务。 

d.以交互的方式获取每个学生的成绩,提示用户输入学生的姓名和分 数。把分数储存到 grade 数组相应的结构中。可以在 main()函数或其他函数 中用循环来完成。

 e.计算每个结构的平均分,并把计算后的值赋给合适的成员。 

f.打印每个结构的信息。 

g.打印班级的平均分,即所有结构的数值成员的平均值。
#include 
#define LEN 10
#define NUM 3
#define CSIZE 4
#define N_SCORES 3

struct name {
    char first_name[LEN];
    char last_name[LEN];
};

struct student {
    struct name names;
    float grade[NUM];
    float average;
};

void get_score(struct student info[], int n);
void get_aver(struct student info[], int n);
void print_info(struct student info[], int n);
void get_all_aver(struct student info[], int n);

int main(void)
{
    struct student score[CSIZE] = {
        {{"Zha", "Yujie"}, {0, 0, 0}, 0},
        {{"Jiang", "Wenjie"}, {0, 0, 0}, 0},
        {{"Liu", "Chengming"}, {0, 0, 0}, 0},
        {{"Pan", "Xiangxiang"}, {0, 0, 0}, 0}
    };
    get_score(score, CSIZE);
    get_aver(score, CSIZE);
    print_info(score, CSIZE);
    get_all_aver(score, CSIZE);

    return 0;
}

void get_score(struct student info[], int n)
{
    int i, j;

    for (i = 0; i < n; i++)
    {
        printf("Input the scores of 3 courses of %s %sn",
            info[i].names.first_name, info[i].names.last_name);
        for (j = 0; j < N_SCORES; j++)
        {
            scanf("%f", &info[i].grade[j]);
        }
    }
}

void get_aver(struct student info[], int n)
{

    int i, j;
    float sum;

    for (i = 0; i < n; i++)
    {
        for (j = 0, sum = 0.0; j < N_SCORES; j++)
        {
            sum += info[i].grade[j];
        }
        info[i].average = sum / N_SCORES;
    }
}

void print_info(struct student info[], int n)
{
    int i, j;

    printf("    Name%15s %s %s  averagen", "score1",
        "score2", "score3");
    for (i = 0; i < n; i++)
    {
        printf("%5s%-10s  ", info[i].names.first_name,
            info[i].names.last_name);
        for (j = 0; j < N_SCORES; j++)
            printf("%6g", info[i].grade[j]);
        printf("%11.2fn", info[i].average);
    }
}

void get_all_aver(struct student info[], int n)
{
    int i;
    float total = 0;

    for (i = 0; i < n; i++)
    {
        total += info[i].average;
    }
        printf("The average score of all students is %.2f.n",
            total / CSIZE);
}

  1. 一个文本文件中保存着一个垒球队的信息。每行数据都是这样排列:
 4 Jessie Joybat 5 2 1 1 

第 1 项是球员号,为方便起见,其范围是 0~18。第 2 项是球员的名。 第 3 项是球员的姓。名和姓都是一个单词。第 4 项是官方统计的球员上场次数。接着 3 项分别是击中数、走垒数和打点(RBI)。文件可能包含多场比赛 的数据,所以同一位球员可能有多行数据,而且同一位球员的多行数据之间 可能有其他球员的数据。编写一个程序,把数据储存到一个结构数组中。该 结构中的成员要分别表示球员的名、姓、上场次数、击中数、走垒数、打点 和安打率(稍后计算)。可以使用球员号作为数组的索引。该程序要读到文 件结尾,并统计每位球员的各项累计总和。

世界棒球统计与之相关。例如,一次走垒和触垒中的失误不计入上场次 数,但是可能产生一个 RBI。但是该程序要做的是像下面描述的一样读取和 处理数据文件,不会关心数据的实际含义。

要实现这些功能,最简单的方法是把结构的内容都初始化为零,把文件 中的数据读入临时变量中,然后将其加入相应的结构中。程序读完文件后, 应计算每位球员的安打率,并把计算结果储存到结构的相应成员中。计算安 打率是用球员的累计击中数除以上场累计次数。这是一个浮点数计算。最 后,程序结合整个球队的统计数据,一行显示一位球员的累计数据。

#include 
#include 
#include 
#define LEN 10
#define NLEN 20
#define SIZE 20

struct member {
    int num;
    char fname[LEN];
    char lname[LEN];
    int play;
    int hit;
    int walk;
    int rbi;
};

void get_initial_val(struct member *, int n);
void get_data(struct member *, int n);
void print_info(struct member *, int n);

int main(void)
{
    static struct member members[SIZE];

    get_initial_val(members, SIZE);
    get_data(members, SIZE);
    print_info(members, SIZE);

    return 0;
}
    
void get_initial_val(struct member * pst, int n)
{
    int i;

    for (i = 0; i < n; i++, pst++)
    {
        pst->num = 0;
        strcpy(pst->fname, "");
        strcpy(pst->lname, "");
        pst->play = 0;
        pst->hit = 0;
        pst->walk = 0;
        pst->rbi = 0;
    }
}

void get_data(struct member * pst, int n)
{
    int number, play_times, hit_times, walk_times, rbi_num;
    FILE * fp;
    char name[NLEN];
    char f_name[LEN], l_name[LEN];

    printf("Please enter the file name: ");
    scanf("%s", name);
    if ((fp = fopen(name, "r")) == NULL)
    {
        fprintf(stderr, "Can't open %sn", name);
        exit(EXIT_FAILURE);
    }
    while (fscanf(fp, "%d%s%s%d%d%d%d", &number, f_name, l_name,
        &play_times, &hit_times, &walk_times, &rbi_num) == 7)
    {
        pst[number].num = number;
        strcpy(pst[number].fname, f_name);
        strcpy(pst[number].lname, l_name);
        pst[number].play += play_times;
        pst[number].hit += hit_times;
        pst[number].walk += walk_times;
        pst[number].rbi += rbi_num;
    }
    fclose(fp);
}

void print_info(struct member * pst, int n)
{
    int i;

    for (i = 0; i < n; i++)
    {
        if (pst[i].fname[0] != '')
        {
            printf("%d %s %s %d %d %d %d", pst[i].num, pst[i].fname, pst[i].lname,
                    pst[i].play, pst[i].hit, pst[i].walk, pst[i].rbi);
            printf("n");
        }
        else
            break;
    }
}


    
  1. 修改程序清单 14.14,从文件中读取每条记录并显示出来,允许用户 删除记录或修改记录的内容。如果删除记录,把空出来的空间留给下一个要 读入的记录。要修改现有的文件内容,必须用"r+b"模式,而不是"a+b"模 式。而且,必须更加注意定位文件指针,防止新加入的记录覆盖现有记录。 最简单的方法是改动储存在内存中的所有数据,然后再把最后的信息写入文 件。跟踪的一个方法是在 book 结构中添加一个成员表示是否该项被删除。

    #include 
    #include 
    #include 
    #define LEN 20
    #define MAXTITL 40
    #define MAXAUTH 40
    #define MAXBKS 10
    
    int count = 0;							//外部变量,书的数目
    
    struct book {
        char title[MAXTITL];
        char author[MAXAUTH];
        float value;
    };
    
    char * s_gets(char * st, int n);		//输入字符串的函数
    char get_choice(void);					//获取用户选择
    void add(struct book *);				//添加若干本书
    void change(struct book *);				//替换一本书
    void del(struct book *);				//删除一本书
    void print(struct book *);				//打印书单
    void write_file(struct book *, char *);	//将数据写入文件
    
    int main(void)
    {
        char name[LEN];
        struct book library[MAXBKS];
        char ch;
        FILE * fp;
    
        //打开文件并读取其中内容到结构体
        printf("Please input the file name: ");
        s_gets(name, LEN);
        if ((fp = fopen(name, "a+b")) == NULL)
        {
            fprintf(stderr, "Can't open %s", name);
            exit(EXIT_FAILURE);
        }
        rewind(fp);
        while (count < MAXBKS && fread(&library[count],
            sizeof(struct book), 1, fp) == 1)
        {
            count++;						//当前文件数
        }
        fclose(fp);
        
        //打印文件中已有数据
        printf("There are %d books:n", count);
        print(library);
    
        //让用户输入选项
        while ((ch = get_choice()) != 'q')
        {
            switch (ch)
            {
                case 'a': add(library);
                          break;
                case 'c': change(library);
                          break;
                case 'd': del(library);
                          break;
                case 'p': print(library);
                          break;
                default: printf("Program error.n");
                        break;
            }
        }
        //将数据输出至文件中
        write_file(library, name);
        
        return 0;
    }
    
    char get_choice(void)
    {
        char ch;
        
        printf("Please input your choice:n");
        printf("a. add some books        c. change a bookn");
        printf("d. delete a book         p. print all booksn");
        printf("q. quit.n");
        while ((ch = getchar()) != 'a' && ch != 'c' && ch != 'd' &&
            ch != 'p' && ch != 'q')
        {
            while (getchar() != 'n')
                continue;
            printf("Please input the right character.n");
        }
        while (getchar() != 'n')
                continue;
    
        return ch;
    }
    
    void add(struct book * ps)
    {
        if (count == MAXBKS)
            printf("Sorry, the list is full.n");
        else
        {
            printf("Please input the title (empty line to quit):n");
            while (count < MAXBKS && s_gets(ps[count].title, MAXTITL) != NULL
                && ps[count].title[0] != '')
            {
                printf("Input the author:n");
                s_gets(ps[count].author, MAXAUTH);
                printf("Input the value:n");
                scanf("%f", &ps[count].value);
                getchar();
                printf("Now, next title (empty line to quit):n");
                count++;
            }
        }
    }
    
    void change(struct book * ps)
    {
        int i;
        char name[MAXTITL];
    
        if (count == 0)
            printf("Sorry, the list is empty.n");
        else
        {
            printf("Please input the title of book you want to change:n");
            s_gets(name, MAXTITL);
            for (i = 0; i < count; i++)
            {
                if (!strcmp(name, ps[i].title))
                {
                    printf("Please input the title of new book:n");
                    s_gets(ps[i].title, MAXTITL);
                    printf("Input the author:n");
                    s_gets(ps[i].author, MAXAUTH);
                    printf("Input the value:n");
                    scanf("%f", &ps[i].value);
                    getchar();
                    break;
                }
            }
            if (i == count)
                printf("Sorry, we can't find the book you input.n");
        }
        
    }
    
    void del(struct book * ps)
    {
        char name[MAXTITL];
        int i, j;
    
        if (count == 0)
            printf("Sorry, the list is empty.n");
        printf("Please input the title of book you want to delete:n");
        s_gets(name, MAXTITL);
        for (i = 0; i < count; i++)
        {
            if (!strcmp(name, ps[i].title))
            {
                for (j = i + 1; j < count; j++)
                    ps[j - 1] = ps[j];
                count--;
                strcpy(ps[count].title, "");
                strcpy(ps[count].author, "");
                ps[count].value = 0;
                break;
            }
        }
        if (i == count)
            printf("Sorry, we can't find the book you input.n");
    }
    
    void print(struct book * ps)
    {
        int i;
    
        for (i = 0; i < count; i++)
        {
            printf("%s by %s: $%gn", ps[i].title, ps[i].author,
                ps[i].value);
        }
    }
    
    void write_file(struct book * ps, char * st)
    {
        FILE * fp;
    
        fp = fopen(st, "w+b");
        fwrite(ps, sizeof(struct book), count, fp);
        fclose(fp);
    }
    
    char * s_gets(char * st, int n)
    {
        char * ret_val;
        char * find;
    
        ret_val = fgets(st, n, stdin);
        if (ret_val)
        {
            find = strchr(st, 'n');
            if (find)
                *find = '';
            else
                while (getchar() != 'n')
                    continue;
        }
    
        return ret_val;
    }
    
  2. 巨人航空公司的机群由 12 个座位的飞机组成。它每天飞行一个航 班。根据下面的要求,编写一个座位预订程序。

a.该程序使用一个内含 12 个结构的数组。每个结构中包括:一个成员 表示座位编号、一个成员表示座位是否已被预订、一个成员表示预订人的 名、一个成员表示预订人的姓。

b.该程序显示下面的菜单:

To choose a function, enter its letter label:
a) Show number of empty seats
b) Show list of empty seats
c) Show alphabetical list of seats
d) Assign a customer to a seat assignment
e) Delete a seat assignment
f) Quit

c.该程序能成功执行上面给出的菜单。选择 d)和 e)要提示用户进行额外 输入,每个选项都能让用户中止输入。

d.执行特定程序后,该程序再次显示菜单,除非用户选择 f)。

#include 
#include 
#include 
#define LEN 20
#define LEN 20
#define MAX 12

struct seat {
    int num;
    int isassign;
    char fname[LEN];
    char lname[LEN];
};

void read_file(struct seat * ps);		//从文件读取
void initialize(struct seat * ps);		//初始化结构
char get_choice(void);					//用户输入选择
void show_number(struct seat * ps);		//空位置的个数
void show_empty(struct seat * ps);		//打印所有空位置
void show_list(struct seat * ps);		//打印所有位置信息
void assign_seat(struct seat * ps);		//预订一个位置
void delete_seat(struct seat * ps);		//删除一个位置
void write_file(struct seat * ps);		//数据写入文件
char * s_gets(char * st, int n);		//输入字符串

int main(void)
{
    char ch;
    struct seat customer[MAX];
    
    initialize(customer);
    read_file(customer);
    
    //用户输入选项
    while ((ch = get_choice()) != 'f')
    {
        switch (ch)
        {
            case 'a': show_number(customer);
                      break;
            case 'b': show_empty(customer);
                      break;
            case 'c': show_list(customer);
                      break;
            case 'd': assign_seat(customer);
                      break;
            case 'e': delete_seat(customer);
                      break;
            default: printf("Program error.n");
                    break;
        }
    }
    //将数据输出至文件中
    write_file(customer);

}
    
void initialize(struct seat * ps)
{
    int i;

    for (i = 0; i < MAX; i++)
    {
        ps[i].num = i + 1;
        ps[i].isassign = 0;
        strcpy(ps[i].fname, "");
        strcpy(ps[i].lname, "");
    }
}

void read_file(struct seat * ps)
{
    FILE * fp;
    
    
    if((fp = fopen("seat.txt", "a+b")) == NULL)
    {
        fprintf(stderr, "Can't open seat.txt.n");
        exit(EXIT_FAILURE);
    }
    fread(ps, sizeof(struct seat), MAX, fp);
}

char get_choice(void)
{
    char ch;
    
    printf("To choose a function, enter its letter label:n");
    printf("a) Show number of empty seatsn");
    printf("b) Show list of empty seatsn");
    printf("c) Show alphabetical list of seatsn");
    printf("d) Assign a customer to a seat assignmentn");
    printf("e) Delete a seat assignmentn");
    printf("f) Quitn");

    while ((ch = getchar()) < 'a' || ch > 'f')
    {
        while (getchar() != 'n')
            continue;
        printf("Please input the right letter.n");
    }
    while (getchar() != 'n')
            continue;

    return ch;
}

void show_number(struct seat * ps)
{
    int i;
    int count = 0;

    for(i = 0; i < MAX; i++)
    {
        if (ps[i].isassign == 0)
            count++;
    }
    printf("The number of empty seats is %dn", count);
}

void show_empty(struct seat * ps)
{
    int i;

    printf("The list of empty seats:n");
    for (i = 0; i <	MAX; i++)
    {
        if (!ps[i].isassign)
            printf("%d ", ps[i].num);
    }
    printf("n");
}

void show_list(struct seat * ps)
{
    int i;

    printf("The list of seats:n");
    for (i = 0; i <	MAX; i++)
    {
        printf("%d %s %sn", ps[i].num, ps[i].fname, ps[i].lname);
    }
}

void assign_seat(struct seat * ps)
{
    int number;
    int ret_val;

    printf("Please input the number of seat you want to book (1 to 12):n");
    while ((ret_val = scanf("%d", &number)) != 1|| number < 1 || number > 12 ||
        ps[number - 1].isassign == 1)
    {
        if (ret_val != 1 || number < 1 || number > 12)
            printf("Sorry, please input a integer from 1 to 12.n");
        else
            printf("Sorry, the seat is assigned, please reselect:n");
        while (getchar() != 'n')
            continue;
    }
    while (getchar() != 'n')
        continue;
    printf("Now, input your firstname:n");
    s_gets(ps[number - 1].fname, LEN);
    printf("Input your lastname:n");
    s_gets(ps[number - 1].lname, LEN);
    ps[number - 1].isassign = 1;
    printf("OK.n");
}


void delete_seat(struct seat * ps)
{
    int number;

    printf("Please input the number of seat you want to delete (1 to 12):n");
    while (scanf("%d", &number) != 1 || number < 1 || number > 12 ||
        ps[number - 1].isassign == 0)
    {
        if (ps[number - 1].isassign == 1)
            printf("Sorry, the seat is empty, please reselect:n");
        else
            printf("Sorry, please input a integer from 1 to 12.n");
        while (getchar() != 'n')
            continue;
    }
    getchar();
    strcpy(ps[number - 1].fname, "");
    strcpy(ps[number - 1].lname, "");
    ps[number - 1].isassign = 0;
    printf("OK.n");
}

void write_file(struct seat * ps)
{
    FILE * fp;

    fp = fopen("seat.txt", "w+b");
    fwrite(ps, sizeof(struct seat), MAX, fp);
    fclose(fp);
}

char * s_gets(char * st, int n)
{
    char * ret_val;
    char * find;

    ret_val = fgets(st, n, stdin);
    if (ret_val)
    {
        find = strchr(st, 'n');
        if (find)
            *find = '';
        else
            while (getchar() != 'n')
                continue;
    }

    return ret_val;
}
        
  1. 巨人航空公司(编程练习 8)需要另一架飞机(容量相同),每天飞 4 班(航班 102、311、444 和 519)。把程序扩展为可以处理 4 个航班。用一 个顶层菜单提供航班选择和退出。选择一个特定航班,就会出现和编程练习 8 类似的菜单。但是该菜单要添加一个新选项:确认座位分配。而且,菜单 中的退出是返回顶层菜单。每次显示都要指明当前正在处理的航班号。另 外,座位分配显示要指明确认状态。

    #include 
    #include 
    #include 
    #define LEN 20
    #define LEN 20
    #define MAX 12
    #define MAXFL 5
    
    struct seat {
        int num;
        int isassign;
        char fname[LEN];
        char lname[LEN];
    };
    
    void read_file(struct seat * ps);		//从文件读取
    void initialize(struct seat * ps);		//初始化结构
    char get_flight(void);				//用户选择航班
    char get_choice(void);					//用户输入选择
    void show_number(struct seat * ps);		//空位置的个数
    void show_empty(struct seat * ps);		//打印所有空位置
    void show_list(struct seat * ps);		//打印所有位置信息
    void assign_seat(struct seat * ps);		//预订一个位置
    void delete_seat(struct seat * ps);		//删除一个位置
    void write_file(struct seat * ps);		//数据写入文件
    char * s_gets(char * st, int n);		//输入字符串
    void is_confirmed(void);				//确认座位分配
    
    //全局变量,值为1时表示被确认,值为0时未确认
    int isconf;
    char flight_num[MAXFL];
    
    int main(void)
    {
        char ch, flight;
        struct seat customer[MAX];
    
        initialize(customer);
        read_file(customer);
    
        //用户输入选项
        while ((flight = get_flight()) != 'q')
        {
            isconf = 0;
            while ((ch = get_choice()) != 'g')
            {
                switch (ch)
                {
                    case 'a': show_number(customer);
                              break;
                    case 'b': show_empty(customer);
                              break;
                    case 'c': show_list(customer);
                              break;
                    case 'd': assign_seat(customer);
                              break;
                    case 'e': delete_seat(customer);
                              break;
                    case 'f': is_confirmed();
                              break;
                    default: printf("Program error.n");
                            break;
                }
            }
        //将数据输出至文件中
        if (isconf)
            write_file(customer);
        }
    
    
        return 0;
    }
    
    void initialize(struct seat * ps)
    {
        int i;
    
        for (i = 0; i < MAX; i++)
        {
            ps[i].num = i + 1;
            ps[i].isassign = 0;
            strcpy(ps[i].fname, "");
            strcpy(ps[i].lname, "");
        }
    }
    
    void read_file(struct seat * ps)
    {
        FILE * fp;
    
    
        if((fp = fopen("seat.txt", "a+b")) == NULL)
        {
            fprintf(stderr, "Can't open seat.txt.n");
            exit(EXIT_FAILURE);
        }
        fread(ps, sizeof(struct seat), MAX, fp);
    }
    
    char get_flight(void)
    {
        char ch;
    
        printf("To choose a flight, enter its letter labal:n");
        printf("a). 102             b). 311n");
        printf("c). 444             d). 519n");
        printf("q). quit.n");
        while ((ch = getchar()) < 'a' || ch > 'd' && ch != 'q')
        {
            while (getchar() != 'n')
                continue;
            printf("Please input the right letter (a, b, c, d or q).n");
        }
        while (getchar() != 'n')
            continue;
        if (ch == 'a')
            strcpy(flight_num, "102");
        else if (ch == 'b')
            strcpy(flight_num, "311");
        else if (ch == 'c')
            strcpy(flight_num, "444");
        else if (ch == 'd')
            strcpy(flight_num, "519");
    
        return ch;
    }
    
    char get_choice(void)
    {
        char ch;
    
        printf("The number of the flight is %s. To choose a function, "
            "enter its letter label:n", flight_num);
        printf("a) Show number of empty seatsn");
        printf("b) Show list of empty seatsn");
        printf("c) Show alphabetical list of seatsn");
        printf("d) Assign a customer to a seat assignmentn");
        printf("e) Delete a seat assignmentn");
        printf("f) Confirmed the seat assignmentn");
        printf("g) Quitn");
    
        while ((ch = getchar()) < 'a' || ch > 'g')
        {
            while (getchar() != 'n')
                continue;
            printf("Please input the right letter.n");
        }
        while (getchar() != 'n')
                continue;
    
        return ch;
    }
    
    void show_number(struct seat * ps)
    {
        int i;
        int count = 0;
    
        for(i = 0; i < MAX; i++)
        {
            if (ps[i].isassign == 0)
                count++;
        }
        printf("The number of empty seats is %dn", count);
    }
    
    void show_empty(struct seat * ps)
    {
        int i;
    
        printf("The list of empty seats in %s flight:n", flight_num);
        for (i = 0; i <	MAX; i++)
        {
            if (!ps[i].isassign)
                printf("%d ", ps[i].num);
        }
        printf("n");
    }
    
    void show_list(struct seat * ps)
    {
        int i;
    
        printf("The list of seats in %s flight:n", flight_num);
        for (i = 0; i <	MAX; i++)
        {
            printf("%d %s %sn", ps[i].num, ps[i].fname, ps[i].lname);
        }
        printf("The seat assignment is not confirmed.n");
    }
    
    void assign_seat(struct seat * ps)
    {
        int number;
        int ret_val;
    
        printf("Please input the number of seat you want to book (1 to 12) "
            "in %s flight:n", flight_num);
        while ((ret_val = scanf("%d", &number)) != 1|| number < 1 || number > 12 ||
            ps[number - 1].isassign == 1)
        {
            if (ret_val != 1 || number < 1 || number > 12)
                printf("Sorry, please input a integer from 1 to 12.n");
            else
                printf("Sorry, the seat is assigned, please reselect:n");
            while (getchar() != 'n')
                continue;
        }
        while (getchar() != 'n')
            continue;
        printf("Now, input your firstname:n");
        s_gets(ps[number - 1].fname, LEN);
        printf("Input your lastname:n");
        s_gets(ps[number - 1].lname, LEN);
        ps[number - 1].isassign = 1;
        printf("OK.n");
    }
    
    
    void delete_seat(struct seat * ps)
    {
        int number;
    
        printf("Please input the number of seat you want to delete (1 to 12) "
            "in %s flight:n", flight_num);
        while (scanf("%d", &number) != 1 || number < 1 || number > 12 ||
            ps[number - 1].isassign == 0)
        {
            if (ps[number - 1].isassign == 1)
                printf("Sorry, the seat is empty, please reselect:n");
            else
                printf("Sorry, please input a integer from 1 to 12.n");
            while (getchar() != 'n')
                continue;
        }
        getchar();
        strcpy(ps[number - 1].fname, "");
        strcpy(ps[number - 1].lname, "");
        ps[number - 1].isassign = 0;
        printf("OK.n");
    }
    
    void is_confirmed(void)
    {
        isconf = 1;
        printf("The seat assignment is confirmed.n");
    }
    
    void write_file(struct seat * ps)
    {
        FILE * fp;
    
        fp = fopen("seat.txt", "w+b");
        fwrite(ps, sizeof(struct seat), MAX, fp);
        fclose(fp);
    }
    
    char * s_gets(char * st, int n)
    {
        char * ret_val;
        char * find;
    
        ret_val = fgets(st, n, stdin);
        if (ret_val)
        {
            find = strchr(st, 'n');
            if (find)
                *find = '';
            else
                while (getchar() != 'n')
                    continue;
        }
    
        return ret_val;
    }
    
    
  2. 编写一个程序,通过一个函数指针数组实现菜单。例如,选择菜单 中的 a,将激活由该数组第 1 个元素指向的函数。

    #include 
    #include 
    #include 
    #include 
    #define LEN 81
    #define SIZE 4
    
    char * s_gets(char * st, int n);
    char get_choice(void);
    void ToUpper(char * st);
    void ToLower(char * st);
    void Transpos(char * st);
    void Dummy(char * st);
    
    int main(void)
    {
        char st[LEN];
        char copy[LEN];
        char ch;
        //函数指针数组
        void(*fp[SIZE])(char *) = {ToUpper, ToLower, Transpos, Dummy};
        int index;
    
        puts("Enter a string (empty line to quit):");
        while (s_gets(st, LEN) != NULL && st[0] != '')
        {
            while ((ch = get_choice()) != 'q')
            {
                switch (ch)
                {
                case 'a': index = 0; break;
                case 'b': index = 1; break;
                case 'c': index = 2; break;
                case 'd': index = 3; break;
                default : printf("Program error.n");  break;
                }
                strcpy(copy, st);
                (*(fp[index]))(copy);
                puts(copy);
            }
            printf("Enter a string (empty line to quit):n");
        }
        puts("Bye.");
    
        return 0;
    }
    
    char get_choice(void)
    {
        char ch;
    
        printf("To choose a function, enter its letter labal:n");
        printf("a). upper             b). lowern");
        printf("c). transposed        d). originaln");
        printf("q). quit.n");
        while ((ch = getchar()) < 'a' || ch > 'd' && ch != 'q')
        {
            while (getchar() != 'n')
                continue;
            printf("Please input the right letter (a, b, c, d or q).n");
        }
        while (getchar() != 'n')
            continue;
    
        return ch;
    }
    
    void ToUpper(char * st)
    {
        while (*st)
        {
            *st = toupper(*st);
            st++;
        }
    }
    
    void ToLower(char * st)
    {
        while (*st)
        {
            *st = tolower(*st);
            st++;
        }
    }
    
    void Transpos(char * st)
    {
        while (*st)
        {
            if (islower(*st))
                *st = toupper(*st);
            else if (isupper(*st))
                *st = tolower(*st);
            st++;
        }
    }
    
    void Dummy(char * st)
    {
    
    }
    
    char * s_gets(char * st, int n)
    {
        char * ret_val;
        char * find;
    
        ret_val = fgets(st, n, stdin);
        if (ret_val)
        {
            find = strchr(st, 'n');
            if (find)
                *find = '';
            else
                while (getchar() != 'n')
                    continue;
        }
    
        return ret_val;
    }
    
  3. 编写一个名为 transform()的函数,接受 4 个参数:内含 double 类型 数据的源数组名、内含 double 类型数据的目标数组名、一个表示数组元素 个数的 int 类型参数、函数名(或等价的函数指针)。transform()函数应把指 定函数应用于源数组中的每个元素,并把返回值储存在目标数组中。例如:

transform(source, target, 100, sin); 

​ 该声明会把 target[0]设置为 sin(source[0]),等等,共有 100 个元素。在 一个程序中调用 transform()4 次,以测试该函数。分别使用 math.h 函数库中 的两个函数以及自定义的两个函数作为参数。

#include 
#include 
#define PSIZE 4
#define SIZE 100

void transform(double [], double [], int, double(*)(double));
double oppsite_val(double);
double double_val(double);

int main(void)
{
    int i, j;
    double source[SIZE], target[SIZE];
    double(*p[PSIZE])(double) = {sin, sqrt, oppsite_val, double_val};
    
    printf("The source array:n");
    for (i = 0; i 
        source[i] = i;
        printf("%7g ", source[i]);
        if (i % 10 == 9)
            printf("n");
    }
    printf("n");
    for (i = 0; i < PSIZE; i++)
    {
        printf("The source array %d:n", i + 1);
        transform(source, target, SIZE, p[i]);
        for (j = 0; j < SIZE; j++)
        {
            printf("%7.2f ", target[j]);
            if (j % 10 == 9)
            printf("n");
        }
        printf("n");
    }

    return 0;
}

void transform(double source[], double target[], int size,
    double(*pf)(double num))
{
    int i;

    for (i = 0; i 
        target[i] = (*pf)(source[i]);
    }
}


double oppsite_val(double num)
{
    return (-1 * num);
}

double double_val(double num)
{
    return (2 * num);
}
第十五章 位操作

1.编写一个函数,把二进制字符串转换为一个数值。例如,有下面的语 句: char * pbin = “01001001”; 那么把pbin作为参数传递给该函数后,它应该返回一个int类型的值25。

#include 
#include 
int btoi(char * st);
int main(void)
{
    char * pbin = "01001001";
    
    printf("The decimal number: %d.n", btoi(pbin));
    
    return 0;
}

int btoi(char * st)
{
    int num = 0;

    while (*st)
        num = (num << 1) + (*st++ - '0');

    return num;
}

2.编写一个程序,通过命令行参数读取两个二进制字符串,对这两个二 进制数使用~运算符、&运算符、|运算符和^运算符,并以二进制字符串形 式打印结果(如果无法使用命令行环境,可以通过交互式让程序读取字符 串)。

#include 
#include 
#include 
#define SIZE 5

int btoi(char * st);				//二进制字符串转化为整数的函数
char * itob(char * st, int n);		//整数转化为二进制字符串的函数
void show_bstr(const char * st);	//4位一组显示二进制字符串

int main(int argc, char * argv[])
{
    int num1, num2;
    char bin_st[CHAR_BIT * sizeof(int) + 1];

    if (argc != 3)
    {
        fprintf(stderr, "The number of arguments is wrong.n");
        exit(EXIT_FAILURE);
    }
    num1 = btoi(argv[1]);
    num2 = btoi(argv[2]);
    show_bstr(itob(bin_st, ~num1));
    show_bstr(itob(bin_st, ~num2));
    show_bstr(itob(bin_st, num1 & num2));
    show_bstr(itob(bin_st, num1 | num2));
    show_bstr(itob(bin_st, num1 ^ num2));

    return 0;
}

int btoi(char * st)
{
    int num = 0;

    while (*st)
        num = (num << 1) + (*st++ - '0');

    return num;
}

char * itob(char * st, int n)
{
    int i;
    const static int size = CHAR_BIT * sizeof(int);
    
    for (i = size - 1; i >= 0; i--, n >>= 1)
        st[i] = (01 & n) + '0';
    st[size] = '';

    return st;
}

void show_bstr(const char * st)
{
    int i = 0;

    while (st[i])
    {
        putchar(st[i]);
        if (++i % 4 == 0 && st[i])
            putchar(' ');
    }
    printf("n");
}

3.编写一个函数,接受一个 int 类型的参数,并返回该参数中打开位的 数量。在一个程序中测试该函数。

#include 
#include 
#define MASK 01

int count_bit_on(int num);

int main(void)
{
    int num;

    printf("Please input a integer:n");
    scanf("%d", &num);
    printf("The number of bit on is: %dn",
        count_bit_on(num));

    return 0;
}

int count_bit_on(int num)
{
    int i;
    int count = 0;
    int size = CHAR_BIT * sizeof(int);
    
    for (i = 0; i < size; i++)
    {
        if (num & MASK)
        {
            count++;
        }
        num >>= 1;
    }

    return count;
}

4.编写一个程序,接受两个int类型的参数:一个是值;一个是位的位 置。如果指定位的位置为1,该函数返回1;否则返回0。在一个程序中测试 该函数。

#include 
#define MASK 01
int check_bit(int num, int bit);
int main(void)
{
    int num, bit;

    printf("Please input a integer:n");
    scanf("%d", &num);
    printf("Now input the position:n");
    scanf("%d", &bit);
    printf("The number in your position is: %d.n",
        check_bit(num, bit));
    
    return 0;
}

int check_bit(int num, int bit)
{
    int i;
    
    for (i = 0; i < bit; i++)
    {
        num >>= 1;
    }
    
    return num & MASK;
}

5.编写一个函数,把一个 unsigned int 类型值中的所有位向左旋转指定数 量的位。例如,rotate_l(x, 4)把x中所有位向左移动4个位置,而且从最左端 移出的位会重新出现在右端。也就是说,把高阶位移出的位放入低阶位。在 一个程序中测试该函数。

#include 
#include 
#define MASK 01
#define SIZE CHAR_BIT * sizeof(unsigned int)

char * itob(char * st, unsigned int n);
void show_bstr(const char * st);
unsigned int move_left(unsigned int, int);
int main(void)
{
    unsigned int num;
    int bit;
    char st[SIZE + 1];

    printf("Please input a integer and the number of bits to move:n");
    scanf("%u%d", &num, &bit);
    printf("The original binary string:n");
    show_bstr(itob(st, num));
    //把所有位向左移动
    num = move_left(num, bit);
    printf("The present binary string:n");
    show_bstr(itob(st, num));
}

unsigned int move_left(unsigned int n, int bit)
{
    int i;
    
    for (i = 0; i < bit; i++)
    {
        n = (n << 1) + ((n >> (SIZE - 1)) & MASK);
    }

    return n;
}

char * itob(char * st, unsigned int n)
{
    int i;
    
    for (i = SIZE - 1; i >= 0; i--, n >>= 1)
        st[i] = (01 & n) + '0';
    st[SIZE] = '';

    return st;
}

void show_bstr(const char * st)
{
    int i = 0;

    while (st[i])
    {
        putchar(st[i]);
        if (++i % 4 == 0 && st[i])
            putchar(' ');
    }
    printf("n");
}
    

6.设计一个位字段结构以储存下面的信息。

字体ID:0~255之间的一个数; 

字体大小:0~127之间的一个数; 

对齐:0~2之间的一个数,表示左对齐、居中、右对齐;  

加粗:开(1)或闭(0); 

斜体:开(1)或闭(0);

在一个程序中使用该结构来打印字体参数,并使用循环菜单来让用户改 变参数。例如,该程序的一个运行示例如下:

该程序要使用按位与运算符(&)和合适的掩码来把字体ID和字体大小 信息转换到指定的范围内。

#include 
#include 

struct word {
    unsigned int font: 8;
    unsigned int size: 7;
    unsigned int alignment: 2;
    unsigned int bold: 1;
    unsigned int italic: 1;
};

const char * align[3] = {"left", "center", "right"};
const char * open[2] = {"off", "on"};

char get_choice(void);
char get_select(void);
void print(struct word *);

int main(void)
{
    struct word type = {1, 12, 0, 0, 0};
    char choice;
    char ch;
    int num;

    print(&type);
    while ((choice = get_choice()) != 'q')
    {
        switch (choice)
        {
        case 'f': printf("Enter font ID (0 - 256): ");
                  scanf("%u", &num);
                  getchar();
                  type.font = num;
                  break;
        case 's': printf("Enter font ID (0 - 127): ");
                  scanf("%u", &num);
                  getchar();
                  type.size = num;
                  break;
        case 'a': printf("Select alignment:n");
                  printf("l)left   c)center   r)rightn");
                  if ((ch = get_select()) == 'l')
                      type.alignment = 0;
                  else if (ch == 'c')
                      type.alignment = 1;
                  else
                      type.alignment = 2;
                  break;
        case 'b': type.bold = !type.bold;
                  break;
        case 'i': type.italic = !type.italic;
                  break;
        default : break;
        }
        print(&type);
    }
    printf("Bye.n");

    return 0;
}

char get_choice(void)
{
    char ch;
    
    printf("f)change fontts)change sizeta)change alignmentn");
    printf("b)toggle boldti)toggle italicnq)quitn");

    while (strchr("fsabiq", ch = getchar()) == NULL)
    {
        while (getchar() != 'n')
            continue;
        printf("Please input the right letter.n");
    }
    while (getchar() != 'n')
        continue;
    
    return ch;
}

char get_select(void)
{
    char ch;

    while (strchr("lcr", ch = getchar()) == NULL)
    {
        while (getchar() != 'n')
            continue;
        printf("Please input the right letter.n");
    }
    while (getchar() != 'n')
        continue;
    
    return ch;
}

void print(struct word * pst)
{
    printf("n ID  SIZE  ALIGNMENT   B    In");
    printf("%3u", pst->font);
    printf("%5u", pst->size);
    printf("%10s", align[pst->alignment]);
    printf("%7s", open[pst->bold]);
    printf("%5snn", open[pst->italic]);
}

7.编写一个与编程练习 6 功能相同的程序,使用 unsigned long 类型的变 量储存字体信息,并且使用按位运算符而不是位成员来管理这些信息。

#include 
#include 

#define ID_MASK 0xff
//括号缺失会出错
#define SIZE_MASK (0x7f << 8)
#define ALIGN_MASK (0x3 << 15)

#define CENTER (0x1 << 15)
#define RIGHt (0x2 << 15)
#define BOLD (0x1 << 17)
#define ITALIC (0x1 << 18)

const char * align[3] = {"left", "center", "right"};
const char * open[2] = {"off", "on"};

char get_choice(void);
char get_select(void);
void print(unsigned long);

int main(void)
{
    unsigned long type = 0;
    char choice;
    char ch;
    int num;

    print(type);
    while ((choice = get_choice()) != 'q')
    {
        switch (choice)
        {
        case 'f': printf("Enter font ID (0 - 256): ");
                  scanf("%lu", &num);
                  getchar();
                  type &= ~ID_MASK;		//把表示字体ID的位清空
                  type |= num;			//重置字体ID
                  break;
        case 's': printf("Enter font ID (0 - 127): ");
                  scanf("%lu", &num);
                  getchar();
                  type &= ~SIZE_MASK;
                  type |= (num << 8);
                  break;
        case 'a': type &= ~ALIGN_MASK;
                  printf("Select alignment:n");
                  printf("l)left   c)center   r)rightn");
                  if ((ch = get_select()) == 'c')
                      type |= CENTER;
                  else if (ch == 'r')
                      type |= RIGHT;
                      break;
        case 'b': type ^= BOLD;
                  break;
        case 'i': type ^= ITALIC;
                  break;
        default : break;
        }
        print(type);
    }
    printf("Bye.n");

    return 0;
}

char get_choice(void)
{
    char ch;
    
    printf("f)change fontts)change sizeta)change alignmentn");
    printf("b)toggle boldti)toggle italicnq)quitn");

    while (strchr("fsabiq", ch = getchar()) == NULL)
    {
        while (getchar() != 'n')
            continue;
        printf("Please input the right letter.n");
    }
    while (getchar() != 'n')
        continue;
    
    return ch;
}

char get_select(void)
{
    char ch;

    while (strchr("lcr", ch = getchar()) == NULL)
    {
        while (getchar() != 'n')
            continue;
        printf("Please input the right letter.n");
    }
    while (getchar() != 'n')
        continue;
    
    return ch;
}

void print(unsigned long num)
{
    printf("n ID  SIZE  ALIGNMENT   B    In");
    printf("%3u", num & ID_MASK);
    printf("%5u", (num & SIZE_MASK) >> 8);
    printf("%10s", align[(num & ALIGN_MASK) >> 15]);
    printf("%7s", open[(num & BOLD) >> 17]);
    printf("%5snn", open[(num & ITALIC) >> 18]);
}
第十六章 C预处理和C库

1.开发一个包含你需要的预处理器定义的头文件。

//之前程序的例子

#include 
#include 
#include 
#define SIZE 100
void print_ar(int ar[], int n);			//打印数组元素的函数
int main(void)
{
    int i, j, temp;
    int digit[SIZE];
    srand((unsigned int)time(0));
    for (i = 0; i < SIZE; i++)
    {
        digit[i] = rand() % 10 + 1;
    }
    printf("The original numbers:n");
    print_ar(digit, SIZE);
    for (j = 0; j < SIZE - 1; j++)
        for (i = j + 1; i < SIZE; i++)
            if (digit[j] < digit[i])
            {
                temp = digit[i];
                digit[i] = digit[j];
                digit[j] = temp;
            }
    printf("nThe numbers in reverse order:n");
    print_ar(digit, SIZE);
}

void print_ar(int ar[], int n)
{
    int i;
    for (i = 0; i < n; i++)
    {
        printf("%3d", ar[i]);
        if (i % 10 == 9)
            printf("n");
    }
}

2.两数的调和平均数这样计算:先得到两数的倒数,然后计算两个倒数 的平均值,最后取计算结果的倒数。使用#define指令定义一个宏“函数”,执 行该运算。编写一个简单的程序测试该宏。

#include 
#define HORMONIC(x, y) (1 / (1 / (x) + 1 / (y)))

int main(void)
{
    double num1, num2;

    printf("Please input two number ('q' to quit): ");
    while (scanf("%lf%lf", &num1, &num2) == 2)
    {
        printf("The hormonic average: %.2fn", HORMONIC(num1, num2));
        printf("Please input two number ('q' to quit): ");
    }
    
    return 0;
}

3.极坐标用向量的模(即向量的长度)和向量相对x轴逆时针旋转的角 度来描述该向量。直角坐标用向量的x轴和y轴的坐标来描述该向量(见图 16.3)。编写一个程序,读取向量的模和角度(单位:度),然后显示x轴 和y轴的坐标。相关方程如下:

x = rcos A y = rsin A

需要一个函数来完成转换,该函数接受一个包含极坐标的结构,并返回 一个包含直角坐标的结构(或返回指向该结构的指针)。

#include 
#include 

#define DEG_TO_RED ((4 * atan(1)) / 180)

typedef struct polar_v {
    double magnitude;
    double angle;
} Polar_V;

typedef struct rect_v {
    double x;
    double y;
} Rect_V;

Rect_V polar_to_rect(Polar_V pv);

int main(void)
{
    Polar_V input;
    Rect_V result;

    puts("Enter magnitude and angle; enter q to quit:");
    while (scanf("%lf%lf", &input.magnitude, &input.angle) == 2)
    {
        result = polar_to_rect(input);
        printf("x = %.2f, y = %.2fn", result.x, result.y);
        puts("Next input (q to quit):");
    }
    puts("Bye.");

    return 0;
}

Rect_V polar_to_rect(Polar_V pv)
{
    Rect_V rv;
    rv.x = pv.magnitude * cos(pv.angle * DEG_TO_RED);
    rv.y = pv.magnitude * sin(pv.angle * DEG_TO_RED);

    return rv;
}

4.ANSI库这样描述clock()函数的特性:

#include
clock_t clock (void);

这里,clock_t是定义在time.h中的类型。该函数返回处理器时间,其单 位取决于实现(如果处理器时间不可用或无法表示,该函数将返回-1)。然 而,CLOCKS_PER_SEC(也定义在time.h中)是每秒处理器时间单位的数 量。因此,两个 clock()返回值的差值除以 CLOCKS_PER_SEC得到两次调用 之间经过的秒数。在进行除法运算之前,把值的类型强制转换成double类 型,可以将时间精确到小数点以后。编写一个函数,接受一个double类型的 参数表示时间延迟数,然后在这段时间运行一个循环。编写一个简单的程序 测试该函数。

 #include 
#include 

void delay(double time);

int main(void)
{
    double time;

    printf("Please input the time (in seconds) to delay"
        " (q to quit):n");
    while (scanf("%lf", &time) == 1)
    {
        delay(time);
        printf("Time is out.n");
        printf("Your next input (q to quit):n");
    }

    return 0;
}

void delay(double time)
{
    double t;

    t = (double) clock() / CLOCKS_PER_SEC;
    while ((double) clock() / CLOCKS_PER_SEC - t < time)
        ;
}

5.编写一个函数接受这些参数:内含int类型元素的数组名、数组的大小 和一个代表选取次数的值。该函数从数组中随机选择指定数量的元素,并打 印它们。每个元素只能选择一次(模拟抽奖数字或挑选陪审团成员)。另 外,如果你的实现有time()(第12章讨论过)或类似的函数,可在srand()中 使用这个函数的输出来初始化随机数生成器rand()。编写一个简单的程序测 试该函数。

#include 
#include 
#include 
#include 
#define SIZE 10
void random(const int ar[], int size, int n);

int main(void)
{
    int ar[SIZE] = {1, 2, 3, 6, 7, 9, 10, 13, 26, 17};
    int i;
    int num;

    srand((unsigned int) time(NULL));
    printf("The original array:n");
    for (i = 0; i < SIZE; i++)
        printf("%d ", ar[i]);
    printf("nPlease input the number of integers (no more than 10)n");
    printf("you want to take (q to quit):n");
    while (scanf("%d", &num) == 1)
    {
        random(ar, SIZE, num);
        printf("Your next input (q to quit):n");
    }
    puts("Bye.");

    return 0;
}

void random(const int ar[], int size, int n)
{
    int i;
    int count;
    int index;
    int acpy[SIZE];

    //创建一个数组副本,避免修改原始数组
    memcpy(acpy, ar, SIZE * sizeof(int));
    if (n > size)
        printf("The number is too big.n");
    else
    {
        for (count = 0; count < n; count++)
        {
            index = rand() % size;
            printf("%d ", acpy[index]);
            for (i = index; i < size - 1; i++)
            {
                acpy[i] = acpy[i + 1];
            }
            size--;
        }
        printf("n");
    }
}

6.修改程序清单16.17,使用struct names元素(在程序清单16.17后面的 讨论中定义过),而不是double类型的数组。使用较少的元素,并用选定的 名字显式初始化数组。

#include 
#include 
#include 
#define SIZE 40
#define NUM 5

struct names {
    char first[SIZE];
    char last[SIZE];
};

int comp(const void * p1, const void * p2);

int main(void)
{
    int i;

    struct names staff[NUM] = {
        {"zha", "yujie"},
        {"xia", "yufeng"},
        {"bu", "jianqiang"},
        {"xu", "feifan"},
        {"ding","bing"}
    };

    qsort(staff, NUM, sizeof(struct names), comp);
    for (i = 0; i < NUM; i++)
    {
        printf("%s %sn", staff[i].first, staff[i].last);
    }

    return 0;
}

int comp(const void * p1, const void * p2)
{
    const struct names *ps1 = (const struct names *) p1;
    const struct names *ps2 = (const struct names *) p2;
    int res;
    res = strcmp(ps1->first, ps2->first);
    if (res)
        return res;
    else
        return strcmp(ps1->last, ps2->last);
}





7.下面是使用变参函数的一个程序段:

#include 
#include 
#include 
void show_array(const double ar[], int n);
double * new_d_array(int n, ...);
int main()
{
	double * p1;
    double * p2;
	p1 = new_d_array(5,1.2,2.3,3.4,4.5,5.6);
	p2 = new_d_array(4, 100.0, 20.00, 8.08, -1890.0);
	show_array(p1, 5);
	show_array(p2, 4);
	free(p1);
	free(p2);
	return 0;
}

new_d_array()函数接受一个int类型的参数和double类型的参数。该函数 返回一个指针,指向由malloc()分配的内存块。int类型的参数指定了动态数 组中的元素个数,double类型的值用于初始化元素(第1个值赋给第1个元 素,以此类推)。编写show_array()和new_d_array()函数的代码,完成这个 程序。

#include 
#include 
#include 
#define SIZE 40

void show_array(const double ar[], int n);
double * new_d_array(int n, ...);

int main()
{
    double * p1;
    double * p2;
    p1 = new_d_array(5, 1.2, 2.3, 3.4, 4.5, 5.6);
    p2 = new_d_array(4, 100.0, 20.00, 8.08, -1890.0);
    show_array(p1, 5);
    show_array(p2, 4);
    free(p1);
    free(p2);
    
    return 0;
}

void show_array(const double ar[], int n)
{
    int i;

    for (i = 0; i < n; i++)
        printf("%g ", ar[i]);
    printf("n");
}

double * new_d_array(int n, ...)
{
    int i;
    double * p = (double *) malloc(n * sizeof(double));

    va_list ap;
    va_start(ap, n);
    for (i = 0; i < n; i++)
        *(p + i) = va_arg(ap, double);
    va_end(ap);

    return p;
}
第十七章 高级数据表示
  1. 修改程序清单17.2,让该程序既能正序也能逆序显示电影列表。一种 方法是修改链表的定义,可以双向遍历链表。另一种方法是用递归。

    #include 
    #include 
    #include 
    #define TSIZE 45
    
    typedef struct film {
        char title[TSIZE];
        int rating;
        struct film * prev;
        struct film * next;
    } Node;
    
    char * s_gets(char * st, int n);
    
    int main(void)
    {
        Node * head = NULL;
        Node * pre = NULL;
        Node * end;
        Node * current;
        char input[TSIZE];
    
        //储存信息
        puts("Enter first movie title:");
        while (s_gets(input, TSIZE) != NULL && input[0] != '')
        {
            current = (Node *) malloc(sizeof(Node));
            if (head == NULL)
                head = current;
            else
            {
                pre->next = current;
            }
            current->prev = pre;
            current->next = NULL;
            strcpy(current->title, input);
            puts("Enter your rating <0-10>:");
            scanf("%d", ¤t->rating);
            while (getchar() != 'n')
                continue;
            puts("Enter next movie title (empty to stop):");
            pre = current;
        }
        end = pre;
    
        if (head == NULL)
        {
            fprintf(stderr, "No data entered.n");
            exit(1);
        }
        else
            printf("Here is the movie list in positive order:n");
    
        //正序显示电影列表
        current = head;
        while (current != NULL)
        {
            printf("Movie: %s  Rating: %dn", current->title,
                current->rating);
            current = current->next;
        }
    
        //逆序显示电影列表
        printf("Here is the movie list in reverse order:n");
        current = end;
        while (current != NULL)
        {
            printf("Movie: %s  Rating: %dn", current->title,
                current->rating);
            current = current->prev;
        }
    
        return 0;
    }
    
    char * s_gets(char * st, int n)
    {
        char * ret_val;
        char * find;
    
        ret_val = fgets(st, n, stdin);
        if (ret_val)
        {
            find = strchr(st, 'n');
            if (find)
                *find = '';
            else
                while(getchar() != 'n')
                    continue;
        }
    
        return ret_val;
    }
    
    
  2. 假设list.h(程序清单17.3)使用下面的list定义: typedef struct list { Node * head; } List; 重写 list.c(程序清单 17.5)中的函数以适应新的定义,并通过 films.c(程序清单 17.4)测试最终的代码。

    //2.c
    #include 
    #include 
    #include 
    #include "movie.h"
    #include "movie.c"
    
    void show_list(Item item);
    char * s_gets(char * st, int n);
    
    int main(void)
    {
        List movies;
        Item temp;
    
        //初始化
        InitializeList(&movies);
        if (ListIsFull(&movies))
        {
            fprintf(stderr, "No memory available.n");
            exit(1);
        }
    
        //储存数据
        printf("Please input the title of movie:n");
        while (s_gets(temp.titile, TSIZE) != NULL &&
            temp.titile[0] != '')
        {
            printf("Enter your rating <0-10>:n");
            scanf("%d", &temp.rating);
            while (getchar() != 'n')
                continue;
            if (AddItem(&movies, temp) == 0)
            {
                fprintf(stderr, "Allocting memory error.n");
                break;
            }
            if (ListIsFull(&movies))
            {
                fprintf(stderr, "Sorry, the list is full.n");
                break;
            }
            printf("Input the next title (Empty line to stop):n");
        }
    
        //显示数据
        if (ListIsEmpty(&movies))
        {
            fprintf(stderr, "Sorry, the list is empty.n");
            return 0;
        }
        printf("Here is the movie list:n");
        Traverse(&movies, show_list);
        printf("You entered %u movies.n", ListItemCount(&movies));
    
        //清空数据
        DeleteAll(&movies);
    
        printf("Bye.n");
    
        return 0;
    }
    
    void show_list(Item item)
    {
        printf("Movie: %s   Rating: %dn", item.titile, item.rating);
    }
    
    char * s_gets(char * st, int n)
    {
        char * ret_val;
        char * find;
    
        ret_val = fgets(st, n, stdin);
        if(ret_val)
        {
            find = strchr(st, 'n');
            if (find)
                *find = '';
            else
                while (getchar() != 'n')
                    continue;
        }
    
        return ret_val;
    }
    
    //movie.c
    #include 
    #include 
    #include "movie.h"
    
    //初始化链表为空
    void InitializeList(List * plist)
    {
        plist->head = NULL;
        plist->end = NULL;
    }
    
    //链表为空,返回1
    int ListIsEmpty(const List * plist)
    {
        if (plist->head == NULL)
            return 1;
        else
            return 0;
    }
    
    //链表为满,返回1
    int ListIsFull(const List * plist)
    {
        Node * pt;
        int full;
    
        pt = (Node *)malloc(sizeof(Node));
        if (pt == NULL)
            full = 1;
        else
            full = 0;
        free(pt);
    
        return full;
    }
    
    //为链表添加项,成功返回1
    int AddItem(List * plist, Item item)
    {
        Node * pnew;
    
        pnew = (Node *)malloc(sizeof(Node));
        if (pnew == NULL)
            return 0;
    
        pnew->next = NULL;
        pnew->item = item;
    
        if (plist->head == NULL)
            plist->head = pnew;
        else
            plist->end->next = pnew;
        plist->end = pnew;
    
        return 1;
    }
    
    //确定链表的项数
    unsigned int ListItemCount(List * plist)
    {
        unsigned int count = 0;
        Node * pnode = plist->head;
    
        while (pnode != NULL)
        {
            pnode = pnode->next;
            count++;
        }
    
        return count;
    }
    
    //遍历链表
    void Traverse(const List * plist, void (*pfun)(Item item))
    {
        Node * pnode = plist->head;
    
        while (pnode != NULL)
        {
            (*pfun)(pnode->item);
            pnode = pnode->next;
        }
    }
    
    //清空链表
    void DeleteAll(List * plist)
    {
        Node * pnode;
    
        while (plist->head != NULL)
        {
            pnode = plist->head;
            plist->head = plist->head->next;
            free(pnode);
        }
    }
    
    
    //movie.h
    #ifndef MOVIE_H_
    #define MOVIE_H_
    
    #define TSIZE 45
    
    typedef struct film {
    	char titile[TSIZE];
    	int rating;
    } Item;
    
    typedef struct node {
    	Item item;
    	struct node * next;
    } Node;
    
    typedef struct list {
    	Node * head;
    	Node * end;
    } List;
    
    //初始化链表为空
    void InitializeList(List * plist);
    
    //链表为空,返回1
    int ListIsEmpty(const List * plist);
    
    //链表为满,返回1
    int ListIsFull(const List * plist);
    
    //为链表添加项,成功返回1
    int AddItem(List * plist, Item item);
    
    //确定链表的项数
    unsigned int ListItemCount(List * plist);
    
    //遍历链表
    void Traverse(const List * plist, void (*pfun)(Item item));
    
    //清空链表
    void DeleteAll(List * plist);
    
    #endif
    
    
    
  3. 假设list.h(程序清单17.3)使用下面的list定义: #define MAXSIZE 100 typedef struct list { Item entries[MAXSIZE]; } List; 重写 list.c(程序清单 17.5)中的函数以适应新的定义,并通过 films.c(程序清单 17.4)测试最终的代码。

    //3.c
    #include 
    #include 
    #include 
    #include "movie2.h"
    #include "movie2.c"
    
    void show_list(Item item);
    char * s_gets(char * st, int n);
    
    int main(void)
    {
        List movies;
        Item temp;
    
        //初始化
        InitializeList(&movies);
        if (ListIsFull(&movies))
        {
            fprintf(stderr, "No memory available.n");
            exit(1);
        }
    
        //储存数据
        printf("Please input the title of movie:n");
        while (s_gets(temp.titile, TSIZE) != NULL &&
            temp.titile[0] != '')
        {
            printf("Enter your rating <0-10>:n");
            scanf("%d", &temp.rating);
            while (getchar() != 'n')
                continue;
            if (AddItem(&movies, temp) == 0)
            {
                fprintf(stderr, "Allocting memory error.n");
                break;
            }
            if (ListIsFull(&movies))
            {
                fprintf(stderr, "Sorry, the list is full.n");
                break;
            }
            printf("Input the next title (Empty line to stop):n");
        }
    
        //显示数据
        if (ListIsEmpty(&movies))
        {
            fprintf(stderr, "Sorry, the list is empty.n");
            return 0;
        }
        printf("Here is the movie list:n");
        Traverse(&movies, show_list);
        printf("You entered %u movies.n", ListItemCount(&movies));
    
        //清空数据
        DeleteAll(&movies);
    
        printf("Bye.n");
    
        return 0;
    }
    
    void show_list(Item item)
    {
        printf("Movie: %s   Rating: %dn", item.titile, item.rating);
    }
    
    char * s_gets(char * st, int n)
    {
        char * ret_val;
        char * find;
    
        ret_val = fgets(st, n, stdin);
        if(ret_val)
        {
            find = strchr(st, 'n');
            if (find)
                *find = '';
            else
                while (getchar() != 'n')
                    continue;
        }
    
        return ret_val;
    }
    //movie.h
    #ifndef MOVIE_H_
    #define MOVIE_H_
    
    #define TSIZE 45
    #define MAXSIZE 5
    
    typedef struct film {
    	char titile[TSIZE];
    	int rating;
    } Item;
    
    typedef struct list {
    	Item entries[MAXSIZE];
    	int items;
    } List;
    
    //初始化链表为空
    void InitializeList(List * plist);
    
    //链表为空,返回1
    int ListIsEmpty(const List * plist);
    
    //链表为满,返回1
    int ListIsFull(const List * plist);
    
    //为链表添加项,成功返回1
    int AddItem(List * plist, Item item);
    
    //确定链表的项数
    unsigned int ListItemCount(List * plist);
    
    //遍历链表
    void Traverse(const List * plist, void (*pfun)(Item item));
    
    //清空链表
    void DeleteAll(List * plist);
    
    #endif
    
    
    //movie.c
    #include 
    #include 
    #include 
    #include "movie2.h"
    
    //初始化链表为空
    void InitializeList(List * plist)
    {
        int i;
    
        for (i = 0; i < MAXSIZE; i++)
        {
            strcpy((plist->entries[i]).titile, "");
            (plist->entries[i]).rating = 0;
            plist->items = 0;
        }
    }
    
    //链表为空,返回1
    int ListIsEmpty(const List * plist)
    {
        if (plist->items == 0)
            return 1;
        else
            return 0;
    }
    
    //链表为满,返回1
    int ListIsFull(const List * plist)
    {
        if (plist->items == MAXSIZE)
            return 1;
        else
            return 0;
    }
    
    //为链表添加项,成功返回1
    int AddItem(List * plist, Item item)
    {
        if (plist->items == MAXSIZE)
        {
            fprintf(stderr, "The list is full.n");
            return 0;
        }
    
        plist->entries[plist->items] = item;
        (plist->items)++;
    
        return 1;
    }
    
    //确定链表的项数
    unsigned int ListItemCount(List * plist)
    {
        return plist->items;
    }
    
    //遍历链表
    void Traverse(const List * plist, void (*pfun)(Item item))
    {
        int i;
    
        for (i = 0; i < plist->items; i++)
        {
            (*pfun)(plist->entries[i]);
        }
    }
    
    //清空链表
    void DeleteAll(List * plist)
    {
        int i;
    
        for (i = 0; i < plist->items; i++)
        {
            strcpy((plist->entries[i]).titile, "");
            (plist->entries[i]).rating = 0;
            plist->items = 0;
        }
    
    }
    
    
    
  4. 重写mall.c(程序清单17.7),用两个队列模拟两个摊位。

    //mall.c
    #include 
    #include 
    #include 
    #include "queue.h"
    #include "queue.c"
    #define MIN_PER_HOUR 60
    
    int newcustomer(double x);
    Item customertime(long when);
    
    Queue line1;
    Queue line2;
    Item temp;
    
    int hours;					//模拟的小时数
    int cust_per_hour;			//平均每小时来的顾客数
    int wait_time1 = 0;         //摊位1从当前到空闲的时间
    int wait_time2 = 0;         //摊位2从当前到空闲的时间
    long cycle;					//循环次数
    long cyclelimit;			//循环的最大数
    long turnaways = 0;			//被拒的顾客数
    long customers = 0;			//加入队列的顾客数
    long served = 0;			//接受服务的顾客数
    long sum_line = 0;			//累计队列总长
    long line_wait = 0;			//累计队列等候时间
    double min_per_cust;		//顾客到来的平均间隔时间
    
    int main(void)
    {
        printf("Enter the number of simulation hours:n");
        scanf("%d", &hours);
        printf("Enter the average number of customers per hour:n");
        scanf("%d", &cust_per_hour);
        cyclelimit = MIN_PER_HOUR * hours;
        min_per_cust = MIN_PER_HOUR / cust_per_hour;
    
        InitializeQueue(&line1);
        InitializeQueue(&line2);
        srand((unsigned int) time(0));
        for (cycle = 0; cycle < cyclelimit; cycle++)
        {
            if (newcustomer(min_per_cust))		//如果一分钟内有顾客来
            {
                if (QueueIsFull(&line1) && QueueIsFull(&line2))
                    turnaways++;
                else
                {
                    customers++;
                    temp = customertime(cycle);
                    if (line1.items > line2.items)
                        EnQueue(&line2, temp);
                    else if (line1.items < line2.items)
                        EnQueue(&line1, temp);
                    else
                        (rand() % 2) ? EnQueue(&line1, temp) : EnQueue(&line2, temp);
                }
            }
    
            if (wait_time1 <= 0 && !QueueIsEmpty(&line1))
            {
                DeQueue(&line1, &temp);
                wait_time1 = temp.processtime;
                line_wait += cycle - temp.arrive;
                served++;
            }
    
            if (wait_time2 <= 0 && !QueueIsEmpty(&line2))
            {
                DeQueue(&line2, &temp);
                wait_time2 = temp.processtime;
                line_wait += cycle - temp.arrive;
                served++;
            }
    
            if (wait_time1 > 0)
                wait_time1--;
    
            if (wait_time2 > 0)
                wait_time2--;
    
            sum_line += (long) QueueItemCount(&line1)
                + (long) QueueItemCount(&line2);
        }
    
        if (customers > 0)
        {
            printf("customers accepted: %ldn", customers);
            printf("  customers served: %ldn", served);
            printf("         turnaways: %ldn", turnaways);
            printf("average queue size: %.2fn", (double) sum_line / cyclelimit);
            printf(" average wait time: %.2f minutesn", (double) line_wait / served);
        }
        else
            puts("No customers!");
        DeleteAll(&line1);
        DeleteAll(&line2);
        puts("Bye!");
    
        return 0;
    }
    
    //一分钟之内有顾客来,返回1
    int newcustomer(double x)
    {
        if (x * rand() / RAND_MAX < 1)
            return 1;
        else
            return 0;
    }
    
    Item customertime(long when)
    {
        Item cust;
    
        cust.arrive = when;
        cust.processtime = rand() % 3 + 1;
    
        return cust;
    }
    
    
    //queue.c
    #include 
    #include 
    #include "queue.h"
    
    static void AddItem(Node * pq, Item item);
    static void CopyItem(Node * pnode, Item * pitem);
    
    //接口函数
    
    //初始化队列
    void InitializeQueue(Queue * pq)
    {
        pq->head = NULL;
        pq->end = NULL;
        pq->items = 0;
    }
    
    //确定队列为空
    int QueueIsEmpty(const Queue * pq)
    {
        if (pq->items == 0)
            return 1;
        else
            return 0;
    }
    
    //确定队列为满
    int QueueIsFull(const Queue * pq)
    {
        if (pq->items == MAXSIZE)
            return 1;
        else
            return 0;
    }
    
    //确定队列项数
    unsigned int QueueItemCount(const Queue * pq)
    {
        return pq->items;
    }
    
    //给队列末尾添加项
    int EnQueue(Queue * pq, Item item)
    {
        Node * pnode;
    
        if (QueueIsFull(pq))
        {
            fprintf(stderr, "The queue is full.n");
            return 0;
        }
    
        pnode = (Node *) malloc(sizeof(Node));
        if (pnode == NULL)
        {
            fprintf(stderr, "Can't alloc memory.n");
            return 0;
        }
    
        AddItem(pnode, item);
        pnode->next = NULL;
        pq->items++;
        if (pq->head == NULL)
        {
            pq->head = pnode;
        }
        else
            pq->end->next = pnode;
        pq->end = pnode;
    
        return 1;
    }
    
    //从队列开头删除项
    int DeQueue(Queue * pq, Item * pitem)
    {
        Node * pnode;
    
        if (QueueIsEmpty(pq))
        {
            fprintf(stderr, "the queue is empty.n");
            return 0;
        }
    
        CopyItem(pq->head, pitem);
        pnode = pq->head;
        pq->head = pq->head->next;
        free(pnode);
        pq->items--;
    
        if (pq->items == 0)
            pq->end = NULL;
    
        return 1;
    }
    
    //清空队列
    void DeleteAll(Queue * pq)
    {
        Item item;
    
        while (!QueueIsEmpty(pq))
            DeQueue(pq, &item);
    }
    
    //局域函数
    static void AddItem(Node * pnode, Item item)
    {
        pnode->item = item;
    }
    
    static void CopyItem(Node * pnode, Item * pitem)
    {
        *pitem = pnode->item;
    }
    
    
    //queue.h
    
    #ifndef QUEUE_H_
    #define QUEUE_H_
    
    #define MAXSIZE 10
    
    typedef struct item {
    	long arrive;
    	int processtime;
    } Item;
    
    typedef struct node {
    	Item item;
    	struct node * next;
    } Node;
    
    typedef struct queue {
    	Node * head;
    	Node * end;
    	int items;
    } Queue;
    
    //初始化队列
    void InitializeQueue(Queue * pq);
    
    //确定队列为空
    int QueueIsEmpty(const Queue * pq);
    
    //确定队列为满
    int QueueIsFull(const Queue * pq);
    
    //确定队列项数
    unsigned int QueueItemCount(const Queue * pq);
    
    //给队列末尾添加项
    int EnQueue(Queue * pq, Item item);
    
    //从队列开头删除项
    int DeQueue(Queue * pq, Item * pitem);
    
    //清空队列
    void DeleteAll(Queue * pq);
    
    #endif
    
    
  5. 编写一个程序,提示用户输入一个字符串。然后该程序把该字符串的 字符逐个压入一个栈(参见复习题5),然后从栈中弹出这些字符,并显示 它们。结果显示为该字符串的逆序。

    //5.c
    #include 
    #include 
    #include 
    #include "stack.h"
    #include "stack.c"
    
    #define SIZE 40
    
    char * s_gets(char * st, int n);
    
    int main(void)
    {
        Stack stack;
        Item temp[SIZE];
        Item ch;
        int i;
    
        InitializeStack(&stack);
    
        //将用户输入数据压入栈中
        printf("Enter a string:n");
        while (s_gets(temp, SIZE) != NULL && temp[0] != '')
        {
            for (i = 0; temp[i] != ''; i++)
            {
                if (AddItem(&stack, temp[i]) == 0)
                {
                    break;
                }
            }
    
            if (StackIsFull(&stack))
            {
                fprintf(stderr, "The stack is full.n");
                break;
            }
            printf("Your next string (empty line to stop):n");
        }
    
        //从栈中弹出数据并输出
        if (StackIsEmpty(&stack))
        {
            fprintf(stderr, "There is no data.n");
            exit(1);
        }
    
        printf("You input %d charcters.n", StackItemCount(&stack));
        printf("The string in reverse order:n");
        while (StackIsEmpty(&stack) != 1)
        {
            DelItem(&stack, &ch);
            putchar(ch);
        }
        printf("nBye.n");
    
        return 0;
    }
    
    
    char * s_gets(char * st, int n)
    {
        char * ret_val;
        char * find;
    
        ret_val = fgets(st, n, stdin);
        if (ret_val)
        {
            find = strchr(st, 'n');
            if (find)
                *find = '';
            else
                while (getchar() != 'n')
                    continue;
        }
    
        return ret_val;
    }
    
    //stack.c
    #include 
    #include "stack.h"
    
    //初始化栈
    void InitializeStack(Stack * ps)
    {
        ps->items = 0;
    }
    
    //确定栈为空
    int StackIsEmpty(const Stack * ps)
    {
        return (ps->items == 0) ? 1 : 0;
    }
    
    //确定栈为满
    int StackIsFull(const Stack * ps)
    {
        return (ps->items == SMAX) ? 1 : 0;
    }
    
    //统计栈内项数
    int StackItemCount(const Stack * ps)
    {
        return ps->items;
    }
    
    //从栈顶压入项
    int AddItem(Stack * ps, Item item)
    {
        if (StackIsFull(ps))
            return 0;
        else
        {
            ps->item[ps->items] = item;
            ps->items++;
            return 1;
        }
    }
    
    //从栈顶弹出项
    int DelItem(Stack * ps, Item * pitem)
    {
        if (StackIsEmpty(ps))
            return 0;
        else
        {
            * pitem = ps->item[ps->items - 1];
            ps->item[ps->items - 1] = '';
            ps->items--;
            return 1;
        }
    }
    //stack.h
    #ifndef STACK_H_
    #define STACK_H_
    
    #define SMAX 100
    
    typedef char Item;
    typedef struct stack {
    	Item item[SMAX];
    	int items;
    } Stack;
    
    //初始化栈
    void InitializeStack(Stack * ps);
    
    //确定栈为空
    int StackIsEmpty(const Stack * ps);
    
    //确定栈为满
    int StackIsFull(const Stack * ps);
    
    //统计栈内项数
    int StackItemCount(const Stack * ps);
    
    //从栈顶压入项
    int AddItem(Stack * ps, Item item);
    
    //从栈顶弹出项
    int DelItem(Stack * ps, Item * pitem);
    
    //清空项
    void EmptyItem(Stack * ps);
    
    #endif
    
    
  6. 编写一个函数接受 3 个参数:一个数组名(内含已排序的整数)、该 数组的元素个数和待查找的整数。如果待查找的整数在数组中,那么该函数 返回 1;如果该数不在数组中,该函数则返回 0。用二分查找法实现。

    #include 
    #define SIZE 8
    
    int find(int ar[], int size, int n);
    
    int main(void)
    {
        int n;
        int array[SIZE] = {1, 3, 6, 7, 9, 10, 13, 15};
    
        printf("Please input the integer you want to search:n");
        while (scanf("%d", &n) == 1)
        {
            if (find(array, SIZE, n))
                printf("Find.n");
            else
                printf("Can't find.n");
            printf("Your next input (q to quit):n");
        }
    
        return 0;
    }
    
    int find(int * ar, int size, int n)
    {
        int head = 0;
        int end = size - 1;
        int mid;
    
        while (head <= end)
        {
            mid = (head + end) / 2;
            if (n < ar[mid])
                end = mid - 1;
            else if (n > ar[mid])
                head = mid + 1;
            else
                return 1;
        }
    
        return 0;
    }
    
    
    
    
    
    
    
  7. 编写一个程序,打开和读取一个文本文件,并统计文件中每个单词出 现的次数。用改进的二叉查找树储存单词及其出现的次数。程序在读入文件 后,会提供一个有3个选项的菜单。第1个选项是列出所有的单词和出现的次 数。第2个选项是让用户输入一个单词,程序报告该单词在文件中出现的次 数。第3个选项是退出。

    //7.c
    #include 
    #include 
    #include 
    #include 
    #include "word.h"
    #include "word.c"
    #define LEN 40
    #define SIZE 40
    
    char get_choice(void);
    char * s_gets(char * st, int n);
    void count_word(Tree * pt, Item * item);
    void print_word(Item temp);
    
    int main(void)
    {
        Tree words;
        Item temp;
        FILE * fp;
        char ch;
        char name[LEN];
        char word[SIZE];
    
        //打开文件
        printf("Please input the file name:n");
        s_gets(name, LEN);
        if ((fp = fopen(name, "r")) == NULL)
        {
            fprintf(stderr, "Can't open the file.n");
            exit(1);
        }
    
        //从文件读取单词
        InitializeTree(&words);
        while (fscanf(fp, "%s", word) == 1)
        {
            strcpy(temp.word, word);
            temp.num = 1;
            AddItem(&words, &temp);
            if (TreeIsFull(&words))
            {
                fprintf(stderr, "The tree is full.n");
                break;
            }
        }
        fclose(fp);
    
        while ((ch = get_choice()) != 'q')
        {
            if (ch == 'a')
            {
                if (TreeIsEmpty(&words))
                    printf("There is no word.n");
                else
                    Traverse(&words, print_word);
            }
            else
                count_word(&words, &temp);
        }
    
        DeleteAll(&words);
        printf("Bye.n");
    
        return 0;
    }
    
    char get_choice(void)
    {
        char ch;
    
        printf("na. show word listn");
        printf("b. find a wordn");
        printf("q. quitn");
    
    
        ch = getchar();
        while (strchr("abq", tolower(ch)) == NULL)
        {
            while (getchar() != 'n')
                continue;
            printf("Please input the a, b, or q.n");
            ch = getchar();
        }
        while (getchar() != 'n')
            continue;
    
        return ch;
    }
    
    void print_word(Item temp)
    {
        printf("word: %stttcount: %dn", temp.word, temp.num);
    }
    
    void count_word(Tree * pt, Item * item)
    {
        int count;
    
        printf("Enter the word you want to search:n");
        s_gets(item->word, SIZE);
        item->num = 1;
        count = ItemCount(pt, item);
        if (!count)
            printf("Can't find the word.n");
        else
            printf("count: %dn", ItemCount(pt, item));
    }
    
    char * s_gets(char * st, int n)
    {
        char * ret_val;
        char * find;
    
        ret_val = fgets(st, n, stdin);
        if (ret_val)
        {
            find = strchr(st, 'n');
            if (find)
                *find = '';
            else
                while (getchar() != 'n')
                    continue;
        }
    
        return ret_val;
    }
    //word.c
    
    #include 
    #include 
    #include 
    #include "word.h"
    
    //局域数据类型
    typedef struct pair {
        Trnode * parent;
        Trnode * child;
    } Pair;
    
    //局域函数声明
    static Pair SeekItem(const Tree * ptree, const Item * pi);
    static int ToLeft(Item * p1, Item * p2);
    static int ToRight(Item * p1, Item * p2);
    static Trnode * MakeNode(Item * item);
    static void AddNode(Trnode * new_node, Trnode * root);
    static void DeleteNode(Trnode * * ptr);
    static void InOrder(Trnode * root, void (*pfun)(Item item));
    static void DeleteAllNodes(Trnode * root);
    
    //接口函数
    
    //初始化树
    void InitializeTree(Tree * ptree)
    {
        ptree->root = NULL;
        ptree->size = 0;
    }
    
    //确认树为满
    int TreeIsFull(const Tree * ptree)
    {
        if (ptree->size == MAX)
            return 1;
        else
            return 0;
    }
    
    //确认树为空
    int TreeIsEmpty(const Tree * ptree)
    {
        if (ptree->size == 0)
            return 1;
        else
            return 0;
    }
    
    //统计项数
    int TreeItemCount(const Tree * ptree)
    {
        return ptree->size;
    }
    
    //查找项
    int InTree(const Tree * ptree, const Item * pi)
    {
        Pair look;
        look = SeekItem(ptree, pi);
    
        if (look.child != NULL)
            return 1;
        else
            return 0;
    }
    
    //添加项
    int AddItem(Tree * ptree, const Item * pi)
    {
        Pair look;
        Trnode * new_node;
    
        if (TreeIsFull(ptree))
            return 0;
    
        look = SeekItem(ptree, pi);
        if (look.child != NULL)
        {
            (look.child->item.num)++;
            return 1;
        }
        else
        {
            new_node = MakeNode(pi);
            if (new_node == NULL)
            {
                fprintf(stderr, "Could't eate noden");
                return 0;
            }
            ptree->size++;
    
            if (ptree->root == NULL)
                ptree->root = new_node;
            else
                AddNode(new_node, ptree->root);
        }
    
        return 1;
    }
    
    //删除项
    int DelItem(Tree * ptree, const Item * pi)
    {
        Pair look;
    
        look = SeekItem(ptree, pi);
        if (look.child == NULL)
            return 0;
    
        if (look.parent == NULL)
            DeleteNode(&ptree->root);
        else if (look.parent->left == look.child)
            DeleteNode(&look.parent->left);
        else
            DeleteNode(&look.parent->right);
        ptree->size--;
    
        return 1;
    }
    
    //遍历树
    void Traverse(const Tree * ptree, void (*pfun)(Item item))
    {
        if (ptree != NULL)
            InOrder(ptree->root, pfun);
    }
    
    //清空树
    void DeleteAll(Tree * ptree)
    {
        if (ptree != NULL)
            DeleteAllNodes(ptree->root);
        ptree->root = NULL;
        ptree->size = 0;
    }
    
    //每一项计数
    int ItemCount(const Tree * ptree, const Item * item)
    {
        Pair look;
    
        look = SeekItem(ptree, item);
        if (look.child == NULL)
            return 0;
        else
            return look.child->item.num;
    }
    
    
    
    //局域函数
    //寻找项
    static Pair SeekItem(const Tree * ptree, const Item * pi)
    {
        Pair look;
        look.parent = NULL;
        look.child = ptree->root;
    
        if (look.child == NULL)
            return look;
    
        while (look.child != NULL)
        {
            if (ToLeft(pi, &(look.child->item)))
            {
                look.parent = look.child;
                look.child = look.child->left;
            }
            else if (ToRight(pi, &(look.child->item)))
            {
                look.parent = look.child;
                look.child = look.child->right;
            }
            else
                break;
        }
    
        return look;
    }
    
    //项在左边
    static int ToLeft(Item * p1, Item * p2)
    {
        if (strcmp(p1->word, p2->word) < 0)
            return 1;
        else
            return 0;
    }
    
    //项在右边
    static int ToRight(Item * p1, Item * p2)
    {
        if (strcmp(p1->word, p2->word) > 0)
            return 1;
        else
            return 0;
    }
    
    static Trnode * MakeNode(Item * item)
    {
        Trnode * pnode;
    
        pnode = (Trnode *) malloc(sizeof(Trnode));
        if (pnode != NULL)
        {
            pnode->item = *item;
            pnode->left = NULL;
            pnode->right = NULL;
        }
    
        return pnode;
    }
    
    static void AddNode(Trnode * new_node, Trnode * root)
    {
        if (ToLeft(&(new_node->item), &(root->item)))
        {
            if (root->left == NULL)
                root->left = new_node;
            else
                AddNode(new_node, root->left);
        }
    
        else if (ToRight(&(new_node->item), &(root->item)))
        {
            if (root->right == NULL)
                root->right = new_node;
            else
                AddNode(new_node, root->right);
        }
    
        else
        {
            fprintf(stderr, "location error in AddNode().n");
            exit(1);
        }
    }
    
    //ptr 是父节点指向目标节点的指针的地址
    static void DeleteNode(Trnode * * ptr)
    {
        Trnode * pnode;
    
        if ((*ptr)->left == NULL)
        {
            pnode = *ptr;
            *ptr = (*ptr)->right;
            free(pnode);
        }
    
        else if ((*ptr)->right == NULL)
        {
            pnode = *ptr;
            *ptr = (*ptr)->left;
            free(pnode);
        }
    
        else
        {
            for (pnode = (*ptr)->left; pnode->right != NULL; pnode = pnode->right)
                continue;
            pnode->right = (*ptr)->right;
            pnode = (*ptr);
            *ptr = (*ptr)->left;
            free(pnode);
        }
    }
    
    static void InOrder(Trnode * root, void (*pfun)(Item item))
    {
        if (root != NULL)
        {
            InOrder(root->left, pfun);
            (*pfun)(root->item);
            InOrder(root->right, pfun);
        }
    }
    
    static void DeleteAllNodes(Trnode * root)
    {
        Trnode * pright;
    
        if (root != NULL)
        {
            pright = root->right;
            DeleteAllNodes(root->left);
            free(root);
            DeleteAllNodes(pright);
        }
    }
    //word.h
    
    #ifndef WORD_H_
    #define WORD_H_
    
    #define LEN 40
    #define MAX 100
    
    typedef struct item {
    	char word[LEN];
    	int num;
    } Item;
    
    typedef struct trnode {
    	Item item;
    	struct trnode * left;
    	struct trnode * right;
    } Trnode;
    
    typedef struct tree {
    	Trnode * root;
    	int size;
    } Tree;
    
    //初始化树
    void InitializeTree(Tree * ptree);
    
    //确认树为满
    int TreeIsFull(const Tree * ptree);
    
    //确认树为空
    int TreeIsEmpty(const Tree * ptree);
    
    //统计项数
    int TreeItemCount(const Tree * ptree);
    
    //查找项
    int InTree(const Tree * ptree, const Item * pi);
    
    //添加项
    int AddItem(Tree * ptree, const Item * pi);
    
    //删除项
    int DelItem(Tree * ptree, const Item * pi);
    
    //遍历树
    void Traverse(const Tree * ptree, void (*pfun)(Item item));
    
    //清空树
    void DeleteAll(Tree * ptree);
    
    //对某一项计数
    int ItemCount(const Tree * ptree, const Item * item);
    
    #endif
    
    
  8. 修改宠物俱乐部程序,把所有同名的宠物都储存在同一个节点中。当 用户选择查找宠物时,程序应询问用户该宠物的名字,然后列出该名字的所 有宠物(及其种类)。

    //8.c
    #include 
    #include 
    #include 
    #include 
    #include "pet.h"
    #include "pet.c"
    
    char get_choice(void);
    char * s_gets(char * st, int n);
    void addpet(Tree * pt);
    void printpet(Item temp);
    void findpet(const Tree * pt);
    void droppet(Tree * pt);
    void showpet(const Tree * pt);
    
    int main(void)
    {
        Tree pet;
        char ch;
    
        InitializeTree(&pet);
        while ((ch = get_choice()) != 'q')
        {
            switch (ch)
            {
            case 'a': addpet(&pet);
                break;
            case 'l': showpet(&pet);
                break;
            case 'f': findpet(&pet);
                break;
            case 'n': printf("%d pets in club.n",
                TreeItemCount(&pet));
                break;
            case 'd': droppet(&pet);
                break;
            default: puts("Swithing error");
            }
            printf("n");
        }
    
        DeleteAll(&pet);
        printf("Bye.n");
    
        return 0;
    }
    
    char get_choice(void)
    {
        char ch;
    
        puts("Nerfville Pet Club Membership Program");
        puts("Enter the letter corresponding to your choice:");
        puts("a) add a pet        l) show list of pets");
        puts("n) number of pets   f) find pets");
        puts("d) delete a pet     q) quit");
    
    
        ch = getchar();
        while (strchr("alnfdq", tolower(ch)) == NULL)
        {
            while (getchar() != 'n')
                continue;
            printf("Please input the a, b, or q.n");
            ch = getchar();
        }
        while (getchar() != 'n')
            continue;
    
        return ch;
    }
    
    void showpet(const Tree * pt)
    {
        if (TreeIsEmpty(pt))
            printf("No pet in club.n");
        else
            Traverse(pt, printpet);
    }
    
    void findpet(const Tree * pt)
    {
        Item temp;
    
        if (TreeIsEmpty(pt))
            puts("No pet in the club.n");
        else
        {
            printf("Enter the name of pet:n");
            s_gets(temp.name, LEN);
            FindItem(pt, &temp);
        }
    }
    
    void addpet(Tree * pt)
    {
        Item temp;
    
        if (TreeIsFull(pt))
            puts("No room in the club.n");
        else
        {
            printf("Enter the name of pet:n");
            s_gets(temp.name, LEN);
            printf("Enter the kind of pet:n");
            s_gets(temp.kind[0], LEN);
            temp.num = 1;
            AddItem(pt, &temp);
        }
    }
    
    void droppet(Tree * pt)
    {
        Item temp;
    
        if (TreeIsEmpty(pt))
        {
            puts("No entries.n");
            return;
        }
    
        printf("Enter the name of pet:n");
        s_gets(temp.name, LEN);
        if (DelItem(pt, &temp) == 0)
        {
            printf("Can't find the pet.n");
        }
    }
    
    void printpet(Item temp)
    {
        int i;
    
        printf("name: %sttkind: ", temp.name);
        for (i = 0; i < temp.num; i++)
            printf("%s ", temp.kind[i]);
        printf("n");
    }
    
    char * s_gets(char * st, int n)
    {
        char * ret_val;
        char * find;
    
        ret_val = fgets(st, n, stdin);
        if (ret_val)
        {
            find = strchr(st, 'n');
            if (find)
                *find = '';
            else
                while (getchar() != 'n')
                    continue;
        }
    
        return ret_val;
    }
    
    
    
    
    
    //pet.c
    #include 
    #include 
    #include 
    #include "pet.h"
    
    //局域数据类型
    typedef struct pair {
        Trnode * parent;
        Trnode * child;
    } Pair;
    
    //内部链接,文件作用域
    static int count = 0;
    
    //局域函数声明
    static Pair SeekItem(const Tree * ptree, const Item * pi);
    static int ToLeft(Item * p1, Item * p2);
    static int ToRight(Item * p1, Item * p2);
    static Trnode * MakeNode(Item * item);
    static void AddNode(Trnode * new_node, Trnode * root);
    static void DeleteNode(Trnode * * ptr);
    static void InOrder(Trnode * root, void (*pfun)(Item item));
    static void DeleteAllNodes(Trnode * root);
    static void CountItem(Trnode * root);
    
    //接口函数
    
    //初始化树
    void InitializeTree(Tree * ptree)
    {
        ptree->root = NULL;
        ptree->size = 0;
    }
    
    //确认树为满
    int TreeIsFull(const Tree * ptree)
    {
        if (ptree->size == SIZE)
            return 1;
        else
            return 0;
    }
    
    //确认树为空
    int TreeIsEmpty(const Tree * ptree)
    {
        if (ptree->size == 0)
            return 1;
        else
            return 0;
    }
    
    //统计项数
    int TreeItemCount(const Tree * ptree)
    {
        count = 0;
    
        CountItem(ptree->root);
    
        return count;
    }
    
    //查找项
    void FindItem(const Tree * ptree, const Item * pi)
    {
        Pair look;
        int i;
    
        look = SeekItem(ptree, pi);
        if (look.child != NULL)
        {
            printf("name: %sttkind: ", look.child->item.name);
            for (i = 0; i < look.child->item.num; i++)
                printf("%s ", look.child->item.kind[i]);
            printf("n");
        }
        else
            printf("Can't find the pet.n");
    
    }
    
    //添加项
    int AddItem(Tree * ptree, const Item * pi)
    {
        Pair look;
        Trnode * new_node;
    
        if (TreeIsFull(ptree))
            return 0;
    
        look = SeekItem(ptree, pi);
        if (look.child != NULL)
        {
            strcpy(look.child->item.kind[look.child->item.num], pi->kind[0]);
            (look.child->item.num)++;
            return 1;
        }
        else
        {
            new_node = MakeNode(pi);
            if (new_node == NULL)
            {
                fprintf(stderr, "Could't eate noden");
                return 0;
            }
            ptree->size++;
    
            if (ptree->root == NULL)
                ptree->root = new_node;
            else
                AddNode(new_node, ptree->root);
        }
    
        return 1;
    }
    
    //删除项
    int DelItem(Tree * ptree, const Item * pi)
    {
        Pair look;
    
        look = SeekItem(ptree, pi);
        if (look.child == NULL)
            return 0;
    
        if (look.parent == NULL)
            DeleteNode(&ptree->root);
        else if (look.parent->left == look.child)
            DeleteNode(&look.parent->left);
        else
            DeleteNode(&look.parent->right);
        ptree->size--;
    
        return 1;
    }
    
    //遍历树
    void Traverse(const Tree * ptree, void (*pfun)(Item item))
    {
        if (ptree != NULL)
            InOrder(ptree->root, pfun);
    }
    
    //清空树
    void DeleteAll(Tree * ptree)
    {
        if (ptree != NULL)
            DeleteAllNodes(ptree->root);
        ptree->root = NULL;
        ptree->size = 0;
    }
    
    //局域函数
    //寻找项
    static Pair SeekItem(const Tree * ptree, const Item * pi)
    {
        Pair look;
        look.parent = NULL;
        look.child = ptree->root;
    
        if (look.child == NULL)
            return look;
    
        while (look.child != NULL)
        {
            if (ToLeft(pi, &(look.child->item)))
            {
                look.parent = look.child;
                look.child = look.child->left;
            }
            else if (ToRight(pi, &(look.child->item)))
            {
                look.parent = look.child;
                look.child = look.child->right;
            }
            else
                break;
        }
    
        return look;
    }
    
    //项在左边
    static int ToLeft(Item * p1, Item * p2)
    {
        if (strcmp(p1->name, p2->name) < 0)
            return 1;
        else
            return 0;
    }
    
    //项在右边
    static int ToRight(Item * p1, Item * p2)
    {
        if (strcmp(p1->name, p2->name) > 0)
            return 1;
        else
            return 0;
    }
    
    static Trnode * MakeNode(Item * item)
    {
        Trnode * pnode;
    
        pnode = (Trnode *) malloc(sizeof(Trnode));
        if (pnode != NULL)
        {
            pnode->item = *item;
            pnode->left = NULL;
            pnode->right = NULL;
        }
    
        return pnode;
    }
    
    static void AddNode(Trnode * new_node, Trnode * root)
    {
        if (ToLeft(&(new_node->item), &(root->item)))
        {
            if (root->left == NULL)
                root->left = new_node;
            else
                AddNode(new_node, root->left);
        }
    
        else if (ToRight(&(new_node->item), &(root->item)))
        {
            if (root->right == NULL)
                root->right = new_node;
            else
                AddNode(new_node, root->right);
        }
    
        else
        {
            fprintf(stderr, "location error in AddNode().n");
            exit(1);
        }
    }
    
    //ptr 是父节点指向目标节点的指针的地址
    static void DeleteNode(Trnode * * ptr)
    {
        Trnode * pnode;
    
        if ((*ptr)->left == NULL)
        {
            pnode = *ptr;
            *ptr = (*ptr)->right;
            free(pnode);
        }
    
        else if ((*ptr)->right == NULL)
        {
            pnode = *ptr;
            *ptr = (*ptr)->left;
            free(pnode);
        }
    
        else
        {
            for (pnode = (*ptr)->left; pnode->right != NULL; pnode = pnode->right)
                continue;
            pnode->right = (*ptr)->right;
            pnode = (*ptr);
            *ptr = (*ptr)->left;
            free(pnode);
        }
    }
    
    static void InOrder(Trnode * root, void (*pfun)(Item item))
    {
        if (root != NULL)
        {
            InOrder(root->left, pfun);
            (*pfun)(root->item);
            InOrder(root->right, pfun);
        }
    }
    
    static void DeleteAllNodes(Trnode * root)
    {
        Trnode * pright;
    
        if (root != NULL)
        {
            pright = root->right;
            DeleteAllNodes(root->left);
            free(root);
            DeleteAllNodes(pright);
        }
    }
    
    static void CountItem(Trnode * root)
    {
        if (root != NULL)
        {
            CountItem(root->left);
            count += root->item.num;
            CountItem(root->right);
        }
    }
    
    //pet.h
    #ifndef WORD_H_
    #define WORD_H_
    
    #define MAX 10
    #define LEN 40
    #define SIZE 100
    
    typedef struct item {
    	char name[LEN];
    	char kind[MAX][LEN];
    	int num;
    } Item;
    
    typedef struct trnode {
    	Item item;
    	struct trnode * left;
    	struct trnode * right;
    } Trnode;
    
    typedef struct tree {
    	Trnode * root;
    	int size;
    } Tree;
    
    //初始化树
    void InitializeTree(Tree * ptree);
    
    //确认树为满
    int TreeIsFull(const Tree * ptree);
    
    //确认树为空
    int TreeIsEmpty(const Tree * ptree);
    
    //统计项数
    int TreeItemCount(const Tree * ptree);
    
    //查找项
    void FindItem(const Tree * ptree, const Item * item);
    
    //添加项
    int AddItem(Tree * ptree, const Item * pi);
    
    //删除项
    int DelItem(Tree * ptree, const Item * pi);
    
    //遍历树
    void Traverse(const Tree * ptree, void (*pfun)(Item item));
    
    //清空树
    void DeleteAll(Tree * ptree);
    
    #endif
    
    
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/942557.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号