Below I have my two functions which are, when when insertItem calls findIndex producing a segmentation fault. For some reason this happens when the value is returned. (I will include the cout statements so that it is easy to see exactly where this error happens). I am trying to locate the index of a value which is not in the list so -1 should be returned but never does. The output is below.
template <class ItemType>
int SortedList<ItemType>::findIndex(ItemType item) {
cout << "Entering findIndex function" << endl;
int first = 0;
int last = length-1;
int middle;
bool found = false;
while(!found) {
middle = (first+last)/2;
cout << "In findIndex, this is middle: " << middle << " and this is the item: " << item << " and this is the length: " << length << endl;
if(info[middle] == item) {
cout << "In findIndex found is now true" << endl;
found = true;
}
else if(item < info[middle])
last = middle-1;
else// if(item > info[middle])
first = middle+1;
if(first > last)//else// if(first > last)
break;
}
cout << "About to exit and return value from findIndex function" << endl;
if(found == true) {
cout << "findIndex Function: the index of the found value was " << middle << endl;
return middle;
}
else {
cout << "findindex Function: -1 was returned" << endl;
return -1;
}
}
template <class ItemType>
void SortedList<ItemType>::insertItem(ItemType item) {
cout << "Inside insertItem function, length: " << length << endl;
if(findIndex(item) != -1)
cout << "**Item already in the list" << endl;
else if(length == Max_Items)
cout << "**There is no room in the list" << endl;
else {
cout << "before the try" << endl;
try{
cout << "This is length at the start of the insertItem function: " << length << endl;
if(length == 0) {//if the list is empty item becomes the first item in the list \
cout << "This is right after length==0 in insertItem function" << endl;
info[0] = item;//was this->inf...
length++;
cout << "This is length right after incrementing it up" << length << endl;
}
else {//its not the first item in the list
for(int i = 0; i <= length; i++) {
cout << "This is the length and i respectively right inside the for in insertItem" << length << " " << i << endl;
if(i == length) {
cout << "this is where i == length" << endl;
info[i] = item;
length++;
break;
}
if(info[i] < item)
continue;
//inserting the item where it needs to go
for(int p = length; p > i; p--) {//was >=
info[p] = info[p-1];
}
//item = info[i];
info[i] = item;
length++;
break;
}
}
}catch(...) {cout << "**insertItem failed" << endl;}
}
cout << "This is length at the end of the insert item function: " << length << endl;
}
output:
...
Inside insertItem function, length: 0
Entering findIndex function
In findIndex, this is middle: 0 and this is the item: Name: Eman ID: 81012 and this is the length: 0
About to exit and return value from findIndex function
findindex Function: -1 was returned
Segmentation fault (core dumped)
~$:
So even the print saying -1 was returned is hit but nothing ever gets back to the original function. I am not sure as to what could cause a seg fault in this area. Could this return do it?
The following loop:
for(int p = length; p > i; p--) {
info[p] = info[p-1];
probably writes to 1 index past the length of the array, because valid array indexes probably range from 0 to length - 1.
A write to an illegal memory location can corrupt the stack, and this is likely to manifest as a crash when returning from a function.
Still, you really need to start using a debugger.
Goal state: I'm supposed to display a result where by randomized e.g. Set S = {dog, cow, chicken...} where randomized size can be 1-12 and animals cannot be replicated so once there is cow, there cannot be another cow in Set S anymore.
Error: I've been displaying a correct randomized size of 1-12. However I have duplicated animals even though I tried to check whether the animal exist in set S before I insert it into Set S.
UPDATE: I couldnt get it to run after the various updates by stackoverflow peers.
Constraints: I have to use pointers to compare with pointers - dynamically.
"Important Note
All storages used for the arrays should be dynamically created; and delete them when
they are no longer needed.
When accessing an element of the array, you should access it via a pointer, i.e. by
dereferencing this pointer. Using the notation, for example set [k] or *(set + k)
accessing to the kth element of the set is not allowed."
Do hope to hear your advice, pals!
Best regards,
MM
/*
MarcusMoo_A2.cpp by Marcus Moo
Full Time Student
I did not pass my assignment to anyone in the class or copy anyone’s work;
and I'm willing to accept whatever penalty given to you and
also to all the related parties involved
*/
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <ctime>
using namespace std;
/* Global Declaration */
const int MAX = 12; // 12 animals
const int MAXSTR = 10;
typedef char * Element;
static Element UniversalSet [MAX] = {"Rat", "Ox", "Tiger", "Rabbit", "Dragon",
"Snake", "Horse", "Sheep", "Monkey", "Rooster", "Dog", "Pig"};
/* Functions */
// Construct a set
void option0(int); // Menu Option 0
void constructSet (Element *, int); // Construct a set
bool checkElement (Element *, Element *, int); // Check element for replicates
int main()
{
// Declarations
int mainSelect;
int size=rand()%12+1; // Random construct
srand (time(NULL)); // Even better randomization
cout << "Welcome to MARCUS MOO Learning Center" << endl;
do
{
cout << "0. An example of set" << endl;
cout << "1. Union" << endl;
cout << "2. Intersection" << endl;
cout << "3. Complement" << endl;
cout << "4. Subset of" << endl;
cout << "5. Equality" << endl;
cout << "6. Difference " << endl;
cout << "7. Distributive Law" << endl;
cout << "9. Quit" << endl;
cout << endl;
if (mainSelect==0)
{
option0(size);
}
cout << "Your option: ";
cin >> mainSelect;
cout << endl;
} while(mainSelect!=9);
return 0;
}
/* Functions */
// Option 0 - An example of set
void option0 (int size)
{
// Mini Declaration
int again;
Element *S;
do
{
cout << "Here is an example on set of animals" << endl;
cout << endl;
// Build set S
constructSet (S,size);
// Display set S
Element *S = &S[0];
cout << "Set S = {";
for (int i = 0; i < size; i++)
{
if (i!=size)
{
cout << *S
<< ", ";
}
else
{
cout << *S
<< "}"
<< endl;
}
S++;
}
cout << endl;
cout << "Note that elements in S are distinct are not in order" << endl;
cout << endl;
// Option 0 2nd Part
cout << "Wish to try the following operations?" << endl;
cout << "1. Add an element to the set" << endl;
cout << "2. Check the element in the set" << endl;
cout << "3. Check the cardinality" << endl;
cout << "9. Quit" << endl;
cout << endl;
cout << "Your choice: ";
cin >> again;
} while (again!=9);
}
// Construct a set
void constructSet (Element *set, int size)
{
// Declarations
Element *ptrWalk;
ptrWalk = &set[0];
int randomA=0;
for (int i = 0;i<size;i++)
{
bool found = true;
while (found)
{
randomA = rand()%MAX; // avoid magic numbers in code...
*ptrWalk = UniversalSet [randomA];
// Ensure no replicated animals in set S
found = checkElement (ptrWalk, set, i);
}
set=ptrWalk;
set++;
}
}
bool checkElement (Element *ptrWalk, Element *set, int size)
{
for (int j=0; j<size;j++)
{
if (ptrWalk==&set[j])
{
return true;
}
}
return false;
}
You have 2 different major problems in your code. First has already be given by Federico: checkElement should return true as soon as one element was found. Code should become simply (but please notice the < in j<size):
bool checkElement (char *ptrWalk, int size)
{
for (int j=0; j<size;j++)
{
if (ptrWalk==S[j])
{
return true;
}
}
return false;
}
The second problem is that you should not search the whole array but only the part that has already been populated. That means that in constructSet you should call checkElement(ptrWalk, i) because the index of current element is the number of already populate items. So you have to replace twice the line
found = checkElement (*ptrWalk, size);
with this one
found = checkElement (*ptrWalk, i);
That should be enough for your program to give expected results. But if you want it to be nice, there are still some improvements:
you correctly declared int main() but forgot a return 0; at the end of main
you failed to forward declare the functions while you call them before their definition (should at least cause a warning...)
you make a heavy use of global variables which is not a good practice because it does not allow easy testing
your algorithms should be simplified to follow the Dont Repeat Yourself principle. Code duplication is bad for future maintenance because if forces to apply code changes in different places and omission to do so leads to nasty bugs (looks like this is bad but I've already fixed it - yes but only in one place...)
constructSet could simply be:
// Construct a set
void constructSet (Element *set, int size)
{
// Declarations
//Element *ptrBase;
voidPtr *ptrWalk;
ptrWalk = &set[0];
int randomA=0;
for (int i = 0;i<size;i++)
{
bool found = true;
while (found) {
randomA = rand()%MAX; // avoid magic numbers in code...
*ptrWalk = UniversalSet [randomA];
// Ensure no replicated animals in set S
found = checkElement (*ptrWalk, i);
}
ptrWalk++;
}
}
Main problem is that 'break' is missing in checkElement() once it finds the element. If you do not break the loop, it will compare with other indices and overwrite the 'found' flag.
if (ptrWalk==S[j])
{
found = true;
break;
}
Also, use ptrWalk as temporary variable to hold the string. Add the string to S only after you make sure that it is not present already.
void constructSet (Element *set, int size)
{
// Declarations
//Element *ptrBase;
Element ptrWalk;
//ptrWalk = &set[0];
int randomA=0;
int randomB=0;
bool found = false;
for (int i = 0;i<size;i++)
{
randomA = rand()%12;
ptrWalk = UniversalSet [randomA];
// Ensure no replicated animals in set S
found = checkElement (ptrWalk, i);
if (found==true)
{
do
{
// Define value for S
randomB = rand()%12;
ptrWalk = UniversalSet [randomB];
found = checkElement (ptrWalk, i);
} while(found==true);
S[i] = UniversalSet [randomB];
//ptrWalk++;
}
else
{
// Define value for S
S[i] = UniversalSet [randomA];
//ptrWalk++;
}
}
}
You need to optimize your code by removing unnecessary variables and making it less complex.
I have fixed this with the guidance of my C++ lecturer! You guys may take a reference from this to solve your pointers to pointers dilemma next time! Cheers!
/*
MarcusMoo_A2.cpp by Marcus Moo
Full Time Student
I did not pass my assignment to anyone in the class or copy anyone’s work;
and I'm willing to accept whatever penalty given to you and
also to all the related parties involved
*/
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <ctime>
using namespace std;
/* Global Declaration */
const int MAX = 12; // 12 animals
const int MAXSTR = 10;
typedef char * Element;
static Element UniversalSet [MAX] = {"Rat", "Ox", "Tiger", "Rabbit", "Dragon",
"Snake", "Horse", "Sheep", "Monkey", "Rooster", "Dog", "Pig"};
/* Functions */
// Construct a set
void option0(int); // Menu Option 0
void constructSet (Element *, int); // Construct a set
bool checkElement (Element, Element *, int); // Check element for replicates
// This function is to get a random element
// with storage allocated
Element getAnElement ()
{
Element *p = &UniversalSet [0];
int k = rand () % MAX;
for (int i = 0; i < k; i++)
++p;
Element e = new char [MAXSTR];
strcpy (e, *p);
return e;
}
int main()
{
// Declarations
int mainSelect;
int size=rand()%12; // Random construct
srand (time(NULL)); // Even better randomization
cout << "Welcome to MARCUS MOO Learning Center" << endl;
do
{
cout << "0. An example of set" << endl;
cout << "1. Union" << endl;
cout << "2. Intersection" << endl;
cout << "3. Complement" << endl;
cout << "4. Subset of" << endl;
cout << "5. Equality" << endl;
cout << "6. Difference " << endl;
cout << "7. Distributive Law" << endl;
cout << "9. Quit" << endl;
cout << endl;
if (mainSelect==0)
{
option0(size);
}
cout << "Your option: ";
cin >> mainSelect;
cout << endl;
} while(mainSelect!=9);
return 0;
}
/* Functions */
// Option 0 - An example of set
void option0 (int size)
{
// Mini Declaration
int again;
Element *S;
// You need to assign storage
S = new Element [MAX];
for (int i = 0; i < MAX; i++)
S [i] = new char [MAXSTR];
do
{
cout << "Here is an example on set of animals" << endl;
cout << endl;
// Build set S
constructSet (S,size);
// Display set S
Element *p = &S[0]; // Change to p
cout << "Set S = {";
for (int i = 0; i < size; i++)
{
if (i!=size-1)
{
cout << *p
<< ", ";
}
else
{
cout << *p
<< "}"
<< endl;
}
p++;
}
cout << endl;
cout << "Note that elements in S are distinct are not in order" << endl;
cout << endl;
// Option 0 2nd Part
cout << "Wish to try the following operations?" << endl;
cout << "1. Add an element to the set" << endl;
cout << "2. Check the element in the set" << endl;
cout << "3. Check the cardinality" << endl;
cout << "9. Quit" << endl;
cout << endl;
cout << "Your choice: ";
cin >> again;
} while (again!=9);
}
// Construct a set
void constructSet (Element *set, int size)
{
// Declarations
Element *ptrWalk;
ptrWalk = &set[0];
int randomA=0;
Element temp = new char [MAXSTR];
for (int i = 0;i<size;i++)
{
bool found = true;
while (found)
{
// randomA = rand()%MAX; ..
temp = getAnElement ();
// Ensure no replicated animals in set S
found = checkElement (temp, set, i);
}
// set=ptrWalk;
// set++;
strcpy (*ptrWalk, temp);
++ptrWalk;
}
}
bool checkElement (Element ptrWalk, Element *set, int size)
{
Element *p = &set[0];
for (int j=0; j<size;j++)
{
if (strcmp (ptrWalk, *p) == 0)
{
return true;
}
p++;
}
return false;
}
So here is my working code for a simple dynamic array. This has to be a sample code for a very entry level data structure implementation:
#include <iostream>
using namespace std;
class AdvancedArray {
public:
AdvancedArray();
~AdvancedArray();
int get_size() const; // get the number of elements stored
double& at(int idx) const; // access the element at idx
void push_back(double d); // adds a new element
void remove(int idx); // remove the element at idx
void clear(); // delete all the data stored
void print() const;
private:
double* elements;
int size;
};
int main()
{
AdvancedArray* arr = new AdvancedArray();
cout << "The Array Size is: " << arr->get_size() << endl;
cout << "Pusing Values: 1.2, 2.1, 3.3, 4.5 in the Array. " << endl;
arr->push_back(1.2);
arr->push_back(2.1);
arr->push_back(3.3);
arr->push_back(4.5);
arr->print();
cout << "The Array Size is: " << arr->get_size() << endl;
cout << "The Element at Index 2 is: " << arr->at(2) << endl;
cout << "Deleting Values: 2.1 from the Array. " << endl;
arr->remove(1);
cout << "The Array Size is: " << arr->get_size() << endl;
arr->print();
cout << "Clearing the Array: " << endl;
arr->clear();
cout << "The Array Size is: " << arr->get_size() << endl;
arr->clear();
return 0;
}
AdvancedArray::AdvancedArray()
{
size = -1;
elements = new double[100]; //Maximum Size of the Array
}
AdvancedArray::~AdvancedArray()
{
delete[] elements;
}
int AdvancedArray::get_size() const
{
if(size < 0)
{
return 0;
}
return size;
}
double & AdvancedArray::at(int idx) const
{
if (idx < 100 && idx >= 0 && size > 0) {
return elements[idx];
}
cout << "Index Out of Bounds." << endl;
}
void AdvancedArray::push_back(double d)
{
if (size >= 100)
{
cout << "Overflow Condition. No More Space!" << endl;
}
else
{
elements[++size] = d;
cout << "Element Pushed In Stack Successfully!" << endl;
}
}
void AdvancedArray::remove(int idx)
{
if (size >= 100 || size < 0)
{
cout << "No Such Element Exists!" << endl;
}
else
{
for(int i = idx; i <size; i++)
{
elements[idx] = elements[idx + 1];
}
size--;
cout << "Element Deleted In Stack Successfully!" << endl;
}
}
void AdvancedArray::clear()
{
delete[] elements;
size = -1;
}
void AdvancedArray::print() const
{
cout << "[ ";
for(int i = 0; i <= size; i++)
{
cout << elements[i] << " ";
}
cout << "]" << endl;
}
So every time I try to run this I have the 2 problems:
What is wrong with my code? Why is the heap getting corrupted (I searched about the error code and that's all has to say)? Is my code doing some major access violations? I am using VS2015.
You do delete [] elements three times without setting elements to nullptr in between. That leads to undefined behavior the second time (and third) time.
When size == 99, the following piece of code attempts to access elements[100]:
if (size >= 100)
{
cout << "Overflow Condition. No More Space!" << endl;
}
else
{
elements[++size] = d;
cout << "Element Pushed In Stack Successfully!" << endl;
}
You need to change ++size to size++.
Below is the code for STACK with no overflow since I am using vector concept. Program seems to be working fine as long as I push integers, but as soon as I push float value (for testing) the output screen goes to infinite loop and debugger doesn't even stop at cin statement and it simply crosses it without giving the control to the console window.
#include"iostream"
class Mystack
{
private:
int *input;
int top;
int capacity;
public:
Mystack();
~Mystack();
void push(int x);
int pop();
int topElement() const;
bool isEmpty() const;
void print();
};
Mystack::Mystack()
{
top = -1;
capacity = 5;
input = new int[capacity];
}
Mystack::~Mystack()
{
delete[]input;
}
void Mystack::push(int x)
{
if (top + 1 == capacity)
{
int *vec = new int[capacity+capacity];
for (int i = 0; i <=top; i++)
{
vec[i] = input[i];
}
input = vec;
capacity = capacity * 2;
top++;
input[top] = x;
}
else
{
top++;
input[top] = x;
}
}
int Mystack::pop()
{
if (isEmpty())
{
throw std::out_of_range("Stack Underflow");
}
else
{
std::cout << "The popped element is" << input[top];
return input[top--];
}
}
bool Mystack::isEmpty() const
{
if (top == -1)
{
std::cout << "Is Empty" << std::endl;
return true;
}
else
{
std::cout << "Not Empty" << std::endl;
return false;
}
}
int Mystack::topElement() const
{
if (top == -1)
{
throw std::out_of_range("No Element to Display");
}
else
{
std::cout << "The top element is : " << input[top];
return input[top];
}
}
void Mystack::print()
{
for (int i = 0; i <= top; i++)
{
std::cout << input[i] << " ";
}
}
int main()
{
Mystack s1;
int num, ch = 1;
while (ch >0)
{
std::cout << "\n1. PUSH" << std::endl;
std::cout << "2. TOP" << std::endl;
std::cout << "3. IsEmpty" << std::endl;
std::cout << "4. POP" << std::endl;
std::cout << "5. EXIT" << std::endl;
std::cout << "6. Print" << std::endl;
std::cout << "Enter the choice" << std::endl;
std::cin >> ch; // DEBUGGER DOES NOT GIVE CONTROL TO CONSOLE WINDOW AND ASK FOR INPUT ONCE I PUT FLOAT VALUES, IT SIMPLE CROSSES IT
switch (ch)
{
case 1:
std::cout << "Enter the number to be pushed" << std::endl;
std::cin >> num;
s1.push(num);
break;
case 2:
std::cout << "Get the TOP Element" << std::endl;
try
{
s1.topElement();
}
catch (std::out_of_range &oor)
{
std::cerr << "Out of Range error:" << oor.what() << std::endl;
}
break;
case 3:
std::cout << "Check Empty" << std::endl;
s1.isEmpty();
break;
case 4:
std::cout << "POP the element" << std::endl;
try
{
s1.pop();
}
catch (const std::out_of_range &oor)
{
std::cerr << "Out of Range error: " << oor.what() << '\n';
}
break;
case 5: exit(0);
case 6:
s1.print();
break;
default:
std::cout << "Enter a valid input";
break;
}
}
std::cin.get();
}
Once you input the int value for example as 1.1 (invalid int value). Input conversion error occurs and the input stream because of invalid data ignores the rest of the operation even the cin. Make your code more generic in order for it to handle float or double or char.
int listRecSearch(list<int>list, const int data)
{
if (list.empty())
{
cout << "The number is not in the list, try again..." << endl;
return -1;
}
else if (list.back() == data)
{
// cout << "list.size(): " << list.size() << endl;
list.pop_back();//I needed the index begins from 0 instead of 1
return list.size();
}
else
{
// cout << "list.back(): " << list.back() << endl;
list.pop_back();
listRecSearch(list, data);
}
}
//funtion used
int main()
{
list<int>list = listGenerator(size);//generate a list with 20 random numbers.
cout << "Specify the element to be searched for: ";
cin >> data;
int position = listRecSearch(list, data);
if (position > -1)
cout << "\nFind the element at position: " << position << endl;
}
The function listRecSearch was able to display correct list.size() value and correct pop_back values. But once it returned, it always return a garbage value. I figured there were steps were still went through after return, but I can't see where and how.
There exists a code path which does not return a value. listRecSearch(list, data); should become return listRecSearch(list, data);.