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.
Related
I've been trying to figure out why my code isn't working correctly for the past few hours. Everything looks perfectly fine to me unless it's something I don't know about. I have asked my professor, but he can't seem to figure it out either. This code will completely ignore the if else statement in the push member function and will keep pushing after reaching the limit (in this case it's 5 elements). When it goes over the 5th element, and I check for the top, it shows the first implementation (element 0). I tried changing around my code by switching the member functions outside the class via scope resolution, but it's still no use. A different set of eyes would be greatly appreciated.
#include <iostream>
#include <cctype>
using namespace std;
class Stack
{
private:
static const int size = 5;
double myarr[size];
int t;
public:
Stack() { t = -1; }
void push(double element);
void pop();
void top();
void menu();
};
void Stack::push(double element)
{
if (t < size) {
t++;
myarr[t] = element;
}
else
cout << "Stack Limit Reach !!!" << endl;
}
void Stack::pop()
{
if (t >= 0) {
cout << "Element : " << myarr[t] << " was popped off the Stack " << endl;
t--;
}
else
cout << "No more elemnts in the Stack !!!" << endl;
}
void Stack::top()
{
if (t >= 0) {
cout << "Element : " << myarr[t] << " is at the top of the Stack " << endl;
}
else
cout << "No more elemnts in the Stack !!!" << endl;
}
void Stack::menu()
{
char choice = 'y';
int pick;
double elem;
while (toupper(choice) == 'Y');//while(choice == 'y' || choice == 'Y');
{
cout << "1. Push" << endl;
cout << "2. Pop" << endl;
cout << "3. Top" << endl;
cout << "4. Exit" << endl;
cin >> pick;
switch (pick)
{
case 1:
cout << "Enter the element: ";
cin >> elem;
cout << endl;
push(elem);
break;
case 2:
pop();
break;
case 3:
top();
break;
case 4:
choice = 'N';
break;
default:
cout << "Please select 1-4" << endl;
}
system("pause");
}
}
int main()
{
Stack obj;
obj.menu();
};
In your example code, the stack's size is 5 (which means array myarr has valid indices 0 through 4).
void Stack::push(double element)
{
if (t < size) {
t++;
myarr[t] = element;
}
else
cout << "Stack Limit Reach !!!" << endl;
}
Consider the case when t here is 4. The if tests true, so the block to add to myarr is entered. First thing that happens is you increment t, which is now 5. Then you use that as the index to store the value into myarr, which is out of bounds.
Try something like:
void Stack::push(double element)
{
if (t < size) {
myarr[t++] = element;
}
else
cout << "Stack Limit Reach !!!" << endl;
}
You are allowing 6 elements to be pushed onto the stack, and there's only room for 5.
Change:
if (t < size) {
t++;
to:
if (t < size-1) {
t++;
I understood your problem when you are searching for the top element you are not getting because whenever the stack becomes full for ex:-
assume you are inserting(below mentioned code) 5th element in 4th index it will be inserted and the value of t get incremented to 5 due to t++.
void Stack::push(double element)
{
if (t < size) {
t++;
myarr[t] = element;
}
else
cout << "Stack Limit Reach !!!" << endl;
}
but at the same time when you call top() function it checks for the index, and obviously 5 is greater that 0 so it enters the loop but index 5 contains '\0'
Character so there is an ambiguity with compiler
void Stack::top()
{
if (t >= 0) {
cout << "Element : " << myarr[t] << " is at the top of the Stack " << endl;
}
else
cout << "No more elemnts in the Stack !!!" << endl;
}
So the change that is required for the above code is just put a if statement by saying the compiler that if the stack is full then decrement t value by 1
void Stack::top()
{
if (t >= 0) {
if(t==size){t--;}
cout << "Element : " << myarr[t] << " is at the top of the Stack " << endl;
}
else
cout << "No more elemnts in the Stack !!!" << endl;
}
This may give you correct result
You skip myarr[0] then 5th element is saved to myarr[5] that is 6th element in myarr! (Accessing to elements of an array by index is zero based in C++)
Change:
Stack() { t = -1; }
to:
Stack() { t = 0; }
and
if (t < size) {
t++;
myarr[t] = element;
to:
if (t < size) {
myarr[t++] = element;
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++.
I have a small program in which I have two structs:
Person - Consists of id, and basic methods
Ppl - Consists of an array of people with some methods to operate on the array.
struct Person {
const int id;
Person();
Person(int a);
};
Person::Person(int a) : id(a) {}
This is the Person struct with its methods.
const int MAX = 5;
Sets limit on array length
struct Ppl {
static int current; //Keeps track of current position in array
Person *ppls[MAX]; //Creates an array of Person structure pointers
void add(int a); //Adds a person with id to the next available position
//void remove(int b);
int searchid(int c); //Searches ppls for an id c.
Ppl(); //Constructor
};
int Ppl::current = 0; //Initializing static variable
void Ppl::add(int a) {
int ret = searchid(a); //Determine if id a already exists in ppls
//cout << "Ret: " << ret << endl;
if (ret > MAX) { //If value returned is > MAX, value exists
cout << "User " << a << " already exists" << endl;
} else { //else, add it to the next available spot
Person p(a);
ppls[current] = &p;
cout << "Added user: " << a << " at index: " << current << endl;
current++;
}
}
Ppl::Ppl() {
current = 0;
int i = 0;
while (i < MAX) { //Sets all Person pointers to NULL on initialization
ppls[i] = NULL;
cout << "ppls[" << i << "] is NULL" << endl;
i++;
}
}
int Ppl::searchid(int c) {
int i = 0;
bool found = false;
while(i < MAX) {
if (ppls[i] == NULL) { //If NULL, then c wasn't found in array because
break; //there is no NULL between available spots.
} else {
if (ppls[i]->id == c) {
found = true;
}
}
i++;
}
if (found == true) {
return 10; //A number higher than MAX
} else {
return 1; //A number lower than MAX
}
}
The main function is:
int main() {
Ppl people;
people.add(21);
cout << people.ppls[0]->id << endl;
people.add(7);
cout << people.ppls[0]->id << " ";
cout << people.ppls[1]->id << endl;
people.add(42);
cout << people.ppls[0]->id << " ";
cout << people.ppls[1]->id << " ";
cout << people.ppls[2]->id << endl;
people.add(21);
cout << people.ppls[0]->id << " ";
cout << people.ppls[1]->id << " ";
cout << people.ppls[2]->id << " ";
cout << people.ppls[3]->id << endl;
}
The output that I get is:
ppls[0] is NULL
ppls[1] is NULL
ppls[2] is NULL
ppls[3] is NULL
ppls[4] is NULL
Added user: 21 at index: 0
21
Added user: 7 at index: 1
7 0
Added user: 42 at index: 2
42 0 0
Added user: 21 at index: 3
21 0 0 0
Why is it adding all new entries to the beginning of the array while keeping the rest NULL?
Why isn't it detecting that 21 was already added.
I have been going crazy trying to figure this out. Any help would be much appreciated.
Thanks a lot community.
EDIT
I have fixed it so that it adds the elements to the array and recognizes when an id exists.
I made changes to the Ppl struct by adding a destructor:
Ppl::~Ppl() {
int i = 0;
while (i < MAX) {
delete ppls[i];
i++;
}
}
and by changing the add method.
void Ppl::add(int a) {
int ret = searchid(a);
//cout << "Ret: " << ret << endl;
if (ret > MAX) {
cout << "User " << a << " already exists" << endl;
} else {
**Person *p = new Person(a);
ppls[current] = p;**
cout << "Added user: " << a << " at index: " << current << endl;
current++;
}
}
So the output now is
ppls[0] is NULL
ppls[1] is NULL
ppls[2] is NULL
ppls[3] is NULL
ppls[4] is NULL
Added user: 21 at index: 0
21
Added user: 7 at index: 1
21 7
Added user: 42 at index: 2
21 7 42
User 21 already exists
Segmentation fault (core dumped)
What is a segmentation fault and how can I fix it?
Thanks again
Person p(a);
ppls[current] = &p;
is a problem. You are storing a pointer to a local variable. Your program is subject to undefined behavior.
Use
Person* p = new Person(a);
ppls[current] = p;
Make sure to delete the objects in the destructor of Ppl.
Suggestion for improvement
It's not clear what's your objective with this program but you can make your life a lot simpler by using
std::vector<Person> ppls;
instead of
Person *ppls[MAX];
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);.
I have been struggling with the output of a linear search algorithm for a bit of time now. I have the function that searches the list and returns the position, either -1 if it is not found, or the numeric value of where the matching number was found. Any suggestions on how to get this to output correctly?
The output needs to search through testList, see if that number is in stdList, and give its position
Number 1 (34) was located in position 15.
Number 2 (74) was not in the file.
Number 3 (56) was not in the file.
Number 4 (103) was located in position 75.
etc.
Here is the main section of code that I am having problems with.
ARRAY_STANDARD is referring to the size of the array stdList.
stdList is the array being compared against
Position is what is being returned by the function searchList()
testList is referring to the array that is being compared to stdList
value is the element that we are searching for
//Outputs
if (position == -1)
cout << "Number " << testCount+1 << "(" << testList << ")" << " was not in the file." << endl;
else
cout << "Number " << testCount+1 << "(" << testList << ")" << " was located in position " << value << endl;
}
int searchList(int stdList [], int numElems, int value)
{
int index=0;
int position = -1;
bool found = false;
while (index < numElems && !found)
{
if (stdList[index] == value)
{
found = true;
position = index;
}
index++;
}
return position;
}
You seem to have lost a few lines of code in the last edit. What you want to do (pseudo code) is this:
for each element in testList: <<<<< this is the for statement you lost
position = findElement(element, stdList) <<<<< this is the function you were not calling
if(position < 0):
print "not found"
else:
print "found element " element " at position " position
Take it away...
You should change your method in following way:
int searchList(int stdList [], int numElems, int value)
{
int index=0;
while (index < numElems)
{
if (stdList[index] == value)
{
return index;
}
index++;
}
return -1;
}
int searchList(int stdList [], int value)
{
for(int i = 0, length = sizeof(stdList); i < length; ++i)
{
if (stdList[i] == value)
return i;
}
return -1;
}
Successful output.
int results;
for(int i = 0; i < 22; i++)
{
results = searchList(stdList, ARRAY_STANDARD, testList[i]);
if (results == -1)
cout << "Number " << i+1 << "(" << testList[i] << ")" << " was not in the file." << endl;
else
cout << "Number " << i+1 << "(" << testList[i] << ")" << " was located in position " << results+1 << endl;
}