我将C程序拆分为多个文件。这是他们的样子。
ListDefinition.h
:
#ifndef ALGORITHM_AND_DATASTRUCTURE_LISTDEFINITION_H
#define ALGORITHM_AND_DATASTRUCTURE_LISTDEFINITION_H
extern typedef struct type DataType; //this is a struct declaration about basic data type in the list
extern typedef struct s_list SeqList, *PseqList; //this is a struct declaration about sequence list
extern typedef struct sl_list SlinkList, *PSlinkList; //this is a struct declaration about linked list
#endif //ALGORITHM_AND_DATASTRUCTURE_LISTDEFINITION_H
或删除extern
#ifndef ALGORITHM_AND_DATASTRUCTURE_LISTDEFINITION_H
#define ALGORITHM_AND_DATASTRUCTURE_LISTDEFINITION_H
typedef struct type DataType; //this is a struct declaration about basic data type in the list
typedef struct s_list SeqList, *PseqList; //this is a struct declaration about sequence list
typedef struct sl_list SlinkList, *PSlinkList; //this is a struct declaration about linked list
#endif //ALGORITHM_AND_DATASTRUCTURE_LISTDEFINITION_H
ListDefinition.c
:
#include "ListDefinition.h"
#define MAXSIZE 100
typedef struct type {
int date;
}DataType;
typedef struct s_list {
DataType a[MAXSIZE];
int length;
int top;
}SeqList, *PseqList;
typedef struct sl_list {
DataType node;
struct sl_list *next;
}SlinkList, *PSlinkList;
我想在ListDefinition.h
ListFunction.h
ListFunction.h
:
#ifndef ALGORITHM_AND_DATASTRUCTURE_LISTFUNCTION_H
#define ALGORITHM_AND_DATASTRUCTURE_LISTFUNCTION_H
#include "ListDefinition.h"
PseqList initial_seqList(PseqList PL);//The function be used to initialize the sequence list
int search_seqlist(PseqList PL, DataType x);//the function be used to search the x in the sequence list
#endif //ALGORITHM_AND_DATASTRUCTURE_LISTFUNCTION_H
ListFunction.c
:
#include <stdio.h>
#include <stdlib.h>
#include "ListFunction.h"
PseqList initial_seqList(PseqList PL) {
PL=malloc(sizeof(SeqList));
if(PL == NULL) {
exit(1);
printf("The memory isn't allocated");
}
PL->length = 0;
PL->top = -1;
return PL;
}
int search_seqlist(PseqList PL, DataType x) {
int i;
for(i = 0;i < PL->length; i++) {
if(PL->a[i].date == x.date)
break;
}
if (i == PL->length)
return 0;
else
return i+1;
}
您不关心代码的含义。出现了许多错误,但是当我在#include "ListDefinition.h"
中将#include "ListDefinition.c"
更改为ListFunction.h
时。所有错误都消失了,我想知道为什么? This problem似乎告诉我应该使用ListFunction.h
。我在Clion中运行代码。
答案 0 :(得分:0)
extern typedef
的组合在C中是非法的。两个关键字都是&#39;存储类&#39;,并且您只能在声明中拥有一个存储类。放下extern
; typedef
没有存储空间(它没有定义任何对象),因此没有其他地方定义的存储空间&#39;使extern
有用。如果删除typedef
,则会尝试声明不完整类型的变量。
您的代码似乎正在尝试实施&#39; opaque类型&#39;。这可能是一项很好的技巧 - 如果你小心的话。但是,要小心包括:
因此,您可以定义一个类似于ListFunction.h
的标题,其中包含ListDefinition.h
的内容 - 结构类型的typedef
(没有单独的标题) - 以及功能声明。您的客户端代码可以使用它。
您可能有一个标题(不是源文件)等同于ListDefinition.c
中的标题,除了结构定义只是定义结构内容;它不包括typedef
或typedef名称。这将是一个私人的&#39;头。它只能由实现提供对ListDefinition.h
中声明的opaque类型的访问的函数的代码使用。如果您需要在多个源文件中使用该信息,则只能创建第二个标头。如果仅在一个源文件中需要该信息,则您将该信息保留在该源文件中(仅限)。
您的设计要求DataType
不透明。您的函数接口要求调用代码传递DataType
的副本,因此调用代码必须能够为DataType
分配存储空间。此外,您没有提供一套管理DataType
值的功能。因此,您必须在ListFunction.h
标题中显示该结构。
使用opaque结构指针比在接口中使用void
指针要好得多。使用void
指针会使代码容易被滥用 - 任何类型的任何指针都可以传递给需要void *
参数的函数。相比之下,如果某个函数需要SeqList *
,则无法将FILE *
或char *
或DataType *
传递给该函数(尽管您可以明确传递某些内容)定义为void *
因为void *
可以在C(但不是C ++)中转换为任何其他对象指针类型)。尽可能避免使用void *
。
请注意Is it a good idea to typedef pointers?中的讨论 - 简洁的答案是&#39;否&#39;。
您与initial_seqlist()
的界面充其量是可疑的。实现表明你不应该接受任何参数(因为你的代码所做的第一件事就是覆盖作为参数传递的值)。它应该是SeqList *initial_seqlist(void)
。
注意到没有声明操作Slinklist
类型的函数,代码可能会变成:
listdef11.h
#ifndef LISTDEF11_H_INCLUDED
#define LISTDEF11_H_INCLUDED
typedef struct DataType
{
int date;
} DataType;
typedef struct SeqList SeqList;
extern SeqList *initial_seqList(void);
extern int search_seqlist(SeqList *PL, DataType x);
/* ... */
#endif /* LISTDEF11_H_INCLUDED */
listdef11.c
#include "listdef11.h"
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 100
struct SeqList
{
DataType a[MAXSIZE];
int length;
int top;
};
SeqList *initial_seqList(void)
{
SeqList *psl = malloc(sizeof(*psl));
if (psl == NULL)
{
fprintf(stderr, "Failed to allocate %zu bytes of memory in %s()\n",
sizeof(*psl), __func__);
exit(1);
}
psl->length = 0;
psl->top = -1;
return psl;
}
int search_seqlist(SeqList *psl, DataType x)
{
for (int i = 0; i < psl->length; i++)
{
if (psl->a[i].date == x.date)
return i + 1;
}
return 0;
}
代码中还有许多其他更改。我并不同意所有的设计决策(例如,top
成员似乎未使用或与length
基本相同;我认为应该这样做。但这至少可以编译。 listdef11.h
的消费者可以做必要的事情 - 或者,如果listdef11.h
中声明的支持函数列表更完整,他们可以做到。该清单至少包括一个析构函数和一个插入器;它可能需要包括更多。用户对search_seqlist()
返回的号码可能做的事情并不完全明显。