Bag with receipts

Question1:

In this project, you will implement a new class called a bag with receipts. This new class is similar to an ordinary bag, but the way that items are added and removed is different. Each time an item is added to a bag with receipts, the insert function returns a unique integer called the receipt. Later, when you want to remove an item, you must provide a copy of the receipt as a parameter to the remove function. The remove function removes the item whose receipt has been presented, and also returns a copy of that item through a reference parameter.
Here is an implementation idea: A bag with receipts can have two private arrays, like this:

class bag_with_receipts
{
...
private:
	value_type data[CAPACITY];
	bool in_use[CAPACITY];
};

Arrays such as these, which have the same size, are called parallel arrays. The idea is to keep track of which parts of the data array are being used by placing boolean values in the second array. When in_use[i] is true, then data[i] is currently being used; when in_use[i] is false, then data[i] is currently unused. When a new item is added, we will find the first spot that is currently unused and store the new item there. The receipt for the item is the index of the location where the new item is stored.

Answer:

bag_with_receipt.h

// FILE: bag_with_receipts1.h
// CLASS PROVIDED: bag_with_receipts (part of the namespace main_savitch_3)
//
// TYPEDEF and MEMBER CONSTANTS for the bag_with_receipts class:
//   typedef ____ value_type
//     bag_with_receipts::value_type is the data type of the items in the bag_with_receipts. It may be any of
//     the C++ built-in types (int, char, etc.), or a class with a default
//     constructor, an assignment operator, and operators to
//     test for equality (x == y) and non-equality (x != y).
//
//   typedef ____ size_type
//     bag_with_receipts::size_type is the data type of any variable that keeps track of how many items
//     are in a bag_with_receipts.
//
//   static const size_type CAPACITY = _____
//     bag_with_receipts::CAPACITY is the maximum number of items that a bag_with_receipts can hold.
//
// CONSTRUCTOR for the bag_with_receipts class:
//   bag_with_receipts( )
//     Postcondition: The bag_with_receipts has been initialized as an empty bag_with_receipts.
//
// MODIFICATION MEMBER FUNCTIONS for the bag_with_receipts class:
//   size_type erase(const value_type& target);
//     Postcondition: All copies of target have been removed from the bag_with_receipts.
//     The return value is the number of copies removed (which could be zero).
//
//   bool erase_one(const value_type& target)
//     Postcondition: If target was in the bag_with_receipts, then one copy has been removed;
//     otherwise the bag_with_receipts is unchanged. A true return value indicates that one
//     copy was removed; false indicates that nothing was removed.
//
//   void insert(const value_type& entry)
//     Precondition:  size( ) < CAPACITY.
//     Postcondition: A new copy of entry has been added to the bag_with_receipts.
//
//   void operator +=(const bag_with_receipts& addend)
//     Precondition:  size( ) + addend.size( ) <= CAPACITY.
//     Postcondition: Each item in addend has been added to this bag_with_receipts.
//
// CONSTANT MEMBER FUNCTIONS for the bag_with_receipts class:
//   size_type size( ) const
//     Postcondition: The return value is the total number of items in the bag_with_receipts.
//
//   size_type count(const value_type& target) const
//     Postcondition: The return value is number of times target is in the bag_with_receipts.
//
// NONMEMBER FUNCTIONS for the bag_with_receipts class:
//   bag_with_receipts operator +(const bag_with_receipts& b1, const bag_with_receipts& b2)
//     Precondition:  b1.size( ) + b2.size( ) <= bag_with_receipts::CAPACITY.
//     Postcondition: The bag_with_receipts returned is the union of b1 and b2.
//
// VALUE SEMANTICS for the bag_with_receipts class:
//    Assignments and the copy constructor may be used with bag_with_receipts objects.

#ifndef MAIN_SAVITCH_BAG1_H
#define MAIN_SAVITCH_BAG1_H
#include <cstdlib>  // Provides size_t

namespace main_savitch_3
{
    class bag_with_receipts
    { 
    public:
        // TYPEDEFS and MEMBER CONSTANTS
        typedef int value_type;
        typedef std::size_t size_type;
        static const size_type CAPACITY = 30;
        // CONSTRUCTOR
        bag_with_receipts( ); 
        // MODIFICATION MEMBER FUNCTIONS
        size_type erase(const value_type& target);
        bool erase_one(const value_type& target);
        void remove(int receipt, value_type& copy_item);
        int insert(const value_type& entry);
        void operator +=(const bag_with_receipts& addend);
        void operator -=(const bag_with_receipts& subend);
        // CONSTANT MEMBER FUNCTIONS
        size_type size( ) const { return used; }
        size_type count(const value_type& target) const;
    private:
        value_type data[CAPACITY];  // The array to store items
        bool in_use[CAPACITY];      // parallel arrays
        size_type used;             // How much of array is used
    };

    // NONMEMBER FUNCTIONS for the bag_with_receipts class
    bag_with_receipts operator +(const bag_with_receipts& b1, const bag_with_receipts& b2);
    bag_with_receipts operator -(const bag_with_receipts& b1, const bag_with_receipts& b2);
}

#endif

bag_with_receipt.cpp

// FILE: bag_with_receipts1.cpp
// CLASS IMPLEMENTED: bag_with_receipts (see bag_with_receipts1.h for documentation)
// INVARIANT for the bag_with_receipts class:
//   1. The number of items in the bag_with_receipts is in the member variable used;
//   2. For an empty bag_with_receipts, we do not care what is stored in any of data; for a
//      non-empty bag_with_receipts the items in the bag_with_receipts are stored in data[0] through
//      data[used-1], and we don't care what's in the rest of data.

#include <algorithm> // Provides copy function
#include <cassert>   // Provides assert function
#include "bag_with_receipts.h"
using namespace std;

namespace main_savitch_3
{
    const bag_with_receipts::size_type bag_with_receipts::CAPACITY;

    bag_with_receipts::bag_with_receipts(){
        used = 0;
        in_use[CAPACITY] = {false};
    }

    bag_with_receipts::size_type bag_with_receipts::erase(const value_type& target)
    {
	size_type index = 0;
	size_type many_removed = 0;

	while (index < CAPACITY)
	{
	    // if (data[index] == target)
	    // {
		// --used;
		// data[index] = data[used];
		// ++many_removed;
	    // }
	    // else
		// ++index;
        if(data[index] == target && in_use[index]){
            ++many_removed;
            in_use[index] =  false;// erase it
        }
        index++;
	}
    used -= many_removed;
	return many_removed;
    }

    bool bag_with_receipts::erase_one(const value_type& target)
    {
	size_type index; // The location of target in the data array    

	// First, set index to the location of target in the data array,
	// which could be as small as 0 or as large as used-1. If target is not
	// in the array, then index will be set equal to used.
	index = 0; 
	while ((index < CAPACITY) && (data[index] != target))
	    ++index;

	if (index == CAPACITY)
	    return false; // target isn’t in the bag_with_receipts, so no work to do.

	// When execution reaches here, target is in the bag_with_receipts at data[index].
	// So, reduce used by 1 and copy the last item onto data[index].
	--used;
	// data[index] = data[used]; 
    in_use[index] = false; // erase it   
	return true;
    }

    int bag_with_receipts::insert(const value_type& entry)
    // Library facilities used: cassert
    {   
        assert(size( ) < CAPACITY);
        int i;
        for(i = 0; i < CAPACITY; i++){
            if(!in_use[i]){
                data[i] = entry;
                in_use[i] = true;
                ++used;
                break;
            }
        }
	    return i;// the receipt
    }

    void bag_with_receipts::remove(int receipt, value_type& copy_item){
        // remove the item whose receipt has been presented
        in_use[receipt] = false;
        --used;
        copy_item = data[receipt];
    }

    void bag_with_receipts::operator +=(const bag_with_receipts& addend)
    // Library facilities used: algorithm, cassert
    {
	assert(size( ) + addend.size( ) <= CAPACITY);
	
	// copy(addend.data, addend.data + addend.used, data + used);
    size_type index1, index2;
    index1 = index2 = 0;

    while(index1 < CAPACITY && index2 < CAPACITY){
        if(!in_use[index1]){
            while(!addend.in_use[index2]){
                index2++;
            }
            // now addend.data[index2] is actually in use
            in_use[index1] = true;
            data[index1] = addend.data[index2];
            index2++;
        }
        index1++;
    }

	used += addend.used;
    }

    void bag_with_receipts::operator -=(const bag_with_receipts& subend){
        // assert(size() - subend.size() >= 0);
        // for(size_type i = 0; i < subend.used; i++){
        //     for(size_type j = 0; j < this->used; j++){
        //         if(subend.data[i] == this->data[j]){
        //             this->erase_one(subend.data[i]);
        //             continue;
        //         }
        //     }
        // }
        for(size_type i = 0; i < subend.CAPACITY; i++){
            for(size_type j = 0; j < this->CAPACITY; j++){
                if((subend.data[i] == this->data[j]) && subend.in_use[i] && this->in_use[j]){
                    this->erase_one(subend.data[i]);
                    continue;
                }
            }
        }
    }

    bag_with_receipts::size_type bag_with_receipts::count(const value_type& target) const
    {
        size_type answer;
        size_type i;

        answer = 0;
        for (i = 0; i < CAPACITY; ++i)
            if (target == data[i] && in_use[i])
                ++answer;
        return answer;
    }

    bag_with_receipts operator +(const bag_with_receipts& b1, const bag_with_receipts& b2)
    // Library facilities used: cassert
    {
        bag_with_receipts answer;

        assert(b1.size( ) + b2.size( ) <= bag_with_receipts::CAPACITY);

        answer += b1; 
        answer += b2;
        return answer;
    }

    bag_with_receipts operator -(const bag_with_receipts& b1, const bag_with_receipts& b2){
        bag_with_receipts answer;

        // assert(b1.size() - b2.size() >= 0);
        answer = b1;
        answer -= b2;
        return answer;
    }
}

main.cpp

#include <iostream>
#include "bag_with_receipts.h"
#include <string>


using namespace std;

int main(){
    string girl = "Anna";
    // prepare to test
    main_savitch_3::bag_with_receipts bag1;// 现在是空的
    cout << "Declare a new bag called bag1." << endl;
    cout << "Keep inserting new items into bag1 until it is full." << endl;
    for(int i = 0; i < bag1.CAPACITY; i++){
        bag1.insert(i);
        cout << "Now there are " << bag1.size() << " item(s) in bag1." << endl;
    }
    cout << "Erase one item from bag1." << endl;
    if(bag1.erase_one(28) == true){
        cout << "Succeed to erase 28 from bag1." << endl;
    } else {
        cout << "Failed to erase 28 from bag1." << endl;
    }
    cout << "Insert another item (-2) into bag1." << endl;
    int receipt = bag1.insert(-2);
    cout << "Remove -2 from bag1." << endl;
    int res;
    bag1.remove(receipt, res);
    cout << "The item that we just removed is " << res << "." << endl;
    cout << "Now there are " << bag1.size() << " item(s) in bag1." << endl;
    cout << "Declare bag2" << endl;
    main_savitch_3::bag_with_receipts bag2;
    cout << "Insert 2 into bag2" << endl;
    bag2.insert(2);
    cout << "bag2 = bag1 + bag2" << endl;
    bag2 += bag1;
    cout << "How many 2s in bag2?" << endl;
    cout << "Here are " << bag2.count(2) << " 2(s)" << endl;
    cout << "Try to erase 2 from bag2." << endl;
    cout << "Erase " << bag2.erase(2) << " 2(s) from bag2" << endl;
    cout << "How many 2s in bag2 now?" << endl;
    cout << "Here are " << bag2.count(2) << " 2(s)" << endl;
    cout << "How many item(s) in bag2 now?" << endl;
    cout << "Here are " << bag2.size() << " item(s) in bag2 now." << endl;

    cout << "bag3 = bag1 - bag2" << endl;
    main_savitch_3::bag_with_receipts bag3 = bag1 - bag2;
    cout << "The size of bag3: " << bag3.size() << endl;
    return 0;
}

测试:

Declare a new bag called bag1.
Keep inserting new items into bag1 until it is full.
Now there are 1 item(s) in bag1.
Now there are 2 item(s) in bag1.
Now there are 3 item(s) in bag1.
Now there are 4 item(s) in bag1.
Now there are 5 item(s) in bag1.
Now there are 6 item(s) in bag1.
Now there are 7 item(s) in bag1.
Now there are 8 item(s) in bag1.
Now there are 9 item(s) in bag1.
Now there are 10 item(s) in bag1.
Now there are 11 item(s) in bag1.
Now there are 12 item(s) in bag1.
Now there are 13 item(s) in bag1.
Now there are 14 item(s) in bag1.
Now there are 15 item(s) in bag1.
Now there are 16 item(s) in bag1.
Now there are 17 item(s) in bag1.
Now there are 18 item(s) in bag1.
Now there are 19 item(s) in bag1.
Now there are 20 item(s) in bag1.
Now there are 21 item(s) in bag1.
Now there are 22 item(s) in bag1.
Now there are 23 item(s) in bag1.
Now there are 24 item(s) in bag1.
Now there are 25 item(s) in bag1.
Now there are 26 item(s) in bag1.
Now there are 27 item(s) in bag1.
Now there are 28 item(s) in bag1.
Now there are 29 item(s) in bag1.
Now there are 30 item(s) in bag1.
Erase one item from bag1.
Succeed to erase 28 from bag1.
Insert another item (-2) into bag1.
Remove -2 from bag1.
The item that we just removed is -2.
Now there are 29 item(s) in bag1.
Declare bag2
Insert 2 into bag2
bag2 = bag1 + bag2
How many 2s in bag2?
Here are 2 2(s)
Try to erase 2 from bag2.
Erase 2 2(s) from bag2
How many 2s in bag2 now?
Here are 0 2(s)
How many item(s) in bag2 now?
Here are 28 item(s) in bag2 now.
bag3 = bag1 - bag2
The size of bag3: 1

没有仔细检查,可能有严重谬误。。


  1. Data Structures and Other Objects Using C++ ( Fourth Edition ) Michael Main, Walter Savitch. p180 ↩︎

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Memories off

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值