无法从 C 中的函数获取响应



我正在编写一个程序,该程序创建一个双链表,并从中删除一个负值元素。除了调用modify函数时和试图删除它时程序崩溃的部分外,一切都很正常。有什么建议吗?

/*
*Given a doubly linked lists with +ve and -ve key values.
*Write a function to delete all the nodes with negative key values.
*/
#include<stdio.h>
#include<stdlib.h>
struct list {
int data;
struct list *next;
struct list *prev;
};
struct list *head = NULL;
struct list* create(int);
void modify(struct list*);
int main(void) {
int n, i, value;
struct list *temp;
printf("Enter the count of node :");
scanf("%d",&n);
for (i = 0; i < n; i ++) {
printf("Enter the value of node: ");
scanf("%d",&value);
create(value);
}
temp = head;
printf("nDoubly linked list is created and the list is as follows : n");
while (temp != NULL) {
printf("%d ",temp -> data);
temp = temp -> next;
}
modify(head);
}
struct list* create(int value) {
struct list *new_node, *temp;
temp = head;
new_node = (struct list*)malloc(sizeof(struct list));
new_node -> data = value;
new_node -> next = NULL;
new_node -> prev = NULL;
if (head == NULL) {
head = new_node;
}
else {
while (temp -> next != NULL) {
temp = temp -> next;
}
temp -> next = new_node;
new_node -> prev = temp;
}
return head;
}
void modify(struct list *head) {
struct list *current_node, *prev_node, *next_node, *temp;
temp = head;
while (temp -> next != NULL) {
if (temp -> data < 0) {
current_node = temp;
prev_node = temp -> prev;
next_node = temp -> next;
prev_node -> next = next_node;
next_node -> prev = prev_node;
free(current_node);
}
}
printf("nThe modified doubly linked list is : n ");
temp = head;
while (temp -> next != NULL) {
printf("%d",temp -> data);
temp = temp -> next;
}
}

查看来自莫斯科的Vlad的示例,以更好地了解您在做什么。

我会仔细检查你的密码,告诉你我会改变什么。

/*
*Given a doubly linked lists with +ve and -ve key values.
*Write a function to delete all the nodes with negative key values.
*/
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>

首先:您正在创建一个(双链接(节点列表,而不是列表列表。称之为节点。此外,您可以执行typedef以防止您一直在编写struct Node

struct Node {
int data;
struct Node* next;
struct Node* prev;
};
void append(struct Node** head, int value); // variable names aren't needed here
struct Node* findLastNode(struct Node** head);
void removeNegativeNodes(struct Node** head);
void removeNode(struct Node** head, struct Node* currNode);
int main(void)
{

尽量不要使用全局变量。为什么不使用它们有很多原因,但在这里也有可能不使用它们。想象一下,如果有数千行代码,你将无法对代码有一个像样的视图。

struct Node* head = NULL;
struct Node* p; // temp-<p>ointer
int n, value;
printf("Enter the count of node :");
scanf("%d", &n);

在for循环中只需要i,所以请将其保留在那里。

for (int i = 0; i < n; ++i) {
printf("Enter the value of node: ");
scanf("%d", &value);

确保你的函数名称清楚,并告诉你它们的作用。create()会告诉我它创建了一个节点,但不是说它也append是节点。

append(&head, value);
}
// this can be in a function! (A) printData
p = head; // temp-<p>ointer
printf("nDoubly linked list is created and the list is as follows : n");
while (p != NULL) {
printf("%d <=> ", p->data);
p = p->next;
}
printf("NULLn");

看看你在做什么:也许你想制作一个通用函数来分割代码?在这里,您再次浏览列表并打印出它的数据成员。

// this can be in a function! (B) printData
removeNegativeNodes(&head);
printf("nThe modified doubly linked list is : n");
p = head;
while (p != NULL) {
printf("%d <=> ", p->data);
p = p->next;
}
printf("NULLn");
}
struct Node* findLastNode(struct Node** head)
{
struct Node* p = *head;
if (p != NULL)
while (p->next != NULL)
p = p->next;
return p;
}

由于你的头像必须更改,你也必须传递头像的地址。此外,对代码进行一点拆分,这样您就更容易了解代码的结构。如果您的函数长度为40条规则,则需要更长的时间才能找到错误的原因(确切地(。

void append(struct Node** head, int value)
{
struct Node* lastNode = findLastNode(head);
struct Node* nextNode = (struct Node*)malloc(sizeof(struct Node));
if (lastNode != NULL) {
lastNode->next = nextNode;
nextNode->prev = lastNode;
}
else {
*head = nextNode;
nextNode->prev = NULL;
}
nextNode->next = NULL;
nextNode->data = value;
}

这里也是:第一个数字可以是负数,所以请确保您可以通过head变量的地址访问它。此外,再次保持简单,并将代码拆分为函数removeNegativeNodes>removeNode

void removeNegativeNodes(struct Node** head)
{
struct Node* p = *head;
struct Node* temp;
while (p != NULL) {
temp = p->next;
if (p->data < 0)
removeNode(head, p);
p = temp;
}
}
void removeNode(struct Node** head, struct Node* currNode)
{
if (currNode->next != NULL)
currNode->next->prev = currNode->prev;
if (currNode->prev != NULL)
currNode->prev->next = currNode->next;
else
*head = currNode->next;
free(currNode);
}

我已经测试了代码,它应该可以工作。不过,让它正常工作并不重要,重要的是了解会发生什么。我建议你仔细看看。祝你好运!

您对双链表的定义没有多大意义。

列表应该包含两个指针:指向列表的头节点和尾节点。

所以你需要定义两个结构。第一个定义节点,第二个定义列表本身。

在这种情况下,您不需要遍历整个列表来将新节点附加到列表的尾部。

具有混淆名称的函数create基于全局变量head,而函数modify通过参数获取变量。

这很令人困惑。例如,结果是您不能在一个程序中创建两个列表。

因此,当函数modify通过值获得指向头节点的指针时,这意味着它处理指向头节点指针的副本。因此,函数中指向头节点的指针的任何变化都不会影响指向头节点原始指针。

函数modify中的此循环

temp = head;
while (temp -> next != NULL) {

通常可以调用未定义的行为,因为不排除指向头节点的指针可以等于CCD_。

在任何情况下,循环的条件都没有意义,因为在循环中,你考虑的不是下一个节点,而是当前的

while (temp -> next != NULL) {
if (temp -> data < 0) {

因此,如果temp->next等于NULL,但指针temp指向的当前节点的值为负数,这是否意味着该节点不会被删除?

请注意,如果您将正确写入循环的条件,那么被移除节点的数据成员prev或被移除节点中的数据成员next,甚至两者都可以等于NULL。在这种情况下,这些语句

prev_node = temp -> prev;
next_node = temp -> next;
prev_node -> next = next_node;
^^^^^^^^^^^^^^^^^
next_node -> prev = prev_node;
^^^^^^^^^^^^^^^^^ 

再次可以调用未定义的行为。

这里有一个演示程序,展示了如何定义列表及其函数。调查一下。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
struct Node
{
int data;
struct Node *next;
struct Node *prev;
};
struct List
{
struct Node *head;
struct Node *tail;
};
int push_back( struct List *list, int data )
{
struct Node *new_node = malloc( sizeof( struct Node ) );
int success = new_node != NULL;
if ( success )
{
new_node->data = data;
new_node->next = NULL;
if ( list->head == NULL )
{
new_node->prev = NULL;
list->head = list->tail = new_node;
}
else
{
new_node->prev = list->tail;
list->tail = list->tail->next = new_node;
}
}
return success;
}
void remove_if( struct List *list, int predicate( int ) )
{
struct Node *prev = NULL;
for ( struct Node **current = &list->head; *current != NULL; )
{
if ( predicate( ( *current )->data ) )
{
struct Node *tmp = *current;
if ( ( *current )->next != NULL )
{
( *current )->next->prev = ( *current )->prev;
}
*current = ( *current )->next;
free( tmp );
}
else
{
prev = *current;
current = &( *current )->next;
}
}
list->tail = prev;
}
void display( const struct List *list )
{
for ( const struct Node *current = list->head; current != NULL; current = current->next )
{
printf( "%d -> ", current->data );
}
puts( "null" );
}
void display_reverse( const struct List *list )
{
for ( const struct Node *current = list->tail; current != NULL; current = current->prev )
{
printf( "%d -> ", current->data );
}
puts( "null" );
}
int is_negative( int data )
{
return data < 0;
}
int main(void) 
{
struct List list = { .head = NULL, .tail = NULL };
const size_t N = 10;
srand( ( unsigned int )time( NULL ) );
for ( size_t i = 0; i < N; i++ )
{
push_back( &list, rand() % N - N / 2 );
}
display( &list );
display_reverse( &list );
putchar( 'n' );
remove_if( &list, is_negative );
display( &list );
display_reverse( &list );
putchar( 'n' );
return 0;
}

程序输出可能看起来像

2 -> 4 -> 3 -> -5 -> 3 -> -3 -> -3 -> -2 -> 0 -> 2 -> null
2 -> 0 -> -2 -> -3 -> -3 -> 3 -> -5 -> 3 -> 4 -> 2 -> null
2 -> 4 -> 3 -> 3 -> 0 -> 2 -> null
2 -> 0 -> 3 -> 3 -> 4 -> 2 -> null

create()函数返回一个链表项。所以您必须将返回值分配给一个项目。此外,结构内部指针的定义也是完全错误的。

struct list {
int data;
struct list *next;
struct list *prev;
};
struct list *head = NULL;
struct list* create(int); //function prototype
void modify(struct list*);//function prototype
int main(void) {
int n, i, value;
struct list *temp;
printf("Enter the number of nodes :");
scanf("%d",&n);
for (i = 0; i < n; i ++) {
printf("Enter the value of node: ");
scanf("%d",&value);
create(value);
}
temp = head;
printf("nDoubly linked list is created and the list is as follows : n");
while (temp != NULL) {
printf("%d ",temp -> data);
temp = temp -> next;
}
modify(head);
}
void create(int value) {
struct list* point = head;
while(point->next){
if(point->data != value)
point = point->next;
else{
printf("Data existsn");
return NULL;
}
}
struct list* item = (struct list*)malloc(sizeof(struct list));
item->data = value;
item->next = NULL;
item->prev = point;
}
void modify(struct list *head) {
struct list *current_node, *prev_node, *next_node, *temp;
temp = head;
while (temp -> next != NULL) {
if (temp -> data < 0) {
temp->prev->next = temp->next;
temp->next->prev = temp->prev;
free(temp);
}
temp = temp->next;
}
printf("nThe modified doubly linked list is : n ");
temp = head;
while (temp -> next != NULL) {
printf("%d",temp -> data);
temp = temp -> next;
}
}

我希望这对你有用。

相关内容

  • 没有找到相关文章

最新更新