我是C语言的新手,正在尝试为C语言编写一个双链表。如果要算出链表中的索引数但不退出整个程序,我想跳出或返回空值。仅用于打印错误并返回Null或用户会识别出超出范围的内容。我不知道C是否可以做到。 这是我的代码的一部分。 free_node函数用于返回节点的数据并释放节点空间。我只想知道该如何处理这个弹出功能,以解决超出范围的问题。
谢谢
typedef struct node{
void *data;
struct node *next,*prev,*head,*tail;
}Node;
typedef Node *List;
Node pop_node(List plist,long index){
Node *pnode;
pnode=direct_to_head(plist)->next;
if(index>list_count(plist)){
fprintf(stderr, "index out of link list scope.");
return;
}
while (pnode->next!=NULL && index-->0) {
pnode=pnode->next;
}
return free_node(pnode);
}
答案 0 :(得分:1)
我想跳出或返回空值...我不知道C是否可以做到。
简短的回答是否
您-作为设计人员-决定函数pop_node
返回类型为Node
(也称为struct node
)的对象。这意味着代码应始终返回类型为Node
的对象。 C不允许您突然返回另一种类型。因此,将不允许使用return NULL;
之类的内容。
我只想知道该怎么处理这个弹出功能,以解决超出范围的问题。
您可以更改函数签名以返回指向Node的指针,并将复制/释放留给调用方。在这种情况下,您可以将NULL用作指示“无对象可用”的值。
答案 1 :(得分:0)
如果声明一个函数返回void
(即什么也没有),则它只能返回什么。如果声明一个函数返回其他类型的T
,那么它就可以返回所有内容。
考虑:
Node
(可以为NULL
)的指针选项1的另一个变体是定义类型为Node
的特殊全局变量,并使用合适/可识别的名称,例如ErrorNode
,并返回指向它的指针。然后,调用者可以将返回的指针与&ErrorNode
进行比较以检测错误情况。乍一看似乎并不特殊,但是如果您最终需要识别几个不同的错误情况(虽然不是太多),则可以定义多个这样的变量(不要太多,因为您需要使用{{1 }}而不是if/else
来区分它们。
答案 2 :(得分:0)
不好,但可能会用{Invalid-Node“值定义一个Node
,并且如果没有要返回的节点,只需返回” Invalid-Node“-节点即可。
const Node InvalidNode = {(void*)-1,
(struct node*)-1, (struct node*)-1, (struct node*)-1, (struct node*)-1
};
#define NODE_IS_INVALID(n) ( \
((n).data == InvalidNode.data) && \
((n).next == InvalidNode.next) && \
((n).prev == InvalidNode.prev) && \
((n).head == InvalidNode.head) && \
((n).tail == InvalidNode.tail) \
)
然后将您的功能更改为如下形式:
Node pop_node(List plist,long index){
Node *pnode;
pnode=direct_to_head(plist)->next;
if(index>list_count(plist)){
fprintf(stderr, "index out of link list scope.");
return InvalidNode;
...
并这样称呼它:
Node n = pop_node(...);
if (NODE_IS_INVALID(n))
{
/* handle error */
}
else
{
/* use n here */
}
答案 3 :(得分:0)
我已经改变了我的功能。我想我不需要将指针返回到节点,我只需要它的数据。这样我就可以在获取数据的同时释放节点。
这是我的整个双交叉链接列表代码:
//
// double_linklist.c
// tt
//
// Created by tarrant on 2019/2/16.
// Copyright © 2019 tarrant. All rights reserved.
//
#include "double_linklist.h"
static void c_free(void *p){
free(p);
p=NULL;
}
static Node *direct_to_index(List plist,long index){
Node *pnode;
unsigned int count = list_count(plist);
if (labs(index) > count+2){
fprintf(stderr, "index out of scope.");
return NULL;
}
if (index >=0){
if(plist->head==NULL){
pnode=plist;
}
else
pnode=plist->head;
while (true){
if(--index<0)
break;
else
if (pnode->next!=NULL)
pnode=pnode->next;
else{
fprintf(stderr, "invalid node %p.",pnode);
return NULL;
}
}
}
else{
if(plist->tail==NULL){
pnode=plist;
}
else
pnode=plist->tail;
while (true){
if(++index>=0)
break;
else
if (pnode->prev!=NULL)
pnode=pnode->prev;
else{
fprintf(stderr, "invalid node %p.",pnode);
return NULL;
}
}
}
return pnode;
}
static Node *direct_to_head(List plist){
return direct_to_index(plist, 0);
}
static Node *direct_to_tail(List plist){
return direct_to_index(plist, -1);
}
void empty_list(List plist){
Node *tmp,*current;
plist=direct_to_head(plist);
current=plist->next;
while (current->next!=NULL) {
if(current->data!=NULL){
c_free(current->data);
}
tmp=current;
current=current->next;
c_free(tmp);
}
current->prev=plist;
plist->next=current;
}
List init_list(void){
Node *head,*tail;
if((head = (Node *)calloc(1, sizeof(Node)))!=NULL){
tail = (Node *)calloc(1, sizeof(Node));
head->tail=tail;
head->data=(unsigned int *)calloc(1, sizeof(unsigned int));
head->next=tail;
if(tail!=NULL){
tail->prev=head;
tail->data=NULL;
tail->head=head;
return head;
}
}
fprintf(stderr, "No space in initing.");
return NULL;
}
bool isempty_node(const Node *pnode){
if(pnode->data==NULL)
return true;
return false;
}
bool free_node(Node *pnode){
unsigned int *count;
Node *next,*prev;
if(pnode->next==NULL ||pnode->prev==NULL){
fprintf(stderr, "You are empting head,tail or invaild node.");
return false;
}
count=direct_to_head(pnode)->data;
next=pnode->next;
prev=pnode->prev;
next->prev=prev;
prev->next=next;
c_free(pnode);
c_free(pnode->data);
--*count;
return true;
}
void free_all_empty_nodes(List plist){
Node *phead;
unsigned int count=0;
phead=direct_to_head(plist)->next;
while (phead->next!=NULL) {
if((phead->data==NULL)&&(free_node(phead)==false))
fprintf(stderr, "error in empting index %d",count);
phead=phead->next;
count++;
}
}
Node *pop_node(List plist,long index){
Node *pnode,*next,*prev;
if (index>=0)
index++;
else
index--;
pnode=direct_to_index(plist, index);
next=pnode->next;
prev=pnode->prev;
pnode->head=NULL;
pnode->tail=NULL;
next->prev=prev;
prev->next=next;
return pnode;
}
unsigned int list_count(List plist){
unsigned int *count;
Node *phead;
if(plist->head==NULL){
phead=plist;
}
else
phead=plist->head;
count=phead->data;
return *count;
}
void insert_list(const void *data,List plist,size_t size,long index){
Node *tmp,*current;
unsigned int *count;
if(data==NULL){
fprintf(stderr, "data is empty.");
return;
}
tmp=(Node *)calloc(1, sizeof(Node));
tmp->data=(void *)calloc(1, size);
if(tmp==NULL||tmp->data==NULL){
fprintf(stderr, "no space for allocation.\n");
return;
}
memcpy(tmp->data,data,size);
if (index<0)
index--;
current=direct_to_index(plist, index);
tmp->next=current->next;
current->next->prev=tmp;
current->next=tmp;
tmp->prev=current;
tmp->head=direct_to_head(current);
tmp->tail=direct_to_tail(current);
count=direct_to_head(plist)->data;
++*count;
}
void append_list(const void *data,List plist,size_t size){
insert_list(data,plist,size,-1);
}
bool modify_node(Node *node,const void *data,size_t size){
if((data==NULL)||(node->prev==NULL)||(node->next)==NULL)
return false;
free(node->data);
node->data=(void *)malloc(size);
memcpy(node->data,data,size);
return true;
}
bool modify_list(const void *data,List plist,long index,size_t size){
Node *phead;
if(data==NULL)
return false;
if (index>=0)
index++;
else
index--;
phead=direct_to_index(plist, index);
return modify_node(phead,data,size);
}
void traverse_list(const List plist,void (*pfun)(void *pdata),int flag){
Node *pnode;
if(flag>=0){
pnode=direct_to_head(plist)->next;
while (pnode->next!=NULL) {
(pfun)(pnode->data);
pnode=pnode->next;
}
}
else{
pnode=direct_to_tail(plist)->prev;
while (pnode->prev!=NULL) {
(pfun)(pnode->data);
pnode=pnode->prev;
}
}
}
答案 4 :(得分:-2)
您想在函数内跳转-看一下goto语句。 goto语句用于在函数内的任何位置跳转。
转到标签;
标签: 声明;
在您的情况下,打印错误并跳转至free_node语句。 C中的return关键字退出并返回代码。