Search code examples
clistiteratormallocabstract-data-type

Problems with the ADT List Iterator in C


i'm making the ADT List Iterator in C. When I use the primitive to print the list to the beginning they work correctly. But then, inside the main, I want to create the iterator over the list and look if the delete primitive works(i't works correctly) but then I want to print the list again with print_list_iterator() again, it doesn't works. I have my structs like this:

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;

These are the primitives of the ADT Iterator that i am working with;

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;
}

Here my primitive to delete de iterator;

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;
}

Then, if i want to print the list i'm using:

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);
    }
}

If I use the print_list_iterator(), then in the main it doesn't let me create an iterator on the same list, and use my primitives. Any ideas? By the way, I would like to know if these primitives are well implemented.

Function test in the main: int main(){

  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);

In terminal:

   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 -> 

So, my function are working right, but: If I call the print function (which is actually a function that runs through the list with the iterator primitives, that's why I shared the iterator primitives since there may be some error there)

    print_list_iterator(destino);
    list_iterator_delete(iter);
    print_list_iterator(destino);
    list_iterator_delete(iter);
    list_iterator_delete(iter);
    list_iterator_delete(iter);

The result in terminal:

MacBook-Air:tp2 UltraT$ ./it2
88 -> 99 -> 1 -> 0 -> 5 -> 106 -> 22 -> 44 -> 56 -> 3 -> 5 -> 6 -> 3 -> 4 -> 6 -> 

It does not work.

That is why my function of eliminating sometimes works and sometimes not. I don't know where the problem is if in the print function (which actually goes through the list) or in the delete function


Solution

  • Finally, I solved it by using *prev and *curr(current node). In the future I want to change the function to use it with double pointers.

    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;