0

Im working on a program that inputs book data in a struct, and deletes an element upon the user's request. However, Im having difficulty figuring out the best way to do delete the requested book. Do you think Im headed in the right direction?

struct Data{                        //struct of data
    string title;
    string author;
    string publisher;
};

void remove (Data *ptr, string title, string author, string publisher, int num)
{
    string book_rem;
    cout << "What book do you want to remove?" << endl;
    getline (cin, book_rem);

    for (int i=0;i<num;i++)
    {
        if (ptr[i].title == book_rem) // check for equality
            {
               for (int j = 0; j < num; j++)  //shift over elements in new array
               ptr[j] = ptr[j+1];
               ptr[j-1] = 0;
            }   
        else 
           {
            cout << "book not found!" << endl;
           }
    }
}

I know my logic is off ?.. but my tutor said i was close..if you have any good resources or links please send them this way these pointers have me slightly confused on the best way to get it done.

5
  • 3
    Why not use a std::vector? All the work is already done for you. Commented Mar 1, 2012 at 5:31
  • ah we havent dove into vectors just yet :/ i will look them up thnx Commented Mar 1, 2012 at 5:32
  • 1
    for (int j = num; j < num; j++) //shift over elements in new array loops over nothing! Commented Mar 1, 2012 at 5:35
  • How was each element stored in ptr? Each element was allocated dynamic memory using new? In that case you need to deallocate the memory by calling delete. Commented Mar 1, 2012 at 5:40
  • When, if you find the title, you need to adjust the array from i onwards upto num'th entry. also, maintain size of your list somewhere. one way could be, to pass num as a reference and decrement it appropriately. Commented Mar 1, 2012 at 5:47

5 Answers 5

2

Well in the for loop, you are marking that the book wasn't found immediately after the first if (ptr[i].title == book_rem). What if the book is present as the 2nd element or thereafter.

You should divide your work into two parts as follows:

  • Search for the book.
  • Delete it if found, otherwise print "Not Found".

He is what it may look like inside the loop:

for (int i = 0 ; i < num ; i++) {
    if (ptr[i].title == book_rem) // check for equality
    {
        break;
    }  
}

And then outside the loop, check if the book was found, and do the required stuff:

if ( i < num ) {// Book was found as i is less than size.
    /*
        You don't have to shift over elements in the array.
        I'm assuming your list isn't sorted, so you can just transfer 
        the last element in the array to the position pointed by i, and 
        then decrement the size by 1. 
    */
    // Copy all the elements from ptr[num-1] to ptr[1].
    num = num - 1;
}
else {
    cout << "book not found!" << endl;
}
Sign up to request clarification or add additional context in comments.

Comments

1
void remove (Data *ptr, int & num)
{
    string book_rem;
    cout << "What book do you want to remove?" << endl;
    getline (cin, book_rem);

    for (int i = 0; i < num; i++)
    {
        if (ptr[i].title == book_rem) // check for equality
        {
            for (int j = j; j + 1 < num; j++)  //shift over elements in new array
            {
                ptr[j] = ptr[j+1];
            }
            num--;        // this will modify the original
            return;
        }
    }
    cout << "book not found!" << endl;
}
  • The 2nd, 3rd and 4th parameters are not used anywhere, so I removed them
  • Passing num by reference allows you to modify the original
  • You need to shift all the elements past the the removed one, so j must start at i
  • You access the array at index j+1, so the condition should be j+1 < num
  • The return statement would exit the function if the element was deleted
  • If the function reaches the last line, it means no match was found

1 Comment

If the order is not important, you can simply move ptr[num-1] to ptr[i]. This is much faster than shifting all the elements after the removed one.
1

Instead of reinventing the wheel, I would suggest using a std::list, considering the task you are performing. A list (as opposed to a vector) enables internally efficient removal and insertion of elements. However, unlike a vector, the memory a list consumes is not contiguous, that is, elements are not guaranteed to be 'side by side' in memory. If you are continually removing and adding elements, a list is a better bet, whereas if you need to continually access elements 'randomly', you're likely to be better off with a vector.

You can remove an element from a list easily: Use list::erase to remove an element via an iterator and list::remove to remove an element by value (which seems appropriate for you). More information can be found here: http://www.cplusplus.com/reference/stl/list/

Comments

1

Instead of writing your own container, use std::map (map book title to author+publisher), std::set or std::list. Or at least use std::find_if to find the book. With std::set only one combination of title+author+publisher can be stored in container. With std::map, you'll be able to quickly find publisher/authoer by title, with std::list you'll be able to insert/remove books quickly (and will be able to have duplicates in container).

Comments

1

You can just swap instead of copying.

void swap(Data &d1, Data &d2)
{
  std::swap(d1.title, d2.title);
  std::swap(d1.author, d2.author);
  std::swap(d1.publisher, d2.publisher);
}


void updateIndexes(int oldId, int newId)
{
  // update all indexes that use oldId to newId here
}

void remove (Data *ptr, int & num)
{
    string book_rem;
    cout << "What book do you want to remove?" << endl;
    getline (cin, book_rem);

    for (int i = 0; i < num; ++i)
    {
        if (ptr[i].title == book_rem)
        {
            swap(ptr[i], ptr[num-1]);
            --num;
            updateIndexes(num, i); // optional updating of indexes if any
            return;
        }
    }
    cout << "book not found!" << endl;
}

2 Comments

ah i get it now. so one when u say update all indexes is that thru a loop as well? also d1 and d2 would be my dynamic pters if im correct? thnx again.
No, you only updateIndexes() if somewhere you had stored the index of the element at num-1 but now it has moved to i. So you need to update those to i. If you haven't kept any such index, then updateIndexes is not needed at all.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.