Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

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

Posted on 2011-09-07
10
Medium Priority
?
462 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 3
10 Comments
 

Author Comment

by:ExMachina1123
ID: 36499228
increased points
0
 
LVL 24

Accepted Solution

by:
alexey_gusev earned 2000 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
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
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 2000 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
 

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

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Computer science students often experience many of the same frustrations when going through their engineering courses. This article presents seven tips I found useful when completing a bachelors and masters degree in computing which I believe may he…
Q&A with Course Creator, Mark Lassoff, on the importance of HTML5 in the career of a modern-day developer.
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.

604 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