我有一个粒子链表。我想让这些粒子一个接一个地移动。所以为了做到这一点,我需要遍历链表中的每个粒子,当它到达最后一个粒子时,我希望它回到第一个粒子。但我的计划不是这样做的。
int particle_update(struct particle **head ){
struct particle *current = *head;
struct particle *next;
printf("particle_update\n");
while(current != NULL){
while(current != NULL && current->lifespan >=0){
current->lifespan --;
current->pos.y = current->pos.y + (current->spd.y * current->dir.y);
current->pos.x = current->pos.x + (current->spd.x * current->dir.x);
current->pos.z = current->pos.z + (current->spd.z * current->dir.z);
current = current->next;
if (current == NULL)
current = *head;
}
}
particle_destroy(head);
return 0;
}
答案 0 :(得分:1)
我感觉有很多问题......
一个......这很奇怪......while(current->lifespan >= 0 && current != NULL){
应为while(current != NULL && current->lifespan >= 0){
这意味着它将首先检查它不为空,并且只有当它不为空时,它才会尝试查看当前 - >生命周期是什么。你拥有它的方式,它可能会崩溃
另外,我不确定你是否想要转移到下一个作为第一件事?我想这可能是你想在循环中做的最后一件事
另外,一旦你得到你想要的内循环,外循环将永远循环。
答案 1 :(得分:0)
我怀疑这里发生的事情就是要破坏你需要修改粒子的粒子,不正确处理这个案子就是绊倒你。
首先,只要您点击链接列表中的最后一个节点,就会在while循环开始时调用current = current -> next
,而应该在结尾处调用它。
因此,当前现在为null,因此当您在取消引用空指针时调用current->position
时,将会遇到BAD_EXEC错误。相反,在while循环结束时增加当前值,以便永远不会取消引用空指针。
接下来,将电流指向头部意味着除了通过粒子到期之外你永远不会退出你的循环,我认为这不是你想要的(否则你会有一段时间(1))。
所以这是处理手术的更好选择:
int particle_update(struct particle **head ){
struct particle * current = *head;
struct particle * prev = NULL;
while (current != NULL) {
// lifespan check
current->lifespan = (current -> lifespan > 0) ? current->lifespan-1:particle_destroy(&prev, ¤t);
// update position of current
...
// increment counter at end of while loop
prev = current;
current = current -> next; //now current is always one node ahead of previous.
}
return 0;
}
然后,你的粒子破坏函数将是:
void particle_destroy(struct particle ** prev, struct particle ** current) {
if (*current = NULL) return; //nothing to do
struct particle * tmp = *current;
if (*prev != NULL) { /* need to modify previous node */
(*prev) -> next = current -> next;
} else { /* head has expired, so change head ptr to next node */
(*current) = (*current) -> next;
}
/* free resources */
// do other clean-up, if necessary.
free(tmp);
return;
}