Is there a shorter way to write compound 'if' conditions? [duplicate] - c++

This question already has answers here:
Shorthand for checking for equality to multiple possibilities [duplicate]
(3 answers)
Closed 6 years ago.
Just instead of:
if ( ch == 'A' || ch == 'B' || ch == 'C' || .....
For example, to do it like:
if ( ch == 'A', 'B', 'C', ...
is there even a shorter way to summarize conditions?

strchr() can be used to see if the character is in a list.
const char* list = "ABCXZ";
if (strchr(list, ch)) {
// 'ch' is 'A', 'B', 'C', 'X', or 'Z'
}

In this case you could use a switch:
switch (ch) {
case 'A':
case 'B':
case 'C':
// do something
break;
case 'D':
case 'E':
case 'F':
// do something else
break;
...
}
While this is slightly more verbose than using strchr, it doesn't involve any function calls. It also works for both C and C++.
Note that the alternate syntax you suggested won't work as you might expect because of the use of the comma operator:
if ( ch == 'A', 'B', 'C', 'D', 'E', 'F' )
This first compares ch to 'A' and then discards the result. Then 'B' is evaluated and discarded, then 'C', and so forth until 'F' is evaluated. Then 'F' becomes the value of the conditional. Since any non-zero value evaluated to true in a boolean context (and 'F' is non-zero), then the above expression will always be true.

Templates allow us to express ourselves in this way:
if (range("A-F").contains(ch)) { ... }
It requires a little plumbing, which you can put in a library.
This actually compiles out to be incredibly efficient (at least on gcc and clang).
#include <cstdint>
#include <tuple>
#include <utility>
#include <iostream>
namespace detail {
template<class T>
struct range
{
constexpr range(T first, T last)
: _begin(first), _end(last)
{}
constexpr T begin() const { return _begin; }
constexpr T end() const { return _end; }
template<class U>
constexpr bool contains(const U& u) const
{
return _begin <= u and u <= _end;
}
private:
T _begin;
T _end;
};
template<class...Ranges>
struct ranges
{
constexpr ranges(Ranges...ranges) : _ranges(std::make_tuple(ranges...)) {}
template<class U>
struct range_check
{
template<std::size_t I>
bool contains_impl(std::integral_constant<std::size_t, I>,
const U& u,
const std::tuple<Ranges...>& ranges) const
{
return std::get<I>(ranges).contains(u)
or contains_impl(std::integral_constant<std::size_t, I+1>(),u, ranges);
}
bool contains_impl(std::integral_constant<std::size_t, sizeof...(Ranges)>,
const U& u,
const std::tuple<Ranges...>& ranges) const
{
return false;
}
constexpr bool operator()(const U& u, std::tuple<Ranges...> const& ranges) const
{
return contains_impl(std::integral_constant<std::size_t, 0>(), u, ranges);
}
};
template<class U>
constexpr bool contains(const U& u) const
{
range_check<U> check {};
return check(u, _ranges);
}
std::tuple<Ranges...> _ranges;
};
}
template<class T>
constexpr auto range(T t) { return detail::range<T>(t, t); }
template<class T>
constexpr auto range(T from, T to) { return detail::range<T>(from, to); }
// this is the little trick which turns an ascii string into
// a range of characters at compile time. It's probably a bit naughty
// as I am not checking syntax. You could write "ApZ" and it would be
// interpreted as "A-Z".
constexpr auto range(const char (&s)[4])
{
return range(s[0], s[2]);
}
template<class...Rs>
constexpr auto ranges(Rs...rs)
{
return detail::ranges<Rs...>(rs...);
}
int main()
{
std::cout << range(1,7).contains(5) << std::endl;
std::cout << range("a-f").contains('b') << std::endl;
auto az = ranges(range('a'), range('z'));
std::cout << az.contains('a') << std::endl;
std::cout << az.contains('z') << std::endl;
std::cout << az.contains('p') << std::endl;
auto rs = ranges(range("a-f"), range("p-z"));
for (char ch = 'a' ; ch <= 'z' ; ++ch)
{
std::cout << ch << rs.contains(ch) << " ";
}
std::cout << std::endl;
return 0;
}
expected output:
1
1
1
1
0
a1 b1 c1 d1 e1 f1 g0 h0 i0 j0 k0 l0 m0 n0 o0 p1 q1 r1 s1 t1 u1 v1 w1 x1 y1 z1
For reference, here was my original answer:
template<class X, class Y>
bool in(X const& x, Y const& y)
{
return x == y;
}
template<class X, class Y, class...Rest>
bool in(X const& x, Y const& y, Rest const&...rest)
{
return in(x, y) or in(x, rest...);
}
int main()
{
int ch = 6;
std::cout << in(ch, 1,2,3,4,5,6,7) << std::endl;
std::string foo = "foo";
std::cout << in(foo, "bar", "foo", "baz") << std::endl;
std::cout << in(foo, "bar", "baz") << std::endl;
}

If you need to check a character against an arbitrary set of characters, you could try writing this:
std::set<char> allowed_chars = {'A', 'B', 'C', 'D', 'E', 'G', 'Q', '7', 'z'};
if(allowed_chars.find(ch) != allowed_chars.end()) {
/*...*/
}

Yet another answer on this overly-answered question, which I'm just including for completeness. Between all of the answers here you should find something that works in your application.
So another option is a lookup table:
// On initialization:
bool isAcceptable[256] = { false };
isAcceptable[(unsigned char)'A'] = true;
isAcceptable[(unsigned char)'B'] = true;
isAcceptable[(unsigned char)'C'] = true;
// When you want to check:
char c = ...;
if (isAcceptable[(unsigned char)c]) {
// it's 'A', 'B', or 'C'.
}
Scoff at the C-style static casts if you must, but they do get the job done. I suppose you could use an std::vector<bool> if arrays keep you up at night. You can also use types besides bool. But you get the idea.
Obviously this becomes cumbersome with e.g. wchar_t, and virtually unusable with multibyte encodings. But for your char example, or for anything that lends itself to a lookup table, it'll do. YMMV.

Similarly to the C strchr answer, In C++ you can construct a string and check the character against its contents:
#include <string>
...
std::string("ABCDEFGIKZ").find(c) != std::string::npos;
The above will return true for 'F' and 'Z' but false for 'z' or 'O'. This code does not assume contiguous representation of characters.
This works because std::string::find returns std::string::npos when it can't find the character in the string.
Live on Coliru
Edit:
There's another C++ method which doesn't involve dynamic allocation, but does involve an even longer piece of code:
#include <algorithm> // std::find
#include <iterator> // std::begin and std::end
...
char const chars[] = "ABCDEFGIKZ";
return std::find(std::begin(chars), std::end(chars), c) != std::end(chars);
This works similarly to the first code snippet: std::find searches the given range and returns a specific value if the item isn't found. Here, said specific value is the range's end.
Live on Coliru

One option is the unordered_set. Put the characters of interest into the set. Then just check the count of the character in question:
#include <iostream>
#include <unordered_set>
using namespace std;
int main() {
unordered_set<char> characters;
characters.insert('A');
characters.insert('B');
characters.insert('C');
// ...
if (characters.count('A')) {
cout << "found" << endl;
} else {
cout << "not found" << endl;
}
return 0;
}

There is solution to your problem, not in language but in coding practices - Refactoring.
I'm quite sure that readers will find this answer very unorthodox, but - Refactoring can, and is used often to, hide a messy piece of code behind a method call. That method can be cleaned later or it can be left as it is.
You can create the following method:
private bool characterIsValid(char ch) {
return (ch == 'A' || ch == 'B' || ch == 'C' || ..... );
}
and then this method can be called in a short form as:
if (characterIsValid(ch)) ...
Reuse that method with so many checks and only returning a boolean, anywhere.

For a simple and effective solution, you can use memchr():
#include <string.h>
const char list[] = "ABCXZ";
if (memchr(list, ch, sizeof(list) - 1)) {
// 'ch' is 'A', 'B', 'C', 'X', or 'Z'
}
Note that memchr() is better suited than strchr() for this task as strchr() would find the null character '\0' at the end of the string, which is incorrect for most cases.
If the list is dynamic or external and its length is not provided, the strchr() approach is better, but you should check if ch is different from 0 as strchr() would find it at the end of the string:
#include <string.h>
extern char list[];
if (ch && strchr(list, ch)) {
// 'ch' is one of the characters in the list
}
Another more efficient but less terse C99 specific solution uses an array:
#include <limits.h>
const char list[UCHAR_MAX + 1] = { ['A'] = 1, ['B'] = 1, ['C'] = 1, ['X'] = 1, ['Z'] = 1 };
if (list[(unsigned char)ch]) {
/* ch is one of the matching characters */
}
Note however that all of the above solutions assume ch to have char type. If ch has a different type, they would accept false positives. Here is how to fix this:
#include <string.h>
extern char list[];
if (ch == (char)ch && ch && strchr(list, ch)) {
// 'ch' is one of the characters in the list
}
Furthermore, beware of pitfalls if you are comparing unsigned char values:
unsigned char ch = 0xFF;
if (ch == '\xFF') {
/* test fails if `char` is signed by default */
}
if (memchr("\xFF", ch, 1)) {
/* test succeeds in all cases, is this OK? */
}

For this specific case you can use the fact that char is an integer and test for a range:
if(ch >= 'A' && ch <= 'C')
{
...
}
But in general this is not possible unfortunately. If you want to compress your code just use a boolean function
if(compare_char(ch))
{
...
}

The X-Y answer on the vast majority of modern systems is don't bother.
You can take advantage of the fact that practically every character encoding used today stores the alphabet in one sequentially-ordered contiguous block. A is followed by B, B is followed by C, etc... on to Z. This allows you to do simple math tricks on letters to convert the letter to a number. For example the letter C minus the letter A , 'C' - 'A', is 2, the distance between c and a.
Some character sets, EBCDIC was discussed in the comments above, are not sequential or contiguous for reasons that are out of scope for discussion here. They are rare, but occasionally you will find one. When you do... Well, most of the other answers here provide suitable solutions.
We can use this to make a mapping of letter values to letters with a simple array:
// a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p, q,r,s,t,u,v,w,x,y, z
int lettervalues[] = {1,3,3,2,1,4,2,4,1,8,5,1,3,1,1,3,10,1,1,1,1,4,4,8,4,10};
So 'c' - 'a' is 2 and lettervalues[2] will result in 3, the letter value of C.
No if statements or conditional logic required what-so-ever. All the debugging you need to do is proof reading lettervalues to make sure you entered the correct values.
As you study more in C++, you will learn that lettervalues should be static (current translation unit-only access) and const (cannot be changed), possibly constexpr (cannot be changed and fixed at compile time). If you don't know what I'm talking about, don't worry. You'll cover all three later. If not, google them. All are very useful tools.
Using this array could be as simple as
int ComputeWordScore(std::string in)
{
int score = 0;
for (char ch: in) // for all characters in string
{
score += lettervalues[ch - 'a'];
}
return score;
}
But this has two fatal blind spots:
The first is capital letters. Sorry Ayn Rand, but 'A' is not 'a', and 'A'-'a' is not zero. This can be solved by using std::tolower or std::toupper to convert all input to a known case.
int ComputeWordScore(std::string in)
{
int score = 0;
for (char ch: in) // for all characters in string
{
score += lettervalues[std::tolower(ch) - 'a'];
}
return score;
}
The other is input of characters that aren't letters. For example, '1'. 'a' - '1' will result in an array index that is not in the array. This is bad. If you're lucky your program will crash, but anything could happen, including looking as though your program works. Read up on Undefined Behaviour for more.
Fortunately this also has a simple fix: Only compute the score for good input. You can test for valid alphabet characters with std::isalpha.
int ComputeWordScore(std::string in)
{
int score = 0;
for (char ch: in) // for all characters in string
{
if (std::isalpha(ch))
{
score += lettervalues[std::tolower(ch) - 'a'];
}
else
{
// do something that makes sense here.
}
}
return score;
}
My something else would be return -1;. -1 is an impossible word score, so anyone who calls ComputeWordScore can test for -1 and reject the user's input. What they do with it is not ComputeWordScore's problem. Generally the stupider you can make a function, the better, and errors should be handled by the closest piece of code that has all the information needed to make a decision. In this case, whatever read in the string would likely be tasked with deciding what to do with bad strings and ComputeWordScore can keep on computing word scores.

Most of the terse versions have been covered, so I will cover the optimized cases with some helper macros to make them a little more terse.
It just so happens that if your range falls within your number of bits per long that you can combine all of your constants using a bitmask and just check that your value falls in the range and the variable's bitmask is non-zero when bitwise-anded with the constant bitmask.
/* This macro assumes the bits will fit in a long integer type,
* if it needs to be larger (64 bits on x32 etc...),
* you can change the shifted 1ULs to 1ULL or if range is > 64 bits,
* split it into multiple ranges or use SIMD
* It also assumes that a0 is the lowest and a9 is the highest,
* You may want to add compile time assert that:
* a9 (the highest value) - a0 (the lowest value) < max_bits
* and that a1-a8 fall within a0 to a9
*/
#define RANGE_TO_BITMASK_10(a0,a1,a2,a3,a4,a5,a6,a7,a8,a9) \
(1 | (1UL<<((a1)-(a0))) | (1UL<<((a2)-(a0))) | (1UL<<((a3)-(a0))) | \
(1UL<<((a4)-(a0))) | (1UL<<((a5)-(a0))) | (1UL<<((a6)-(a0))) | \
(1UL<<((a7)-(a0))) | (1UL<<((a8)-(a0))) | (1UL<<((a9)-(a0))) )
/*static inline*/ bool checkx(int x){
const unsigned long bitmask = /* assume 64 bits */
RANGE_TO_BITMASK_10('A','B','C','F','G','H','c','f','y','z');
unsigned temp = (unsigned)x-'A';
return ( ( temp <= ('z'-'A') ) && !!( (1ULL<<temp) & bitmask ) );
}
Since all of a# values are constants, they will be combined into 1 bitmask at compile time. That leaves 1 subtraction and 1 compare for the range, 1 shift and 1 bitwise and ... unless the compiler can optimize further, it turns out clang can (it uses the bit test instruction BTQ):
checkx: # #checkx
addl $-65, %edi
cmpl $57, %edi
ja .LBB0_1
movabsq $216172936732606695, %rax # imm = 0x3000024000000E7
btq %rdi, %rax
setb %al
retq
.LBB0_1:
xorl %eax, %eax
retq
It may look like more code on the C side, but if you are looking to optimize, this looks like it may be worth it on the assembly side. I'm sure someone could get creative with the macro to make it more useful in a real programming situations than this "proof of concept".
That will get a little complex as a macro, so here is an alternative set of macros to setup a C99 lookup table.
#include <limits.h>
#define INIT_1(v,a) [ a ] = v
#define INIT_2(v,a,...) [ a ] = v, INIT_1(v, __VA_ARGS__)
#define INIT_3(v,a,...) [ a ] = v, INIT_2(v, __VA_ARGS__)
#define INIT_4(v,a,...) [ a ] = v, INIT_3(v, __VA_ARGS__)
#define INIT_5(v,a,...) [ a ] = v, INIT_4(v, __VA_ARGS__)
#define INIT_6(v,a,...) [ a ] = v, INIT_5(v, __VA_ARGS__)
#define INIT_7(v,a,...) [ a ] = v, INIT_6(v, __VA_ARGS__)
#define INIT_8(v,a,...) [ a ] = v, INIT_7(v, __VA_ARGS__)
#define INIT_9(v,a,...) [ a ] = v, INIT_8(v, __VA_ARGS__)
#define INIT_10(v,a,...) [ a ] = v, INIT_9(v, __VA_ARGS__)
#define ISANY10(x,...) ((const unsigned char[UCHAR_MAX+1]){ \
INIT_10(-1, __VA_ARGS__) \
})[x]
bool checkX(int x){
return ISANY10(x,'A','B','C','F','G','H','c','f','y','z');
}
This method will use a (typically) 256 byte table and a lookup that reduces to something like the following in gcc:
checkX:
movslq %edi, %rdi # x, x
cmpb $0, C.2.1300(%rdi) #, C.2
setne %al #, tmp93
ret
NOTE: Clang doesn't fare as well on the lookup table in this method because it sets up const tables that occur inside functions on the stack on each function call, so you would want to use INIT_10 to initialize a static const unsigned char [UCHAR_MAX+1] outside of the function to achieve similar optimization to gcc.

Related

Generate string lexicographically larger than input

Given an input string A, is there a concise way to generate a string B that is lexicographically larger than A, i.e. A < B == true?
My raw solution would be to say:
B = A;
++B.back();
but in general this won't work because:
A might be empty
The last character of A may be close to wraparound, in which case the resulting character will have a smaller value i.e. B < A.
Adding an extra character every time is wasteful and will quickly in unreasonably large strings.
So I was wondering whether there's a standard library function that can help me here, or if there's a strategy that scales nicely when I want to start from an arbitrary string.
You can duplicate A into B then look at the final character. If the final character isn't the final character in your range, then you can simply increment it by one.
Otherwise you can look at last-1, last-2, last-3. If you get to the front of the list of chars, then append to the length.
Here is my dummy solution:
std::string make_greater_string(std::string const &input)
{
std::string ret{std::numeric_limits<
std::string::value_type>::min()};
if (!input.empty())
{
if (std::numeric_limits<std::string::value_type>::max()
== input.back())
{
ret = input + ret;
}
else
{
ret = input;
++ret.back();
}
}
return ret;
}
Ideally I'd hope to avoid the explicit handling of all special cases, and use some facility that can more naturally handle them. Already looking at the answer by #JosephLarson I see that I could increment more that the last character which would improve the range achievable without adding more characters.
And here's the refinement after the suggestions in this post:
std::string make_greater_string(std::string const &input)
{
constexpr char minC = ' ', maxC = '~';
// Working with limits was a pain,
// using ASCII typical limit values instead.
std::string ret{minC};
auto rit = input.rbegin();
while (rit != input.rend())
{
if (maxC == *rit)
{
++rit;
if (rit == input.rend())
{
ret = input + ret;
break;
}
}
else
{
ret = input;
++(*(ret.rbegin() + std::distance(input.rbegin(), rit)));
break;
}
}
return ret;
}
Demo
You can copy the string and append some letters - this will produce a lexicographically larger result.
B = A + "a"

R G B element array swap

I'm trying to create this c++ program to perform the description below. I am pretty certain the issue is in the recursive, but uncertain how to fix it. I'm guessing it just keeps iterating through to infinity and crashes. I do not even get an output. I figured I could just compare the previous and current pointer and perform a 3-piece temp swap based on lexicography. I would use a pointer to iterate through the array and decrement it after each swap, then recursively call with that ptr as the parameter. Didn't work, I'm here, help me please :). If there is a simpler solution that would work too, but prefer to understand where I went wrong with this code.
#include <string>
#include <iostream>
using namespace std;
// Given an array of strictly the characters 'R', 'G', and
// 'B', segregate the values of the array so that all the
// Rs come first, the Gs come second, and the Bs come last.
// You can only swap elements of the array.
char* RGBorder(char* c_a)
{
size_t sz = sizeof(c_a)/sizeof(*c_a);
char* ptr_ca = c_a;
char* prv_ptr = ptr_ca;
ptr_ca++;
char temp;
while(*ptr_ca)
{
switch(*ptr_ca)
{
case 'R' :
if( *prv_ptr < *ptr_ca ) {
temp = *prv_ptr; *prv_ptr = *ptr_ca; *ptr_ca = temp;
} else if( *prv_ptr == *ptr_ca ) {
continue;
} else { ptr_ca--; RGBorder(ptr_ca); }
case 'G' :
if( *prv_ptr < *ptr_ca ) {
temp = *prv_ptr; *prv_ptr = *ptr_ca; *ptr_ca = temp;
} else if( *prv_ptr == *ptr_ca ) {
continue;
} else { ptr_ca--; RGBorder(ptr_ca); }
default:
ptr_ca++;
continue;
}
ptr_ca++;
cout << *ptr_ca;
}
return c_a;
}
int main()
{
char ca[] = {'G', 'B', 'R', 'R', 'B', 'R', 'G'};
char *oca =RGBorder(ca);
char *pca = oca;
while(*pca)
{
cout << *pca << endl;
pca++;
}
}
There are many issues with your code.
1) You call the function RGBorder with a character pointer, and then attempt to get the number of characters using this:
size_t sz = sizeof(c_a)/sizeof(*c_a);
This will not get you the number of characters. Instead this will simply get you the
sizeof(char *) / sizeof(char)
which is usually 4 or 8. The only way to call your function using a char array is either provide a null-terminated array (thus you can use strlen), or you have to pass the number of characters in the array as a separate argument:
char *RGBorder(char *c_a, int size)
2) I didn't go through your code, but there are easier ways to do a 3-way partition in an array. One popular algorithm to do this is one based on the Dutch National Flag problem.
Since you want the array in RGB order, you know that the series of G will always come in the middle (somewhere) of the sequence, with R on the left of the sequence, and B always on the right of the sequence.
So the goal is to simply swap R to the left of the middle, and B to the right of the middle. So basically you want a loop that incrementally changes the "middle" when needed, while swapping R's and B's to their appropriate position when they're detected.
The following code illustrates this:
#include <algorithm>
char *RGBorder(char *c_a, int num)
{
int middle = 0; // assume we only want the middle element
int low = 0; // before the G's
int high = num - 1; // after the G's
while (middle <= high)
{
if ( c_a[middle] == 'R' ) // if we see an 'R' in the middle, it needs to go before the middle
{
std::swap(c_a[middle], c_a[low]); // swap it to a place before middle
++middle; // middle has creeped up one spot
++low; // so has the point where we will swap when we do this again
}
else
if (c_a[middle] == 'B') // if we see a 'B' as the middle element, it needs to go after the middle
{
std::swap(c_a[middle], c_a[high]); // place it as far back as you can
--high; // decrease the back position for next swap that comes here
}
else
++middle; // it is a 'G', do nothing
}
return c_a;
}
Live Example
Here is another solution that uses std::partition.
#include <algorithm>
#include <iostream>
char *RGBorder(char *c_a, int num)
{
auto iter = std::partition(c_a, c_a + num, [](char ch) {return ch == 'R';});
std::partition(iter, c_a + num, [](char ch) {return ch == 'G';});
return c_a;
}
Live Example
Basically, the first call to std::partition places the R's to the front of the array. Since std::partition returns an iterator (in this case, a char *) to the end of where the partition occurs, we use that as a starting position in the second call to std::partition, where we partition the G values.
Note that std::partition also accomplishes its goal by swapping.
Given this solution, we can generalize this for an n-way partition by using a loop. Assume we want to place things in RGBA order (4 values instead of 3).
#include <algorithm>
#include <iostream>
#include <cstring>
char *RGBorder(char *c_a, int num, char *order, int num2)
{
auto iter = c_a;
for (int i = 0; i < num2 - 1; ++i)
iter = std::partition(iter, c_a + num, [&](char ch) {return ch == order[i];});
return c_a;
}
int main()
{
char ca[] = "AGBRRBARGGARRBGAGRARAA";
std::cout << RGBorder(ca, strlen(ca), "RGBA", 4);
}
Output:
RRRRRRRGGGGGBBBAAAAAAA
Sorry to put it blunt, but that code is a mess. And I don't mean the mistakes, those are forgivable for beginners. I mean the formatting. Multiple statements in one line make it super hard to read and debug the code. Short variable names that carry no immediate intrinsic meaning make it hard to understand what the code is supposed to do. using namespace std; is very bad practise as well, but I can imagine you were taught to do this by whoever gives that course.
1st problem
Your cases don't break, thus you execute all cases for R, and both G and default for G. Also your code will never reach the last 2 lines of your loop, as you continue out before in every case.
2nd problem
You have an endless loop. In both cases you have two situations where you'll end up in an endless loop:
In the else if( *prv_ptr == *ptr_ca ) branch you simply continue; without changing the pointer.
In the else branch you do ptr_ca--;, but then in default you call ptr_ca++; again.(Note that even with breaks you would still call ptr_ca++; at the end of the loop.)
In both cases the pointer doesn't change, so once you end up in any of those conditions your loop will never exit.
Possible 3rd problem
I can only guess, because it is not apparent from the name, but it seems that prv_ptr is supposed to hold whatever was the last pointer in the loop? If so, it seems wrong that you don't update that pointer, ever. Either way, proper variable names would've made it more clear what the purpose of this pointer is exactly. (On a side note, consistent usage of const can help identify such issues. If you have a variable that is not const, but never gets updated, you either forgot to add const or forgot to update it.)
How to fix
Format your code:
Don't use using namespace std;.
One statement per line.
Give your variables proper names, so it's easy to identify what is what. (This is not 1993, really, I'd rather have a thisIsThePointerHoldingTheCharacterThatDoesTheThing than ptr_xy.)
Fix the aforementioned issues (add breaks, make sure your loop actually exits).
Then debug your code. With a debugger. While it runs. With breakpoints and stepping through line by line, inspecting the values of your pointers as the code executes. Fancy stuff.
Good luck!
just count the number of 'R', 'G' and 'B' letters and fill the array from scratch.
much easier, no recursions.

How do I check if a variable is not equal to multiple things in C++?

I'm writing a piece of my code that checks whether what the user has entered is actually one of the valid inputs (1-9 in this case), and will give an error message if it isn't.
This is what I have:
if (input != '1', '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' , '0' )
{
cout << "Error";
}
But it doesn't seem to work. I thought I could use commas to separate them, but maybe I'm imagining that.
Is the only option to just do:
input != '1' && input != '2' && input != '3' etc etc
I know that method would work, but it seems a bit long winded. Is there a simpler way?
You can store the values in a container and utilize the std::find_if, std::none_of or std::any_of functions:
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
std::vector<char> v = { '1', '2', '3', '4', '5', '6', '7', '8', '9', '0' };
char input = '1';
if (std::none_of(v.cbegin(), v.cend(), [&input](char p){ return p == input; })) {
std::cout << "None of the elements are equal to input.\n";
}
else {
std::cout << "Some of the elements are equal to input.\n";
}
}
How do I check if a variable is not equal to multiple things
Is the only option to just do:
input != '1' && input != '2' && input != '3' etc etc
In the general case, for an arbitrary set of values: No, that is not the only option, but it is the simplest. And simplest is often best, or at least good enough.
If you dislike the redundant repetition of input !=, a variadic template can be used to generate the expression. I've written an example of this in another question: https://stackoverflow.com/a/51497146/2079303
In specific cases, there may be better alternatives. There exists std::isdigit for example for exactly the particular case in your example code.
In order to check if a variable is (not) equal to mutliple things which are not known until runtime, the typical solution is to use a set data structure, such as std::unordered_set.
If you are looking for a more general and human-readable construct, you can create something like this:
template <typename T, int TSize>
struct AnyOfThis {
template <typename TFirst, typename... TOthers>
explicit AnyOfThis(TFirst&& first, TOthers&&... others)
: values({ std::forward<TFirst>(first), std::forward<TOthers>(others)... }) {}
std::array<T, TSize> values;
};
template <typename TFirst, typename... TOthers>
auto anyOf(TFirst&& first, TOthers&&... others) {
constexpr std::size_t size = 1 + sizeof...(others);
return AnyOfThis<typename std::decay<TFirst>::type, size>(std::forward<TFirst>(first),
std::forward<TOthers>(others)...);
}
template <typename T, int TSize>
bool operator==(const T value, const AnyOfThis<typename std::decay<T>::type, TSize>& anyOfThis) {
return std::find(anyOfThis.values.begin(), anyOfThis.values.end(), value) != anyOfThis.values.end();
}
Basically, it creates a static array from a variadic function. Then there is another function which serves as a comparator, which takes the value you want to compare and looks for this value in the array.
The use-case reads fairly well, too:
if (1 == anyOf(1, 2, 3)) {
// do stuff
}
LIVE DEMO AT COLIRU
simple and efficient way would be.
std::unordered_set<char> allowedValues = {'1','2','3','4','5','6','7','8','9','0'};
std::unordered_set<char>::const_iterator index = allowedValues.find(input);
if(index == allowedValues.end())
std::cout << "Error";
else
std::cout << "Valid";
by using unordered set you expect O(1) complexity for lookup. It is good when input number is high. If your index is equal to end of set it does not exist in the list, you will get end of set as index which is invalid input for you. otherwise you will count it as a valid input
If you are looking for "if a string is not equal to multiple strings in C" you may use the following (Not everyone would consider it elegant, but if you are fond of good old c-str then you may find it nice. Surely, it is simple and fast):
int GetIdxOfStringInOptionList (const char *Xi_pStr)
{
char l_P2[205];
sprintf(l_P2, "<#%s^>", Xi_pStr); // TODO: if (strlen>=200) return -1. Note that 200 is above length of options string below
_strlwr(l_P2); // iff you want comparison to be case insensitive
const char *l_pCO = strstr("01<#gps^>02<#gps2^>03<#log^>04<#img^>05<#nogps^>06<#nogps2^>07<#gps3^>08<#pillars0^>09<#pillars1^>10<#pillars2^>11<#pillars3^>", l_P2);
return l_pCO? atoi(l_pCO-2) : -1;
}

Integer to string optimized function?

I have currently this function to convert an unsigned integer to a string (I need a function that works on non-standard types like __uint128_t):
#include <iostream>
#include <algorithm>
#include <string>
template <typename UnsignedIntegral>
std::string stringify(UnsignedIntegral number, const unsigned int base)
{
static const char zero = '0';
static const char alpha = 'A';
static const char ten = 10;
std::string result;
char remainder = 0;
do {
remainder = number%base;
result += (remainder < ten) ? (zero+remainder) : (alpha+remainder-ten);
number /= base;
} while (number > 0);
std::reverse(std::begin(result), std::end(result));
return result;
}
int main()
{
std::cout<<stringify(126349823, 2)<<std::endl;
return 0;
}
Is there any way to optimize this code ?
You may want to read this article by Alexei Alexandrescu, where he talks about low-level optimizations by using a (fixed-radix) int to string conversion as an example:
https://www.facebook.com/notes/facebook-engineering/three-optimization-tips-for-c/10151361643253920
Keep in mind that the most important thing when optimizing is always profiling.
One simple thing is avoiding multiple heap allocations, which can be done by either result.reserve(CHAR_BIT * sizeof(Integral)) (the largest possible string being base 2) or building the string into a local array first and then creating the std::string from it. Even with that, I agree with #SebastianRedl; you cannot optimize w/o measuring. Also, your code doesn't take into account negative numbers.
If you're lucky you will be inside "short string optimization" buffer size for the string. If not, then you incur a dynamic memory allocation which is probably at least an order of magnitude slower than the conversion code. So first, get rid of that std::string, and add support for determining suitable raw buffer size.
When you've done that, get rid of the branching caused by the choice operator. Table lookup might be faster (or not). But it's also possible to use bit tricks such as converting small negative number to all one's by bit-shifting right, then use that as a mask.
Finally, instead of reversing the result you can build it directly backward from the end of the supplied buffer, and produce pointer to start as function result.
All this said, do remember to MEASURE.
For optimizations that logically can't be significantly worse than the original, such as the above, measuring might be more work than simply doing the optimizations coding. But when you have done the obvious and you're interested in eeking out the last bit of performance, measuring is necessary. Also, for most programmers measuring is necessary just in order to not waste time on completely unnecessary optimization, or introducing new inefficiency.
You are asking for a way to optimize the code. There is indeed a faster way than pure digit-by-digit conversion: you can work with groups of digits, i.e. in a base that is a power of the desired base.
For example:
Base 2 -> base 256 (8 bits at a time)
Base 8 -> base 512 (3 octal digits at a time)
Base 10 -> base 100 (2 decimal digits at a time)
Base 16 -> base 256 (2 hexadecimal digits at a time)
You will need to pre-tabulate the representation of the digit combinations as short ASCII character strings. And you will need to add special processing of the high-order digits to avoid or undo leading zeroes.
OctalStrings[]= { "000", "001", "002" ... }
But the main loop will remain of the form:
do
Q= N / Base
R= N - Q * Base
N= Q
Insert(Strings[R])
while N>0
or, for a binary base:
do
R= N & (Base - 1)
N= N >> LgBase
Insert(Strings[R])
while N>0
You can also do the conversion directly left-to-right by precomputing all powers of the base and using quotient/remainder.
Base100Powers[]= { 1, 100, 10000, 1000000... }
do
Q= N / Powers[k]
N= N - Powers[k] * Q
Append(Strings[Q])
k--
while k>0
Here is, I think, a more efficient version, I have just coded:
#include <iostream>
#include <type_traits>
#include <algorithm>
#include <string>
#include <array>
template <bool Upper = true,
typename Char = char,
Char Zero = '0',
Char Nine = '9',
Char Alpha = Upper ? 'A' : 'a',
Char Zeta = Upper ? 'Z' : 'z',
Char One = 1,
Char Ten = Nine-Zero+One,
Char Size = (Nine-Zero+One)+(Zeta-Alpha+One),
typename... Types,
class = typename std::enable_if<
(std::is_convertible<Char, char>::value) &&
(sizeof...(Types) == Size)>::type>
constexpr std::array<char, Size> alphabet(const Types&... values)
{
return {{values...}};
}
template <bool Upper = true,
typename Char = char,
Char Zero = '0',
Char Nine = '9',
Char Alpha = Upper ? 'A' : 'a',
Char Zeta = Upper ? 'Z' : 'z',
Char One = 1,
Char Ten = Nine-Zero+One,
Char Size = (Nine-Zero+One)+(Zeta-Alpha+One),
typename... Types,
class = typename std::enable_if<
(std::is_convertible<Char, char>::value) &&
(sizeof...(Types) < Size)>::type>
constexpr std::array<char, Size> alphabet(Types&&... values)
{
return alphabet<Upper, Char, Zero, Nine, Alpha, Zeta, One, Ten, Size>
(std::forward<Types>(values)...,
Char(sizeof...(values) < Ten ? Zero+sizeof...(values)
: Alpha+sizeof...(values)-Ten));
}
template <typename Integral,
Integral Base = 10,
Integral Zero = 0,
Integral One = 1,
Integral Value = ~Zero,
class = typename std::enable_if<
(std::is_convertible<Integral, int>::value) &&
(Value >= Zero) &&
(Base > One)>::type>
constexpr Integral digits()
{
return (Value != ~Zero)+
(Value > Zero ? digits<Integral, Base, Zero, One, Value/Base>()
: Zero);
}
template <bool Upper = true,
typename Integral,
std::size_t Size = digits<Integral, 2>()>
std::string stringify(Integral number, const std::size_t base)
{
static constexpr auto letters = alphabet<Upper>();
std::array<char, Size+1> string = {};
std::size_t i = 0;
do {
string[Size-i++] = letters[number%base];
} while ((number /= base) > 0);
return &string[Size+1-i];
}
int main()
{
std::cout<<stringify(812723U, 16)<<std::endl;
return 0;
}
It could be optimized more efficiently using the technique of Yves Daoust (using a base that is a power of the provided base).

C++ Integer [?]

In Java, strings have a charAt() function.
In C++, that function is simply stringname[INDEX]
However, what if I wanted to use a particular number at a certain index of an integer?
E.g.
int value = 9123;
Let's say I wanted to work with the index 0, which is just the 9.
Is there a way to use index at's with integers?
int value = 9123;
std::stringstream tmp;
tmp << value;
char digit = (tmp.str())[0];
No, there is no standard function to extract decimal digits from an integer.
In C++11, there is a function to convert to a string:
std::string string = std::to_string(value);
If you can't use C++11, then you could use a string stream:
std::ostringstream stream;
stream << value;
std::string string = stream.str();
or old-school C formatting:
char buffer[32]; // Make sure it's large enough
snprintf(buffer, sizeof buffer, "%d", value);
std::string string = buffer;
or if you just want one digit, you could extract it arithmetically:
int digits = 0;
for (int temp = value; temp != 0; temp /= 10) {
++digits;
}
// This could be replaced by "value /= std::pow(10, digits-index-1)"
// if you don't mind using floating-point arithmetic.
for (int i = digits-index-1; i > 0; --i) {
value /= 10;
}
int digit = value % 10;
Handling negative numbers in a sensible way is left as an exercise for the reader.
You can use the following formula (pseudo-code) :
currDigit = (absolute(value) / 10^index) modulo 10; // (where ^ is power-of)
Just to make things complete, you can also use boost::lexical_cast, for more info check out the documentation here.
Basically its just a nice wrapper around the code which can be found at Andreas Brinck answear.
Another solution, which does use 0 for the lestmost digit. digits is used to break down value into individual digits in written order. (i.e. "9347" becomes 9,3,4,7). We then discard the first index values. I.e. to get the 3nd digit, we discard the first two and take the new front.
if (value==0 && index ==0) return 0; // Special case.
if (value <0) { ... } // Unclear what to do with this.
std::list<char> digits;
while (value) {
digits.push_front(value % 10);
value /= 10;
}
for(; index > 0 && !digits.empty(); index--) {
digits.pop_front();
}
if (!digits.empty()) {
return digits.front();
} else
{
throw std::invalid_argument("Index too large");
}
An integer is not a string and therefor you can not do that. What you need is indeed to convert an integer to string. You can use itoa or have a look here.
Try sprintf to write the integer out to a string:
http://www.cplusplus.com/reference/clibrary/cstdio/sprintf/
Then you can index into the char array that you've just printed into.
I've implemented a variant of giorashc s solution, with all the suggested fixes and issues resolved: Its a bit long but it should be fast if everything is inlined: Most of the code is tests which I've left in for completeness.
#include <iostream>
#include <math.h>
char get_kth_digit( int v, int index)
{
assert(v>0);
int mask = pow(10,index);
return '0'+(v % (mask*10))/mask;
}
int count_digits( int v )
{
assert(v>0);
int c=0;
while(v>0)
{
++c;
v/=10;
}
return c;
}
char get_int_index(int v, int index)
{
if( v==0 ) return '0';
if( v < 0 )
{
if(index==0) { return '-'; }
return get_int_index(-v,index-1);
}
// get_kth_digit counts the wrong way, so we need to reverse the count
int digits = count_digits(v);
return get_kth_digit( v, digits-index-1);
}
template<typename X, typename Y>
void compare(const X & v1, const Y & v2, const char * v1t, const char * v2t, uint32_t line, const char * fname )
{
if(v1!=v2)
{
std::cerr<<fname<<":"<<line<<": Equality test failed "<< v1t << "("<<v1<<") <> " << v2t <<" ("<<v2<<")"<<std::endl;
}
}
#define test_eq(X,Y) compare(X,Y,#X,#Y,__LINE__,__FILE__)
int main()
{
test_eq( 1, count_digits(1) );
test_eq( 1, count_digits(9) );
test_eq( 2, count_digits(10) );
test_eq( 2, count_digits(99) );
test_eq( 3, count_digits(100) );
test_eq( 3, count_digits(999) );
test_eq( '1', get_kth_digit(123,2) );
test_eq( '2', get_kth_digit(123,1) );
test_eq( '3', get_kth_digit(123,0) );
test_eq( '0', get_kth_digit(10,0) );
test_eq( '1', get_kth_digit(10,1) );
test_eq( '1', get_int_index(123,0) );
test_eq( '2', get_int_index(123,1) );
test_eq( '3', get_int_index(123,2) );
test_eq( '-', get_int_index(-123,0) );
test_eq( '1', get_int_index(-123,1) );
test_eq( '2', get_int_index(-123,2) );
test_eq( '3', get_int_index(-123,3) );
}
Longer version respect to Andreas Brink.
The C++ library is designed so that between "sequences" and "values" there is a "mediator" named "stream", that actually act as a translator from the value to their respecting sequence.
"sequences" is an abstract concept whose concrete implementation are "strings" and "files".
"stream" is another abstract concept whose correspondent concrete implementation are "stringstream" and "fstream", that are implemented in term of helper classes "stringbuf" and "filebuf" (both derived form the abstract "streambuf") and from a helper object of "locale" class, containing some "facets".
The cited answer code, works this way:
The tmp object of class stringstream is default-constructed: this will construct also internally a stingbuf and a string, plus a locale referencing the facets of the system global locale (the default one remaps the "classic" or "C" locale)
The operator<< between stream and int function is called: there is one of them, for all the basic types
The "int version" gets the num_put facet from the locale, and a "buffer iterator" from the buffer, and calls the put function passing the format flags of the given stream.
the "put function" actually converts the number into the character sequence thus filling the buffer
When the buffer is full, or when a particular character is inserted or when the str function is called, the buffer content is "sent" (copyed, in this case) to the string, and the string content returned.
This very convoluted process looks complex at first but:
Can be completely hidden (resulting in two lines of code)
Cam be extended to virtually anything but...
It is often kept as a (sort of ) misery in its details in the most of C++ courses and tutorials
I would convert it to a string, then index it -- CPP also has the:
str.at(i)
function similar to Java's.
Another simpler loop in C++11 would be a range based loop --
int i = 0
for(auto s : int_or_str){
if(i == idx)
cout << s;
else
i++
}
I guess this isn't easier than the standard for loop -- thought auto may be helpful, not really. I know this is answered, but I prefer simple and familiar answers.
Zach