I need to iterate over a vector from the end to the beginning. The "correct" way is
for(std::vector<SomeT>::reverse_iterator rit = v.rbegin(); rit != v.rend(); ++rit)
{
//do Something
}
When //do Something involves knowing the actual index, then some calculations need to be done with rit to obtain it, like index = v.size() - 1 - (rit - v.rbegin)
If the index is needed anyway, then I strongly believe it is better to iterate using that index
for(int i = v.size() - 1; i >= 0; --i)
{
//do something with v[i] and i;
}
This gives a warning that i is signed and v.size() is unsigned.
Changing to
for(unsigned i = v.size() - 1; i >= 0; --i) is just functionally wrong, because this is essentially an endless loop :)
What is an aesthetically good way to do what I want to do which
is warning-free
doesn't involve casts
is not overly verbose
As you've noted, the problem with a condition of i >= 0 when it's unsigned is that the condition is always true. Instead of subtracting 1 when you initialize i and then again after each iteration, subtract 1 after checking the loop condition:
for (unsigned i = v.size(); i-- > 0; )
I like this style for several reasons:
Although i will wrap around to UINT_MAX at the end of the loop, it doesn't rely on that behavior — it would work the same if the types were signed. Relying on unsigned wraparound feels like a bit of a hack to me.
It calls size() exactly once.
It doesn't use >=. Whenever I see that operator in a for loop, I have to re-read it to make sure there isn't an off-by-one error.
If you change the spacing in the conditional, you can make it use the "goes to" operator.
There's nothing to stop your reverse_iterator loop also using the index as described in multiple other answers. That way you can use the iterator or index as needed in the // do the work part, for minimal extra cost.
size_t index = v.size() - 1;
for(std::vector<SomeT>::reverse_iterator rit = v.rbegin();
rit != v.rend(); ++rit, --index)
{
// do the work
}
Though I'm curious to know what you need the index for. Accessing v[index] is the same as accessing *rit.
to be aesthetically pleasing! ;)
for(unsigned i = v.size() - 1; v.size() > i; --i)
I would prefer the reverse iterator variant, because it's still easy to interpret and allows to avoid index-related errors.
Sometimes you can simply use the BOOST_REVERSE_FOREACH, which would make your code look the following way:
reverse_foreach (int value, vector) {
do_something_with_the_value;
}
Actually speaking, you can always use foreach statements for these kinds of loops, but then they become a bit unobvious:
size_t i = 0;
foreach (int value, vector) {
do_something;
++i;
}
In C++20 one can use ranges (#include <ranges>)
//DATA
std::vector<int> vecOfInts = { 2,4,6,8 };
//REVERSE VECTOR (
for (int i : vecOfInts | std::views::reverse)
{
std::cout << i << " ";
}
or if it is required to save in a different variable.
//SAVE IN ANOTHER VARIABLE
auto reverseVecOfInts = std::views::reverse(vecOfInts);
//ITERATION
for (int i : reverseVecOfInts)
{
std::cout << i << " ";
}
Try out a do while :
std::vector<Type> v;
// Some code
if(v.size() > 0)
{
unsigned int i = v.size() - 1;
do
{
// Your stuff
}
while(i-- > 0);
}
Hi i think better way use iterator as you use in first sample and if you need get iterator index you can use
std::distance to calculate it, if i understand your question
loop condition i != std::numeric_limits<unsigned>::max() ... or use UINT_MAX if you think its to verbose.
or another way:
for(unsigned j=0, end=v.size(), i=end-1; j<end; --i, ++j)
or
for(unsigned end=v.size(), i=end-1; (end-i)<end; --i)
I think that:
for(unsigned i = v.size() - 1; i >= 0; --i)
is fine if you check
!v.empty()
earlier.
for (it = v.end()-1; it != v.begin()-1; --it)
{
}
The "goes to" operator definitely messes with my head.
Related
The expected output is 1a1b1c but I only get 1a1b If I try putting '-1' next to input.size() in the for loop but that will just ignore the bug. What I'm looking for is that I want to be able to iterate through the last member of the string without going out of bounds.
std::string input = "abc";
for (unsigned int i = 0; i < input.size(); i++){
int counter = 1;
while(input.at(i) == input.at(i+1) && i < input.size()-1){
counter++;
i++;
}
number.push_back(counter);
character.push_back(input.at(i));
}
Few points for you to consdier:
1: for (unsigned int i = 0; i < input.size(); i++) specifically i++. This is a postfix operation meaning it returns i then increments the value of i. Not as big a deal here with integers but with iterators this can get very expensive as you create a copy of the iterator each time. Prefer to say what you mean / what you actually want, which is to increment i, not get a copy of i and increment i afterwards. So prefer ++i which only increments i and does not make a copy.
2: unsigned int i = 0 Firstly its better than using an int which has a signed -> unsigned conversaion every comparison with input.size() which returns a size_t. Secondly unsigned int is not guaranteed to be big enough to hold the size of the string and requires a promotion from (probably) 32 bit -> 64 bit unsigned to compare with size_t
3: cognitive complexity, nested loops which both mutate the same invariant (in this case i) makes the code more difficult to reason about and will ultimately lead to more bugs as code evolves over time. where possible only have one place where a loop invariant is mutated.
4: As pointed out by others the while loop while(input.at(i) == input.at(i+1) && i < input.size()-1) can exceed the size of the string and using the .at member function of string will throw for an out of bounds access. This can be simply resolved with point 3 by refactoring ther nested loop into a single loop.
5: Avoid so many calls to .at, we are in complete control of the index we use to index the string so you can use operator[] safely as long as we can guarantee i will always be a valid index which in this case i think you can.
6: i < input.size() using < when its not the check you want and its much more expensive than the check you actually want which is i != input.size(). Check out this trivial comparison in compiler explorer
Thankfully the fix from shadowranger Fixes your problem completely ie: while(i < s.size()-1 && s.at(i) == s.at(i+1)) However i would like to offer an alternitive with no nested loops to show you how to avoid my points 3,4, 5 and 6 :
void do_the_thing(std::string const& s) {
std::cout << "Considering: \"" + s + "\"\n";
if(s.empty()) {
return;
}
size_t const length = s.length(); // avoiding repeated calls to length which never changes in this case
if(length == 1) {
std::cout << "1" << s[0] << "\n";
return;
}
std::vector<unsigned> number;
std::vector<char> character;
// do the stuff your example did
char last = s[0];
unsigned same_count = 1;
for(size_t ii = 1; ii != length; ++ii) {
char const cur = s[ii];
if(cur == last) {
++same_count;
} else {
number.push_back(same_count);
character.push_back(last);
last = cur;
same_count = 1;
}
}
if(*s.rbegin() == last) {
number.push_back(same_count);
character.push_back(last);
}
// print the things or use them in some way
assert(number.size() == character.size());
size_t const out_len = character.size();
for(size_t ii = 0; ii != out_len; ++ii) {
std::cout << number[ii] << character[ii];
}
std::cout << "\n";
}
I am reversing a string and comparing it to another string whether it matches or not.
String d is reversed correctly, but in the If statement, it is not comparing. Strings comparing like this usually works I have done it before. Can someone explain this?
Thank You
int main()
{
string a, d, e;
int b, c;
cin >> a >> e;
for (int i = a.size(); i >= 0; i--)
{
d.push_back(a[i]);
}
cout << d;
if (d == e)
cout << "YES";
else
cout << "NO";
return 0;
}
If a string is 4 characters long, then s[4] will give you 1 past the end of the string. So here:
for (int i = a.size(); i >= 0; i--)
when you use i which would be 4 in the first step, you are accessing past the end of the string. You could do:
for (int i = a.size() - 1; i >= 0; i--)
but be careful if a is empty! You will underflow the integer and end up with big problems! You could check for empty string at the top of your function but that is extra work. To avoid this problem, you could use an iterator, but these only go forward :( Oh wait, reverse_iterator!
for (auto rit = s.rbegin(); rit != s.rend(); ++rit) {
d.push_back(*rit);
This will solve the problem. You could wrap this up in a function, call it reverse! Luckily, this actually exists: std::reverse:
a = d;
std::reverse(std::begin(d), std::end(d));
Easy peasy
Note that the i = a.size() when used in d.push_back(a[i]); will lead to undesired subscript access (recall that indexing starts with 0, while size() returns the amount of elements in a container).
You should look toward this implementation:
#include <string>
#include <iostream>
int main()
{
std::string a, d, e;
int b, c;
std::cin >> a >> e;
for (auto i = a.rbegin(); i != a.rend(); ++i) // Using return iterators
{
d.push_back(*i); // Dereference the iterator and push_back() it
}
std::cout << d << std::endl;
if (d == e)
std::cout << "YES" << std::endl;
else
std::cout << "NO" << std::endl;
return 0;
}
Example:
foo
oof
oof
YES
This approach uses reverse iterators on the string. Note, in order to advance this type of iterator, you use the same increment operation, only in this case, the iterator goes backwards (from the end of container to beginning).
The issue is that you accessing the NUL terminator of a, and putting that at the start of d. The behaviour of your program was undefined up to but not including C++11.
Using
a = d;
std::reverse(std::begin(d), std::end(d));
is the solution. Alternatives such as character by character access are poor due to the potential pitfalls with using unsigned arithmetic. Using the C++ standard library can also help your compiler in its optimisation choices.
Rather than reversing the string then comparing, you could compare the strings using std::equal:
bool result = std::equal(a.rbegin(), a.rend(),
d.begin(), d.end());
If all you want is to check if the string is a palindrome, you don't need to allocate a new string. Here's a much more efficient way:
#include <algorithm>
#include <string_view>
[[nodiscard]] constexpr bool IsPalindrome(std::string_view const str) noexcept {
auto begin = str.begin();
auto mid = begin + str.size() / 2;
return std::equal(begin, mid, str.rbegin());
}
The usual idiom for writing a loop is to start at the beginning and stop when you've passed the last element. With an index it looks like this:
for (int i = 0; i < a.size(); ++i) {
// do something with a[i]
}
Note that the terminating condition becomes true when i goes off the end.
To do that when you want to go in the other direction you have two choices:
for (int i = a.size(); i > 0; --i) {
// do something with a[i - 1]
}
In this case, the element we're interested in is a[i - 1]. The loop starts with the topmost element, when i is a.size(), and stops after the last element, when i becomes 0 and accessing a[i - 1] would be off the end.
That's a bit tricky to visualize, so you might be tempted to write it like this instead:
for (int i = a.size() - 1; i >= 0; --i) {
// do something with a[i]
}
This version has a subtle bug, and should not be your usual approach. The problem is that a.size() is unsigned. When a is empty, a.size() is 0, and a.size() - 1 wraps around and becomes a very large value. So don't use it.
Another way to avoid problems like this is to use iterators, which handle the details of recognizing the beginning and end of the sequence:
for (auto iter = std::begin(a); iter != std::end(a); ++iter) {
// do something with *iter
}
This is easily adapted to reverse iteration:
for (auto iter = std::rbegin(a); iter != std::rend(a); ++iter) {
// do something with *iter
}
And yet another possibility is to let the standard library handle the iteration:
void do_someting_with_a_sub_i(int) {
// whatever
}
std::for_each(std::begin(a), std::end(a), do_someting_with_a_sub_i);
or, in reverse,
std::for_each(std::rbegin(a), std::rend(a), do_someting_with_a_sub_i);
(yes, modern fashion calls for using a lambda instead of writing out do_something_with_a_sub_i. Sigh.)
I'm hoping you can entertain this hypothetical question even though this has probably never been a problem for anyone ever.
I used to write my for loops like
for (size_t i = 0; i < container.size(); ++i)
to avoid the warnings related to comparing a signed and unsigned, but after being bitten a few too many times trying to involve i in operations that resulted in negative numbers, I started writing them like this, casting the size to int to also avoid that warning:
for (int i = 0; i < (int)container.size(); ++i)
Now lets say that there's a case where container.size() > INT_MAX and in the loop we have something like.
for (int i = 0; i < (int)container.size(); ++i) {
size_t x = 0;
while (i - x++ > INT_MIN) {
// do stuff
}
}
We need i to be signed, but we also need i to be able to represent a number larger than INT_MAX. I know that the super simple answer here to use long, but then the same problem arises eventually even if you use long long if you have to run your loop > LLONG_MAX times.
In this case, you would finally be forced into using an unsigned type for your counter variable capable of representing a number that large, but you would still need to be able to check this condition
while (i - x++ > LLONG_MIN)
how do you do it? (given you actually have some reason to run a loop 9 quintillion times).
I guess a reasonable approach would be to use some bignum library. A less reasonable, but probably more interesting approach would be to implement what's needed on your own.
Most containers have a size_type typedef to specify the data type that is used for indexes and sizes within the container. For example, if container is a std::vector, you would use std::vector::size_type instead of int or even size_t:
for (std::vector<type>::size_type i = 0; i < container.size(); ++i)
{
// use container[i] as needed
}
An alternative solution is to use iterators instead of indexes, then you don't need to worry about any counter data type at all:
for (std::vector<type>::iterator iter = container.begin(); iter != container.end(); ++iter)
{
// use *iter as needed
}
Which can be simplified using auto in C++11 and later:
for (auto iter = container.begin(); iter != container.end(); ++iter)
{
// use *iter as needed
}
Your inner while loop doesn't really make any sense to me, but if you really need something like INT_MIN for a container, you can use std::numeric_limits to get the min/max values of the container's size_type, eg:
typedef std::vector<type>::size_type container_size_type;
for (container_size_type i = 0; i < container.size(); ++i) {
container_size_type x = 0;
while ((i - x++) > std::numeric_lists<container_size_type>::min()) {
// do stuff
}
}
It seems it would be easier to just loop between the two indexes instead:
typedef std::vector<type>::size_type container_size_type;
for (container_size_type i = 0; i < container.size(); ++i) {
for (container_size_type j = 0; j < i; ++j) {
// do stuff
}
}
Or:
typedef std::vector<type>::size_type container_size_type;
for (container_size_type i = 0; i < container.size(); ++i) {
for (container_size_type j = i; j >= 0; --j) {
// do stuff
}
}
Depending on which direction you want the inner loop to run.
However, either of those loops can be re-written using iterators as well (replace 'auto' with the appropriate type if you are not using C++11), eg:
for (auto iter = container.begin(); iter != container.end(); ++iter) {
for (auto iter2 = container.begin(); iter2 != iter; ++iter2) {
// do stuff
}
}
for (auto iter = container.begin(); iter != container.end(); ++iter) {
for (auto iter2 = std::vector<type>::reverse_iterator(iter); iter2 != container.rend(); ++iter2) {
// do stuff
}
}
If you really had a need to execute such a thing its likely that you care about the execution time because its going to take forever. At that point you have to look at something like intel's AVX, which now supports up to 512 bit numbers. In practical terms, 64 bits is almost always big enough for a loop because I seriously doubt anything that takes 2^64 (1.8e19) cycles to finish is ever going to complete in your life time because there are only about 3e18 nano seconds in a human life time.
You can use a library that can handle and compare large numbers. Or you can add another variable that will represent how many time you reached max number.
for example:
long i = 0;
long t = 0;
while (true) {
// DO your thing.
if (i >= 2000000000) {
i = 0;
++t;
if (t >= 2000000000)
break;
}
}
Or using a for loop
for (long i = 0; i < 2000000000; ++i)
for (long j = 0; j < 2000000000; ++j) {
// Do your thing
}
This way you will loop i * j times.
Here is a simple question I have been wondering about for a long time :
When I do a loop such as this one :
for (int i = 0; i < myVector.size() ; ++i) {
// my loop
}
As the condition i < myVector.size() is checked each time, should I store the size of the array inside a variable before the loop to prevent the call to size() each iteration ? Or is the compiler smart enough to do it itself ?
mySize = myVector.size();
for (int i = 0; i < mySize ; ++i) {
// my loop
}
And I would extend the question with a more complex condition such as i < myVector.front()/myVector.size()
Edit : I don't use myVector inside the loop, it is juste here to give the ending condition. And what about the more complex condition ?
The answer depends mainly on the contents of your loop–it may modify the vector during processing, thus modifying its size.
However if the vector is just scanned you can safely store its size in advance:
for (int i = 0, mySize = myVector.size(); i < mySize ; ++i) {
// my loop
}
although in most classes the functions like 'get current size' are just inline getters:
class XXX
{
public:
int size() const { return mSize; }
....
private:
int mSize;
....
};
so the compiler can easily reduce the call to just reading the int variable, consequently prefetching the length gives no gain.
If you are not changing anything in vector (adding/removing) during for-loop (which is normal case) I would use foreach loop
for (auto object : myVector)
{
//here some code
}
or if you cannot use c++11 I would use iterators
for (auto it = myVector.begin(); it != myVector.end(); ++it)
{
//here some code
}
I'd say that
for (int i = 0; i < myVector.size() ; ++i) {
// my loop
}
is a bit safer than
mySize = myVector.size();
for (int i = 0; i < mySize ; ++i) {
// my loop
}
because the value of myVector.size() may change (as result of , e.g. push_back(value) inside the loop) thus you might miss some of the elements.
If you are 100% sure that the value of myVector.size() is not going to change, then both are the same thing.
Yet, the first one is a bit more flexible than the second (other developer may be unaware that the loop iterates over fixed size and he might change the array size). Don't worry about the compiler, he's smarter than both of us combined.
The overhead is very small.
vector.size() does not recalculate anything, but simply returns the value of the private size variable..
it is safer than pre-buffering the value, as the vectors internal size variable is changed when an element is popped or pushed to/from the vector..
compilers can be written to optimize this out, if and only if, it can predict that the vector is not changed by ANYTHING while the for loop runs.
That is difficult to do if there are threads in there.
but if there isn't any threading going on, it's very easy to optimize it.
Any smart compiler will probably optimize this out. However just to be sure I usually lay out my for loops like this:
for (int i = myvector.size() -1; i >= 0; --i)
{
}
A couple of things are different:
The iteration is done the other way around. Although this shouldn't be a problem in most cases. If it is I prefer David Haim's method.
The --i is used rather than a i--. In theory the --i is faster, although on most compilers it won't make a difference.
If you don't care about the index this:
for (int i = myvector.size(); i > 0; --i)
{
}
Would also be an option. Altough in general I don't use it because it is a bit more confusing than the first. And will not gain you any performance.
For a type like a std::vector or std::list an iterator is the preffered method:
for (std::vector</*vectortype here*/>::iterator i = myVector.begin(); i != myVector.end(); ++i)
{
}
If I have a set in C++, and it contains numbers from 0 to n. I wish to find out the number that is missing from 1 to n and output that and if none of them is missing, then output the number (n+1).
For example, if the set contains, 0 1 2 3 4 5 6 7, then it should output 8
If it contains, 0 1 3 4 5 6, then it should output 2.
I made the following code for this, but it always seems to output 0. I dont know what is the problem.
set<int>::iterator i = myset.begin();
set<int>::iterator j = i++;
while (1)
{
if ( *(j) != *(i)+1 )
{
cout<<*(j)<<"\n";
break;
}
else
{
i++;
j++;
}
}
What is the problem? Thanks!
The problem is that you're advancing i:
set<int>::iterator i = myset.begin(); // <-- i points to first element
set<int>::iterator j = i++; // <-- j points to first element
// i points to second!
while (1)
{ // so if our set starts with {0, 1, ...}
if ( *(j) != *(i)+1 ) // then *j == 0, *i == 1, *i + 1 == 2, so this
// inequality holds
What you meant to do is have j be the next iterator after i:
std::set<int>::iterator i = myset.begin(), j = myset.begin();
std::advance(j, 1);
With C++11, there's also std::next():
auto i = myset.begin();
auto j = std::next(i, 1);
Or, alternatively, just reverse your construction:
std::set<int>::iterator j = myset.begin();
std::set<int>::iterator i = j++; // now i is the first element, j is the second
Or, lastly, you really only need one iterator:
int expected = 0;
for (std::set<int>::iterator it = myset.begin(); it != myset.end();
++it, ++expected)
{
if (*it != expected) {
std::cout << "Missing " << expected << std::endl;
break;
}
}
The easiest stuff: Use count() function of set to check whether an element is present in set or not.
The count() takes an integer argument: The number whose existence in the set is to be checked. If the element is present in set, count() returns a non zero value, else it returns 0.
For example:
#include <iostream>
#include <set>
using namespace std;
int main()
{
set<int> s;
//I insert 0 - 4 in the set.
for(int i=0;i < 5; ++i)
s.insert(i);
//Let 10 be the 'n'.
for(int i = 0; i < 10; ++i)
{
//If i is NOT present in the set, the below condition will be true.
if (!s.count(i))
cout<<i<<" is missing!\n";
}
}
One problem is that you access beyond the end of the set if the set is
dense, which is undefined behavior. Another is that you always output
an element in the set (*j, where j is an iterator into the set);
according to your description, what you want to output is a value which
isn't in the set.
There are a couple of ways of handling this. The simplest is probably
just to maintain a variable expected, initialized with 0 and
incremented each time. Something like the following.
int
firstAvailable( std::set<int> const& allocated )
{
int expected = 0;
for ( auto current = allocated.begin(), end = allocated.end();
current != end && *current == expected;
++ current ) {
++ expected;
}
return expected;
}
If you don't want to return 0 if the list isn't empty, but starts with
some other value, initialize expected with the first element of the
set (or with whatever you want to return if the set is empty).
EDIT:
Of course, other algorithms may be better. For this sort of thing, I usually use a bit map.
The problem with your original code has already been pointed out in the other answers. You're modifying i while assigning j. You can fix this by initializing the iterators as:
set<int>::iterator i = myset.begin();
set<int>::iterator j = i;
j++;
A more elegant solution is to take advantage of the fact that the sum of all values up to n is n * (n + 1) / 2. You can calculate the sum of the actual values, and subtract it from the full sum to obtain the missing value:
int findMissing(const std::set<int>& valSet) {
int valCount = valSet.size();
int allSum = (valCount * (valCount + 1)) >> 1;
int valSum = std::accumulate(valSet.begin(), valSet.end(), 0);
return allSum - valSum;
}
The big advantage of this approach is that it does not rely on using a container where iterators provide the values in sorted order. You can use the same solution e.g. on an unsorted std::vector.
One danger to look out for when using this approach is overflow. With 32-bit ints, it will overflow with approximately 2^16 values. It might actually still work if it overflows, particularly if you use unsigned instead of int, but I did not confirm that.
There's a similar approach that uses the XOR of all values instead of the sum, which does not have the problem with overflow.