我正在尝试打印 map 的内容,这就是我的代码失败的地方。我已经测试了所有方法,从文件读取、过滤单词、将其放入 map 中都没有问题,甚至打印功能也正常工作。 但是,当我从 main 调用打印机函数时,它不会打印 map 。 我是多态性的新手,我认为我的错误在于如何将映射传递给 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;
}
还有我的MapWorks.cpp,其中包含 map 以及与 map 相关的函数:
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
函数可能无法按预期工作,因为您按值将映射传递给函数,这意味着该函数向其中添加项目的映射实际上是传入的映射的拷贝.
当控制权传递给调用函数时,该拷贝将被销毁,并且传递的映射仍然为空。
要通过引用传递 map ,您需要添加 &
函数声明中参数的类型。
即在头文件中,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
明确地。
关于C++ 在 main 中调用打印 map 的函数时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2075008/