Validate the return value of copy_if - c++

I would like to check if the return value of std::copy_if is valid.
Something like this
auto it=std::copy_if(s.begin(),s.end(),d.begin(),[&](...){...});
if([it]) // ????
{
// do something
}

The return value of copy_if marks the "one past the end" of the destination range. If you passed a range to copy_if that can hold all of your to-be-copied values then you can dereference everything between the begin of your output range up to it - 1.
#include <vector>
#include <algorithm>
#include <iostream>
int main()
{
std::vector<int> s{1,2,3,4,5,6,7,8,9,10};
std::vector<int> d(10);
auto ce = std::copy_if(s.begin(),s.end(),d.begin(),[&](int x){ return x > 5; });
for(auto i = d.begin(); i != ce; ++i)
{
std::cout << *i << "\n";
}
}

A variant of #Pixelchemist's answer is to erase from the returned iterator to the end of the destination. This leaves behind only those elements that satisfied the condition.
#include <vector>
#include <algorithm>
#include <iostream>
int main()
{
std::vector<int> s{1,2,3,4,5,6,7,8,9,10};
std::vector<int> d(10);
auto it = std::copy_if(s.begin(),s.end(),d.begin(),[&](int x){ return x > 5; });
d.erase(it, d.end());
for(int i : d)
{
std::cout << i << "\n";
}
}

copy_if returns a pointer one past the element it last copied. So in your case the destination range would be [d.begin(), it).
Not sure what type of error checking you would want to do but you can for example use the pointers to see how many elements were copied:
unsigned int elementsCopied = it - d.begin();
You can also iterate over the elements copied:
for(auto i = d.begin(); i != it; ++i)
{
//perform action on i
}
If you are still unsure about how copy_if works, c++ reference gives a clear explanation in my opinion.
Perhaps also interesting, this is a possible implementation of copy_if so you can see what is going on:
template <class InputIterator, class OutputIterator, class UnaryPredicate>
OutputIterator copy_if (InputIterator first, InputIterator last,
OutputIterator result, UnaryPredicate pred)
{
while (first!=last) {
if (pred(*first)) {
*result = *first;
++result;
}
++first;
}
return result;
}

Related

How to apply the concept of counting occurrences on strings variables in C++

following program ca calculate the frequency of ints in an array
how to apply this concept on string variable because a string is also an array on the back end
using namespace std;
int counter[10]={0,0,0,0,0,0,0,0,0,0};
int arr [9][9],x;
int main()
{
srand(time(NULL));
cout<<"enter the array \n";
for(int i=0;i<9;i++){
for(int j=0;j<9;j++){
arr[i][j]=rand()%10;
}
}
for(int i=0;i<9;i++){
for(int j=0;j<9;j++){
cout<<arr[i][j]<<" ";
}
cout<<endl;
}
for(int i=0;i<9;i++){
for(int j=0;j<9;j++){
counter[arr[i][j]]++;
}
}
for(int j=0;j<10;j++){
cout<<j<<" : "<< counter[j]<<endl;
}
return 0;
}
Here is how one can count occurrences of anything from anything:
Code
#include <iterator>
#include <map>
#include <algorithm>
template<class InputIt>
auto
occurrences(InputIt begin, InputIt end)
{
std::map<typename std::iterator_traits<InputIt>::value_type, std::size_t> result;
std::for_each(begin, end, [&result](auto const& item){ ++result[item]; });
return result;
}
Usage
#include <string>
#include <iostream>
int main()
{
auto text = std::string{"Hello, World!"};
auto occ = occurrences(begin(text), end(text));
std::cout << occ['l'] << '\n'; // outputs 3
}
Live demo
Explanation
template<class InputIt>
This is a generic (template) function iterating over any input iterator.
auto
Its return type is inferred from its implementation. Spoiler alert: it is a std::map of (value counter, occurrence of this value).
occurrences(InputIt begin, InputIt end)
occurrences is called with a couple of iterators defining a range, generally calling begin(C) and end(C) on your container C.
std::for_each(begin, end, //...
For each element in the range...
[&result](auto const& item){ //...
...execute the following treatment...
++result[item]; });
...increment the occurrence count for the value item, starting with zero if its the first.
This is not an efficient implementation since it copies the values it counts. For integers, characters, etc. its perfect but for complex types you might want to improve this implementation.
It's generic and standard container compatible. You could count anything iterable.
If I understand correctly, you want to count occurrences of strings. STL container map is useful for this purpose. Following is example code.
#include<iostream>
#include<map>
#include<string>
#include<vector>
int main()
{
std::vector<std::string> arrayString;
std::map<std::string, int> counter;
std::map<std::string, int>::iterator it;
arrayString.push_back("Hello");
arrayString.push_back("World");
arrayString.push_back("Hello");
arrayString.push_back("Around");
arrayString.push_back("the");
arrayString.push_back("World");
// Counting logic
for(std::string strVal : arrayString)
{
it = counter.find(strVal);
if(it != counter.end())
it->second += 1; // increment count
else
counter.insert(std::pair<std::string, int>(strVal, 1)); // first occurrence
}
// Results
for(std::map<std::string, int>::iterator it = counter.begin(); it != counter.end(); ++it)
std::cout << it->first << ": " << it->second << std::endl;
return 0;
}
More compact way to write the counting logic is :
// Counting logic
for(std::string strVal : arrayString)
{
++counter[strVal]; // first time -> init to 0 and increment
}

Find last element in std::vector which satisfies a condition

I have this requirement to find the last element in the vector which is smaller than a value.
Like find_first_of but instead of first i want last.
I searched and found that there is no find_last_of but there is find_first_of.
Why is that so? Is the standard way is to use find_first_of with reverse iterators?
Use reverse iterators, like this:
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v{1,2,42,42,63};
auto result = std::find_if(v.rbegin(), v.rend(),
[](int i) { return i == 42; });
std::cout << std::distance(result, v.rend()) << '\n';
}
Live demo.
This is how it is done with reverse iterators:
std::vector<int> vec = {2,3,10,5,7,11,3,6};
//below outputs '3':
std::cout << *(std::find_if(vec.rbegin(), vec.rend(), [](int i) { return i < 4; }));
Just one thing. Be careful with the predicate if you're looking to find the tail-end of the range which includes the predicated element:
int main()
{
std::vector<int> x { 0, 1, 2, 3, 4, 5 };
// finds the reverse iterator pointing at '2'
// but using base() to convert back to a forward iterator
// also 'advances' the resulting forward iterator.
// in effect, inverting the sense of the predicate to 'v >= 3'
auto iter = std::find_if(std::make_reverse_iterator(x.end()),
std::make_reverse_iterator(x.begin()),
[](auto& v) { return v < 3; }).base();
std::copy(iter,
x.end(),
std::ostream_iterator<int>(std::cout, ", "));
}
result:
3, 4, 5,
From ZenXml:
template <class BidirectionalIterator, class T> inline
BidirectionalIterator find_last(const BidirectionalIterator first, const
BidirectionalIterator last, const T& value)
{
for (BidirectionalIterator it = last; it != first;)
//reverse iteration: 1. check 2. decrement 3. evaluate
{
--it; //
if (*it == value)
return it;
}
return last;
}

How do iterators map/know their current position or element

Consider the following code example :
#include <vector>
#include <numeric>
#include <algorithm>
#include <iterator>
#include <iostream>
#include <functional>
int main()
{
std::vector<int> v(10, 2);
std::partial_sum(v.cbegin(), v.cend(), v.begin());
std::cout << "Among the numbers: ";
std::copy(v.cbegin(), v.cend(), std::ostream_iterator<int>(std::cout, " "));
std::cout << '\n';
if (std::all_of(v.cbegin(), v.cend(), [](int i){ return i % 2 == 0; })) {
std::cout << "All numbers are even\n";
}
if (std::none_of(v.cbegin(), v.cend(), std::bind(std::modulus<int>(),
std::placeholders::_1, 2))) {
std::cout << "None of them are odd\n";
}
struct DivisibleBy
{
const int d;
DivisibleBy(int n) : d(n) {}
bool operator()(int n) const { return n % d == 0; }
};
if (std::any_of(v.cbegin(), v.cend(), DivisibleBy(7))) {
std::cout << "At least one number is divisible by 7\n";
}
}
If we look at this part of the code :
if (std::all_of(v.cbegin(), v.cend(), [](int i){ return i % 2 == 0; })) {
std::cout << "All numbers are even\n";
}
which is fairly easy to understand. It iterates over those vector elements , and finds out i%2==0 , whether they are completely divisible by 2 or not , hence finds out they're even or not.
Its for loop counterpart could be something like this :
for(int i = 0; i<v.size();++i){
if(v[i] % 2 == 0) areEven = true; //just for readablity
else areEven = false;
}
In this for loop example , it is quiet clear that the current element we're processing is i since we're actually accessing v[i]. But how come in iterator version of same code , it maps i or knows what its current element is that we're accessing?
How does [](int i){ return i % 2 == 0; }) ensures/knows that i is the current element which iterator is pointing to.
I'm not able to makeout that without use of any v.currently_i_am_at_this_posiition() , how is iterating done. I know what iterators are but I'm having a hard time grasping them. Thanks :)
Iterators are modeled after pointers, and that's it really. How they work internally is of no interest, but a possible implementation is to actually have a pointer inside which points to the current element.
Iterating is done by using an iterator object
An iterator is any object that, pointing to some element in a range of
elements (such as an array or a container), has the ability to iterate
through the elements of that range using a set of operators (with at
least the increment (++) and dereference (*) operators).
The most obvious form of iterator is a pointer: A pointer can point to
elements in an array, and can iterate through them using the increment
operator (++).
and advancing it through the set of elements. The std::all_of function in your code is roughly equivalent to the following code
template< class InputIt, class UnaryPredicate >
bool c_all_of(InputIt first, InputIt last, UnaryPredicate p)
{
for (; first != last; ++first) {
if (!p(*first)) {
return false; // Found an odd element!
}
}
return true; // All elements are even
}
An iterator, when incremented, keeps track of the currently pointed element, and when dereferenced it returns the value of the currently pointed element.
For teaching's and clarity's sake, you might also think of the operation as follows (don't try this at home)
bool c_all_of(int* firstElement, size_t numberOfElements, std::function<bool(int)> evenTest)
{
for (size_t i = 0; i < numberOfElements; ++i)
if (!evenTest(*(firstElement + i)))
return false;
return true;
}
Notice that iterators are a powerful abstraction since they allow consistent elements access in different containers (e.g. std::map).

Returning an iterator from a generic function

I am new to C++ and I am unsure how to do this. I am trying to learn templates.
This is my current code. It sends a container (not specified which type it will receive) and returns true if the integer passes alongside the iterators is in the container. False if it does not appear.
#include <iostream>
#include <vector>
#include <list>
template <typename Iter>
bool function(Iter first, Iter last, const int x)
{
for (auto it = first; it!=last; ++it)
{
if (*it == x)
{
return true;
}
}
return false;
}
int main()
{
std::vector<int> vec = {1,2,5,10,11};
std::list<int> lis = {1,1,5,9,55};
auto first = vec.begin(), last = vec.end();
auto first2 = lis.begin(), last2 = lis.end();
std::cout<<function(first, last, 11);
std::cout<<function(first, last, 9)<<std::endl;
std::cout<<function(first2, last2, 6);
std::cout<<function(first2, last2, 55)<<std::endl;
return 0;
}
I would like to modify this function so that instead of returning a bool, it returns an iterator to the first match. How would I go about doing this? It would be really helpful if someone could push me in the right direction.
I don't really know how to push you in the right direction without just giving you the answer, since it is so simple.
template <typename Iter>
Iter // change 1
function(Iter first, Iter last, const int x)
{
for (auto it = first; it!=last; ++it)
{
if (*it == x)
{
return it; // change 2
}
}
return last; // change 3
}
By the way, this is exactly what std::find does.

Why can I not convert a reverse iterator to a forward iterator?

Well, I know why, it's because there isn't a conversion, but why isn't there a conversion? Why can forward iterators be turned to reverse iterators but not the other way round? And more importantly, what can I do if I want to do this? Is there some adapter that allows you to iterate backwards using a forward iterator?
std::vector<int> buffer(10);
std::vector<int>::iterator forward = buffer.begin();
std::vector<int>::reverse_iterator backward = buffer.rbegin();
++forward;
++backward;
std::vector<int>::iterator forwardFromBackward = std::vector<int>::iterator(backward); // error! Can't convert from reverse_iterator to iterator!
std::vector<int>::reverse_iterator backwardFromForward = std::vector<int>::reverse_iterator(forward); // this is fine
You could write a helper function. One particularity of reverse_iterator is that base() gives a forward iterator that is next from the value that the reverse iterator dereferences to. This is because a reverse iterator physically points to the element after the one it logically points to. So to have the forward iterator to the same item as your reverse_iterator, you'll need to decrement the result of base() by one, or you could increment the reverse iterator first, then take the .base() of that.
Both examples are shown below:
#include <iostream>
#include <vector>
#include <iterator>
//result is undefined if passed container.rend()
template <class ReverseIterator>
typename ReverseIterator::iterator_type make_forward(ReverseIterator rit)
{
return --(rit.base()); // move result of .base() back by one.
// alternatively
// return (++rit).base() ;
// or
// return (rit+1).base().
}
int main()
{
std::vector<int> vec(1, 1);
std::vector<int>::reverse_iterator rit = vec.rbegin();
std::vector<int>::iterator fit = make_forward(rit);
std::cout << *fit << ' ' << *rit << '\n';
}
Warning: this behavior is different from that of the reverse_iterator(iterator) constructor.
It's very common to have two (reverse) iterators span a range of values (such as in begin(),end() and rbegin(),rend()). For any range described by the two reverse iterators rA,rB, the range rB.base(),rA.base() will span the same range in the forward direction.
#include <iostream>
#include <iterator>
#include <vector>
int main() {
std::vector<int> vec{10,11,12,13,14,15};
// spans the range from 13 to 10
auto rfirst=std::rbegin(vec)+2;
auto rlast=std::rend(vec);
// Loops forward, prints 10 11 12 13
for(auto it = rlast.base(); it != rfirst.base(); ++it){
std::cout << *it << " ";
}
}
If conceptually you are only interested in a single item (such as the result of find_if), then use make_forward by #visitor. Even in this case, the range idea helps to keep track of the validity of the reverse iterator:
#include <iostream>
#include <iterator>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> vec{10,11,12,13,14,15};
auto rfirst=std::rbegin(vec);
auto rlast=std::rend(vec);
auto rfound = std::find_if(rfirst,rlast, [](int v){ return v<13; });
if(rfound != rlast){
std::cout << *rfound << " "; // prints 12
auto forwardFound = make_forward(rfound) ;
std::cout << *forwardFound << " "; // prints 12
}
}
You can get forward iterator from reverse iterator using this code
container.begin() + (reverseIter - container.rbegin() - 1);