c语言 这段代码array of pointers to function哪里有问题吗?谢谢!

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;
}
阅读 1.1k
1 个回答

大致过了一遍code,感觉两组程序不太一样。
OK的程序用的是a,b,c,d,e作为菜单标注,用getchar应该没问题
NG的程序用的是1,2,3,4,5作为菜单标注,用的是scanf函数

修改方案,两个:

  1. 对于1,2,3,4,5的菜单,继续用getchar和eatline函数组合,转换数字则用int(choice2-'0')
  2. 用scanf函数,scanf是以回车作为数据结束响应的,所以后面的eatline函数调用是不需要的,可以去掉。

GOOD LUCK!!!

已参与了 SegmentFault 思否社区 10 周年「问答」打卡 ,欢迎正在阅读的你也加入。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进