я делаю ADT List Iterator
в C
.
Когда я использую примитив для печати списка в начало, они работают правильно. Но затем, внутри основного, я хочу создать итератор по списку и посмотреть, работает ли примитив удаления (я не работает правильно), но затем я хочу снова распечатать список с помощью print_list_iterator()
, это не работает.
У меня есть такие структуры:
typedef struct node{
struct node *next;
void *data;
}nodo_t;
typedef struct list{
struct node *head;
}list_t;
typedef struct iterator{
node_t **pn;
}list_iterator_t;
Это примитивы ADT Iterator
, с которыми я работаю;
list_iterator_t * list_iterator_create(list_t * l){
struct iterator *li = malloc(sizeof(struct iterator));
if (li == NULL)
return NULL;
li->pn = &(l->head);
return li;
}
bool list_iterator_next(list_iterator_t *li){
if (*li->pn == NULL){
return false;
}
*li->pn = (*li->pn)->next;
return true;
}
void *list_iterator_current(const list_iterator_t *li){
if ((*li->pn) == NULL){
return NULL;
}
return (*li->pn)->data;
}
Вот мой примитив для удаления итератора;
void *list_iterator_delete(lista_iterator_t *li){
if (*li->pn == NULL)
return NULL;
struct node *aux;
void *aux_data = (*li->pn)->data;
aux = (*li->pn);
*li->pn = (*li->pn)->next;
free(aux);
return aux_data;
}
Затем, если я хочу распечатать список, который я использую:
void print_list_iterator(lista_t * l){
for(list_iterator_t *li =list_iterator_create(l);
!list_iterator_finish(li);
list_iterator_next(li)
){
int *e = list_iterator_current(li);
printf("%d -> ",*e);
}
}
Если я использую print_list_iterator()
, то в основном это не позволяет мне создать итератор в том же списке и использовать мои примитивы.
Любые идеи?
Кстати, хотелось бы узнать, хорошо ли реализованы эти примитивы.
Функциональный тест в основном: интервал основной () {
list_t *dest = list_create();
list_iterator_t *iter = list_iterator_create(dest);
int vector[] = {88,99,1,0,5,106,22,44,56,3,5,6,3,4,6};
size_t vector_size = sizeof(vector)/sizeof(vector[0]);
for(size_t i=0; i<vector_size; i++)
list_append(dest, vector +i);
list_iterator_delete(iter);
list_iterator_delete(iter);
list_iterator_delete(iter);
list_iterator_delete(iter);
print_list_iterator(dest);
В терминале:
MacBook-Air: UltraT$ gcc iterator_double_pointers.c -std=c99 -Wall -pedantic -o it2
MacBook-Air: UltraT$ ./it2
5 -> 106 -> 22 -> 44 -> 56 -> 3 -> 5 -> 6 -> 3 -> 4 -> 6 ->
Итак, моя функция работает правильно, но: Если я вызываю функцию печати (которая на самом деле является функцией, которая проходит через список с примитивами итератора, поэтому я поделился примитивами итератора, поскольку там может быть какая-то ошибка)
print_list_iterator(destino);
list_iterator_delete(iter);
print_list_iterator(destino);
list_iterator_delete(iter);
list_iterator_delete(iter);
list_iterator_delete(iter);
Результат в терминале:
MacBook-Air:tp2 UltraT$ ./it2
88 -> 99 -> 1 -> 0 -> 5 -> 106 -> 22 -> 44 -> 56 -> 3 -> 5 -> 6 -> 3 -> 4 -> 6 ->
Это не работает.
Вот почему моя функция устранения иногда работает, а иногда нет. Я не знаю, где проблема, если в функции печати (которая фактически проходит по списку) или в функции удаления
Гена имеет в виду этот минимальный воспроизводимый пример.
Буквально вчера был вопрос по этому поводу, воспользуйтесь поиском. Вам нужен указатель на указатель элемента prev в итераторе!
@AnttiHaapala Да, вы правы насчет поста. Но здесь я не спрашиваю то же самое, здесь функция, которую я сделал, работает правильно (list_iterator_delete()), если я создаю итератор в списке в файле main. Затем, если я вызываю функцию print_list_iterator(), я могу печатать на экране, но после использования этой функции (которая создает мне еще один итератор в списке, который я прошу вас распечатать) я не могу использовать итератор в ранее созданном.
@Gene Да, ты прав, я попытаюсь обобщить свою проблему. Я подумал, что было бы неплохо показать всю имеющуюся у меня информацию, потому что моя проблема может заключаться в любом из примитивов. Если бы я разделял только функции print_list_iterator() и list_iterator_delete(), возможно, было бы мало информации для анализа проблемы.
Та же проблема, нужно перелинковать список по удаленному узлу
@AnttiHaapala извините, но я вас не понимаю. Если можно, посмотрите на редакцию, которую я сделал к посту. Моя функция удаления работает (иногда). Я не знаю, проблема в устранении или просмотре списка (распечатать)
@Renzo: в вашей функции удаления после того, как вы удалили текущий узел, предыдущий узел по-прежнему будет указывать на теперь удаленный узел, или, если он был первым, голова все равно будет указывать на него.
@ 500-InternalServerError, не могли бы вы помочь мне с кодом?
Взгляните на этот пример для вдохновения (не мое).
Наконец, я решил это, используя *prev и *curr(текущий узел). В будущем я хочу изменить функцию, чтобы использовать ее с двойными указателями.
struct list_iterator{
node_t *prev;
node_t *curr;
list_t *l_iter;
};
typedef struct list_iterator list_iterator_t
void * delete_iterator_list(list_iterator_t * li) {
if (list_iterator_finish (li))
return NULL;
struct node * aux_node;
void * data;
if (! li-> prev) {
data = li-> curr-> data;
aux_node = li-> curr;
li-> l_iter-> head = aux_node-> next;
li-> curr = li-> l_iter-> head;
}
else if (li-> curr-> next == NULL) {
data = li-> curr-> data;
aux_node = li-> curr;
li-> curr = li-> curr-> next;
li-> prev-> next = li-> curr;
}
else {
data = li-> curr-> data;
aux_node = li-> curr;
li-> curr = li-> curr-> next;
li-> prev-> next = li-> curr;
}
free (aux_node);
return data;
Пожалуйста, прочитайте справку о предоставлении минимального полного проверяемого примера с вашим вопросом. Это повысит ваши шансы на получение помощи, которую вы хотите.