【问题标题】:Is there any way to make a function smartly in C such that it performs different functions in different values of arguments?有什么方法可以在 C 中巧妙地创建一个函数,以便它在不同的参数值中执行不同的函数?
【发布时间】:2020-03-12 06:33:19
【问题描述】:

??????

我必须创建 2 个结构,即矩形和椭圆形,其中矩形结构包含其长度和宽度,椭圆形结构包含其半短轴和半长轴的长度。然后我必须创建一个以上述两个结构作为其成员的联合形状。然后我必须创建一个通用函数'area',它计算联合的面积(根据传递给函数的参数,矩形或椭圆形)。我目前使用菜单驱动的方法和使用开关案例(问题后附加的代码)处理了上述问题。

我想创建一个智能函数,它以联合作为参数并根据联合中存储的结构计算面积。

代码

typedef struct rect{
    int l,b;
}r;
typedef struct oval{
    int x,y;
}o;
union shape{
    r r1;
    o o1;
}sh;
void area(int a);
void main()
{
    int ch;
    int a;
    printf(" 1.Area of rect\n 2.Area of oval\n 3.EXIT");
    while(1){
        printf("\nEnter your choice: ");
        scanf("%d",&ch);
        switch(ch)
        {
            case 1:a=0;
                area(a);
                break;
            case 2:a=1;
                area(a);
                break;
            default:printf("BYE\n");
                return;
        }
    }
}
void area(int a)
{
    if(a==0){
        printf("Enter Length and Breadth: ");
        scanf("%d %d",&sh.r1.l,&sh.r1.b);
        int ar=sh.r1.l*sh.r1.b;
        printf("%d",ar);
    }
    else if(a==1){
        printf("Enter x and y of Oval: ");
        scanf("%d %d",&sh.o1.x,&sh.o1.y);
        float ar=sh.o1.x*sh.o1.y;
        printf("%.2f",ar*3.14);
    }
}

提前致谢!

【问题讨论】:

  • 您需要一个具有type 成员的structuniontype 用于指示union 的哪个字段有效。
  • @user3386109 你能提供一个使用type成员的例子吗?
  • 看看this question。第一个答案有一个我正在谈论的例子(在更大的代码 sn-p 中)。 this question 在主题上有一个变化。
  • @user3386109 良好的链接。但是我可以建议将“第一个答案”更改为“最受好评的答案”吗?您知道的每个用户都可以单独配置答案的排序。
  • 如果您想留在纯 C 语言中,另一种方法是在您的 shape 结构中添加一个指向 area 函数的指针。创建椭圆时,只需将此指针指向ovalArea 函数;当你创建一个矩形时,让它指向一个 rectArea ;等等与其他几何。当您需要sh *a 的区域时,只需致电a->area(a)

标签: c gcc struct shapes unions


【解决方案1】:

作为风险(非类型安全)的替代方案,并假设该功能是必须要求的,请考虑使用 Type-Generic _Generic 宏,它允许您根据类型调度单个调用。

我不得不承认,在 10 多年的 C 开发中,我从来没有遇到过证明使用这种结构是合理的情况 - 使用对多态性(c++、Java)有适当支持的语言总是更可取的。

#define area(shape) _Generic((shape), struct oval: oval_area, struct rect: rect_area)

typedef struct rect{
    int l,b;
}r;
typedef struct oval{
    int x,y;
}o;

int rect_area(struct rect v) {
        return v.l *  v.b ;
}

int oval_area(struct oval v) {
        return v.x * v.y * 2 ;
}

void main(void)
{
        struct rect r ;
        struct oval o ;

        area(r) ;
        area(o) ;
}

【讨论】:

    【解决方案2】:

    user3386109 通过指向其他帖子的链接描述了最安全的解决方案。
    我非常推荐使用这种方法。

    但是,还有另一种选择,基于隐式跟踪哪个类型在哪个联合中表示。 (这个概念我已经在这里描述过How to verify if a void pointer (void *) is one of two data types?)。

    联合基本上告诉编译器,它可能是这种类型或那种类型,并且明确表示该变量/类型的编译器并不比程序员更了解(否则通常是这种情况)。因此,如果程序员指示编译器访问这个或那个联合成员,那么编译器将相信它与上次写入的内容相匹配。

    在这种情况下,程序员必须比编译器更了解
    IE。这与程序员容易误解的联合相反,而不是“我不需要知道里面是哪种类型”。它的意思是“我必须在每一点都知道里面有什么,因为我需要告诉编译器。”

    现在使用变量的另一部分来跟踪存储的内容(由 user3386109 描述)的概念使这项职责变得非常容易。
    但是,如果您不遵循这种方法,那么知识可以而且必须仍然存在于其他地方。
    例如,您可以将所有椭圆存储在一个数组中,将所有矩形存储在另一个数组中。从语法上讲,两者都是相同的,但您只能用椭圆数组做椭圆形的事情,并且只能用矩形数组做矩形。
    我选择这个例子是因为它很容易理解,但我承认它没有多大的实际意义,因为那样的话,对两者都使用联合类型没有任何好处。
    然而,它确实说明了类型信息在某处但隐含的可能性,并且存储它的这种形式在执行时间和内存消耗方面可能更有效。

    包含您的形状结构的稍微复杂的数据结构可能更有意义。例如,气球的结构将包含形状中的几何信息,并且永远不会有问题是指椭圆(旋转椭圆体)还是矩形(方面盒子),描述墙壁部分的东西也不会需要铺纸的房间永远不会有任何疑问。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-19
      • 1970-01-01
      • 2019-08-01
      • 2016-03-08
      • 2023-03-19
      相关资源
      最近更新 更多