Hi,
I am working on a program that reads through a file, gets the words, and finds all the anagrams in the file. For example if the input is
Pans
stop
pots
pots
Sits
it's
snap
I have no trouble reading the words from the file. I create a signature for each word as such.
Original Word Signature
Pans anps
snap anps
Sit ist
it’s ist
stop opts Pots opts Pots opts
opt opt
Now I am suppose to sort the anagrams by lines and then display as such :
Pans snap
Pots stop Pots
Sit it’s
opt
This is where I am stuck. I am having difficulty geting pass the signatures.
What I want to do is use a 2D vector or array and then sort it by the signatures. Then I could go through the sorted word list and display play all the anagrams line by line.
I need help. This is the code that I have so far.
//CLASS DECLARATION
class anagram{
private: //I have variables here
public:
//Constructor
anagram(){
}
//MEMBER FUNCTIONS
//get and returns the name of the input file
string get_fileName(){
cout << "Please Enter the Name of the File: ";
getline(cin, fileName);
return fileName;
}//end
//opens, reads, and closes the input file
void processFile (){
//open file
inFile.open(fileName.c_str(),ios::in);
//CHECK if file opens
if (inFile.bad() || inFile.fail()){
cerr << "\tFile Does Not Exist OR the Name is spelled incorrectly --> "
<< fileName << endl << endl;
exit(1);
}
//CHECK if file is "empty"
long int byteSize = 0;
//move pointer and get length
inFile.seekg(0, ios::end);
//get the position of the pointer
byteSize = inFile.tellg();
if ( byteSize == 0) { // input file is empty; size = 0 bytes
cerr << "\t\t\tThe file --> " << fileName << " is empty" << endl;
exit(1);
}
else
//rewind the stream
inFile.seekg(0, ios::beg);
//////////Now PROCESS the words in the file//////////////////////////////////////////////
//initialize the word counter
numWords = 0;
while (!inFile.eof()){
//get_fileName();
//get data in lines from the file
getline(inFile, line);
//break lines into words
istringstream instr (line);
while (instr >> word){
//check length of word >= 15
//cout << word << endl;
if (word.length() <= 15){
word = removeJunk(word);
//build the list of words
//change word case and store
//transform (word.begin(), word.end(),word.begin(), tolower);
//mod_wordList.push_back(word);
//sort words and store into vector
//sort(word.begin(),word.end());
//wordDict.push_back(word);
//Add to dictionary
wordList.push_back(word);
numWords++;
//TERMINATE pogram if number of words of proper length exceeds 50
if(numWords > 50){
cout << "\t\tThere are more than 50 words in " << fileName << endl;
exit (1);
}
}//end if
}//end inner while
}//end outer while
inFile.close();//close the file
cout << "NUM = " <<numWords << endl;
for (int i = 0; i < wordList.size(); i++){
cout << wordList[i] << endl;
}
cout<<endl;
}//end procesFile
//removes excess characters from words
string removeJunk(string word){
int numChars =0;
int wordLength = word.length(); //stores the processed word
string result; //stores the porcessed word
for (int i=0; i < wordLength; i++){
if (isalpha(word[i])){
result = result + word[i];
numChars++;
}
}
//ACCOUNT for a file of non alpha characters
if (numChars == 0){
cerr << "\t\tThe file --> " << fileName << " contains 0 words!!!" << endl;
exit(1);
}
return result;
}//endEasiest way to sort two arrays at the same time is to create another array used as an index array into the two originals. For example:
string words[20];
string signature[20];
int index[20] = {0,1,2,3,4 ... 18,19}; Now accesssignature array using the index array for the sort: signature[index[j]]
You end up sorting theindex array instead of the string arrays. Once sorted, access both signature and words using index and they still match.
> This is where I am stuck. I am having difficulty geting pass the signatures.
What I want to do is use a 2D vector or array and then sort it by the signatures.
So basically you want to create a class and then have the option to sort by its various attributes. In that case you can utilize std::sort to achieve your goals. Viz...
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
class Student
{
public:
string name;
double tuition;
};
//This functions sort by name
bool SortStudentByName ( const Student& left, const Student& right )
{
//Here you can define whatever the sort criterion
//needs to be. It can be as complicated as you wish
if ( left.name > right.name )
{
return false;
}
else if ( left.name < right.name )
{
return true;
}
//else //i.e if both are equal
}
//This function sorts by tuitions fees
bool SortStudentByTute ( const Student& left, const Student& right )
{
if ( left.tuition > right.tuition )
{
return false;
}
else if ( left.tuition < right.tuition )
{
return true;
}
}
int main()
{
Student myStudent [3]; //create an array of objects
myStudent[0].name = "sarah";
myStudent[0].tuition = 10.2;
myStudent[1].name = "carry";
myStudent[1].tuition = 11.2;
myStudent[2].name = "zog";
myStudent[2].tuition = 3;
// call the sort like this (assuming array has size of 3):
cout << "sorting by tutition fees\n";
std::sort ( myStudent, myStudent + 3, SortStudentByTute );
cout << myStudent[0].name << " " << myStudent[0].tuition << endl;
cout << myStudent[1].name << " " << myStudent[1].tuition << endl;
cout << myStudent[2].name << " " << myStudent[2].tuition << endl;
//--------------------------------------------------------
cout << "\nsorting by names\n";
std::sort ( myStudent, myStudent + 3, SortStudentByName );
cout << myStudent[0].name << " " << myStudent[0].tuition << endl;
cout << myStudent[1].name << " " << myStudent[1].tuition << endl;
cout << myStudent[2].name << " " << myStudent[2].tuition << endl;
// Or use a vector instead of the array and sort like this:
//std::sort(myStudentVec.begin(), myStudentVec.end(), SortStudentByName);
cin.get();
}