The code is about Huffman code.
I typed in "6 a 16 b 5 c 12 d 17 e 10 f 25", to fill in the priority_queue and the program exited without an error.
The priority queue is used to set up a binary search tree for decoding.
I made a function storeBinayNumber() to store the code for each character into an unordered map
called HuffmanCode , which is used for encoding;
and two function encocde() and decode() to encode or decode the string that will be later typed in .
What might be the problem ?
#include <iostream>
#include <queue>
#include <unordered_map>
#include <vector>
using namespace std;
class Node
{
public:
char ch = '\0';
int freq = 0;
Node *left;
Node *right;
};
void storeBinaryNumber(Node *root, unordered_map<char, string> &HuffmanCode, string str = '\0')
{
if (root = nullptr)
return;
if (!root->left && !root->right)
HuffmanCode[root->ch] = str;
storeBinaryNumber(root->left, HuffmanCode, str + "0");
storeBinaryNumber(root->right, HuffmanCode, str + "1");
}
void decode(Node *root, Node *current, string str, int index = 0)
{
if (index > str.length() - 1)
{
if (current == root)
{
cout << "Decoding suceeded" << endl;
return;
}
else
cout << "Invalid code" << endl;
return;
}
if (!current->left && !current->right)
{
cout << current->ch;
decode(root, root, str, index + 1);
}
else if (str[index] == '0')
{
decode(root, current->left, str, index + 1);
}
else if (str[index] == '1')
{
decode(root, current->right, str, index + 1);
}
}
void encode(string str, unordered_map<char, string> HuffmanCode)
{
for (int i = 0; i < str.length(); i++)
{
cout << HuffmanCode[str[i]];
}
}
int main()
{
int num;
cin >> num; //6 a 16 b 5 c 12 d 17 e 10 f 25
auto compare = [](Node *a, Node *b) //lambda expression
{ return a->freq > b->freq; };
priority_queue<Node *, vector<Node *>, decltype(compare)> q(compare);
unordered_map<char, string> HuffmanCode;
char character;
int frequency;
for (int i = 1; i <= num; i++)
{
cin >> character >> frequency;
Node *node = new Node;
node->ch = character;
node->freq = frequency;
node->left = nullptr;
node->right = nullptr;
q.push(node);
}
Node *root;
while (q.size() > 1)
{
Node *A = q.top();
q.pop();
Node *B = q.top();
q.pop();
Node *C = new Node;
C->left = A;
C->right = B;
C->freq = A->freq + B->freq;
if (q.empty())
root = C;
q.push(C);
}
storeBinaryNumber(root, HuffmanCode);
int en_or_de;
string input;
cout << "press 1 to encode , press 2 to decode." << endl;
cin >> en_or_de;
cout << "input: " << endl;
cin >> input;
if (en_or_de == 1)
{
encode(input, HuffmanCode);
}
else
decode(root, root, input);
system("pause");
return 0;
}
The code have several bugs:
Assign char type to string won't compile on my compiler
void storeBinaryNumber(Node *root, unordered_map<char, string> &HuffmanCode, string str = '\0')
The comparison should use ==, this seems to be a typo.
if (root = nullptr)
And the Node type missed destructor, which needs to a memory leak. After my fix the code seems to work. But it may still have logic bugs.
#include <iostream>
#include <queue>
#include <unordered_map>
#include <vector>
using namespace std;
class Node {
public:
char ch = '\0';
int freq = 0;
~Node() {
delete left;
delete right;
}
Node *left;
Node *right;
};
void storeBinaryNumber(Node *root, unordered_map<char, string> &HuffmanCode,
string str = "") {
if (root == nullptr) return;
if (!root->left && !root->right) HuffmanCode[root->ch] = str;
storeBinaryNumber(root->left, HuffmanCode, str + "0");
storeBinaryNumber(root->right, HuffmanCode, str + "1");
}
void decode(Node *root, Node *current, string str, int index = 0) {
if (index > str.length() - 1) {
if (current == root) {
cout << "Decoding suceeded" << endl;
return;
}
else
cout << "Invalid code" << endl;
return;
}
if (!current->left && !current->right) {
cout << current->ch;
decode(root, root, str, index + 1);
}
else if (str[index] == '0') {
decode(root, current->left, str, index + 1);
}
else if (str[index] == '1') {
decode(root, current->right, str, index + 1);
}
}
void encode(string str, unordered_map<char, string> HuffmanCode) {
for (int i = 0; i < str.length(); i++) {
cout << HuffmanCode[str[i]];
}
std::cout << std::endl;
}
int main() {
int num;
cin >> num; // 6 a 16 b 5 c 12 d 17 e 10 f 25
auto compare = [](Node *a, Node *b) // lambda expression
{ return a->freq > b->freq; };
priority_queue<Node *, vector<Node *>, decltype(compare)> q(compare);
unordered_map<char, string> HuffmanCode;
char character;
int frequency;
for (int i = 1; i <= num; i++) {
cin >> character >> frequency;
Node *node = new Node;
node->ch = character;
node->freq = frequency;
node->left = nullptr;
node->right = nullptr;
q.push(node);
}
Node *root;
while (q.size() > 1) {
Node *A = q.top();
q.pop();
Node *B = q.top();
q.pop();
Node *C = new Node;
C->left = A;
C->right = B;
C->freq = A->freq + B->freq;
if (q.empty()) root = C;
q.push(C);
}
storeBinaryNumber(root, HuffmanCode);
int en_or_de;
string input;
cout << "press 1 to encode , press 2 to decode." << endl;
cin >> en_or_de;
cout << "input: " << endl;
cin >> input;
if (en_or_de == 1) {
encode(input, HuffmanCode);
}
else
decode(root, root, input);
delete root;
// system("pause");
return 0;
}
Related
I have two problems where I'm having a hard time to understand.
1) I'm having a hard time to understand how to pass my L1 doublyLinkedList into an array so that I can save each list of numbers my txt file reads
2) If I have an uneven negative number my break_into_nodes() method is reading an error as stoi is creating 1 node for a negative sign, how would I create an if statement to continue to breaking it into a node
#include "stdafx.h"
#include <iostream>
#include <iterator>
#include <fstream>
#include <string>
#include <cstdlib>
#include "ArgumentManager.h"
using namespace std;
struct Node
{
long long value;
Node *next, *prev;
Node(long long y)
{
value = y;
next = prev = NULL;
}
};
class doubleLinkedList
{
Node *back;
public:
Node *front;
doubleLinkedList() { front = NULL; back = NULL; }
~doubleLinkedList() { destroyList(); }
doubleLinkedList(const string& num, int digitsPerNode) {
appendNodeFront(stoi(num, 0, 10));
}
void appendNodeFront(long int x);
void dispNodesForward(int digits);
void destroyList();
void clean();
};
void doubleLinkedList::clean()
{
destroyList();
}
void doubleLinkedList::appendNodeFront(long int x)
{
Node *n = new Node(x);
if (front == NULL)
{
front = n;
//back = n;
}
else
{
front->prev = n;
n->next = front;
front = n;
}
}
void doubleLinkedList::dispNodesForward(int digits)
{
Node *temp = front;
int temp_val;
if (temp != NULL)
{
/* First node does not get Zero padding */
temp_val = (int)temp->value;
printf("%d", temp_val);
temp = temp->next;
while (temp != NULL)
{
temp_val = (int)temp->value;
printf("%0*d", digits, temp_val);
temp = temp->next;
}
}
}
void doubleLinkedList::destroyList()
{
Node *T = back;
while (T != NULL)
{
Node *T2 = T;
T = T->prev;
delete T2;
}
front = NULL;
back = NULL;
}
void break_into_nodes(doubleLinkedList *list, string number, int digits) {
string node_value;
int num_index, num_iterations;
int i, j;
num_index = number.length();
if (num_index < digits)
{
node_value = number;
list->appendNodeFront(stoi(node_value));
}
else {
/* adjust for incomplete nodes */
if ((number.length() % digits) == 0)
num_iterations = (number.length() / digits);
else
num_iterations = (number.length() / digits) + 1;
for (j = 0; j < num_iterations; j++) {
node_value.clear();
for (i = 0; i < digits; i++) {
num_index--;
if (num_index < 0)
break;
node_value = node_value.insert(0, number.substr(num_index, 1));
}
list->appendNodeFront(stoi(node_value));
}
}
}
// Driver program
int main(int argc, char* argv[]) {
doubleLinkedList l1;
if (argc < 2) {
cerr << "Usage: infinitearithmetic \"input=xyz.txt;digitsPerNode= <number>\"\n";
}
ArgumentManager am(argc, argv);
string filename = am.get("input");
/* Digits per Node ar from 1 to 8 */
int digitsPerNode = stoi(am.get("digitsPerNode"));
ifstream ifs(filename.c_str());
string line;
string num1;
int i = 0;
while (!ifs.eof())
{
getline(ifs, line);
//cout << "" << line << endl;
num1 = line;
break_into_nodes(&l1, num1, digitsPerNode);
l1.dispNodesForward(digitsPerNode);
cout << endl;
l1.clean();
i++;
}
return 0;
}
I'm trying to create a program that gets string input from a text file, inserting the content into a list, word by word. I also have to calculate the numbers of the duplicates. My program works fine for the small input text file (1 line of string). But whenever I feed it with a bigger text file, it crashes. Any help will be great.
Here is my code:
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
class Bag
{
private:
struct BagNode
{
string dataValue;
int dataCount;
BagNode *next;
BagNode(string);
};
BagNode *root;
string removePunctuations(string);
string toLower(string);
void insertData(string);
public:
Bag();
void procesFile(string, string);
void removeData(string);
void traverse();
};
Bag::BagNode::BagNode(string _data)
{
dataValue.assign(_data);
dataCount=1;
next = NULL;
}
Bag::Bag()
{
root = NULL;
}
void Bag::procesFile(string ifile, string ofile)
{
ifstream infile;
infile.open(ifile.c_str());
if (!infile.good())
{
cout<<"Input file not opening."<<endl;
return;
}
string line;
while(getline(infile,line))
{
stringstream lineStream(line);
string token = "";
while(lineStream >> token)
{
insertData(removePunctuations(token));
}
}
infile.close();
traverse();
cout<< endl <<"File processed successfully." << endl;
}
string Bag::removePunctuations(string data)
{
int length = data.size();
for(int i = 0; i < length; i++)
{
if(ispunct(data[i]))
{
data.erase(i--, 1);
length = data.size();
}
}
return data;
}
string Bag::toLower(string data)
{
for(int i = 0; data[i]; i++){
data[i] = tolower(data[i]);
}
return data;
}
void Bag::insertData(string data)
{
BagNode *n = new BagNode(data);
if (root == NULL)
{
root = n;
return;
}
BagNode *temp = root;
BagNode *prev = NULL;
string tdata;
data.assign(toLower(data));
while(temp != NULL)
{
tdata.assign(temp->dataValue);
tdata.assign(toLower(tdata));
if (tdata.compare(data) == 0)
{
temp->dataCount++;
return;
}
else
{
if (data.compare(tdata) < 0)
{
if (temp == root)
{
n->next = temp;
root = n;
return;
}
else
{
n->next = temp;
prev->next = n;
return;
}
}
}
prev = temp;
temp = temp->next;
}
n->next = temp;
prev->next = n;
}
void Bag::removeData(string data)
{
BagNode *temp = root;
BagNode *prev = NULL;
if (root->dataValue.compare(data)==0)
{
if (root->dataCount > 1)
root->dataCount--;
else
{
delete root;
root = NULL;
}
cout<<"Data removed successfully."<<endl;
return;
}
while (temp != NULL)
{
if (temp->dataValue.compare(data)==0)
{
if (temp->dataCount > 1)
temp->dataCount--;
else
{
prev->next = temp->next;
delete temp;
temp = NULL;
}
cout<<"Data removed successfully."<<endl;
return;
}
prev = temp;
temp = temp->next;
}
cout<<"Data not found match."<<endl;
}
void Bag::traverse()
{
if (root == NULL)
{
cout<<"No data."<<endl;
return;
}
BagNode *temp = root;
while(temp != NULL)
{
if (temp->dataCount > 1)
cout << temp -> dataValue << "(" << temp->dataCount << ")" << endl;
else
cout << temp -> dataValue << endl;
temp = temp->next;
}
}
int main(int argc, char *argv[])
{
bool outputConsole = false;
string infile, outfile = "\0";
cout << "Welcome!" << endl;
int option = -1;
do{
if (argc==1 || option == 1)
{
cout << "Enter the input file: ";
cin >> infile;
cout << "Enter the output file: ";
cin >> outfile;
}
else
{
infile.assign(argv[1]);
if (argc == 3)
outfile.assign(argv[2]);
}
Bag b;
b.procesFile(infile,outfile);
//b.traverse();
cout<<endl<<"If you want to input another file press 1 or 2 to quit: ";
cin>>option;
}while (option != 2);
return 0;
}
If ordering of words is not an issue,you should really try and use a hash table instead of a linked list as hash table is suitable for keeping track of duplicates.This will lead to O(1) insert operation (in ideal situation)
I am working on writing a list of children binary tree implementation. In my code I have an array of lists. Each list contains a node followed by its children on the tree. I finished writing the code and everything compiled, but I keep getting a segmentation fault error and I cannot figure out why. I have been attempting to debug and figure out where my code messes up. I know that there is an issue with the FIRST function. It causes a segmentation fault. Also, when I try to print just one of the lists of the array, it prints everything. I have been stuck on this for a very long time now and would like some help. Can anyone offer suggestions as to why the FIRST and PRINT functions are not working? Maybe there is a large error that I just cannot see.
My code is as follows:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <array>
#include <string.h>
using namespace std;
struct node
{
char element;
struct node *next;
}*start;
class list
{
public:
void ADD(char n);
node* CREATE(char n);
void BEGIN(char n);
char FIRST();
char END();
char NEXT(char n);
char PREVIOUS(char n);
int LOCATE(char n);
void EMPTY();
void PRINT();
list()
{
start = NULL;
}
};
char PARENT(const char n, list tree[], int length)
{
int i=0;
list l;
for (i; i<length; i++)
{
l = tree[i];
if (n != l.FIRST())
{
if (l.LOCATE(n)>0)
return l.FIRST();
}
}
}
char LEFTMOST_CHILD(char n, list tree[], int length)
{
int i;
list l;
for (i=0; i<length; i++)
{
l = tree[i];
if (l.FIRST() == n)
return l.NEXT(n);
}
}
char RIGHT_SIBLING(char n, list tree[], int length)
{
int i;
list l;
for (i=0; i<length; i++)
{
l = tree[i];
if(n != l.FIRST())
{
if (l.LOCATE(n) > 0)
{
return l.NEXT(n);
}
}
}
}
char ROOT(list tree[]) //assumes array is in order, root is first item
{
list l;
l = tree[0];
cout << "Assigned tree to l" << endl;
return l.FIRST();
}
void MAKENULL(list tree[], int length)
{
int i;
list l;
for (i=0; i<length; i++)
{
l = tree[i];
l.EMPTY();
}
}
void list::PRINT()
{
struct node *temp;
if (start == NULL)
{
cout << "The list is empty" << endl;
return;
}
temp = start;
cout << "The list is: " << endl;
while (temp != NULL)
{
cout << temp->element << "->" ;
temp = temp->next;
}
cout << "NULL" << endl << endl;
}
void list::EMPTY()
{
struct node *s, *n;
s = start;
while (s != NULL)
{
n = s->next;
free(s);
s = n;
}
start = NULL;
}
int list::LOCATE(char n)
{
int pos = 0;
bool flag = false;
struct node *s;
s = start;
while (s != NULL)
{
pos++;
if (s->element == n)
{
flag == true;
return pos;
}
s = s->next;
}
if (!flag)
return -1;
}
void list::ADD(char n)
{
struct node *temp, *s;
temp = CREATE(n);
s = start;
while (s->next != NULL)
s = s->next;
temp->next = NULL;
s->next = temp;
}
node *list::CREATE(char n)
{
struct node *temp;
temp = new(struct node);
temp->element = n;
temp->next = NULL;
return temp;
}
void list::BEGIN(char n)
{
struct node *temp, *p;
temp = CREATE(n);
if (start == NULL)
{
start = temp;
start->next = NULL;
}
}
char list::FIRST()
{
char n;
struct node *s;
s = start;
cout << "s = start" << endl;
n = s->element;
cout << "n" << endl;
return n;
}
char list::END()
{
struct node *s;
s = start;
int n;
while (s != NULL)
{
n = s->element;
s = s->next;
}
return n;
}
char list::NEXT(char n)
{
char next;
struct node *s;
s = start;
while (s != NULL)
{
if (s->element == n)
break;
s = s->next;
}
s = s->next;
next = s->element;
return next;
}
char list::PREVIOUS(char n)
{
char previous;
struct node *s;
s = start;
while (s != NULL)
{
previous = s->element;
s = s->next;
if (s->element == n)
break;
}
return previous;
}
main()
{
list a,b,c,d,e,f,g,h,i,j,k,l,m,n;
a.BEGIN('A');
b.BEGIN('B');
c.BEGIN('C');
d.BEGIN('D');
e.BEGIN('E');
f.BEGIN('F');
g.BEGIN('G');
h.BEGIN('H');
i.BEGIN('I');
j.BEGIN('J');
k.BEGIN('K');
l.BEGIN('L');
m.BEGIN('M');
n.BEGIN('N');
a.ADD('B');
a.ADD('C');
b.ADD('D');
b.ADD('E');
e.ADD('I');
i.ADD('M');
i.ADD('N');
c.ADD('F');
c.ADD('G');
c.ADD('H');
g.ADD('J');
g.ADD('K');
h.ADD('L');
a.PRINT();
list tree[] = {a,b,c,d,e,f,g,h,i,j,k,l,m,n};
int length = sizeof(tree)/sizeof(char);
char root = ROOT(tree);
cout << "Found root" << endl;
char parent = PARENT('G', tree, length);
cout << "Found Parent" << endl;
char leftChild = LEFTMOST_CHILD('C', tree, length);
cout << "found left child" << endl;
char rightSibling = RIGHT_SIBLING('D', tree, length);
cout << "found right sibling" << endl;
cout << "The root of the tree is: ";
cout << root << endl;
cout << "The parent of G is: ";
cout << parent << endl;
cout << "The leftmost child of C is" ;
cout << leftChild << endl;
cout << "The right sibling of D is: " ;
cout << rightSibling << endl;
}
Any help will be very appreciated. Thanks you!
The fundamental problem is that you have written a lot of code before testing any of it. When you write code, start with something small and simple that works perfectly, add complexity a little at a time, test at every step, and never add to code that doesn't work.
The specific problem (or at least one fatal problem) is here:
struct node
{
char element;
struct node *next;
}*start;
class list
{
public:
//...
list()
{
start = NULL;
}
};
The variable start is a global variable. The class list has no member variables, but uses the global variable. It sets start to NULL every time a list is constructed, and every list messes with the same pointer. The function FIRST dereferences a pointer without checking whether the pointer is NULL, and when it is, you get Undefined Behavior.
It's not entirely clear what you intended, but you seem to misunderstand how variables work in C++.
I am using Visual Studio 2013, running on windows 7 64 bit.
I am trying to display a language different than English. My code is:
#include <iostream>
#include <string>
using namespace std;
typedef char byte;
byte text[] = "текст";
int text_len;
struct Huf {
byte id;
int wh;
Huf *left, *right;
};
struct List {
List *next;
Huf *tree;
};
List *head;
char code[256];
void createList();
void writeList();
void delList(List *);
void addList(Huf *);
Huf *findDels();
void createTree();
void rlrootTree(Huf *, unsigned);
int main()
{
text_len = strlen(text);
createList();
writeList();
createTree();
cout << "writeCodes\n";
rlrootTree(head->tree, 0);
cout << endl;
system("pause");
return 0;
}
void createList()
{
int i;
int ch[256] = { 0 };
for (i = 0; i<text_len; i++) ch[text[i]]++;
List *l;
Huf *h;
head = 0;
for (i = 0; i<255; i++) if (ch[i]>0)
{
h = new Huf;
h->id = i; h->wh = ch[i];
h->left = 0; h->right = 0;
l = new List;
l->tree = h;
l->next = head; head = l;
}
}
void writeList()
{
cout << "writeList\n";
List *l = head;
while (l)
{
cout << (l->tree)->id << " ";
l = l->next;
}
cout << endl;
l = head;
while (l)
{
cout << (l->tree)->wh << " ";
l = l->next;
}
cout << endl;
}
void delList(List *l)
{
List *lp, *lc;
if (l == head) { head = l->next; delete l; }
else
{
lp = head; lc = lp->next;
while (lc != l) { lp = lc; lc = lc->next; }
lp->next = lc->next; delete lc;
}
}
void addList(Huf *h)
{
List *l = new List;
l->tree = h;
l->next = head;
head = l;
}
Huf *findDels()
{
List *l = head, *sm = head;
Huf *h;
while (l)
{
if ((l->tree)->wh < (sm->tree)->wh) sm = l;
l = l->next;
}
h = sm->tree;
delList(sm);
return h;
}
void createTree()
{
Huf *h, *h1, *h2;
while (head->next)
{
h1 = findDels();
h2 = findDels();
h = new Huf;
h->id = ' '; h->wh = h1->wh + h2->wh;
h->left = h1; h->right = h2;
addList(h);
}
}
void rlrootTree(Huf *h, unsigned index)
{
if (h)
{
code[index] = '0';
rlrootTree(h->right, index + 1);
if (h->left == 0)
{
code[index] = '\0';
cout << h->id << "->" << code << " ";
}
code[index] = '1';
rlrootTree(h->left, index + 1);
}
}
I have tried adding <locale> and <windows.h> includes with AnsiToOem() but it doesnt seem to compile - I get character errors.
You are iterating through the text byte by byte. But each letter (grapheme) consists of two code units, that is two bytes.
To make this simple I would store the string as an array of char32_t, because then the whole codepoint (one grapheme) would fit in one element of the array.
If you want to be able to handle absolutely every international "character" you would also have to handle grapheme clusters then you would have have a look at the ICU library or similar.
A dangerously simplified suggestion:
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
typedef char32_t byte;
byte text[] = U"текст";
int text_len;
struct Huf {
byte id;
int wh;
Huf *left, *right;
};
struct List {
List *next;
Huf *tree;
};
List *head;
char code[16000];
void createList();
void writeList();
void delList(List *);
void addList(Huf *);
Huf *findDels();
void createTree();
void rlrootTree(Huf *, unsigned);
unsigned strlen(char32_t* st) {
unsigned len = 0;
while (*(st+len) != 0) ++len;
return len;
}
int main()
{
text_len = strlen(text);
std::cout << "len = " << text_len << std::endl;
createList();
writeList();
createTree();
cout << "writeCodes\n";
rlrootTree(head->tree, 0);
cout << endl;
system("pause");
return 0;
}
void createList()
{
int i;
int ch[16000] = { 0 }; //you really need more here
for (i = 0; i<text_len; i++) ch[text[i]]++;
List *l;
Huf *h;
head = 0;
for (i = 0; i<16000; i++) if (ch[i]>0)
{
h = new Huf;
h->id = i; h->wh = ch[i];
h->left = 0; h->right = 0;
l = new List;
l->tree = h;
l->next = head; head = l;
}
}
void writeList()
{
cout << "writeList\n";
List *l = head;
while (l)
{
cout << (l->tree)->id << " ";
l = l->next;
}
cout << endl;
l = head;
while (l)
{
cout << (l->tree)->wh << " ";
l = l->next;
}
cout << endl;
}
void delList(List *l)
{
List *lp, *lc;
if (l == head) { head = l->next; delete l; }
else
{
lp = head; lc = lp->next;
while (lc != l) { lp = lc; lc = lc->next; }
lp->next = lc->next; delete lc;
}
}
void addList(Huf *h)
{
List *l = new List;
l->tree = h;
l->next = head;
head = l;
}
Huf *findDels()
{
List *l = head, *sm = head;
Huf *h;
while (l)
{
if ((l->tree)->wh < (sm->tree)->wh) sm = l;
l = l->next;
}
h = sm->tree;
delList(sm);
return h;
}
void createTree()
{
Huf *h, *h1, *h2;
while (head->next)
{
h1 = findDels();
h2 = findDels();
h = new Huf;
h->id = ' '; h->wh = h1->wh + h2->wh;
h->left = h1; h->right = h2;
addList(h);
}
}
void rlrootTree(Huf *h, unsigned index)
{
if (h)
{
code[index] = '0';
rlrootTree(h->right, index + 1);
if (h->left == 0)
{
code[index] = '\0';
cout << h->id << "->" << code << " ";
}
code[index] = '1';
rlrootTree(h->left, index + 1);
}
}
I'm using a linked list to implement a concordance program. I am getting the following compiler error when trying to compile the program with g++:
concordancetest.cpp: In function 'void build_list(std::ifstream&, char*)':
concordancetest.cpp:65: error: no matching function for call to ‘Concordance::insert(char*&, int&)'
concordance.h:22: note: candidates are: void Concordance::insert(char (&)[9], int&)
Below is the code I have written:
Header File:
#ifndef CONCORDANCE_H
#define CONCORDANCE_H
#include <iostream>
#include <cstdlib>
const int MAX = 8;
class Concordance
{
public:
//typedef
typedef char Word[MAX+1];
//constructor
Concordance();
//destructor
~Concordance();
//modification member functions
void insert(Word& word, int& n);
void remove(Word& word);
int get_count(Word& word);
//constant member functions
int length() const;
//friend member functions
friend std::ostream& operator << (std::ostream& out_s, Concordance& c);
private:
struct Node
{
Word wd;
int count;
Node *next;
};
Node *first;
Node* get_node(Word& word, int& count, Node* link);
};
#endif
Implementation Code:
//class definition
#include "concordance.h"
#include <iostream>
#include <cstring>
#include <iomanip>
using namespace std;
Concordance::Concordance()
{
first = NULL;
}
Concordance::~Concordance()
{
Node *temp;
while(first != NULL)
{
temp = first;
first = first -> next;
delete temp;
}
}
void Concordance::insert(Word& word, int& n)
{
Node *prev;
if(first == NULL || strcmp(first -> wd, word) > 0)
first = get_node(word, n, first);
else
{
prev = first;
while(prev -> next != NULL && strcmp(prev -> next -> wd, word) > 0)
prev = prev -> next;
prev -> next = get_node(word, n, prev -> next);
}
}
void Concordance::remove(Word& word)
{
Node *prev, *temp;
prev = temp;
if(prev -> wd == word)
{
first = first -> next;
delete prev;
}
else
{
while(strcmp(prev -> next -> wd, word) > 0)
prev = prev -> next;
temp = prev -> next;
prev -> next = temp -> next;
delete temp;
}
}
int Concordance::get_count(Word& word)
{
while(strcmp(first -> wd, word) != 0)
first = first -> next;
return first -> count;
}
int Concordance::length() const
{
Node *cursor;
int len;
len = 0;
for(cursor = first; cursor != NULL; cursor = cursor -> next )
len++;
return len;
}
Concordance::Node* Concordance::get_node (Word& word, int& count, Node* link)
{
Node *temp;
temp = new Node;
strcpy(temp-> wd, word);
temp-> next = link;
temp -> count = count+1;
return temp;
}
ostream& operator << (ostream& out_s, Concordance& c)
{
Concordance::Node *cursor;
out_s << "Word" << setw(10) << " " << "Count" << endl;
out_s << "--------------------" << endl;
for(cursor = c.first; cursor != NULL && cursor->next != NULL; cursor = cursor-> next )
out_s << cursor-> wd << setw(10) << " " << cursor -> count << endl;
if(cursor != NULL)
out_s << cursor-> wd << setw(10) << " " << cursor -> count << endl;
out_s << "--------------------" << endl;
return out_s;
}
Test Program:
#include <iostream>
#include <iomanip>
#include <fstream>
#include <cstring>
#include "concordance.h"
using namespace std;
void read_word(ifstream& in_file, char array[]);
void build_list(ifstream& in_file, char array[]);
int main()
{
char file_name[100];
ifstream in_file;
char array[MAX+1];
cout << "Enter a file name: ";
cin >> file_name;
in_file.open(file_name);
build_list(in_file, array);
in_file.close();
return EXIT_SUCCESS;
}
void read_word(ifstream& in_file, char array[])
{
char ch;
int i = 0;
in_file.get(ch);
while(isalpha(ch) && !isspace(ch))
{
if(i > MAX-1)
{
while(!isspace(ch))
in_file.get(ch);
break;
}
ch = tolower(ch);
array[i] = ch;
i++;
in_file.get(ch);
}
for(int j = 0; j < i; j++)
cout << array[j];
cout << endl;
}
void build_list(ifstream& in_file, char array[])
{
Concordance c;
int count = 0;
while(!in_file.eof())
{
read_word(in_file, array);
c.insert(array, count);
}
cout << c;
}
The type of char array[] is char *, so when it looks for a matching function, none is found. You can fix this by using typedef char* Word; and enforcing your max length inside the functions that require it.