Fix a variety of bugs found in dllist.c while addressing Issue #1559. (#1577)

* Fix a variety of bugs found in dllist.c while addressing Issue #1559.

* Added More descriptive error messages.
* Wrote google-test based unit tests for the DLL List library.
* Deleted old, incomplete test program.
* Added new function DLL_ListContainsPos which determines whether the given list contains the node at the given pos.
* DLLFind bug: Added check to determine whether a compare function has been specified, and emit an error message if it hasn’t.
* DLL_FindIndex bug: Corrected bounds checking.
* DLL_GetAt bug: Added check to ensure that the specified pos is actually in the given list.
* DLL_SetAt bug: Added check to ensure that the specified pos is actually in the given list.
* DLL_RemoveAt: corrected logic mistake in NULL ptr check. Added check to ensure that the specified pos is actually in the given list.
* DLL_InsertBefore bug: element count not correctly updated.
* DLL_InsertAfter: next and prev ptrs not correctly updated, which corrupted the list.
* DLL_GetNext bug: logic error in NULL ptr checks. Added check to ensure that the specified pos is actually in the given list.
* DLL_GetPrev bug: logic error in NULL ptr checks. Added check to ensure that the specified pos is actually in the given list.
* DLL_AddHead: Fixed NULL check logic error.
* DLL_AddTail: Fixed NULL check logic error.

* Address review comments, remove extraneous make target.

* Change false to 0 in dllist.c
This commit is contained in:
jmpenn 2023-10-05 13:33:38 -05:00 committed by GitHub
parent 73cc7aabfa
commit 1d0e324c6f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 1236 additions and 464 deletions

View File

@ -19,12 +19,13 @@ DLLIST *DLL_Create(void)
/* initializes a list */
/* return: none */
// JMP: This should return a status to let us know whether or not we succeeded
void DLL_Delete(DLLIST * list)
{
if (list == NULL) {
fprintf(stderr, "List is NULL");
fprintf(stderr, "Error (%s): List is NULL.\n", __FUNCTION__);
fflush(stderr);
return;
}
@ -34,15 +35,31 @@ void DLL_Delete(DLLIST * list)
}
}
/* Determine whether the given list contains the node at the given pos.
If it does, return 1, otherwise return 0.
*/
static int DLL_ListContainsPos( DLLPOS pos, DLLIST * list) {
/* returns number of elements in list */
/* return: count */
if ((list == NULL) || (pos == NULL)) {
return 0;
}
DLLPOS lpos = list->head;
while ((lpos != pos) && (lpos != NULL)) {
lpos = lpos->next;
}
if (lpos == NULL) {
return 0;
}
return 1;
}
// JMP: This should return a status to let us know whether or not we succeeded
void DLL_Init(DLLIST * list)
{
if (list == NULL) {
fprintf(stderr, "List is NULL");
fprintf(stderr, "Error (%s): List is NULL.\n", __FUNCTION__);
fflush(stderr);
return;
}
@ -62,7 +79,8 @@ int DLL_GetCount(DLLIST * list)
{
if (list == NULL) {
fprintf(stderr, "List is NULL");
fprintf(stderr, "Error (%s): List is NULL.\n", __FUNCTION__);
fflush(stderr);
return -1;
}
@ -80,9 +98,14 @@ void *DLL_Find(void *data, DLLIST * list)
{
DLLPOS pos;
if (list == NULL) {
fprintf(stderr, "List is NULL");
fprintf(stderr, "Error (%s): List is NULL.\n", __FUNCTION__);
fflush(stderr);
return NULL;
}
if (list->compare == NULL) {
fprintf(stderr, "Error (%s): List doesn't have a compare function.\n", __FUNCTION__);
fflush(stderr);
return NULL;
}
@ -105,7 +128,8 @@ DLLPOS DLL_FindPos(void *data, DLLIST * list)
if (list == NULL) {
fprintf(stderr, "List is NULL");
fprintf(stderr, "Error (%s): List is NULL.\n", __FUNCTION__);
fflush(stderr);
return NULL;
}
@ -122,6 +146,7 @@ DLLPOS DLL_FindPos(void *data, DLLIST * list)
/* find position at given index */
/* return: position of nth element */
DLLPOS DLL_FindIndex(int n, DLLIST * list)
{
int nPos = 0;
@ -129,13 +154,14 @@ DLLPOS DLL_FindIndex(int n, DLLIST * list)
if (list == NULL) {
fprintf(stderr, "List is NULL");
fprintf(stderr, "Error (%s): List is NULL.\n", __FUNCTION__);
fflush(stderr);
return NULL;
}
if (n < 0 && n >= list->count) {
fprintf(stderr, "Index is either negative or exceeds the number of elements in the list");
if ( (n < 0) || (n >= list->count) ) {
fprintf(stderr, "Error (%s): Index is either negative or exceeds the number of elements in the list.\n", __FUNCTION__);
fflush(stderr);
return NULL;
}
@ -154,23 +180,18 @@ DLLPOS DLL_FindIndex(int n, DLLIST * list)
void *DLL_GetAt(DLLPOS pos, DLLIST * list)
{
if (list == NULL) {
fprintf(stderr, "List is NULL");
if ((list == NULL) || (pos == NULL)) {
fprintf(stderr, "Error (%s): Either pos, list, or both are NULL.\n", __FUNCTION__);
fflush(stderr);
return NULL;
}
if (pos == NULL) {
fprintf(stderr, "Position is NULL");
if ( !DLL_ListContainsPos(pos, list) ) {
fprintf(stderr, "Error (%s): The specified list doesn't contain the specified node (pos).\n", __FUNCTION__);
fflush(stderr);
return NULL;
}
if (list) {
return pos->info;
}
return (NULL);
}
/* sets info at a position */
@ -178,21 +199,19 @@ void *DLL_GetAt(DLLPOS pos, DLLIST * list)
void *DLL_SetAt(DLLPOS pos, void *info, DLLIST * list)
{
void *ret;
if (pos == NULL && list == NULL) {
fprintf(stderr, "List and Position are NULL");
if ((list == NULL) || (pos == NULL)) {
fprintf(stderr, "Error (%s): Either pos, list, or both are NULL.\n", __FUNCTION__);
fflush(stderr);
return NULL;
}
if (pos != NULL && list != NULL) {
ret = pos->info;
pos->info = info;
return ret;
if ( !DLL_ListContainsPos(pos, list) ) {
fprintf(stderr, "Error (%s): The specified list doesn't contain the specified node (pos).\n", __FUNCTION__);
fflush(stderr);
return NULL;
}
return (NULL);
void* prev_info = pos->info;
pos->info = info;
return prev_info;
}
@ -203,35 +222,38 @@ void *DLL_RemoveAt(DLLPOS pos, DLLIST * list)
{
void *ret;
if (pos == NULL && list == NULL) {
fprintf(stderr, "List and Position are NULL");
if ((pos == NULL) || (list == NULL)) {
fprintf(stderr, "Error (%s): List or Position is NULL.\n", __FUNCTION__);
fflush(stderr);
return NULL;
}
if (pos != NULL && list != NULL) {
list->count--;
if (pos->prev != NULL) {
pos->prev->next = pos->next;
if (pos->next != NULL)
pos->next->prev = pos->prev;
if ( !DLL_ListContainsPos(pos, list) ) {
fprintf(stderr, "Error (%s): The specified list doesn't contain the specified node (pos).\n", __FUNCTION__);
fflush(stderr);
return NULL;
}
if (pos->prev != NULL) { // check whether pos is the head
pos->prev->next = pos->next; // pos is not the head
if (pos->next != NULL) // check whether pos is the tail
pos->next->prev = pos->prev; // pos is not the tail
else
list->tail = pos->prev;
} else if (pos->next != NULL) {
list->head = pos->next;
list->tail = pos->prev; // pos is the tail
} else if (pos->next != NULL) { // pos is the head, check whether it's also the tail
list->head = pos->next; // pos not the tail
pos->next->prev = NULL;
} else {
} else { // pos is both the head and the tail
list->head = NULL;
list->tail = NULL;
}
ret = pos->info;
list->count --;
ret = pos->info;
free(pos);
return ret;
}
return (NULL);
}
/* removes all elements in the list */
@ -244,7 +266,8 @@ void DLL_RemoveAll(DLLIST * list)
if (list == NULL) {
fprintf(stderr, "List is NULL");
fprintf(stderr, "Error (%s): List is NULL.\n", __FUNCTION__);
fflush(stderr);
return;
}
@ -263,13 +286,6 @@ DLLPOS DLL_InsertBefore(DLLPOS pos, void *data, DLLIST * list)
{
if (pos != NULL && list != NULL) {
DLLPOS newpos = (DLLPOS) malloc(sizeof(DLLNODE));
if (pos == NULL && list == NULL) {
fprintf(stderr, "List and Position are NULL");
return NULL;
}
newpos->info = data;
if (pos->prev == NULL) {
newpos->next = list->head;
@ -282,8 +298,11 @@ DLLPOS DLL_InsertBefore(DLLPOS pos, void *data, DLLIST * list)
newpos->next = pos;
pos->prev = newpos;
}
list->count++;
return newpos;
}
fprintf(stderr, "Error (%s): Either List, Position, or both are NULL.\n", __FUNCTION__);
fflush(stderr);
return (NULL);
}
@ -295,16 +314,9 @@ DLLPOS DLL_InsertAfter(DLLPOS pos, void *data, DLLIST * list)
{
if (pos != NULL && list != NULL) {
DLLPOS newpos = (DLLPOS) malloc(sizeof(DLLNODE));
if (pos == NULL && list == NULL) {
fprintf(stderr, "List and Position are NULL");
return NULL;
}
newpos->info = data;
if (pos->next == NULL) {
newpos->next = list->tail;
newpos->prev = list->tail;
newpos->next = NULL;
list->tail = newpos;
pos->next = newpos;
@ -314,56 +326,53 @@ DLLPOS DLL_InsertAfter(DLLPOS pos, void *data, DLLIST * list)
newpos->prev = pos;
pos->next = newpos;
}
list->count++;
return newpos;
}
fprintf(stderr, "Error (%s): Either List, Position, or both are NULL.\n", __FUNCTION__);
fflush(stderr);
return (NULL);
}
/* gets the next position in the list */
/* return: the data at the current pos */
void *DLL_GetNext(DLLPOS * pos, DLLIST * list)
void *DLL_GetNext(DLLPOS* pos_p, DLLIST * list)
{
void *ret;
if (pos == NULL && list == NULL) {
fprintf(stderr, "List and Position are NULL");
return NULL;
}
if (pos != NULL && list != NULL) {
ret = (*pos)->info;
*pos = (*pos)->next;
return ret;
}
if ((list == NULL) || (pos_p == NULL)) {
fprintf(stderr, "Error (%s): Either the List, the Position pointer, or both are NULL.\n", __FUNCTION__);
fflush(stderr);
return (NULL);
}
if ( !DLL_ListContainsPos(*pos_p, list) ) {
fprintf(stderr, "Error (%s): List doesn't contain a node at the given position.\n", __FUNCTION__);
fflush(stderr);
return NULL;
}
void* data = (*pos_p)->info;
*pos_p = (*pos_p)->next;
return data;
}
/* gets the previous position in the list */
/* return: the data at the current position */
void *DLL_GetPrev(DLLPOS * pos, DLLIST * list)
void *DLL_GetPrev(DLLPOS * pos_p, DLLIST * list)
{
void *ret;
if (pos == NULL && list == NULL) {
fprintf(stderr, "List and Position are NULL");
return NULL;
}
if (pos != NULL && list != NULL) {
ret = (*pos)->info;
*pos = (*pos)->prev;
return ret;
}
if ((list == NULL) || (pos_p == NULL)) {
fprintf(stderr, "Error (%s): Either the List, the Position pointer, or both are NULL.\n", __FUNCTION__);
fflush(stderr);
return (NULL);
}
if ( !DLL_ListContainsPos(*pos_p, list) ) {
fprintf(stderr, "Error (%s): List doesn't contain a node at the given position.\n", __FUNCTION__);
fflush(stderr);
return NULL;
}
void* data = (*pos_p)->info;
*pos_p = (*pos_p)->prev;
return data;
}
/* adds an element to the head of the list */
/* return: the position of the new element */
@ -372,13 +381,6 @@ DLLPOS DLL_AddHead(void *data, DLLIST * list)
{
if (list != NULL) {
DLLPOS newpos = (DLLPOS) malloc(sizeof(DLLNODE));
if (list == NULL) {
fprintf(stderr, "List is NULL");
return NULL;
}
newpos->info = data;
if (list->head == NULL) {
list->head = newpos;
@ -394,6 +396,8 @@ DLLPOS DLL_AddHead(void *data, DLLIST * list)
list->count++;
return newpos;
}
fprintf(stderr, "Error (%s): List is NULL.\n", __FUNCTION__);
fflush(stderr);
return (NULL);
}
@ -405,13 +409,6 @@ DLLPOS DLL_AddTail(void *data, DLLIST * list)
{
if (list != NULL) {
DLLPOS newpos = (DLLPOS) malloc(sizeof(DLLNODE));
if (list == NULL) {
fprintf(stderr, "List is NULL");
return NULL;
}
newpos->info = data;
if (list->tail == NULL) {
list->head = newpos;
@ -427,6 +424,8 @@ DLLPOS DLL_AddTail(void *data, DLLIST * list)
list->count++;
return newpos;
}
fprintf(stderr, "Error (%s): List is NULL.\n", __FUNCTION__);
fflush(stderr);
return (NULL);
}
@ -438,7 +437,8 @@ DLLPOS DLL_GetHeadPosition(DLLIST * list)
{
if (list == NULL) {
fprintf(stderr, "List is NULL");
fprintf(stderr, "Error (%s): List is NULL.\n", __FUNCTION__);
fflush(stderr);
return NULL;
}
@ -454,9 +454,9 @@ DLLPOS DLL_GetHeadPosition(DLLIST * list)
DLLPOS DLL_GetTailPosition(DLLIST * list)
{
if (list == NULL) {
fprintf(stderr, "List is NULL");
fprintf(stderr, "Error (%s): List is NULL.\n", __FUNCTION__);
fflush(stderr);
return NULL;
}

View File

@ -0,0 +1,60 @@
#SYNOPSIS:
#
# make [all] - makes everything.
# make TARGET - makes the given target.
# make clean - removes all files generated by make.
include ${TRICK_HOME}/share/trick/makefiles/Makefile.common
# Flags passed to the preprocessor.
TRICK_CXXFLAGS += -I$(GTEST_HOME)/include -I$(TRICK_HOME)/include -g -Wall -Wextra ${TRICK_SYSTEM_CXXFLAGS} ${TRICK_TEST_FLAGS}
TRICK_LIBS = ${TRICK_LIB_DIR}/libtrick.a
TRICK_EXEC_LINK_LIBS += -L${GTEST_HOME}/lib64 -L${GTEST_HOME}/lib -lgtest -lgtest_main -lpthread
# Added for Ubuntu... not required for other systems.
TRICK_EXEC_LINK_LIBS += -lpthread
# ==================================================================================
# All tests produced by this Makefile. Add new tests you create to this list.
# ==================================================================================
TESTS = dllist_unittest
# List of XML files produced by the tests.
unittest_results = $(patsubst %,%.xml,$(TESTS))
# List if Test-specific object files.
unittest_objects = $(patsubst %,%.o,$(TESTS))
# House-keeping build targets.
# ==================================================================================
# TARGETS
# ==================================================================================
all : test
test: unit_tests $(unittest_results)
unit_tests: $(TESTS)
clean :
rm -f $(TESTS)
rm -f *.o
# ==================================================================================
# Generate JUNIT (XML) Test Results
# ==================================================================================
$(unittest_results): %.xml: %
./$< --gtest_output=xml:${TRICK_HOME}/trick_test/$@
# ==================================================================================
# Build Unit test Objects
# ==================================================================================
$(unittest_objects): %.o: %.cpp
$(TRICK_CXX) $(TRICK_CXXFLAGS) -c $<
# ==================================================================================
# Build Unit test programs
# ==================================================================================
$(TESTS) : %: %.o
$(TRICK_CXX) $(TRICK_SYSTEM_LDFLAGS) -o $@ $^ -L${TRICK_HOME}/lib_${TRICK_HOST_CPU} $(TRICK_LIBS) $(TRICK_EXEC_LINK_LIBS)

File diff suppressed because it is too large Load Diff

View File

@ -1,236 +0,0 @@
#############################################################################
# Makefile:
# This is a makefile for maintaining the
# '/stroke/users/trick_dev/trick_source/trick_adt/test_program'
# directory. This make file was automatically generated by the
# "make_build" program.
#
#############################################################################
# Creation:
# Author: Trick auto makefile program - "make_build", Version 1998.1.Beta
# Date: 13:46:16 on Monday 16 February 1998
#
#############################################################################
#
# To get a desription of the arguments accepted by this makefile,
# type 'make help'
#
#############################################################################
#############################################################################
## DIRECTORY DEFINITIONS ##
#############################################################################
ifndef TRICK_HOST_CPU
TRICK_HOST_CPU := $(shell trick-gte TRICK_HOST_CPU)
endif
ifndef TRICK_HOST_TYPE
TRICK_HOST_TYPE := $(shell trick-gte TRICK_HOST_TYPE)
endif
TRICK_VER = 1998.1.Beta
CWD_DIR = /stroke/users/trick_dev/trick_source/trick_adt/test_program
SRC_DIR =
OBJ_DIR = object_${TRICK_HOST_CPU}
MODEL_BIN_DIR = $(OBJ_DIR)
#############################################################################
## UTILITY DEFINITIONS ##
#############################################################################
SHELL = /bin/sh
AWK = awk
SED = sed
LEX = lex
YACC = yacc
CD = cd
MV = mv
RM = rm
#
# Make information
#
MAKEFILE = Makefile
AWKTEMPFILE = awk.temp
SEDTEMPFILE = sed.temp
MAKEDEPEND = makedepend
FTNDEPEND = ftn_depend
#
# Awk program to filter out system include dependencies
#
AWK_PRGM = $(TRICK_HOME)/bin/depend.awk
#############################################################################
## COMPILER DEFINITIONS ##
#############################################################################
#
# C Compilation Variables
#
CPP_PRE_DEFS =
CPP_POST_DEFS =
CPPFLAGS = $(CPP_PRE_DEFS) $(TRICK_CFLAGS) $(CPP_POST_DEFS)
ifeq ($(TRICK_FORCE_32BIT), 1)
CPPFLAGS += -m32
endif
#
# FORTRAN Compilation Variables
#
FCFLAGS = $(TRICK_FTNFLAGS)
#############################################################################
## FILE NAME DEFINITIONS ##
#############################################################################
MODEL_C_SRC = \
$(SRC_DIR)test.c
MODEL_IO_SRC =
MODEL_FTN_SRC =
MODEL_C_OBJS = \
$(OBJ_DIR)/test.o
MODEL_IO_OBJS =
MODEL_FTN_OBJS =
#############################################################################
## SPECIAL TARGETS ##
#############################################################################
.PRECIOUS: $(MODEL_C_SRC) $(MODEL_FTN_SRC)
#############################################################################
## MODEL TARGETS ##
#############################################################################
default: verify_trick_version object_files
verify_trick_version:
@if ( test `trick_version $(TRICK_VER)` != $(TRICK_VER) ) then \
echo "Make ERROR:" ; \
echo " The current Makefile was generated with version $(TRICK_VER) of the Trick" ; \
echo " processors which is incompatible with the the current Trick version," ; \
echo " `trick_version`. Run 'catalog -versions' to get a complete list of" ; \
echo " potential incompatibility problems. You must delete this Makefile" ; \
echo " before make_build will generate a new Makefile." ; \
exit 1 ; \
fi
object_files: $(OBJ_DIR) $(MODEL_IO_OBJS) $(MODEL_C_OBJS) $(MODEL_FTN_OBJS)
@ echo "$(CWD_DIR) object files up to date"
help :
@ echo "\
Source Directory Make Options:\n\
make - Compiles are source files\n\
\n\
make ICG - Deletes the io_src directory and runs ICG\n\
on all pertinent *.h files\n\
\n\
make catalog - Deletes the local catalog and builds a new one\n\
\n\
make depend - Adds file dependencies to Makefile\n\
\n\
make io_clean - Deletes the local io_src directory\n\
\n\
make catalog_clean - Deletes the local catalog directory\n\
\n\
make clean - Deletes the object code directory\n\
\n\
make real_clean - Deletes html/, io_src/, catalog/,\n\
and object_${TRICK_HOST_CPU}/ directories\n"
$(OBJ_DIR):
@ mkdir -p $(OBJ_DIR)
@ echo "Created $(OBJ_DIR)"
#
# MODEL_IO_OBJS
#
#
# MODEL_IO_SRC
#
#
# MODEL_C_OBJS
#
$(OBJ_DIR)/test.o : $(SRC_DIR)test.c
$(TRICK_CC) $(CPPFLAGS) -c test.c -o $(OBJ_DIR)/test.o
$(TRICK_CC) ${TRICK_CFLAGS} $(OBJ_DIR)/test.o -L${TRICK_HOME}/lib_${TRICK_HOST_CPU} -o test -ltrick_adt
#
# LEX/YACC SOURCE
#
#
# MODEL_F_OBJS
#
#
# ICG Target
#
ICG: verify_trick_version io_clean $(OBJ_DIR) $(MODEL_IO_OBJS)
@ echo "IO files are up to date!"
#############################################################################
## MAINTENANCE TARGETS ##
#############################################################################
depend:
$(MAKEDEPEND) -f $(MAKEFILE)
@ touch $(AWKTEMPFILE)
@ $(MAKEDEPEND) -f $(AWKTEMPFILE) -Iinclude -- $(CPPFLAGS) -- $(MODEL_C_SRC) $(MODEL_IO_SRC)
@ $(FTNDEPEND) -- $(FCFLAGS) -- $(MODEL_FTN_SRC) >> $(AWKTEMPFILE)
@ $(AWK) -f $(AWK_PRGM) $(AWKTEMPFILE) >> $(SEDTEMPFILE)
@ $(RM) -f $(AWKTEMPFILE)
@ $(SED) -e 's:$(TRICK_HOME):$$(TRICK_HOME):' $(SEDTEMPFILE) >> $(AWKTEMPFILE)
@ $(SED) s:\$\(MODEL_BIN_DIR\)/src:\$\(MODEL_BIN_DIR\): $(AWKTEMPFILE) >> $(MAKEFILE)
@ $(RM) -f $(AWKTEMPFILE) $(AWKTEMPFILE).bak $(SEDTEMPFILE)
@ echo "Appended dependencies to $(MAKEFILE)"
io_clean: verify_trick_version
$(RM) -rf io_src
real_clean: verify_trick_version clean io_clean
$(RM) -rf html *~ *.bak core
@ echo "Directory is really clean!"
clean: verify_trick_version
$(RM) -rf $(LIB) $(OBJ_DIR)
@ echo "Object files successfully removed"
catalog_clean : verify_trick_version
$(RM) -rf catalog
@ echo "Catalog purged"
catalog : verify_trick_version catalog_clean $(MODEL_IO_SRC)
MIS
@ echo "$(CWD_DIR) Catalog rebuilt"
#############################################################################
#------------------------------------------------------------------------
# Below this are the object module dependencies, built with makedepend.
#------------------------------------------------------------------------
# DO NOT DELETE THIS LINE -- make depend depends on it.
$(MODEL_BIN_DIR)/test.o: ../bst.h

View File

@ -1,103 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include "../bst.h"
#include <string.h>
typedef struct
{
int key;
char* data;
}ITEM;
int compare(void* left, void* right)
{
ITEM* pitem1=(ITEM*)left;
ITEM* pitem2=(ITEM*)right;
if(pitem1->key-pitem2->key < 0)
return -1;
else if(pitem1->key-pitem2->key > 0)
return 1;
else
return 0;
}
void main()
{
short done=0;
int newnum;
char ch;
char buffer[256];
ITEM* newitem;
BST bst;
bstNode* node;
ITEM tempitem;
bstInit(&bst);
bstSetCompareFunc(&bst,compare);
while(!done)
{
fprintf(stderr,"(1) Add Item\n(2) Lookup\n(3) Remove Item\n");
ch=getchar();
fflush(stdin);
switch(ch)
{
case '1':
newitem=(ITEM*)malloc(sizeof(ITEM));
printf("\nEnter a string\n");
scanf("%s",buffer);
newitem->data=strdup(buffer);
printf("Enter key\n");
scanf("%d",&newnum);
newitem->key=newnum;
printf("inserting at %d\n",newnum);
bstInsert(newitem,&bst);
break;
case '2':
printf("Enter key\n");
scanf("%d",&newnum);
printf("Looking for %d\n",newnum);
tempitem.key=newnum;
node=bstFind(&tempitem,&bst);
if(node != NULL)
{
newitem=(ITEM*)bstGetInfo(node);
printf("found %s\n",newitem->data);
}
else
{
printf("Item not found\n");
}
break;
case '3':
printf("Enter key\n");
scanf("%d",&newnum);
tempitem.key=newnum;
node=bstFind(&tempitem,&bst);
if(node != NULL)
{
newitem=(ITEM*)bstGetInfo(node);
printf("removing %s\n",newitem->data);
bstDelete(node,&bst);
}
else
{
printf("Item not found\n");
}
break;
default:done=1;
}
fflush(stdin);
}
}