【问题标题】:Is There a Standard Method for Making Abstract Data Types in ansi C?是否有在 ansi C 中制作抽象数据类型的标准方法?
【发布时间】:2019-08-08 15:38:27
【问题描述】:

我最近转入了另一所学校和 cs 课程。与我以前学校教授的 java 相比,使用的语言是 C。我的主要问题之一可能是由于没有编写足够的 C 代码导致我无法找到制作抽象数据类型的标准。

据我所见,这些实现方式有很多种,而且缺乏可见的标准让我担心我在自学 C 时遗漏了一些东西。我见过对用户隐藏 init 变量的实现比如

#define createVector(vec) Vector vec; void init_vector(&vec)

还有另一个版本,我更习惯使用句柄来保存从 createVector() 函数返回的指向 struct 的指针。问题是我在网上或我的课程 2 书中找不到任何关于句柄的详细描述。课程 2 的书只展示了接口和方法,但没有展示它们是如何以一种对用户隐藏实现的方式组合在一起的。我想知道 ADT 是否有“正确”的方式/标准?有问题的书是 Robert Sedgewick “Algorithms in C - Third Edition”。

【问题讨论】:

  • 您可以使用函数指针创建一个结构,或者适当地命名函数以明确它们与结构相关联。例如。带有函数指针的链表可能如下所示:github.com/Xatenev/c-algorithms/blob/master/src/data-structures/…
  • 我所知道的过程没有法律上的(如“ISO”或“ECMA”)标准。有多种事实上的标准——您发现的所有这些不同的变体。您展示的宏将在我的建议“好主意”列表中大放异彩。

标签: c abstract-data-type


【解决方案1】:

抽象数据类型

拆分您的来源。 头文件(.h 文件)包含 abstract 声明,如数据类型(结构、函数、枚举、常量等) 实际实现在 .c 文件中完成。 使用这样的(让我们称之为)模块时,您只需在源代码中包含标题。 您使用的实现是在链接时决定的。您可能决定使用不同的 .c 文件来实现或使用静态库(甚至是动态库)。 如果你想隐藏你使用opaque structures的数据。

为什么是这个标准?听说过FILE 类型吗?这是 c 的 standard 库中用于 IO 的不透明类型。您只包含标题 stdio.h 并将实现留给编译器。另一方面,标题或至少它定义的符号都有很好的文档记录(并且是 c 标准的一部分)。

抽象类

Java 有抽象类的概念。嗯,它也有一个类的概念。 C 没有。这更多是个人意见,但不要浪费时间模拟该语言不提供的语言功能。 对于非抽象方法,使用函数,该函数采用指向(可能是不透明的)结构的指针,该结构包含作为第一个参数所需的所有数据,如fprintf(FILE*,const char*,...)。 对于抽象方法,你需要函数指针。 使用这些函数指针(或者可能是函数指针的结构),例如 strategy。您可以定义一个method 来注册这样的策略并将正常功能委托给它们。以atexit 函数为例,它在全局范围内(您可以称其为单例)添加了一个退出的-策略

XY 问题

我很难找到制作抽象数据类型的标准

阅读this 并将其应用于您的问题。 与其试图强迫你的解决方案工作,不如重新考虑尝试的解决方案是否适用于问题。尝试熟悉上述技术。这可能需要一些练习,但是您可以以更c-styled 的方式为您的解决方案建模。

【讨论】:

  • 完成本题所依据的课程后,您对不透明数据结构的看法是正确的。通常,我们使用 void* 来保存实际对象和包含所述 void* 及其可以使用的函数的结构。然后我们制作了一个宏,以便每个对象的函数调用引用结构中的 object/void*
【解决方案2】:

我只是想发布这个,因为我想出了更适合我的案例的答案,但是我知道这可能并不适用于所有人。我正在寻找的是“First Class ADTs”的想法,它使用句柄来包含指向实际对象的指针,该对象是从对用户隐藏的 .c 实现文件创建的。

【讨论】:

    【解决方案3】:

    对于使用 C 的 ADT,据我所知,这种方法是标准方法。您将拥有一个头文件 (.h) 和一个或多个实现 (.c) 文件。头文件可能类似于:

    typedef struct * Doodad;
    
    Doodad * doodadInit(int);
    
    void doodadDestroy(Doodad *);
    
    int doodadGetData(Doodad *);
    
    void doodadSetData(int);
    

    对于您的实施文件,您可能有:

    typedef struct iDoodad {
       int data;
    } Doodad;
    
    Doodad * doodadInit(int data) {
       ...
    }
    
    ...
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-06-06
      • 2016-01-25
      • 1970-01-01
      • 2012-06-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多