Not getting the input values when printing vector of pairs - c++

I want to add a pair to a vector of pairs.
When I print the vector elements, I don't get the integers I input.
Please help.
#include<iostream>
#include<vector>
#include<utility>
using namespace std;
int main()
{
vector<vector<unsigned long int> >matrix;
vector<pair<int,int> >pmat;
int L;
cin>>L;
int n1, n2;
pmat.resize(L);
for(int k = 0; k<L; k++)
{
cin>>n1>>n2;
pair<int,int> p = make_pair(n1,n2);
cout<<p.first<<p.second<<endl;
pmat.push_back(p);
}
for(int k = 0; k<L; k++)
{
cout<<pmat[k].first<<','<<pmat[k].second<<' ';
}
cout<<endl;
return 0;
}

Method 1:
Delete this line:
pmat.resize(L);
You don't need to resize it in the first place as you do push_back() when adding afterwards.
Method 2:
Change the following line
pmat.push_back(p);
to
pmat[k] = p;
You can do resize() in the first place, but after this, you should not use push_back() when adding, just use pmat[k] = p.
PS: you should not mix these two ways up. Always use one of them consistently.

Since you're using pmat.resize(L) and L times pmat.push_back(...), you're ending up having stored 2 * L entries in your vector. However you're printing just the first half, index 0 to L - 1. The values you want are stored from index L to 2 * L - 1.
Just change pmat.resize(L) to pmat.reserve(L).
Alternatively, you can use the resize(L), but to end up with L entries, you need to store each input pair to pmat[k], hence you write pmat[k] = p;.
As a rule of thumb, I recommend using the reserve + push_back approach if you know how many elements you're going to add. The reason is, that resize initializes the elements, while reserving just asserts that there will be enough space and no reallocation will be necessary with any following push_back.

You don't want to add more pairs after you allocated them. You can now directly access them.
Just use pmat[k] = p; instead of pmat.push_back(p);

If you print the size of the vector after reading the values, you will notice a small problem with your program:
./test
2
1 2
12
3 4
34
Size of the vector: 4
0,0 0,0
Huh? Even though I only entered 2 pairs, the size of the vector is 4. How did this happen?
If you look at the documentation for resize, it says
Resizes the container to contain count elements.
So even before you read any values, your vector will already contain 2 elements! Those will be default-constructed and therefore be 0. When you then push_pack the elements you read in, those will land at the indices 2 and 3 in the vector, so the end vector has twice as much elements as you wanted (4 in this case). You only print out the first half, which are the zero values.
The solution is to use reserve instead of resize, which doesn't create the elements but only reserves space for them, or just delete the call to resize. Using reserve is more efficient though, because then the vector will only need to allocate memory once.

pmat.resize(L);
if vector in empty its going to initialize a vector pmat with size L then assign default values to vector so now pmat size is L with default values
for(int k = 0; k<L; k++)
{
cin>>n1>>n2;
pair<int,int> p = make_pair(n1,n2);
cout<<p.first<<p.second<<endl;
pmat.push_back(p);
}
then u r pushing values to pmat L times so the final size is 2*L
for(int k = 0; k<L; k++)
{
cout<<pmat[k].first<<','<<pmat[k].second<<' ';
}
here u r going to read from 0 to L-1 , it contains default values you can see your values from L-1 to 2L-1.
so finally what i want say is use reserve instead of resize
or
pmat.resize(L); comment this line

Related

C++ : Fastest Way to find number of elements of one array in another array

I have two arrays, one sorted array int b[] and other unsorted array int a[n] having n elements . The sorted array is made of some or all elements of unsorted array. Now there are M queries. For each query values of l and r are given. In each query I need to find the number of elements of a[n] which are present in b[].
For eg -
N=5 ,M=2
a= [2 5 1 2 3]
b=[3 2 1]
for each m:
l=1 r=5 ->a[1]=1, a[5]=5 -> answer should be 3 as all elements of b i.e 1,2,3 are present in a
l=2 r=4 ->a[2]=5 , a[4]=2 ->answer should be 2 as only 1 and 2 are there in b for given value of l and r for array.
How to find the answer with not more than O(M * LOGN) time complexity ?
NOTE:
Array is not necessary. Vector can also be used that is if it helps in reducing time complexity or easier to implement the code.
Well i think you can do something like this
std::map<int,int> c;
for(int i = 0;i<b.length.i++){
c[b[i]] = 0;
}
for(int i = l; i<=r; i++){
int number = a[i];
c[number]++;
}
//Iterate through c with b index and get all number which different than 0. The left is for you
The purpose of this is creating a map hold index of B. Then while iterating A you can increase the c value. So that after that you can check whether each element in C has value different than zero mean that A has hold the number of B.
You can use array instead of map if C starting from zero and increase by 1 for better performance. Make sure to check if a[i] can throw out of bounds exception if you use array.

std vector size keep ground Although i insert in the same indexs

Something wired i see here with std vector
I have
variable that its value is dynamically changes but always under 20
dynamicSizeToInsert in the example.
why the vector size keeps growing ?
std::vector<int> v;
//sometimes its 5 sometimes it is 10 sometimes it is N < 20
int dynamicSizeToInsert = 5
int c = 0;
for(std::vector<int>::size_type i = 0; i != 100; i++) {
if(c == dynamicSizeToInsert )
{
c = 0;
}
v.insert(v.begin() + c, c);
c++;
printf("%d",v.size()) //THIS THINK KEEP growing although i only using vector indexes 0 to 4 allways
}
i want to keep my vector side 5 elements big
and that new value will run over other value in the same index .
std::vector::insert, as the name suggests, inserts elements at the specified position.
When c == dynamicSizeToInsert, c is set to 0. So now, v.size() == 5. Now this lines executes:
v.insert(v.begin() + c, c);
This will insert 0 at posistion v.begin() + 0, which is position 0 and it will offset every other element (it will not replace the element at position 0), and so the vector keeps growing.
Instead of using insert, use operator[]:
//So that 'v' is the right size
v.resize(dynamicSizeToInsert);
for(std::vector<int>::size_type i = 0; i != 100; i++) {
if(c == dynamicSizeToInsert )
{
c = 0;
}
v[i] = c; //Sets current index to 'c'
c++;
}
insert doesn't replace element, rather it inserts element at given location and shifts all the right elements to one position right. That's why your vector size is growing.
If you want to replace an existing index then you can use operator[]. However, keep in mind that the index must be between 0 - size() - 1 in order to use operator[].
std::vector::insert inserts a new member into the array at the index you specify, and moving the other elements forward or even reallocating the array once it reaches capacity(a relatively expensive operation)
The vector is extended by inserting new elements before the element at
the specified position, effectively increasing the container size by
the number of elements inserted.
This causes an automatic reallocation of the allocated storage space
if -and only if- the new vector size surpasses the current vector
capacity.
(http://www.cplusplus.com/reference/vector/vector/insert/)
As quoted above, the vector is extended with every insert operation.
to get the behaviour you want you need to use the [] operator like so:
v[i] = some_new_value;
this way a new element is never added, its only the value of the ith element that is changed.
const int dynamicSizeToInsert = 5;
std::vector<int> v(dynamicSizeToInsert);
int c = 0;
for(std::vector<int>::size_type i = 0; i !=100; i++)
{
v.at(i%dynamicSizeToInsert) = (dynamicSizeToInsert == c?c = 0,c ++: c ++);
printf("%d",v.size());
}

Shifting elements in array by N elements

I have an array where each 'element' is composed of 4 consecutive values. Upon update I move the array by 4 values towards the end and insert 4 new values in the beginning.
Shift:
int m = 4;
for (int i = _vsize - 1; i + 1 - m != 0; i--){
_varray[i] = std::move(_varray[i - m]);
}
Insertion:
memcpy(&_varray[0], glm::value_ptr(new_element), 4 * sizeof(float));
where new_element is of type glm::vec4 containing said 4 new values.
Any suggestions on how to improve this?
(Right now Im only shifting by one element, but want the flexibility of being able to shift say 8 times, without having to put this in a loop)
Thank you.
You can try std::copy_backward. You want to copy a range of values to another range in the same container. Since the ranges overlap and you are copying to the right you can't use regular std::copy but must use std::copy_backward instead.
int m = 4; // make this a multiple of your 'element' size
std::copy_backward(&_varray[0], &_varray[_vsize - m], &_varray[_vsize]);
There is also std::move_backward but that doesn't really matter since your float values aren't movable.

I don't understand how to create and use dynamic arrays in C++

Okay so I have;
int grid_x = 5
int * grid;
grid = new int[grid_x];
*grid = 34;
cout << grid[0];
Should line 3 create an array with 5 elements? Or fill the first element with the number 5?
Line 4 fills the first element, how do I fill the rest?
Without line 4, line 5 reads "-842150451".
I don't understand what is going on, I'm trying to create a 2 dimensional array using x and y values specified by the user, and then fill each element one by one with numeric values also specified by the user. My above code was an attempt to try it out with a 1 dimensional array first.
The default C++ way of creating a dynamic(ally resizable) array of int is:
std::vector<int> grid;
Don't play around with unsafe pointers and manual dynamic allocation when the standard library already encapsulates this for you.
To create a vector of 5 elements, do this:
std::vector<int> grid(5);
You can then access its individual elements using []:
grid[0] = 34;
grid[1] = 42;
You can add new elements to the back:
// grid.size() is 5
grid.push_back(-42);
// grid.size() now returns 6
Consult reference docs to see all operations available on std::vector.
Should line 3 create an array with 5 elements?
Yes. It won't initialise them though, which is why you see a weird value.
Or fill the first element with the number 5?
new int(grid_x), with round brackets, would create a single object, not an array, and specify the initial value.
There's no way to allocate an array with new and initialise them with a (non-zero) value. You'll have to assign the values after allocation.
Line 4 fills the first element, how do I fill the rest?
You can use the subscript operator [] to access elements:
grid[0] = 34; // Equivalent to: *(grid) = 34
grid[1] = 42; // Equivalent to: *(grid+1) = 42
// ...
grid[4] = 77; // That's the last one: 5 elements from 0 to 4.
However, you usually don't want to juggle raw pointers like this; the burden of having to delete[] the array when you've finished with it can be difficult to fulfill. Instead, use the standard library. Here's one way to make a two-dimensional grid:
#include <vector>
std::vector<std::vector<int>> grid(grid_x, std::vector<int>(grid_y));
grid[x][y] = 42; // for any x is between 0 and grid_x-1, y between 0 and grid_y-1
Or might be more efficient to use a single contiguous array; you'll need your own little functions to access that as a two-dimenionsal grid. Something like this might be a good starting point:
template <typename T>
class Grid {
public:
Grid(size_t x, size_t y) : size_x(x), size_y(y), v(x*y) {}
T & operator()(size_t x, size_t y) {return v[y*size_x + x];}
T const & operator()(size_t x, size_t y) const {return v[y*size_x + x];}
private:
size_t size_x, size_y;
std::vector<T> v;
};
Grid grid(grid_x,grid_y);
grid(x,y) = 42;
Should line 3 create an array with 5 elements? Or fill the first element with the number 5?
Create an array with 5 elements.
Line 4 fills the first element, how do I fill the rest?
grid[n] = x;
Where n is the index of the element you want to set and x is the value.
Line 3 allocates memory for 5 integers side by side in memory so that they can be accessed and modified by...
The bracket operator, x[y] is exactly equivalent to *(x+y), so you could change Line 4 to grid[0] = 34; to make it more readable (this is why grid[2] will do the same thing as 2[grid]!)
An array is simply a contiguous block of memory. Therefore it has a starting address.
int * grid;
Is the C representation of the address of an integer, you can read the * as 'pointer'. Since your array is an array of integers, the address of the first element in the array is effectively the same as the address of the array. Hence line 3
grid = new int[grid_x];
allocates enough memory (on the heap) to hold the array and places its address in the grid variable. At this point the content of that memory is whatever it was when the physical silicon was last used. Reading from uninitialised memory will result in unpredictable values, hence your observation that leaving out line 4 results in strange output.
Remember that * pointer? On line four you can read it as 'the content of the pointer' and therefore
*grid = 34;
means set the content of the memory pointed to by grid to the value 34. But line 3 gave grid the address of the first element of the array. So line 4 sets the first element of the array to be 34.
In C, arrays use a zero-based index, which means that the first element of the array is number 0 and the last is number-of-elements-in-the-array - 1. So one way of filling the array is to index each element in turn to set a value to it.
for(int index = 0; index < grid_x; index++)
{
grid[index] = 34;
}
Alternatively, you could continue to use a pointer to do the same job.
for(int* pointerToElement = grid; 0 < grid_x; grid_x-- )
{
// save 34 to the address held by the pointer
/// and post-increment the pointer to the next element.
*pointerToElement++ = 34;
}
Have fun with arrays and pointers, they consistently provide a huge range of opportunities to spend sleepless hours wondering why your code doesn't work, PC reboots, router catches fire, etc, etc.
int grid_x = 5
int * grid;
grid = new int[grid_x];
*grid = 34;
cout << grid[0];
Should line 3 create an array with 5 elements? Or fill the first
element with the number 5?
Definitely the former. With the operator "new" you are allocating memory
Line 4 fills the first element, how do I fill the rest?
Use operator [], e.g.:
for int (i=0; i < grid_x; i++) { //Reset the buffer
grid[i] = 0;
}
Without line 4, line 5 reads "-842150451".
You are just reading uninitialized memory, it could be any value.
I don't understand what is going on, I'm trying to create a 2
dimensional array using x and y values specified by the user, and then
fill each element one by one with numeric values also specified by the
user. My above code was an attempt to try it out with a 1 dimensional
array first.
Other users explained how to use vectors. If you have to set only once the size of your array, I usually prefer boost::scoped_array which takes care of deleting when the variable goes out of scope.
For a two dimensional array of size not known at compile time, you need something a little bit trickier, like a scoped_array of scoped_arrays. Creating it will require necessarily a for loop, though.
using boost::scoped_array;
int grid_x;
int grid_y;
///Reading values from user...
scoped_array<scoped_array<int> > grid(new scoped_array<int> [grid_x]);
for (int i = 0; i < grid_x; i++)
grid[i] = scoped_array<int>(new int[grid_y] );
You will be able then to access your grid elements as
grid[x][y];
Note:
It would work also taking scoped_array out of the game,
typedef int* p_int_t;
p_int_t* grid = new p_int_t [grid_x];
for (int i = 0; i < grid_x; i++)
grid[i] = new int[grid_y];
but then you would have to take care of deletion at the end of the array's life, of ALL sub arrays.

C++ : iterating the vector

I'm very new to C++ and I'm trying to learn the vector in C++..
I wrote the small program as below. I like to foreach(var sal in salaries) like C# but it doesn't allow me to do that so I googled it and found that I have to use iterator.. Im able to compile and run this program but I dont get the expected output.. I'm getting "0 0 0 0 0 0 1 2 3 4 5 6 7 8 9" instead of "0 1 2 3 4 5 6 7 8 9"..
Could anyone please explain me why? Thanks.
#include <iostream>
#include <iomanip>
#include <vector>
using namespace std;
void show(int i)
{
cout << i << " ";
}
int main(){
vector<int> salaries(5);
for(int i=0; i < 10; i++){
salaries.push_back(i);
}
for_each(salaries.begin(), salaries.end(), show);
}
You created a vector with 5 elements, then you push 10 more onto the end. That gives you a total of 15 elements, and the results you're seeing. Try changing your definition of the vector (in particular the constructor call), and you'll be set. How about:
vector<int> salaries;
This code creates a vector with a size of 5, and with each of those 5 elements initialized to their default value (0):
vector<int> salaries(5);
push_back inserts a new element, so here, you insert 10 new elements, ending up with a vector with 15 elements:
for(int i=0; i < 10; i++){
salaries.push_back(i);
}
You can create your vector like this instead:
vector<int> salaries;
and you'll get a vector with size 0.
Alternatively, you could initialize it with size 10, and then overwrite each element, instead of inserting new ones:
vector<int> salaries(10);
for(int i=0; i < 10; i++){
salaries[i] = i;
}
In some cases, it may be more efficient to write something like this:
vector<int> salaries; // create a vector with size 0
// allocate space for 10 entries, but while keeping a size of 0
salaries.reserve(10);
for(int i=0; i < 10; i++){
// because we reserved space earlier, these new insertions happen without
// having to copy the vector contents to a larger array.
salaries.push_back(i);
}
When you declare salaries(5), it's adding 5 entries into the vector with values of 0. Then your loop adds 0..9. Therefore you have 15 elements in your vector instead of just 10. Try declaring the vector without the 5.
vector<int> salaries;
vector<int> salaries(5); means, that you are creating the vector which contains 5 int objects from the start, and each int object is initialized with default constructor, and in the case of int contructor sets zero value. That's why you have 5 zero integers at the beginning of the vector container.
#Michael: Which book is that? I'd say
it's wrong. Using resize() is a good
practice if you know in advance how
big you need the vector to be, but
don't set the size at creation unless
you need the vector to contain
default-initialized values.
You can also reserve some capacity in the array in advance which is subtely different than re-size. Reserving simply reserves "at least" that much capacity for the vector (but does not change the size of the vector), while resize adds\removes elements to\from the vector to make it the requested size.
vector<int> salaries(5);
This creates a vector of 5 zeros for its elements. [0, 0, 0, 0, 0]
for(int i=0; i < 10; i++){
salaries.push_back(i);
}
This adds 10 more elements at the end ranging from 0 to 9 [0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Finally, I don't recommend using foreach so much. Functional programming has the downside of decentralizing code. It is extremely useful in some cases, but for these cases, and especially considering how you're starting out, I'd recommend:
for (vector<int>::const_iterator it = salaries.begin(), end = salaries.end(); it != end; ++it){
salaries.push_back(i);
}
Using this technique, you'll be able to iterate through any collection in the standard library without having to write separate functions or function objects for the loop body.
With C++0x you'll get a lot of goodies to make this easier:
for (int salary: salaries)
cout << salary << endl;
There's also BOOST_FOR_EACH already which is almost as easy if you can use boost.