我想在两个节点之间执行二进制运算,将结果存储在一个节点中,而消除另一个节点。这是我写的:
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <math.h>
struct n{
double value;
char op;
struct n *next;
};
void delete(struct n *head);
void add_item(struct n **ptr, double *data);
int main(){
struct n *head = NULL;
double result;
add_item(&head, 5);
add_item(&head, 3);
head->op = '*';
result = (head->next)->value * head->value;
(head->next)->value = result;
delete(head);
printf("%lf\n",head->value);
free(head);
return 0;
}
void add_item(struct n **ptr, double *data)
{
struct n *item = malloc(sizeof *item);
item->value = *data;
item->next = *ptr;
item->op = '?';
*ptr = item;
}
void delete(struct n *head)
{
struct n *temp;
temp = head->next;
head->next = temp->next;
free(temp);
}
在此示例中,我有一个像这样的列表3 -> 5 -> NUll
。我想要这个15 -> NUll
。
当我尝试打印剩余节点的值时,得到的是3
而不是15
答案 0 :(得分:3)
两个功能均无效。
对于功能add_item
,您不按引用传递数据(按引用传递数据也没有意义。)
add_item(&head, 5);
add_item(&head, 3);
因此该函数应像这样声明和定义
void add_item(struct n **ptr, double data)
{
struct n *item = malloc(sizeof *item);
item->value = data;
item->next = *ptr;
item->op = '?';
*ptr = item;
}
您还必须通过引用将头节点传递给函数delete
。
void delete(struct n **head)
{
if ( *head )
{
struct n *temp = *head;
*head = ( *head )->next;
free( temp );
}
}
并称呼它
delete( &head );
当我尝试打印剩余节点的值时,得到3而不是 15
这是因为您在头之后的节点中编写了操作结果,因此您删除了头之后的节点,而不是删除头节点。
(head->next)->value = result;
这是您更新的程序
#include <stdio.h>
#include <stdlib.h>
struct n{
double value;
char op;
struct n *next;
};
void delete(struct n **head);
void add_item(struct n **ptr, double data);
int main(){
struct n *head = NULL;
double result;
add_item(&head, 5);
add_item(&head, 3);
head->op = '*';
result = (head->next)->value * head->value;
(head->next)->value = result;
delete(&head);
printf("%lf\n",head->value);
free(head);
return 0;
}
void add_item(struct n **ptr, double data)
{
struct n *item = malloc(sizeof *item);
item->value = data;
item->next = *ptr;
item->op = '?';
*ptr = item;
}
void delete(struct n **head)
{
if ( *head )
{
struct n *temp = *head;
*head = ( *head )->next;
free( temp );
}
}
其输出为
15.000000
答案 1 :(得分:3)
通常与C一样,要使函数有权更改通过参数列表传递给它的对象,必须传递对象的地址,而不是对象本身。 ( read more on this here )
在此示例中,如果要以任何方式更改对象head
,则要求将其 address (&head
)传递给函数,不是对象本身。
所以声明:
delete(head); //passing the object will not allow it to be changed
应更改为
delete(&head); //The object's address is passed, allowing the object to be changed
由于要传递的对象是作为指针创建的:struct n *head = NULL;
,因此delete
函数的原型需要在其参数中容纳指针的地址。这是通过指向指针的指针完成的:
void delete(struct n **head);//accommodates the address of a pointer object
然后在delete
函数内部,对对象本身(现在为*head
)进行更改。
void delete(struct n **head)
{
if (*head == NULL) return;
struct n *temp = *head;
*head = temp->next;//point head to next node
free(temp);//free old head
}
相反,在您的void add_item(struct n **ptr, double *data);
函数中,data
不需要更改,只需要在体内使用即可。确实,在您的代码中调用它的方式是发送数据的正确方式:
add_item(&head, 5); // 2nd argument passes object directly, i.e. not an address
因此,由于该函数需要数据本身而不是数据指针,因此请更改原型以适应:
void add_item(struct n **ptr, double data);
相应地在代码主体中更改代码。