c primer plus这本书第14章的课后练习,是写航班订票的代码。
用了2种代码。第一种,只用了pointer to function。测试是正常的。第二种,用了array of pointers to function。测试的时候,开始的时候正常,后来就乱了。找不到原因。能看一下吗?多谢。
正常的代码是:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
struct flight {
int seatid;
bool isassigned;
char name[40];
};
struct company {
int flightid;
struct flight handle[12];
};
int showcomenu(void);
char showmenu(void);
void shownumber(struct company *,int n);
void showlist(struct company *,int n);
void assignseat(struct company *,int n);
void deleteseat(struct company *,int n);
void showfunc(void (* ptf)(struct company *,int n),struct company *,int n);
void eatline(void);
char * s_gets(char *,int n);
int main()
{
FILE * fp;
struct company wanfeng[4];
void (* ptf)(struct company *,int n);
int choice1;
char choice2;
while ((choice1 = showcomenu()) != 5)
{
fp = fopen("flightbase.dat","r+b");
fread(wanfeng,sizeof(struct company),4,fp);
while ((choice2 = showmenu()) != 'q')
{
switch(choice2)
{
case 'a': ptf = shownumber;break;
case 'b': ptf = showlist;break;
case 'c': ptf = assignseat;break;
case 'd': ptf = deleteseat;break;
}
showfunc(ptf,wanfeng,choice1);
}
rewind(fp);
fwrite(wanfeng,sizeof(struct company),4,fp);
fclose(fp);
}
return 0;
}
int showcomenu(void)
{
puts("Please select a flight number:");
puts("1)101 2)202 3)303 4)404 5)quit.");
int choice1;
scanf("%d",&choice1);
eatline();
while (choice1 != 1 && choice1 != 2 && choice1 != 3 &&choice1 != 4 && choice1 != 5)
{
puts("Please enter an int between 1 and 5.");
scanf("%d",&choice1);
eatline();
}
return choice1;
}
char showmenu(void)
{
puts("To choose a function, enter its letter label:");
puts("a) show number of empty seats;");
puts("b) show list of empty seats;");
puts("c) assign a customer to a seat assignment;");
puts("d) delete a seat assignment;");
puts("q) quit.");
char ans;
ans = getchar();
eatline();
while (strchr("abcdq",ans) == NULL)
{
puts("Please enter a b c d q:");
ans = getchar();
eatline();
}
return ans;
}
void shownumber(struct company * pts,int n)
{
int count = 0;
for (int i = 0;i < 12;i++)
{
if (pts[n-1].handle[i].isassigned == false)
count++;
}
printf("There are %d empty seats in flight %d.\n",count,pts[n-1].flightid);
}
void showlist(struct company * pts,int n)
{
printf("The empty seats in flight %d are:\n",pts[n-1].flightid);
for (int i = 0;i < 12;i++)
{
if (pts[n-1].handle[i].isassigned == false)
printf("%d ",pts[n-1].handle[i].seatid);
}
putchar('\n');
}
void assignseat(struct company * pts,int n)
{
puts("Please enter a seat number:");
int num;
while (scanf("%d",&num) == 1&&pts[n-1].handle[num - 1].isassigned == true)
{
puts("The seat is occupied. Please enter another seat number:");
eatline();
}
eatline();
puts("Please enter your name:");
char line[40];
s_gets(line,40);
puts("Confirm the seat number(y or n)?");
char ch;
ch = getchar();
eatline();
if (ch == 'y' || ch == 'Y')
{
pts[n-1].handle[num - 1].isassigned = true;
strcpy(pts[n-1].handle[num - 1].name,line);
puts("The seat is saved for you.");
}
}
void deleteseat(struct company * pts,int n)
{
puts("Please enter your seat number:");
int num;
while (scanf("%d",&num) == 1 && pts[n-1].handle[num - 1].isassigned == false)
{
puts("The seat is empty.Please enter your correct seat number:");
eatline();
}
eatline();
puts("Are you sure to delete your seat (y or n)?");
char ch;
ch = getchar();
eatline();
if (ch == 'y' || ch == 'Y')
{
pts[n-1].handle[num - 1].isassigned = false;
}
}
void showfunc(void(* ptf)(struct company *,int n),struct company * pts,int n)
{
ptf(pts,n);
}
void eatline(void)
{
while(getchar() != '\n')
continue;
}
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 = '\0';
else
while (getchar() != '\n')
continue;
}
return ret_val;
}
以上代码测试是正常的。
以下是有问题的:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
struct flight {
int seatid;
bool isassigned;
char name[40];
};
struct company {
int flightid;
struct flight handle[12];
};
int showcomenu(void);
int showmenu(void);
void shownumber(struct company *,int n);
void showlist(struct company *,int n);
void assignseat(struct company *,int n);
void deleteseat(struct company *,int n);
void showfunc(void (* ptf)(struct company *,int n),struct company *,int n);
void eatline(void);
char * s_gets(char *,int n);
int main()
{
FILE * fp;
struct company wanfeng[4];
void ( * ptfarray[4])(struct company *,int n) = {shownumber,showlist,assignseat,deleteseat};
int choice1;
int choice2;
while ((choice1 = showcomenu()) != 5)
{
fp = fopen("flightbase.dat","r+b");
fread(wanfeng,sizeof(struct company),4,fp);
while ((choice2 = showmenu()) != 5)
showfunc(ptfarray[choice2 - 1],wanfeng,choice1);
rewind(fp);
fwrite(wanfeng,sizeof(struct company),4,fp);
fclose(fp);
}
return 0;
}
int showcomenu(void)
{
puts("Please select a flight number:");
puts("1)101 2)202 3)303 4)404 5)quit.");
int choice1;
scanf("%d",&choice1);
eatline();
while (choice1 != 1 && choice1 != 2 && choice1 != 3 &&choice1 != 4 && choice1 != 5)
{
puts("Please enter an int between 1 and 5.");
scanf("%d",&choice1);
eatline();
}
return choice1;
}
int showmenu(void)
{
puts("To choose a function, select one of the following numbers:");
puts("1) show number of empty seats;");
puts("2) show list of empty seats;");
puts("3) assign a customer to a seat assignment;");
puts("4) delete a seat assignment;");
puts("5) quit.");
int choice2;
scanf("%d",&choice2);
eatline();
while (choice2 != 1 && choice2 != 2 && choice2 != 3 &&choice2 != 4 && choice2 != 5)
{
puts("Please enter an int between 1 and 5.");
scanf("%d",&choice2);
eatline();
}
return choice2;
}
void shownumber(struct company * pts,int n)
{
int count = 0;
for (int i = 0;i < 12;i++)
{
if (pts[n-1].handle[i].isassigned == false)
count++;
}
printf("There are %d empty seats in flight %d.\n",count,pts[n-1].flightid);
}
void showlist(struct company * pts,int n)
{
printf("The empty seats in flight %d are:\n",pts[n-1].flightid);
for (int i = 0;i < 12;i++)
{
if (pts[n-1].handle[i].isassigned == false)
printf("%d ",pts[n-1].handle[i].seatid);
}
putchar('\n');
}
void assignseat(struct company * pts,int n)
{
puts("Please enter a seat number:");
int num;
while (scanf("%d",&num) == 1&&pts[n-1].handle[num - 1].isassigned == true)
{
puts("The seat is occupied. Please enter another seat number:");
eatline();
}
eatline();
puts("Please enter your name:");
char line[40];
s_gets(line,40);
puts("Confirm the seat number(y or n)?");
char ch;
ch = getchar();
eatline();
if (ch == 'y' || ch == 'Y')
{
pts[n-1].handle[num - 1].isassigned = true;
strcpy(pts[n-1].handle[num - 1].name,line);
puts("The seat is saved for you.");
}
}
void deleteseat(struct company * pts,int n)
{
puts("Please enter your seat number:");
int num;
while (scanf("%d",&num) == 1 && pts[n-1].handle[num - 1].isassigned == false)
{
puts("The seat is empty.Please enter your correct seat number:");
eatline();
}
eatline();
puts("Are you sure to delete your seat (y or n)?");
char ch;
ch = getchar();
eatline();
if (ch == 'y' || ch == 'Y')
{
pts[n-1].handle[num - 1].isassigned = false;
}
}
void showfunc(void(* ptf)(struct company *,int n),struct company * pts,int n)
{
ptf(pts,n);
}
void eatline(void)
{
while(getchar() != '\n')
continue;
}
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 = '\0';
else
while (getchar() != '\n')
continue;
}
return ret_val;
}
大致过了一遍code,感觉两组程序不太一样。
OK的程序用的是a,b,c,d,e作为菜单标注,用getchar应该没问题
NG的程序用的是1,2,3,4,5作为菜单标注,用的是scanf函数
修改方案,两个:
GOOD LUCK!!!
已参与了 SegmentFault 思否社区 10 周年「问答」打卡 ,欢迎正在阅读的你也加入。