试图将一个字母编码成莫尔斯码的等价物

时间:2011-06-26 20:49:21

标签: c++ encoding binary-tree

所以我正在创建一个可以接受字符串并将该字符串编码为莫尔斯代码的程序。反之亦然。我在charToMorse方法中遇到问题但是在mc_tree.cpp中。

字母及其摩尔码等价物按照它们在morse-code.txt中的位置顺序存储在树中。

莫尔斯code.txt:

e .
t -
i ..
a .-
n -.
m --
s ...
u ..-
r .-.
w .--
d -..
k -.-
g --.
o ---
h ....
v ...-
f ..-.
l .-..
p .--.
j .---
b -...
x -..-
c -.-.
y -.--
z --..
q --.-

当用户在encode()中输入字符串时,字符串将通过stringToMorse()和charToMorse()方法分解为字母。 charToMorse()是一个递归方法,它使用char的参数来搜索树,以及指向树根的指针。

它应找到该字符的匹配项,然后返回莫尔斯代码中的等效值。但是,我的代码没有做我认为应该在这部分做的事情。我得到奇怪的输出错误,我不明白。我希望能够通过树搜索charToMorse()并找到该字母,然后输出该字母的莫尔斯码值。

输出:

inside encode
Please enter a message to encode: stringhere
inside stringToMorse
s is = stringhere
inside charToMorse
_, _, 0x10fd410, 0x10fd4b0
inside charToMorse
., e, 0x10fd550, 0x10fd5f0
inside charToMorse
.., i, 0x10fd7d0, 0x10fd870
inside charToMorse
..., s, 0x10fdcd0, 0x10fdd70
inside charToMorse
...., h, 0, 0
terminate called after throwing an instance of 'std::length_error'
what():  basic_string::_S_create
Aborted

以下是我的课程:

#include <iostream>
#include <fstream>
#include <sstream>
#include "mc_tree.h"
#include "MTNode.h"

using namespace std;

mc_tree::mc_tree(){
    root = new MTNode("_", "_", NULL, NULL);
    build_tree();   
}

void mc_tree::build_tree(){
    string line;
    ifstream morse_code_file;
    morse_code_file.open("morse-code.txt");
    //cout << "loading data file" << endl;
    while(!morse_code_file.eof())
    {
        //cout << "inside build_tree() while loop" << endl;
        if(morse_code_file.eof())
        {            
            break;
        }
        else{
            getline(morse_code_file, line);
            addToTree(line);                    
        }                            
    }
    morse_code_file.close();
    //cout << "exiting build_tree()" << endl;   
}

void mc_tree::addToTree(string s){
    string l, c;
    istringstream line(s);
    line >> l >> c;
    MTNode* temp_node = get_root();
    //cout << "trying to insert " << l << " " << c << endl; 
    for(unsigned i = 0; i < c.size(); i++){
        if(c[i] == '.'){
            if(temp_node->dot == NULL)
                temp_node->dot = new MTNode(c,l,NULL,NULL);
            else
                temp_node = temp_node->dot;
        }
        else if(c[i]    == '-'){
            if(temp_node->dash == NULL)
                temp_node->dash = new MTNode(c,l,NULL,NULL);
            else            
                temp_node = temp_node->dash;
        }
        //cout << "c["<<i<<"] = " << c[i] << endl;
        //cout << "temp_node letter " << temp_node->letter 
            //     << " temp_node code " << temp_node->code
            //     << "temp_node->dot " << temp_node->dot
            //     << " temp_node->dash " << temp_node->dash << endl;
    }           
    //temp_node = new MTNode(c,l,NULL,NULL);
    //cout << "exiting addToTree()" <<  endl;
}

string mc_tree::encode(){
    cout << "inside encode " << endl;
    string temp_string;
    string encoded_string;
    cout << "Please enter a message to encode: ";    
    //cin.ignore();
    getline (cin, temp_string);
    encoded_string = stringToMorse(temp_string);    
    return encoded_string;
}

string mc_tree::stringToMorse(string s){
    cout << "inside stringToMorse " << endl;
    cout << "s is = " << s << endl;
    string encoded_string;
    for(unsigned i = 0; i < s.size(); i++){
        encoded_string += charToMorse(s[i], get_root());        
    }
    return encoded_string;  
}

string mc_tree::charToMorse(char c, MTNode* current){
    string encoded_char;
    char l = atoi(current->letter.c_str());
    cout << "inside charToMorse " << endl;
    cout << current->code << ", " << current->letter << ", "\
        << current->dot << ", " << current->dash << endl;

    if(l == c)
        return current->code;
    else if(current == NULL) 
        return "";
    else{
        if(current->dot != NULL)            
            return charToMorse(c, current->dot);
        //cout << current->data;
        if(current->dash != NULL)
            return charToMorse(c, current->dash);
    }

}

void mc_tree::print(MTNode *r){
    if (r) {
        print(r->dot);
        cout << r->letter << " " << r->code << endl;
        print(r->dash);
    }       
}

#ifndef _MTNODE_
#define _MTNODE_

using std::string;

struct MTNode{
    std::string code;
    std::string letter;
    MTNode* dot;
    MTNode* dash;

    //constructor 
    MTNode(const std::string c, const std::string l, MTNode* left = NULL,
        MTNode* right = NULL) : code(c), letter(l), dot(left), dash(right) {}
    //MTNode(): dot(NULL), dash(NULL) {}

    //destructor
    virtual ~MTNode() {}

    //accessors
    std::string get_code(){
        return code;    
    }

    std::string get_letter(){
        return letter;  
    }   
};

#endif 

3 个答案:

答案 0 :(得分:1)

您需要使用树吗?由于您的字母表是有限的并且非常小,因此可以更好地在查找表中对值进行编码。这对编程来说要简单得多,并且执行速度比树搜索快得多。

答案 1 :(得分:0)

正如另一个答案所示,查找表是一个更清洁的解决方案。

关于你的代码: 您使用NULL终止叶节点...现在,当您使用charToMorse时,即使您没有检查整个树,此代码也将终止搜索:

else if(current == NULL) 
    return "";

因此,当您执行递归调用时,请验证返回的值,并仅在您实际找到该字母时终止。

答案 2 :(得分:0)

我认为这是学习使用树木的功课吗? 如果没有,更简单的解决方案可能如下所示:

#include <iostream>
#include <string>
#include <map>
#include <sstream>
using namespace std;

typedef map<string, string> MorseMap;

MorseMap setupAlphaToMorse()
{
  MorseMap map;
  // could populate from a file, or just add them here:
  map["e"] = ".";
  map["t"] = "-";
  // ...
  map["h"] = "....";
  // ...
  return map;
}

string encode(MorseMap& map, const string& source)
{
  stringstream ss;
  for (size_t i = 0; i < source.size(); ++i)
  {
    ss << map[string(1,source[i])] << " ";
  }
  return ss.str();
}

如此使用:

int main()
{
  MorseMap alphaToMorse = setupAlphaToMorse();

  cout << "Result: " << encode(alphaToMorse, "the") << endl;
}

Code

结果:- .... .