I'm having some trouble with an assignment that requires creating a hash table using a vector of Entry (ADT created by the professor). The program compiles successfully but gdb gives me the error message "No stack." when I try debugging. I've traced the error to a call to my function search() in my function insert().
I'm not sure where the problem comes from but I think it either stems from the way I access the vector or how I tried to initialize it in the constructor.
My source code is below, my professor wrote the structure Entry and class HT as well as the functions main() and hashing() which cannot be edited although new functions can be added to the class. Even though those parts cannot be edited I included them here for reference.
Here's my header file assignment8.h:
#ifndef ASSIGNMENT8_H
#define ASSIGNMENT8_H
#include <vector>
#include <string>
struct Entry {
std::string key;
std::string description;
Entry() { key = "---"; }
};
class HT {
private:
std::vector<Entry>* hTable;
int table_size=11;
int item_count;
int hashing(const std::string&);
public:
HT();
HT(int size);
~HT();
bool insert(const Entry& e);
int search(const std::string& key);
bool remove(const std::string& s);
void print();
//Student-made member fucntions
void setsize(int size){table_size = size;}
void setItemCount(int ic){ic = item_count;}
int getItemCount(){return item_count;}
};
#endif
and my cc file assignment8.cc:
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include "assignment8.h"
using namespace std;
Entry* get_entry(const string& line)
{
//Holder for string fragments
string strArr[3];
int index = 0;
//Split the string
for(unsigned int i = 0; i < line.length(); i++)
{
if(line[i] != ':')
strArr[index] += line[i];
else
index++;
}
Entry* newEntry = new Entry;
//Pass strings to newEntry
(*newEntry).key = strArr[1];
(*newEntry).description = strArr[2];
return newEntry;
}
string get_key(const string& line)
{
//Holder for string fragments
string strArr[2];
int index = 0;
//Split string
for(unsigned int i = 0; i < line.length(); i++)
{
if(line[i] != ':')
strArr[index] += line[i];
else
index++;
}
//Return item-key
return strArr[1];
}
//----HT----//
// key is in form of letter-letter-digit
// compute sum <-- ascii(pos1)+ascii(pos2)+ascii(pos3)
// compute sum%htable_size
int HT::hashing(const string& key) {
return ((int)key[0] + (int)key[1] + (int)key[2])%table_size;
}
//--Constructors
//Default Constructor
HT::HT(){}
//Constructor
HT::HT(int size)
{
//Initializations
if(!size)
size = 11;
setsize(size);
hTable = new vector<Entry>[table_size];
}
HT::~HT()
{
delete[] hTable;
}
int HT::search(const std::string& key)
{
//Look for unused slot
for(int i = 0; i < table_size; i++)
{
if((*hTable)[i].key == key)
return hashing(key);
}
return -1;
}
bool HT::insert(const Entry& e)
{
//Get e's key
string eKey = e.key;
//If it's full, print error message and return false
if(getItemCount() == table_size)
{
cout << "Hash table is full\n";
return false;
}
//Checks to see if key already exists
if(search(eKey) != -1)
{
cout << "Key already exists in table\n";
return false;
}
//If it does not already exist,
for(int i = 0; i < table_size; i++)
{
string iKey = (*hTable)[i].key;
cout << i << "iteration(s)"<< endl;
if(iKey == "---" || iKey == "+++")
{
//Compute hash key value and insert into position
(*hTable)[i] = e;
setItemCount(++item_count);
return true;
}
}
return false;
}
bool HT::remove(const std::string& s)
{
for(int i = 0; i < table_size; i++)
{
string iKey = (*hTable)[i].key;
if(iKey == s)
{
iKey = "+++";
setItemCount(--item_count);
return true;
}
}
return false;
}
void HT::print()
{
cout << "----Hash Table----" << endl;
for(int i = 0; i < table_size; i++)
{
cout << (*hTable)[i].key << " " << (*hTable)[i].description << endl;
}
cout << endl << "------------------" << endl;
}
int main(int argc, char** argv ) {
if ( argc < 2 ) {
cerr << "argument: file-name\n";
return 1;
}
HT ht;
ifstream infile(argv[1], ios::in);
string line;
infile >> line;
while ( !infile.eof() ) {
if ( line[0] == 'A' ) {
Entry* e = get_entry( line );
ht.insert( *e );
delete e;
}
else {
string key = get_key(line);
if ( line[0] == 'D' ) {
cout << "Removing " << key << "...\n";
bool removed = ht.remove( key );
if ( removed )
cout << key << " is removed successfully...\n\n";
else
cout << key << " does not exist, no key is removed...\n\n";
}
else if ( line[0] == 'S' ) {
int found = ht.search( key );
if ( found < 0 )
cout << key << " does not exist in the hash table ..." << endl << endl;
else
cout << key << " is found at table position " << found << endl << endl;
}
else if ( line[0] == 'P' ) {
cout << "\nDisplaying the table: " << endl;
ht.print();
}
else
cerr << "wrong input: " << line << endl;
}
infile >> line;
}
infile.close();
return 0;
}
Thank you for any help or advice! :)
Related
Trie()
{
nxt.assign(26, NULL);
cout << nxt.size() << endl;
Trie* root = this;
isWord = false;
}
/** Inserts a word into the trie. */
void insert(string word)
{
auto node = root;
for (int i = 0; i < word.size(); i++)
{
cout << "node: " << node<< ":" << "word[i] -'a': " << word[i] - 'a' << endl;
if (node->nxt[word[i] - 'a'] == NULL ) // misaligned memory access here
node->nxt[word[i]-'a'] = new Trie();
node = node->nxt[word[i]-'a'];
}
node->isWord = true;
}
I am getting the following error although the vector seems to have correct length: Member access within misaligned address 0xbebebebebebebe for type 'Trie' which requires 8 byte alignment. Why is the nxt vector elements not accessible?
Update:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class Trie {
public:
Trie() {
nxt.assign(26, NULL);
isWord = false;
}
void insert(string word) {
auto node = this;
for(int i = 0; i < word.size(); i++) {
if (!node->nxt[word[i]-'a']) {
cout << " nxt entry not found... :" << word[i] << endl;
node->nxt[word[i]-'a'] = new Trie();
}
else {
cout << "nxt entry found! :" << word[i] << endl;
node = node->nxt[word[i]-'a'];
}
node->isWord = true;
}
}
bool search(string word) {
auto node = this;
for(int i = 0; i < word.size(); i++) {
if (!node->nxt[word[i]-'a']) return false;
node = node->nxt[word[i]-'a'];
}
return node->isWord ? true: false;
}
private:
vector<Trie*> nxt;
bool isWord;
};
int main() {
Trie* trie = new Trie();
trie->insert("test");
cout << "found test: " << trie->search("test") << endl;
cout << "success!" << endl;
return 0;
}
This runs! Bailey's comment helped me realize my mistake. I had declared a local root in ctor. The intent was to only initialize the class member, root! Thank you!
Trying to Implement a hash table in C++, Where the table has to take in string data and must hold at least 10 items. Implemented this below but doesn't compile and have broke it somehow :(, open to other ideas on how is best to implement or a fix for this one
Thanks
Someone be a legend please. :)
#include <iostream>
#include <cstdlib>
#include <string>
using namespace std;
class hash{
private:
static const int tableSize = 10;
struct item
{
string d;
item* next;
};
item* HashTable[tableSize];
public:
hash();//the constructor
int Hash(string key);
void AddItem(string d);//will add new item
int NumberOfItemsInBucket(int bucket);
void PrintTable();
void PrintItemsInBucket(int bucket);
};
hash::hash()
{
for(int i = 0;i < tableSize;i++)
{
HashTable[i] = new item;
HashTable[i]->d = "";
HashTable[i]->next = NULL;
}
};
void hash::AddItem(string d)
{
int bucket = Hash(d);
if(HashTable[bucket]->d == "")
{
HashTable[bucket]->d = d;
}
else
{
item* Ptr = HashTable[bucket];
item* n = new item;
n->d = d;
n->next = NULL;
while(Ptr->next != NULL)
{
Ptr = Ptr->next;
}
Ptr->next;
}
}
int hash::NumberOfItemsInBucket(int bucket)
{
int slot = 0;
if(HashTable[bucket]->d == "")
{
return slot;
}
else
{
slot++;
item* Ptr = HashTable[bucket];
while(Ptr->next != NULL)
{
slot++;
Ptr = Ptr->next;
}
}
return slot;
}
void hash::PrintTable()
{
int number;
for(int i = 0;i < tableSize;i++)
{
number = NumberOfItemsInBucket(i);
cout << "--------------------\n";
cout << "bucket = " << i << endl;
cout << "Data: " << HashTable[i]->d << endl;
cout << "No. of items = " << number << endl;
cout << "--------------------\n";
}
}
void hash::PrintItemsInBucket(int bucket){
item* Ptr = HashTable[bucket];
if(Ptr->d == ""){
cout << "bucket " << bucket << " is empty!\n";
}else{
cout << "Bucket " << bucket << " contains this: " << endl;
while(Ptr != NULL){
cout << "--------------------\n";
cout << Ptr->d << endl;
cout << "--------------------\n";
Ptr = Ptr->next;
}
}
}
int hash::Hash(string key){
int hash = 0;
int index;
for(int i = 0;i < key.length();i++)
{
hash = hash + (int)key[i];
//cout << "Hash = " << hash << endl; //displays the hash function result
}
index = hash % tableSize;
return index;
}
int main (){
hash newHash;
newHash.AddItem("restaurant");
newHash.AddItem("innovation");
newHash.AddItem("vegetarian");
newHash.AddItem("opposition");
newHash.AddItem("attractive");
newHash.AddItem("incredible");
newHash.AddItem("assessment");
newHash.AddItem("illustrate");
newHash.AddItem("presidency");
newHash.AddItem("background");
newHash.PrintTable();
//newHash.PrintItemsInBucket();
return 0;
}
Compile errors:
note: class hash
error: 'newHash' not declared in the scope
error: reference to 'hash' is ambiguous
Just remove the using manespace std; and add explicitly add std:: to endl, cout, and string.
I'm trying to implement a trie that can print out the frequency of words with a given prefix.
Edit: Thanks to #kaidul-islam finding my error with the following error:
new_word->child[letter]->prefixes_++;
Below is the fixed code:
Trie Class:
class Trie
{
public:
Trie(): prefixes_(0), is_leaf_(false), frequency_(0)
{
for (int i=0; i<26; i++)
{
child[i] = nullptr;
}
}
virtual ~Trie();
//Child nodes of characters from a-z
Trie *child[26];
//vector<Trie> child;
int prefixes_;
//accessor & mutator functions
bool GetIsLeaf() { return is_leaf_; }
void SetIsLeaf(bool val) { is_leaf_ = val; }
int GetFrequency() { return frequency_; }
void SetFrequency(int val) { frequency_ = val; }
int GetPrefixes() { return prefixes_; }
void SetPrefixes(int val) { prefixes_ = val; }
bool is_leaf_;
private:
//bool is_leaf_;
int frequency_;
};
Function in Question:
void AddWord(string &word, Trie *root)
{
Trie *new_word = root;
new_word->prefixes_++;
for(unsigned int i = 0 ; i < word.length(); i++)
{
int letter = (int)word[i] - (int)'a'; //extract character of word
if(new_word->child[letter] == nullptr)
{
new_word->child[letter] = new Trie;
}
/*cout << "not value of x: " << new_word->child[letter]->GetPrefixes() << endl;
int x = (new_word->child[letter]->GetPrefixes())+1;
cout << "value of x: " << x << endl;
new_word->child[letter]->SetPrefixes(x);*/
new_word->child[letter]->prefixes_++;
new_word = new_word->child[letter];
}
new_word->SetFrequency(new_word->GetFrequency()+1);
/*
cout << "Word: " << word << endl;
cout << "frequency: " << new_word->GetFrequency() << endl;
cout << "prefixes: " << new_word->GetPrefixes() << endl;
cout << "is leaf: " << new_word->GetIsLeaf() << endl << endl;
*/
}
After a quick inspection, I found you didn't initialize member variables in your constructor.
Trie(): prefixes_(0),
is_leaf_(false),
frequency_(0) {
for(int i = 0; i < 26; i++) {
child[i] = nullptr;
}
}
Unlike global variable, there is no guarantee that prefixes_ will be 0 by default on declaration. And child[i] is not guaranteed to be nullptr too. You need to initialize everything.
there. I am trying to get collision and compare times in Hash search. Yet it doesn't work out. Can anyone point out what the problem is? Thanks very much. Here is my code.
HashSerch.cpp
#include <cstring>
#include <iostream>
#include <iomanip>
using namespace std;
const int TOTAL=32; //32 keywords
const int MAXLEN=10; //length of keyword
const int HASHLEN=41; //length of HASH table
const char* KeyWords[TOTAL] =
{
"auto","double","int","struct","break","else","long","switch",
"case","enum","register","typedef","char","extern","return","union",
"const","float","short","unsigned","continue","for","signed","void",
"default","goto","sizeof","volatile","do","if","while","static",
};
class HASH
{
public:
char keyword[MAXLEN];
int count; //occurrence number
int con; //collision times
};
HASH HS[HASHLEN];
//declaration
int isLetter(char ch);
int isKeyWords(char *word);
int FindHX(char *keyword); //search Hash table
int CreatHX(char *keyword); //create Hash table
int GetFreePos(int key); //get free position when having collision
void ResetHX();
int GetKey(char *keyword); //get Hash value of keywords
int ShowHashTable(int key); //show search results
int isLetter(char ch)
{
if( (ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z') ) return 1;
else return 0;
}
int FindHX(char *keyword, int &cmp_count) //search Hash table
{
int key,find,tem=0;
if(!isKeyWords(keyword)) return -1;
key=GetKey(keyword);
if(strcmp(HS[key].keyword,keyword)==0)
{
cmp_count++;
return key;
}
for(find=key+1;find<HASHLEN;find++) //if keyword exsits
{
cmp_count++; //count compare times
tem++; //count collision times
if(strcmp(HS[find].keyword,keyword)==0)
{
HS[find].con=tem;
return find;
}
}
for(find=0;find<key;find++)
{
cmp_count++;
tem++;
if(strcmp(HS[find].keyword,keyword)==0)
{
HS[find].con=tem;
return find;
}
}
return -1;
}
int CreatHX(char *keyword) //create Hash table
{
int key;
if(!isKeyWords(keyword)) return -1;
key=GetKey(keyword); //get Hash value of keywords
if(strlen(HS[key].keyword)>0) //if the keyword exists
{
if(strcmp(HS[key].keyword,keyword)==0) //if equals to position in Hash table
{
HS[key].count++;
return 1;
}
key=FindHX(keyword, cmp_count); //not equal
if(key<0)
{
key=GetFreePos(GetKey(keyword));
if(key<0) return -1;
strcpy(HS[key].keyword,keyword); //insert keyword into Hash table
}
if(key<0) return -1;
HS[key].count++;
}
else //if position is empty, insert keyword
{
strcpy(HS[key].keyword,keyword);
HS[key].count++;
}
return 1;
}
int GetFreePos(int key) //get free position
{
int find,tem=0;
if(key<0||key>=HASHLEN) return -1;
for(find=key+1;find<HASHLEN;find++) //positions afterwards
{
tem++;
if(strlen(HS[find].keyword)==0)
{
HS[find].con=tem;
return find;
}
}
for(find=0;find<key;find++) //position forewards
{
tem++;
if(strlen(HS[find].keyword)==0)
{
HS[find].con=tem;
return find;
}
}
return -1; //Hash table is full
}
void ResetHX()
{
int i;
for(i=0;i<HASHLEN;i++)
{
strcpy(HS[i].keyword,"");
HS[i].count=0;
HS[i].con=0;
}
}
int GetKey(char *keyword) //get Hash value of keywords
{
//Hash(Key)=[(initial letter)*100+(tail letter)] Mod 41
return ( keyword[0]*100+keyword[strlen(keyword)-1] ) % 41;
}
int isKeyWords(char *word)
{
int i;
for(i=0;i<TOTAL;i++)
if(strcmp(word,KeyWords[i])==0) return 1;
return 0;
}
int ShowHashTable(int key) //show results
{
int hash_count = 0;
if(key < 0 || key >= HASHLEN)
{
cout << "Error! Invalid key word!" << endl;
return 0;
}
if(strlen(HS[key].keyword) == 0)
{
cout << "[" << key << "]" << setw(12) << "N/A" << endl;
return 0;
}
cout << "[" << key << "]" << setw(12) << HS[key].keyword << setw(12) << "Count: " << HS[key].count << endl;
hash_count++;
return hash_count;
}
main.cpp
#include <iostream>
#include <cstring>
#include "HashSearch.h"
extern HASH HS[MAXLEN];
using namespace std;
int hash_count = 0;
for(int i = 0; i < HASHLEN; i++)
{
hash_count = hash_count + ShowHashTable(i);
}
cout << "Amount of key words: " << hash_count << endl << endl;
int conf_count = 0;
cout << setiosflags(ios::left) << setw(15) << "[Index]" << setiosflags(ios::left) << setw(20)
<< "[KeyWords]" << setiosflags(ios::left) << setw(20) << "[Conflicts]" << endl;
for(int i = 0; i < HASHLEN; i++)
{
if(strlen(HS[i].keyword) > 0)
{
int key = Hash(HS[i].keyword);
if(key != i)
{
conf_count++;
//cout << HS[i].con << endl;
cout << setiosflags(ios::left) << setw(15) << i << setiosflags(ios::left) << setw(25)
<< HS[i].keyword << setiosflags(ios::left) << setw(20) << HS[i].con << endl;
}
}
}
if(conf_count == 0)
cout << "No conflicts!" << endl;
else
cout << "Amount of conflict keywords: " << conf_count << endl << endl;
I first imported a source txt file and created a Hash table. It seems that all goes well. But when I want to get the compare times and collision times, the variable HS.con(to count collision times) and cmp_count(to count compare times) don't accumulate correctly. The value stays 0 if watching in debug mode. And how can I get correct count?
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
So, I can run this program in Visual Studio with absolutely no problems, producing correct output. However, after compiling in the Linux terminal, I get a seg fault when trying to run the same code. Upon debugging using GDB, the information given is not very helpful (will be provided below). The program consists of two header files and three .cpp files. I will provide all of them below, along with the debugging information given. (If the indenting is weird, it is because of the 4-space code indent rule for submission). I have been trying to find the issue for hours on end to no avail. I have a feeling it is a small, minor mistake. Thank you all very much in advance.
Song.h
#ifndef Song_h
#define Song_h
#include <iostream>
#include <fstream>
#include <string>
#include <ctime>
#include <stdlib.h>
using namespace std;
class Song
{
private:
string artist;
string title;
int size;
public:
Song(); //declares blank song array
Song(string _title, string _artist, int _size); //initializes object with given parameters for Song instance
string getArtist() const
{
return artist;
}
string getTitle() const
{
return title;
}
int getSize() const
{
return size;
}
void setArtist(string _artist)
{
artist = _artist;
}
void setTitle(string _title)
{
title = _title;
}
void setSize(int _size)
{
size = _size;
}
bool operator == (Song const &rhs);
bool operator != (Song const &rhs);
bool operator > (Song const &rhs);
bool operator < (Song const &rhs);
};
#endif
TsuPod.h
#ifndef TsuPod_h
#define TsuPod_h
#include "Song.h"
//TsuPod class declaration
class TsuPod
{
private:
struct SongNode
{
Song data;
SongNode *next;
};
SongNode *songs; //the head pointer
static const int MAX_SIZE = 512;
static const int SUCCESS = 0;
static const int FAILURE = 1;
static const int NO_MEMORY = -1;
static const int NOT_FOUND = -2;
int getNumSongs();
int memSize;
public:
TsuPod();
TsuPod(int size);
~TsuPod();
int addSong(Song const &s);
int removeSong(Song const &s);
void shuffle();
void showSongList();
void sortSongList();
int getRemainingMemory();
int getTotalMemory()
{
return memSize;
}
};
Song.cpp
#endif
#include "TsuPod.h"
#include "Song.h"
Song::Song() //default constructor, initializes a blank song
{
artist = "";
title = "";
size = 0;
}
Song::Song(string _artist, string _title, int _size) //constructor for song when arguments are given by user
{
artist = _artist;
title = _title;
size = _size;
}
bool Song::operator == (Song const &rhs) //overloaded for sorting
{
return (title == rhs.title &&
artist == rhs.artist &&
size == rhs.size);
}
bool Song::operator != (Song const &rhs) //overloaded for sorting
{
return (title != rhs.title ||
artist != rhs.artist ||
size != rhs.size);
}
bool Song::operator > (Song const &rhs) //overloaded for sorting
{
if (artist != rhs.artist)
return (artist > rhs.artist);
else
if (title != rhs.title)
return (title > rhs.title);
else
if (size != rhs.size)
return (size > rhs.size);
else
return false;
}
bool Song::operator < (Song const &rhs) //overloaded for sorting
{
if (artist != rhs.artist)
return (artist < rhs.artist);
else
if (title != rhs.title)
return (title < rhs.title);
else
if (size != rhs.size)
return (size < rhs.size);
else
return false;
}
TsuPod.cpp
#include "TsuPod.h"
#include "Song.h"
TsuPod::TsuPod() //default constructor
{
memSize = MAX_SIZE;
}
TsuPod::TsuPod(int _size) //constructor for when user specifies their prefered memory size, prevents input of a size greater than MAX_SIZE or less than 0
{
if (_size > MAX_SIZE || _size <= 0)
memSize = MAX_SIZE;
else
memSize = _size;
}
TsuPod::~TsuPod() //destructor
{
SongNode *p;
while (songs != NULL)
{
p = songs;
songs = songs->next;
delete p;
}
}
int TsuPod::getRemainingMemory() //finds remaining memory, returns int value
{
int memSum = 0;
SongNode *p = songs;
while (p != NULL)
{
memSum += p->data.getSize();
p = p->next;
}
return memSize - memSum;
}
int TsuPod::addSong(Song const &s) //adds song to TsuPod, returns int number to display result, 0 = success, 1 = failure, -1 = not enough memory
{
if (s.getSize() > getRemainingMemory()) //ensures there is enough unsused memory for song
return NO_MEMORY;
if (s.getSize() > 0) //ensures song is valid
{
SongNode *temp = new SongNode;
temp->data = s;
temp->next = songs;
songs = temp;
return SUCCESS;
}
else
return FAILURE;
}
int TsuPod::removeSong(Song const &s) //removes song, returns int value to display result, 0 = success, 1 = failure, -2 = not found
{
if (songs != NULL)
{
SongNode *prev = NULL;
SongNode *p = songs;
if (p->data == s)
{
songs = p->next;
return SUCCESS;
}
while (p != NULL && p->data != s)
{
prev = p;
p = p->next;
if (songs->data == s)
{
songs = p->next;
delete p;
return SUCCESS;
}
else
if (p->data == s)
{
prev->next = p->next;
delete p;
return SUCCESS;
}
else
{
}
}
}
return NOT_FOUND;
}
int TsuPod::getNumSongs() //calculates number of songs, returns int value
{
SongNode *p1 = songs;
int i = 0;
while (p1 != NULL)
{
i++;
p1 = p1->next;
}
return i;
}
void TsuPod::shuffle() //shuffles TsuPod song list, void return value
{
srand((unsigned)time(NULL));
for (int j = 0; j < getNumSongs() * 2; j++)
{
int r1 = rand() % getNumSongs();
int r2 = rand() % getNumSongs();
SongNode *p1 = songs;
SongNode *p2 = songs;
for (int i = 0; i < r1; i++)
p1 = p1->next;
for (int i = 0; i < r2; i++)
p2 = p2->next;
Song temp = p1->data;
p1->data = p2->data;
p2->data = temp;
}
cout << endl << " PLAYLIST SHUFFLED" << endl << endl;
}
void TsuPod::sortSongList() //sorts song list by artist, title, and size respectively, void return value
{
for (SongNode *p1 = songs; p1 != NULL; p1 = p1->next)
{
SongNode *small = p1;
for (SongNode *p2 = p1->next; p2 != NULL; p2 = p2->next)
{
if (small->data > p2->data)
{
small = p2;
}
}
if (p1 != small)
{
Song temp = small->data;
small->data = p1->data;
p1->data = temp;
}
}
cout << endl << " PLAYLIST SORTED" << endl;
}
void TsuPod::showSongList() //shows song list, void return value
{
cout << " ___________________________________________________ " << endl << " TsuPod 2.0" << endl << endl;
cout << " Memory ---- Total: " << getTotalMemory() << " MB" << " -- Remaining: " << getRemainingMemory() << " MB" << endl;
SongNode *p = songs;
int i = 0;
while (p != NULL)
{
i++;
cout << endl << " " << i << ". " << p->data.getArtist();
int artistLength = p->data.getArtist().length();
for (int j = 0; j < (24 - artistLength); j++) //This loop is implemented to evenly space the artist from the song
cout << " ";
cout << p->data.getTitle();
int titleLength = p->data.getTitle().length();
for (int j = 0; j < (24 - titleLength); j++) //This loop is implemented to evenly space the song title from the song size
cout << " ";
cout << p->data.getSize() << " (MB)" << endl;
p = p->next;
}
cout << endl;
}
TsuPod_Driver.cpp
#include <cstdlib>
#include <iostream>
#include "Song.h"
#include "TsuPod.h"
using namespace std;
int main(int argc, char *argv[])
{
TsuPod t;
Song s1("Animals As Leaders", "Another Year", 4);
int result = t.addSong(s1);
cout << " add result = " << result << endl;
Song s2("Gorillaz", "Stylo", 6);
result = t.addSong(s2);
cout << " add result = " << result << endl;
Song s3("August Burns Red", "Meridian", 6);
result = t.addSong(s3);
cout << " add result = " << result << endl;
Song s4("The Ink Spots", "If I Didn't Care", 7);
result = t.addSong(s4);
cout << " add result = " << result << endl;
Song s5("Beatles", "I Feel Fine", 241);
result = t.addSong(s5);
cout << " add result = " << result << endl;
Song s6("Fine Constant", "Sea", 3);
result = t.addSong(s6);
cout << " add result = " << result << endl;
Song s7("Human Abstract", "Nocturne", 9);
result = t.addSong(s7);
cout << " add result = " << result << endl;
Song s8("August Burns Red", "Meridian", 4);
result = t.addSong(s8);
cout << " add result = " << result << endl;
Song s9("Frank Sinatra", "My Way", 5);
result = t.addSong(s9);
cout << " add result = " << result << endl;
t.showSongList();
t.shuffle();
t.showSongList();
t.sortSongList();
t.showSongList();
result = t.removeSong(s1);
cout << " delete result = " << result << endl;
result = t.removeSong(s2);
cout << " delete result = " << result << endl;
result = t.removeSong(s3);
cout << " delete result = " << result << endl;
t.showSongList();
result = t.removeSong(s4);
cout << " delete result = " << result << endl;
result = t.removeSong(s5);
cout << " delete result = " << result << endl;
result = t.removeSong(s6);
cout << " delete result = " << result << endl;
result = t.removeSong(s7);
cout << " delete result = " << result << endl;
result = t.removeSong(s8);
cout << " delete result = " << result << endl;
result = t.removeSong(s9);
cout << " delete result = " << result << endl;
t.showSongList();
cout << " memory = " << t.getRemainingMemory() << endl << endl << endl << endl;
for (int i = 1; i < 33; i++) //tests to ensure that user cannot add a song when there is not enough space available
{
Song s1("August Burns Red", "Meridian", i);
result = t.addSong(s1);
cout << " add result = " << result << endl;
}
t.showSongList();
cin.get();
return EXIT_SUCCESS;
Debugging Info From Linux Terminal
Program received signal SIGSEGV, Segmentation fault.
0x0000000000402d50 in Song::getSize() const ()
(gdb) backtrace
#0 0x0000000000402d50 in Song::getSize() const ()
#1 0x00000000004024ac in TsuPod::getRemainingMemory() ()
#2 0x00000000004024fb in TsuPod::addSong(Song const&) ()
#3 0x000000000040112e in main ()
I don't see any sign of TsuPod::songs being initialized. There is no guarantee that it's going to be NULL in the empty list case, so your
while (p != NULL)
test in TsuPod::getRemainingMemory() may pass with an insane value from the stack and blow up when you use p on the next line.
I recommend
TsuPod::TsuPod():songs(NULL) //default constructor
{
memSize = MAX_SIZE;
}
TsuPod::TsuPod(int _size):songs(NULL) //constructor for when user specifies their prefered memory size, prevents input of a size greater than MAX_SIZE or less than 0
{
if (_size > MAX_SIZE || _size <= 0)
memSize = MAX_SIZE;
else
memSize = _size;
}
to ensure that songs starts with your end of list condition.
Also, consider using std::list to do your list management in place of the roll-your-own linked list.