ошибка "неопределенная ссылка" с g ++ - PullRequest
2 голосов
/ 14 сентября 2011

Я только что написал простую игру (если вам интересно, каждый игрок должен сказать слово, начинающееся с последней буквы слова, сказанного его противником.) Он не скомпилируется со следующим выводом:

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";
    }
}   
}

Я не мог понять ни причину ошибки, ни как ее исправить, поэтому, пожалуйста, скажите мне, что я делаю неправильно.

1 Ответ

3 голосов
/ 14 сентября 2011

Удалите файлы компиляции / объектных файлов в вашем каталоге и перекомпилируйте - код работает отлично, вам, вероятно, просто нужна make-clean.

...