Subscribe to The Occasional Programmer        RSS Feed
-----

C++ Navajo Windtalker Translator

Icon 1 Comments
A poster brought up the Navajo Windtalker code and thought a translator might be a neat project as a beginner in C++. I thought I'd whip something up as a way to keep my waning C++ skills from completely falling by the wayside.

#include <iostream>
#include <fstream>
#include <string>
#include <map>
#include <cstdlib>
#include <sstream>
#include <cctype>

using namespace std;


class NavajoTranslator
{
   // Alias the multimap
   typedef multimap<char, string> CharToMultiStringDict;
  
   public:
      NavajoTranslator() : randomize_(true) { srand(time(NULL)); }
      NavajoTranslator(bool randomize) : randomize_(randomize) { srand(time(NULL)); }
      bool loadDict(const string& dictFile);
      string translateString(const string &toBeTranslated) const;
      string translateFile(const string &fileToTranslate) const;

   private:
      string getCode(char c) const;
      string getRandomCode(char c) const;
      bool randomize_;
      CharToMultiStringDict dict_;
};

// Loads the dictionary from a file
bool NavajoTranslator::loadDict(const string& dictFile) {
   ifstream inFile(dictFile.c_str());
   if (!inFile.good()) {
      return false;
   }

   char letter;
   string word;
   string mapping; // Ignored
   while(inFile >> letter >> word >> mapping) {
      dict_.insert(pair<char, string>(letter, word));
   }

   return true;
}

string NavajoTranslator::getRandomCode(char c) const {
   // Get the number of entries for this character
   int numChoices = dict_.count(c);
  
   // Randomly select an entry
   int choice = (rand() % numChoices);  
   // Iterator to the start of entries for this character
   CharToMultiStringDict::const_iterator it = dict_.equal_range(c).first;
   // Iterator to one past the end of the entries for this character
   CharToMultiStringDict::const_iterator itEnd = dict_.equal_range(c).second;
   int i = 0; // Counter
   // Go through the entries until we reach the randomly-selected one,
   // at which point we return the corresponding string
   while (itEnd != it) {
      if (choice == i) {
         return it->second;
      }
      ++i;
      ++it;
   }
  
   string notFound(1, c);
   return notFound;
}

string NavajoTranslator::getCode(char c) const {
   if (!isalpha(c)) {
      // If this is a non-alpha char, then just return the char
      string notFound(1, c);
      return notFound;
   }
  
   if (randomize_) {
      return getRandomCode(toupper(c));
   }
   // Find the character in the multimap and return the corresponding string
   CharToMultiStringDict::const_iterator it = dict_.find(toupper(c));
   if (it != dict_.end())
      return it->second;

   string notFound(1, c);
   return notFound;
}

string NavajoTranslator::translateString(const string &toBeTranslated) const {
   stringstream translated;

   // Go through each character in the string, get the corresponding code,
   // and add it to the stringstream object.
   string::const_iterator it = toBeTranslated.begin();
   string::const_iterator itEnd = toBeTranslated.end();
   while (itEnd != it) {
      translated << getCode(*it++) << " ";
   }
  
   // Return the string stored in the stringstream object.
   return translated.str();
}

string NavajoTranslator::translateFile(const string &fileToTranslate) const {
   stringstream translated;

   ifstream inFile(fileToTranslate.c_str());
   // Read each line in the provided file, passing the line to the
   // translate string function above.
   if (inFile.good()) {
      string line;
      while (getline(inFile, line)) {
         translated << translateString(line) << endl;
      }
   }

   return translated.str();
}

int main()
{
   NavajoTranslator translator;
   if (!translator.loadDict("navajo_dict.txt")) {
      cerr << "Failed loading dictionary" << endl;
      return 1;
   }

   cout << "Enter string for translation: ";
   string toTranslate;
   getline(cin, toTranslate);
   if (cin.good()) {
      cout << toTranslate << " translates to " << translator.translateString(toTranslate) << endl;
   }

   cout << "Enter file for translation: ";
   getline(cin, toTranslate);
   if (cin.good()) {
      cout << "File " << toTranslate << " translates to:" << endl << translator.translateFile(toTranslate) << endl;
   }
   return 0;
}



It's a bit rough and in need of improvement, but it's functional.

EDIT: Oops, I forgot to mention this. The dictionary file came from this page; I simply copied the lines containing the alphabet and code (and the third column as well, although it is ignored in the code) and pasted it into a text file.

1 Comments On This Entry

Page 1 of 1

trevster344 Icon

05 December 2011 - 05:29 PM
I ran into your post on the home page primarily a .net programmer right now but I really enjoyed this project. Nice job! :)
0
Page 1 of 1

Trackbacks for this entry [ Trackback URL ]

There are no Trackbacks for this entry

April 2014

S M T W T F S
  12345
6789101112
13141516 17 1819
20212223242526
27282930   

Recent Entries

Recent Comments

Search My Blog

0 user(s) viewing

0 Guests
0 member(s)
0 anonymous member(s)