您好我正在制作一个队列抽象数据类型,我遇到了一个问题,我将尽可能清楚地解释。 基本上我有两个结构,一个用于元素,一个用于队列(因此可以初始化多个队列)。
struct element
{
TYPE value;
struct element* next;
};
struct queue
{
struct element* head;
struct element* tail;
int element_counter;
};
我有一个初始化队列结构的函数。
int make_new_queue(struct queue* name)
{
name = malloc(sizeof(struct queue));
name->head = NULL;
name->tail = NULL;
name->element_counter = 0;
}
我遇到的问题是这个代码万无一失。例如,我在main函数中初始化了我的第一个队列。
struct queue* first = make_new_queue(first);
但如果有人试图在代码中间的某处再次做同样的事情,那就写下来了:
first = make_new_queue(first);
它会覆盖它并使head和tail指针为NULL。我无法弄清楚的是如何使我的make_new_queue函数更好,并检查队列中是否有我提供的东西,但仍然让我初始化空队列。
抱歉我的英文。我希望你能理解我想做的事情。感谢。
答案 0 :(得分:1)
将其初始化为NULL
并将指针传递给指针:
void make_new_queue(struct queue **name)
{
if (*name != NULL) return; /* Yet initialized ? */
*name = malloc(sizeof(struct queue));
if (*name == NULL) {
perror("malloc");
exit(EXIT_FAILURE);
}
*name->head = NULL;
*name->tail = NULL;
*name->element_counter = 0;
}
struct queue *first = NULL;
make_new_queue(&first);
答案 1 :(得分:0)
您只需检查变量name
是否为NULL
。
如果你的变量是非空的,你可以分配并初始化你的队列,否则就做你想做的事。
答案 2 :(得分:0)
没有好的方法可以在没有用户纪律的情况下强制执行您想要的内容。在我看来,最好的方法是坚持已知的模式。
您可以使用Alter Mann的方法将指针传递给指针以更新结构。缺点是你必须将变量声明和初始化分开。它还依赖于用户将结构的指针初始化为NULL
。如果您忘了它,队列指针将不会被初始化,您甚至不知道,因为您无法检查NULL
。
struct stuff *stuff = NULL;
stuff_initialise(&stuff);
您可以使用原始方法传入结构,并在初始化时返回相同的结构或新结构。它具有与第一种方法相同的问题以及您忘记分配返回值的可能性。但是,您可以将分配和初始化结合起来:
struct stuff *stuff = stuff_new(NULL);
最简单的方法是不传递旧指针并依赖用户在分配后不更改指针。毕竟,标准库的功能也存在同样的问题:
char *buf = malloc(BUFSIZE);
buf = malloc(2 * BUFSIZE); // Memory leak
buf++; // Allowed, but a bad idea
free(buf); // Ouch!
FILE *f = fopen("palomino.txt", "r");
f = stdin; // Switch horses midstream?
您应该设计API,以便拥有定义结构范围的匹配函数对:
struct stuff *stuff = stuff_create(...);
// use stuff ...
stuff_destroy(stuff);
良好的命名应明确stuff
充当句柄,不应更改,并且在关闭或销毁句柄后,它无效。您应该将这些调用视为函数中的第一个和最后一个语句。 (此方法类似于标准库的malloc
/ free
或fopen
/ fclose
对。)
最后,如果您作为句柄的用户想要避免更改,您可以将指针(而不是它指向的内容)定义为const
:
struct stuff *const handle = stuff_create("X");
handle = stuff_create("Y"); // Compiler error
但我很少看到这一点。 C程序员通常只使用一个朴素的指针,并记住将手指放在加热板上。