For a class I'm teaching I needed to write a piece of code to iterate over all possible char
values. I wanted to do this in a way that was portable across different C implementations. This meant that
- I can't assume
char
issigned
orunsigned
, - I can't assume
char
is eight bits, - I can't assume that
sizeof(int) > 1
, - I can't assume the
int32_t
etc. types exist, - I can't assume that integer overflow will not trap,
- etc.
The best solution I came up with was the following unusual do ... while
loop:
char ch = numeric_limits<char>::min();
process(ch);
do {
ch ;
process(ch);
} while (ch != numeric_limits<char>::max());
This approach works, but it feels pretty clunky to me. It intuitively makes sense that an approach like this might be needed because the number of increments is one more than the number of possible characters, but perhaps there's a fundamentally different approach available that more closely resembles a traditional for
loop.
Is there a portable way to achieve this that's less clunky than this?
CodePudding user response:
but perhaps there's a fundamentally different approach available that more closely resembles a traditional for loop.
Well, you can use an actual for
loop:
#include <limits>
#include <iostream>
void process(char ch)
{
std::cout << static_cast<long>(ch) << ' ';
}
int main()
{
for ( char ch = std::numeric_limits<char>::min(); ; ch )
{
process(ch);
if ( ch == std::numeric_limits<char>::max() )
break;
}
std::cout << '\n';
}
CodePudding user response:
You can create a wrapper class that looks like a container.
struct Chars {
enum {
Chars_MIN = std::numeric_limits<char>::min(),
Chars_MAX = std::numeric_limits<char>::max()
};
struct Iterator {
char c_;
bool end_;
Iterator (char c, bool e = false) : c_(c), end_(e) {}
auto & operator () {
if (c_ == Chars_MAX) end_ = true;
else c_;
return *this;
}
auto operator * () const { return c_; }
auto operator == (const Iterator &other) const {
return c_ == other.c_ && end_ == other.end_;
}
auto operator != (const Iterator &other) const {
return !(*this == other);
}
};
Iterator begin () const { return Iterator(Chars_MIN); }
Iterator end () const { return Iterator(Chars_MAX, true); }
};
Then, you can use the modern for
syntax:
Chars ccc;
for (auto x : ccc) {
process(x);
}