Solved

attempting to convert a single-file project into a multi-file class-based project.

Posted on 2011-09-07
10
451 Views
Last Modified: 2013-12-14
Im attempting to adapt the solution from here for my own purposes but am having issues breaking it down into a mult-file class (.h &.cpp)
Attached are the main.cpp Dicto.cpp and Dicto.h files as I have them currently (will not compile)

Upon compiling I get errors dealing with the Dicto pointer "root" stating it is undeclared though I have it declared in the header and initialized in the constructor.

Please advise I'm sure there is something simple that I've overlooked.
#include <iostream>
#include <fstream>
#include <string>
#include "functions.h"
#include "Dicto.h"
using namespace std;
Dictio::Dictio()
{
   root = new Dictio;
   for (int i = 0; i < 26; ++i)
      a[i] = 0;
   FlagEndWord = false;
   
}

Dictio::~Dictio()
{
   for (int i = 0; i < 26; ++i)
      delete a[i];
}
bool VerifyWord(const char * word, int len)
{
   int plen;
   Dictio * n = root->follow(word,len,plen);
   return (plen == len && n -> IsFullWord());
}

// insert the word into dictionary.
void Dictio::InsertDictionary(const char * word, int len)
{
   int plen;
   Dictio * n = root -> follow(word,len,plen);
   if (plen == len) {
      n -> FlagEndWord = true;
      return;
   }
   // need to add more nodes to the tree.
   do {
      char c = word[plen++];
      if (c >= 'A' && c <= 'Z')
        c = c - 'A' + 'a';
      if (c < 'a' || c > 'z') {
         // Not a word letter.
         // Now if you want to allow for - or other
         // letters in words you can always arrange for
         // that by allow for 27 or more letters in that
         // array, but then the waste becomes even more
         // appearant as every node will have those extra
         // pointers.
         // throw some error if you want here.
         return;
      }
      Dictio * & next = n -> a[c - 'a'];
      if (next != 0) {
         // follow() didn't do what it's supposed to do.
         // fatal error, throw error or something if you
         // want here.
         return;
      }
      next = n = new Dictio;
   } while (plen < len);
}

// read the file and add words to dictionary.
void AppendDictionary(const char * file)
{
   ifstream f(file);
   char buf[100];

   // each line is one word.
   while (f.getline(buf,sizeof(buf),'\n')) {
      // skip the newline at end of line if any.
      f.ignore(1024,'\n');
      Dictio::InsertDictionary(buf,strlen(buf));
   }
}

Dictio * Dictio::follow(const char * word, int len, int & plen)
{
   int x = 0;

   Dictio * n = this;
   while (x < len) {
      char c = word[x++];
      if (c >= 'A' && c <= 'Z')
         c = c - 'A' + 'a';
      if (c < 'a' || c > 'z') {
         // again not a legal letter....
         break;
      }
      Dictio * & next = n -> a[c - 'a'];
      if (next == 0) {
         // continuation not in dictionary.
         break;
      }
      n = next;
   }
   plen = x;
   return n;
}

Open in new window

// reading a text file
#include <iostream>
#include <fstream>
#include <string>
#include "functions.h"
#include "Dicto.h"
using namespace std;


Dictio * root = new Dictio;



int main()
{
   AppendDictionary("dict.txt");
   // use it as you like.
   // if you have a word in a buffer and the length of it
   // you can check if it is in the dictionary by calling
   // follow or VerifyWord.
}

Open in new window

class Dictio {
private:
  Dictio * a[26];
  bool FlagEndWord;
  Dictio * root;
  

public:
   Dictio();
   ~Dictio();
   
   // This function follow from the current node
   // the letters given by word. The word is assumed
   // to be len characters.
   // On output plen will have the length of characters
   // leading to the returned entry.
   // The function searches from the given node
   // for a continuation using the first letter of
   // word and so on until it either find a complete
   // plen == len on output it means the whole word
   // has been read to reach the returned node, otherwise
   // the search stopped at some node because there is
   // no continuation present for the given leters.
   // len == plen and returned node has FlagEndWord
   // it means the input word was in the dictionary and
   // is a complete word.
   // if len == plen but the returned node do not have
   // FlagEndWord it means the 'word' contains a valid
   // prefix but is not in itself a complete word.
   // iF plen < len then not all the characters in word
   // could be followed because the word is not in the
   // dictionary, the plen indicate how many letters make
   // up a prefix that IS in the dictionary.
   // The functions VerifyWord and VerifyList can easily
   // be implemented in terms of this function.
   // also, insertion into the dictionary can be made
   // using this function as this function return the
   // leaf node that represent a prefix.

   Dictio * follow(const char * word, // the word
                   int len, // length of word
                   int & plen); // OUT: Length of prefix.

   bool IsFullWord() const { return FlagEndWord; }

   static void InsertDictionary(const char * word, int len);
};

Open in new window

0
Comment
Question by:ExMachina1123
  • 6
  • 3
10 Comments
 

Author Comment

by:ExMachina1123
ID: 36499228
increased points
0
 
LVL 24

Accepted Solution

by:
alexey_gusev earned 500 total points
ID: 36500877
in VerifyWord() you're using "root" which is declared in main file, so it's not visible in that function. add

extern Dictio* root;

somewhere before VerifyWord().

and besides, shouldn't VerifyWord be a member of Dictio class ?
0
 

Author Comment

by:ExMachina1123
ID: 36500936
ok I changed the .h file to the following

class Dictio {
private:
  Dictio * a[26];
  bool FlagEndWord;
  Dictio * root;
  

public:
   Dictio();
   ~Dictio();

   bool VerifyWord(const char * word, int len);
   void Dictio::AppendDictionary(const char * file);
   Dictio * follow(const char * word, // the word
                   int len, // length of word
                   int & plen); // OUT: Length of prefix.

   bool IsFullWord() const { return FlagEndWord; }

   static void InsertDictionary(const char * word, int len);
};

Open in new window

and the .cpp to
#include <iostream>
#include <fstream>
#include <string>
#include "functions.h"
#include "Dicto.h"
using namespace std;

extern Dictio* root;

Dictio::Dictio()
{
  // root = new Dictio;
   for (int i = 0; i < 26; ++i)
      a[i] = 0;
   FlagEndWord = false;
   
}

Dictio::~Dictio()
{
   for (int i = 0; i < 26; ++i)
      delete a[i];
}

bool Dictio::VerifyWord(const char * word, int len)
{
   int plen;
   Dictio * n = root->follow(word,len,plen);
   return (plen == len && n -> IsFullWord());
}

// insert the word into dictionary.
void Dictio::InsertDictionary(const char * word, int len)
{
   int plen;
   Dictio * n = root -> follow(word,len,plen);
   if (plen == len) {
      n -> FlagEndWord = true;
      return;
   }
   // need to add more nodes to the tree.
   do {
      char c = word[plen++];
      if (c >= 'A' && c <= 'Z')
        c = c - 'A' + 'a';
      if (c < 'a' || c > 'z') {
         // Not a word letter.
         // Now if you want to allow for - or other
         // letters in words you can always arrange for
         // that by allow for 27 or more letters in that
         // array, but then the waste becomes even more
         // appearant as every node will have those extra
         // pointers.
         // throw some error if you want here.
         return;
      }
      Dictio * & next = n -> a[c - 'a'];
      if (next != 0) { 
         // follow() didn't do what it's supposed to do.
         // fatal error, throw error or something if you
         // want here.
         return;
      }
      next = n = new Dictio;
   } while (plen < len);
}

// read the file and add words to dictionary.
void Dictio::AppendDictionary(const char * file)
{
   ifstream f(file);
   char buf[100];

   // each line is one word.
   while (f.getline(buf,sizeof(buf),'\n')) {
      // skip the newline at end of line if any.
      f.ignore(1024,'\n');
      Dictio::InsertDictionary(buf,strlen(buf));
   }
}

Dictio * Dictio::follow(const char * word, int len, int & plen)
{
   int x = 0;

   Dictio * n = this;
   while (x < len) {
      char c = word[x++];
      if (c >= 'A' && c <= 'Z')
         c = c - 'A' + 'a';
      if (c < 'a' || c > 'z') {
         // again not a legal letter....
         break;
      }
      Dictio * & next = n -> a[c - 'a'];
      if (next == 0) {
         // continuation not in dictionary.
         break;
      }
      n = next;
   }
   plen = x;
   return n;
}

Open in new window


but I am getting error
Error      1      error C2227: left of '->follow' must point to class/struct/union/generic type      
targeting the line

Dictio * n = root -> follow(word,len,plen);

Open in new window


we are getting closer.


0
 
LVL 86

Expert Comment

by:jkr
ID: 36503363
Try removing the whitespace about the operator, i.e.
Dictio * n = root->follow(word,len,plen);

Open in new window

0
 
LVL 24

Assisted Solution

by:alexey_gusev
alexey_gusev earned 500 total points
ID: 36506371
indeed, we are getting closer :)

so, I feel I have to clarify few things:

- if you declared some member variable then it is visible in any member functions EXCEPT static ones (eg InsertDictionary() in your last post)
- static functions and members are like global ones but provide more OO design and so on
- you can declare global variables in one file and then use "extern sometype somevariable" in other files so it's visible there OR put that line in header file and include it; but you have to declare the variable itself somewhere, so compiler knows how to compile and link the code

So to cut long story short, your InsertDictionary is static, so root variable does NOT exist for such case (because it is not declared as "static"). I'm not sure why InsertDictionary() should ever be static. So I'd advise to spend some time on cleaning up the design issues.
0
6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

 

Author Comment

by:ExMachina1123
ID: 36507302
removing white space had no effect.
0
 

Author Comment

by:ExMachina1123
ID: 36507326
removing "static" allowed compilation!
0
 

Author Comment

by:ExMachina1123
ID: 36507334
for any one with future interest the following will compile

main. cpp
// reading a text file
#include <iostream>
#include <fstream>
#include <string>
#include "functions.h"
#include "Dicto.h"
using namespace std;

Dictio * test = new Dictio;

int main()
{
   test->AppendDictionary("dict.txt");
   // use it as you like.
   // if you have a word in a buffer and the length of it
   // you can check if it is in the dictionary by calling
   // follow or VerifyWord.
}

Open in new window


Dicto.h
class Dictio {
private:
  Dictio * a[26];
  bool FlagEndWord;
  Dictio * root;
  

public:
   Dictio();
   ~Dictio();

   bool VerifyWord(const char * word, int len);
   void AppendDictionary(const char * file);
   Dictio * follow(const char * word, // the word
                   int len, // length of word
                   int & plen); // OUT: Length of prefix.

   bool IsFullWord() const { return FlagEndWord; }

   void InsertDictionary(const char * word, int len);
};

Open in new window


Dicto.cpp
#include <iostream>
#include <fstream>
#include <string>
#include "functions.h"
#include "Dicto.h"
using namespace std;

extern Dictio* root;

Dictio::Dictio()
{
  // root = new Dictio;
   for (int i = 0; i < 26; ++i)
      a[i] = 0;
   FlagEndWord = false;
   
}

Dictio::~Dictio()
{
   for (int i = 0; i < 26; ++i)
      delete a[i];
}

bool Dictio::VerifyWord(const char * word, int len)
{
   int plen;
   Dictio * n = root->follow(word,len,plen);
   return (plen == len && n -> IsFullWord());
}

// insert the word into dictionary.
void Dictio::InsertDictionary(const char * word, int len)
{
   int plen;
   Dictio * n = root->follow(word,len,plen);
   if (plen == len) {
      n -> FlagEndWord = true;
      return;
   }
   // need to add more nodes to the tree.
   do {
      char c = word[plen++];
      if (c >= 'A' && c <= 'Z')
        c = c - 'A' + 'a';
      if (c < 'a' || c > 'z') {
         // Not a word letter.
         // Now if you want to allow for - or other
         // letters in words you can always arrange for
         // that by allow for 27 or more letters in that
         // array, but then the waste becomes even more
         // appearant as every node will have those extra
         // pointers.
         // throw some error if you want here.
         return;
      }
      Dictio * & next = n -> a[c - 'a'];
      if (next != 0) { 
         // follow() didn't do what it's supposed to do.
         // fatal error, throw error or something if you
         // want here.
         return;
      }
      next = n = new Dictio;
   } while (plen < len);
}

// read the file and add words to dictionary.
void Dictio::AppendDictionary(const char * file)
{
   ifstream f(file);
   char buf[100];

   // each line is one word.
   while (f.getline(buf,sizeof(buf),'\n')) {
      // skip the newline at end of line if any.
      f.ignore(1024,'\n');
      Dictio::InsertDictionary(buf,strlen(buf));
   }
}

Dictio * Dictio::follow(const char * word, int len, int & plen)
{
   int x = 0;

   Dictio * n = this;
   while (x < len) {
      char c = word[x++];
      if (c >= 'A' && c <= 'Z')
         c = c - 'A' + 'a';
      if (c < 'a' || c > 'z') {
         // again not a legal letter....
         break;
      }
      Dictio * & next = n -> a[c - 'a'];
      if (next == 0) {
         // continuation not in dictionary.
         break;
      }
      n = next;
   }
   plen = x;
   return n;
}

Open in new window


thanks alot alexy!
0
 

Author Closing Comment

by:ExMachina1123
ID: 36507344
thanks again!
0
 
LVL 24

Expert Comment

by:alexey_gusev
ID: 36507986
just for the sake of education :) - if I were you, I'd pass Dictio* to InsertDictionary() instead of using global variable "root" in 2 files
0

Featured Post

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

A short article about a problem I had getting the GPS LocationListener working.
Entering a date in Microsoft Access can be tricky. A typo can cause month and day to be shuffled, entering the day only causes an error, as does entering, say, day 31 in June. This article shows how an inputmask supported by code can help the user a…
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now