struct Node {
char gender;
int turns_in_bathroom;
struct Node *next;
};
struct Queue {
struct Node *front, *back;
};
int QueueDeleteNext(Queue *myQueue, char value) {
Node *current_node, *previous_node;
previous_node = NULL;
int found = 0;
for (current_node = myQueue->front; current_node != NULL;
previous_node = current_node, current_node = current_node->next) {
if (current_node->gender == value) {
if (previous_node == NULL) {
myQueue->front = myQueue->back = NULL;
}
else {
previous_node->next = current_node->next;
if(previous_node->next == NULL){
myQueue->back = previous_node;
}
}
free(current_node);
found = 1;
}
}
return found;
}
我在线上遇到了分段错误
if (current_node->gender == value) {
我不能为我的生活找出原因。这里发生了什么? 更不用说尽管我的调试器中出现了错误,但代码仍会一直运行。但是,我认为可能存在一些与此相关的错误,我想确保我已经覆盖了所有基础。
答案 0 :(得分:2)
for (current_node = myQueue->front; current_node != NULL;
previous_node = current_node, current_node = current_node->next)
在for循环的每次迭代结束时,你要求current_node指向他的下一个元素。然而,下面有几行:
free(current_node);
您释放此节点。所以它指向不再分配任何东西,导致你稍后得到的分段错误。只要找到要删除的元素,就立即退出该功能:
int QueueDeleteNext(Queue *myQueue, char value) {
Node *current_node, *previous_node;
previous_node = NULL;
for (current_node = myQueue->front; current_node != NULL;
previous_node = current_node, current_node = current_node->next) {
if (current_node->gender == value) {
if (previous_node == NULL) {
myQueue->front = myQueue->back = NULL;
}
else {
previous_node->next = current_node->next;
if(previous_node->next == NULL){
myQueue->back = previous_node;
}
}
free(current_node);
return 1;
}
}
return 0;
}
答案 1 :(得分:2)
显然,问题已经解决,但代码仍有问题:
条件next
测试当前节点是否是队列的头部。在这种情况下,必须调整头部而不是前一个节点的int QueueDeleteNext(struct Queue *q, char value)
{
struct Node *prev = NULL;
struct Node *curr = q->front;
int count = 0;
while (curr) {
if (curr->gender == value) {
struct Node *nn = curr;
if (prev == NULL) {
q->front = curr->next;
} else {
prev->next = curr->next;
}
if (curr == q->back) q->back = prev;
curr = curr->next;
free(nn);
count++;
} else {
prev = curr;
curr = curr->next;
}
}
return count;
}
,但代码会清空整个队列而不会正确删除可能的尾随节点。
删除队列中的最后一个节点后,应该更新队列的后退,以便后续推送可以追加到最后。
最后,看起来有点像OP的意图是删除具有相应值的所有节点,因为执行在第一次删除后没有停止。所以让我们这样做并返回已删除节点的数量:
while
主循环现在是一个curr->next
循环,用于以不同方式处理删除和跳过节点。在这两个例子中,下一个节点是prev
,但是当一个节点被删除时,prev
节点保持不变!此代码还保留了队列的后面。
实现此目的的另一种方法是使用指向节点指针的指针代替nd
指针。这消除了区分头部和其他节点的需要。 field after that. The code updates the pointer that points to the current node via
首先是队列头部的地址,以及前一个节点'下一个int QueueDeleteNext(struct Queue *q, char value)
{
struct Node **nd = &q->front;
int count = 0;
q->back = NULL;
while (*nd) {
if ((*nd)->gender == value) {
struct Node *nn = *nd;
(*nd) = (*nd)->next;
free(nn);
count++;
} else {
q->back = *nd;
nd = &(*nd)->next;
}
}
return count;
}
nd`的地址:
QString printPath = QSettings(classesRoot + "\\" + pdfId + "\\shell\\print\\command", QSettings::NativeFormat).value("Default").toString();
此代码可以扩展为只删除第一个节点或第一个_n_nodes。
答案 2 :(得分:-1)
在found = 1之后添加一个return语句;阻止调试器抛出错误。