题
我要打印的地图的内容,这是我的代码失败。我过我的所有的方法和我没有问题,从文件中读取,文件服务器上的字,把它放到地图,甚至连打印功能是否正常。 然而,当我从主调用打印机功能未打印的地图。 我是新来的多态性,我认为我的错误是,我如何在地图传递给函数的主。
下面是我的主类:
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;
}
和我的MapWorks.cpp含有地图和有关地图的功能:
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
我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
和我ReadPunctWords(ReadNumWords和ReadCapWords是完全一样的,只是检查,如果这个词有数字或字母大写,而不是像标点符号这里):
#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
我将不胜感激您的任何帮助。 谢谢,阿德里安娜
解决方案
有许多事情是在你的代码中潜在的问题,但可能导致printMap
不能达到预期效果最明显的一点就是这个while循环。
map<string, int>::iterator it = myMap.begin();
cout<<"test"<<endl;
while(it!=myMap.end()){
cout<<(*it).first<<" ==> "<<(*it).second<<endl;
}
无处你递增迭代所以无论是什么都不会被打印(如果该映射为空),否则第一个项目将印刷一遍又一遍循环将不会终止。
写这个循环中的惯用的方式将是作为一个for循环。
for (std::map<string, int>::iterator it = myMap.begin(); it != myMap.end(); ++it)
{
std::cout << it->first << " ==> " << it->second << '\n';
}
另一个问题是,你的addToMap
功能可能如预期,因为按值传递的地图功能的 的不工作,这意味着该地图的功能被添加到为项目实际上这是传入的映射的副本。
当控制传递到调用函数此副本被破坏,这是通过它仍然是空的地图。
要通过引用传递的地图需要&
添加到函数声明的参数的类型。
即。在headfile中,所述MapWorks
类定义:
void addToMap(string myword, map<string, int>& myMap);
和在源文件:
void MapWorks::addToMap(string myword, map<string, int>& myMap)
{
// definition...
}
您使用了动态分配的对象引用的是不寻常的,至少可以说。你的目的,我没有看到任何一点做的:
ReadWords &rnw = *new ReadNumWords();
当你在其被创建的同一功能的结束删除该对象。你可以这样做(完全按照你MapWorks mw;
做的)。
ReadNumWords rnw;
如果你必须使用动态分配的对象,只是使用指针,而不是引用是更平常,但强烈建议使用某种智能指针,让你不必记得显示调用delete
。
其他提示
您忘记递增迭代器:
while(it!=myMap.end()){
cout<<(*it).first<<" ==> "<<(*it).second<<endl;
// you forgot this:
it++;
}
和,更重要的是,考虑一些修改代码:
// 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)
如果可能的话,我建议打破逻辑成略小单位,并推动更多的逻辑入班 - 现在,main
做了很多比我更想看到那里,(尤其)知道更多的关于类的内部比我想看到任一
如果我在干什么,我会用一个地图,知道如何过滤掉的话开始,所以它只能接受什么它应该为:
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;
};
然后我们需要滤波器的一些衍生物做真正滤波。这些可能不工作,你真正想要的方式;他们真的只是占位符:
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;
}
};
然后MapWorks可以委派几乎所有的实际工作的图(其又使用滤波器):
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";
}
};
通过这些到位,main
变得非常简单:(尽管就目前而言,我刚刚读它,而不是寻找“开始”和“FINIS”整个文件):
int main() {
MapWorks m;
std::string temp;
while (std::cin >> temp)
m.push_back(temp);
std::cout << m;
return 0;
}
有其他一些星星点点,如typedef'ing计数类型,并限定它的插入器,但他们非常小的细节。