一、

第一种:普通函数的调用+switch语句

#include<stdio.h>
void menu()
{
   printf("*************************");
   printf("*****1. add   2.sub******");
   printf("*****3. mul   4.div******");
   printf("*********0. exit*********");
   printf("*************************");
}
int add(int x,int y)
{
  return x+y; 
}
int sub(int x,int y)
{
  return x-y;
}
int mul(int x,int y)
{
  return x*y;
}
int div(int x,inty)
{
  return x/y;
}
int main()
{
  int input=0;
  int x=0;
  int y=0;
  do
  {
    menu();
    printf("请选择:>");
    scanf_s("%d",&input);
    //printf("请输入两个操作数:>");
    //scanf_s("%d%d",x.y);
    //上面这两句话如果放在这,那么就算是输入非0、1、2、3、4的数程序也会让输入两个操作符,显得啰嗦
    //所以将这两句话放在了case语句里面
    switch(input)
    {
      case 1:
        printf("请输入两个操作数:>");
        scanf_s("%d%d",&x,&y);
        printf("%d\n",add(x,y));
        break;
      case 2:
        printf("请输入两个操作数:>");
        scanf_s("%d%d",&x,&y);
        printf("%d\n",sub(x,y));
        break;
      case 3:
        printf("请输入两个操作数:>");
        scanf_s("%d%d",&x,&y);
        printf("%d\n",mul(x,y));
        break;
      case 4:
        printf("请输入两个操作数:>");
        scanf_s("%d%d",&x,&y); 
        printf("%d\n",div(x,y));
        break;
      case 0:
        printf("退出\n");
        break;
      default:
        printf("选择错误\n");
    }
  }
  while(input);
}

     我们不难看出来,第一种方法中的代码有两处地方显得很冗余:

  • 加减乘除函数的每次调用(细想一下:计算器中可不止加减乘除四个运算法则,而每一次都调用(case语句也会越来越多)会很费劲、很矬)
  • printf("请输入两个操作数:>");scanf_s("%d%d",&x,&y);这两句话在四个case语句中都重复出现,也会使代码显得很矬

所以我们依照这两个不足之处加以改进:

二、函数指针数组的使用

#include<stdio.h>
void menu()
{
   printf("*************************");
   printf("*****1. add   2.sub******");
   printf("*****3. mul   4.div******");
   printf("*********0. exit*********");
   printf("*************************");
}
int add(int x,int y)
{
  return x+y; 
}
int sub(int x,int y)
{
  return x-y;
}
int mul(int x,int y)
{
  return x*y;
}
int div(int x,inty)
{
  return x/y;
}
int main()
{
  int x=0;
  int y=0;
  int (*pfarr[])(int,int)={0,add,sub,mul,div};//函数指针数组
  int input=0;//这里input是pfarr数组的下标
  //这里函数指针数组中的第一位初始化为0是有原因的:和上面的menu函数中的对应起来
  do
  {
    menu();
    printf("请选择:>");
    scanf_s("%d",&input);
    if(input>=1&&input<=4)
    {
       printf("请输入两个操作数:>");
       scanf_s("%d%d",&x,&y);
       int ret=pfarr[input](x,y);
       printf("%d\n",ret);
    }
    else if(input==0)
    {
      printf("退出\n");
    }
    else
    {
      printf("选择错误\n");
    }
  }
  while(input);
}

三、回调函数(通过函数指针调用的函数)

用这个方法解决代码冗余的问题

将重复性的语句分装成函数Calc;来接收函数名(地址)

void Calc(int (*pf)(int,int))
{
  int x=0;
  int y=0;
  printf("请输入两个操作符:>");
  scanf_s("%d%d",x,y);
  printf("%d\n",pf(x,y));
}

所以case语句中变成了:

case 1:
Calc(add);
break;
case 2:
Calc(sub);
break;
case 3:
Calc(mul);
break;
case 4:
Calc(div);
break;

这样就显得很简洁明了,最后的代码就变成了:

#include<stdio.h>
void menu()
{
   printf("*************************\n");
   printf("*****1. add   2.sub******\n");
   printf("*****3. mul   4.div******\n");
   printf("*********0. exit*********\n");
   printf("*************************\n");
}
int add(int x,int y)
{
  return x+y; 
}
int sub(int x,int y)
{
  return x-y;
}
int mul(int x,int y)
{
  return x*y;
}
int div(int x,inty)
{
  return x/y;
}
void Calc(int(*pf)(int,int))
{
  int x=0;
  int y=0;
  printf("请输入两个操作符:>");
  scanf_s("%d%d",&x,&y);
  printf("%d\n",pf(x,y));
  break;
}
int main()
{
  int input=0;
  do
  {
    menu();
    printf("请选择:>");
    scanf_s("%d",&input);
    switch(input)
    {
        case 1:
        Calc(add);
        break;
        case 2:
        Calc(sub);
        break;
        case 3:
        Calc(mul);
        case 4:
        Calc(div);
        break;
      case 0:
        printf("退出\n");
        break;
      default:
        printf("选择错误\n");
    }
  }
  while(switch)