Hello, I have been struggling with this project for several days. This is all about doubly Linked List and I have to add reverse section with given code in project. So far it was doing good. I learned a lot from this but the only thing I had issue is deleting reverse characters. I noticed if I have certain characters, it won't have issue to delete the characters but when I have certain characters, the reversed charcter displayed different character like if I want to delete n, this project will display E with dash mark above it. I don't know how to address this problem. Last thing, I'm trying to learn this in program c not c++.
Also, when it comes to deleting the last node, the program kept running infinite. I tried to add system pause or break but nothing works.
(Sorry, English isn't my first language. I hoped I clarified as I can! And thank you for taking time to help me to understand this :) )

Here's my code:

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


// self-referential structure                     
struct queueNode {                                   
   char data; // define data as a char            
   struct queueNode *nextPtr; // queueNode pointer
   struct queueNode *prevPtr;
}; // end structure queueNode                     

typedef struct queueNode QueueNode;
typedef QueueNode *QueueNodePtr;

// function prototypes
void printQueue( QueueNodePtr currentPtr );
int isEmpty( QueueNodePtr headPtr );
char dequeue( QueueNodePtr *headPtr, char value );
void enqueue( QueueNodePtr *headPtr,  char value );
void instructions( void );
void reverse( QueueNodePtr currentPtr);


// function main begins program execution
int main( void )
{ 
   QueueNodePtr headPtr = NULL; // initialize headPtr
   QueueNodePtr tailPtr = NULL; // initialize tailPtr
   unsigned int choice; // user's menu choice
   char item; // char input by user

   instructions(); // display the menu
   printf( "%s", "? " );
   scanf( "%u", &choice );

   // while user does not enter 3
   while ( choice != 3 ) { 

      switch( choice ) { 
         // enqueue value
         case 1:
            printf( "%s", "Enter a character: " );
            scanf( "\n%c", &item );
            enqueue( &headPtr, item );
            printQueue( headPtr );
            reverse( headPtr );
            break;
         // dequeue value
         case 2:
            // if queue is not empty

            if ( !isEmpty( headPtr ) ) 
            { 
                printf("Enter a character to be deleted:");
                scanf("\n%c", &item);

                if(dequeue(&headPtr, item))
                {
                    printf("%c deleted.\n", item);
                    printQueue(headPtr);
                    reverse(headPtr);
                }
                else{
                    printf("%c not found.\n", item);
                }
            }
            else
            {
                printf("List is empty.\n");


            }      
            break;
         default:
            puts( "Invalid choice.\n" );
            instructions();
            break;
      } // end switch

      printf( "%s", "? " );
      scanf( "%u", &choice );
   } // end while

   puts( "End of run." );
} // end main

// display program instructions to user
void instructions( void )
{ 
   printf ( "Enter your choice:\n"
           "   1 to add an item to the queue\n"
           "   2 to remove an item from the queue\n"
           "   3 to end\n" );
} // end function instructions

// insert a node in at queue tail
void enqueue( QueueNodePtr *headPtr, char value )
{ 
   QueueNodePtr newPtr; // pointer to new node
   QueueNodePtr currentPtr; 
   QueueNodePtr previousPtr; 

   newPtr = (QueueNodePtr)malloc(sizeof(QueueNode));

   if ( newPtr != NULL ) { // is space available 
      newPtr->data = value;
      newPtr->nextPtr = NULL;
      newPtr->prevPtr = NULL; 
      previousPtr = NULL; 
      currentPtr = *headPtr; 

      while(currentPtr != NULL && value > currentPtr-> data)
      {
        previousPtr = currentPtr; 
        currentPtr = currentPtr->nextPtr; 
      }

      if(previousPtr == NULL)
      {
        newPtr->nextPtr = *headPtr; 

        if(*headPtr != NULL)
            (*headPtr)->prevPtr = newPtr; 
        *headPtr = newPtr; 
      }
      else
      {
        newPtr->prevPtr = previousPtr; 
        previousPtr->nextPtr = newPtr; 
        newPtr->nextPtr = currentPtr; 
            if(currentPtr != NULL)
                currentPtr->prevPtr = newPtr;
      }
   } // end if
   else {
      printf( "%c not inserted. No memory available.\n", value );
   } // end else
} // end function enqueue

// remove node from queue head
char dequeue( QueueNodePtr *headPtr, char value )
{ 

   QueueNodePtr tempPtr; // temporary node pointer
   QueueNodePtr currentPtr; 
   QueueNodePtr previousPtr;

  if(value == ( *headPtr )->data)
   {
        tempPtr = *headPtr;   

        if((*headPtr)->nextPtr !=NULL)
        {
            *headPtr = ( *headPtr )->nextPtr;
            (*headPtr)->prevPtr = NULL; 


        }           
        free(tempPtr);
        return value; 


   }
   else
   {
    previousPtr = *headPtr; 
    currentPtr = (*headPtr)->nextPtr; 

    while(currentPtr != NULL && currentPtr->data != value)
    {
        previousPtr = currentPtr; 
        currentPtr = currentPtr->nextPtr; 
    }
    if(currentPtr !=NULL)
    {
        tempPtr = currentPtr; 
        previousPtr->nextPtr= currentPtr->nextPtr; 
        free(tempPtr);
        return value; 
    }
   }
   return '\0';

} // end function dequeue

// return 1 if the queue is empty, 0 otherwise
int isEmpty( QueueNodePtr headPtr )
{ 
   return headPtr == NULL;
} // end function isEmpty

// print the queue
void printQueue( QueueNodePtr currentPtr )
{ 
   // if queue is empty
   if ( currentPtr == NULL ) {
      puts( "List is empty.\n" );


   } // end if

   else { 
      puts( "The list is:" );

      // while not end of queue
      while ( currentPtr != NULL ) { 

         printf( "%c --> ", currentPtr->data );
         currentPtr = currentPtr->nextPtr;
      } // end while

      puts( "NULL\n" );
   } // end else
} // end function printQueue

void reverse(QueueNodePtr currentPtr )
{
    QueueNodePtr tempPtr = NULL; 

    if(currentPtr == NULL)
    {   
        puts("  ");
    }
    else
    {

        while(currentPtr != NULL)
        {
            tempPtr = currentPtr; 
            currentPtr = currentPtr->nextPtr; 
        }
        printf("\nThe list in reverse is: \n");

        currentPtr = tempPtr; 
        while (currentPtr != NULL)
        {
            printf(" %c -->", currentPtr->data); 
            currentPtr = currentPtr->prevPtr;
        }
        printf("NULL");
        printf("\n\n");
    }

}

Recommended Answers

All 2 Replies

In general, not specifically looking at the code itself much, but more looking at the approach/debugging process, a few points:

"Also, when it comes to deleting the last node, the program kept running infinite. I tried to add system pause or break but nothing works."

"the program kept running infinite" could mean a few different things. You could be in a truly "infinite" loop. You could be have some memory leak or some other problem that APPEARS "infinite", but would actually eventually crash the program, some pointer pointing to the wrong place, some undefined behavior, all sorts of stuff. I don't know. Just pointing out that just because a program appears to be freezing/not doing anything, it may or may not mean that there's an infinite loop somewhere. But it's clearly not working as it should.

As for the system("PAUSE") debugging technique, I'll caution you to research the drawbacks of using that when debugging. A quick Google search will bring up some interesting articles, including this one from Daniweb's WaltP:

http://www.gidnetwork.com/b-61.html

That said, it can be a quick and dirty debugging technique, so while I don't recommend getting in the habit of using it, use it if you want, just understanding what's happening? The above article and others mention some alternatives. Using a debugger and breakpoints is a good one. Sprinkling some debugging statements in there to print out should help you track down where that infinite loop is, if it is indeed an infinite loop.

" I noticed if I have certain characters, it won't have issue to delete the characters but when I have certain characters, the reversed charcter displayed different character like if I want to delete n, this project will display E with dash mark above it. I don't know how to address this problem."

Ah, now this is interesting. Could mean a few things. Looking at your variable data, I see it is a char. You say you're storing and printing letters. So you're using the ASCII table, yes? Appropriate values for data would be 32 to 126. Those are the "printable" values. If you try to "print" other values as a char, your output looks messed up, as you found out: "E with dash mark above it". That's not a printable ASCII character.

So try printing out the character not as a character but as an integer. Change the "%c" to "%d" in your printf statement. If you get anything outside of the range of 32 to 126, you have identified a problem.

So try printing out the character not as a character but as an integer. Change the "%c" to "%d" in your printf statement. If you get anything outside of the range of 32 to 126, you have identified a problem.

Note that when I write this, I mean change the "%c" to "%d" for debugging purposes, not for final code purposes. Keep notes of what you are printing out when debugging so you can change it back when the debugging is done. The final product should print out characters, so you'll use "%c". Using "%d" just makes it clear what the data value is.

Or use a debugger.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.