Q:

how to delete node from doubly-linked list

I am currently trying to delete a Node from a doubly linked list, but when only one item is left it throws an access violation exception upon attempting to delete it on line 11 (*sPtr)->prevPtr = NULL;.  This is my current delete function:
char del(ListNodePtr *sPtr, char value)
{
    ListNodePtr previousPtr; /* pointer to previous node in list */
    ListNodePtr currentPtr; /* pointer to current node in list */
    ListNodePtr tempPtr; /* temporary node pointer */

    /* delete first node */
    if (value == (*sPtr)->data) {
        tempPtr = *sPtr; /* hold onto node being removed */
        *sPtr = (*sPtr)->nextPtr; /* de-thread the node */
        (*sPtr)->prevPtr = NULL;
        if ((*sPtr)->nextPtr ! = NULL) {
            free(tempPtr); /* free the de-threaded node */
        }
        return value;
    } /* end if */
    else {
        previousPtr = *sPtr;
        currentPtr = (*sPtr)->nextPtr;

        /* loop to find the correct location in the list */
        while (currentPtr ! = NULL && currentPtr->data ! = value) {
            previousPtr = currentPtr; /* walk to ...   */
            currentPtr = currentPtr->nextPtr; /* ... next node */
        } /* end while */

          /* delete node at currentPtr */
        if (currentPtr ! = NULL) {
            tempPtr = currentPtr;
            previousPtr->nextPtr = currentPtr->nextPtr;
            free(tempPtr);
            return value;
        } /* end if */
    } /* end else */

    return '\0';
} 

EDIT: I am going to add my main function and my print function in that order below for better context of what I am trying to do so that my question can be reopened:
here is my main function with my listNode struct:
struct listNode {
    char data; /* each listNode contains a character */
    struct listNode *nextPtr; /* pointer to next node*/
    struct listNode *prevPtr; /* pointer to previous node*/
}; /* end structure listNode */

typedef struct listNode ListNode; /* synonym for struct listNode */
typedef ListNode *ListNodePtr; /* synonym for ListNode* */

        /* prototypes */
void insert(ListNodePtr *sPtr, char value);
char del(ListNodePtr *sPtr, char value);
int isEmpty(ListNodePtr sPtr);
void printList(ListNodePtr currentPtr);
void printReverse(ListNodePtr currentPtr);
void instructions(void);

int main(void)
{
    ListNodePtr startPtr = NULL; /* initially there are no nodes */
    int choice; /* user's choice */
    char item; /* char entered by user */

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

    /* loop while user does not choose 3 */
    while (choice ! = 3) {

        switch (choice) {
        case 1:
            printf("Enter a character: ");
            scanf("\n%c", &item);
            insert(&startPtr, item); /* insert item in list */
            printList(startPtr);
            printReverse(startPtr);
            break;
        case 2:
            /* if list is not empty */
            if (! isEmpty(startPtr)) {
                printf("Enter character to be deleted: ");
                scanf("\n%c", &item);

                /* if character is found, remove it */
                if (del(&startPtr, item)) { /* remove item */
                    printf("%c deleted.\n", item);
                    printList(startPtr);
                    printReverse(startPtr);
                } /* end if */
                else {
                    printf("%c not found.\n\n", item);
                } /* end else */
            } /* end if */
            else {
                printf("List is empty.\n\n");
            } /* end else */

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

        printf("? "); 
        scanf("%d", &choice);
    } /* end while */

    printf("End of run.\n");
    return 0; /* indicates successful termination */
} /* end main */

and here are my printReverse and printList functions:
void printList(ListNodePtr currentPtr)
{

    /* if list is empty */
    if (currentPtr == NULL) {
        printf("List is empty.\n\n");
    } /* end if */
    else {
        printf("The list is:\n");

        /* while not the end of the list */
        while (currentPtr ! = NULL) {
            printf("%c --> ", currentPtr->data);
            currentPtr = currentPtr->nextPtr;
        } /* end while */

        printf("NULL\n\n");
    } /* end else */
} /* end function printList */

void printReverse(ListNodePtr currentPtr)
{
    /* if list is empty */
    if (currentPtr == NULL) {
        printf("List is empty.\n\n");
    } /* end if */
    else {
        printf("The list in reverse is:\n");

        while (currentPtr->nextPtr ! = NULL)
            currentPtr = currentPtr->nextPtr;

        /* while not the beginning of the list */
        while (currentPtr ! = NULL) {
            printf("%c --> ", currentPtr->data);
            currentPtr = currentPtr->prevPtr;
        } /* end while */

        printf("NULL\n\n");
    } /* end else */
} /* end function printList */

I really hope this makes it more clear on everything that is happening because I have been stuck on this for the last 3 days and there are little to no topics I can find online that talk about how to do what I'm doing, because the list is sorted alphabetically on insertion and deletion.  
So if anyone can attempt to tell me what is wrong and why it throws an access violation exception on line 11 when trying to delete the last item in the list I would be ever so grateful.  Thanks! 

A:

I think you've made things too complicated.  You don't separate the "list" type from the "node" type, but I think you can get by without passing pointers-to-pointers if you just return a replacement. 
You might want to write a "find" method to handle looking up the character and returning a pointer to that node. 
/**
  Delete the node containing value from the list starting with start. 
  If value is not found in list, then the list is unchanged.  Returns
  a replacement value for start, which may be needed if the value is
  contain in the start node. 
*/

ListNodePtr  del(ListNodePtr start, char value)
{
    ListNodePtr curr;

    for (curr = start; curr && curr->data ! = value; curr = curr->nextPtr) {
        // skip this node
    }

    if (! curr) {
        // Value not found in list.  List is unchanged. 
        return start;
    }

    /* Compute return value */

    if (curr == start) {
        start = start->nextPtr;
    }

    /* Remove curr node from chain */

    if (curr->prevPtr) {
        curr->prevPtr->nextPtr = curr->nextPtr;
    }

    if (curr->nextPtr) {
        curr->nextPtr->prevPtr = curr->prevPtr;
    }

    free(curr);
    return start;
}

