| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Для новичков > Удаления значения в списку. Бага |
| Автор: sswt 28.10.2015, 12:38 | ||
У меня проблема: когда я вывожу значения printBackward послу удаления головы или следущего значения у меня бага сплывает, printForward нормально выводит подскажите где ошибка. Тоесть когда я с хвоста начинаю читать бага появляеться
|
| Автор: math64 28.10.2015, 12:50 |
| При удалении элементов RemoveFirst и RemoveAfter не проверяешь, пустой ли список. Нужно также проверить, удаляется ли последний элемент и поправить list->tail если нужно. |
| Автор: sswt 28.10.2015, 13:11 | ||
math64,
|
| Автор: sswt 28.10.2015, 13:25 |
| feodorv, можете написать как нужно для RemoveFirst, а то я запуталась немножко((( |
| Автор: math64 28.10.2015, 13:27 | ||||
| Не break, а return. Прежде, чем делать list->head->prevNode = nullptr; нужно проверить list->head != nullptr; Аналогичные изменения в RemoveAfter. Возможны ошибки в невыложенной части кода. Добавлено через 7 минут и 7 секунд
|
| Автор: sswt 28.10.2015, 13:34 |
| math64, не помогло( |
| Автор: feodorv 28.10.2015, 13:35 | ||||
Думаю, как-то так:
|
| Автор: sswt 28.10.2015, 13:36 |
| feodorv, спасибо Добавлено через 2 минуты и 24 секунды feodorv, у нас тут list нету, откуда вы берету переменую tail = node; ???? |
| Автор: feodorv 28.10.2015, 13:42 | ||||
Ааааа. А я было подумал, что:
А так-то да, лист в аргументы добавить придётся. А если у Вас там ещё head и tail приватные, то придётся браться за голову))) |
| Автор: math64 28.10.2015, 14:33 |
| Либо 1) RemoveAfter(DoublyLinkedList::Node* node) будет методом класса DoublyLinkedList, либо 2) в DoublyLinkedList::Node нужно добавить поле DoublyLinkedList* list, либо 3) нужно добавить параметр в RemoveAfter(DoublyLinkedList* list, DoublyLinkedList::Node* node); Лучше сделать 1) и 2) одновременно и добавить проверку, что node принадлежит нужному списку. |
| Автор: sswt 28.10.2015, 15:47 | ||
math64,
|
| Автор: math64 28.10.2015, 16:27 | ||
| В обоих случаях нужна проверка firstNode != nullptr. В RemoveAfter ты заводишь secondNode, но нигде его не используешь (можно сделать как в RemoveFirst). list != nullptr можешь проверять, а можешь нет - если это гарантировано при вызове. Добавлено через 4 минуты и 51 секунду Кстати можно сделать
и проверять в RemoveAfter на node == nullptr - в этом случае удалять первый элемент списка, код получается похожим. К сожалению, в RemoveAfter нет контроля, что node принадлежит нужному списку. |
| Автор: sswt 28.10.2015, 16:45 | ||
math64, так ? та нет лутче поддельности 2 функции делать
|
| Автор: feodorv 28.10.2015, 16:57 | ||||
Выглядит ужасно. Сначала Вы разименовываете указатель, а затем проверяете, не нулевой ли он. Нужно наоборот. Добавлено через 7 минут и 33 секунды Вообще, вся логика по проверке на нулевые указатели нарушена полностью (заодно и логика алгоритма). secondNode тоже может быть нулевым указателем, тогда делать secondNode->prevNode никак нельзя. Если уж Вам так не нравится конструкция node->nextNode->prevNode, то реализовывайте её последовательно:
|
| Автор: sswt 28.10.2015, 17:06 | ||
feodorv,
как то так, я уже запуталась, поэтому если дурню пишу извините) |
| Автор: feodorv 28.10.2015, 17:07 |
| И жутко не нравится это free(). Почему не new+delete? Добавлено через 4 минуты и 19 секунд Дурните. Я Вам привел правильный и лаконичный вариант. Почему бы не подумать над ним хоть немножко? Зачем Вы опять разименовываете firstNode до проверки? Почему не проверяете secondNode на nullptr? Почему делаетев случае, когда нулевой firstNode (а в этом случае вообще ничего делать не нужно - с Вас объяснение, почему так)???????????????????????????????????????????????????????????????????????????????? |
| Автор: sswt 28.10.2015, 17:30 | ||||||||
free та как я на Си пишу.... Но я же посмотрела как вы тут сделали и так само написала
|
| Автор: feodorv 28.10.2015, 18:33 | ||||
Вы в этом уверены? Можно посмотреть Ваше определение DoublyLinkedList и DoublyLinkedList::Node? Послушайте. Вы мне напоминаете маленького ребёнка, которого заставили собирать пазл. И вот он попеременно с силой вставляет один неподходящий элемент мозаики в другой и удивляется, почему не получается цельной картины? Всё же программирование лежит в иной плоскости. С одной стороны, это творчество, что Вам пытался донести math64, предлагая несколько вариантов подхода к решению этой незатейливой задачи. С другой стороны - это ясное понимание того, что должно происходить в Вашей программе. Это и логика, это и обработка особых ситуаций, это адекватная реакция программы на любые входные данные. И многое чего ещё. Но это не перебор пазлинок, авось повезёт на этот раз и всё заработает, и заработает правильно. У Вас на руках в функции RemoveAfter всего три элемента: node, firstNode, secondNode (и гдет-то на заднем фоне маячит tail). Они взаимосвязаны друг с другом через поля nextNode и prevNode. Абсолютно ничего не мешает Вам взять бумагу и зарисовать эти взаимосвязи. А потом зарисовать то, что должно получиться при выдёргивании из этой цепочки срединного члена - firstNode. А потом рассмотреть случай, когда firstNode есть нулевой указатель. Что поменяется в коде в этом случае? Когда нужно проверить firstNode на nullptr, куда в код вставить эту проверку, чтобы не было разименовывания нулевого указателя. Меняется ли в этом случае tail и/или nextNode/prevNode у наших трёх элементов? А затем рассмотреть случай, когда secondNode есть нулевой указатель (ведь такое может случиться, правда ведь?) Аналогичные вопросы. Я Вас очень попрошу в устной форме прямо в этой ветке на них ответить. Только тогда Вам станет ясно, что не так в том коде, который Вы привели и который, по Вашему утверждению, Вы сделали после "посмотрела как вы тут сделали". И почему я должен по десять раз повторять, что:
Я Вам написал, и ещё раз напишу: Вообще, вся логика по проверке на нулевые указатели нарушена полностью (заодно и логика алгоритма). secondNode тоже может быть нулевым указателем, тогда делать secondNode->prevNode никак нельзя. Если уж Вам так не нравится конструкция node->nextNode->prevNode, то реализовывайте её последовательно:
Соглашаться на этот код Вам не обязательно, но с Вас объяснение того, что должно происходить в коде при:
|
| Автор: math64 29.10.2015, 08:18 | ||||||||
Как можно видеть RemoveFirst и RemoveAfter очень похожи. В RemoveAfter нужно внести только 2 изменения, чтобы она могла удалять и первый элемент списка:
Или даже так:
Но это менее понятно Добавлено через 6 минут и 12 секунд
Это C++. На C будет
Чтобы код работал как на C, так и на C++, нельзя объявлать структуру в структуре и нужно не забывать ключевое слово struct. |
| Автор: feodorv 29.10.2015, 09:04 |
Да и вообще, для http://learnc.info/adt/double_linked_list.html делить узлы на "первый" и "следующий" весьма странно (для односвязного - нормально). Достаточно просто функции removeNode, которая удаляет из списка именно тот node, который и передаётся функции removeNode. И уже внутри себя функция removeNode определяет, первый ли это элемент в списке, последний ли или ещё как-то. Для C придётся ещё избавляться от nullptr. |
| Автор: math64 29.10.2015, 09:10 | ||
Ну с этим просто:
|
| Автор: sswt 29.10.2015, 09:43 | ||||
math64, аможете обяснить вот это:
Как я уже писала я на Си пишу
|
| Автор: math64 29.10.2015, 10:22 | ||||||||||
| Это - C++. Надо так:
(с учетом того, чтобы можно было компилироваться как в C, так и в C++) В C есть оператор ?: поэтому можно писать
Это эквивалентно:
А вот вместо
Придётся писать
|
| Автор: sswt 29.10.2015, 10:30 | ||
| math64, спасибо. Буду знать Добавлено @ 10:40 math64, я написала :
но бага так и есть( как вы можете увидеть на картинке |
| Автор: math64 29.10.2015, 10:48 | ||||
Вместо firstNode = secondNode; нужно писать:
Сокращенная запись возможно только с firstNodeRef или firstNodePtrPtr (если пишете на C):
|
| Автор: sswt 29.10.2015, 12:45 | ||
Я надеюсь я хоча б эти функци правильно сделала?
Выводит нормально..... |
| Автор: math64 29.10.2015, 13:54 | ||
Правильно. Но в C нельзя объявлять переменую цикла в for:
|
| Автор: sswt 30.10.2015, 12:09 | ||
а можете пример скинуть реализации этой функции? Если есть в интернете |
| Автор: volatile 30.10.2015, 12:38 | ||
|
| Автор: feodorv 30.10.2015, 12:51 | ||
Ну, это я оставлю без коментариев))) |
| Автор: math64 30.10.2015, 12:55 | ||
|
| Автор: sswt 30.10.2015, 13:23 |
| спасибо |