Outputting a string pointer array - c++

I'm having a bit of trouble figuring out exactly what I am doing wrong here, and haven't found any posts with the same issue. I am using a dynamic array of strings to hold a binary tree with the root at [0], first row of children, left to right, at [1] and [2], etc. While I haven't debugged that output format yet, I am much more concerned as to why that specific line is crashing my program.
I thought it was a pointer de-referencing issue, but outStream << &contestList[i] prints addresses as I'd expect, and outStream << *contestList[i] throws errors as I'd expect them to.
//3 lines are from other functions/files
typedef string elementType;
typedef elementType* elementTypePtr;
elementTypePtr contestList = new elementType[arraySize];
void BinTreeTourneyArray::printDownward(ostream &outStream)
{
int row = 1;
for (int i = 0; i < getArraySize(); i++)
{
outStream << contestList[i]; //this is crashing the program
if (isPowerOfTwo(i))
{
outStream << endl;
row++;
}
else
{
outStream << ":";
}
}
}
arraySize is a private member arraySize = ((2 * contestants) - 1) where contestants is the number of contestants in my tournament. Each round or "row" in the tree is synonymous with a tournament bracket. If there are n contestants, then there are 2n-1 nodes needed in the tree. The issue wouldn't be with this function.
getArraySize() { return arraySize; }

Turns out elementTypePtr contestList = new elementType[arraySize]; was the issue. contestList was a private member of the class, then I threw this line in a function declaring a local variable of the same name that disappears after the function ends. No biggie, except for the fact that I needed it in the print function...Oops.

Related

Skip List C++ segmentation fault

I'm trying to implement the Skip List using this article Skip List.
Code:
#include<iostream>
#include<cstdlib>
#include<ctime>
#include<limits>
using namespace std;
template<class T>
class SkipList{
private:
class SkipNode{
public:
T* key; //Pointer to the key
SkipNode** forward; //Forward nodes array
int level; //Node level
//SkipNode constructor
SkipNode(T* key, int maxlvl, int lvl){
forward = new SkipNode*[maxlvl];
this->key=key;
level=lvl;
}
//Method that print key and level node
print(){
cout << "(" << *key << "," << level << ") ";
}
};
SkipNode *header,*NIL; //Root and End pointers
float probability; //Level rate
int level; //Current list level
int MaxLevel; //Maximum list levels number
//Function that returns a random level between 0 and MaxLevel-1
int randomLevel(){
int lvl = 0;
while( (float(rand())/RAND_MAX < probability) && (lvl < MaxLevel-1) )
lvl++;
return lvl;
}
public:
//SkipList constructor
SkipList(float probability, int maxlvl){
this->probability = probability;
MaxLevel = maxlvl;
srand(time(0));
header=new SkipNode(NULL,MaxLevel,0); //Header initialization
T* maxValue = new T;
*maxValue = numeric_limits<T>::max(); //Assign max value that T can reach
NIL = new SkipNode(maxValue,0,0); //NIL initialization
level=0; //First level
for(int i=0; i<MaxLevel; i++){ //Every header forward node points to NIL
header->forward[i]=NIL;
}
}
//SkipList destructor
~SkipList(){
delete header;
delete NIL;
}
//Method that search for a key in the list
SkipNode* search(T* key){
SkipNode* cursor = header;
//Scan the list
for(int i=level; i>=0; i--)
while(*(cursor->forward[i]->key) < (*key))
cursor=cursor->forward[i];
cursor=cursor->forward[0];
if(*(cursor->key) == *key)
return cursor;
return NULL;
}
//Method that insert a key in the list
SkipList* insert(T* key){
SkipNode* cursor = header;
SkipNode* update[MaxLevel]; //Support array used for fixing pointers
//Scan the list
for(int i=level; i>=0; i--){
while(*(cursor->forward[i]->key) < *(key))
cursor=cursor->forward[i];
update[i]=cursor;
}
cursor=cursor->forward[0];
if(*(cursor->key) == *(key)){ //Node already inserted
return this;
}
int lvl = randomLevel(); //New node random level
if(lvl > level){ //Adding missing levels
for(int i=level+1; i<=lvl; i++)
update[i]=header;
level=lvl;
}
SkipNode* x = new SkipNode(key,MaxLevel,lvl); //New node creation
for(int i=0; i<=lvl; i++){ //Fixing pointers
x->forward[i] = update[i]->forward[i];
update[i]->forward[i] = x;
}
return this;
}
//Method that delete a key in the list
SkipList* erase(T* key){
SkipNode* cursor = header;
SkipNode* update[MaxLevel]; //Support array used for fixing pointers
//Scan the list
for(int i=level; i>=0; i--){
while(*(cursor->forward[i]->key) < *(key))
cursor=cursor->forward[i];
update[i]=cursor;
}
cursor=cursor->forward[0];
if(*(cursor->key) == *(key)){ //Deletetion of the founded key
for(int i=0; i<=level && update[i]->forward[i] == cursor; i++){
update[i]->forward[i] = cursor->forward[i];
}
delete cursor;
while(level>0 && header->forward[level]==NIL){
level=level-1;
}
}
return this;
}
//Method that print every key with his level
SkipList* print(){
SkipNode* cursor = header->forward[0];
int i=1;
while (cursor != NIL) {
cursor->print();
cursor = cursor->forward[0];
if(i%15==0) cout << endl; i++;
}
cout << endl;
return this;
}
};
main(){
SkipList<int>* list = new SkipList<int>(0.80, 8);
int v[100];
for(int i=0; i<100; i++){
v[i]=rand()%100;
list->insert(&v[i]);
}
list->print();
cout << endl << "Deleting ";
for(int i=0; i<10; i++){
int h = rand()%100;
cout << v[h] << " ";
list->erase(&v[h]);
}
cout << endl;
list->print();
cout << endl;
for(int i=0; i<10; i++){
int h = rand()%100;
cout << v[h] << " ";
if(list->search(&v[h]))
cout << " is in the list" << endl;
else
cout << " isn't in the list" << endl;
}
delete list;
}
It gives me Segmentation Fault on line 59 (the for-cycle on the insert), but I can't understand why. May you help me please? I will accept any other improvement that you suggest. My deadline is on two days, that's why I'm asking for help.
EDIT:
I've corrected the code with bebidek suggestions (Thanks). Now first level is 0. It seems to be working, but sometimes some nodes is not inserted correctly and the search give a bad result.
LAST EDIT:
It works, thanks to all
ONE MORE EDIT:
Added comments to code, if you have any suggestion you're welcome
The biggest problem in your code is probably NIL=new SkipNode(numeric_limits<T*>::max());
First of all i suspect you want the key pointer to point to a memory address that contains the biggest possible int value.
But that's not what's actually happening here. Instead the key pointer points to the biggest possible memory-address which is most likely not available for your process.
Also the forward property probably contains an array of junk pointers.
Then when the first loop in the insert method is executed this leads to 2 problems:
while(*(cursor->forward[i]->key) < *(key)) will compare the key value to an invalid pointer
cursor=cursor->forward[i]; will re-assign cursor to an invalid pointer
I would first suggest you'd change the design to let SkipNode keep a value to T instead of a pointer:
class SkipNode{
public:
T key;
SkipNode* forward[100];
This will make a lot of pointer related code unnecessary and make the code simpler so less likely to run into access violation.
Also it might be cleaner to use an actual NULL (or event better nullptr) value instead of a dummy NIL value to indicate the end of the list.
So, first problem is when you create NIL node:
NIL=new SkipNode(numeric_limits<T*>::max());
As argument you should use pointer to existing variable, for example:
T* some_name = new T;
*some_name = numeric_limits<T>::max();
NIL = new SkipNode(some_name);
Notice, I used T instead of T* in numeric_limits. Of course you have to remember about deleting this variable in destructor.
Second problem is that level variable in your code sometimes is inclusive (I mean level number level exists) as in line 61, and sometimes exclusive (level number level doesn't exist) as in line 71. You have to be consistent.
Third problem is in line 52. You probably mean cursor=cursor->forward[1];, but after loop i = 0, and forward[0] doesn't have any sense in your code.
EDIT:
Fourth and fifth problem is in erase function.
cursor->~SkipNode();
It won't delete your node, but only run empty destructor. Use delete cursor; instead.
And in loop you probably wanted to write update[i]->forward[i] == cursor instead of !=.
ONE MORE EDIT:
You haven't implemented any destructor of SkipList and also you forgot about delete list; at the end of main(). These two will give you a memory leak.
ANOTHER EDIT:
srand(time(0));
This line should be executed once at the beginning of main and that's all. If you execute it before each random generation, you will get the same result every time (as time(0) counts only seconds and your program can run function randomLevel() more than once a second).
You also forgot about rewriting precision variable in constructor of SkipList.
NEXT EDIT:
In your insert function you don't have level randomization. I mean, you do not have ability of inserting node of level less than level of whole skip list. It's not error which will crash your program or give wrong results, but time complexity of queries in your structure is O(n) instead of O(log n).
You should use lvl instead of level in this loop in insert function:
for(int i=1; i<level; i++){
x->forward[i] = update[i]->forward[i];
update[i]->forward[i] = x;
}
And also minimum result of your random function randomLevel should be 1 instead of 0, as you don't want node witch level=0.

Data don't insert into an array of pointers

I have my class CompressionAlgorithm from which classes RLE and MTF inherits. I made an array to which I am trying to add these child classes but only first class gets added.
int const size = 2;
CompressionAlgorithm * CA[size];
CA[0] = new RLE();
CA[1] = new MTF();
Both RLE and MTF get initialized but when I am trying to print their name using printall method MTF doesn't get any info printed on console or I am getting an error saying std::bad_alloc.
Print p;
p.printall(*CA, (size));
void Print::printall(CompressionAlgorithm *ca, int size)
{
for (int i = 0; i < size; i++)
{
cout << i+1 << " for ";
cout << ca[i].GetName();
cout << "\n";
}
}
Where am I making a mistake?
You need make function to accept array of pointers not just a pointer:
void Print::printall(CompressionAlgorithm *ca[], int size)
and whil calling you need to call like this:
p.printall(CA, (size));
You don't need to dereference the pointer when passing it to the function; doing so only passes the first element. Additionally the function signature needs to accept an array of pointers, which is what you have.
instead of calling *ca in the printall() call only ca as calling *ca only accesses the first element of the array when not in a loop.

c++ pointer to function and void pointers iteraction resulting in wierd things

Im making a little project at home about genetic algorithm. But im trying to make it generic, so i use pointers to function and void pointers. but i think it might be making some problems.
The main goal of this section of the project is to get a pointer to a function, which return a certain struct. The struct containing a void pointer
and when im trying to view the value of where it points too it isn`t quite right.I suspect that maybe the interaction between these two might be causing me some problems.
details:
struct:
struct dna_s{
int size;
void *dna;
};
population is a class contaning all the population for the process. besides, it contains 2 functions as well, init_func and fitter_func which are both pointers to functions.
pointer to function definition:
typedef dna_s (*init_func_t)();
typedef int (*fitter_func_t)(dna_s);
population class:
class population{
private:
// Parameters
int population_size;
node *pop_nodes;
// Functions
init_func_t init_func;
fitter_func_t fitter_func;
public:
population(int pop_size,init_func_t initialization_func){
// Insert parameters into vars.
this->population_size = pop_size;
this->init_func = initialization_func;
// Create new node array.
this->pop_nodes = new node[this->population_size];
for(int i = 0;i < this->population_size; i++){
dna_s curr_dna = this->init_func();
char *s = static_cast<char*>(curr_dna.dna);
cout << s << endl;
this->pop_nodes[i].update_dna(curr_dna);
}
}
};
You can see that in the constructor im inserting a pointer to function, init_func. this function is generating random words.
init_func:
dna_s init_func(){
string alphanum = "0123456789!##$%^&*ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
char init_s[STRING_SIZE+1] = {};
dna_s dna;
// Generate String
for(int i = 0; i < STRING_SIZE; i++){
init_s[i] = alphanum[rand() % alphanum.size()];
}
cout << "-->" << init_s << endl;
// Insert into struct.
dna.size = STRING_SIZE;
dna.dna = static_cast<void*>(&init_s);
// Return it
return dna;
}
the main function is not so interesting but it might be connected:
int main(){
// Init srand
srand(time(0));
// Parameters
int population_size = 10;
population pop(population_size, init_func);
}
now for the interesting part, whats the problem?
in the init_func the cout prints:
-->e%wfF
which is all good
but in the population class the cout prints:
e%Ω²(
and the wierd thing is the first 2 characters will always be the same, but the other 3 will always be this string Ω²(.
example:
-->XaYN7
XaΩ²(
-->oBK9Q
oBΩ²(
-->lf!KF
lfΩ²(
-->RZqMm
RZΩ²(
-->oNhMC
oNΩ²(
-->EGB6m
EGΩ²(
-->osafQ
osΩ²(
-->3#NQt
3#Ω²(
-->D62l0
D6Ω²(
-->tV#mu
tVΩ²(
Your code has a few lifetime issues. In your dna_S struct:
void *dna;
This is a pointer, it points to an object that exists elsewhere. Then, in your init_func:
dna_s init_func(){
...
char init_s[STRING_SIZE+1] = {};
dna_s dna;
...
dna.dna = static_cast<void*>(&init_s);
...
return dna;
}
init_s is a variable that exists inside init_func, you make dna point to that variable and then leave the function. init_s ceases to exist at this point, dna is pointing nowhere useful when the population constructor gets it, causing undefined behavior.
You could work around that by allocating memory with new char[], like you did for pop_nodes, but you are responsible for deleting that memory when it is no longer used.

Adding to hash table in C++?

Guessing I'm doing something stupidly simple wrong, but can't seem to find an answer in existing stack overflow questions. I'm trying to implement a simple hash table containing lists of strings in C++ for a programming class. My add() function appears to be working correctly from inside the function, but as soon as I check the hash table's contents from the contains() function it's obvious that something's gone wrong.
void string_set::add(const char *s) {
//copy s into new char array str
char str[strlen(s)];
strcpy(str, s);
//find hash value of string
int hValue = string_set::hash_function(s);
//create new node to contain string
node* newNode = new node();
newNode->s = str;
//if string's position in hash table is empty, add directly and
//set newNode's next to null. if not, set newNode next to
//current first node in list and then add to hash table
if(hash_table[hValue] == NULL) {
hash_table[hValue] = newNode;
newNode->next = NULL;
} else {
newNode->next = hash_table[hValue];
hash_table[hValue] = newNode;
}
cout << "string added: " << hash_table[hValue]->s << endl;
return;
}
This prints the expected string; i.e. if I add "e" it prints "e".
But when I call this immediately after:
int string_set::contains(const char *s) {
//find hash value of string
int hValue = string_set::hash_function(s);
//return inital value of hash table at that value
cout << "hash table points to " << hash_table[hValue]->s << endl;
}
It prints some junk. What have I done?
Since this is for a class, the specifications have been provided and I have no opportunity to change the way the hash table is set up. I'll be adding exceptions etc later, just want to get the add function working. Thanks!
EDIT: Sorry, new to stack overflow and not sure about comment formatting! Yes, I can use std::string. The hash function is as follows
int string_set::hash_function(const char *s) {
int cValue =0;
int stringSum = 0;
unsigned int i = 0;
for(i = 0; i < strlen(s); i++) {
cValue = (int) s[i];
stringSum = stringSum + cValue;
}
stringSum = stringSum % HASH_TABLE_SIZE;
return stringSum;
}
You are trying to use local variable outside of its function scope. This is an undefined behavior in C++. In your compiler realization, stack frame is invalidated, so all newNode->s pointers became dangling, memory, they are pointing, is already used to store different stack frame. To solve this issue you could either dynamically allocate memory on the heap or use std::string instead of char* which is the best approach.
Also its worth pointing out, that standard C++ library already have hash table realization std::unordered_map.

A few questions regarding overloading stream operators in c++

I am working on a hangman program and I want to output a status report to the user after each guess. As I am using classes, I need to use a 'friend' keyword. I'm ok with the concept of classes and friends however I am struggling to implement it properly in my program.
The main issue is that the numbers of vowels is not being counted and the number of letters the user can try is not updating. The full alphabet is being displayed each time.
The code of my program is substantial and I'm not going to post all of it here. The issues I have are with the functions remainingLetters(); and vowelCount(). I have attached the relevant code snippets. This code will obviously not compile. I'm just hoping that someone might see an obvious mistake that I've missed.
**Hangman.h:**
{
public:
...
int vowelCount()const; //to be implemented
char* remainingLetters()const;//to be implemented
friend ostream& operator<< (ostream &out, Hangman &game);
private:
...
int vowel_count;
char secretWord[MAXWORDLENGTH];
char* remaining_letters;
}
**hangman.cpp:**
{
...
int Hangman::vowelCount()const
{
int vowel_count = 0;
int i;
secretWord[i];
for(i=0; i<strlen(secretWord); i++)
{
if(secretWord[i]=='a'||secretWord[i]=='e'||secretWord[i]=='i'||secretWord[i]=='o'||secretWord[i]=='u')
{
vowel_count++;
}
}
return vowel_count;
}
char* Hangman::remainingLetters()const
{
char alphabet[26]={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
char *remaining_letters=new char[ALPHABETSIZE];
for(int i=0; i<strlen(secretWord); i++)
{
for(int j=0; j<ALPHABETSIZE; j++)
{
if(secretWord[i]!=alphabet[j])
{
remaining_letters[j]=alphabet[j];
}
}
}
return remaining_letters;
}
ostream& operator<< (ostream &out, Hangman &game)
{
out << "Number of guesses remaining is: " << game.numGuessesAllowed-game.numWrongGuesses << endl
<< "Number of incorrect guesses so far is: "<<game.numWrongGuesses <<endl
<< "Letters remaining are: "<<game.remaining_letters <<endl
<< "Hint: The secret word contains "<<game.vowel_count <<" vowels"<<endl;
return out;
}
}
**main.cpp**
{
...
cout << game;
...
return 0;
}
You need to call the functions vowelCount() and remainingLetters() for the corresponding variables to be calculated (so that you can output them).
Also, char *remaining_letters=new char[ALPHABETSIZE]; will allocate the memory for the letters and initialize each position with 0 -- which also happens to be the string terminating value. So if the first position (letter 'a') is not set, out<<game.remaining_letters will not output anything
Moreover, the function vowelCount() defines the local variable vowel_count that hides the one in the class (member variable), so the member variable will not get updated (uless you explicitly assign the return value of vowelCount() to that member variable) I suggest you delete the local variable declaration from the vowelCount() function and it will use the member variable, which is what you need
The previous paragraph also applies to the member variable remaining_letters
One more thing: the memory allocated with new is not deallocated automatically, and once you return from the function call, the allocated memory is lost (as in there is no way to access it again, but it still uses memory), unless you assign it when the function returns. You will need to pari each new[] call with its corresponding delete[] call. Better yet: allocate the memory in the constructor of the class and delete it in the destructor for the member variable
Note: yet another bug is in this logic:
for(int i=0; i<strlen(secretWord); i++)
{
for(int j=0; j<ALPHABETSIZE; j++)
{
if(secretWord[i]!=alphabet[j])
{
remaining_letters[j]=alphabet[j];
}
}
}
you cycle through the alphabet and every time the current letter in secret word is not matvching, you assign to remaining_letters. This will assignment will happen every time as there will be a letter in the alphabet that does not match the curent secretWord letter.
To fix this, you will need do something like this (note the inversion of the loops):
int secret_len = strlen(secretWord); // cache length, so we don't recalculate it
// every time: secretWord does not change
for(int j=0; j<ALPHABETSIZE; j++)
{
bool found = false; // assume the current ABC letter is not in secretWord
for(int i=0; i<secret_len; i++)
{
if(secretWord[i]!=alphabet[j])
{
found = true; // but it was
}
}
if (!found) // if it wasn't
{
remaining_letters[j]=alphabet[j];
}
}
Your main problem is that you do not keep the vowels count in the class member vowel_count. You store it in a local variable vowel_count and return it but the class member is never updated.