I'm getting weird numbers as output in this code :
#include <iostream>
#include <vector>
int main(){
std::vector<std::vector<int>> vec = {{0,1},{2,3}};
vec.push_back({4,5});
vec.push_back({5,6});
for (int i = 0; i < vec.size(); i++){
for (int i2 = 0; i2 < vec.size(); i2++){
std::cout << vec[i][i2] << std::endl;
}
}
return 0;
}
It's returning to me:
0
1
1280136264
0
2
3
347673833
38962
4
5
297276653
134256690
5
6
280499436
268474418
I just want to know how to do it properly, and why I'm getting these numbers.
The output you are seeing is due to undefined behavior in your code.
The outer vector object has 4 inner vector<int> objects added to it. Each of those inner vector<int> objects is holding 2 int values.
Your inner for loop is going out of bounds of the inner vector<int> objects, by trying to access 4 int values when there are only 2 int values available.
In your inner for loop, you need to change vec.size() to vec[i].size() instead, eg:
#include <iostream>
#include <vector>
int main(){
std::vector<std::vector<int>> vec = {{0,1},{2,3}};
vec.push_back({4,5});
vec.push_back({5,6});
for (size_t i = 0; i < vec.size(); ++i){
for (size_t i2 = 0; i2 < vec[i].size(); ++i2){
std::cout << vec[i][i2] << std::endl;
}
/* alternatively:
auto &vec2 = vec[i];
for (size_t i2 = 0; i2 < vec2.size(); ++i2){
std::cout << vec2[i2] << std::endl;
}
*/
}
return 0;
}
Online Demo
That being said, a safer way to code this is to use range-for loops instead, eg:
#include <iostream>
#include <vector>
int main(){
std::vector<std::vector<int>> vec = {{0,1},{2,3}};
vec.push_back({4,5});
vec.push_back({5,6});
for (auto &vec2 : vec){
for (auto value : vec2){
std::cout << value << std::endl;
}
}
return 0;
}
Online Demo
Related
I got stuck in many problems where I was trying to store values in 2D vectors.
So I have written this simple code.
I am just storing and printing my values :
int main()
{
vector<vector<int>> vec;
vector<int> row{1,3,5,7,9,12,34,56};
int i,n,m,rs,vs;
rs=row.size();
cout<<"rs = "<<rs<<endl;
for(i=0;i<(rs/2);i++)
{
vec[i].push_back(row.at(i));
vec[i].push_back(row.at(i+4));
}
vs=vec.size();
cout<<vs<<endl;
for(n=0;n<vs;n++)
{
for(m=0;m<2;m++)
{
cout<<vec[n][m]<<" ";
}
cout<<endl;
}
return 0;
}
First you should read Why is “using namespace std;” considered bad practice?.
Declare variables when you use them and not at the beginning of your program.
The vector vec is empty at the beginning. In the loop
for(i=0;i<(rs/2);i++)
{
vec[i].push_back(row.at(i));
vec[i].push_back(row.at(i+4));
}
you are taking a reference to the i-th element in vec with
vec[i]
but this element does not exist. This is undefined behavior and can result in a segmentation fault. You can fix it by constructing the vector with the needed elements
#include <iostream>
#include <vector>
int main()
{
std::vector<int> row{1,3,5,7,9,12,34,56};
int rs = row.size();
std::vector<std::vector<int>> vec(rs / 2);
std::cout << "rs = " << rs << '\n';
for(int i = 0; i < rs / 2; ++i)
{
vec[i].push_back(row.at(i));
vec[i].push_back(row.at(i + 4));
}
int vs = vec.size();
std::cout << vs << '\n';
for(int n = 0; n < vs; ++n)
{
for(int m = 0; m < 2; ++m)
{
std::cout << vec[n][m] << " ";
}
std::cout << '\n';
}
return 0;
}
In this example the line
std::vector<std::vector<int>> vec(rs / 2);
constructs a vector containing rs / 2 default constructed elements. Alternatively you can start with an empty vector and push back elements in the loop
#include <iostream>
#include <vector>
int main()
{
std::vector<int> row{1,3,5,7,9,12,34,56};
int rs=row.size();
std::vector<std::vector<int>> vec;
std::cout << "rs = " << rs << '\n';
for(int i = 0; i < rs / 2; ++i)
{
vec.push_back({row.at(i), row.at(i+4)});
//
// is similar to:
// vec.push_back({});
// vec.back().push_back(row.at(i));
// vec.back().push_back(row.at(i+4));
//
// is similar to:
// vec.push_back({});
// vec[i].push_back(row.at(i));
// vec[i].push_back(row.at(i+4));
}
int vs = vec.size();
std::cout << vs << '\n';
for(int n = 0; n < vs; ++n)
{
for(int m = 0; m < 2; ++m)
{
std::cout << vec[n][m] << " ";
}
std::cout << '\n';
}
return 0;
}
I recommend the first solution. It's better to allocate memory for all elements and work with it instead of allocate memory in each loop iteration.
Say I have an array like this:
int arr [9] = {2,1,5,8,9,4,10,15,20}
How can you split the array at a certain value threshold? So say int 8 is our splitting value, the end result would be two separate arrays (or a 2d array if you want to give that a shot) that in this example would be arr1 [4] = {1,2,4,5} and arr2 [5] = {8,9,10,15,20}. arr1 stores all the values in arr that are below 8 and and arr2 stores all the values in arr that are 8 and above.
I haven't been able to locate sufficient documentation or examples of this being done and I think array manipulation and splitting is worth having examples of.
Use std::partition, or if you want to maintain the relative order and not sort the data, std::stable_partition.
#include <algorithm>
#include <iostream>
#include <vector>
int main()
{
int pivot = 8;
int arr [9] = {2,1,5,8,9,4,10,15,20};
// get partition point
int *pt = std::stable_partition(arr, std::end(arr), [&](int n) {return n < pivot;});
// create two vectors consisting of left and right hand side
// of partition
std::vector<int> a1(arr, pt);
std::vector<int> a2(pt, std::end(arr));
// output results
for (auto& i : a1)
std::cout << i << " ";
std::cout << '\n';
for (auto& i : a2)
std::cout << i << " ";
}
Live Example
If you can use C++11 then this is one way of using the standard library:
Using a partition_point: (edited the example from the link)
#include <algorithm>
#include <array>
#include <iostream>
#include <iterator>
#include <vector>
int main()
{
std::array<int, 9> v = {2,1,5,8,9,4,10,15,20};
auto is_lower_than_8 = [](int i){ return i < 8; };
std::partition(v.begin(), v.end(), is_lower_than_8 );
auto p = std::partition_point(v.begin(), v.end(), is_lower_than_8 );
std::cout << "Before partition:\n ";
std::vector<int> p1(v.begin(), p);
std::sort(p1.begin(), p1.end());
std::copy(p1.begin(), p1.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << "\nAfter partition:\n ";
std::vector<int> p2(p, v.end());
std::sort(p2.begin(), p2.end());
std::copy(p2.begin(), p2.end(), std::ostream_iterator<int>(std::cout, " "));
}
Which prints:
Before partition:
1 2 4 5
After partition:
8 9 10 15 20
I'm working on a solution with loops. This is a work in progress. Let me know what you think.
void splitarr(int arr[], int length) {
int accu = 0;
int accu2 = 0;
int splitter = rand() % 20;
for (int i = 0; i < length; i++) {
if (i != splitter) {
accu++;
}
}
int arr1[accu];
for (int i = 0; i < length; i++) {
if (i != splitter) {
arr1[i] = i;
}
}
for (int i = 0; i < length; i++) {
if (i == splitter) {
accu2++;
}
}
int arr2[accu2];
for (int i = 0; i < length; i++) {
if (i == splitter) {
arr2[i] = i;
}
}
}
I`m writing a code for which I'm using a 3 dimensional boost multiarray to save coordinates. But I always get a segmentation fault at some point.
How are boost multiarray sizes limited and how can I get around those limits?
Here is a simplified test code that reproduces the problem:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <string>
#include <algorithm>
#include <map>
#include <boost/multi_array.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>
#include "Line.h"
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
typedef struct {
Eigen::Vector3d coords;
int gpHostZone;
int gpHostFace;
int calculated;
} Vertex;
class LGR {
public:
LGR (int i, int j, int k) :
grid(boost::extents[i][j][k])
{
};
std::string name;
std::vector<int> hostZones;
std::vector<int> refine;
boost::multi_array<Vertex*, 3> grid;
std::vector<double> data;
};
int main(void){
LGR lgr(11,11,21);
std::cout << lgr.grid.size();
std::vector<LGR> v;
std::vector<Vertex> vertexDB;
for(int i = 0; i < 1; i++ ){
for(int j = 0; j < lgr.grid.size(); j++ ){
for(int k = 0; k < lgr.grid[0].size(); k++ ){
for(int l = 0; l < lgr.grid[0][0].size(); l++ ){
Vertex coord;
coord.coords << i,j,k;
coord.gpHostZone = 0;
coord.gpHostFace = 0;
coord.calculated = 0;
vertexDB.push_back(coord);
lgr.grid[j][k][l] = &(vertexDB.back());
}
}
}
for(int j = 0; j < lgr.grid.size(); j++ ){
for(int k = 0; k < lgr.grid[0].size(); k++ ){
for(int l = 0; l < lgr.grid[0][0].size(); l++ ){
std::cout << "At ("<< i << ","<< j << ","<< k << "," << l << ")\n";
std::cout << lgr.grid[j][k][l]->coords<<"\n\n";
}
}
}
}
return 1;
}
Please do not comment on the includes. I just copy and pasted from the actual code. Most of the are probably not needed here. The dimensions are from a real example, so I actually need those kind of dimensions (and probably more).
The following is a definite issue that leads to undefined behavior, and doesn't have anything to do with boost::multiarray.
These lines:
std::vector<Vertex> vertexDB;
//...
vertexDB.push_back(coord);
lgr.grid[j][k][l] = &(vertexDB.back());
resizes the vertexDB vector and then stores a pointer to the last item in the vector to lgr.grid[j][k][l]. The problem with this is that pointers and iterators to items in a vector may become invalidated due to the vector having to reallocate memory when resizing the vector.
This manifests itself later here, in the subsequent loop:
std::cout << lgr.grid[j][k][l]->coords<<"\n\n";
There is no guarantee that the address you assigned previously is valid.
A quick fix for this is to use a std::list<Vertex>, since adding items to a std::list does not invalidate iterators / pointers.
Hi I have an array of share prices but I only want to output them as they increase.
For example if I have 1,1,1,2,2,2,3,3,3,4,4,4,5,5,5, etc. I only want to print 1,2,3,4.
I have tried setting a temporary max and min but still can't get it.
Now I only have this:
for(int h = 0; h < max; h++)
{
if(v3[h].getPrice() > 0)
{
ofile << v[h].getPrice() << ", ";
}
}
What you want is this
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main()
{
// Assign your vector
int a[] = {1,1,1,2,2,3,3,3,4,4,5,5,5,1,3};
vector<int> vec(a, a+15);
// Sort before calling unique
sort(vec.begin(), vec.end());
// Impose only one of each
vector<int>::iterator it;
it = unique(vec.begin(), vec.end());
vec.resize( distance(vec.begin(),it) );
// Output your vector
for( vector<int>::iterator i = vec.begin(); i!= vec.end(); ++i)
cout << (*i) << endl;
return 0;
}
Live example
The sort is necessary for unique to work.
#include <iostream>
using namespace std;
int main()
{
int a[15] = {1,1,1,2,2,2,3,3,3,4,4,4,5,5,5};
for (int i=0; i<15; i+=3)
{
cout << a[i] <<",";
}
return 0;
}
Increment the counter 3 times in the loop " for(int h=0;h < max; h+=3){} ".
i have a vector of vector "mydata". i want to iterate my data in negative direction. the iterator should be started from the middle to the beginning.
i wish to use following way;
vector<vector<int> >::const_iterator points;
int i, k;
(lets assume k = 10)
for (i=k, points=mydata.begin()+k; i != -1; i--, points--){
//do stuff
}
does this way is the proper way to iterate in backward? (I am using dev c++, so predicates and some modern commands cant be used.)
Hope your suggestions to do this.
A possible solution using reverse_iterators vector::rbegin() and vector::rend():
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
for (std::vector<int>::const_reverse_iterator it = v.rbegin()+(v.size()/2);
it != v.rend();
it++)
{
std::cout << *it << "\n";
}
return 0;
}
You can use std::vector::const_reverse_iterator. Here's the example of how to iterate backwards through the vector, starting from the middle:
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v;
for(int i = 0; i< 10; i++)
v.push_back(i);
std::vector<int>::const_reverse_iterator it = v.rbegin() + 5;
for(;it != v.rend(); it++)
{
std::cout << *it << std::endl;
}
return 0;
}
Output:
4
3
2
1
0
Since it's vector, you dont need to use iterator at all:
for (int k = 4; k >= 0; k--)
{
// do something with v[k]
}
Example:
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char** argv)
{
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
vector<int> v(arr, arr + 10);
for (int k = 4; k >= 0; k--)
{
cout << v[k] << endl;
}
}
output:
5
4
3
2
1
There are roughly two nice solutions. Either you just write the loop:
vector<int>::const_iterator i = v.begin() + 4;
do {
// stuff with *i
while (--i != v.begin());
or use reverse iterators and the standard STL algorithms:
std::for_each(v.rend()-4, v.rend(), &stuff);