2016-11-14 88 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::明確的代碼,我加的)。

相關問題