#c #visual-c
#c #visual-c
Вопрос:
Я относительно новичок в C , и у меня есть проблема, которую я действительно не понимаю. Мой код создает связанный список. На самом деле он длиннее, но я сократил его для целей этого вопроса.
Когда я запускаю код, он добавляет три узла, а затем, когда он переходит к удалению узла с помощью URI b
, он вызывает delete
operator и заканчивает удалением узла, но затем, похоже, возвращается к delete
operator (когда я перехожу через него), и он уничтожает весь мой список.
#include <iostream>
#include <string>
#include <cstdlib>
#include <cstdio>
using namespace std;
class CLinkedList
{
protected:
class ip_uri_store
{
public:
string uri, ip;
ip_uri_store* next;
ip_uri_store(const stringamp; URI, const stringamp; IP) {uri = URI, ip = IP, next = NULL;}
};
typedef ip_uri_store* nodeAddress;
nodeAddress head;
void AddNode(const stringamp;, const stringamp;, nodeAddress);
void DeleteNode(const stringamp;, nodeAddress, nodeAddress);
public:
CLinkedList() {head = NULL;}
void AddNode(const stringamp; URI, const stringamp; IP) {AddNode(URI, IP, head);}
void DeleteNode(const stringamp; URI) {DeleteNode(URI, head, head);}
};
void CLinkedList::AddNode(const stringamp; URI, const stringamp; IP, nodeAddress node)
{
nodeAddress temp = new ip_uri_store(URI, IP);
temp->uri = URI;
temp->ip = IP;
temp->next = head;
head = temp;
}
void CLinkedList::DeleteNode(const stringamp; URI, nodeAddress node, nodeAddress behindNode)
{
if(node)
{
if(!node->uri.compare(URI))
node == head ? head = head->next : behindNode->next = node->next;
else
DeleteNode(URI, node->next, node);
delete node;
}
}
int main(int argc, char* argv[])
{
CLinkedList lList;
lList.AddNode("a", "1");
lList.AddNode("b", "2");
lList.AddNode("c", "3");
lList.DeleteNode("b");
return 0;
}
Комментарии:
1. Это серьезное злоупотребление троичным условным оператором.
2. Учитывая, что он новичок в этом, код кажется скопированным со случайного сайта…
3. Я его не копировал. Это мой код. Под новым я подразумеваю несколько месяцев. Я много читал о c …
4. Это только я или реализации связанных списков трудно читать?
5. «В принципе, то, что происходит, » довольно излишне.
Ответ №1:
Вы вызываете delete node;
, даже если сравнение завершается неудачно (т.е. node->uri != URI
).
if(!node->uri.compare(URI))
{
node == head ? head = head->next : behindNode->next = node->next;
delete node;
}
else
DeleteNode(URI, node->next, node);
Кроме того, условие, похоже, инвертировано.
Комментарии:
1. Большое вам спасибо. Рекурсия меня смутила. Я не понимал, что он вызвал deleteNode в части else, запустил удаление и повторно вызвал его, когда он вернулся к вызывающей функции. Еще раз спасибо!
2. Ничто не получает «повторного вызова». Рекурсия — это не волшебство: вы просто выполняете вызов функции, как и любой другой. Выполнение продолжается после завершения вызова функции.
3. @user968243, вы должны попытаться переписать это без рекурсии. Как общее эмпирическое правило, рекурсию следует использовать только для деревьев, для которых вы можете гарантировать ограниченную высоту. Попробуйте проверить URI и, если сравнение завершилось неудачно, назначить
node
его преемнику и повторить (с подобной конструкцией циклаwhile
).
Ответ №2:
Во-первых, вы должны использовать std::list и избегать переосмысления мира. В любом случае, если вы по какой-то причине застряли в этой реализации :
- temp->uri = URI; и temp-> ip = IP; в методе AddNode бесполезны, поскольку члены уже инициализированы в конструкторе класса ip_uri_store.
- удаление заголовка списка происходит потому, что «удаление узла» должно выполняться только в случае node->uri.compare(URI) в методе deleteNode.
Опять же, вам следует серьезно подумать об использовании стандартных классов…
Комментарии:
1. Я знаю о std::List; однако я должен реализовать связанный список с использованием классов и рекурсии. Однако в будущем я буду использовать std::List . Спасибо, что указали на ненужное назначение.
Ответ №3:
Вы вызываете delete на всех узлах. Его необходимо переместить внутрь условного, чтобы удалить только те узлы, которые соответствуют URI
if(!node->uri.compare(URI)) {
node == head ? head = head->next : behindNode->next = node->next;
delete node;
} else {
DeleteNode(URI, node->next, node);
}