2016-11-14 90 views
-3

我想通过跟随代码表以编程方式将存储在文件中的字符串转换为字符代码(编码)的字符串。这串二进制代码应该转到一个文件中,我可以从这个文件中将它恢复为稍后的字符串(解码)。代码表中的代码是使用霍夫曼算法生成的,代码表存储在一个文件中。给定一个自定义代码表的字符串编码

例如,通过下面的一个代码表,其中的字符和其相应的代码是单个隔开这样的:

E 110 
H 001 
L 11 
O 111 

编码“HELLO”应该为“0011101111111”

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

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

    while (!infile.eof()) 
    { 
     getline (infile,English); 
    } 
    infile.close(); 
    cout<<endl; 
    cout<<"This is the text in the file:"<<endl<<endl; 
    cout<<English<<endl<<endl; 

    ofstream codefile("codefile.txt"); 
    ofstream outfile ("compressed.txt"); 
    ifstream codefile_input("codefile.txt"); 
    char ch; 
    string st; 

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

对于“The_Quick_brown_fox_jumps_over_the_lazy_dog”的输入字符串,则输出字符串为011100110,但它应该是长于!

output image

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

+0

你是否尝试在调试器中逐句通过你的代码? –

+1

在'codefile.txt'中找到第一个字符的编码值,写出来并且现在必须找到第二个字符的编码值之后,您认为会发生什么?你的'codefile_input'仍然在文件的中间,在某个地方,它不会奇迹般地回到文件的开头,而是单独搜索第二个字符的编码值。 –

+0

+ Sam所以我怎样才能让codefile_input回到文件的开头? –

回答

0

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

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::明确的代码,我加的)。

相关问题