我正在尝试编写两个函数:一个函数推出列表的最后一个单元格,另一个函数使该单元格成为另一个列表的第一个单元格。不知何故,我的功能无法正常工作(我已经检查了代码的其他部分很多次了。)
void last_cell_out(CellPtr list, CellPtr c)
{
if (list==NULL)/*if list is empty*/
return;/*doing nothing*/
if (list->next==NULL)/*if theres only one cell in the list*/
{
c=list;
list=NULL;
return;/*deleting from list and moving to c*/
}
if (list->next->next==NULL)
{
c=list->next;
list->next=NULL;
}
else
last_cell_out(list->next, c);
return;
}
CellPtr new_first_cell(CellPtr list, CellPtr c)
{
c->next=list;
return c;/*returnes the start of the list*/
}
答案 0 :(得分:1)
鉴于您如何描述需求,此功能对我来说似乎非常好
delegate_to
但是da_march_to_june = da.sel(time = slice('2000-03-01', '2000-06-30')).sum(dim = 'time')
da_july_to_november = da.sel(time = slice('2000-08-01', '2000-11-30')).sum(dim = 'time')
有一些问题。
首先,您不需要此代码块
CellPtr new_first_cell(CellPtr list, CellPtr c)
{
c->next=list;
return c;/*returnes the start of the list*/
}
无论如何,它将在下一个周期中处理。
话虽这么说,您的函数确实从列表中删除了最后一个元素。 它只是不会返回或以您可以看到的方式更改代码。
一个选择是返回最后一个单元格,而不是将其作为参数传递。
last_cell_out
第二个变体将c作为指针传递,因此您可以在代码内更改其内容。
if (list->next->next==NULL)
{
c=list->next;
list->next=NULL;
}
如果列表太大,您也可以完全避免递归,以避免可能的堆栈溢出。
CellPtr last_cell_out(CellPtr *listPtr)
{
CellPtr list = *listPtr;
if (list==NULL)/*if list is empty*/
return NULL;/*doing nothing*/
if (list->next==NULL)/*if theres only one cell in the list*/
{
*listPtr = NULL;
return list;/*deleting from list and return*/
}
return last_cell_out(&(list->next));
}
完整的测试程序:
void last_cell_out(CellPtr *listPtr, CellPtr *c)
{
CellPtr list = *listPtr;
if (list==NULL)/*if list is empty*/
{
*c = NULL;
return;/*doing nothing*/
}
if (list->next==NULL)/*if theres only one cell in the list*/
{
*c=list;
*listPtr = NULL;
return;/*deleting from list and moving to c*/
}
last_cell_out(&((*listPtr)->next), c);
return;
}
答案 1 :(得分:1)
函数last_cell_out
必须通过引用接受其参数,因为它会更改其原始值。否则,该函数将具有未定义的行为,因为例如该语句
list=NULL;
不会更改列表的原始值。只会更改其局部变量list
,该变量被定义为具有原始列表vlaue副本的参数。
因此,至少应通过以下方式定义函数
void last_cell_out(CellPtr *list, CellPtr *c)
{
if ( *list == NULL )/*if list is empty*/
{
*c = NULL;
return;/*doing nothing*/
}
else if ( ( *list )->next == NULL )/*if theres only one cell in the list*/
{
*c = *list;
*list = NULL;
return;/*deleting from list and moving to c*/
}
else if ( ( *list )->next->next == NULL )
{
*c = ( *list )->next;
( *list )->next = NULL;
return;/*deleting from list and moving to c*/
}
else
{
last_cell_out( &( *list )->next, c );
return;/*doing nothing*/
}
}
这是一个演示程序。
#include <stdio.h>
#include <stdlib.h>
struct Cell
{
int data;
struct Cell *next;
};
typedef struct Cell *CellPtr;
void last_cell_out(CellPtr *list, CellPtr *c)
{
if ( *list == NULL )/*if list is empty*/
{
*c = NULL;
return;/*doing nothing*/
}
else if ( ( *list )->next == NULL )/*if theres only one cell in the list*/
{
*c = *list;
*list = NULL;
return;/*deleting from list and moving to c*/
}
else if ( ( *list )->next->next == NULL )
{
*c = ( *list )->next;
( *list )->next = NULL;
return;/*deleting from list and moving to c*/
}
else
{
last_cell_out( &( *list )->next, c );
return;/*doing nothing*/
}
}
CellPtr new_first_cell(CellPtr list, CellPtr c)
{
c->next = list;
return c;/*returnes the start of the list*/
}
void print_cells( CellPtr list )
{
for ( CellPtr current = list; current != NULL; current = current->next )
{
printf( "%d -> ", current->data );
}
puts( "NULL" );
}
int main(void)
{
CellPtr list = NULL;
CellPtr cell = malloc( sizeof( struct Cell ) );
cell->data = 1;
list = new_first_cell( list, cell );
print_cells( list );
last_cell_out( &list, &cell );
CellPtr list1 = NULL;
list1 = new_first_cell( list1, cell );
print_cells( list );
print_cells( list1 );
last_cell_out( &list1, &cell );
free( cell );
return 0;
}
其输出为
1 -> NULL
NULL
1 -> NULL
考虑到将typedef用作指针是一个坏主意,因为它有时会使用户感到困惑。
函数last_cell_out
可以更简单地编写而无需递归。例如
void last_cell_out(CellPtr *list, CellPtr *c)
{
if ( *list )
{
while ( ( *list )->next ) list = &( *list )->next;
}
*c = *list;
*list = NULL;
}
或递归
void last_cell_out(CellPtr *list, CellPtr *c)
{
if ( *list && ( *list )->next )
{
last_cell_out( &( *list )->next, c );
}
else
{
*c = *list;
*list = NULL;
}
}