- C primer plus编程题答案下
- 第十二章 存储类别,链接和存储
- 第十三章 文件输入输出
- 第十四章 结构和其他数据形式
- 第十五章 位操作
- 第十六章 C预处理和C库
- 第十七章 高级数据表示
-
不使用全局变量,重写程序清单 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; } -
在美国,通常以英里/加仑来计算油耗;在欧洲,以升/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 #includestatic 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);
-
重新设计编程练习 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); -
在一个循环中编写并测试一个函数,该函数返回它被调用的次数。
#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++; } -
编写一个程序,生成 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"); } } -
编写一个程序,生成 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; } -
编写一个程序,按照程序清单 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 #includeint * 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"); }
- 编写一个符合以下描述的函数。首先,询问用户需要输入多少个单 词。然后,接收用户输入的单词,并显示出来,使用 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; }
-
修改程序清单 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; } -
编写一个文件拷贝程序,该程序通过命令行获取原始文件名和拷贝文 件名。尽量使用标准 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; } -
编写一个文件拷贝程序,提示用户输入文本文件名,并以该文件名作 为原始文件名和输出文件名。该程序要使用 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; } -
编写一个程序,按顺序在屏幕上显示命令行中列出的所有文件。使用 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; } -
修改程序清单 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; } -
使用命令行参数的程序依赖于用户的内存如何正确地使用它们。重写 程序清单 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; } -
编写一个程序打开两个文件。可以使用命令行参数或提示用户输入文 件名。
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; }
-
编写一个程序,以一个字符和任意文件名作为命令行参数。如果字符 后面没有参数,该程序读取标准输入;否则,程序依次打开每个文件并报告 每个文件中该字符出现的次数。文件名和字符本身也要一同报告。程序应包 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; } -
修改程序清单 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; } -
编写一个程序打开一个文本文件,通过交互方式获得文件名。通过 一个循环,提示用户输入一个文件位置。然后该程序打印从该位置开始到下 一个换行符之前的内容。用户输入负数或非数值字符可以结束输入循环。
#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; } -
编写一个程序,接受两个命令行参数。第 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; } -
创建一个文本文件,内含 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; } -
用变长数组(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 ; } -
数字图像,尤其是从宇宙飞船发回的数字图像,可能会包含一些失 真。为编程练习 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; }
-
重新编写复习题 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; } -
编写一个函数,提示用户输入日、月和年。月份可以是月份号、月份 名或月份名缩写。然后该程序应返回一年中到用户指定日子(包括这一天) 的总天数。
#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; } -
修改程序清单 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; } -
编写一个程序,创建一个有两个成员的结构模板: 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"); }
- 编写一个程序满足下面的要求。
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); }
- 一个文本文件中保存着一个垒球队的信息。每行数据都是这样排列:
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; } }
-
修改程序清单 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; } -
巨人航空公司的机群由 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; }
-
巨人航空公司(编程练习 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; } -
编写一个程序,通过一个函数指针数组实现菜单。例如,选择菜单 中的 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; } -
编写一个名为 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第十六章 C预处理和C库#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]); }
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()函数的特性:
#includeclock_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; }
-
修改程序清单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; } -
假设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 -
假设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; } } -
重写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.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 -
编写一个函数接受 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; } -
编写一个程序,打开和读取一个文本文件,并统计文件中每个单词出 现的次数。用改进的二叉查找树储存单词及其出现的次数。程序在读入文件 后,会提供一个有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.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



