Я только что написал простую игру (если вам интересно, каждый игрок должен сказать слово, начинающееся с последней буквы слова, сказанного его противником.)
Он не скомпилируется со следующим выводом:
totosus@btop:~/projects/dict$ g++ wordgame.cc
/tmp/ccIjadX8.o: In function `main':
wordgame.cc:(.text+0x90b): undefined reference to `WGdict::~WGdict()'
wordgame.cc:(.text+0x92e): undefined reference to `WGdict::~WGdict()'
collect2: ld returned 1 exit status
код:
dict.h:
#include <map>
#include <string>
#include <fstream>
#include <set>
#include <vector>
#define ft first
#define sd second
#define MCMSB map<char,map<string,bool> >
#define MSB map<string,bool>
#define PSB pair<string,bool>
using std::map;
using std::vector;
using std::pair;
using std::set;
using std::ifstream;
using std::ofstream;
using std::string;
class WGdict{
private:
MCMSB M;//main map
bool HasBeenFilled;
bool WasUsed(MSB::iterator it){//a small function which checks the "used" bit at the iterator
return (*it).sd;
}
string strip(string str){
string::iterator i = str.begin();
char space = ' ';
while( *i == space){
i = str.erase(str.begin());
}
i = str.end()-1;
while( *i == space){
str.erase(i);
i = str.end()-1;
}
return str;
}
bool FillFromFile(string filename){return FillFromFile(filename,false);}//default
bool FillFromFile(string filename, bool PreserveContents){//fills the main map with contents of file
ifstream dicfile ( filename.c_str() );//open file
if(dicfile.is_open()&&dicfile.good()){
string str;
if(!PreserveContents){
M.clear();//clear map
}
char c;
while(!dicfile.eof()){//get words from file and add them to the map
dicfile>>str;
str = strip(str);
c=str[0];
M[c].insert(PSB(str,false));
}
HasBeenFilled = 1;
dicfile.close();
return true;
}
else if (dicfile.is_open()) dicfile.close();
return false;
}
bool setbool(string word, bool state , bool flip){// set to STATE (or flip) the "used" bool
bool ok = false;
MCMSB::iterator it = M.find(word[0]);
if( it != M.end() ){
MSB::iterator O = it->sd.find(word);
if( O != it->sd.end()){
if(!flip) O->sd = state;
else O->sd = ! (O->sd);
ok=true;
}
}
}
public:
WGdict(){HasBeenFilled = false;}//default constructor
~WGdict(){ M.clear(); }//destructor
WGdict(string fname){//file-opening constructor
open(fname);
}
bool open(string fname){//open new file with default settings
return FillFromFile(fname);
}
bool open(string fname,bool pc){//open new file and choose whether to preserve contents
return FillFromFile(fname,pc);
}
MSB find(char ch){//search the dictionary by first letter
MCMSB::iterator it = M.find(ch);
MSB results;
if (it!=M.end()){
results = (*it).sd;
}
return results;
}
vector<string> find(char ch, bool wu){//search the dictionary by first letter&"used" parameter
vector<string> v;
MSB search = find(ch);
for(MSB::iterator it = search.begin();it!=search.end();it++){
if(WasUsed(it)==wu) v.push_back((*it).ft);
}
}
set<string> findS(char ch, bool wu){//same as previous, but output is in a set
set<string> s;
MSB search = find(ch);
for(MSB::iterator it = search.begin();it!=search.end();it++){
if(WasUsed(it)==wu) s.insert((*it).ft);
}
}
void save(string filename){//save a dictionary
ofstream of( filename.c_str() );
if(of.is_open()&&of.good()){
for(MCMSB::iterator me=M.begin() ; me!=M.end();me++){
for(MSB::iterator i = me->sd.begin(); i != me->sd.end() ; i++){
of<<( (*i).ft+"\n" ).c_str();
}
}
of.close();
}
else if (of.is_open()) of.close();
}
void add(string word){add(word,false);}//add a word to the dictionary
void add(string word,bool b){
char c = strip(word)[0];
M[c].insert(PSB(word,b));
}
bool flip(string word){return setbool(word,0,1);}
bool use(string word){return setbool(word,1,0);}
bool use(string word, bool state){ return setbool(word,state,false);}
bool exists(string word){
bool ok = false;
MCMSB::iterator it = M.find(word[0]);
if( it != M.end() ){
MSB::iterator O = it->sd.find(word);
if( O != it->sd.end()){
ok=true;
}
}
}
bool used(string word){
if(exists(word)){
return M.find(word[0])->sd.find(word)->sd;
}
return true;
}
};
wordgame.cc:
# include "dict.h"
# include <vector>
# include <iostream>
# include <algorithm>
using namespace std;
char getlastletter(string str){return str[str.size()-1];}
char sayword(vector<string> words){
random_shuffle ( words.begin(), words.end() );
string theword = (*words.begin());
cout<<theword;
return getlastletter(theword);
}
char big(char ch){
if('a'<=ch<='z') ch-=32;
return ch;
}
char small(char ch){
if('A'<=ch<='Z') ch+=32;
return ch;
}
string small(string str){
for(string::iterator it = str.begin();it != str.end();it++){
(*it) = small((*it));
}
}
string big(string str){
for(string::iterator it = str.begin();it != str.end();it++){
(*it) = big((*it));
}
}
int main(){
WGdict dict;
vector<string> ws;
string fnm,word;
char yourletter = 'a';
char myletter;
while(true){
cout<<"Write the filename of the dictionary:";
cin>>fnm;
if(fnm == "[exit]" || dict.open(fnm)) break;
else cout<<"It seems that the file \""<<fnm<<"\" does not exist.\n Try again\n\n" ;
}
if(fnm == "[exit]") return 0;
cout<<"Let's play a word game!\n\n";
while(true){
cout<<"My turn: ";
ws = dict.find(yourletter,false);
if(ws.size() == 0){//exit if no more words are available.
cout<<"uh oh. It appears that I couldn't find any unused words with this letter. \n But, yet, congratulations! You won! \n bye! \n";
return 0;
}
myletter = sayword(ws);
cout<<"\n";
ws = dict.find(myletter,false);
if(ws.size() == 0){//exit if no more words are available.
cout<<"So... I managed to win this game! My dictionary contains no more words beginning with this letter. \n Although I won, you also did well. \n bye! \n See you soon!";
return 0;
}
cout<<"Your turn:\n";
while(true){
cout<<big(myletter);
cin>>word;
word = small(word);
if (word == "[exit]") return 0;
if ( word[0] == small(myletter) ){
if(dict.exists(word)) {
if(!dict.used(word)){
yourletter = getlastletter(word);
dict.use(word);
break;
}
else cout<<"this word has already been used \n";
}
else cout<<"Sorry, I couldn't find \""<<word<<"\" in my dictionary. \n";
}else cout<<"\""<<word<<"\" does not begin with letter "<<big(myletter)<<"! \n";
cout<<"try again! \n";
}
}
}
Я не мог понять ни причину ошибки, ни как ее исправить, поэтому, пожалуйста, скажите мне, что я делаю неправильно.