implementation of stacks using vector - segmentation fault in peek() function - c++

#include <iostream>
#include <vector>
using namespace std;
class Stack{
public:
vector<string> vc;
int length=0;
void peek(){
if(vc.size()==0){
cout<< "The stack is empty"<<endl;
}
cout<< vc[length]<<endl; //----> does not work;
//cout<<vc[vc.size()-1]; ---> does not work either
//cout<<vc.end(); ----> does not work either;
}
void add(string value){
vc.push_back(value);
length++;
}
void pop(){
vc.erase(vc.end());
length--;
}
void show(){
for (int i=0;i<vc.size();i++){
cout << vc[i] << " ";
}
cout<<endl;
}
};
int main()
{
Stack mystack;
mystack.peek();
mystack.add("Hello");
mystack.peek();
mystack.add("frands");
mystack.add("chai");
mystack.add("pee");
mystack.add("lo");
mystack.show();
mystack.peek();
mystack.pop();
mystack.show();
}
problem 1->
the problem arises in the peek() function i cannot access the last element in my vector space i get returned with a segmentation fault(core dump) error.
problem 2->
and while pasting this code on stack overflow i had to manually add 4spaces in each code line how to do this at one step (sorry for a silly question).

There are a few problems in your code:
void peek(){
if(vc.size()==0){
cout<< "The stack is empty"<<endl;
}
cout<< vc[length]<<endl; //----> does not work;
}
If vc.size() == 0, you print out a message, and then proceed to index into the empty vector. You should return inside that if, to avoid looking at an invalid index.
Below it you use use a length variable, which I presume is the acting the role of the vector's size(). EITHER you need to ensure the vector's size is the same as the stack's logical size (and then you don't need a length variable), OR you should be testing if length == 0, and not looking at size() here. Otherwise, you could have a positive size of vector, and a length of zero, and what's logically empty may print junk values.
Another serious mistake, your pop function:
void pop(){
vc.erase(vc.end()); // <<< MISTAKE
length--;
}
This is erasing the "end" element, which is not a valid position to erase. Remember, end denotes the first place after the last valid element in the vector, so your code yields undefined behavior. You should use the vector function pop_back instead, as it does precisely what you want. It also will reduce the size of the vector, meaning you don't need a length variable at all! Instead you can use the vector's size().
Next, in peek():
cout<< vc[length]<<endl;
When a vector contains N things, they are indexed from 0..(N-1). Using the number of elements will go too far into the vector. Instead, use length-1 (or vc.size()-1 after fixing pop()). However, you can use vc.back() to access the last element without any need to compute its offset.

Related

C++: Insert an element in a Vector without insert()

I have been trying to solve the above problem for a friend, everytime the last element of the vector gets removed although I feel that its size should increase dynamically after insertion.
Here's the Code:
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
void display(vector<int> arr){
cout<<"Result"<<endl;
for(auto &p: arr){
cout<<p<<endl;
}
}
void indsert(vector<int> arr, int size, int element, int ind){
for(int i=size+1; i>=ind; i--)
arr[i] = arr[i-1];
arr[ind] = element;
display(arr);
}
int main()
{
int ind,size,element;
cout<<"Enter the size of the array"<<endl;
cin>>size;
vector<int> arr;
cout<<"Enter the elements of the array"<<endl;
for(int i=0;i<size;i++){
int temp;
cin>> temp;
arr.push_back(temp);
}
cout<<"Enter the element to be inserted"<<endl;
cin>>element;
cout<<"Enter the index"<<endl;
cin>>ind;
indsert(arr, size, element, ind);
return 0;
}
You have two problems.
The first is with the function signature:
void indsert(vector<int> arr, ...)
You pass the vector by value. That means a copy of the vector is made, and that copy is passed to the function.
You can modify this copy as much as you want, but the original vector will still not change.
You need to pass the vector by reference:'
void indsert(vector<int>& arr, ...)
// ^
// Note ampersand here, making this a reference
The second problem is much worse: You seem to assume that you can insert into a vector using the [] operator. That's not what's happening.
Instead you go out of bounds of the vector, which leads to undefined behavior.
You need to explicitly resize the vector, either using insert, push_back/emplace_back, or resize.
Also remember that since indexes are zero-based, the top-index is the same as the vector size minus one. Using the vector size as index will be out of bounds. Using the vector size plus one is even more out of bounds.
Your code exhibits undefined behaviour. You are accessing arr[size+1] in a vector arr of size size. Such a vector has values at positions 0 up to and including size-1.
If you want to append a value, use std::vector::push_back(). Alternatively you can std::vector::resize() the vector beforehand.
Also, you don't need to pass the size argument because std::vector::size() will tell you the current size of the vector. Furthermore, as has been pointed out to you, pass the vector by reference to avoid copying data for no reason.

Segfault in my stack implementation (C++) code, but cannot understand why

To set the record straight, I am fairly new to C++ and most of my experience in programming is in Java. I'm writing an array based stack implementation and I cannot seem to read any of the data saved in my stack.
Objects can be pushed and this seems to function normally. Commenting out the top() operation yields a successful output of zero, which seems to tell me that I know the item is at least being added to the array.
However, reading the item, I get a segfault error. After a quick google or two, I learned that a segfault means that there is an operation accessing data it does not have access to. This leads me to think that my top() function does not have access to the array. It is a private member of the class, but my previous knowledge of OOP tells me that a class method should have access to all private variables.
Could anyone help point me in the right direction here? (Apologies if the documentation is a bit excessive for such a primitive data structure, let me know if it should be removed).
Thanks! Code is below:
#include <iostream>
using namespace std;
/*
Class: arrayStack()
A simple stack implemented with a single array.
Handles char objects.
*/
class arrayStack {
int length; //cap on stack length
int count; //Keeps track of which element in the array to pop from.
char array[]; //Hold data here
public:
/*
arrayStack()
Constructor used to create a stack object. No default constructor exists, the length (l) is a required argument as a parameter to create a stack.
l space is reserved in the array and count is set to -1, the int value required for an empty stack.
*/
arrayStack(int l)
{
char array[l];
length = l;
count = -1;
}
/*
push() -- return type void.
Method to add a desired char element (o) to the stack.
*/
void push(char o)
{
array[count] = o;
count++; //Increment the counter to accurately pull element from array.
}
/*
pop() -- return type char.
Method to remove an element from the stack. Element is pulled from the stack and returned.
*/
char pop()
{
//temp space to store pulled element before returning.
char temp;
temp = array[count];
//Replace popped element with null to reduce memory waste. Then decrement counter for proper functioning of the stack.
array[count] = '\0';
count--;
return temp;
}
/*
top() -- return type char.
Method which returns the top element of the function without deleting it from the stack. Useful for inspection and testing, but functionally very similar to pop().
*/
char top()
{
//temp space to store pulled element.
char temp;
temp = array[count];
return temp;
}
/*
isEmpty() -- return type boolean.
Method which checks the stack for elements. If there are no elements, the method returns true. If there exists one or more elements, the method will return false.
Method is very simple-- a simple check against the count (int) variable.
*/
bool isEmpty()
{
if (count == -1) {
return true;
} else {
return false;
}
}
/*
size() -- return type int.
Method which returns the number of elements in the stack.
*/
int size()
{
return count++;
}
};
int main() {
arrayStack stack(10);
stack.push('c');
cout << stack.top(); //SEGFAULT OCCURS HERE.
cout << stack.isEmpty();
return 0;
}
Your member array is still uninitialized:
arrayStack(int l)
{
char array[l];
length = l;
count = -1;
}
Here, you create a new array (which I doubt is legal anyway, since C++ doesn't support VLA's. It should probably be
arrayStack(int l)
{
array = new char[l];
length = l;
count = -1;
}
You also need to implement a destructor to delete the allocated memory. Which means you also need a copy constructor and copy assignment operator.

Vector <int> input and output

I am stuck with simple vector input and output operations. The compiler returns error saying 'std::outof range'
Here is the code
int main()
{
int size;
cout <<"Enter size of vector\n";
cin>>size;
cout<<"Now to input the vector of size "<<size<<endl;
vector <int> trial;
for (size_t i=0;i<size;++i){
int x;
cout<<"write at position"<<trial.at(i)<<'t';
cin>>x;
trial.push_back(x);
cout<<endl;
}
ostream_iterator<int> output(cout,"");
copy(trial.begin(),trial.end(),output);
}
I would appreciate a brief explanation of the internal workings of the problem.
You invoke trial.at(i) before trial.push_back(x), accessing a not yet existing element. Since the element doesn't (yet) exist, i is an invalid index, and at() will throw a std::out_of_range exception when passed an invalid index. If an exception isn't caught, it will terminate the program. Presumably your platform's runtime library displays the exception that caused the program to be terminated.
I suppose what you actually want is this:
std::cout << "write at position " << i << '\t';
Consider the first iteration of this loop:
vector <int> trial;
for (size_t i=0;i<size;++i){
int x;
cout<<"write at position"<<trial.at(i)<<'t';
At the first iteration nothing has been pushed into the vector, so trial.at(0) isn't yet valid. The result will be an exception. Since you don't have a try/catch anywhere, that will end your program's execution.
It looks to me like you want cout << "write at position " << i; instead. i is the position; after it has been pushed onto the vector so it's valid, vector.at(i) will be the value at that position.
trial.at(i)
You're accessing an element that doesn't exist.
You probably want cout<<"write at position"<< i <<'t'; anyway.
The problem is this line:
cout<<"write at position"<<trial.at(i)<<'t';
You call this before you have set the size of the vector. I'm not really sure what that line is trying to accomplish anyway. If you're trying to print the in memory position (address) that won't do it, if you're trying to print what was already there then it would work if it had already been allocated. Using vector::push_back() means that you don't need to preallocate though.
You can fix this by resizing the vector and accessing the elements directly like this:
trial.resize(size);
// loop
// vector.push_back(x) -- now becomes
vector[i] = x;
Or, you can simply remove the printing of the position and use push_back() as you are now.
Since it seems you're investigating how to use vector I would suggest trying to gain an understanding of how the push_back() and resize() methods differ, and have also have a look at the vector::reserve() function.

stl map, set error: memory clobbered past end of allocated block

As I tried to solve this interview problem: find the sum of continuous element in an array which equals to a target number, so I come up with the following code. However, I really don't understand why it has some memory allocation problem. Here is the link to the full code. when I tried to insert the second element of currSum into the set and map, it will have some error message like "memory clobbered past end of allocated block". Isn't set, map dynamically allocated for insert? I really don't understand why it's not working as I think.
I also paste the full code here:
#include <map>
#include <set>
#include <iostream>
using namespace std;
void print_array(int arr[], int start, int end)
{
for(int i=start;i<=end;i++)
cout<<arr[i]<<" ";
cout<<endl;
}
//given an array, find the continous sum of the array which is a target number
void findTargetSum(int arr[], int target, int sizeArr)
{
map<int, int> valIdxMap;
set<int> prevSet;
int* currSum= new int(sizeArr+1);
currSum[0]=0;
for(int i=1;i<=sizeArr;i++)
{
currSum[i]=currSum[i-1]+arr[i-1];
}
//now the problem is to find two elements i, j in array currSum,where currSum[j]-currSum[i]=target && j>i
for(int i=0; i<=sizeArr;i++)
{
int tmp=currSum[i]-target;
set<int>::iterator iter=prevSet.find(tmp);
if (iter !=prevSet.end())
{
cout<<"located one range of array elements with sum to"<<target<<endl;
int startIdx=valIdxMap[*iter];
print_array(arr,startIdx,i-1);
}
else
{
prevSet.insert(currSum[i]);
valIdxMap.insert(make_pair(currSum[i],i));
}
}
delete currSum;
}
void testfindTargetSum()
{
int tst_arr[]={2,4,5,-1,3,8};
int target=11;
findTargetSum(tst_arr,11,6);
}
int main()
{
testfindTargetSum();
return 1;
}
The error is in this line:
int* currSum= new int(sizeArr+1);
That line acquires a single int and initializes it to the value sizeArr+1. You probably meant:
int* currSum= new int[sizeArr+1];
That will acquire a block of sizeArr+1 elements of type int. Additionally you will have to change the line delete currSum; to be delete [] currSum;.
My advice, on the other hand, would be not to manage memory manually but use a standard container, for example:
std::vector<int> currSum( sizeArr+1 );
Will basically be an in-place replacement for your current implementation and it will manage memory automatically.
As of the implementation, I believe that you can actually do it without any extra memory in O(N) by accumulating the start index, end index and sum of the values in three variables while iterating. While the accumulated value is smaller than the target, increment the end index and add the value. When the accumulated value grows higher than the target, increment the start index and decrement the accumulated value by that amount.
you wrote
int* currSum= new int(sizeArr+1);
you probably meant
int* currSum= new int[sizeArr+1];

While inserting nodes in heap how to use bubble up?

Following is my code which doesnot properly bubbles up the larger value .Can any one help out .The problem is somewhat at count++ .
#include<iostream>
using namespace std;
class heap{
public:
int count;
heap(int c)
{
count=c;
}
int Arr[10];
void insert(int num);
void deletemax();
void print();
};
void heap::insert(int num){
if(count==10){
cout<<"Heap full\n";
exit(1);
}
else{
Arr[count]=num;
count++; //The real problem arises here that the compiler adds 1 to count and when the code moves ahead it sets position var to count++ value and tries to compare a value at Arr[POS] with its parent whereas there is no value at this place set uptill.
}
int POS=count;
while(Arr[POS]>Arr[(POS-1)/2]){
int temp;
temp=Arr[POS];
Arr[(POS-1)/2]=temp;
POS=(POS-1)/2;
}
}
void heap::print(){
for(int i=0; i<10; i++){
cout<<Arr[i]<<endl;
}
}
int main(){
heap h(0);
int a;
int b=0;
while(b<10){
cout<<"Insert node in heap\n";
cin>>a;
h.insert(a);
b++;
}
h.print();
return 0;
}
I would agree, that's where your problem is.
There are many issues with the code you posted, some of which include:
As to your specific issue, I would guess you need to change the line in heap::insert() to "int POS=count-1;" to properly start iterating from the back of the array.
You need to consider the case of adding an element to an empty array and what then happens in your sorting code.
Your constructor allows someone to create a heap that will overflow the fixed sized array, for example heap(1000). In addition, the Arr member is not initialized which means it has undefined data for any value but heap(0). In this case your constructor should not take any parameters and count should just be initialized to 0.
The purpose of the code is confusing. Is it a heap, a sorted array, an attempt to approximate a heap with an array, none of the above? If you are simply trying to implement a fixed sized sorted array then I believe your sorting code in insert() will not work (e.g., consider adding 100 to a heap containing [1,2,3]).
There are other, more basic things, wrong (like not using any the STL containers, public class member, non-const parameter passing, "using std", etc...) but I'm assuming you are merely experimenting/playing here.