Enumerating array in reverse order using size_t index - c++

Let's say we need to print int array with size N in reverse order:
// Wrong, i is unsigned and always >= 0:
for(size_t i = N-1; i >= 0; --i){cout << data[i];}
// Correct, but uses int instead of size_t:
for(int i = N-1; i >= 0; --i){cout << data[i];}
// Correct, but requires additional operation in the loop:
for(size_t i = N; i > 0; --i){cout << data[i-1];}
// Probably the best version, but less readable.
// Is this well-defined behavior?
for(size_t i = N-1; i != (size_t)(-1); --i){cout << data[i];}
Is there better way to do such enumeration using size_t index and without additional operations in the loop?
Is it valid to assume that (size_t)0 - 1 gives (size_t)(-1) or this is undefined?

You can move the decrement to "after" the condition.
for(size_t i = N; i > 0;) {
--i;
cout << data[i];
}
It's not as elegant as a forwards loop but it works. We break at 0 so i never wraps.

since C++14:
for (auto it = std::rbegin(data); it != std::rend(data); ++it) { std::cout << *it; }
Or if you can use boost, you may use boost::adaptors::reversed and for range.

You can simply test for i < N.
size_t is defined as an unsigned integer, which in turn is defined to have modulo semantics. So your index will go from N-1 down to 0 and then wrap around to numeric_limits<size_t>::max() for which i<N doesn't hold true any longer.
To give a full example:
for(size_t i = N-1; i < N; --i){cout << data[i];}

Related

How can I iterate through the last element of the vector without going out of bounds?

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";
}

Idiom for handling size_t underflow in loop condition

In C and C++, size_t is an unsigned type that is used for expressing size. It expresses intent and somewhat simplifies range assertions (len < upper_bound vs len >= 0 && len < upper_bound for signed integers).
(In all the examples below len means the length of the array a).
The idiom for a for loop is: for (i = 0; i < len; i++). The idiom for a backward for loop is for (i = len-1; i >= 0; i--). But having unsigned loop indices introduces subtle bugs, and every so often I mess up the edge cases.
First, the backwards for loop. This code underflows for len=0.
for (size_t i = len-1; i >= 0; i--) { // Bad: Underflows for len=0
use(a[i]);
}
There's the --> "operator" trick, which looks strange if you're not used to it.
for (size_t i = len; i--> 0;) {
use(a[i]);
}
You can use a signed type for the loop index variable, but that overflows if len > INT_MAX. Many people and organizations considers that risk so minimal that they just stick to int.
for (int i = len-1; i >= 0; i--) { // BAD: overflows for len < INT_MAX
use(a[i]);
}
So I've settled for this construct, since it's closest to the canonical for-loop form and has the simplest expressions.
for (size_t i = len; i > 0; i--) {
size_t pos = i-1;
use(a[pos]);
}
My problem iterating from 0 to len-1
That is, looping over the range [0, len-1). This loop underflows when len=0.
for (size_t i = 0; i < len-1; i++) { // BAD: Underflows for len=0.
use(a[i]);
}
As for the iterating backwards case, you can use signed integers but that may cause overflows.
for (int i = 0; i < len-1; i++) { // BAD: Will overflow if len > INT_MAX
use(a[i]);
}
I tend to add another expression to the loop condition, checking for len > 0, but that feels clumsy.
for (size_t i = 0; len > 0 && i < len-1; i++) {
use(a[i]);
}
I can add an if statement before the loop, but that also feels clumsy.
Is there a less bulky way of writing a for loop with unsigned index variables looping from 0 to len-1?
There are two cases here.
Iterating forward from 0 to len - 2 inclusive
for (size_t i = 0; i + 1 < len; ++i) {
size_t index = i;
// use index here
}
Iterating backward from len - 2 to 0 inclusive
for (size_t i = len; i > 1; --i) {
size_t index = i - 2;
// use index here
}
How about
for (size_t i = 0; i+1 < len; i++) {
use(a[i]);
}
In all these cases, you have one common theme: You have an index that has a start value. It gets incremented or decremented until it reaches the end value, which terminates the loop.
One thing that helps here is to make these two values explicit. In the simplest case, forward-iterating the whole range, the end value is simply len:
for (size_t i=0, end=len; i!=end; ++i) {
///...
}
This follows the general advise given to people using iterators. In particular, pay attention to the comparison, which works here and which is actually required for some iterators.
Now, backward iterating:
for (size_t i=len-1, end=-1; i!=end; --i) {
///...
}
Lastly, iterating a subset excluding the last n elements of the range backwards:
if (len > n) {
for (size_t i=len-n-1, end=-1; i!=end; --i) {
///...
}
}
Actually, what you were fighting with was your attempt to put too much stuff into the loop logic. Just be explicit that this requires more than n elements in order to do anything at all. Yes, you could put len > n into the loop condition, but that wouldn't give you clear and simple code who's intention anyone understands.
I tend to add another expression to the loop condition, checking for
len > 0, but that feels clumsy.
Your code should follow the logic. It is not clumsy at all. And it is much more readable for humans.
As the loop makes no sense if the len == 0 and I usually use the if statement. It makes the code easy to understand and maintain.
if(len)
{
for (size_t i = 0; i < len-1; i++) { /*...*/ }
}
or you can also add the check in the loop. BTW you only check if it is not zero.
for (size_t i = 0; len && i < len-1; i++) { /*...*/ }
There are many possible answers for this question. Which is best is opinion based. I'll offer some options.
For iterating over all elements of an array in reverse order, using an unsigned index, one option is
for (size_t index = 0; index < len; ++index)
{
size_t i = len - 1 - index;
use(a[i]);
}
or (more simply)
for (size_t i = 0; i < len; ++i)
{
use(a[len - 1 - i]);
}
In both cases, if len is zero, the loop body is not executed. Although the loops increment rather than decrement, both access elements in reverse order. If you are frequently writing such loops, it is also not difficult to write a little inline function of the form
size_t index_in_reverse(size_t index, size_t len)
{
return len - 1 - index;
}
and do
for (size_t i = 0; i < len; ++i)
{
use(index_in_reverse(i, len));
}
To iterate forward over all elements of the loop in forward order, except the last, I'd make that explicit rather than trying to do it in the loop condition.
if (len > 0)
{
size_t shortened_len = len - 1;
for (size_t i = 0; i < shortened_len; ++i)
use(a[i]);
}
The reason I introduce the variable shortened_len is to make the code self-documenting about the fact it is not iterating over the entire array. I've seen too many cases where a condition of the form i < len - 1 is "corrected" by a subsequent developer to remove the - 1 because they believe it is a typo.
That may feel "clumsy" to the OP, but I suggest that
for (size_t i = 0; len > 0 && i < len-1; i++) {
use(a[i]);
}
is harder for a human to understand (putting multiple tests in a loop condition, forces a person maintaining the code to actually work out what both conditions do and, how they interact). Given a choice between code that is "concise" or code that is "less concise but consumes less brainpower of an unacquainted human to understand" I will ALWAYS choose the latter. Bear in mind that the user maintaining the code six months later may be yourself, and there are few thought processes more humbling than "What idiot wrote this?? Oh, it was me!".

Why program throws runtime error while iterating over an emtpy vector in c++

vector <int> o; //Empty vector
for(int i=0;i<=o.size()-1;i++) cout<<o[i];
got runtime error in the above
vector <int> o;
for(auto j : o){
cout<<j<<" ";
}
However this code runs fine if iterator is used instead
o.size() is required by the C++ standard to return an unsigned type. When that's zero, subtracting 1 yields std::numeric_limits<decltype(o.size())>::max() which means your loop runs past the bounds of the empty vector.
for(std::size_t i = 0; i < o.size(); ++i) is the obvious fix. The use of <= and -1 seems almost disingenuously contrived to me.
o.size() will return an unsigned value of 0. Subtracting one from it returns a very large positive number, essentially making an infinite loop. Eventually your out-of-bounds array accesses to o[i] will result in a crash.
You could use
for(int i = 0; i <= int(o.size() - 1); i++)
Or just use the more typical
for(int i = 0;i < o.size(); i++)
where you check for "less than", not "less or equal" to a number one less.
Since sizeof(size_t) is greater or equal than sizeof(int) (although this might be implementation dependent) and size_t is unsigned, the int (1) is converted to size_t.
Therefore, in the expression o.size() - 1, the 1 is implicitly converted to size_t, and o.size() - 1 (which is equivalent to size_t(0 - 1)) becomes equal to std::numeric_limits<size_t>::max(). Therefore, the for loop is entered and accessing your empty o at index 0 results in undefined behavior.
You should:
for (size_t idx = 0; idx < o.size(); ++idx) { /* ... */ }
If for some reason you need the index to be of type int, you can:
for (int idx = 0; idx < static_cast<int>(o.size()); ++idx) { /* ... */ }
or in your example (which is less common):
for (int idx = 0; idx <= static_cast<int>(o.size()) - 1; ++idx) { /* ... */ }

Return the index for the maximum value

I have written the following which gets the index value for the maximum number.
int TravellingSalesMan::getMaximum(double *arr){
double temp = arr[0];
int iterator = 0;
for(int i = 0; i < 30; i++){
if(arr[i] > temp){
iterator = i;
}
}
return iterator;
}
But the output keeps stepping into the conditional statement and keeps printing out 29. I am not sure why this is happening
I also tried using max_element() but with no luck
EDIT
The above function is invoked as following
static unsigned int chromosome = 30;
double value[chromosome]
for(int i = 0; i < chromosomes; i++){
value[i] = estimateFitness(currPopultaion[i]);
}
int best = 0;
best = getMaximum(value);
cout<<best<<endl; // this just prints out 29
Okay, so I didn't plan on writing the answer, but I just saw too many logical mistakes in the code for me to write in the comments section!
First of all, your use of the variable name iterator is very
wrong. It's not used for iteration over the list. Why create confusion. Best to use something like max_index or something like that.
Why start from i=0? Your temp value is arr[0], so there is no use. of checking with first element again. Start from i=1!
temp is pointless in that function. The maximum index should initially be 0, and set to i if ever there is some arr[i] that is greater than arr[max_index].
Passing the length separately to the function is better coding as it makes the code more clearer.
The content in arr is not modified, and as such better safe than sorry: make the pointer const.
Re-writing the code, it should be:
int TravellingSalesMan::getMaximum(const double *arr,int len)
{
int max_index = 0;
for(int i = 1; i < len; i++)
{
if(arr[i] > arr[max_index])
max_index = i;
}
return max_index;
}
Worth noting, but unchanged in the code above, len, i, and the function result should all be an unsigned integer type. There is no reason, to allow signed integer indexing, so make it a warning-condition from the caller if they do so by hard-specifying unsigned or just size_t as the indexing variable types.
You should be assigning a new value to temp when you find a new maximum.
int TravellingSalesMan::getMaximum(double *arr){
double temp = arr[0];
int iterator = 0;
for(int i = 0; i < 30; i++){
if(arr[i] > temp){
iterator = i;
temp = arr[i]; // this was missing
}
}
return iterator;
}
Without this you are finding the largest index of a value greater than the value at index zero.
A much better solution is to simply use std::max_element instead. Pointers can be used as iterators in most (if not all) algorithms requiring iterators.
#include <algorithm>
static unsigned int chromosomes = 30;
double value[chromosomes];
for (int i=0; i<chromosomes; ++i) {
value[I] = estimate_fitness(current_population[i]);
}
double *max_elm = std::max_element(&value[0], &value[chromosomes]);
int best = int(max_elm - &value[0]);
std::cout << best << std::endl;

how can I work with the last element of iterations

for(int t(0); t < 10;++t) { cout<<t<<endl;}
I'm just biginer in C++, and want to know how can I take the last elemnt of my "cout...."; in this case my laste element is 9
thx for help ;)
int c = 0;
for(int t = 0; t<10; t++)
{
c = t;
}
cout<<c;
This might be what you are looking for I am not sure I understand your question properly though.The variable c should hold the last element of t when the loop ends.
You can extract int t from the for loop :
int t;
for (t = 0; t < 10; ++t)
{
cout << t << endl;
}
int t = 9;
cout << t << endl;
Now you have the last element, #9.
ghagha, in C++ the ranges are run from 0 to n-1, in your example you have a range of 0 to < 10 hence 0 to 9, therefore your last element is 9. But as I said you can do any range as n-1 for the last element, provided that it follows normal conventions (it is possible to have a range from 1 to n if you code it that way)
It is not clear what you want but in any case your loop contains a bug. Instead of
for(int t(0); t < 10; t) { cout<<t<<endl;}
should be
for(int t(0); t < 10; t++) { cout<<t<<endl;}
that is variable t has to be incremented.
One simple way -
int t = 0;
for (; t < 10; ++t)
cout << t << ;
Tough the correct way to do it will be (one variable should not have two meanings, i.e 1. last element, 2. iterator context) -
int last_element;
for (int t = 0; t < 10; ++t;
{
cout << t << ;
last_element = t;
}