程序清单14.1,book.c:
/* book.c -- 一本书的图书目录 */
#include <stdio.h>
#include <string.h>
#define MAXTITL 41 /* 书名的最大长度 + 1 */
#define MAXAUTL 31 /* 作者姓名的最大长度 + 1 */
char * s_gets(char * st, int n);
struct book { /* 结构模板:标记是 book */
char title[MAXTITL]; /* 书名 */
char author[MAXAUTL]; /* 作者 */
float value; /* 价格 */
}; /* 结构模板结束 */
int main(void)
{
struct book library; /* 把 library 声明为一个 book 类型的变量 */
printf("Please enter the book title.\n");
s_gets(library.title, MAXTITL); /* 访问 title 部分 */
printf("Now enter the author.\n");
s_gets(library.author, MAXAUTL);
printf("Now enter the value.\n");
scanf("%f", &library.value);
printf("%s by %s: $%.2f\n", library.title, library.author, library.value);
printf("%s: \"%s\" ($%.2f)\n", library.author, library.title, library.value);
printf("Done.\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) // 如果地址不为NULL
*find = '\0'; // 在此处放置一个空字符
else
while (getchar() != '\n') // 处理多余字符
continue;
}
return ret_val;
}
输出结果:
![](https://i-blog.csdnimg.cn/blog_migrate/a73af25b4c9becc97ce81f06421c9328.png)
程序清单14.2,manybook.c:
/* manybook.c -- 包含多本书的图书目录 */
#include <stdio.h>
#include <string.h>
#define MAXTITL 40
#define MAXAUTL 40
#define MAXBKS 100 /* 书籍的最大数量 */
char * s_gets(char * st, int n);
struct book{
char title[MAXTITL];
char author[MAXAUTL];
float value;
};
int main(void)
{
struct book library[MAXBKS]; /* book 类型结构的数组 */
int count = 0;
int index;
printf("Please enter the book title.\n");
printf("Press [enter] at the start of a line to stop.\n");
while (count < MAXBKS && s_gets(library[count].title, MAXTITL) != NULL
&& library[count].title[0] != '\0')
{
printf("Now enter the author.\n");
s_gets(library[count].author, MAXAUTL);
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("Here is the list of your books:\n");
for (index = 0; index < count; index++)
printf("%s by %s: $%.2f\n", library[index].title, library[index].author, library[index].value);
}
else
printf("No books? Too bad.\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) //如果地址不为NULL
*find = '\0'; // 在此处放置一个空字符
else
while (getchar() != '\n') // 处理多余字符
continue;
}
return ret_val;
}
输出结果:
![](https://i-blog.csdnimg.cn/blog_migrate/a1d8c29a9fe7a6d6612d2f7bf91d30fc.png)
程序清单14.3,friend.c:
// friend.c -- 嵌套结构示例
#include <stdio.h>
#define LEN 20
const char * msgs[5] = // 指针数组,每一个数组元素都是一个 char 类型的指针
{
" Thank you for wonderful evening, ",
"You certainly prove that a ",
"is a special kind of guy. We must get together",
"over a delicious ",
" and have a few laughs"
};
struct names { // 第一个结构
char first[LEN];
char last[LEN];
};
struct guy { // 第二个结构
struct names handle; // 嵌套结构
char favfood[LEN];
char job[LEN];
float income;
};
int main(void)
{
struct guy fellow = { // 初始化一个结构体变量
{ "Ewen", "Villard" },
"grilled salmon",
"personality coach",
68112.00
};
printf("Dear %s, \n\n", fellow.handle.first);
printf("%s%s.\n", msgs[0], fellow.handle.first);
printf("%s%s\n", msgs[1], fellow.job);
printf("%s\n", msgs[2]);
printf("%s%s%s", msgs[3], fellow.favfood, msgs[4]);
if (fellow.income > 150000.0)
puts("!!");
else if (fellow.income > 75000.0)
puts("!");
else
puts(".");
printf("\n%40s%s\n", " ", "See you soon,");
printf("%40s%s\n", " ", "Shalala");
return 0;
}
输出结果:
![](https://i-blog.csdnimg.cn/blog_migrate/2121fcb56fc591ed01d73994e5be3274.png)
程序清单14.4,friends.c:
/* friends.c -- 使用指向结构的指针 */
#include <stdio.h>
#define LEN 20
struct names {
char first[LEN];
char last[LEN];
};
struct guy {
struct names handle;
char favfood[LEN];
char job[LEN];
float income;
};
int main(void)
{
struct guy fellow[2] = {
{ { "Ewen", "Villard" },
"grilled salmon",
"personality coach",
68112.00
},
{ { "Rodney", "Swillbelly" },
"tripe",
"tabloid editor",
432400.00
}
};
struct guy * him; // 指向结构的指针
printf("address #1: %p #2: %p\n", &fellow[0], &fellow[1]);
him = &fellow[0];
printf("pointer #1: %p #2: %p\n", him, him + 1);
printf("him->income is $%.2f: (*him).income is $%.2f\n", him->income, (*him).income);
him++; // 指向下一个结构
printf("him->favfood is %s: him->handle.last is %s\n", him->favfood, him->handle.last);
return 0;
}
输出结果:
![](https://i-blog.csdnimg.cn/blog_migrate/682579b0466eb841556ab6297d4b86e6.png)
程序清单14.5,funds1.c:
/* funds1.c -- 把结构成员看作参数传递 */
#include <stdio.h>
#define FUNDLEN 50
struct funds {
char bank[FUNDLEN];
double bankfund;
char save[FUNDLEN];
double savefund;
};
double sum(double, double);
int main(void)
{
struct funds stan = {
"Garlic-Melon Bank",
4032.27,
"Lucky's Savings and Loan",
8543.94
};
printf("Stan has a total of $%.2f.\n", sum(stan.bankfund, stan.savefund));
return 0;
}
double sum(double x, double y)
{
return (x + y);
}
输出结果:
![](https://i-blog.csdnimg.cn/blog_migrate/d095d336898707dde1e554bf7a5ac92f.png)
程序清单14.6,funds2.c:
/* funds2.c -- 传递指向结构的指针 */
#include <stdio.h>
#define FUNDLEN 50
struct funds {
char bank[FUNDLEN];
double bankfund;
char save[FUNDLEN];
double savefund;
};
double sum(const struct funds *); // 参数是一个指针
int main(void)
{
struct funds stan = {
"Garlic-Melon Bank",
4032.27,
"Lucky's Savings and Loan",
8543.94
};
printf("Stan has a total of $%.2f.\n", sum(&stan));
return 0;
}
double sum(const struct funds * money)
{
return (money->bankfund + money->savefund);
}
输出结果:
![](https://i-blog.csdnimg.cn/blog_migrate/ba55e0cffca65a0ab7fa7eb2c6ce6df0.png)
程序清单14.7,funds3.c:
/* funds3.c -- 传递一个结构 */
#include <stdio.h>
#define FUNDLEN 50
struct funds {
char bank[FUNDLEN];
double bankfund;
char save[FUNDLEN];
double savefund;
};
double sum(const struct funds moolah); /* 参数是一个结构 */
int main(void)
{
struct funds stan = {
"Garlic-Melon Bank",
4032.27,
"Lucky's Savings and Loan",
8543.94
};
printf("Stan has a total of $%.2f.\n", sum(stan));
return 0;
}
double sum(const struct funds moolah)
{
return (moolah.bankfund + moolah.savefund);
}
输出结果:
![](https://i-blog.csdnimg.cn/blog_migrate/3c4b08c2a1168c65e3beb4af2b41e04a.png)
程序清单14.8,names1.c:
/* names1.c -- 使用指向结构的指针 */
#include <stdio.h>
#include <string.h>
#define NLEN 30
struct namect {
char fname[NLEN];
char lname[NLEN];
int letters;
};
void getinfo(struct namect *);
void makeinfo(struct namect *);
void showinfo(const struct namect *);
char * s_gets(char * st, int n);
int main(void)
{
struct namect person;
getinfo(&person);
makeinfo(&person);
showinfo(&person);
return 0;
}
void getinfo(struct namect * pst)
{
printf("Please enter you first name.\n");
s_gets(pst->fname, NLEN);
printf("Please enter your last name.\n");
s_gets(pst->lname, NLEN);
}
void makeinfo(struct namect * pst)
{
pst->letters = strlen(pst->fname) + strlen(pst->lname);
}
void showinfo(const struct namect * pst)
{
printf("%s %s, your name contains %d letters.\n", pst->fname, pst->lname, pst->letters);
}
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) //如果地址不为NULL
*find = '\0'; // 在此处放置一个空字符
else
while (getchar() != '\n') // 处理多余字符
continue;
}
return ret_val;
}
输出结果:
![](https://i-blog.csdnimg.cn/blog_migrate/3491a57ac9f8822b8532c8843cd780ef.png)
程序清单14.9,names2.c:
/* names2.c -- 传递并返回结构 */
#include <stdio.h>
#include <string.h>
#define NLEN 30
struct namect {
char fname[NLEN];
char lname[NLEN];
int letters;
};
struct namect getinfo(void);
struct namect makeinfo(struct namect); //不用指针一定要返回,否则只是局部变量的值改变
void showinfo(struct namect);
char * s_gets(char * st, int n);
int main(void)
{
struct namect person;
person = getinfo();
person = makeinfo(person);
showinfo(person);
return 0;
}
struct namect getinfo(void)
{
struct namect temp;
printf("Please enter you first name.\n");
s_gets(temp.fname, NLEN);
printf("Please enter your last name.\n");
s_gets(temp.lname, NLEN);
return temp;
}
struct namect makeinfo(struct namect info)
{
info.letters = strlen(info.fname) + strlen(info.lname);
return info; //操作后返回值
}
void showinfo(struct namect info)
{
printf("%s %s, your name contains %d letters.\n", info.fname, info.lname, info.letters);
}
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) //如果地址不为NULL
*find = '\0'; // 在此处放置一个空字符
else
while (getchar() != '\n') // 处理多余字符
continue;
}
return ret_val;
}
输出结果:
![](https://i-blog.csdnimg.cn/blog_migrate/26cc653cc0030dd90397c21c74751f08.png)
程序清单14.10,names3.c:
/* names3.c -- 使用指针与 malloc() */
#include <stdio.h>
#include <string.h> //提供 strcpy()、strlen()
#include <stdlib.h> // 提供 malloc()、free()
#define SLEN 30
struct namect {
char * fname; // 使用指针
char * lname;
int letters;
};
void getinfo(struct namect *); // 分配内存
void makeinfo(struct namect *);
void showinfo(const struct namect *);
void cleanup(struct namect *); // 调用该函数时释放内存
char * s_gets(char * st, int n);
int main(void)
{
struct namect person;
getinfo(&person);
makeinfo(&person);
showinfo(&person);
cleanup(&person);
return 0;
}
void getinfo(struct namect * pst)
{
char temp[SLEN];
printf("Please enter you first name.\n");
s_gets(temp, SLEN);
// 分配内存以存储名
pst->fname = (char *) malloc(strlen(temp) + 1);
// 把名拷贝到动态分配的内存中
strcpy(pst->fname, temp);
printf("Please enter your last name.\n");
s_gets(temp, SLEN);
pst->lname = (char *) malloc(strlen(temp) + 1);
strcpy(pst->lname, temp);
}
void makeinfo(struct namect * pst)
{
pst->letters = strlen(pst->fname) + strlen(pst->lname);
}
void showinfo(const struct namect * pst)
{
printf("%s %s, your name contains %d letters.\n", pst->fname, pst->lname, pst->letters);
}
void cleanup(struct namect * pst)
{
free(pst->fname);
free(pst->lname);
}
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) //如果地址不为NULL
*find = '\0'; // 在此处放置一个空字符
else
while (getchar() != '\n') // 处理多余字符
continue;
}
return ret_val;
}
输出结果:
![](https://i-blog.csdnimg.cn/blog_migrate/87a79425150923791752513057f47d41.png)
程序清单14.11,complit.c:
/* complit.c -- 复合字面量 */
#include <stdio.h>
#define MAXTITL 41
#define MAXAUTL 31
struct book { // 结构模板:标记是book
char title[MAXTITL];
char author[MAXAUTL];
float value;
};
int main(void)
{
struct book readfirst;
int score;
printf("Enter test score: ");
scanf("%d", &score);
if (score >= 84)
readfirst = (struct book) { "Crime and Punishment",
"Fyodor Dostoyevsky",
11.25};
else
readfirst = (struct book) { "Mr. Bouncy's Nice Hat",
"Fred Winsome",
5.99};
printf("Your assigned reading:\n");
printf("%s by %s: $%.2f\n", readfirst.title, readfirst.author, readfirst.value);
return 0;
}
输出结果:
![](https://i-blog.csdnimg.cn/blog_migrate/d50444af9e8d04e9b34cc7ad5863af9f.png)
程序清单14.12,flexmemb.c:
// flexmemb.c -- 伸缩型数组成员(C99 新增特性)
#include <stdio.h>
#include <stdlib.h>
struct flex {
size_t count;
double average;
double scores []; // 伸缩型数组成员
};
void showFlex(const struct flex * p);
int main(void)
{
struct flex * pf1, * pf2;
int n = 5;
int i;
int tot = 0;
pf1 = malloc(sizeof(struct flex) + n * sizeof(double));
pf1->count = n;
for (i = 0; i < n; i++)
{
pf1->scores[i] = 20.0 - i;
tot += pf1->scores[i];
}
pf1->average = tot / n;
showFlex(pf1);
n = 9;
tot = 0;
pf2 = malloc(sizeof(struct flex) + n * sizeof(double));
pf2->count = n;
for (i = 0; i < n; i++)
{
pf2->scores[i] = 20.0 - i / 2.0;
tot += pf2->scores[i];
}
pf2->average = tot / n;
showFlex(pf2);
free(pf1);
free(pf2);
return 0;
}
void showFlex(const struct flex * p)
{
int i;
printf("Scores: ");
for (i = 0; i < (int) p->count; i++)
printf("%g ", p->scores[i]);
printf("\nAverage: %g\n", p->average);
}
输出结果:
![](https://i-blog.csdnimg.cn/blog_migrate/7b4f29298a7c65dba9b8b5891c764db1.png)
程序清单14.13,funds4.c:
/* funds4.c -- 把结构数组传递给函数 */
#include <stdio.h>
#define FUNDLEN 50
#define N 2
struct funds {
char bank[FUNDLEN];
double bankfund;
char save[FUNDLEN];
double savefund;
};
double sum(const struct funds money [], int n);
int main(void)
{
struct funds jones[N] = {
{
"Garlic-Melon Bank",
4032.27,
"Lucky's Saving and Loan",
8543.94
},
{
"Honest Jack's Bank",
3620.88,
"Party Time Savings",
3802.91
}
};
printf("The Joneses have a total of $%.2f.\n", sum(jones, N));
return 0;
}
double sum(const struct funds money [], int n)
{
double total;
int i;
for (i = 0; i < n; i++)
total += (money + i)->bankfund + (money + i)->savefund; //用指针操作
//total += money[i].bankfund + money[i].savefund;
return total;
}
输出结果:
![](https://i-blog.csdnimg.cn/blog_migrate/829d32159ca5f829e1c4352b5432d6aa.png)
程序清单14.14 ,booksave.c:
/* booksave.c -- 在文件中保存结构中的内容 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXTITL 40
#define MAXAUTL 40
#define MAXBKS 10 /* 最大书籍数量 */
char * s_gets(char * st, int n);
struct book { /* 建立 book 模板 */
char title[MAXTITL];
char author[MAXAUTL];
float value;
};
int main(void)
{
struct book library[MAXBKS]; /* 结构数组 */
int count = 0;
int index, filecount;
FILE * pbooks;
int size = sizeof(struct book);
if ((pbooks = fopen("book.dat", "a+b")) == NULL) // 在文件末尾追加内容
{
fputs("Can't open book.dat file\n", stderr);
exit(1);
}
rewind(pbooks); /* 定位到文件开始 */
while (count < MAXBKS && fread(&library[count], size, 1, pbooks) == 1) //从文件中读入到数组中
{
if (count == 0)
puts("Current contens of book.dat:");
printf("%s by %s: $%.2f\n", library[count].title, library[count].author, library[count].value);
count++;
}
filecount = count; // 备份以在写入时使用地址
if (count == MAXBKS)
{
fputs("The book.dat file is full.", stderr);
exit(2);
}
puts("Please add new book title.");
puts("Press [enter] at the start of a line to stop.");
while (count < MAXBKS && s_gets(library[count].title, MAXTITL) != NULL &&library[count].title[0] != '\0')
{
puts("Now enter the author.");
s_gets(library[count].author, MAXAUTL);
puts("Now enter the value.");
scanf("%f", &library[count++].value);
while (getchar() != '\n')
continue;
if (count < MAXBKS)
puts("Enter the next title.");
}
if (count > 0)
{
puts("Here is the list of your books:");
for (index = 0; index < count; index++)
printf("%s by %s: $%.2f\n", library[index].title, library[index].author, library[index].value);
fwrite(&library[filecount], size, count - filecount, pbooks);
}
else
puts("No books? Too bad.\n");
puts("Bye.\n");
fclose(pbooks);
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) //如果地址不为NULL
*find = '\0'; // 在此处放置一个空字符
else
while (getchar() != '\n') // 处理多余字符
continue;
}
return ret_val;
}
输出结果:
![](https://i-blog.csdnimg.cn/blog_migrate/86de16195688de573fc1f0011b8cb94d.png)
程序清单14.15,enum.c:
/* enum.c -- 使用枚举类型的值 */
#include <stdio.h>
#include <string.h> // 提供 strcmp() 、strchr() 函数原型
#include <stdbool.h>
#define LEN 30
char * s_gets(char * st, int n);
enum spectrum { red, orange, yellow, green, blue, violet };
const char * colors [] = { "red", "orange", "yellow", "green", "blue", "violet" };
int main(void)
{
char choice[LEN];
enum spectrum color;
bool color_is_found = false;
puts("Enter a color (empty line to quit):");
while (s_gets(choice, LEN) != NULL && choice[0] != '\0')
{
for (color = red; color <= violet; color++)
{
if (strcmp(choice, colors[color]) == 0)
{
color_is_found = true;
break;
}
}
if (color_is_found)
switch (color)
{
case red: puts("Rose are red.");
break;
case orange: puts("Poppies are orange.");
break;
case yellow: puts("Sunflowers are yellow.");
break;
case green: puts("Grass is green.");
break;
case blue: puts("Bluebells are blue.");
break;
case violet: puts("Violets are violet.");
break;
}
else
printf("I don't know about the color %s.\n", choice);
color_is_found = false;
puts("Next color, please (empty line to quit):");
}
puts("Goodbye!");
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) //如果地址不为NULL
*find = '\0'; // 在此处放置一个空字符
else
while (getchar() != '\n') // 处理多余字符
continue;
}
return ret_val;
}
输出结果:
![](https://i-blog.csdnimg.cn/blog_migrate/f8dac1342aee0b40a0f652ee716e79a3.png)
程序清单14.16,func_ptr.c:
// func_ptr.c -- 使用函数指针
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define LEN 81
char * s_gets(char * st, int n);
char showmenu(void);
void eatline(void); // 读取至行末尾
void show(void (*fp) (char *), char * str);
void ToUpper(char *); // 把字符串转换为大写
void ToLower(char *); // 把字符串转换为小写
void Transpose(char *); // 大小写转置
void Dummy(char *); // 不更改字符串
int main(void)
{
char line[LEN];
char copy[LEN];
char choice;
void (*pfun) (char *); //函数指针
puts("Enter a string (empty line to quit):");
while (s_gets(line, LEN) != NULL && line[0] != '\0')
{
while ((choice = showmenu()) != 'n')
{
switch (choice)
{
case 'u': pfun = ToUpper; break;
case 'l': pfun = ToLower; break;
case 't': pfun = Transpose; break;
case 'o': pfun = Dummy; break;
}
strcpy(copy, line); //让原始数据不动,操作备份数据即copy
show(pfun, copy);
}
puts("Enter a string (empty line to quit):");
}
puts("Bye!");
return 0;
}
char showmenu(void)
{
char ans;
puts("Enter menu choice:");
puts("u) uppercase 1) lowercase");
puts("t) tansepose case o) original case");
puts("n) next string");
ans = getchar();
ans = tolower(ans);
eatline();
while (strchr("ulton", ans) == NULL)
{
puts("Please enter a u, l, t, o, or n:");
ans = tolower(getchar());
eatline();
}
return ans;
}
void eatline(void)
{
while (getchar() != '\n')
continue;
}
void ToUpper(char * str)
{
while (*str)
{
*str = toupper(*str);
str++;
}
}
void ToLower(char * str)
{
while (*str)
{
*str = tolower(*str);
str++;
}
}
void Transpose(char * str)
{
while (*str)
{
if (islower(*str))
*str = toupper(*str);
else if (isupper(*str))
*str = tolower(*str);
str++;
}
}
void Dummy(char * str)
{
*str = *str;
}
void show(void (*fp) (char *), char * str)
{
(*fp)(str);
//fp(str); 也可直接操作,理解为函数名表地址
puts(str);
}
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) //如果地址不为NULL
*find = '\0'; // 在此处放置一个空字符
else
while (getchar() != '\n') // 处理多余字符
continue;
}
return ret_val;
}
输出结果:
![](https://i-blog.csdnimg.cn/blog_migrate/6670a5f87c95306453965b0e55ca43c5.png)
编程练习
![](https://i-blog.csdnimg.cn/blog_migrate/faa2444b1f49a4365b18c87d5fb93644.jpeg)
![](https://i-blog.csdnimg.cn/blog_migrate/cc46795154fc044c445ddd3f9bfa56b4.jpeg)
![](https://i-blog.csdnimg.cn/blog_migrate/20588e1506bf9116e3e483af0c4d69b7.jpeg)
题目1,方法:重新编写复习题5。示例代码14_1.c:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define LEN 12
typedef struct {
char name[10];
char abbrev[4];
int days;
int monumb;
} MONTH;
const MONTH months[LEN] =
{
{"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 days(char *); // 获取指定月份及之前的所有天数
int main(void)
{
int daynum;
char mname[LEN];
printf("Please enter the name of the month(q to quit): ");
while (scanf("%11s", mname) == 1 && mname[0] != 'q')
{
daynum = days(mname);
if (daynum > 0)
printf("Totally %d days.\n", daynum);
else
printf("%s is not a valid month.\n", mname);
printf("You can enter again: ");
while (getchar() != '\n')
continue;
}
printf("Done!\n");
return 0;
}
int days(char * str)
{
int i = 0;
int total = 0;
str[0] = toupper(str[0]); //首字母大写
while (*(str + ++i)) //其他字母小写
*(str + i) = tolower(*(str + i));
for (i = 0; i < LEN; i++)
if (0 == strcmp(months[i].name, str))
return total + months[i].days;
else
total += months[i].days;
return -1;
}
输出结果:
![](https://i-blog.csdnimg.cn/blog_migrate/7f2bb792e705c666f47e60ed54e06a0e.png)
题目2,方法:获取该年到指定日期(包括该日期)的天数。示例代码14_2.c:
#include <stdio.h>
#include <string.h> //提供 strcmp() 函数
#include <ctype.h> //提供 toupper() 函数
#include <stdbool.h> //提供 bool 类型
#include <stdlib.h> // 提供 atoi() 函数
#define LEN 12
typedef struct {
char name[10];
char abbrev[4];
int days;
int monumb;
} MONTH;
typedef struct {
int year;
char mname[LEN];
int day;
} DATE;
bool is_leap_year(int);
int days(DATE *, MONTH *);
int main(void)
{
int daynum; //总天数
DATE dates; //日期
MONTH months[LEN] = {
{ "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 }
};
printf("Please enter the year, month, day: ");
while (scanf("%d%11s%d", &dates.year, dates.mname, &dates.day) == 3)
{
if ((daynum = days(&dates, months)) >= 0)
printf("Totally %d days.\n", daynum);
else
printf("Illigal input.\n");
(months + 1)->days = 28; // 重置为非闰年 2 月份的天数
printf("You can enter the year , month, day again: ");
}
return 0;
}
bool is_leap_year(int n)
{
if ((n % 4 == 0 && n % 100 != 0) || n % 400 == 0)
return true;
else
return false;
}
int days(DATE * pd, MONTH * pm)
{
int is_num = 1, i = 0, total = 0;
if (is_leap_year(pd->year)) //判断是否闰年
(pm + 1)->days = 29; //闰年则更改 2 月份的天数,也可考虑传递结构参数不传递指针
is_num = atoi(pd->mname); //尝试转换为数字,不成功则返回 0
if (!is_num) //非数字转换
{
*(pd->mname) = toupper(*(pd->mname)); //首字母大写
while (*(pd->mname + ++i)) //其他字母小写
*(pd->mname + i) = tolower(*(pd->mname + i));
}
for (i = 0; i < LEN; i++)
if (strcmp((pm + i)->name, pd->mname) == 0
|| strcmp((pm + i)->abbrev, pd->mname) == 0 ||
is_num == (pm + i)->monumb)
if (pd->day > (pm + i)->days)
return -1;
else
return total + pd->day;
else
total += (pm + i)->days;
return -1;
}
输出结果:
![](https://i-blog.csdnimg.cn/blog_migrate/69fb7cf449d6b812fe8e83fb83c251f0.png)
题目3,方法1:按要求修改程序清单14.3。示例代码14_3.c:
#include <stdio.h>
#include <string.h>
#define MAXTITL 40
#define MAXAUTL 40
#define MAXBKS 100
typedef struct{
char title[MAXTITL];
char author[MAXAUTL];
float value;
} BOOK;
char * s_gets(char * st, int n);
void sort_title(BOOK **, int);
void sort_price(BOOK **, int);
typedef void (* pfun)(BOOK **, int); //函数指针
void sort_func(pfun fp, BOOK **, int); //包含函数指针的函数
pfun fun[2] = { sort_title, sort_price }; //函数指针数组
int main(void)
{
BOOK library[MAXBKS];
BOOK * book[MAXBKS]; // 指针数组
int count = 0;
int index;
printf("Please enter the book title.\n");
printf("Press [enter] at the start of a line to stop.\n");
while (count < MAXBKS && s_gets(library[count].title, MAXTITL) != NULL && library[count].title[0] != '\0')
{
printf("Now enter the author.\n");
s_gets(library[count].author, MAXAUTL);
printf("Now enter the value.\n");
book[count] = &library[count]; // 保存地址以备用
scanf("%f", &library[count++].value);
while (getchar() != '\n')
continue;
if (count < MAXBKS)
printf("Enter the next title.\n");
}
if (count > 0)
{
printf("Here is the original list of your books:\n");
for (index = 0; index < count; index++)
printf("%s by %s: $%.2f\n", library[index].title, library[index].author, library[index].value);
printf("Here is the list ordered by title:\n");
sort_func(fun[0], book, count);
for (index = 0; index < count; index++)
printf("%s by %s: $%.2f\n", book[index]->title, book[index]->author, book[index]->value);
printf("Here is the list ordered by price:\n");
sort_func(fun[1], book, count);
for (index = 0; index < count; index++)
printf("%s by %s: $%.2f\n", book[index]->title, book[index]->author, book[index]->value);
}
else
printf("No books? Too bad.\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) //如果地址不为NULL
*find = '\0'; // 在此处放置一个空字符
else
while (getchar() != '\n') // 处理多余字符
continue;
}
return ret_val;
}
void sort_title(BOOK ** pb, int n)
{
int i, j;
BOOK * temp;
for (i = 0; i < n - 1; i++) // 冒泡排序
for (j = i + 1; j < n; j++)
if (strcmp((*(pb + i))->title, (*(pb + j))->title) > 0) // ASCII 码升序,交换地址
{
temp = *(pb + i);
*(pb + i) = *(pb + j);
*(pb + j) = temp;
}
}
void sort_price(BOOK ** pb, int n)
{
int i, j;
BOOK * temp;
for (i = 0; i < n - 1; i++) // 冒泡排序
for (j = i + 1; j < n; j++)
if ((*(pb + i))->value > (*(pb + j))->value) //价格升序,交换地址
{
temp = *(pb + i);
*(pb + i) = *(pb + j);
*(pb + j) = temp;
}
}
void sort_func(pfun fp, BOOK ** pb, int n)
{
fp(pb, n);
}
输出结果:
![](https://i-blog.csdnimg.cn/blog_migrate/2e64f9826fd89da407427e37f0c1d6cc.png)
方法2,示例代码14_3_2.c:
#include <stdio.h> // ->的优先级高于 *,因此要加括号
#include <string.h> //变量(左值)才能被赋值
#define MAXTITL 40
#define MAXAUTL 40
#define MAXBKS 100
typedef struct{
char title[MAXTITL];
char author[MAXAUTL];
float value;
} BOOK;
char * s_gets(char * st, int n);
void sort(BOOK **, int, int);
int main(void)
{
BOOK library[MAXBKS];
BOOK * book[MAXBKS];
int count = 0;
int index;
printf("Please enter the book title.\n");
printf("Press [enter] at the start of a line to stop.\n");
while (count < MAXBKS && s_gets(library[count].title, MAXTITL) != NULL && library[count].title[0] != '\0')
{
printf("Now enter the author.\n");
s_gets(library[count].author, MAXAUTL);
printf("Now enter the value.\n");
book[count] = &library[count];
scanf("%f", &library[count++].value);
while (getchar() != '\n')
continue;
if (count < MAXBKS)
printf("Enter the next title.\n");
}
if (count > 0)
{
printf("Here is the original list of your books:\n");
for (index = 0; index < count; index++)
printf("%s by %s: $%.2f\n", library[index].title, library[index].author, library[index].value);
printf("Here is the list ordered by title:\n");
sort(book, count, 1);
for (index = 0; index < count; index++)
printf("%s by %s: $%.2f\n", book[index]->title, book[index]->author, book[index]->value);
printf("Here is the list ordered by price:\n");
sort(book, count, 2);
for (index = 0; index < count; index++)
printf("%s by %s: $%.2f\n", book[index]->title, book[index]->author, book[index]->value);
}
else
printf("No books? Too bad.\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) //如果地址不为NULL
*find = '\0'; // 在此处放置一个空字符
else
while (getchar() != '\n') // 处理多余字符
continue;
}
return ret_val;
}
void sort(BOOK ** pb, int n, int type)
{
int i, j;
BOOK * temp;
for (i = 0; i < n - 1; i++)
for (j = i + 1; j < n; j++)
if (type == 1)
{
if (strcmp((*(pb + i))->title, (*(pb + j))->title) > 0) // ASCII 码升序,交换地址
{
temp = *(pb + i);
*(pb + i) = *(pb + j);
*(pb + j) = temp;
}
}
else
if ((*(pb + i))->value > (*(pb + j))->value) //价格升序,交换地址
{
temp = *(pb + i);
*(pb + i) = *(pb + j);
*(pb + j) = temp;
}
}
题目4,方法:根据要求打印结构信息。示例代码14_4_a.c:
#include <stdio.h>
#include <string.h>
#define N 5
#define LEN 30
typedef struct {
char fname[LEN];
char mname[LEN];
char lname[LEN];
} NAME;
typedef struct {
char insnum[LEN];
NAME name;
} ID;
void show_id(ID *, int);
int main(void)
{
ID id[5] = {
{ "3021248", { "Jony", "Gds", "Fdi" } },
{ "3032427", { "Marry", "Fd", "Sdf" } },
{ "3023132", { "Caffd", "", "Dferw" } },
{ "3032432", { "David", "Daf", "Caff" } },
{ "3043254", { "Sally", "", "Jdafd" } }
};
show_id(id, N);
return 0;
}
void show_id(ID * pd, int n)
{
int i;
printf("The ID information:\n");
for (i = 0; i < n; i++)
if (*(pd + i)->name.mname != '\0')
printf("%s, %s %c. -- %s\n", (pd + i)->name.fname, (pd + i)->name.lname, *(pd + i)->name.mname, (pd + i)->insnum);
else
printf("%s, %s -- %s\n", (pd + i)->name.fname, (pd + i)->name.lname, (pd + i)->insnum);
}
输出结果:
![](https://i-blog.csdnimg.cn/blog_migrate/f6bf21b64901479d2cbb7b8f97956dfd.png)
14_4_b.c:
#include <stdio.h>
#include <string.h>
#define N 5
#define LEN 30
typedef struct {
char fname[LEN];
char mname[LEN];
char lname[LEN];
} NAME;
typedef struct {
char insnum[LEN];
NAME name;
} ID;
void show_id(ID);
int main(void)
{
int i;
ID id[5] = {
{ "3021248", { "Jony", "Gds", "Fdi" } },
{ "3032427", { "Marry", "Fd", "Sdf" } },
{ "3023132", { "Caffd", "", "Dferw" } },
{ "3032432", { "David", "Daf", "Caff" } },
{ "3043254", { "Sally", "", "Jdafd" } }
};
printf("The ID information:\n");
for (i = 0; i < N; i++)
show_id(id[i]);
return 0;
}
void show_id(ID pd)
{
if (*pd.name.mname != '\0')
printf("%s, %s %c. -- %s\n", pd.name.fname, pd.name.lname, *pd.name.mname, pd.insnum);
else
printf("%s, %s -- %s\n", pd.name.fname, pd.name.lname, pd.insnum);
}
输出结果:
![](https://i-blog.csdnimg.cn/blog_migrate/dfcb3b2848ea028d129f042c2f63aef0.png)
题目5,方法:按要求处理结构数据。示例代码14_5.c:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h>
#define CSIZE 4
#define LEN 30
#define N 3
typedef struct {
char fname[LEN];
char lname[LEN];
} NAME;
typedef struct {
NAME name;
float grade[N];
float average;
} STUDENT;
void get_score(STUDENT *, int);
void ave(STUDENT *, int);
void show_info(STUDENT *, int);
void show_class(STUDENT *, int);
void eatline(void);
int main(void)
{
STUDENT student[CSIZE] = {
{ { "Marry", "Kaily" }, { 0.0 , 0.0, 0.0 }, 0.0 },
{ { "Jony", "Farry" }, { 0.0 , 0.0, 0.0 }, 0.0 },
{ { "Sailly", "Lay" }, { 0.0 , 0.0, 0.0 }, 0.0 },
{ { "Pony", "Yummy" }, { 0.0 , 0.0, 0.0 }, 0.0 }
};
get_score(student, CSIZE);
ave(student, CSIZE);
show_info(student, CSIZE);
show_class(student, CSIZE);
return 0;
}
void get_score(STUDENT * ps, int n)
{
char f_name[LEN], l_name[LEN];
int i;
bool is_con = true, is_found = false;
char choice;
while (is_con)
{
puts("Please enter the name:");
scanf("%s%s", f_name, l_name);
eatline();
for (i = 0; i < n; i++)
if (strcmp(f_name, (ps + i)->name.fname) == 0 && strcmp(l_name, (ps + i)->name.lname) == 0)
{
puts("Please enter three scores:");
while (scanf("%f%f%f", &(ps + i)->grade[0], &(ps + i)->grade[1], &(ps + i)->grade[2]) != 3)
{
printf("Illigal input, try again: ");
eatline();
}
is_found = true;
eatline();
printf("Entered.\n");
break;
}
if (!is_found)
puts("No found!");
printf("Continue to enter(y/n)?");
if ((choice = getchar()) == 'n')
is_con = false;
if (choice != '\n')
eatline();
is_found = false;
}
}
void ave(STUDENT * ps, int n)
{
int i, j;
float fnum = 0.0;
for (i = 0; i < n; i++)
{
for (j = 0; j < N; j++)
fnum += ps[i].grade[j];
(ps + i)->average = fnum / N;
fnum = 0.0;
}
}
void show_info(STUDENT * ps, int n)
{
int i, j;
for (i = 0; i < n; i++)
{
printf("\nName: %s %s\n", (ps + i)->name.fname, (ps + i)->name.lname);
for (j = 0; j < N; j++)
printf("Score %d: %.2f\n", j + 1, (ps + i)->grade[j]);
printf("Average: %.2f\n", (ps + i)->average);
}
}
void show_class(STUDENT * ps, int n)
{
int i;
float class_ave = 0.0;
for (i = 0; i < n; i++)
class_ave += (ps + i)->average;
printf("\nClass Average: %.2f\n", class_ave / CSIZE);
}
void eatline(void)
{
while (getchar() != '\n')
continue;
}
输出结果:
![](https://i-blog.csdnimg.cn/blog_migrate/a995417b71691f551426fb6e0786e5c7.png)
题目6,方法:按要求计算和存储结构信息。示例代码14_6.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LEN 20
typedef struct {
int id;
char fname[LEN];
char lname[LEN];
int stage;
int hit;
int base;
int rbi;
float hit_rate;
} TEAM;
void record_info(TEAM *, FILE *, int);
int main(void)
{
static TEAM team[LEN]; //静态变量自动初始化为 0
FILE * fp;
if ((fp = fopen("team.txt","r")) == NULL)
{
fprintf(stderr, "Can not open %s.\n", "team.txt");
exit(EXIT_FAILURE);
}
record_info(team, fp, LEN);
if (fclose(fp) != 0)
{
fprintf(stderr, "Can not close %s.\n", "team.txt");
exit(EXIT_FAILURE);
}
return 0;
}
void record_info(TEAM * pt, FILE * pf, int n)
{
int count = 0; //不同球员计数
int ids; //存储读入的id
char fn[LEN], ln[LEN];
int stage_n, hit_n, base_n, rbi_n;
int i;
while (fscanf(pf, "%d%20s%20s%d%d%d%d", &ids, fn, ln, &stage_n, &hit_n, &base_n, &rbi_n) == 7 && count < n)
{
if((pt + ids)->stage == 0) //录入一个新的球员身份信息并更新数据
{
count++;
(pt + ids)->id = ids;
strcpy((pt + ids)->fname, fn);
strcpy((pt + ids)->lname, ln);
}
(pt + ids)->stage += stage_n;
(pt + ids)->hit += hit_n;
(pt + ids)->base += base_n;
(pt + ids)->rbi += rbi_n;
}
if (count > 0)
for (i = 0; i < n; i++)
{
if ((pt + i)->stage != 0)
{
(pt + i)->hit_rate = (float) (pt + i)->hit / (pt + i)->stage;
printf("Id: %d Name: %s %s ",(pt + i)->id, (pt + i)->fname, (pt + i)->lname);
printf("Stage: %d Hit: %d Base: %d Rbi: %d ", (pt + i)->stage, (pt + i)->hit, (pt + i)->base, (pt + i)->rbi);
printf("Hit_rate: %.2f\n", (pt + i)->hit_rate);
}
}
else
puts("No data!");
}
team.txt:
0 Jessie Joybat 5 2 1 1
1 Mary Json 6 3 7 9
2 Filp Shell 5 3 6 1
9 Francy Card 9 6 1 2
4 Wan cary 8 5 2 1
11 Keassy Coffee 3 3 6 7
0 Jessie Joybat 7 9 8 2
11 Keassy Coffee 4 7 5 8
输出结果:
![](https://i-blog.csdnimg.cn/blog_migrate/72e464fee06c4cdee0f75543bb2ae01d.png)
题目7,方法:按要求改写程序清单14.14。该项目包含两个头文件和三个源文件。
check.h:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h>
#include <stdlib.h>
#define WRONG 100
void wait(void);//暂停打印提示信息
void consumer(char *, int *);//清空缓冲区并保存清空的字符
bool character_check(char *, int *); //检测是否有非空字符并清空第一个非空字符及之前的缓冲区
char choose_check(int, char *, void (*)(void)); //将输入限制在合法区间并返回输入值
void show_menu1(void); //打印一级菜单
void show_menu2(void); //打印二级菜单
void dummy(void);
check.c:
#include "check.h"
void show_menu1(void)
{
printf("****************************************\n");
printf("Please choose the operation:\n");
printf("s. Showinfo a. Add\n");
printf("m. Modify d. Delete\n");
printf("q. Quit\n\n");
}
void show_menu2(void)
{
printf("****************************************\n");
printf("Please choose the modify section:\n");
printf("t. Title a. Author\n");
printf("v. Value q. Quit\n\n");
}
void dummy(void)
{
}
void wait(void)
{
char ch;
printf("Enter to continue...");
while ((ch = getchar()) != '\n')
continue;
//system("cls");
}
void consumer(char * wrong, int * n)
{
char cha;
while ((cha = getchar()) != '\n')
*(wrong + (*n)++) = cha;
}
bool character_check(char * wrong, int * n)
{
char ch2;
while ((ch2 = getchar()) != '\n') //第一个非空字符为回车,则读走回车
{
*(wrong + (*n)++) = ch2;
if (ch2 != '\t' && ch2 != ' ') //若第一个非空字符非回车,回车不被读走
return true;
}
return false;
}
char choose_check(int n, char * str, void (*pfun) (void))
{
char ch1;
char notice[n];
int num = 1;
int * count = #
pfun();
printf("Enter a character to choose: ");
//防止第一个非空合法字符后出现第二个非空字符,例如assss
while (strchr(str, (ch1 = tolower(getchar()))) == NULL || character_check(notice, count) == true)
{
if (ch1 == ' ' || ch1 == '\n' || ch1 == '\t') // 使至少第一个非空字符被ch1获得
continue;
else if (character_check(notice, count) == true) //防止出现 assss 这样的输入,即之前非法,之后合法,以及清空非空白字符缓冲区
consumer(notice, count); //输入a2时判断返回false,不执行此步(此时所有字符包括回车均已被读走)
*notice = ch1;
printf("%s is illegal, try again: ", notice);
memset(notice, 0 ,sizeof(notice)); //初始化字符串数组
num = 1; //重置计数
}
return ch1;
}
book.h:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#define LEN 10
#define MAXTITL 40
#define MAXAUTL 40
#define MAXBKS 10
typedef struct {
int booknum; //书本编号
char title[MAXTITL]; //书名
char author[MAXAUTL]; //作者
float value; //价格
bool deleted; //是否被删除
} BOOK;
int show_book(char *, int); //显示当前书本信息
void add_book(char *, int); //添加书本
void modify_book(char *, int); //修改书本信息
void dele_book(char *, int); //删除书本信息
char * s_gets(char * st, int n);
book.c:
#include "book.h"
#include "check.h"
int show_book(char * fname, int n)
{
FILE * fp;
BOOK books[n];
int size = sizeof(BOOK);
int count = 0;
if ((fp = fopen(fname, "r")) == NULL)
{
fprintf(stderr, "Can not open %s.\n", fname);
exit(EXIT_FAILURE);
}
while (count < n && fread(&books[count], size, 1, fp) == 1) //从文件中读入一块数据
{
if (count == 0)
printf("Current contens of %s:\n", fname);
if (books[count].deleted == true)
printf("BookNum : %d %s by %s: $%.2f\n", books[count].booknum, books[count].title, books[count].author, books[count].value);
count++;
}
if (fclose(fp) != 0)
{
fputs("Can not close file.\n", stderr);
exit(EXIT_FAILURE);
}
return count;
}
void add_book(char * fname, int n)
{
FILE * fp;
static BOOK books[MAXBKS]; //静态变量自动初始化
int size = sizeof(BOOK);
int count = 0;
int num;
int total = 0; // 统计当前文件多少本书
int i;
show_book(fname, n);
if ((fp = fopen(fname, "r+b")) == NULL)
{
fputs("Can't open book.dat file\n", stderr);
exit(EXIT_FAILURE);
}
rewind(fp); //回到文件开始便于计数
while (count < n && fread(&books[count], size, 1, fp) == 1) // 从文件读入到数组中
count++;
for (i = 0; i < n; i++) // 统计当前书本数
if (books[i].deleted == true)
total++;
if (total == n) // 如果已经满了
{
fputs("The book.dat file is full.", stderr);
exit(2);
}
for (i = 0; i < n; i++)
if (books[i].deleted == false) // 找到第一个可用位置
{
num = i;
break;
}
puts("Please add new book title.");
puts("Press [enter] at the start of a line to stop.");
while (s_gets(books[num].title, MAXTITL) != NULL && books[num].title[0] != '\0')
{
books[num].booknum = num;
puts("Now enter the author.");
s_gets(books[num].author, MAXAUTL);
puts("Now enter the value.");
scanf("%f", &books[num].value);
books[num].deleted = true;
total++;
while (getchar() != '\n')
continue;
if (total < n)
puts("Enter the next title.");
else
break;
for (i = 0; i < n; i++)
if (books[i].deleted == false) // 找到第一个可用位置
{
num = i;
break;
}
}
rewind(fp);
fwrite(books, size, MAXBKS, fp);
if (fclose(fp) != 0)
{
fputs("Can not close file.\n", stderr);
exit(EXIT_FAILURE);
}
puts("Saved!");
}
void modify_book(char * fname, int n)
{
char choose;
int num, count = 0;
FILE * fp;
static BOOK books[MAXBKS];
int size = sizeof(BOOK);
system("cls");
show_book(fname, n); // range = 可用于限制输入编号范围
if ((fp = fopen(fname, "r+b")) == NULL)
{
fprintf(stderr, "Can not open %s.\n", fname);
exit(EXIT_FAILURE);
}
while (count < n && fread(&books[count], size, 1, fp) == 1)
count++;
while ((choose = choose_check(WRONG, "tavq", show_menu2)) != 'q')
{
printf("Please input the num: ");
scanf("%d", &num);
while (getchar() != '\n')
continue;
switch (choose)
{
case 't':
printf("Please enter the new title: ");
s_gets(books[num].title, MAXTITL);
break;
case 'a':
printf("Please enter the new author: ");
s_gets(books[num].author, MAXTITL);
break;
case 'v':
printf("Please enter the new value: ");
scanf("%f", &books[num].value);
break;
case 'q':
break;
}
rewind(fp);
fseek(fp, num * size, SEEK_SET);
fwrite(&books[num], size, 1, fp);
if (fclose(fp) != 0)
{
fputs("Can not close file.\n", stderr);
exit(EXIT_FAILURE);
}
system("cls");
show_book(fname, n);
printf("Saved!\n");
if ((fp = fopen(fname, "r+b")) == NULL)
{
fprintf(stderr, "Can not open %s.\n", fname);
exit(EXIT_FAILURE);
}
}
if (fclose(fp) != 0)
{
fputs("Can not close file.\n", stderr);
exit(EXIT_FAILURE);
}
}
void dele_book(char * fname, int n)
{
int num, count = 0;
FILE * fp;
static BOOK books[MAXBKS];
int size = sizeof(BOOK);
system("cls");
show_book(fname, n); // range = 可用于限制输入编号范围
if ((fp = fopen(fname, "r+b")) == NULL)
{
fprintf(stderr, "Can not open %s.\n", fname);
exit(EXIT_FAILURE);
}
while (count < n && fread(&books[count], size, 1, fp) == 1)
count++;
printf("Please input the num(q to quit): ");
while (scanf("%d", &num) == 1)
{
while (getchar() != '\n')
continue;
books[num].deleted = false;
rewind(fp);
fseek(fp, num * size, SEEK_SET);
fwrite(&books[num], size, 1, fp);
if (fclose(fp) != 0)
{
fputs("Can not close file.\n", stderr);
exit(EXIT_FAILURE);
}
system("cls");
show_book(fname, n);
printf("Saved!\n");
if ((fp = fopen(fname, "r+b")) == NULL)
{
fprintf(stderr, "Can not open %s.\n", fname);
exit(EXIT_FAILURE);
}
printf("Please input the num(q to quit): ");
}
while (getchar() != '\n')
continue;
if (fclose(fp) != 0)
{
fputs("Can not close file.\n", stderr);
exit(EXIT_FAILURE);
}
}
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) //如果地址不为NULL
*find = '\0'; // 在此处放置一个空字符
else
while (getchar() != '\n') // 处理多余字符
continue;
}
return ret_val;
}
main.c:
#include <stdio.h>
#include "book.h"
#include "check.h"
int main(void)
{
char data_file[LEN] = "book.dat"; // 保存书本文件
char choose; // 保存一级菜单选项
while ((choose = choose_check(WRONG, "sdamq", show_menu1)) != 'q')
{
switch (choose)
{
case 's':
show_book(data_file, MAXBKS);
wait();
break;
case 'a':
add_book(data_file, MAXBKS);
wait();
break;
case 'm':
modify_book(data_file, MAXBKS);
break;
case 'd':
dele_book(data_file, MAXBKS);
break;
case 'q':
break;
}
system("cls");
}
return 0;
}
输出结果:
![](https://i-blog.csdnimg.cn/blog_migrate/dbc1c3f5a66bd5a5b090c99ba75dd7e1.png)
题目8,方法:按照要求将数据从文件读入结构体。
check.h:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h>
#include <stdlib.h>
#define WRONG 100
void wait(void); // 暂停打印提示信息
void consumer(char *, int *); // 清空缓冲区并保存清空的字符
bool character_check(char *, int *); // 检测是否有非空字符并清空第一个非空字符及之前的缓冲区
char choose_check(int, char *, void (*)(void)); // 将输入限制在合法区间并返回输入值
void show_menu(void); // 打印一级菜单
void dummy(void); // 无操作
check.c:
#include "check.h"
void show_menu(void)
{
puts("****************************************");
puts("To choose a function, enter lts letter lable:");
puts("a) Show number of empty seats");
puts("b) Show list of empty seats");
puts("c) Show alphabetical list of seats");
puts("d) Assign a customer to a seats");
puts("e) Delete a seat assignment");
puts("f) Quit");
}
void dummy(void)
{
}
void wait(void)
{
char ch;
printf("Enter to continue...");
while ((ch = getchar()) != '\n')
continue;
}
void consumer(char * wrong, int * n)
{
char cha;
while ((cha = getchar()) != '\n')
*(wrong + (*n)++) = cha;
}
bool character_check(char * wrong, int * n)
{
char ch2;
while ((ch2 = getchar()) != '\n') // 第一个非空字符为回车,则读走回车
{
*(wrong + (*n)++) = ch2;
if (ch2 != '\t' && ch2 != ' ') // 若第一个非空字符非回车,回车不被读走
return true;
}
return false;
}
char choose_check(int n, char * str, void (*pfun) (void))
{
char ch1;
char notice[n];
int num = 1;
int * count = #
pfun();
printf("Enter a character to choose: ");
// 防止第一个非空合法字符后出现第二个非空字符,例如assss
while (strchr(str, (ch1 = tolower(getchar()))) == NULL || character_check(notice, count) == true)
{
if (ch1 == ' ' || ch1 == '\n' || ch1 == '\t') // 使至少第一个非空字符被ch1获得
continue;
else if (character_check(notice, count) == true) // 防止出现 assss 这样的输入,即之前非法,之后合法,以及清空非空白字符缓冲区
consumer(notice, count); // 输入a2时判断返回false,不执行此步(此时所有字符包括回车均已被读走)
*notice = ch1;
printf("%s is illegal, try again: ", notice);
memset(notice, 0 ,sizeof(notice)); // 初始化字符串数组
num = 1; // 重置计数
}
return ch1;
}
airplan.h:
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
#include <ctype.h>
#define LEN 20
#define N 12
typedef struct {
char seat_id[LEN]; // 座位编号
bool marked; // 是否预定
char fname[LEN]; // 名
char lname[LEN]; // 姓
} SEAT;
void initiate(SEAT *, char *); // 初始化数据
int show_emnum(SEAT *, int); // 显示空座位的数量
void show_emlist(SEAT *, int); // 显示空座位列表
void show_alplist(SEAT *, int); // aplphabet 顺序输出座位列表
void assign_seat(SEAT *, char *, int); // 为一位客户分配座位
void delete_seat(SEAT *, char *, int); // 为一位客户取消座位
char * s_gets(char * st, int n);
void eatline(void);
airplan.c:
#include "airplan.h"
void initiate(SEAT * ps, char * data_file)
{
int i = 0;
int size = sizeof(SEAT);
FILE * fp;
if ((fp = fopen(data_file, "r+b")) == NULL) // 如果文件不存在,则初始化
{
if ((fp = fopen(data_file, "w+b")) == NULL)
{
fprintf(stderr, "Can not creat file %s.\n", data_file);
exit(EXIT_FAILURE);
}
SEAT seat[N] = {
{ "C01", false, "", "" },
{ "C02", false, "", "" },
{ "C03", false, "", "" },
{ "B01", false, "", "" },
{ "B02", false, "", "" },
{ "B03", false, "", "" },
{ "A01", false, "", "" },
{ "A02", false, "", "" },
{ "A03", false, "", "" },
{ "D01", false, "", "" },
{ "D02", false, "", "" },
{ "D03", false, "", "" },
};
fwrite(seat, size, N, fp);
if (fclose(fp) != 0)
{
fputs("Can not close file.\n", stderr);
exit(EXIT_FAILURE);
}
if ((fp = fopen(data_file, "r+b")) == NULL)
{
fputs("Can not open file.\n", stderr);
exit(EXIT_FAILURE);
}
}
while (i < N && fread(ps + i, size, 1, fp) == 1) // 将数据从文件中读入结构数组
i++;
if (fclose(fp) != 0)
{
fputs("Can not close file.\n", stderr);
exit(EXIT_FAILURE);
}
}
int show_emnum(SEAT * ps, int n)
{
int i, num = 0; // 空座位的数量
for (i = 0; i < n; i++)
if ((ps + i)->marked == false)
num++;
return num;
}
void show_emlist(SEAT * ps, int n)
{
int i, num = 0;
putchar('\n');
for (i = 0; i < n; i++)
if ((ps + i)->marked == false)
{
printf("%s ", (ps + i)->seat_id);
num++;
}
putchar('\n');
if (!num)
printf("No empty seat!\n");
}
void show_alplist(SEAT * ps, int n)
{
SEAT * alpha[n];
SEAT * temp;
int i, j;
for (i = 0; i < n; i++) //获取结构地址便于操作
alpha[i] = (ps + i);
for (i = 0; i < n - 1; i++)
for (j = i+ 1; j < n; j++)
if (strcmp(alpha[i]->seat_id, alpha[j]->seat_id) > 0)
{
temp = alpha[i];
alpha[i] = alpha[j];
alpha[j] = temp;
}
putchar('\n');
for (i = 0; i < n; i++)
printf("%s ", (*(alpha + i))->seat_id); // -> 的优先级高于 *,因此加括号
putchar('\n');
}
void assign_seat(SEAT * ps, char * fname, int n)
{
char seat[LEN];
int id = 0, em_num;
bool find = false;
int size = sizeof(SEAT);
FILE * fp;
em_num = show_emnum(ps, n);
if (em_num)
{
printf("\nEmpty seats:\n");
show_emlist(ps, n);
printf("Input the ID(empty to quit): ");
s_gets(seat, n);
*seat = toupper(*seat);
while (id < n)
{
if (strcmp(seat, (ps + id)->seat_id) == 0)
{
find = true;
break;
}
id++;
}
if (find && (ps + id)->marked == false) //防止输入已分配座位
{
printf("Please input first name: ");
s_gets((ps + id)->fname, n);
printf("Please input last name: ");
s_gets((ps + id)->lname, n);
(ps + id)->marked = true;
if ((fp = fopen(fname, "r+b")) == NULL)
{
fprintf(stderr, "Can not open %s.\n", fname);
exit(EXIT_FAILURE);
}
fseek(fp, id * size, SEEK_SET);
fwrite((ps + id), size, 1, fp);
if (fclose(fp) != 0)
{
fprintf(stderr, "Can not close file %s.\n", fname);
exit(EXIT_FAILURE);
}
printf("Saved!\n");
}
else
{
if (*seat != '\0')
printf("Not found!\n");
else
printf("Opraton canceled!\n");
}
}
else
printf("No empty seat!\n");
}
void delete_seat(SEAT * ps, char * fname, int n)
{
int i, count = 0, id = 0;
char seat[LEN];
bool find = false;
int size = sizeof(SEAT);
FILE * fp;
for (i = 0; i < n; i++)
if ((ps + i)->marked == true)
{
if (i == 0)
printf("\nAssigned seats: \n");
printf("Name: %s %s\n", (ps + i)->fname, (ps + i)->lname);
printf("ID: %s\n", (ps + i)->seat_id);
count++;
}
if (count)
{
printf("Input the ID to delete(empty to quit): ");
s_gets(seat, n);
*seat = toupper(*seat);
while (id < n)
{
if (strcmp(seat, (ps + id)->seat_id) == 0)
{
find = true;
break;
}
id++;
}
if (find && (ps + id)->marked == true) //防止输入未分配座位
{
(ps + id)->marked = false;
if ((fp = fopen(fname, "r+b")) == NULL)
{
fprintf(stderr, "Can not open %s.\n", fname);
exit(EXIT_FAILURE);
}
fseek(fp, id * size, SEEK_SET);
fwrite((ps + id), size, 1, fp);
if (fclose(fp) != 0)
{
fprintf(stderr, "Can not close file %s.\n", fname);
exit(EXIT_FAILURE);
}
printf("Saved!\n");
}
else
{
if (*seat != '\0')
printf("Not found!\n");
else
printf("Opraton canceled!\n");
}
}
else
puts("No assigned seat!\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) //如果地址不为NULL
*find = '\0'; // 在此处放置一个空字符
else
while (getchar() != '\n') // 处理多余字符
continue;
}
return ret_val;
}
void eatline(void)
{
while (getchar() != '\n')
continue;
}
输出结果:
![](https://i-blog.csdnimg.cn/blog_migrate/4de978d5221de3776e907f3d30c1f9f3.png)
题目9,方法:按照要求操作文件和结构体。与题目8类似,不过多了几个文件。该项目包括2个头文件及3个源文件。
check.h:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h>
#include <stdlib.h>
#define WRONG 100
void wait(void);//暂停打印提示信息
void consumer(char *, int *);//清空缓冲区并保存清空的字符
bool character_check(char *, int *); //检测是否有非空字符并清空第一个非空字符及之前的缓冲区
char choose_check(int, int, char *, void (*)(int)); //将输入限制在合法区间并返回输入值
void show_menu1(int); //打印一级菜单
void show_menu2(int); //打印二级菜单
check.c:
#include "check.h"
void show_menu1(int m)
{
puts("****************************************");
if (m)
puts("TOP MENU\n");
puts("To choose a airplan:");
puts("a) Flight 102");
puts("b) Flight 311");
puts("c) Flight 444");
puts("d) Flight 519");
puts("q) Quit");
}
void show_menu2(int num)
{
puts("****************************************");
printf("FLIGHT %d\n", num);
puts("To choose a function, enter lts letter lable:");
puts("a) Show number of empty seats");
puts("b) Show list of empty seats");
puts("c) Show alphabetical list of seats");
puts("d) Assign a customer to a seats");
puts("e) Delete a seat assignment");
puts("f) Show state of the flight");
puts("g) Quit");
}
void wait(void)
{
char ch;
printf("Enter to continue...");
while ((ch = getchar()) != '\n')
continue;
}
void consumer(char * wrong, int * n)
{
char cha;
while ((cha = getchar()) != '\n')
*(wrong + (*n)++) = cha;
}
bool character_check(char * wrong, int * n)
{
char ch2;
while ((ch2 = getchar()) != '\n') //第一个非空字符为回车,则读走回车
{
*(wrong + (*n)++) = ch2;
if (ch2 != '\t' && ch2 != ' ') //若第一个非空字符非回车,回车不被读走
return true;
}
return false;
}
char choose_check(int m, int n, char * str, void (*pfun) (int))
{
char ch1; // 转换小写后的第一个非空字符
char o_ch1; //保存原始第一个非空字符
char notice[n];
int num = 1;
int * count = #
pfun(m);
printf("Enter a character to choose: ");
// 防止第一个非空合法字符后出现第二个非空字符,例如assss
while (strchr(str, (ch1 = tolower(o_ch1 = getchar()))) == NULL || character_check(notice, count) == true)
{
if (ch1 == ' ' || ch1 == '\n' || ch1 == '\t') // 使至少第一个非空字符被ch1获得
continue;
else if (character_check(notice, count) == true) // 防止出现 assss 这样的输入,即之前非法,之后合法,以及清空非空白字符缓冲区
consumer(notice, count); // 输入a2时判断返回false,不执行此步(此时所有字符包括回车均已被读走)
*notice = o_ch1;
printf("%s is illegal, try again: ", notice);
memset(notice, 0 ,sizeof(notice)); // 初始化字符串数组
num = 1; // 重置计数
}
return ch1;
}
airplan.h:
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
#include <ctype.h>
#define LEN 20
#define N 12
typedef struct {
char seat_id[LEN]; // 座位编号
bool marked; // 是否预定
char fname[LEN]; // 名
char lname[LEN]; // 姓
} SEAT;
void initiate(SEAT *, char *, int); // 初始化数据
int show_emnum(SEAT *, int); // 显示空座位的数量
void show_emlist(SEAT *, int); // 显示空座位列表
void show_state(SEAT *, int); // 显示座位情况
void show_alplist(SEAT *, int); // aplphabet 顺序输出座位列表
void assign_seat(SEAT *, char *, int); // 为一位客户分配座位
void delete_seat(SEAT *, char *, int); // 为一位客户取消座位
char * s_gets(char * st, int n);
void eatline(void);
void second_menu(int, SEAT *, char *, int);
airplan.c:
#include "airplan.h"
#include "check.h"
void initiate(SEAT * ps, char * data_file, int n)
{
int i = 0;
int size = sizeof(SEAT);
FILE * fp;
if ((fp = fopen(data_file, "r+b")) == NULL) //如果文件不存在,则初始化
{
if ((fp = fopen(data_file, "w+b")) == NULL)
{
fprintf(stderr, "Can not creat file %s.\n", data_file);
exit(EXIT_FAILURE);
}
SEAT seat[N] = {
{ "C01", false, "", "" },
{ "C02", false, "", "" },
{ "C03", false, "", "" },
{ "B01", false, "", "" },
{ "B02", false, "", "" },
{ "B03", false, "", "" },
{ "A01", false, "", "" },
{ "A02", false, "", "" },
{ "A03", false, "", "" },
{ "D01", false, "", "" },
{ "D02", false, "", "" },
{ "D03", false, "", "" },
};
fwrite(seat, size, n, fp);
if (fclose(fp) != 0)
{
fputs("Can not close file.\n", stderr);
exit(EXIT_FAILURE);
}
if ((fp = fopen(data_file, "r+b")) == NULL)
{
fputs("Can not open file.\n", stderr);
exit(EXIT_FAILURE);
}
}
while (i < N && fread(ps + i, size, 1, fp) == 1) // 将数据从文件中读入结构数组
i++;
if (fclose(fp) != 0)
{
fputs("Can not close file.\n", stderr);
exit(EXIT_FAILURE);
}
}
int show_emnum(SEAT * ps, int n)
{
int i, num = 0; // 空座位的数量
for (i = 0; i < n; i++)
if ((ps + i)->marked == false)
num++;
return num;
}
void show_state(SEAT * ps, int n)
{
int i, num_empty = 0, num_full = 0;
putchar('\n');
for (i = 0; i < n; i++)
if ((ps + i)->marked == false)
{
if (num_empty == 0)
printf("\nEmpty seats: \n");
printf("%s ", (ps + i)->seat_id);
num_empty++;
}
putchar('\n');
if(!num_empty)
printf("No empty seat!\n");
else
printf("Totally %d empty seats.", num_empty);
putchar('\n');
for (i = 0; i < n; i++)
if ((ps + i)->marked == true)
{
if (num_full == 0)
printf("\nAssigned seats: \n");
printf("Name: %s %s\n", (ps + i)->fname, (ps + i)->lname);
printf("ID: %s\n", (ps + i)->seat_id);
num_full++;
}
if(!num_full)
printf("No assigned seat!\n");
else
printf("Totally %d full seats.", num_full);
putchar('\n');
}
void show_emlist(SEAT * ps, int n)
{
int i, num = 0;
putchar('\n');
for (i = 0; i < n; i++)
if ((ps + i)->marked == false)
{
printf("%s ", (ps + i)->seat_id);
num++;
}
putchar('\n');
if (!num)
printf("No empty seat!\n");
}
void show_alplist(SEAT * ps, int n)
{
SEAT * alpha[n];
SEAT * temp;
int i, j;
for (i = 0; i < n; i++) //获取结构地址便于操作
alpha[i] = (ps + i);
for (i = 0; i < n - 1; i++)
for (j = i+ 1; j < n; j++)
if (strcmp(alpha[i]->seat_id, alpha[j]->seat_id) > 0)
{
temp = alpha[i];
alpha[i] = alpha[j];
alpha[j] = temp;
}
putchar('\n');
for (i = 0; i < n; i++)
printf("%s ", (*(alpha + i))->seat_id); // -> 的优先级高于 *,因此加括号
putchar('\n');
}
void assign_seat(SEAT * ps, char * fname, int n)
{
char seat[LEN];
int id = 0, em_num;
bool find = false;
int size = sizeof(SEAT);
FILE * fp;
em_num = show_emnum(ps, n);
if (em_num)
{
printf("\nEmpty seats:\n");
show_emlist(ps, n);
printf("Input the ID(empty to quit): ");
s_gets(seat, n);
*seat = toupper(*seat);
while (id < n)
{
if (strcmp(seat, (ps + id)->seat_id) == 0)
{
find = true;
break;
}
id++;
}
if (find && (ps + id)->marked == false) //防止输入已分配座位
{
printf("Please input first name: ");
s_gets((ps + id)->fname, n);
printf("Please input last name: ");
s_gets((ps + id)->lname, n);
(ps + id)->marked = true;
if ((fp = fopen(fname, "r+b")) == NULL)
{
fprintf(stderr, "Can not open %s.\n", fname);
exit(EXIT_FAILURE);
}
fseek(fp, id * size, SEEK_SET);
fwrite((ps + id), size, 1, fp);
if (fclose(fp) != 0)
{
fprintf(stderr, "Can not close file %s.\n", fname);
exit(EXIT_FAILURE);
}
printf("Saved!\n");
}
else
{
if (*seat != '\0')
printf("Not found!\n");
else
printf("Operaton canceled!\n");
}
}
else
printf("No empty seat!\n");
}
void delete_seat(SEAT * ps, char * fname, int n)
{
int i, count = 0, id = 0;
char seat[LEN];
bool find = false;
int size = sizeof(SEAT);
FILE * fp;
for (i = 0; i < n; i++)
if ((ps + i)->marked == true)
{
if (i == 0)
printf("\nAssigned seats: \n");
printf("Name: %s %s\n", (ps + i)->fname, (ps + i)->lname);
printf("ID: %s\n", (ps + i)->seat_id);
count++;
}
if (count)
{
printf("Input the ID to delete(empty to quit): ");
s_gets(seat, n);
*seat = toupper(*seat);
while (id < n)
{
if (strcmp(seat, (ps + id)->seat_id) == 0)
{
find = true;
break;
}
id++;
}
if (find && (ps + id)->marked == true) //防止输入未分配座位
{
(ps + id)->marked = false;
if ((fp = fopen(fname, "r+b")) == NULL)
{
fprintf(stderr, "Can not open %s.\n", fname);
exit(EXIT_FAILURE);
}
fseek(fp, id * size, SEEK_SET);
fwrite((ps + id), size, 1, fp);
if (fclose(fp) != 0)
{
fprintf(stderr, "Can not close file %s.\n", fname);
exit(EXIT_FAILURE);
}
printf("Saved!\n");
}
else
{
if (*seat != '\0')
printf("Not found!\n");
else
printf("Operaton canceled!\n");
}
}
else
puts("No assigned seat!\n");
}
void second_menu(int num, SEAT * p, char * fname, int n)
{
char choose2;
while ((choose2 = choose_check(num, WRONG, "abcedfg", show_menu2)) != 'g')
{
switch (choose2)
{
case 'a':
printf("\nCurrently have %d of empty seats.\n", show_emnum(p, n));
wait();
break;
case 'b':
show_emlist(p, n);
wait();
break;
case 'c':
show_alplist(p, n);
wait();
break;
case 'd':
assign_seat(p, fname, n);
wait();
break;
case 'e':
delete_seat(p, fname, n);
wait();
break;
case 'f':
show_state(p, n);
wait();
break;
case 'g':
break;
}
system("cls");
}
}
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) //如果地址不为NULL
*find = '\0'; // 在此处放置一个空字符
else
while (getchar() != '\n') // 处理多余字符
continue;
}
return ret_val;
}
void eatline(void)
{
while (getchar() != '\n')
continue;
}
main.c:
#include "check.h"
#include "airplan.h"
int main(void)
{
char choose1; // 一级菜单
char filename1[LEN] = "flight1.dat";
char filename2[LEN] = "flight2.dat";
char filename3[LEN] = "flight3.dat";
char filename4[LEN] = "flight4.dat";
SEAT seats1[N];
SEAT seats2[N];
SEAT seats3[N];
SEAT seats4[N];
initiate(seats1, filename1, LEN);
initiate(seats2, filename2, LEN);
initiate(seats3, filename3, LEN);
initiate(seats4, filename4, LEN);
while ((choose1 = choose_check(1, WRONG, "abcdq", show_menu1)) != 'q')
{
system("cls");
switch (choose1)
{
case 'a':
second_menu(102, seats1, filename1, N);
break;
case 'b':
second_menu(311, seats2, filename2, N);
break;
case 'c':
second_menu(444, seats3, filename3, N);
break;
case 'd':
second_menu(519, seats4, filename4, N);
break;
case 'q':
break;
}
system("cls");
}
return 0;
}
输出结果:
![](https://i-blog.csdnimg.cn/blog_migrate/a28e068c8cb539a34f85c3419b395d75.png)
题目10,方法:通过函数指针数组实现菜单。函数指针在前两个项目中有所应用。该项目包括1个头文件和2个源文件。
check.h:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h>
#include <stdlib.h>
#define WRONG 100
typedef void (* pfunc)(void);
void wait(void); // Pause printing prompt
void consumer(char *, int *); // Empty the buffer and save the characters in the buffer
bool character_check(char *, int *); // Detect whether there are non null characters and clear the first non null character and the buffer before it
char choose_check(int, char *, pfunc); // Limit the input to the legal range and return the input value
void show_menu(void); // Print the first level menu
check.c:
#include "check.h"
void show_menu(void)
{
puts("****************************************");
puts("To choose a function:");
puts("a) Function 1");
puts("b) Function 2");
puts("q) Quit");
}
void wait(void)
{
char ch;
printf("Enter to continue...");
while ((ch = getchar()) != '\n')
continue;
}
void consumer(char * wrong, int * n)
{
char cha;
while ((cha = getchar()) != '\n')
*(wrong + (*n)++) = cha;
}
bool character_check(char * wrong, int * n)
{
char ch2;
while ((ch2 = getchar()) != '\n') // If the first non null character is a carriage return, read the carriage return
{
*(wrong + (*n)++) = ch2;
if (ch2 != '\t' && ch2 != ' ') // If the first non null character is not a carriage return character, the carriage return character will not be read away
return true;
}
return false;
}
char choose_check(int n, char * str, pfunc pfun)
{
char ch1; // Save the first non null character after converting to lowercase
char o_ch1; // Save the original first non null character
char notice[n];
int num = 1;
int * count = #
pfun();
printf("Enter a character to choose: ");
// Prevent the second non null character after the first non null legal character, such as assss
while (strchr(str, (ch1 = tolower(o_ch1 = getchar()))) == NULL || character_check(notice, count) == true)
{
if (ch1 == ' ' || ch1 == '\n' || ch1 == '\t') // Make at least the first non null character obtained by ch1
continue;
else if (character_check(notice, count) == true) // Prevent the occurrence of input such as assss, which is illegal before and legal after, and clear the non blank character buffer
consumer(notice, count); // When inputting a2, it is judged to return false, and this step is not executed (at this time, all characters including the Enter key have been read away)
*notice = o_ch1;
printf("%s is illegal, try again: ", notice);
memset(notice, 0 ,sizeof(notice)); // Initialize string array
num = 1; // Reset Count
}
return ch1;
}
main.c:
#include "check.h"
void func1(void);
void func2(void);
void show(pfunc);
int main(void)
{
char choose;
pfunc func[2] = { func1, func2 };
while ((choose = choose_check(WRONG, "abq", show_menu)) != 'q')
{
switch (choose)
{
case 'a':
show(func[0]);
wait();
break;
case 'b':
show(func[1]);
wait();
break;
case 'q':
break;
}
system("cls");
}
return 0;
}
void func1(void)
{
printf("I am Function 1\n");
}
void func2(void)
{
printf("I am Function 2\n");
}
void show(pfunc pf)
{
pf();
}
输出结果:
![](https://i-blog.csdnimg.cn/blog_migrate/9c4c29b57ed2111b5f7bb6c07c5f67bd.png)
题目11,方法:使用包含函数指针作为参数的函数。示例代码14_11.c:
#include <stdio.h>
#include <math.h>
#define N 4
#define LEN 5
#define MAX 10
typedef double (* pfun) (double);
double func1(double);
double func2(double);
void transform(const double [], double [], int, pfun);
void show_array(const double [], int);
int main(void)
{
pfun pf_array[N] = { cbrt, sqrt, func1, func2 };
char func_name[N][MAX] = { "cbrt", "sqrt", "func1", "func2" };
const double original[LEN] = { 1.0, 2.0, 3.0, 4.0, 5.0 };
double target[LEN] = { 0.0 };
int i;
printf("Original array:\n");
show_array(original, LEN);
printf("Target array:\n");
show_array(target, LEN);
for (i = 0; i < N; i++)
{
printf("After %s function, target array:\n", func_name[i]);
transform(original, target, LEN, pf_array[i]);
show_array(target, LEN);
}
return 0;
}
void show_array(const double arr[], int n)
{
int i;
for (i = 0; i < n; i++)
printf("%.2f ", arr[i]);
puts("\n");
}
void transform(const double orig[], double targ[], int n, pfun pf)
{
int i;
for (i = 0; i < n; i++)
targ[i] = pf(orig[i]);
}
double func1(double d_num)
{
return 2.0 * d_num;
}
double func2(double d_num)
{
return d_num + 10.0;
}
输出结果:
![](https://i-blog.csdnimg.cn/blog_migrate/ecdf9ecdc2cf981265ef28700dc11760.png)