Using functions on vectors in C++ - c++

I'm trying to change the data inside a vector's element by using a function. It happens that the elements are changed just inside the function. How can I keep the changings outside the function? Do I must use pointers?
The code:
#include <iostream>
#include <vector>
using namespace std;
void populate( int size_, vector<int> pop)
{
//Set the vector's size and populate the vector
pop.resize(size_);
for(int i = 0; i<3 ; i++)
{
pop[i] = i;
}
}
int main()
{
vector<int> vec;
int size = 3;
populate(size, vec);
for(vector<int>::iterator it = vec.begin(); it != vec.end(); ++it)
{
cout << *it << endl;
}
}
The output at cout should be : 0 1 2
But it is empty.

What you're trying to do is easily and idiomaticaly done with standard library facilities:
int size = 3;
std::vector<int> vec(size);
std::iota(vec.begin(), vec.end(), 0); // include algorithm for this

You need to take the vector by reference
void populate( int size_, vector<int>& pop)
Otherwise you are passing in a copy of the vector, populating it, then returning, but the original vector is unmodified.
Or as #juanchopanza recommended, since the sole purpose of this function is to make this vector for you, it could be
vector<int> populate( int size_ )
{
vector<int> temp(size_);
for(int i = 0; i < size_ ; i++)
{
pop[i] = i;
}
return temp;
}
Then
int main()
{
int size = 3;
vector<int> vec = populate(size, vec);
for(vector<int>::iterator it = vec.begin(); it != vec.end(); ++it)
{
cout << *it << endl;
}
}

You are sending in the vector to populate by value. This creates a copy, so pop is a copy of vec. Changes you make only affect pop.

Related

Copy vector (returned from a function) into a specific point of another vector directly at function call without needing extra temp variables [c++]

I have a function that returns a vector and I want all of that vector inserted into another vector at a specific point directly when calling that function.
What I would like to do is something like this:
#include <vector>
#include <iostream>
using namespace std;
typedef vector<double> Double1D;
Double1D myFunction(Double1D vector, int vector_size){
Double1D result;
result.resize (vector_size, 0);
result = vector; //here is where I would do calculations
return result;
}
int main()
{
int vector_size1 = 3;
int vector_size2 = 6;
Double1D vector_results;
vector_results.resize (9, 3);
vector_results[0-2] = myFunction(randomvector, vector_size1);
vector_results[3-8] = myFunction(randomvector2, vector_size2);
At the moment I am doing this which needs a for loop and needs extra temporary variables (minimal reproducible example):
#include <vector>
#include <iostream>
using namespace std;
typedef vector<double> Double1D;
Double1D myFunction(Double1D vector, int vector_size){
Double1D result;
result.resize (vector_size, 0);
result = vector; //here is where I would do calculations
return result;
}
int main()
{
int vector_size1 = 3;
int vector_size2 = 6;
Double1D vector_results;
vector_results.resize (9, 3);
Double1D vector1 ;
vector1.resize (vector_size1, 0);
Double1D vector2 ;
vector2.resize (vector_size2, 0);
Double1D temp_vector1 = myFunction(vector1, vector_size1);
Double1D temp_vector2 = myFunction(vector2, vector_size2);
for (int i = 0; i < (vector_size1 + vector_size2); i++){
if (i < vector_size1) vector_results[i] = temp_vector1[i];
if (i < vector_size2) vector_results[i+vector_size1] = temp_vector2[i];
cout<<vector_results[i]<<endl;
}
return 0;
}
The idiomatic method for writing a range of results is to take OutputIterators as function parameters.
#include <vector>
using Double1D = std::vector<double>;
void myFunction(Double1D::iterator dFirst, Double1D::iterator dLast) {
int n = /* number between 0 and dLast - dFirst */
dFirst[n] = /* calculations */
// or
for (; dFirst != dLast; ++dFirst) {
*dFirst = /* calculation */
}
}
int main() {
Double1D array_results;
array_results.resize(9, 0);
myFunction(randomvector, vector_size1);
myFunction(randomvector1, vector_size2);
}
If you insist on assigning a Double1D to something:
class AssignableSlice {
Double1D::iterator first;
Double1D::iterator last;
public:
AssignableSlice(Double1D & values, size_t first, size_t last)
: first(values.begin() + first), last(values.begin() + last) {}
AssignableSlice& operator=(Double1D & other) {
if (other.size() != std::distance(first, last)) throw std::out_of_range("wrong size in assignment");
std::copy(other.begin(), other.end(), first, last);
return *this;
}
};
int main() {
Double1D vector1;
vector1.resize (vector_size1, 0);
Double1D vector2;
vector2.resize (vector_size2, 0);
Double1D array_results;
array_results.resize(9, 0);
AssignableSlice(array_results, 0, vector_size1) = myFunction(vector1, vector_size1);
AssignableSlice(array_results, vector_size1, vector_size1 + vector_size2) = myFunction(vector2, vector_size2);
}
G'day, Alex from the past. This is you from the future. Here is how you solved it.
The function you want to use is a vector function called: insert() or a more efficient way that works for you is using copy() with back_inserter().
copy with back_inserter can only insert the vector to the back, whereas insert allows to insert anywhere. Both increase the size of the vector automatically.
Disclaimer: This may not be the best solution I am not an expert.
#include <vector>
#include <iostream>
using namespace std;
//vector<double> is variable that is a vector of doubles
typedef vector<double> Double1D; //this basically just gives vector<double> the name Double1D to make it easier to write
Double1D myFunction(Double1D vector, int vector_size){
Double1D result;
result.resize (vector_size, 0);
result = vector; //here is where I would do calculations
return result;
}
int main()
{
int vector_size1 = 3;
int vector_size2 = 6;
Double1D vector_results(vector_size1+vector_size2, 0);//fill vector with vector_size1+vector_size2 many 0s
Double1D vector1(vector_size1,1) ;//fill vector with vector_size1 many 1s
Double1D vector2(vector_size2, 2) ; //fill vector with vector_size2 many 1s
for (int i = 0; i < vector_results.size(); i++){ //see that it is full of 0s
cout<<vector_results[i]<<" ";
}
cout<<endl;
//this is specifically what you asked for
vector_results = myFunction(vector1, vector_size1); //vector_results is now just a copy of the vector of the output of the function
for (int i = 0; i < vector_results.size(); i++){
cout<<vector_results[i]<<" ";
}
cout<<endl;
//yourvectorname.insert(where to insert (an iterator), what to insert beginning, what to insert end)
//vector_results.insert(vector_results.begin()+3, myFunction(vector2, vector_size2).begin(), myFunction(vector2, vector_size2).end()); //this doesnt work as I think the function gets called twice?
Double1D temp_vec = myFunction(vector2, vector_size2);
vector_results.insert(vector_results.begin()+vector_size1, temp_vec.begin(), temp_vec.end());
for (int i = 0; i < vector_results.size(); i++){
cout<<vector_results[i]<<" ";
}
cout<<endl;
//here is a version using back_inserter which I have read is more efficient
//whatever you want at the start you just overwrite the destined vector with it
vector_results = myFunction(vector1, vector_size1); //vector_results is now just a copy of the vector of the output of the function
//create a tempvector to be able to use it
Double1D temp_vec2 = myFunction(vector2, vector_size2);
//now the important part: copy(start of what you wanna copy,end of what you wanna copy, where you want to insert it)
copy(temp_vec2.begin(), temp_vec2.end(), back_inserter(vector_results)); //back_inserter inserts it at the back (and from what I read more efficient than an insert in the middle)
for (int i = 0; i < vector_results.size(); i++){
cout<<vector_results[i]<<" ";
}
cout<<endl;
return 0;
}

Deleting both an element and its duplicates in a Vector in C++

I've searched the Internet and known how to delete an element (with std::erase) and finding duplicates of an element to then delete it (vec.erase(std::unique(vec.begin(), vec.end()),vec.end());). But all methods only delete either an element or its duplicates.
I want to delete both.
For example, using this vector:
std::vector<int> vec = {2,3,1,5,2,2,5,1};
I want output to be:
{3}
My initial idea was:
void removeDuplicatesandElement(std::vector<int> &vec)
{
std::sort(vec.begin(), vec.end());
int passedNumber = 0; //To tell amount of number not deleted (since not duplicated)
for (int i = 0; i != vec.size(); i = passedNumber) //This is not best practice, but I tried
{
if (vec[i] == vec[i+1])
{
int ctr = 1;
for(int j = i+1; j != vec.size(); j++)
{
if (vec[j] == vec[i]) ctr++;
else break;
}
vec.erase(vec.begin()+i, vec.begin()+i+ctr);
}
else passedNumber++;
}
}
And it worked. But this code is redundant and runs at O(n^2), so I'm trying to find other ways to solve the problem (maybe an STL function that I've never heard of, or just improve the code).
Something like this, perhaps:
void removeDuplicatesandElement(std::vector<int> &vec) {
if (vec.size() <= 1) return;
std::sort(vec.begin(), vec.end());
int cur_val = vec.front() - 1;
auto pred = [&](const int& val) {
if (val == cur_val) return true;
cur_val = val;
// Look ahead to the next element to see if it's a duplicate.
return &val != &vec.back() && (&val)[1] == val;
};
vec.erase(std::remove_if(vec.begin(), vec.end(), pred), vec.end());
}
Demo
This relies heavily on the fact that std::vector is guaranteed to have contiguous storage. It won't work with any other container.
You can do it using STL maps as follows:
#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;
void retainUniqueElements(vector<int> &A){
unordered_map<int, int> Cnt;
for(auto element:A) Cnt[element]++;
A.clear(); //removes all the elements of A
for(auto i:Cnt){
if(i.second == 1){ // that if the element occurs once
A.push_back(i.first); //then add it in our vector
}
}
}
int main() {
vector<int> vec = {2,3,1,5,2,2,5,1};
retainUniqueElements(vec);
for(auto i:vec){
cout << i << " ";
}
cout << "\n";
return 0;
}
Output:
3
Time Complexity of the above approach: O(n)
Space Complexity of the above approach: O(n)
From what you have searched, we can look in the vector for duplicated values, then use the Erase–remove idiom to clean up the vector.
#include <vector>
#include <algorithm>
#include <iostream>
void removeDuplicatesandElement(std::vector<int> &vec)
{
std::sort(vec.begin(), vec.end());
if (vec.size() < 2)
return;
for (int i = 0; i < vec.size() - 1;)
{
// This is for the case we emptied our vector
if (vec.size() < 2)
return;
// This heavily relies on the fact that this vector is sorted
if (vec[i] == vec[i + 1])
vec.erase(std::remove(vec.begin(), vec.end(), (int)vec[i]), vec.end());
else
i += 1;
}
// Since all duplicates are removed, the remaining elements in the vector are unique, thus the size of the vector
// But we are not returning anything or any reference, so I'm just gonna leave this here
// return vec.size()
}
int main()
{
std::vector<int> vec = {2, 3, 1, 5, 2, 2, 5, 1};
removeDuplicatesandElement(vec);
for (auto i : vec)
{
std::cout << i << " ";
}
std::cout << "\n";
return 0;
}
Output: 3
Time complexity: O(n)

Generating and Displaying all subsets recursively C++

I am trying to generate all subsets of the set {1,2,3} recursivley. When I run the code though, nothing is printed. I add elements into the vector but printing the vector gives me nothing. Am I not printing in the right place or is something else going on?
#include <stdio.h>
#include <vector>
#include <iostream>
using namespace std;
int n=3;
void gen(int k) {
vector<int> v;
if (k == n + 1) {
cout <<"(";
for (auto i = v.begin(); i != v.end(); ++i){
cout << *i ;
}
cout <<")";
}
else {
gen(k + 1);
v.push_back(k);
gen(k + 1);
v.pop_back();
}
}
int main(){
gen(1);
return 0;
}
Your issue is that the vector v in gen is a function local object so each call to gen has its own v. That isn't what you want since you want all the recursive calls to populate the same v.
You have a couple ways to fix that. You could make v static but then you could only call the function once. You could make v a global variable but then you need to remember to call clear() on then vector after each time you run gen. Lastly, you can make a helper function that declares the vector and then passes it to your recursive function to use. This IMHO is the more correct solution as it requires no user intervention. That would give you
void gen(int k, std::vector<int>& v) {
if (k == n + 1) {
cout <<"(";
for (auto i = v.begin(); i != v.end(); ++i){
cout << *i ;
}
cout <<")";
}
else {
gen(k + 1, v);
v.push_back(k);
gen(k + 1, v);
v.pop_back();
}
}
void gen(int k) {
vector<int> v;
gen(k, v);
}
int main(){
gen(1);
return 0;
}

Switching data from array to vector

I'm trying to convert my array to a vector, yet I'm having trouble printing it.
It says in int main() in my for loop that v is undefined. When I define
vector v; inside int main() the program compiles and runs and yet prints nothing. What am I doing wrong?
#include <iostream>
#include <vector>
using namespace std;
vector<int> a2v(int x[], int n)
{
vector<int> v(n);
for(int i = 0; i < n; i++)
{
v.push_back(x[i]);
}
return(v);
}
int main()
{
vector<int> a2v(int x[], int n);
int array[] = {11,12,13,14,15,16,17,18};
a2v(array, 8);
for(int i = 0; i < v.size(); i++)
{
cout << v[i] <<" ";
}
cout << endl;
return(0);
}
This is your program corrected:
#include <iostream>
#include <vector>
using namespace std;
vector<int> a2v(int x[], int n)
{
vector<int> v(0);
v.reserve(n); //optional
for(int i = 0; i < n; i++)
{
v.push_back(x[i]);
}
return(v);
}
int main()
{
int array[] = {11,12,13,14,15,16,17,18};
auto v = a2v(array, 8);
for(size_t i = 0; i < v.size(); i++)
{
cout << v[i] <<" ";
}
cout << endl;
return(0);
}
There were 2 errors:
In the function a2v, you instantiated a vector of 0 with length n, and then you pushed back other elements;
You were not defining v inside the main, as the return value of a2v
The vector you want to read is the return of the a2v function.
But there is a lot more simpler than that to go from C-array to vector array , I put here the example in found the vector reference web page :
http://www.cplusplus.com/reference/vector/vector/vector/
int myints[] = {16,2,77,29};
std::vector<int> fifth (myints, myints + sizeof(myints) / sizeof(int) );
When you define a variable, such as your vector v, you always do it in a certain scope. The body of a function such as a2v, or main, is an example of a possible scope. So if you only do it in the function a2v, that's the only scope where it will be visible.
It says in int main() in my for loop that v is undefined.
Well it will be because there is no v in main()
a2v(array, 8);
The above function call returns a vector so you need to collect the returned vector like
vector<int> v=a2v(array,8)
Also,
vector<int> v(n);//creates a vector of size n
for(int i = 0; i < n; i++)
{
v.push_back(x[i]);//adds n more elements to the vector
}
The returned vector has 2n elements and not n
Finally you could directly create a vector from an array as
vector<int> v(arr,arr+n);//where n is the number of elements in arr

C++ store iterators in a SET

In my program I have a set: ( std::set<int> myset; ) and after some treatment I finally take one iterator which I have decelerated like this ( set<int>::iterator findnumb; ). Well let say I have to do this 5 times in MYSET, 5 times define differences iterators (it1, it2 ,....it5) and not only this but after that to sort them by the content that they show. My idea it was to create a loop and in every time put the specific iterator in a set and sort but I don't know how I declare this.
I create an simple example that take for user 5 number and finds the nearest bigger from our set and print it. But in every loop the old iterator replace from the new one and in my real program I want to store this iterator int a set. Well based on this can you modify this example and store the iterators in a set sort by the content that they show.
#include <iostream>
#include <set>
#include <vector>
using namespace std;
int main()
{
std::set<int> myset;
for (int i=1; i<=20; ++i)
{myset.insert(i*10);}
vector<int> vect;
int numb;
for (int i=0; i<5; ++i)
{
cout << "give a number" <<endl;
cin >> numb;
vect.push_back(numb);
}
set<int>::iterator findnumb;
for (vector<int>::iterator it = vect.begin(); it != vect.end(); ++it)
{
findnumb=myset.find(*it);
while ( (*findnumb)!=(*it))
{ ++(*it); findnumb=myset.find(*it);}
cout << *findnumb<<" ";
}
cout << endl;
return 0;
}
I am not sure if I understood your question correctly.
struct dereferenced_less {
template<typename I>
bool operator()(const I& lh, const I& rh) const { return *lh < *rh; }
};
int main()
{
using namespace std;
set<int> myset = { 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 };
vector<int> vect = { 17, 32, 4, 16, 28, 120 };
set<set<int>::const_iterator, dereferenced_less> findnumbs;
for (int i : vect)
{
auto findnumb = myset.upper_bound(i);
if (findnumb != end(myset))
findnumbs.insert(findnumb);
}
// findnumbs: {10, 20, 30, 40}
}
If you only want the iterators ordered it might be better to sort the input vector and process the set skipping dupklicate elements.
vector<set<int>::const_iterator> result;
sort(begin(vect), end(vect));
for (int i : vect)
{
auto find = myset.upper_bound(i);
if (find != end(myset) && (result.empty() || *result.back() != *find))
result.push_back(find);
}
Don't use sets where you can use vectors.
and this
for (vector<int>::iterator it = vect.begin(); it != vect.end(); ++it)
is NOT how you traverse a vector!!! Iterators are made to be used in template algorithms, an on containers that cannot be randomly accessed. This is how you use vectors
for (size_t i = 0; i < vect.size(); ++ i)
vec[i] // the i-th element
Or with the new syntax
for (int x : vect)
x // the i-th element
Also find will allways find the element in the set, when not it will return the end iterator, that's after the very last element
so this
findnumb=myset.find(*it);
while ( (*findnumb)!=(*it))
{ ++(*it); findnumb=myset.find(*it);}
is useless and wrong. To test if find found the element use
if (findnumb != myset.end())
Of course if all you want to know is whether or not the element is in the set, it's better to use count and forget about the iterators at all.
if (myset.count(x) > 0)
And don't store iterators if you only want to read the value not write it. Just store the value itself
with the help of hansmaad I found out what I need (baste on my code) thanks a lot.!!!!!!!!!!! Also I have a last question, how I use FIND in set findnumbs!!!! like set::const_iterator, dereferenced_less>::iterator ithelp; ithelp=findnumbs.find(20)
#
include <iostream>
#include <set>
#include <vector>
#include <algorithm>
struct dereferenced_less {
template<typename I>
bool operator()(const I& lh, const I& rh) const { return *lh < *rh; }
};
int main()
{
using namespace std;
set<int> myset;
for (int i=1; i<=10; ++i)
{myset.insert(i*10);}
int vc[] = { 17, 32, 4, 16, 28 };
vector<int> vect ;
vect.assign (vc, vc+5);
set<set<int>::const_iterator, dereferenced_less> findnumbs;
set<int>::iterator findnumb;
for (std::vector<int>::iterator i = vect.begin(); i != vect.end(); ++i)
{ cout << *i << endl; }
for (std::vector<int>::iterator i = vect.begin(); i != vect.end(); ++i)
{
findnumb = myset.find(*i);
while ( (*findnumb)!=(*i))
{ ++(*i); findnumb=myset.find(*i);}
findnumbs.insert(findnumb);
cout << *findnumb<<" ";
}
for (set<set<int>::const_iterator, dereferenced_less>::iterator it=findnumbs.begin(); it!=findnumbs.end(); ++it)
std::cout << ' ' << *(*it);
std::cout << '\n';
return 0;
}