ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
I was hoping to get some clarification on some things. I know this is the set up for maps / multimaps:
typedef pair<const Key, T> value_type;
replchoices.h
Code:
#ifndef REPLCHOICES_H
#define REPLCHOICES_H
// Spellcheck program: choosing replacements for misspelled words
#include "cs361set.h"
#include <string>
#include <vector>
// This class implements a policy for choosing "plausible"
// replacements for a misspelled word. Many such policies are possible.
// For example, we might choose words from the system dictionary that
// "look like" the misspelled word, or words from the system dictionary that
// "sound like" the misspelled word, or some combination of these.
//
struct ReplacementChooserData;
class ReplacementChooser
{
public:
typedef CS361Set<std::string> Dictionaries;
// Plan for replacements to be suggested from the
// given dictionary.
ReplacementChooser(const Dictionaries& dictionary); // constructor
~ReplacementChooser(); // destructor
// Choose some number of "plausible" replacements for the given word,
// returning them in the order we want them listed to the user.
std::vector<std::string> getPlausibleReplacements(const std::string& word)
const;
private:
ReplacementChooserData* d;
// This is an ilustration of a common programming idiom in C++. Normally,
// the implementing data structure for an ADT is visible in the private
// portion of a class's .h file. Thus if the ADT designer wants to later
// change the data structure, he/she must edit the .h file as well as the
// .cpp file. We can, at a slight cost, however, hide the data structure
// from the .h file by placing the implementing data structure inside
// another class/struct, and simply having a pointer to that class/struct
// in the ADT.
// Don't allow copying and assignment of this ADT
ReplacementChooser(const ReplacementChooser&) {}
void operator= (const ReplacementChooser&) {}
};
#endif
replchoices.cpp
Code:
#include "replchoices.h"
#include "edit1.h"
#include "soundex.h"
#include <algorithm>
#include <map>
using namespace std;
// This class implements a policy for choosing "plausible"
// replacements for a misspelled word. Many such policies are possible.
// For example, we might choose words from the system dictionary that
// "look like" the misspelled word, or words from the system dictionary that
// "sound like" the misspelled word, or some combination of these.
//
struct ReplacementChooserData
{
/*!!
This is the data structure for the "off-by-one-character"
suggestion strategy. You will want to replace this data members
here by a multimap that maps soundex codes to words having that
soundex. Then rewrite the function bodies below accordingly.
!!*/
const ReplacementChooser::Dictionaries& dict;
ReplacementChooserData(const ReplacementChooser::Dictionaries& d): dict(d) {}
};
typedef multimap< ReplacementChooser, ReplacementChooserData, less <ReplacementChooser> > my_Map;
my_Map mm;
pair < multimap < string , string >::iterator, bool > d;
ReplacementChooser::ReplacementChooser(const Dictionaries& dictionary)
{
// d = new ReplacementChooserData(dictionary);
d = mm.insert(ReplacementChooser, ReplacementChooserData(dictionary));
}
ReplacementChooser::~ReplacementChooser()
{
mm.clear();
}
// Choose some number of "plausible" replacements for the given word,
// returning them in the order we want them listed to the user.
vector<string> ReplacementChooser::getPlausibleReplacements
(const string& word) const
{
vector<string> replacements;
for (Dictionaries::const_iterator w = d->dict.begin();
w != d->dict.end(); ++w)
{
if (oneEditAway(word, *w))
replacements.push_back (*w);
}
return replacements;
}
This is what I am trying to accomplish with my multimap.
When the public constructor is called, a multimap is constructed that, for each word W in the dictionary, maps that word's soundex code (computed as extendedSounded(W,-1)) onto W. In other words, this map, when completed, will let you look up words given their soundex codes. We use a multimap for this precisely because many words are supposed to have identical soundex codes.
When a set of replacements for a misspelled word is requested, your code should consult the earlier-constructed multimap to get all dictionary words that sound like the misspelling. These should be sorted these into ascending ASCII lexicographic (i.e., the "usual" case-sensitive string <) order.If there are 10 or fewer such words, return them all. Otherwise, return the first 10 of them.
Am I even on the right track towards implementing this properly? (in regards to my replchoices.cpp as that is the only file that I should change per my instruction).
You've defined your multimap variable, mm, in global scope, meaning it can only have a single instance. Is there anything in ReplacementChooser's interface that precludes client code making multiple instances of it? What would happen with your current design if someone created two ReplacementChoosers?
I believe I only need one instance of it so that I can load the information from a file onto the map. This .cpp doesn't have the main so I don't think I have any other choice than making it global correct?
I believe I am also supposed to use the algorithm from soundex.cpp too.
"The crucial code in this assignment is the ReplacementChooser ADT in replchoices.* and the extendedSoundex() function in soundex.* The extendedSoundex function computes a code string for a word such that similarly pronounced words are supposed to produce identical codes (it's a very crude approach). ReplacementChooser encapsulates the strategy for selecting potential replacement words. You should rewrite the implementation of ReplacementChooser so that (refer to bullets above in OP)"
Code:
#include "soundex.h"
#include <algorithm>
//
// The Soundex code is a rather primitive way of encoding the way words
// (especially names) sound so that variant spellings of the same word may
// be identified by the same code.
//
// Traditional Soundex codes have 4 alphanumeric characters
// 1 Letter and 3 Digits
// - The Letter of the word is the first character of the Soundex code.
// - The 3 digits are defined sequentially from the word using the
// Soundex Key below.
// - Adjacent letters in the word which belong to the same Soundex Key
// code number are assigned a single digit.
// - If the end of the word is reached prior to filling 3 digits,
// use zeroes to complete the code. All codes have only 4 characters,
// even if the word is long enough to yield more.
//
// The Soundex Key:
// 1: b p f v
// 2: c s k g j q x z
// 3: d t
// 4: l
// 5: m n
// 6: r
// no code: a e h i o u y w
// This function computes an "extended" Soundex code of k code characters
// If k<0, the code returned contains as many characters as can be obtained
// from the word by the above rules without adding zeroes at the end.
using namespace std;
string extendedSoundex (const string& word, int k)
{
// "abcdefghijklmnopqrstuvwxyz";
static const char* keys = " 123 12 22455 12623 1 2 2";
string soundexCode;
char lastCode = ' ';
for (int i = 0; i < word.size(); ++i)
{
char c = word[i];
//convert to lowercase, if necessary
if (c >= 'A' && c <= 'Z')
c += 'a' - 'A';
if (i == 0)
// First char of soundex code is the unencoded character
soundexCode += c;
else if (c >= 'a' && c <= 'z')
{
// append the soundex character code
char soundexChar = keys[c - 'a'];
if (soundexChar != lastCode && soundexChar != ' ')
soundexCode += soundexChar;
lastCode = soundexChar;
}
}
if (k >= 0)
{
if (soundexCode.size() > k)
// truncate code to k characters
soundexCode = soundexCode.substr(0, k);
else
// pad code with zeros
soundexCode += string(k-soundexCode.size(), '0');
}
return soundexCode;
}
Was I correct in the Key / T values being ReplacementChooser / ReplacementChooserData?
I believe I only need one instance of it so that I can load the information from a file onto the map. This .cpp doesn't have the main so I don't think I have any other choice than making it global correct?
The comment in the code has your professor asking you to make the multimap collection be a member of ReplacementChooserData. Besides that your teacher has gone to the trouble of controlling how items of the class can be created by hiding its copy operations, so I'd guess if she wanted a singleton (https://en.wikipedia.org/wiki/Singleton_pattern) she would have either designed it that way or made some kind of comment to that effect. Instead you have this: "We can, at a slight cost, however, hide the data structure from the .h file by placing the implementing data structure inside another class/struct, and simply having a pointer to that class/struct in the ADT."
Quote:
Was I correct in the Key / T values being ReplacementChooser / ReplacementChooserData?
Then think more about what the soundex values would be used for, what multimap provides you, what you might want to look up in your application based on what key to get what value(s).
Perhaps it would be helpful if you wrote the program without the pimpl idiom first, putting the multimap directly into ReplacementChooser. Then when you have that working you could move it over to ReplacementChooserData to fit your professor's structure. I'm not saying it's a bad structure, but maybe the issues of separate compilation and preparing you to engineer for large programs is distracting here from grasping what your program is supposed to be doing.
#include "replchoices.h"
#include "edit1.h"
#include "soundex.h"
#include <algorithm>
#include <map>
using namespace std;
// This class implements a policy for choosing "plausible"
// replacements for a misspelled word. Many such policies are possible.
// For example, we might choose words from the system dictionary that
// "look like" the misspelled word, or words from the system dictionary that
// "sound like" the misspelled word, or some combination of these.
//
typedef multimap<string, string> my_map; //have a blank multimap of types stringx2 and load ReplacementChooser etc onto it.
typedef multimap<string, string>::const_iterator it;
my_map extendedSoundex(); //Will become key value of my_map
struct ReplacementChooserData
{
/*!!
This is the data structure for the "off-by-one-character"
suggestion strategy. You will want to replace this data members
here by a multimap that maps soundex codes to words having that
soundex. Then rewrite the function bodies below accordingly.
!!*/
const ReplacementChooser::Dictionaries& dict;
ReplacementChooserData(const ReplacementChooser::Dictionaries& d): dict(d) {}
};
ReplacementChooser::ReplacementChooser(const Dictionaries& dictionary)
{
d = new ReplacementChooserData(dictionary);
my_map::insert(extendedSoundex(stuff?), d); //to load the multimap
}
ReplacementChooser::~ReplacementChooser()
{
delete d; //destructor
}
// Choose some number of "plausible" replacements for the given word,
// returning them in the order we want them listed to the user.
vector<string> ReplacementChooser::getPlausibleReplacements //Will handle this later
(const string& word) const
{
vector<string> replacements;
for (Dictionaries::const_iterator w = d->dict.begin();
w != d->dict.end(); ++w)
{
if (oneEditAway(word, *w))
replacements.push_back (*w);
}
return replacements;
}
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.