在给定自定义代码表的情况下对一串字符进行编码

时间:2016-11-14 13:57:50

标签: c++ string file-io huffman-code

我希望通过遵循代码表以编程方式将存储在文件中的字符串转换为字符代码字符串(编码)。然后应该将二进制代码字符串转到一个文件,稍后我可以将其恢复为字符串(解码)。代码表中的代码是使用霍夫曼算法生成的,代码表存储在文件中。

例如,通过遵循代码表,其中字符及其对应的代码是单个间隔的,如下所示:

0xFFFFC389

编码“HELLO”应输出为“0011101111111”

我的C ++代码似乎无法完成编码的字符串。这是我的代码:

E 110
H 001
L 11
O 111

对于输入字符串“The_Quick_brown_fox_jumps_over_the_lazy_dog”,输出字符串为011100110,但它应该比这更长!

output image

请帮忙!有什么我错过了吗? (n.b.我的C ++代码没有语法错误)

1 个答案:

答案 0 :(得分:1)

让我们来看看主循环,你正在做的工作:

for (int i=0; i<English.length();)
{
    while(!codefile_input.eof())
    {
        codefile_input >> ch >> st;
        if (English[i] == ch)
        {
            outfile<<st;
            cout<<st;
            i++;
        }
    }
}

您的代码将通过codefile_input读取一次,然后卡在codefile_input.eof () == true条件下,然后,for (int i=0; i<English.length();)将成为无限循环,因为事实,它不会成为代码路径,其中i会增加,并且永远不会达到等于English.length ()的值。

作为旁注,请阅读Why is iostream::eof inside a loop condition considered wrong?

为了避免上述问题,请考虑将字典文件读取到数据容器(例如std::map),然后在迭代字符串时使用它来编码。

例如:

std::ifstream codefile_input("codefile.txt");
char ch;
std::string str;
std::map<char, std::string> codes;
while (codefile_input >> ch >> str)
    {
    codes[ch] = str;
    }

codefile_input.close ();

for (int i=0; i<English.length(); ++i)
    {
    auto it = codes.find (English[i]);
    if (codes.end () != it)
        {
        outfile << codes->second;
        cout << codes->second;
        }
    }

注意,您需要#include <map>才能使用std::map

除了解决问题之外,你的问题实际上是关于你的循环:

while (!infile.eof())
{
  getline (infile,English);
}

只读取文件的最后一行,同时丢弃之前的所有其他行。如果要处理文件中的所有行,请考虑将该循环更改为:

while (std::getline (infile, English))
    {
    /* Line processing goes here */
    }

而且,既然你的词典对于不同的行不太可能不同,你可以将这个逻辑移到这个循环的前面:

std::ifstream codefile_input("codefile.txt");
char ch;
std::string str;
std::map<char, std::string> codes;
while (codefile_input >> ch >> str)
    {
    codes[ch] = str;
    }

codefile_input.close ();

ifstream infile("English.txt");
if (!infile.is_open())  
    {    
    cout << "Cannot open file.\n";    
    exit(1); 
    }

ofstream outfile ("compressed.txt");
string English;
while (std::getline (infile, English))
    {
    for (int i=0; i<English.length(); ++i)
        {
        auto it = codes.find (English[i]);
        if (codes.end () != it)
            {
            outfile << codes->second;
            cout << codes->second;
            }
        }
    }

此外,请考虑为您打开的所有文件添加错误检查。您检查是否可以打开文件English.txt,如果不能,请退出,但不要检查是否可以打开任何其他文件。

在不相关的注释#2上,考虑阅读Why is “using namespace std” considered bad practice?(这就是为什么你看到我在代码中明确使用std::的原因,我添加了)。