我得到了一些现有的C代码(一个头文件和一些源代码)来实现链表,并被赋予了一个任务来使用它来实现队列。
以下是我得到的头文件的一部分,其中包含相关的函数描述:
/* List is a pointer to a list_t struct */
typedef struct list_t* List;
struct list_t {
void *data;
List next;
};
/* Pushes data as the new head of list. May be used to create a new list:
* new_list = push(NULL, data) */
extern List push(List list, void *data);
/* Pop the head off the list */
extern void *pop(List *list);
/* Return the length of the list */
extern int len(List list);
/* Returns a reversed copy of list */
List reverse(List list);
/* Prepend data to list and update list */
extern List prepend(List *list, void *data);
/* Append l1 to the end of l2 */
void append(List l1, List *l2);
/* Inserts data into the tail of list */
void insert(void *data, List *list);
/* Inserts data into the tail of list or position equal to the next element */
void insert_by(bool (*eq)(void *data, void *node), void *data, List *list);
/* Inserts data into the tail of list. Returns true if sucessful,
* false if it finds an element already equal to data */
bool insert_if(bool (*eq)(void *data, void *node), void *data, List *list);
/* Returns the node equal to aim in list, returns NULL if not found */
extern List find(bool (*eq)(void *aim, void *node), void *aim, List list);
/* Removes and returns the element equal to aim in list,
* returns NULL if not found */
extern void *del(bool (*eq)(void *aim, void *node), void *aim, List *list);
/* Returns a new list that passes the predicate p */
List filter(bool (*p)(void *data), List list);
/* Print list to f by applying print to each node that is not NULL */
extern void print_list(void (*print)(FILE *f, void *data), FILE *f, List node);
/* Free the memory allocated to each list node */
extern void free_list(List node);
我知道为了实现队列,我至少需要两个函数,enqueue()
和 dequeue()
.我继续使用上述头文件中的 List 类型为队列创建自己的头文件和用于队列的 typedef:
//Queue.h
#include "list.h"
typedef List Queue;
//Add item to queue...
void enqueue(Queue q, void *data);
//removes and returns an item from the queue...
void dequeue(Queue *q);
然后我继续在queue.c
中实现了源代码。我现在只实现了enqueue
,因为我想确保它在继续之前有效:
#include "queue.h"
void enqueue(Queue q, void *data){
if (q == NULL){
q = push(q, data);
}
else {
insert(data, &q);
}
}
很简单,我知道。我计划使用以下文件,main.c
测试队列:
#include <stdio.h>
#include "queue.h"
int main(int argc, char **argv){
Queue q = NULL;
int i;
for (i = 0; i < 10; i++){ enqueue(q, &i); } //one line for brevity
return 0;
}
在这一点上,我没想到在运行时会看到任何输出 main.c
,我所期望的只是程序运行没有错误然后停止。一切都编译得很好,但是当我运行main.c
时,我得到的只是:
sh: ./main.exe: bad file number
这意味着什么,任何人都可以确定可能导致此问题的原因吗?
编辑:源代码是这样编译的:
gcc -c list.c
gcc -c queue.c
gcc -c main.c -o main.exe
您的enqueue
函数破坏了push
方法的协定。
push
方法返回新头。
您将需要:
Queue enqueue(Queue q, void *data){
return push(q, data);
}
在您的通话中:
for (i = 0; i < 10; i++){
q = enqueue(q, &i);
}
但请注意,这将在每次迭代时推送相同的指针。如果更改i
则将更改队列中每个节点的值。这可能不是你想要的!
另请注意,对局部(自动)变量的地址进行排队可能是一件坏事,当变量超出范围时,可能会导致堆栈问题。(在您的情况下,i
是在 main
中声明的,因此在程序结束之前它不会超出范围。
这不仅仅是关于 C 编程问题,而是关于未正确调用的编译器命令。
编译命令不完整。
使用这个:
gcc -c list.c
gcc -c queue.c
gcc -c main.c
gcc list.o main.o queue.o -o main.exe
./main.exe
解释:
gcc -c list.c produces list.o
gcc -c queue.c produces queue.o
gcc -c main.c produces main.o
gcc list.o main.o queue.o -o main.exe invokes the linker that links the .o files
together producing main.exe
./main.exe run the program
C 代码中可能存在其他与编程相关的问题。