1

I got a chance to gain some extra points for a couple of C exercises. The task is to enhance program to use head and tail pointers (for FIFO queue) to avoid unneccessary while loops at extract function.

Insert() works fine. It sets the tail and head, but extract() always runs to the infinite loop or crashes. MinGW gcc shows no any extra warning (-Wall), so I am a bit confused here.

I did some debugging and found the lines, where things goes to somewhere in the unknown universe…

    queue->previous->next = queue->previous; // works
    *head = (*head)->next;   // loses pointer
    free(queue);   // as it should be,
    return qtail;  // caller function loses queue 

Funny enough, that original code (before this) works fine without losing pointer to queue. I rewrote entire program (cleaned my mess), however still having the issue.

Program output:

 queue tester

 insert 0: first head: first,  tail: first
 insert 1: second head: second,  tail: first
 insert 2: third head: third,  tail: first
 insert 3: foruth head: foruth,  tail: first
 insert 4: some head: some,  tail: first
 insert 5: another head: another,  tail: first
 insert 6: last head: last,  tail: first

 ***

 extracting last  head: last,  tail: first
 extracting ê7H  head: ê7H,  tail: first
 extracting ê7H  head: ê7H,  tail: first
 extracting ê7H  head: ê7H,  tail: first

… and so on until program is terminated by Ctrl+C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXLEN 50
#define MAX 7

typedef struct qelement *qpointer;

typedef struct qelement {
    char name[ MAXLEN ];
    qpointer next, previous;

} qelement;

qpointer insert(char *name, qpointer queue, qpointer *head, qpointer *tail); 
qpointer extract(qpointer queue, qpointer *head, qpointer *tail);

qpointer insert(char *name, qpointer queue, qpointer *head, qpointer *tail) {

    qpointer new = (qpointer)malloc(sizeof(qelement));
    strcpy(new->name, name);

    if(queue != (qpointer)NULL) {
        new->next = queue;
        queue->previous = new;
        (*head) = new;
    } 
    else {
        new->next = new;
        (*head) = new;
        (*tail) = new;
    }
    new->previous = new;
    return new;
    }

qpointer extract(qpointer queue,  qpointer *head, qpointer *tail) {

    qpointer qtail =(*head);

    if(queue == (qpointer)NULL)
        return (qpointer)NULL;
    else {
        if(queue->previous != queue) {
            free(queue);
            (*head)=NULL;
            (*tail)=NULL;
            return (qpointer)NULL;
        }
        else {
            queue->previous->next = queue->previous;
            *head = (*head)->next;  
            free(queue);
            return qtail; // usually main program loses queue after this. 
        }
    }
}




int main ( void ) {

    int i;

    qpointer qptr =NULL;
    qpointer head =NULL ;
    qpointer tail =NULL ;

    char teksti[MAX][MAXLEN] = {
        "first", "second", "third", "foruth", "some", "another", "last"
    };

    /* insert into queue */
    printf("\n queue tester \n");
    for (i =0; i<= MAX-1 ; i++) {

        printf("\n insert %d: %s", i , teksti[i]);
        qptr= insert( teksti[i], qptr, &head, &tail);
        printf(" head: %s, ", head->name ? head->name : "no data");
        printf(" tail: %s ",  tail->name ? tail->name : "no data");
    }
    printf("\n\n");

    /* remove from queue */
    printf("\n ***\n");
    while (  qptr != NULL ) {

        printf("\n extracting %s ",qptr->name);
        printf(" head: %s, ", head->name ? head->name : "no data");
        printf(" tail: %s ",  tail->name ? tail->name : "no data");
        qptr = extract(qptr, &head, &tail);
    }

    return(0);
}

Thanks!

Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
tuomas
  • 25
  • 4
  • You might want to think about having a double-linked list. – Some programmer dude Apr 30 '13 at 18:43
  • Don't know if you're aware of this, OP, but you might find this useful: [sys/queue.h](http://www.manpagez.com/man/3/queue/) – Maggy May Apr 30 '13 at 19:48
  • If this is not a double-linked list (with ->previous and ->next) then what is this?. Yes I have seen sys/queue.h, however original task was NOT to use ready-to-use functions and structures. – tuomas May 01 '13 at 09:31

1 Answers1

1

should be modified as follows

qpointer extract(qpointer queue,  qpointer *head, qpointer *tail) {

    qpointer qtail =(*head);

    if(queue == (qpointer)NULL)
        return (qpointer)NULL;
    else {
        if(queue->next == queue) {
            free(queue);
            (*head)=NULL;
            (*tail)=NULL;
            return (qpointer)NULL;
        }
        else {
            queue->next->previous = queue->next;
            *head = (*head)->next;  
            free(queue);
            return *head; // qtail already free
        }
    }
}
BLUEPIXY
  • 39,699
  • 7
  • 33
  • 70