0

I have designed for Huffman tree convert binary code with shorter bin code. In main if you call a Binary tree.init(q), then the tree would come out with key: frequency and value: bin code. The problem is converting const char* with char*. I've looked at some codes, and here I converted it by using strdup. Sometimes works fine but sometimes doesn't work. so I checked out the parameter for the function. Is there wrong in calling strdup or maybe others?

#pragma once
#include <stdio.h>
#include <queue>
#include <iostream>
#include "pch.h"
#include <string.h>
#include <string>
#define _CRT_SECURE_NO_WARNINGS

//this is a header file

using namespace std;


class Node
{
public:

     
    //key : frequency, value : code
    int f;
    char* code;
    Node* left;
    Node* right;



    int getFrequency()
    {
        return f;
    }

    char* getCode()
    {
        return code;
    }

    void init(int frequency, char* codestring)
    {
        f = frequency;
        code = codestring;

    }

    Node* getLeft() {
        return left;
    }

    Node* getRight()
    {
        return right;
    }

    void setLeft(Node* L)
    {
        left = L;
    }

    void setRight(Node* R)
    {
        right = R;
    }

    void setFrequency(int frequency)
    {
        f = frequency;
    }

    void setCode(char* string)
    {
        code = string;
    }

};


class BinaryTree
{
public:
    typedef priority_queue<int, vector<int>, greater<int>> pq;
    pq q;
    Node* proot;
    int sizeofqueue;
    void init(pq PriorityQueue)
    {
        q = PriorityQueue;
        sizeofqueue = q.size();

        N = 0;

        int comparetimes = q.size() - 1;
        for (int i = 0; i < comparetimes; i++)
        {
            if (i == 0)
            {
                put_first_two_nodes();
            }

            else
            {
                if (proot->getFrequency() <= q.top())
                {
                    put_right_node();
                }

                else if (proot->getFrequency() > q.top())
                {
                    put_left_node();
                }

                q.pop();
            }

        }

    }

    void put_first_two_nodes()
    {
        Node* pleft = new Node();
        (*pleft).setFrequency(q.top());
        (*pleft).setCode("0");
        q.pop();

        Node* pright = new Node();
        (*pright).setFrequency(q.top());
        (*pright).setCode("1");
        put(pleft, pright);
        q.pop();
    }

    void put_right_node()
    {
        Node* pright = new Node();
        pright->setFrequency(q.top());
        pright->setCode("1");
        put(proot, pright);

        appendcode(0);
    }
    void appendcode(int prefix)
    {
        string pre;
        if (prefix == 1) pre = "1";

        else pre = "0";
        Node* targetNode = proot->getRight();
        char* rcode = targetNode->getRight()->getCode();
        char* lcode = targetNode->getLeft()->getCode();

        string lefts = pre;
        string rights = pre;

        lefts.append(lcode);
        rights.append(rcode);

        char* leftstring = strdup(lefts.c_str());
        char* rightstring = strdup(rights.c_str());

        targetNode->getLeft()->setCode(leftstring);
        targetNode->getRight()->setCode(rightstring);

        free(leftstring);
        free(rightstring);
    }
    void put_left_node()
    {
        Node* pleft = new Node();
        pleft->setFrequency(q.top());
        pleft->setCode("0");
        put(pleft, proot);

        appendcode(1);
        
    }

    char* get(int k)
    {
        return getItem(*proot, k);
    }
    char* getItem(Node root, int k)
    {
        //if there's no node
        if (&root == nullptr) return "";

        //if f or root > k, search left sibling
        if (root.getFrequency() > k) return  getItem(*(root.getLeft()), k);

        //else, search right sibling
        else if (root.getFrequency() < k) return getItem(*(root.getRight()), k);

        //get it
        else return root.getCode();
    }

    

    void put(Node* left, Node* right)
    {
        put_item(left,right);
    }

    void put_item(Node* left, Node* right)
    {
        //make new node that has sibling with left and right
        Node* newnode = new Node();
        newnode->setLeft(left);
        newnode->setRight(right);

        //exchange the new node and root without losing data
        Node* temp;

        temp = proot;
        proot = newnode;
        newnode = temp;

        //proot's frequency : left f + right f
        (*proot).setFrequency((*left).getFrequency() + (*right).getFrequency());
        
    }

    void printpost()
    {
        postorder(proot);
    }
    void postorder(Node* root)
    {
        if (root != nullptr)
        {
            if (root->getLeft() != nullptr) postorder(root->getLeft());

            if (root->getRight() != nullptr) postorder(root->getRight());

            printf("%d : %s ",root->getFrequency(), root->getCode());
        }

        

    }

private:

    int N;
    Node root;
};


  • Please provide a [mre] –  Nov 10 '20 at 08:37
  • 2
    You should not use `string` as a variable name, especially if you have `#include ` and `using namespace std;`. Why do you use `char *` and `const char *` at all? You have `string`. – mch Nov 10 '20 at 08:37
  • String literals has `const char*` type. You can't assign `const char*` to `char*` because `const` loses sense. Listen to @mch, use `string` –  Nov 10 '20 at 08:37
  • When you get this kind of error (cannot convert const char* to char*) it's almost never a sign that you need to do that conversion. It's usually a sign that your code is bugged or badly designed. So stop looking for a way to convert and start thinking about how you can avoid the need to do this conversion. In this case I agree with everyone else, use `std::string`. Just replace `char* code;` with `std::string code;` in your `Node` class, and then follow that change through the rest of the code. Much easier than what you are doing now. – john Nov 10 '20 at 08:53
  • okay, I will try it. It would be much better than now. –  Nov 10 '20 at 09:03
  • @EOF -- the type of a string literal is not `const char*`. It is array of const `char`. Like all arrays, they decay into a pointer to the first member if you breathe on them. – Pete Becker Nov 10 '20 at 14:17
  • @PeteBecker yeah. I know. Type of `"abc"` is `const char[4]`. These are just details that do not play a special role in this case. –  Nov 10 '20 at 14:21
  • @EOF -- details matter. Sloppy habits persist, and end up causing sloppy code. – Pete Becker Nov 10 '20 at 14:23
  • see [Why is “using namespace std;” considered bad practice?](https://stackoverflow.com/q/1452721/995714). And `#include "pch.h"` must be at the **beginning** of the cpp files, not in the middle of a .h file – phuclv Nov 11 '20 at 13:39

1 Answers1

0

You shouldn't use const char* and char* at all in (unless when sometimes dealing with legacy or foreign interfaces).

Switch up your code to use eg. std::string or std::string_view () instead (string_view requires a bit more understanding to handle correctly and is const so to speak - so I would stick to string off the bat). Pass std::string by reference or by const reference where neccesary. The overhead of std::string is for most programs negliable.

darune
  • 10,480
  • 2
  • 24
  • 62