0
votes

I have a program that produces a Huffman tree based on ASCII character frequency read in a text input file. The Huffman codes are stored in a string array of 256 elements, empty string if the character is not read. This program also encodes and compresses an output file.

I am now trying to decompress and decode my current output file which is opened as an input file and a new output file is to have the decoded message identical to the original text input file.

My thought process for this part of the assignment is to recreate a tree with huffman codes and then while reading 8 bits at a time, traverse through tree until I reach a leaf node where I will have updated an empty string(string answer) and then output it to my output file.

My problem: After writing this function I see that only one character in between all of the other characters of my original input file gets output repeatedly. I am confused as to why this is the case because I am expecting the output file to be identical to the original input file.

Any guidance or solution to this problem is appreciated.

(For encodedOutput function, fileName is the input file parameter, fileName2 is the output file parameter)

(For decodeOutput function, fileName2 is the input file parameter, fileName 3 is output file parameter)

code[256] is a parameter for both of these functions and holds the Huffman code for each unique character read in the original input file, for example, the character 'H' being read in the input file may have a code of "111" stored in the code array for code[72] at the time it is being passed to the functions.

freq[256] holds the frequency of each ascii character read or holds 0 if it is not in original input file.

void encodeOutput(const string & fileName, const string & fileName2, string code[256]) {
    ifstream ifile;
    ifile.open(fileName, ios::binary);
    if (!ifile)
    {
        die("Can't read again");
    }
    ofstream ofile;
    ofile.open(fileName2, ios::binary);
    if (!ofile) {
        die("Can't open encoding output file");
    }
    int read;
    read = ifile.get();
    char buffer = 0, bit_count = 0;
    while (read != -1) {
        for (unsigned b = 0; b < code[read].size(); b++) { // loop through bits (code[read] outputs huffman code)
            buffer <<= 1;
            buffer |= code[read][b] != '0';
            bit_count++;
            if (bit_count == 8) {
                ofile << buffer;
                buffer = 0;
                bit_count = 0;
            }
        }
        read = ifile.get();
    }

    if (bit_count != 0)
        ofile << (buffer << (8 - bit_count));

    ifile.close();
    ofile.close();
}
// Work in progress
void decodeOutput(const string & fileName2, const string & fileName3, string code[256], const unsigned long long freq[256]) {
    ifstream ifile;
    ifile.open(fileName2, ios::binary);
    if (!ifile)
    {
        die("Can't read again");
    }
    ofstream ofile;
    ofile.open(fileName3, ios::binary);
    if (!ofile) {
        die("Can't open encoding output file");
    }
    priority_queue < node > q;
    for (unsigned i = 0; i < 256; i++) {
        if (freq[i] == 0) {
            code[i] = "";
        }
    }

    for (unsigned i = 0; i < 256; i++)
        if (freq[i])
            q.push(node(unsigned(i), freq[i]));

    if (q.size() < 1) {
        die("no data");
    }

    while (q.size() > 1) {
        node *child0 = new node(q.top());
        q.pop();
        node *child1 = new node(q.top());
        q.pop();
        q.push(node(child0, child1));
    } // created the tree
    string answer = "";
    const node * temp = &q.top(); // root 
    for (int c; (c = ifile.get()) != EOF;) {
        for (unsigned p = 8; p--;) { //reading 8 bits at a time 
            if ((c >> p & 1) == '0') { // if bit is a 0
                temp = temp->child0; // go left
            }
            else { // if bit is a 1
                temp = temp->child1; // go right
            }
            if (temp->child0 == NULL && temp->child1 == NULL) // leaf node
            {
                ans += temp->value;
                temp = &q.top();
            }
            ofile << ans;
        }
    }
}
1
If you haven't done it before, now is definitely the time to learn how to debug your programs. - Some programmer dude
If that doesn't get you anywhere, reducing this to a minimal complete verifiable example will improve your chances of getting an answer. At the moment you have external file dependencies, and you're essentially asking for a review. Something self-contained that reproduces the problem will allow other people to actually run it themselves, and really narrows down the scope. - Useless
previous question for some context stackoverflow.com/questions/55116567/… - Alan Birtles
Have you checked your input is correct? Try examining the file in a hex editor and decode the first few characters by hand, do you get the expected result? After you've done this see the above comments about debugging - Alan Birtles
One suggestion for making your code easier to debug, easier to unit test, and better for providing MCVEs: seperate file I/O from the Huffman encode/decode functions. If they just operate on istream/ostreams, you can easily run them with canned data in a stringstream. - Useless

1 Answers

3
votes
(c >> p & 1) == '0'

Will only return true when (c >> p & 1) equals 48, so your if statement will always follow the else branch. The correct code is:

(c >> p & 1) == 0