2016-11-14 3 views
-3

ファイルに格納された文字列をコードテーブルの次の文字列(エンコード)にプログラムで変換したい。バイナリコードの文字列はファイルに移動し、後で文字列に戻すことができます(デコード)。コードテーブルのコードは、ハフマンアルゴリズムを使用して生成され、コードテーブルはファイルに格納されます。カスタムコードテーブルを指定して文字列をエンコードする

E 110 
H 001 
L 11 
O 111 

エンコーディング「HELLO」「0011101111111」

マイC++コードとして出力することができないようすべきである。例えば、文字及びその対応するコードはこのように離間単一であるコードテーブルを以下により

エンコードされた文字列を完成させます。ここに私のコードは次のとおりです。「The_Quick_brown_fox_jumps_over_the_lazy_dog」の入力文字列の場合

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; 
} 

、出力文字列は011100110ですが、それはそれよりも長くする必要があります!

output image

助けてください!私が逃したものはありますか? (私のC++コードに構文エラーがないNB)

+0

デバッガでコードをステップ実行しようとしましたか? –

+1

最初の文字の符号化された値を 'codefile.txt'で見つけてそれを書き出した後、2番目の文字の符号化された値を見つけなければならないと思いますか?あなたの 'codefile_input'はまだファイルの途中にあります。どこかで、魔法のようにファイルの先頭に戻って2番目の文字のエンコードされた値をすべて検索しません。 –

+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の状態になってしまい、iが増加し、English.length()に等しい値に達することのないコードパスが存在しないため、for (int i=0; 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; 
     } 
    } 

注意、あなたはstd::mapを使用する#include <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を開くことができるかどうかを確認し、できない場合は終了しますが、他のファイルを開くことができるかどうかはチェックしません。 Why is “using namespace std” considered bad practice?を読ん考慮無関係なノート#2で


、(あなたは私が私が追加した、コード内で明示的にstd::を使用して参照理由です)。

関連する問題