How to limit the maximum size of vector? - c++

I am trying to use a limited-size buffer like a queue to put some numbers at the back until it gets to a specific size (e.g. 10) and then remove one element from front when a new element is added to the back.
I have used a vector for this purpose, but after several times of running the program (in debug mode) suddenly, I am getting heap corruption errors like:
Critical error detected c0000374
in the middle of the run, and I think it should be related to memory issues, because the error goes away when I reduce the number of vectors.
So far I just use a vector and put the new value to it each time. For example, suppose the code is like this:
#include <iostream>
using namespace std;
vector<int> myvec;
int i = 0;
int main()
{
while(True) {
myvec.push_back(i);
i++;
}
return 0;
}
How can I limit the size of myvec to 10, so that when it contains 10 elements and a new element is being added to it, the first element is removed from the memory?
Is it a good idea to use vectors here, or I should use a queue instead?

You can do something like this->
#include <iostream>
using namespace std;
vector<int> myvec;
int i = 0;
int main()
{
while(True) {
if(myvec.size()==10)
{
myvec.pop_back();
}
myvec.push_back(i);
i++;
}
return 0;
}

Related

computer lab with pointers

I have this assignment with managing computer labs. Specifically, there are 4 labs, each has a different number of computers. Hence, I want to create a 2D array with pointers, but after trying different stuff, I count on you for this error (please!!!). Below is a part of my programme, up to where the annoying bug comes up.
I got a run-time error after 1 run (terminate called after throwing an instance of std::bad_array_new_length what(): std::bad_array_new_length) when I leave the line with comment //PROBLEM HERE as such.
Add a & in front of lab room, the compiler gave me the error: lvalue required as left operand of assignment.
Newbie in C++, first time with pointers, I'd appreciate any help.
#include <iostream>
using namespace std;
//Global variables
const int SIZE = 4;
typedef int* Stations;
Stations *labroom;
//Function declaration:
void numberOfComputers();//Receive number of computers in each lab
int menu();//Display menu options for users
void menu_processor(int option);//process user's option
int main()
{
numberOfComputers();
menu();
menu_processor(menu());
return 0;
}
void numberOfComputers ()
{ char ans;
for (int i=0;i<SIZE;i++)
{
cout<<"Enter the number of computer stations in lab "<<i+1<<": ";
do
{
cin.get(ans);
} while (ans!='\n');
labroom [i] = new int [ans-'0'];//PROBLEM HERE
cout<<"\n";
}
}
That's not c++ code, it's just (ugly) C.
In C++ we have array for static arrays and vector for dynamic arrays.
First of all, choose the name of your variables or function in a smart way: prefer getNumberOfComputersFromUser instead of numberOfComputers. What numberOfComputers means? A function name must describe what it is doing.
Here a simplified snippet:
#include <vector>
#include <array>
#include <iostream>
using namespace std;
using Station = int;
using LabRooms = array<vector<Station>, 4>;
LabRooms getNumberOfComputersFromUser()
{
LabRooms labRooms;
int roomIndex = 0;
for(auto& computersInLab : labRooms)
{
cout << "Enter the number of computer stations in lab " << ++roomIndex << ": ";
auto computerCount = 0;
cin >> computerCount;
computersInLab.resize(computerCount);
}
return labRooms;
}
Explain
array requires two template arguments: the type and the size. Elements are statically allocated, no need to new because we already know how many rooms we have. The list of computers in each room is not know so we use vector that can dynamically increase or decrease.
using LabRooms = array<vector<Station>, 4>; it's the same of typedef array<vector<Station>, 4> LabRooms but it's clearer I think
for( auto& computersInLab : labRooms) iterate over labRooms and get a reference to its elements (in this case a reference to a vector of Station. This is the same of:
for(int i = 0; i < labRooms.size(); ++i)
{
auto& computersInLab = labRooms[i];
...
}
computersInLab.resize(computerCount); resize the list of computers with the value specified from the user.
Now, labRooms is an array of 4 elements, each element is a list of Station.

Segmentation fault during counting of elements in array of strings c++

I am trying to solve an old problem found on topcoder. I am immediately stuck in trying to find the number of elements in an array of strings. Here is my code
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string>
using namespace std;
class MiniPaint {
private:
size_t numLines;
public:
int leastBad(string picture[], int maxStrokes) {
numLines = 0;
while (!picture[numLines].empty()) {
numLines++;
}
cout << numLines << '\n';
return 0;
}
};
int main() {
MiniPaint instance;
string picture[] = {"BBBBBBBBBBBBBBB", "WWWWWWWWWWWWWWW", "WWWWWWWWWWWWWWW", "WWWWWBBBBBWWWWW"};
instance.leastBad(picture, 10);
return 0;
}
This code gives me a segmentation fault. Something is going wrong, the code is a little bit excessive for just the functionality of counting the number of elements but of course I want to extend the class to include more functionality. If anyone can explain what is going wrong here I would be grateful! Thanks in advance.
EDIT: when I expand the code by
cout << picture[numlines] << '\n';
in the while loop, to show the actual elements in the array, first the four proper strings are shown and then somehow it endlessly prints spaces to the terminal. So the problem lies somewhere in the fact that
picture[4].empty()
does not return true, even though picture has only four elements.
Your while loop condition assumes that the last string in the array is empty:
int leastBad(string picture[], int maxStrokes) {
numLines = 0;
while (!picture[numLines].empty()) {
But your input string array defined in main() is not terminated with an empty "" string.
So you may want to add this empty string terminator:
// inside main()
string picture[] = {..., "" /* Empty string terminator */ };
In addition, in modern C++ I'd encourage you to use array container classes instead of raw C-style arrays, typically std::vector<std::string>.
In this case, you can use the size() method to get the array size (i.e. element count), or just a range-for loop for iterating through the whole array.
You access the array out of bounds.
When you call picture[4] you want to access a string object which is not there end the call to the function empty() is on uninitialized memory.
You either need to store how big the array is and iterate until numLines<=3 or you can use a vector
std::vector<std::string> picture = ...
for(std::string line : picture)
{
//do stuff
}
You are out of array bounds at picture[numLines]. You should pass array length or calculate it and check the index numLines. Code will look like:
size_t length = sizeof(picture) / sizeof(*picture); // For VS use _countof macro
while (numLines < length && !picture[numLines].empty())
{
++numLines;
}

c++ double free or corruption (out) error

I am getting error of "Double free or corruption(out)" after I print my output. But this error is only coming for small inputs. For bigger inputs program doesn't throw that error. When I create the multidimensional arrays inside the main and delete them, I do not get the error. I have only posted the part of the code which is relevant to this issue here. Please kindly explain how to resolve the issue.
#include<iostream>
#include<vector>
using namespace std;
class Knapsack{
public:
int noItems, capacity, value, weight;
int *weightArray, *valueArray;
int **ValueMatrix, **BacktrackMatrix;
vector<int> itemsChosen;
~Knapsack();
void getInputs(); // reads in data
void findItems(); // calculates best value of items
void backTrack(int row, int col); // backtracks items selected
void print(); //prints out data
};
Knapsack::~Knapsack()
{
delete[] weightArray;
delete[] valueArray;
for(int i=1;i<=noItems;i++)
{
delete[] ValueMatrix[i];
}
delete[] ValueMatrix;
for(int i=1;i<=noItems;i++)
{
delete[] BacktrackMatrix[i];
}
delete[] BacktrackMatrix;
}
void Knapsack::getInputs()
{
cin>>noItems;
cin>>capacity;
weightArray=new int[noItems];
valueArray=new int[value];
for(int i=1;i<=noItems;i++)
{
cin>>value;
valueArray[i]=value;
}
for(int i=1;i<=noItems;i++)
{
cin>>weight;
weightArray[i]=weight;
}
ValueMatrix=new int*[noItems];
for(int i=1;i<=noItems;i++)
{
ValueMatrix[i]=new int[capacity+1];
}
BacktrackMatrix=new int*[noItems];
for(int i=1;i<=noItems;i++)
{
BacktrackMatrix[i]=new int[capacity+1];
}
}
int main()
{
Knapsack *knap=new Knapsack();
knap->getInputs();
knap->findItems();
knap->print();
delete knap;
return 0;
}
I believe the root of your issue is caused by the allocation of valueArray, and the fact that you are iterating out of bounds.
The line valueArray=new int[value]; initializes valueArray with an array of size value which is an uninitialized variable. Perhaps you meant to use noItems?
Also, as songyuanyao pointed out in the comments, your for loops look like for(int i=1;i<=noItems;i++) which starts the counter at 1 and finishes with the counter at noItems, which is erroneous. In a lot of languages, C++ included, arrays start at index 0 (meaning the first item is array[0], not array[1]) and the last item is one minus the size of the array (so the last item of an array with 5 elements is array[4]).
If you change your for loop to start at 0 and end one element before noItems you should be golden. That would be for(int i = 0; i < noItems; i++ )
What's probably happening with smaller allocations is the different chunks of memory are arranged sequentially in the same area of the memory heap, so when you overrun the buffer with data, you're smashing new's bookkeeping data.
When you have larger allocations, the new memory can't fit as cleanly into the free space of the heap, so the allocator ends up leaving some slack space between the allocations. Thus, a small overrun doesn't destroy heap information.

Create a struct in each iteration

I want to store queues in a queue structure from the stl library. For some reasons I have to store a queue in each iteration of my program, but I think that create a new queue over and over again is too expensive.
I only know two ways to do this. The first one:
#include <iostream>
#include <deque>
using namespace std;
int main () {
unsigned int limit, i = 0;
deque<deque<int> > container;
cin >> limit;
for ( ; i < limit; i++ ) {
deque<int> values;
//set some values in the values structure.
setValues(values, i);
container.push(values);
}
}
the second one:
#include <iostream>
#include <deque>
using namespace std;
int main () {
unsigned int limit, i = 0;
deque<deque<int> > container;
deque<int> values;
cin >> limit;
for ( ; i < limit; i++ ) {
//reset the structure, i.e. delete al the previous values.
reset(values);
//set some values in the values structure.
setValues(values, i);
container.push(values);
}
}
the problem here is that I don't know any function for reset my queue, or maybe I have to do values=NULL?
How can I do this in an efficient way?
Thanks! :D
You can push an empty deque in the loop, get a reference to it, and then add items to it.
#include <iostream>
#include <deque>
using namespace std;
int main () {
unsigned int limit, i = 0;
deque<deque<int> > container;
cin >> limit;
for ( ; i < limit; i++ ) {
container.push_back(deque<int>());
deque<int>& values = container.back();
//set some values in the values structure.
setValues(values, i); }
}
You should check in debugger what your compiler is actually doing when you make copies of deque. I have checked in VS2013 and its all move semantics - as expected. This is a test code:
std::deque<int> getValues() {
std::deque<int> res;
res.push_back(1);
return res; // deque(_Myt&& _Right) called, also other compilers might use RVO
}
std::deque<int> ff;
std::deque<std::deque<int>> aff;
aff.push_back(getValues()); // void push_back(value_type&& _Val) called
at first it looks like a lot of copying, but actually in both problematic places move semantics are used, and only pointers of temporary objects are copied, so its all super fast.
But maybe you are stuct in pre c++11 world? At least this fragment
deque<deque<int> > container;
^^^
gives such a hint.

Constructor issue <Unable to read memory>

I have to create a class Histogram and make operations on this class. The input can be one dimensional array or a two dimensional array. The problem appears when i convert the array into a matrix. This what i have tried so far. The error is <Unable to read memory>
histrogram.h
#ifndef HISTOGRAM_H
#define HISTOGRAM_H
#include<iostream>
class Histogram
{
private:
int** matrix;
int lines;
void SortMatrix();
public:
Histogram(){ }
Histogram(int elements[], int elementsNr);
Histogram(int** m, int l);
void Print();
};
#endif
historgram.cpp
#include"histogram.h"
using namespace std;
Histogram::Histogram(int** m, int l)
{
matrix=m;
lines=l;
SortMatrix();
}
Histogram::Histogram(int elements[], int elementsNr)
{
lines=0;
//initialize matrix : elementrNr lines and 2 columns
int** matrix=new int*[elementsNr];
for(int i=0;i<elementsNr;i++)
{
matrix[i]=new int[2];
matrix[i][0]=INT_MIN;
matrix[i][1]=INT_MIN;
}
//search each element from the array in the matrix
bool found=false;
for(int i=0;i<elementsNr;i++)
{
found=false;
for(int j=0;j<elementsNr;j++)
{
//the element was found in the matrix ( on the first column )
if(matrix[j][0] == elements[i])
{
matrix[j][1]++;
found=true;
break;
}
}
if(!found)
{
matrix[lines][0]=elements[i];
matrix[lines][1]=1;
lines++;
}
}
SortMatrix();
}
void Histogram::SortMatrix()
{
bool flag=true;
int temp;
for(int i=0;(i<lines) && flag;i++)
{
flag=false;
if(matrix[i+1][0]>matrix[i][0])
{
temp=matrix[i][0];
matrix[i][0]=matrix[i+1][0];
matrix[i+1][0]=temp;
flag=true;
}
}
}
void Histogram::Print()
{
for(int i=0;i<lines;i++)
{
cout<<matrix[i][0]<<" : " <<matrix[i][1]<<endl;
}
}
main.cpp
#include"histogram.h"
#include<iostream>
using namespace std;
int main()
{
int arr[]={6,7,3,1,3,2,4,4,7,5,1,1,5,6,6,4,5};
Histogram h(arr,17);
h.Print();
}
Here
int** matrix=new int*[elementsNr];
replace with
matrix=new int*[elementsNr];
becausematrix is already a member variable. You are creating a new temporary variable double pointer named matrix and allocating memory to it rather than your member variable matrix
A couple of people have already given you advice about how to fix some of the problems with this code. I'll give slightly different advice that may initially seem a bit brutal by comparison, but I'll try to demonstrate how it's honestly useful rather than nasty.
I would throw out your existing code with the possible exception of what you have in main, and start over, using an std::map. What you're doing right now is basically trying to re-create the capabilities that std::map already provides (and even when your code is fixed, it's not doing the job as well as std::map does right out of the box).
Using map, your whole program comes out to something like this:
std::ostream &operator<<(std::ostream &os, std::pair<int, int> const &d) {
return os << d.first << " : " << d.second;
}
int main() {
std::map<int, int> h;
for (int i=0; i<17; i++)
++h[arr[i]];
std::copy(h.begin(), h.end(),
std::ostream_iterator<std::pair<int, int> >(std::cout, "\n"));
return 0;
}
If you want to maintain virtually the same interface as your histogram class provided, it's pretty easy to do that -- the for loop goes into the constructor, the copy into print (and SortMatrix disappears, because a map is always sorted).
By doing this, you change from an O(N2) algorithm to an O(N log N) algorithm. The bugs others have pointed out disappear completely, because the code that contained them is no longer needed. The only real disadvantage I can see is that the result will probably use a bit more memory -- it uses a balanced tree with individually allocated nodes, which is likely to introduce a fair amount of overhead for nodes that only contain 2 ints (and a bit for balancing). I can't quite imagine worrying about this though -- long before you have enough nodes for the memory usage to become significant, you have way too many to present to even consider presenting to the user.
#mathematician1975 already provided an answer for the main problem. There's another bug in SortMatrix(): you only swap the elements of the first column, therefore after sorting, the counts (in the second column) will not be correct anymore. You'll have to insert
temp=matrix[i][1];
matrix[i][1]=matrix[i+1][1];
matrix[i+1][1]=temp;
to get it working.