Thread: sorting an array by alphabetizing the char*

  1. #1
    Registered User
    Join Date
    Nov 2011
    Posts
    6

    sorting an array by alphabetizing the char*

    I'm not really sure what I am doing for my assignment, though I have spent the better part of 5 days trying to figure this project out. The outcome is to get the program to read the list of words off a text document, create a key for each word (ie. "letter" would have the key "eelrt") and then sort them if their keys match (matching anagrams together on one line). Currently I am working on the sorting part, but I quite honestly don't know what I'm doing...

    Code:
    #include <iostream>
    char** read(const char* fileName, int& count);
    class KeyedWord {
    private:
     char* _word;
     char* _key;
    public:
     KeyedWord(char* word);
     char* getWord() { return _word; }
     char* getKey() { return _key; }
     char* getAnagram() { return getKey(); }
    };
    KeyedWord::KeyedWord(char* word)
    {
     _word = word;
    }
    // sort by increasing anagram
    void sort(KeyedWord** key, int numberOfObjects)
    {
     int arrayLength;
    //finds length of string for each array
    string strHold(key);
    arrayLength = strHold.length();//sorts letters of word in alphabetical order to make key
    for (int index = (arrayLength - 1); index >= 0; index--) {
     for (int index2 = 1; index2 <= index; index2++) {
      if (key[index2-index] > key[index]) {
       char hold = key[index2-1];
       key[index2-1] = key[index2];
       key[index2] = hold;
      } // end if
     } // end for
    } // end for
    
    }
    void printAnagrams(KeyedWord** keyedWords, int numberOfObjects)
    {
     int wordIndex = 0; 
     while (wordIndex + 1 < numberOfObjects) {
      char* anagram = keyedWords[wordIndex]->getKey();
      if (anagram == keyedWords[wordIndex + 1]->getKey()) {
       std::cout << "Anagrams: " << std::endl;
       std::cout << " " << keyedWords[wordIndex]->getWord();
       std::cout << " " << keyedWords[wordIndex + 1]->getWord();
       wordIndex += 1;
       while (wordIndex + 1 < numberOfObjects && anagram == keyedWords[wordIndex + 1]->getKey()) {
        std::cout << " " << keyedWords[wordIndex + 1]->getWord();
        wordIndex += 1;
       }
       std::cout << std::endl;
      } else {
       wordIndex += 1;
      }
     }
    }
    
    void main(int argumentCount, char** arguments)
    {
     if (argumentCount <= 1) {
      std::cout << "No file name given as argument" << std::endl;
     } else {
      int numberOfWords = 0;
      int testArraySize = 6;
      char** words = read(arguments[1], numberOfWords);
      char* testWords[6] = {"RUDE", "WORD", "DURE","FROM", "FORM", "LETTER" };
      // allocate the arrays of KeyedWord objects
      KeyedWord** keyedWords = new KeyedWord* [numberOfWords];
      KeyedWord** testKeyedWords = new KeyedWord* [6];
      // populate the array of keyedWord objects
      for (int wordIndex = 0; wordIndex < numberOfWords; ++wordIndex)
      {
       keyedWords[wordIndex] = new KeyedWord(words[wordIndex]);
      }
      //populate the array of testKeyedWords objects
      for (int wordIndex = 0; wordIndex < testArraySize; ++wordIndex) {
       testKeyedWords[wordIndex] = new KeyedWord(testWords[wordIndex]);
       std::cout << testWords[wordIndex] << std::endl;
      }
      sort(testKeyedWords, testArraySize);
      printAnagrams(testKeyedWords, testArraySize);
      /*/tests ability to read words.txt file
      for(int i = 0; i < numberOfWords; i++) {
       std::cout << words[i]<< std::endl;
       if (i == 200)
        system ("pause");
       else if (i == 400)
        system ("pause");
       else if (i == 600)
        system ("pause");
       else if (i == 800)
        system ("pause");
       else if (i == 1000)
        system ("pause");
      }
      std::cout << std::endl;
      system ("pause");*/
        
     //sort(keyedWords, numberOfWords);
     
     //printAnagrams(keyedWords, numberOfWords);
     for (int wordIndex = 0; wordIndex < numberOfWords; wordIndex++) {
      delete keyedWords[wordIndex];
     }
     delete [] keyedWords;
    
     system("pause");
     }
    }
    I'm sorry about the code being so jammed together, I'm not quite sure how to post it properly yet. so I highlighted in blue the part I am working on, the test file of 6 words. If I can get that far, I should be able to do the .txt file.

    Originally it sorted only the initial first letter to the front of the line, then quit, and now there is some kind of error with the identifier of "string" for "strHold(key)"?? Any help would be greatly appreciated. I have heard something about a squot? or something...but I honestly don't know enough about built in functions to grasp it...

    Thanks in advance for the help!

    ~Shadow

  2. #2
    Registered User
    Join Date
    Nov 2011
    Posts
    6
    Unfortunately the deadline has already passed... Regardless I still would like to know how to get this to work. I found out a little that the initial collection of the key should have been in the constructor...though every time I try to impliment it, it begins the exchange of letters, then I get the Key "(something close)garbage of characters and a heart" -_-

    Anyway, after doing away with the entire sort function, I have this in the Constructor now:

    Code:
    KeyedWord::KeyedWord(char* word)
    {
     
     _word = word;
     
     char key[20];
      //sorts letters of word in alphabetical order to make key
      for (int index = (strlen(word) - 1); index >= 0; index--) {
       key[index] = word[index];
       for (int index2 = 1; index2 <= index; index2++) {
        if (key[index2-index] > key[index]) {
         char hold = key[index2-1];
         key[index2-1] = key[index2];
         key[index2] = hold;
        } // end if
        key[index2] = word[index2];
       } // end for
      } // end for
      //sets key to the word key
      _key = key;
     std::cout << *key << std::endl;
    }
    

  3. #3
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    1.
    create a key for each word (ie. "letter" would have the key "eelrt")
    Do you mean "eelrtt" as a key?

    2. You should be using std::string containers instead of all those char pointers. Your use of them - by simple assignment of word to _word - in the constructor is particularly worrying.

    3. It should never be void main, only int main.

    4. Your use of dynamic memory allocation is unnecessary. You should instead be using some type of STL container of such KeyedWord objects. Some containers automatically sort based on a given rule, others you can sort based on a passed in parameter to a sorting function. Get familiar with the STL especially the containers:
    Code:
    #include <string>
    #include <vector>
    #include <set>
    #include <algorithm>
    #include <iterator>
    #include <iomanip>
    
    struct person
    {
        std::string firstname;
        std::string lastname;
        int age;
        person(const std::string& fname,
               const std::string& lname,
               int yrs) : firstname(fname), lastname(lname), age(yrs)
        {
            // Empty constructor
        }
    };
    
    //Overloaded operator<<
    std::ostream& operator<<(std::ostream& lhs, const person& rhs)
    {
        return lhs << "Name: " << std::setw(10) << std::left << rhs.lastname
            << ", " << std::setw(12) << std::left << rhs.firstname
            << "\tAge: " << rhs.age;
    }
    
    // Default sort method: sorts according to lastname, firstname
    struct default_sort
    {
        inline bool operator()(const person& lhs, const person& rhs) const
        {
            if( lhs.lastname == rhs.lastname )
            {
                    return lhs.firstname < rhs.firstname;
            }
            else
                return lhs.lastname < rhs.lastname;
        }
    };
    
    // Sort by age, then lastname
    struct age_sort
    {
        inline bool operator()(const person& lhs, const person& rhs) const
        {
            if(lhs.age == rhs.age)
            {
                return lhs.lastname < rhs.lastname;
            }
            else
                return lhs.age < rhs.age;
        }
    };
    
    // SET container uses the less-than operator as a default for how to sort
    bool operator<(const person& lhs, const person& rhs)
    {
        return default_sort()(lhs,rhs);
    }
    
    
    int main()
    {
        std::set<person> personSet;
        std::vector<person> personVect;
        person people[] = {person("Bart","Simpson",12),
                           person("Lisa","Simpson",10),
                           person("Marge","Simpson",38),
                           person("Homer","Simpson",40),
                           person("Montgomery","Burns",100),
                           person("Milhouse","Van Houten",12)};
        const int num_people = sizeof(people)/sizeof(person);
    
        // Load set/vector with data from the array
        std::copy(people,people+num_people,back_inserter(personVect));
        std::copy(people,people+num_people,inserter(personSet,personSet.end()));
    
        // Display set contents, container is automatically sorted according to operator<
        std::cout << "Writing contents of SET container: " << std::endl;
        std::copy(personSet.begin(),personSet.end(),
                  std::ostream_iterator<person>(std::cout,"\n"));
    
        // Display vector contents, unsorted currently
        std::cout << "\n\nWriting contents of VECTOR container (unsorted): " << std::endl;
        std::copy(personVect.begin(),personVect.end(),
            std::ostream_iterator<person>(std::cout,"\n"));
    
        // Sort by age and redisplay vector contents
        std::sort(personVect.begin(),personVect.end(),age_sort());
        std::cout << "\n\nWriting contents of VECTOR container (age sort): " << std::endl;
        std::copy(personVect.begin(),personVect.end(),
            std::ostream_iterator<person>(std::cout,"\n"));
    
        // Resort by default and redisplay vector contents
        std::sort(personVect.begin(),personVect.end(),default_sort());
        std::cout << "\n\nWriting contents of VECTOR container (default sort): " << std::endl;
        std::copy(personVect.begin(),personVect.end(),
            std::ostream_iterator<person>(std::cout,"\n"));
    
        return 0;
    }
    Output:
    Attached Images Attached Images sorting an array by alphabetizing the char*-untitled-jpg 
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  4. #4
    Registered User
    Join Date
    Nov 2011
    Posts
    6
    1. Sorry yes, the key would have been "eelrtt"

    2. Unfortunately that was how the project was given. The only thing I have control over is the way in which the constructor sorted the information, the sort function, and the print function. Although, truth be told I couldn't make heads or tails of the char* _key and ended up using a string like so:
    Code:
    
    #include <iostream>
    #include <string>
    
    char** read(const char* fileName, int& count);
    
    class KeyedWord {
    private:
    char* _word; std::string _key;
    public:
    KeyedWord(char* word); char* getWord() { return _word; } std::string getKey() { return _key; }
    }; KeyedWord::KeyedWord(char* word) {
    _word = word; std::string key = word; int doubleCheck = 0; //makes key sort perform repeatedly to check for missed letters //sorts letters of word in alphabetical order to make key while (doubleCheck < strlen(word)) {
    for (int index = 0; index < strlen(word); index++) { //pushes greater charater to the end of the line
    if ((index + 1) < strlen(word) && key[index] > key[index + 1]) {
    char hold = key[index + 1]; key[index + 1] = key[index]; key[index] = hold;
    }
    }
    doubleCheck++; } //sets key to the word key _key = key;
    } // sort by increasing anagram void sort(KeyedWord** keyedWords, int numberOfObjects) {
    for (int wordIndex = 0; wordIndex < numberOfObjects; wordIndex++) {
    std::cout << keyedWords[wordIndex]->getWord() << " "; std::cout << keyedWords[wordIndex]->getKey() << std::endl;
    }
    } void printAnagrams(KeyedWord** keyedWords, int numberOfObjects) {
    std::cout << "Anagrams: " << std::endl; for (int wordIndex = 0; wordIndex < numberOfObjects; wordIndex++) {
    KeyedWord* temp = (keyedWords[wordIndex]);
    for (int checkKey = 0; checkKey < numberOfObjects; checkKey++) {
    if (wordIndex != checkKey && keyedWords[wordIndex]->getKey() == keyedWords[checkKey]->getKey()) { std::cout << " " << keyedWords[wordIndex]->getWord();
    while (checkKey < numberOfObjects && keyedWords[wordIndex]->getKey() == keyedWords[checkKey]->getKey()) {
    if (keyedWords[wordIndex]->getWord() != keyedWords[checkKey]->getWord())
    std::cout << " " << keyedWords[checkKey]->getWord(); checkKey++;
    }
    std::cout << std::endl; break; }
    }
    }
    } int main(int argumentCount, char** arguments) { if (argumentCount <= 1) { std::cout << "No file name given as argument" << std::endl; } else { int numberOfWords = 0; int testArraySize = 6; char** words = read(arguments[1], numberOfWords); char* testWords[6] = {"RUDE", "WORD", "DURE","FROM", "FORM", "LETTER" }; // allocate the arrays of KeyedWord objects KeyedWord** keyedWords = new KeyedWord* [numberOfWords]; KeyedWord** testKeyedWords = new KeyedWord* [6]; //populate the array of testKeyedWords objects for (int wordIndex = 0; wordIndex < testArraySize; ++wordIndex) { testKeyedWords[wordIndex] = new KeyedWord(testWords[wordIndex]); } sort(testKeyedWords, testArraySize); printAnagrams(testKeyedWords, testArraySize); system ("pause"); // populate the array of keyedWord objects for (int wordIndex = 0; wordIndex < numberOfWords; ++wordIndex) { keyedWords[wordIndex] = new KeyedWord(words[wordIndex]); } sort(keyedWords, numberOfWords); printAnagrams(keyedWords, numberOfWords); system ("pause"); // EXTRA CREDIT (+5 points): clean up all allocated memory int allocateMemory = 0; std::cout << "Would you like to clear allocated memory? Press 1 for Yes. "; std::cin >> allocateMemory; if (allocateMemory == 1) { for(int i = 0 ; i < numberOfWords ; i++) { delete keyedWords[i]; keyedWords [i] = NULL; } delete keyedWords; keyedWords = NULL; std::cout << "Memory has been cleared!" << std::endl; } else std::cout << "Memory has NOT been cleared!" << std::endl; system ("pause"); return 0; } }
    It works...sort of? though it makes the sort function irrelivant... and the anagrams printed by the print function repeat themselves. I feel I should be adding a "If keyedWords[wordIndex] is used by a previous keyedWords[wordIndex] then skip it" ...

    3.) Yes I went ahead and changed that, thank you for pointing it out

    4.) The memory allocation was extra credit...and I don't know what STL containers are yet.
    Last edited by ShadowDragon; 12-01-2011 at 11:22 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Help With Sorting Char Arrays Using Pointers
    By Charley in forum C++ Programming
    Replies: 3
    Last Post: 04-13-2011, 04:43 PM
  2. uincode char array to array<unsigned char,1>^
    By ripspinner in forum Windows Programming
    Replies: 5
    Last Post: 12-14-2009, 05:41 PM
  3. Replies: 3
    Last Post: 11-17-2008, 12:36 PM
  4. signed char array to unsign char array.
    By beon in forum C Programming
    Replies: 5
    Last Post: 12-14-2006, 07:19 PM
  5. alphabetizing
    By mouse163 in forum C++ Programming
    Replies: 8
    Last Post: 12-18-2002, 03:59 PM