要求:
Templates
In this workshop, you design and code a class template and test it on two different classes.
LEARNING OUTCOMES
Upon successful completion of this workshop, you will have demonstrated the abilities to
• design and code a class template
• store key-value information in a pair of parallel arrays
• reflect on the material learned in this workshop
SPECIFICATIONS
The source files for this workshop include:
• KVList.h - defines a class template for a list of key-value pairs
• w4.cpp - the application that uses your class template
KVList Template
Design and code a class template named KVList for managing lists of key-value pairs. The classes generated by your template contain two parallel arrays of dimension N - a key array of type K and a value array of type V. K, V and Nare template parameters, which the porgrammer who uses your template can specify. Save your template in a header file named KVList.h.
Your design includes the following member functions:
• KVList() - default constructor - adopts a safe empty state
• size_t size() const - returns the number of entires in the key-value list
• const K& key(int i) const - returns an unmodifiable reference to the key of element i in the list
• const V& value(int i) const - returns an unmodifiable reference to the value of element i in the list
• KVList& add(const K&, const V&) - adds a new element to the list if room exists and returns a reference to the current object, does nothing if no room exists
• int find(const K& k) const - returns the index of the first element in the list with a key equal to k - defaults to 0
• KVList& replace(int i, const K& k, const V& v) - replaces element i in the list with the key and value received and returns a reference to the current object
Main Program
The main program that uses your template definition manages
1. an inventory of product-price pairs
2. a glossary of acronym-definition pairs
For each list, this main program sets the maximum number of entries to 5.
// Workshop 4 - Templates
// w4.cpp
#include <iostream>
#include <iomanip>
#include <string>
#include "KVList.h"
template <typename K, typename V, int N>
void display(const std::string& msg, const KVList<K, V, N>& list, int w) {
std::cout << msg;
for (int i = 0; i < list.size(); i++)
std::cout << std::setw(w) << list.key(i)
<< " : " << list.value(i) << std::endl;
}
int main(int argc, char** argv) {
if (argc != 1) {
std::cerr << argv[0] << ": too many arguments\n";
return 1;
}
int width;
bool keepreading;
std::cout << std::fixed << std::setprecision(2);
std::cout << "\nInventory\n=========\n";
KVList <std::string, double, 5> inventory;
std::string str;
double price;
keepreading = true;
do {
std::cout << "Product : ";
getline(std::cin, str);
if (str.compare("quit") == 0) {
keepreading = false;
} else {
std::cout << "Price : ";
std::cin >> price;
std::cin.ignore();
inventory.add(str, price);
}
} while(keepreading);
display("\nPrice List\n----------\n", inventory, 13);
std::cout << "\nCorrections\n-----------\n";
keepreading = true;
do {
std::cout << "Product : ";
getline(std::cin, str);
if (str.compare("quit") == 0) {
keepreading = false;
} else {
int i = inventory.find(str);
if (i != -1) {
std::cout << "Price : ";
std::cin >> price;
std::cin.ignore();
inventory.replace(i, str, price);
}
}
} while(keepreading);
display("\nPrice List\n----------\n", inventory, 13);
std::cout << "\nGlossary\n========\n";
KVList <std::string, std::string, 5> glossary;
std::string key, definition;
keepreading = true;
do {
std::cout << "Key : ";
getline(std::cin, key);
if (key.compare("quit") == 0) {
keepreading = false;
} else {
std::cout << "Definition : ";
getline(std::cin, definition);
glossary.add(key, definition);
}
} while(keepreading);
display("\nEntries\n-------\n", glossary, 5);
}
For the input listed below the main program with your template produces the output shown:
Inventory
=========
Product : Pizza
Price : 4.49
Product : Pierogi
Price : 2.56
Product : Potato Chips
Price : 2.29
Product : Black Tea
Price : 4.49
Product : Green Tea
Price : 3.46
Product : Fruit Tea
Price : 2.29
Product : quit
Price List
----------
Pizza : 4.49
Pierogi : 2.56
Potato Chips : 2.29
Black Tea : 4.49
Green Tea : 3.46
Corrections
-----------
Product : Black Tea
Price : 5.29
Product : quit
Price List
----------
Pizza : 4.49
Pierogi : 2.56
Potato Chips : 2.29
Black Tea : 5.29
Green Tea : 3.46
Glossary
========
Key : CPU
Definition : central processing unit
Key : ALU
Definition : arithmetic logic unit
Key : quit
Entries
-------
CPU : central processing unit
ALU : arithmetic logic unit
Note that the input data is only stored for the first N items, which is the size specified in the definitions of inventoryand glossary.
SUBMISSION
Once you have completed your lab create a single ZIP file that contains the following information and upload your ZIP file to Blackboard using the lab submission link.
All your source code files (*.h and *.cpp)
Execution instructions file (if there is anything special I need to know to successfully run your program write them down in a README file)
Any input files required (test inputs, etc….)
A 2-paragraph “what did I do and learn in this lab” write-up
#ifndef KVLIST_H_
#define KVLIST_H_
#include <list>
#include <algorithm>
using namespace std;
template<typename K,typename V,int N>
class KVList
{
public:
KVList();
size_t size() const; //return number of key-value
const K& key(int i) const; //return unmodifiable reference to the key
const V& value(int i) const; //return modifiable reference to the value
KVList &add(const K&,const V&); //add a new element to the list
int find(const K& k) const; //return the index
KVList &replace(int i,const K&k,const V&v); //replace
private:
list<pair<K,V>> *myList;
size_t num;
};
template<typename K,typename V,int N>
KVList<K,V,N>::KVList():myList(new list<pair<K,V>>(N))
{
num=0;
}
template<typename K,typename V,int N>
size_t KVList<K,V,N>::size() const
{
return num;
}
template<typename K,typename V,int N>
const K& KVList<K,V,N>::key(int i) const
{
list<pair<K,V>>::const_iterator it=myList->begin();
for(int index=0;index<i;index++)
{
it++;
}
return ((*it).first);
}
template<typename K,typename V,int N>
const V& KVList<K,V,N>::value(int i) const
{
list<pair<K,V>>::const_iterator it=myList->begin();
for(int index=0;index<i;index++)
{
it++;
}
return ((*it).second);
}
template<typename K,typename V,int N>
KVList<K,V,N>& KVList<K,V,N>::add(const K& k,const V& v)
{
list<pair<K,V>>::const_iterator it=myList->begin();
if(num>=N) return *this;
for(unsigned int index=0;index<num;index++)
{
it++;
}
myList->insert(it,make_pair(k,v));
num++;
return *this;
}
template<typename K,typename V,int N>
int KVList<K,V,N>::find(const K& k) const
{
int index=0;
list<pair<K,V>>::const_iterator it=myList->begin();
for(;it!=myList->end();it++)
{
if((*it).first==k)
break;
index++;
}
if(it==myList->end() && (*(--it)).first!=k)
{
index=-1;
}
return index;
}
template<typename K,typename V,int N>
KVList<K,V,N> & KVList<K,V,N>::replace(int i,const K& k,const V& v)
{
list<pair<K,V>>::iterator it=myList->begin();
int index=0;
for(;index<i;index++)
{
it++;
}
(*it).first=k;
(*it).second=v;
return *this;
}
#endif
// Workshop 4 - Templates
// w4.cpp
#include <iostream>
#include <iomanip>
#include <string>
#include "KVList.h"
template <typename K, typename V, int N>
void display(const std::string& msg, const KVList<K, V, N>& list, int w) {
std::cout << msg;
for (unsigned int i = 0; i < list.size(); i++)
std::cout << std::setw(w) << list.key(i)
<< " : " << list.value(i) << std::endl;
}
int main(int argc, char** argv) {
if (argc != 1) {
std::cerr << argv[0] << ": too many arguments\n";
return 1;
}
bool keepreading;
std::cout << std::fixed << std::setprecision(2);
std::cout << "\nInventory\n=========\n";
KVList <std::string, double, 5> inventory;
std::string str;
double price;
keepreading = true;
do {
std::cout << "Product : ";
getline(std::cin, str);
if (str.compare("quit") == 0) {
keepreading = false;
}
else {
std::cout << "Price : ";
std::cin >> price;
std::cin.ignore();
inventory.add(str, price);
}
} while(keepreading);
display("\nPrice List\n----------\n", inventory, 13);
std::cout << "\nCorrections\n-----------\n";
keepreading = true;
do {
std::cout << "Product : ";
getline(std::cin, str);
if (str.compare("quit") == 0) {
keepreading = false;
}
else {
int i = inventory.find(str);
if (i != -1) {
std::cout << "Price : ";
std::cin >> price;
std::cin.ignore();
inventory.replace(i, str, price);
}
}
} while(keepreading);
display("\nPrice List\n----------\n", inventory, 13);
std::cout << "\nGlossary\n========\n";
KVList <std::string, std::string, 5> glossary;
std::string key, definition;
keepreading = true;
do {
std::cout << "Key : ";
getline(std::cin, key);
if (key.compare("quit") == 0) {
keepreading = false;
}
else {
std::cout << "Definition : ";
getline(std::cin, definition);
glossary.add(key, definition);
}
} while(keepreading);
display("\nEntries\n-------\n", glossary, 5);
}
还是说下收获,这次收获挺大的,主要体现在以前一直不晓得:如果一个类的私有成员是list或vector等的对象,如何进行初始化及分配内存。
如果将对象直接声明为:list<string> myList;(此处以string为例)
则无法为其动态分配内存。较好的做法是声明为:list<string> *myList;
即用指针来代替,这样就可以用new来分配内存了。
其他收获是对list更为熟悉,对迭代器的使用更熟练了。
注意:又犯老错误了,构造函数中出现new以后,没有对应的析构函数来释放内存,特此标注,希望以后不会再犯错。