2016-11-14 9 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

Пожалуйста, помогите! Я что-то пропустил? (пь мой C++ код не имеет синтаксических ошибок)

+0

Вы пробовали выполнить свой код в отладчике? –

+1

Как вы думаете, что произойдет после того, как вы найдете кодированное значение первого символа в 'codefile.txt', выпишите его, и теперь вам нужно найти кодированное значение второго символа? Ваш 'codefile_input' все еще находится в середине файла, где-то он не собирается волшебно возвращаться к началу файла, чтобы искать кодированное значение второго символа, само по себе. –

+0

+ Сэм так как я могу сделать 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:: явно в коде, который я добавил).

 Смежные вопросы

  • Нет связанных вопросов^_^