hey i created an abstract class called "Node" and and class NodeBlock that implements the Node class. in my main class i need to print the values that inside the NodeBlock this is some of my code for the main class:
//receving the fasteset route using the BFS algorithm.
std::stack<Node *> fast = bfs.breadthFirstSearch(start, goal);
/*print the route*/
while (!fast.empty()) {
cout << fast.top() << endl;
fast.pop();
}
Node:
#include <vector>
#include "Point.h"
#include <string>
using namespace std;
/**
* An abstract class that represent Node/Vertex of a graph the node
* has functionality that let use him for calculating route print the
* value it holds. etc..
*/
class Node {
protected:
vector<Node*> children;
bool visited;
Node* father;
int distance;
public:
/**
* prints the value that the node holds.
*/
virtual string printValue() const = 0;
/**
* overloading method.
*/
virtual string operator<<(const Node *node) const {
return printValue();
};
};
NodeBlock.h:
#ifndef ADPROG1_1_NODEBLOCK_H
#define ADPROG1_1_NODEBLOCK_H
#include "Node.h"
#include "Point.h"
#include <string>
/**
*
*/
class NodeBlock : public Node {
private:
Point point;
public:
/**
* prints the vaule that the node holds.
*/
ostream printValue() const override ;
};
#endif //ADPROG1_1_NODEBLOCK_H
NodeBlock.cpp:
#include "NodeBlock.h"
using namespace std;
NodeBlock::NodeBlock(Point point) : point(point) {}
string NodeBlock::printValue() const {
return "(" + to_string(point.getX()) + ", " + to_string(point.getY());
}
i deleted all the unnecessary method of those class. now i'm trying to overload the << operator so when i top.() from the stack it will and assign it to the "cout" it will print the string of the point.
but my current output is:
0x24f70e0
0x24f7130
0x24f7180
0x24f7340
0x24f7500
which as you know is the address. thanks for the help
What you're looking for is a << operator that has an ostream on the left and a Node on the right, and evaluates to the same ostream. Thus, it should be defined like this (outside of the Node class):
std::ostream& operator<<(std::ostream& out, const Node& node) {
out << node.printValue();
return out;
}
Then you need to make sure that you're couting a Node, not a Node*:
cout << *fast.top() << endl; // dereference the pointer
Related
This problem occurs in my main.cpp:
using namespace std;
#include <iostream>
#include "BST.h"
#include "Packet.h"
int main()
{
BST test; // It occurs on this line!
Packet one(1, "testPacket", 1, 1);
system("Pause");
}
The error on that line says:
argument list for class template "BST" is missing
I don't know how to fix it. I just want to initialize the BST. How can I fix this error? I'm not very experienced with templates. Please help. My priority is fixing this glaring problem right now. Can I get help?
For reference purposes:
BST.h:
#ifndef BST_H
#define BST_H
using namespace std;
template <typename T>
class Node {
public:
Node() : rlink(nullptr), llink(nullptr) {}
~Node() {}
private:
T data;
Node *rlink, *llink;
};
template <typename T>
class BST {
public:
BST();
void insert(T data);
private:
Node * root;
};
#endif
BST.cpp
#include "BST.h"
template <typename T>
BST<T>::BST() : root(nullptr) {}
template <typename T>
void BST<T>::insert(T data) {
if (root != nullptr) {
}
else {
cout << "NPTR" << endl;
}
}
Packet.h
#ifndef PACKET_H
#define PACKET_H
#include <string>
using namespace std;
class Packet {
public:
Packet(int partId, string description, double price, int partCount) :
partId(partId), description(description), price(price), partCount(partCount) {}
int getPartId() const { return partId; }
string getDescription() const { return description; }
double getPrice() const { return price; }
int getPartCount() const { return partCount; }
private:
int partId;
string description;
double price;
int partCount;
};
#endif
There are 2 problems.
The first is that Node needs to know what type T is, so you need to tell it when you use Node like this:
template <typename T>
class BST {
public:
BST();
void insert(T data);
private:
Node<T> * root;
};
Secondly, BST needs to know what its own type T is when you try to use it, so you need to do it like this:
BST<int> test; // Or whatever you are searching for in your tree. Doesn't have to be an int
P.S. Just heading this off now, you're probably going to need to implement BST in the header file. Failure to do so might cause linker problems.
P.P.S. I've been reading your comments on the original post, and what you actually probably need this instead:
BST<Packet> test; // Since you are searching for packets.
this is my situation:
I am writing a data structure in C++ which consists of Nodes and Edges.
Nodes are connected to other nodes by means of edges.
I have different types of nodes, such as text nodes, or int nodes.
Text nodes are connected to text nodes and int nodes are connected to int nodes.
I am using inheritance to implement the different types of nodes because it makes sense:
fundamentally, all nodes are connected to other nodes so Node is the base class,
and TxtNode, IntNode are inherited classes which share the fundamental property of a node.
However, this gives me problems when I try to fetch a connected inherited node from an inherited node, because the fetching function (function which retrieves a specific node connected to the calling node) is defined in the base class Node. For example, calling this fetch function from TextNode returns me the base version of the TextNode, which lacks extra information.
I am not sure what would be the sensible coding practice to do here.
I chose to code it this way because it didn't seem to make sense that I must define a different connection fetch function for all different types of nodes.
Please let me know if there is any more information I can disclose.
Here is my code, I am trying to print an inherited node's partner but it will result in printing the base node.
Node.cpp
#include "Node.h"
#include "Edge.h"
#include "common.h"
#include <vector>
#include <cassert>
#include <cstddef>
#include <stdint.h>
#include <iostream>
Node::Node() {
id = (intptr_t)this;
edges.clear();
}
int Node::connect(Node* dst) {
// establish link between calling node
// and dst node, first linkage will
// edge between each other, links after
// increments strength. returns number of
// links
// fetch edge connecting this node and
// dst node
Edge* edge = findDstEdge(dst);
// if the branch isn't established yet,
// then make connection
if (edge==NULL) {
establishConnection(dst, 1);
return 0;
} else {
edge->strengthenConnection();
return 1;
}
}
Edge* Node::findDstEdge(Node* dst) {
// fetches edge corresponding
// to destination node
// walk through vector of edges to find
// edge connecting to dst
vector<Edge*>::iterator iter = edges.begin();
while(iter!=edges.end()) {
Edge* e = *iter;
Node* partner = e->getPartner(this);
if (partner->getID() == dst->getID())
return e;
iter++;
}
// not found
return NULL;
}
void Node::establishConnection(Node* dst, int str) {
// low level node addition
// establish a new edge between
// nodes which don't know each other
Edge* e = new Edge(this, dst, str);
this->manuallyConnect(e);
dst->manuallyConnect(e);
}
void Node::manuallyConnect(Edge* e) {
edges.push_back(e);
}
ostream& operator<<(ostream& stream,Node n) {
vector<Edge*>::iterator iter = n.edges.begin();
while(iter!=n.edges.end()) {
Edge* e = *iter;
stream << *e << endl;
iter++;
}
return stream;
}
Node.h
#ifndef _NODE_H_
#define _NODE_H_
#include "common.h"
#include <vector>
#include <string>
#include <stdint.h>
class Edge;
using namespace std;
class Node {
protected:
vector<Edge*> edges;
intptr_t id;
public:
Node();
// manipulation
void establishConnection(Node* dst,
int str);
int connect(Node* dst);
Edge* findDstEdge(Node* dst);
// fetchers
intptr_t getID() {return id;}
vector<Edge*> getEdges() {return edges;}
void manuallyConnect(Edge* e);
friend ostream& operator<<(ostream& stream, Node n);
};
#endif
TxtNode.cpp
#include "TxtNode.h"
#include "Edge.h"
#include "common.h"
#include <iostream>
TxtNode::TxtNode(char c): Node() {
_c = c;
}
ostream& operator<<(ostream& stream, TxtNode tn) {
// print out character of this TxtNode
stream << "char: " << tn._c << endl;
stream << "id: " << tn.id << endl;
// print out all connections and its
// strength
vector<Edge*>::iterator iter = tn.edges.begin();
while(iter!=tn.edges.end()) {
Edge* e = *iter;
stream << *e << endl;
iter++;
}
return stream;
}
Edge.cpp
#include "Edge.h"
#include "Node.h"
#include "common.h"
#include <cassert>
#include <iostream>
using namespace std;
Edge::Edge(Node* a, Node* b, int str) {
node_a = a;
node_b = b;
strength = str;
}
void Edge::strengthenConnection() {
strength++;
}
Node* Edge::getPartner(Node* src) {
uint src_ID = src->getID();
if (node_a->getID() == src_ID)
return node_b;
else if (node_b->getID() == src_ID)
return node_a;
assert(false);
}
ostream& operator<<(ostream& stream, Edge e) {
stream << "strength: "
<< e.strength
<< endl;
stream << "node_a: "
<< e.node_a->getID()
<< endl;
stream << "node_b: "
<< e.node_b->getID()
<< endl;
return stream;
}
Currently I just have the code to print the ID which is an intptr_t,
because I found out that I can't access inherited class's member from base class.
I am inclined to access the inherited class's member from base class because the edge class deals with base node class.
The classes code would've been a nice to have.
From what you are telling you don't declare the fetch function virtual.
Here's a very quick example on how virtual / non virtual functions work
class baseNode {
public:
int fetch() { printf "fetched from base";};
}
class intNode : public baseNode {
public:
int fetch() { printf "fetched from derived int";};
}
class txtNode : public baseNode {
public:
int fetch() { printf "fetched from derived txt";};
}
The following code
baseNode * ptr = new intNode();
ptr->fetch();
Will print "fetched from base"
But if you declare the fetch function virtual :
class baseNode {
public:
virtual int fetch() { printf " fetched from base";};
}
Then the same code will print "fetched from derived int".
You write
“ Text nodes are connected to text nodes and int nodes are connected to int nodes.
Then you can very simply define Node_ as a class template:
template< class Value >
struct Node_
{
vector<Node_*> connected_nodes;
Value value;
};
In other words, use compile time polymorphism, not dynamic polymorphism, in order to have the relevant type information available at compile time.
That said, do have a look at Boost.Graph and see if it doesn't suit your needs.
I am trying to get this to return a string, but i am having trouble getting it working. The goal is to have a doubly-linked list that points to strings. I am not allowed to have it contain the string, it must point to it instead. Currently i am having trouble getting my program to use it. For example, it always seems to return what the command was, and its confusing me and hard to explain.
#ifndef DOUBLY_LINKED_LIST_H
#define DOUBLY_LINKED_LIST_H
#include <iostream>
#include <string>
//#include "Playlist.h"
using namespace std;
class DoublyLinkedList
{
public:
DoublyLinkedList();
~DoublyLinkedList();
bool empty();
void append(string& s);
void insertBefore(string& s);
void insertAfter(string& s);
void remove(string& s);
void begin();
void end();
bool next();
bool prev();
bool find(string& s);
const string& getData();
private:
class Node
{
public:
Node (string *data, Node *next, Node *prev)
{m_data = data; m_next = next; m_prev = prev;}
string *m_data;
Node * m_next;
Node * m_prev;
};
Node *m_head;
Node *m_tail;
Node *m_current;
};
#endif // DOUBLYLINKEDLIST_H_INCLUDED
.cpp file>>>>
const string& DoublyLinkedList::getData()
{
string *m_tmp;
m_tmp = m_current->m_data;
cout << m_current->m_data << endl;
//cout << "returning: " << m_current->m_data << endl;
// return m_current->m_data;
return *m_tmp;
}
void DoublyLinkedList::append(string &s)
{
if (!m_head)
{
m_head = new Node(&s, NULL, NULL);
m_tail = m_head;
m_current = m_head;
}
else
{
m_tail->m_next = new Node (&s, NULL, m_tail);
m_tail = m_tail->m_next;
m_current = m_tail;
}
}
Consider the following example:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
void store_value(vector<string*>& vec, string& str)
{
vec.push_back(&str);
}
void create_and_store_value(vector<string*>& vec)
{
string str("This string is temporary");
store_value(vec, str);
}
int main(int argc, char** argv)
{
vector<string*> pointers;
create_and_store_value(pointers);
cout << *pointers.back() << endl;
string myPersistingString("Yay");
store_value(pointers, myPersistingString);
cout << *pointers.back() << endl;
return 0;
}
This example contains two function, a function store_value which behaves similar to your append function (except, for the purposes of this example working on a std::vector) and a second function showing the possible danger of taking the address of a reference (this is one of the possible hazards that I believe Manu343726 and Mats Petersson are preluding too).
The reason this is dangerous is because the string declared inside create_and_store_value does not persist after the completion of the function. This means that we are left with a pointer to memory which is probably not what we expect. On the other hand, creating a string inside the main function is fine, since the string there persists until the end of the program.
For us to help you further, I would suggest editing your question to give us an example of how you are calling your function. I would suggest pasting a minimal striped down version of your code including an example of how you are calling append, something like:
#include <blah>
class DoubleLinkedList
{
DoubleLinkedList(void)
{
// Include these inline to make copying and pasting simpler.
}
~DoubleLinkedList(void)
{
...
}
append(...) { ... }
getData(...) { ... }
};
int main(int argc, char** argv)
{
DoubleLinkedList dll;
// Show us how you are using this list
return 0;
}
In the above, replace the comments and dots with the relevant code.
Hi im working on a program that uses an array of linked lists but im having trouble running it. I keep getting this error and I cannot find a way to fix it. Im only going to include parts of the code that way everything isnt too cluttered. The error message is saying that lines 112 in NodeADT.h, line 141 in MultiListADT.h and line 21 in main.cpp are the ones throwing the error. Ill highlight those lines to make it easier.
Main.cpp
#include <iostream>
#include "MultiListADT.h"
#include <fstream>
#include <string>
using namespace std;
void main(void)
{
MultiListADT<string,100> myList;
string item;
ifstream data;
string input;
int x=0;
data.open("input.txt");
while (!data.eof())
{
getline(data,input);
myList.AddToFront(input); //This is line 21
}
cout << myList << endl;
system("pause");
}
MultiListADT.h
#include <iostream>
#include <fstream>
#include "NodeADT.h"
#include <string>
using namespace std;
template <class TYPE,int threads>
class MultiListADT
{
public:
/** Constructor **/
MultiListADT();
/** Destructor **/
~MultiListADT();
/** Declare accessors (observers) **/
void ResetListForward(int=0);
void ResetListBackward(int=0);
bool IsEmpty(int=0);
int LengthIs(int=0);
bool Search(string, bool=true,int=0);
void GetNextItem(TYPE &,int i=0);
void GetPreviousItem(TYPE &,int=0);
int GetInfo(int=0);
friend ostream& operator << (ostream&, MultiListADT<TYPE, 100>&);
/** Declare mutators (transformers) **/
void MakeEmpty();
void AddToFront(TYPE);
void AddToRear(TYPE);
void InsertInOrder(TYPE);
void Delete(TYPE);
void Sort();
private:
NodeADT<TYPE,threads>* head[threads];
NodeADT<TYPE,threads>* tail[threads];
int length;
string indices[threads];
NodeADT<TYPE,threads>* currentNode[threads];
};
template <class TYPE,int threads>
MultiListADT<TYPE,threads>::MultiListADT()
{
head[threads] = new NodeADT<string,threads>();
tail[threads] = new NodeADT<string,threads>();
head[threads]->setNext(tail[threads]);
tail[threads]->setPrevious(head[threads]);
length = 0;
}
template <class TYPE,int threads>
void MultiListADT<TYPE,threads>::AddToFront(TYPE item)
{
head[0]->AddToFront(item); //This is line 141
length++;
}
NoteADT.h
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
const int null = 0;
template<class TYPE, int threads>
class MultiListADT;
template <class TYPE, int threads>
class NodeADT
{
public:
NodeADT();
NodeADT(TYPE);
~NodeADT();
TYPE getInfo();
NodeADT<TYPE, threads>* getPrevious(int=0);
NodeADT<TYPE, threads>* getNext(int=0);
void setNext(NodeADT<TYPE, threads>*,int=0);
void setPrevious(NodeADT<TYPE, threads>*,int=0);
bool Search(TYPE, bool=true,int=0);
void AddToFront(TYPE item);
void AddToRear(TYPE item);
void InsertInOrder(TYPE);
bool Delete(TYPE);
friend ostream& operator << (ostream&, MultiListADT<TYPE, threads>&);
private:
TYPE info;
NodeADT<TYPE, threads>* prev[threads];
NodeADT<TYPE, threads>* next[threads];
};
template <class TYPE,int threads>
NodeADT<TYPE,threads>::NodeADT()
{
prev[threads] = null;
next[threads] = null;
}
template <class TYPE,int threads>
NodeADT<TYPE,threads>::NodeADT(TYPE item)
{
info = item;
prev = null;
next = null;
}
template <class TYPE,int threads>
void NodeADT<TYPE,threads>::AddToFront(TYPE item)
{
NodeADT<TYPE,threads> *temp = new NodeADT<TYPE,threads>;
temp->info = item;
temp->prev[0] = this;
temp->next[0] = next[0];
next[0]->prev[0] = temp; //This is line 112
next[0] = temp;
}
What do YOU think the error means?
On line 112, where do the values for next, prev and temp come from and what are they set to when it crashes? Knowing the values, why do you think it crashed?
Also in one of your NodeADT constructors you assign null to the last element of the array. Or so it appears.
Question: What happens when you assign a value to the element numbered 100 in an array of 100 elements, when element counting starts at 0?
I think the answer, which Zan Lynx has implied, is that you are using threads as an index into your arrays in the constructor of MultiListADT. In AddToFront you use 0 as the index, but that element in the array has never been initialised.
I am trying to print the contents of the map and this is where my code fails. I have tested all my methods and I have no problem to read from file, filer the word, put it into map, and even the print function is working.
However, when I am calling the printer function from main it does not print the map.
I am new to polymorphism and I think that my error is in how I am passing the map to the function in main.
Here is my main class:
using namespace std;
#include <iostream>
#include "ReadWords.h"
#include "ReadPunctWords.h"
#include "ReadNumWords.h"
#include "ReadCapWords.h"
#include "MapWorks.h"
#include <fstream>
#include <string>
#include <map>
#include <iterator>
/**
* This main function uses all other classes.
*/
int main() {
char* name = "RomeoJuliet.txt";
//ReadPunctWords &obj = *new ReadPunctWords(name);
ReadPunctWords obj(name);
string startSearch="BEGIN";
string endSearch="FINIS";
ReadPunctWords rpw;
ReadCapWords rcw;
ReadNumWords rnw;
MapWorks mw;
while(rpw.isNextWord()){
string tempword = obj.getNextWord();
if(tempword == startSearch){
break;
}
}
while(rpw.isNextWord()){
string tempword = obj.getNextWord();
if(tempword == endSearch){
break;
}
else{
if(rpw.filter(tempword)){
mw.addToMap(tempword, mw.mapPunct);
}
if(rcw.filter(tempword)){
mw.addToMap(tempword, mw.mapCap);
}
if(rnw.filter(tempword)){
mw.addToMap(tempword, mw.mapNum);
}
}
}
mw.printMap(mw.mapPunct);
mw.printMap(mw.mapCap);
mw.printMap(mw.mapNum);
//clear map
mw.clearMap(mw.mapPunct);
mw.clearMap(mw.mapCap);
mw.clearMap(mw.mapNum);
//close the file
//obj.close();
//delete &obj;
//exit(0); // normal exit
return 0;
}
And my MapWorks.cpp which contains the maps and the functions related to maps:
using namespace std;
#include <iostream>
#include <string>
#include <map>
#include <iterator>
#include "MapWorks.h"
/**
* MapWorks class builds the maps and does the map processing and printing
*/
MapWorks::MapWorks() {}
void MapWorks::addToMap(string myword, map<string, int> & myMap){
int n = myMap[myword];
myMap[myword]= n+1;
}
void MapWorks::printMap (map<string, int> &myMap){
for (map<string, int>::iterator it = myMap.begin(); it != myMap.end(); ++it)
{
cout << it->first << " ==> " << it->second << '\n'<<endl;
}
}
//delete entries in map
void MapWorks::clearMap(map<string, int>myMap) {
myMap.clear();
}
MapWorks.h :
#ifndef MAPWORKS_H
#define MAPWORKS_H
#include <string>
#include <map>
using namespace std;
/**
* MapWorks class builds the maps and does the map processing and printing
*/
class MapWorks {
public:
map<string, int> mapPunct; //(word, number of occurences)
map<string, int> mapNum; //(word, number of occurences)
map<string, int> mapCap; //(word, number of occurences)
MapWorks();
void addToMap(string myword, map<string, int> & myMap); //adds words to a map
void printMap (map<string, int> &myMap); //prints the map
void clearMap(map<string, int>); //clear map
};
#endif
My ReadWords.h :
/**
* ReadWords class, the base class for ReadNumWords, ReadPunctWords, ReadCapWords
*/
#ifndef READWORDS_H
#define READWORDS_H
using namespace std;
#include <string>
#include <fstream>
#include<iostream>
class ReadWords
{
private:
string nextword;
ifstream wordfile;
bool eoffound;
public:
/**
* Constructor. Opens the file with the default name "text.txt".
* Program exits with an error message if the file does not exist.
*/
ReadWords();
/**
* Constructor. Opens the file with the given filename.
* Program exits with an error message if the file does not exist.
* #param filename - a C string naming the file to read.
*/
ReadWords(char *filename);
/**
* Closes the file.
*/
void close();
/**
* Returns a string, being the next word in the file.
* #return - string - next word.
*/
string getNextWord();
/**
* Returns true if there is a further word in the file, false if we have reached the
* end of file.
* #return - bool - !eof
*/
bool isNextWord();
//pure virtual function for filter
virtual bool filter(string word)=0;
/**
* Fix the word by the definition of "word"
* end of file.
* #return - string
*/
string fix(string word);
};
#endif
And my ReadPunctWords (ReadNumWords and ReadCapWords are quite the same, just checking if the word has digits or capital letters instead of punctuations like in here):
#ifndef READPUNCTWORDS_H
#define READPUNCTWORDS_H
using namespace std;
#include <string>
#include "ReadWords.h"
/**
* ReadPunctWords inherits ReadWords, so MUST define the function filter.
* It chooses to override the default constructor.
*/
class ReadPunctWords: public ReadWords {
public:
ReadPunctWords();
ReadPunctWords(char *filename): ReadWords(filename){};
virtual bool filter(string word);
};
#endif
I would appreciate any help from you.
Thanks, Adriana
There are a number of things that are potential issues in your code, but the most obvious thing that may be causing the printMap not to work as expected is this while loop.
map<string, int>::iterator it = myMap.begin();
cout<<"test"<<endl;
while(it!=myMap.end()){
cout<<(*it).first<<" ==> "<<(*it).second<<endl;
}
Nowhere do you increment the iterator so either nothing will be printed (if the map is empty) or else the first item will printed over and over again and the loop won't terminate.
The idiomatic way to write this loop would be as a for loop.
for (std::map<string, int>::iterator it = myMap.begin(); it != myMap.end(); ++it)
{
std::cout << it->first << " ==> " << it->second << '\n';
}
The other issue is that your addToMap function probably isn't working as intended because you pass the map to the function by value and this means that the map that the function is adding an item to is actually a copy of the map that was passed in.
When control is passed to the calling function this copy is destroyed and the map that was passed it is still empty.
To pass a map by reference you need to add & to the type of the parameter in the function declaration.
i.e. in the headfile, the the MapWorks class definition:
void addToMap(string myword, map<string, int>& myMap);
and in the source file:
void MapWorks::addToMap(string myword, map<string, int>& myMap)
{
// definition...
}
Your use of references for dynamically allocated objects is unusual, to say the least. For your purposes, I don't see any point to doing:
ReadWords &rnw = *new ReadNumWords();
when you delete the object at the end of the same function in which it is created. You can just do this (exactly as you do with MapWorks mw;).
ReadNumWords rnw;
If you have to use dynamically allocated objects, just using pointers rather than references is much more usual but it is highly recommended to use some sort of a smart pointer so that you don't have to remember to call delete explicitly.
You forgot to increment iterator:
while(it!=myMap.end()){
cout<<(*it).first<<" ==> "<<(*it).second<<endl;
// you forgot this:
it++;
}
And, more importantly, consider few modifications to your code:
// ReadPunctWords &obj = *new ReadPunctWords(name);
// should likely be:
ReadPunctWords obj(name);
// same applies to other 'newed' 'references'
// and then there's no need to do
// delete &obj;
// exit(0); // normal exit
// should probably be just a
return 0;
// obj.close();
// can be called in the destructor of ReadPunctWords class
// and RAII will help you get your file closed correctly when needed
// void MapWorks::printMap (map<string, int>myMap)
// should better be:
void MapWorks::printMap (const std::map<string, int> &myMap)
// same applies to other functions in your code
// here's how your commented-out function could look like
void MapWorks::printMap(const std::map<string, int> &myMap) {
typedef std::map<string, int>::iterator mapsi;
for (mapsi m = myMap.begin(); m != myMap.end(); ++m) {
std::cout << (*m).first << " ==> " << (*m).second << "\n";
}
}
// void MapWorks::addToMap(string myword, map<string, int>myMap)
// should be:
void MapWorks::addToMap(std::string myword, std::map<string, int> &myMap)
If possible, I'd suggest breaking the logic up into slightly smaller units, and pushing more of the logic into the classes -- right now, main does quite a lot more than I'd like to see there, and (particularly) knows more about the internals of the classes than I'd like to see either.
If I were doing it, I'd start with a map that knew how to filter out words, so it can only accept what it's supposed to:
class Map {
std::map<std::string, int> counts;
public:
struct Filter {
virtual bool operator()(std::string const &) const = 0;
};
Map(Filter const &f) : filter(f) {}
bool InsertWord(std::string const &word) {
return filter(word) && (++counts[word] != 0);
}
friend std::ostream &operator<<(std::ostream &os, Map const &m) {
std::copy(m.counts.begin(),
m.counts.end(),
std::ostream_iterator<count>(std::cout, "\n"));
return os;
}
private:
Filter const &filter;
};
Then we'd need some derivatives of Filter to do the real filtering. These probably don't work the way you really want; they're really just placeholders:
struct Num : Map::Filter {
bool operator()(std::string const &w) const {
return isdigit(w[0]) != 0;
}
};
struct Punct : Map::Filter {
bool operator()(std::string const &w) const {
return ispunct(w[0]) != 0;
}
};
struct Letter : Map::Filter {
bool operator()(std::string const &w) const {
return isalpha(w[0]) != 0;
}
};
Then MapWorks can delegate almost all the real work to the Map (which in turn uses a Filter):
class MapWorks {
Map num;
Map punct;
Map letter;
public:
// For the moment, these allocations just leak.
// As long as we only create one MapWorks object,
// they're probably not worth fixing.
MapWorks()
: num(Map(*new Num())),
punct(Map(*new Punct())),
letter(Map(*new Letter()))
{}
// Try adding the word until we find a Map
// that accepts it.
bool push_back(std::string const &word) {
return num.InsertWord(word)
|| punct.InsertWord(word)
|| letter.InsertWord(word);
}
// Write out by writing out the individual Map's:
friend std::ostream &operator<<(std::ostream &os, MapWorks const &m) {
return os << m.num << "\n" << m.punct << "\n" << m.letter << "\n";
}
};
With these in place, main becomes pretty simple: (though for the moment, I've just had it read a whole file instead of looking for "BEGIN" and "FINIS"):
int main() {
MapWorks m;
std::string temp;
while (std::cin >> temp)
m.push_back(temp);
std::cout << m;
return 0;
}
There are a few other bits and pieces, such as typedef'ing the count type and defining an inserter for it, but they're pretty minor details.