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
没有仔细检查,可能有严重谬误。。
Data Structures and Other Objects Using C++ ( Fourth Edition ) Michael Main, Walter Savitch. p180 ↩︎