Jun 1, 2016 at 3:02am UTC
I'm learning Hashtables and I have this problem where there's garbage when I display my data. I ran the debugger and when it adds to the table it has all the right information but when it displays it has garbage. If anyone can help me if would be much appreciated.
#ifndef STOCK_H
#define STOCK_H
#include <iostream>
#include <cstring>
#include <fstream>
#include <cstdlib>
#include <cstdio>
#include <iomanip>
using namespace std;
const int MAX_CHAR = 100;
const int tableSize = 15;
class stock{
public:
stock();
~stock();
void getSymbol(char tickerSymbol[]) const;
void setSymbol(const char tickerSymbol[]);
void getfundName(char fundName[]) const;
void setfundName(const char fundName[]);
float getnetAssetVal() const;
void setnetAssetVal(float netAssetVal);
void getDate(char date[]) const;
void setDate(const char date[]);
float getDateReturn() const;
void setDateReturn(float dateReturn);
friend ostream& operator<< (ostream& out, const stock& aStock);
private:
char * tickerSymbol;
char * fundName;
float netAssetVal;
char * date;
float dateReturn;
};
#endif
--------------------------------------------------------------------------------
#include "stock.h"
stock::stock()
{
tickerSymbol = NULL;
fundName = NULL;
netAssetVal = 0;
date = NULL;
dateReturn = 0;
}
stock::~stock()
{
if(this->tickerSymbol)
delete[] tickerSymbol;
if(this->fundName)
delete[] fundName;
if(this->date)
delete[] date;
}
void stock::getSymbol(char * tickerSymbol) const
strcpy(tickerSymbol, this->tickerSymbol);
}
void stock::setSymbol(const char * tickerSymbol)
{
if(this->tickerSymbol == tickerSymbol)
return;
if(this->tickerSymbol)
{
delete[] this->tickerSymbol;
}
this->tickerSymbol = new char[strlen(tickerSymbol) + 1];
strcpy(this->tickerSymbol, tickerSymbol);
}
void stock::getfundName(char * fundName) const
{
strcpy(fundName, this->fundName);
}
void stock::setfundName(const char * fundName)
{
if(this->fundName == fundName)
return;
if(this->fundName)
{
delete[] this->fundName;
}
this->fundName = new char[strlen(fundName) + 1];
strcpy(this->fundName, fundName);
}
float stock::getnetAssetVal() const
{
return netAssetVal;
}
void stock::setnetAssetVal(float netAssetVal)
{
this->netAssetVal = netAssetVal;
}
void stock::getDate(char * date) const
{
strcpy(date, this->date);
}
void stock::setDate(const char * date)
{
if(this->date == date)
return;
if(this->date)
{
delete[] this->date;
}
this->date = new char[strlen(date) + 1];
strcpy(this->date, date);
}
float stock::getDateReturn() const
{
return dateReturn;
}
void stock::setDateReturn(float dateReturn)
{
this->dateReturn = dateReturn;
}
ostream& operator<< (ostream& out, const stock& aStock)
{
out << setw(10) << aStock.tickerSymbol << endl
<< setw(10) << aStock.fundName << endl
<< setw(10) << aStock.netAssetVal << endl
<< setw(10) << aStock.date << endl
<< setw(10) << aStock.dateReturn << endl;
return out;
}
--------------------------------------------------------------------------------
#ifndef HASH_H
#define HASH_H
#include "stock.h"
class hashTable{
public:
hashTable();
int Hash(char const * key);
void init();
void loadData(char fileName[]);
void add(const stock& aStock);
bool remove(char * tickerSymbol);
bool modify(char * tickerSymbol, float newNetAssetVal, char * newDate, float newDateReturn);
bool retrieve(char * tickerSymbol, stock& aStock);
void display();
void monitor(); //display length for individual chain
private:
struct Node
{
stock data;
Node * next;
Node(const stock& aStock)
{
data = aStock;
next = NULL;
}
};
Node * table[tableSize];
int currCapacity;
int size;
};
#endif
--------------------------------------------------------------------------------
#include "hash.h"
hashTable::hashTable()
{
init();
}
void hashTable::init()
{
for (int i = 0; i < tableSize; i++)
{
table[i] = NULL;
}
size = 0;
}
void hashTable::loadData(char fileName[])
{
ifstream in;
float netAssetVal;
float dateReturn;
stock currStock;
in.open(fileName);
if (!in)
{
cerr << "Fail to open " << fileName << " for input!" << endl;
exit(1);
}
char* tickerSymbol = new char[MAX_CHAR];
char* fundName = new char[MAX_CHAR];
char* date = new char[MAX_CHAR];
in.get(tickerSymbol, MAX_CHAR, ';');
while (!in.eof())
{
in.ignore(MAX_CHAR, ';');
in.get(fundName, MAX_CHAR, ';');
in.ignore(MAX_CHAR, ';');
in >> netAssetVal;
in.ignore(MAX_CHAR, ';');
in.get(date, MAX_CHAR, ';');
in.ignore(MAX_CHAR, ';');
in >> dateReturn;
in.ignore(MAX_CHAR, '\n');
currStock.setSymbol(tickerSymbol);
currStock.setfundName(fundName);
currStock.setnetAssetVal(netAssetVal);
currStock.setDate(date);
currStock.setDateReturn(dateReturn);
this->add(currStock);
if(tickerSymbol)
{
tickerSymbol = new char[MAX_CHAR];
}
if(fundName)
{
fundName = new char[MAX_CHAR];
}
if(date)
{
date = new char[MAX_CHAR];
}
in.get(tickerSymbol, MAX_CHAR, ';');
}
in.close();
}
int hashTable::Hash(char const * key)
{
int index;
index = strlen(key);
return index;
}
void hashTable::add(const stock& aStock)
{
char symbol[MAX_CHAR];
aStock.getSymbol(symbol);
int pos = Hash(symbol);
Node * newNode = new Node(aStock);
newNode->next = table[pos];
table[pos] = newNode;
size++;
}
void hashTable::display()
{
Node * curr;
for (int i = 0; i < tableSize; i++)
{
cout << "Chain #" << i << ":" << endl;
for (curr = table[i]; curr; curr = curr->next)
{
cout << curr->data << endl;
}
cout << endl;
}
}
--------------------------------------------------------------------------------
my main function just calls the loadData function then the display function. It loads the data from my ticker.txt file which contains:
EGLRX;Alpine international real estate;30.39;Apr 20, 2006;12.85
DOW;Dow Jones Industrial Average;145.46;May 26, 2016;0.82
Nasda;NASDAQ Composite;33.84;May 26, 2016;0.70
--------------------------------------------------------------------------------
And it displays this:
Chain #0:
Chain #1:
Chain #2:
Chain #3:
145.46
▒▒▒
0.82
Chain #4:
Chain #5:
33.84
▒▒▒
0.7
30.39
▒▒▒
12.85
Chain #6:
Chain #7:
Chain #8:
Chain #9:
Chain #10:
Chain #11:
Chain #12:
Chain #13:
Chain #14:
did not find
Jun 1, 2016 at 4:32am UTC
Your code is incompled and not formated.
Make a dump of the data after read
currStock.setSymbol(tickerSymbol);
currStock.setfundName(fundName);
currStock.setnetAssetVal(netAssetVal);
currStock.setDate(date);
currStock.setDateReturn(dateReturn);
cout << "tickerSymbol:" << tickerSymbol << endl;
etc.
Why do you use "char* tickerSymbol = new char[MAX_CHAR];" and not "string"?
and why do you allocate again memory:
if(tickerSymbol) {
tickerSymbol = new char[MAX_CHAR];
}
use cppCheck to find such errors which the compiler not finds:
http://cppcheck.sourceforge.net/
Jun 1, 2016 at 5:04am UTC
We're supposed to use char pointers instead of strings in my class (i guess the teacher wants it to be harder) and I allocate the memory after just so that its new for the next loop. i just like to be sure. It doesn't have to be there. I've dumped the data after the read and it reads it perfectly but it still print out garbage (lines) when i display.
Jun 1, 2016 at 5:53am UTC
Can you give show us the structure of "stock"?
if you allocate memory with "new" you should free the allocation with "delete" (or "delete []" in the case of arrays) before you reallocate memory. but so far I see it is not necessary to reallocate memory. better you should initialize the memory with memset
http://www.cplusplus.com/reference/cstring/memset/
Jun 1, 2016 at 6:03am UTC
the first file that i pasted contained my class stock which contained my files for the node because I am doing a linked list.
Also, I've commented out the "new char" declarations I've put.
Jun 1, 2016 at 8:56am UTC
@Necip,
thanks for posting this link to cppcheck. Looks really useful.
Jun 1, 2016 at 5:24pm UTC
You're welcome, Thomas. CppCheck is one of the tools that I never want to miss. I found tons of hidden bugs with it!