I'm attempting to use a seeded random_shuffle to simply shuffle a vector, before I use it. I tested this out by doing
#include <iostream>
#include <map>
#include <vector>
#include <algorithm>
#include <cstdlib>
#include <bits/stdc++.h>
using namespace std;
int seed;
int rng(int i)
{
srand(seed);
return rand()%i;
}
int main()
{
vector<int> myVec;
cin >> seed;
for (int i = 0; i < 10; ++i)
myVec.push_back(i);
for (auto it = myVec.begin(); it != myVec.end(); ++it)
cout << *it;
cout << endl;
random_shuffle(myVec.begin(), myVec.end(), rng);
for (auto it = myVec.begin(); it != myVec.end(); ++it)
cout << *it;
}
and it worked just fine. This lets me enter an int for the seed, and then prints out the before and after. However, when I tried to insert it into a class and run a build task with VSCode, it exploded.
class Test
{
public:
Test(int seed)
{
random = seed;
for (int i = 0; i < 10; ++i)
myVec2.push_back(i);
random_shuffle(myVec2.begin(), myVec2.end(), r);
}
private:
vector<int> myVec2;
int random;
int r(int i)
{
srand(random);
return rand()%i;
}
};
Here's the errors that came up:
25:54 required from here
error: must use '.*' or '->*' to call pointer-to-member function in '__rand (...)', e.g. '(... ->* __rand) (...)'
4619 | _RandomAccessIterator __j = __first + __rand((__i - __first) + 1);
Why is random_shuffle functioning correctly in main(), but not a class?
rng is a global function. r is a member function of a class.
Consider it from the viewpoint of random_shuffle. When it wants to call r, on what object will it call it? Since it knows nothing about your class it simply won't be able to. This is what the error message is trying to tell you (clumsily).
One typical way would be to make int r(int i) static. But then, you won't have access to random. A more modern way would be to use a lambda:
random_shuffle(myVec2.begin(), myVec2.end(), [this](int i){return r(i);} );
Basically, the lambda is an object wrapping a function that calls r(i) for you, but on the this pointer.
As #cigien recommends, using shuffle instead would be a very good idea as the standard changed a long time ago. See: https://en.cppreference.com/w/cpp/algorithm/random_shuffle This would remove the need for r or rng altogether and get rid of this question :-)
Related
I have got a small problem. I want to capitalize on doubled letters in a string. I managed to compile a program, but not successfully.
#include <iostream>
#include <cctype>
#include <string>
std::string::iterator function(
std::string::const_iterator a,
std::string::const_iterator b,
std::string::const_iterator e)
{
for (; a < b; a++)
{
if (*a == *(a + 1))
{
toupper(*a);
toupper(*(a + 1));
}
}
}
int main()
{
std::string in = "peppermint 1001 bubbles balloon gum", out(100, '*');
auto e = function(in.cbegin(), in.cend(), out.begin());
int n = e - out.begin();
std::string s = out.substr(0, n);
bool b = (s == "pePPermint 1001 buBBles baLLOOn gum");
std::cout << std::boolalpha << b << std::endl;
}
What do I do wrong?
You have a couple of issues there.
Firstly, your function promised to return std::string::iterator
std::string::iterator function(....)
{
//... return statement is missing here!
}
and you are not keeping the promise. This will leads to undefined behaviour. For example, in your case, it just compiles and does not give the output.
In order to get a defined behaviour, you should return from the function
std::string::iterator function(...)
{
// ... code
return {}; // return appropriately iterator of std::string
}
Secondly, you want to modify the characters of the string, which requires a modifiable iterator rather than std::string::const_iterator.
Then in the loop, you need to alter the capitalized charector by reassigning to it. For example:
*a = toupper(*a);
Thirdly, you should be careful about doing this in the for-loop of your function
for(; a < b; a++)
{
if(*a == *(a + 1)) // --->here
// ... code
}
What would happen for the case when a== str.end()-1, you still would do the increment(i.e. *(a + 1)), right?. Incrementing the end iterator again leads you Undefined behaviour.
In that case, you could use std::next from <iterator> header to safely check this.
Following is the demonstrative code which clears the issues mentioned above:
#include <iostream>
#include <string>
#include <iterator> // std::next
std::string::iterator function(
std::string::iterator a,
std::string::iterator b,
std::string::iterator e)
{
auto beg = a;
for (; a < b; a++)
{
if (std::next(a) != b && *a == *std::next(a)) {
*a = toupper(*a);
*std::next(a) = toupper(*std::next(a));
}
}
std::cout << std::string{ beg, b };
return {}; // return appropriately iterator of std::string
}
prints for now: https://godbolt.org/z/ZsLHxw
pePPermint 1001 buBBles baLLOOn gum
I assume that you want somehow to get the output to the third function parameter std::string::iterator e. I will let that part for you to figure it out. Meanwhile, have a look at the standard algorithm function std::transform, which might be handy to do such kind of transformation.
Answers are already given. I want additionally to show an answer based on existing C++ functionality. For your given task there is a function existing in the C++ standard algorithm library. It is called std::adjacent_find. Please see here.
With that you could rewrite your code simply to:
#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>
int main() {
std::string test{ "peppermint 1001 bubbles balloon gum" };
// Find all duplicates
for (auto il = std::adjacent_find(test.begin(), test.end()); il != test.end(); il = std::adjacent_find(il+1, test.end())) {
// If duplicate found, then convert both to uppercase
*il = std::toupper(*il);
*(il + 1) = std::toupper(*(il+1));
}
std::cout << test << '\n';
return 0;
}
We call this function in a simple for loop, until no more duplicates could be found.
Maybe it can give you an idea for a more simple implementation.
Your function exhibits undefined behavior because it never returns a value. Please compile with -Wall -Wextra to enable all compiler warnings to avoid such unnecessary bugs.
I am stuck in multiple Async problems like that
example:
void updateList(vector<int> &list, int value){
list.push_back(value);
}
int main(){
vector<future<void>> asyncTasks;
vector<int> list;
for(int i = 0; i < 10; i ++){
asyncTasks.push_back(async(launch::async, updateList,i ));
}
for(auto &&f : asyncTasks){
f.get();
}
}
The problem is sometimes it throws errors about insert violent.
Can you give me any ideas ?
Well the problem is that you are doing 2 things at once in updateList:
Calculating a value based on the index given (by calculation I mean just using it)
Adding a value to a container
Doing the second in parallel does not make much sense, since you would have to serialize on the container, otherwise you get data races, which is the reason for your errors.
void updateList(vector<int> &list, int value){
list.push_back(value); //< Data race-> Undefined behavior -> Sometimes Crash
}
But we can do the stuff which can be paralleled easily, namely 1. the calculation of a value.
If we just add dummy zeros in the container, at first, we are allowed to modify the elements in the container i.e. std::vector, since we don't modify the container it self, like count or order, only its members.
So after that you can calculate in parallel, but why not directly use the new parallel algorithms to do that for us? So I added a second solution.
Also this discovery that your work consists of work which can not be paralleled and work which can, can be found in Amdahl's law.
#include <iostream>
#include <vector>
#include <numeric>
#include <algorithm>
#include <execution>
#include <future>
//Your modified solution
void updateList(std::vector<int> &list, int value){
const auto index = value;
//Do the heavy stuff here
list[index] = value;
}
int main(){
std::vector<int> list(10);
std::vector<std::future<void>> asyncTasks;
for(int i = 0; i < 10; i ++){
asyncTasks.emplace_back(std::async(std::launch::async, &updateList, std::ref(list), i));
}
for(auto &f : asyncTasks){
f.get();
}
std::for_each(list.begin(),list.end(), [](auto v) {std::cout << v << " ";});
std::cout << "\n";
}
//Better solution:
int heavy_work_calculation(int input) {
//Do the heavy stuff here
return input;
}
int main(){
std::vector<int> list(10);
std::iota(list.begin(), list.end(), 0);
std::transform(std::execution::par_unseq, list.begin(), list.end(),
list.begin(), heavy_work_calculation);
std::for_each(list.begin(),list.end(), [](auto v) {std::cout << v << " ";});
std::cout << "\n";
}
I am new to c++ std::set user.
Here is the question: I initialize a set in main function, and I want to insert an
element by calling some function. But it doesn't seem to work.
Is it about call by reference or something else? Thanks!
#include <iostream>
#include <set>
using namespace std;
void f(set<int> myset){
set<int>::iterator it;
// insert element
for(int i=1;i<11;i++){
myset.insert(i*10);
}
}
int main ()
{
set<int> myset;
set<int>::iterator it;
f(myset);
//output element
for(it=myset.begin();it!=myset.end();it++){
cout<<*it<<" ";
}
return 0;
}
You are right, you need to pass by reference, otherwise you would be modifying a local copy of the set:
void f(set<int>& myset)
{ // ^
for(int i = 1; i < 11; i++)
myset.insert(i*10);
}
I'm making a program that uses the std::generate_n function. I can get it to work fine with arrays, but I can't figure out how to make it work with a list container. Here is what I have:
#include <iostream>
#include <algorithm>
#include <list>
using namespace std;
int current = 0;
int UniqueNumber () { return ++current; }
int main ()
{
list<int> L;
list<int>::iterator it;
generate_n (L.begin(), 9, UniqueNumber);
cout << "list contains:";
for (it=L.begin(); it!=L.end(); ++it)
cout << ' ' << *it << '\n';
return 0;
}
The output only displays "list contains:" with nothing after that. I know my output loop functions correctly because I tried it manually with the insert() method, so the problem is something with the generate_n function. I think I'm passing the arguments wrong. Anyone know what I did?
You want to use an insert-iterator to add items to your list:
generate_n (back_inserter(L), 9, UniqueNumber);
Be sure to #include <iterator> to use it. Another possibility would be to use std::iota:
list<int> L(10);
std::iota(L.begin(), L.end(), 1);
Oh, and to display the contents of the list, you probably want:
std::copy(L.begin(), L.end(), ostream_iterator<int>(std::cout, "\n"));
or (in C++11):
for (auto i : L)
std::cout << ' ' << i << '\n';
generate_n doesn't insert, it just dereferences and assigns.
See the below possible implementation of generate_n (copied from here):
template< class OutputIt, class Size, class Generator >
OutputIt generate_n( OutputIt first, Size count, Generator g )
{
for( Size i = 0; i < count; i++ ) {
*first++ = g();
}
return first;
}
So you need to make sure the list is the appropriate size before you call it.
So, change:
list<int> L;
to:
list<int> L(9);
I want to convert this simple code:
void setZComp(Imath::V3f& pt)
{
pt.z = 0.0;
}
int myfunc()
{
...
std::vector<Imath::V3f> vec(5,Imath::V3f(1.0,1.0,1.0));
std::for_each(vec.begin(),vec.end(),boost::bind(&setZComp,_1));
...
}
to something like that, in order to not have setZComp declared outside but some sort of inline declaration
int myfunc()
{
...
boost::function<double(Imath::V3f&)> f = (boost::lambda::_1 ->* &Imath::V3f::z = 0.0) ;
std::for_each(vec.begin(),vec.end(),boost::bind(&f,_1));
...
}
I'm quite new to Boost Bind and Lambda and I don't know if this can be done in some way. Obviously the code above does not work.
Are you using a sledgehammer to break a nut? Sometimes, I think it is simpler to just use a normal for loop and set the variable explicitly yourself. This makes the code much easier to read and maintain.
typedef std::vector<Imath::V3f> V3fVector;
V3fVector vec(5,Imath::V3f(1.0,1.0,1.0));
for (V3fVector::iterator i = vec.begin(), iEnd = vec.end(); iEnd != i; ++i)
i->z = 0.0;
As much as boost bind is useful, its also a syntactical mess that make simple code unreadable.
If you cannot use a C++11 lambda, then you can use boost::lambda::bind.
So in your case something like the following:
boost::lambda::bind(&Imath::V3f::z, boost::lambda::_1) = 0.0
A full example since I don't know your internals:
struct S
{
S():i(0){};
int i;
};
int main()
{
std::vector<S> vec;
vec.push_back(S());
std::for_each(vec.begin(), vec.end(), boost::lambda::bind(&S::i, boost::lambda::_1) = 5);
std::cout << vec.front().i << std::endl; // outputs 5
return 0
}
You might also consider taking a look at boost::phoenix. I think it's a more fully fleshed out implementation of functional programming for c++ than the lambda library.
As explained in the section Member variables as targets:
A pointer to a member variable is not really a function, but the first argument to the [boost::lambda::bind] function can nevertheless be a pointer to a member variable. Invoking such a bind expression returns a reference to the data member.
So to construct a lambda expression that accesses the z member, you can use:
boost::lambda::bind(&Imath::V3f::z, boost::lambda::_1)
The returned object can itself be used in other expressions. For example,
boost::lambda::bind(&Imath::V3f::z, boost::lambda::_1) = 0.0
means "obtain the double ref to the z member of the first argument (type Imath::V3f&) and assign the value 0.0".
You can then use this lambda with Boost.Function and std::for_each:
boost::function<void(Imath::V3f&)> f = boost::lambda::bind(&Imath::V3f::z, boost::lambda::_1) = 0.0;
std::for_each(vec.begin(), vec.end(), f);
For reference, here is a complete, compilable example:
#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <boost/function.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/lambda/lambda.hpp>
namespace Imath
{
class V3f
{
public:
double x, y, z;
V3f(double x_, double y_, double z_)
: x(x_), y(y_), z(z_)
{
}
friend std::ostream& operator<<(std::ostream& os, const V3f& pt) {
return (os << '(' << pt.x << ", " << pt.y << ", " << pt.z << ')');
}
};
}
int main()
{
std::vector<Imath::V3f> vec(5, Imath::V3f(1.0, 1.0, 1.0));
boost::function<void(Imath::V3f&)> f = boost::lambda::bind(&Imath::V3f::z, boost::lambda::_1) = 0.0;
std::for_each(vec.begin(), vec.end(), f);
std::vector<Imath::V3f>::iterator it, end = vec.end();
for (it = vec.begin(); it != end; ++it) {
std::cout << *it << std::endl;
}
return EXIT_SUCCESS;
}
Outputs:
(1, 1, 0)
(1, 1, 0)
(1, 1, 0)
(1, 1, 0)
(1, 1, 0)
If you have access to a recent version of g++ with C++11 support, or MSVC 2010, you could do the following:
int myfunc()
{
...
std::for_each(vec.begin(),vec.end(),[](Imath::V3f& pt){ pt.z = 0.0; });
...
}
If you want to use boost::lambda, I sometimes find it cleaner to declare a "pointer-to-member" variable immediately before the line that contains the lambda, which then allows you to use the ->* operator instead of using boost::lambda::bind.
However, as Alan pointed out, a simple loop here might be the simplest solution. Use BOOST_FOREACH to make it even simpler.
Here's a modified version of mkaes's sample implementation that uses operator ->* instead of bind, and it also shows how to use BOOST_FOREACH as an alternative.
#include <iostream>
#include <vector>
#include <boost/lambda/lambda.hpp>
#include <boost/foreach.hpp>
// I like to provide alternate names for the boost::lambda placeholders
boost::lambda::placeholder1_type& arg1 = boost::lambda::_1 ;
boost::lambda::placeholder2_type& arg2 = boost::lambda::_2 ;
boost::lambda::placeholder3_type& arg3 = boost::lambda::_3 ;
struct S
{
S():i(0){};
int i;
};
int main()
{
std::vector<S> vec;
vec.push_back(S());
// Define this pointer-to-member so we can
// use it in the lambda via the ->* operator
int S::* i = &S::i ;
std::for_each(vec.begin(), vec.end(), &arg1->*i = 5);
std::cout << vec.front().i << std::endl; // outputs 5
// Alternatively, just use a simple foreach loop
BOOST_FOREACH( S & s, vec )
{
s.i = 6 ;
}
std::cout << vec.front().i << std::endl; // outputs 6
return 0 ;
}