Compact multi-conditional if statement - c++

I have the simplest question ever. I was practising with the if statement and wondered if I could print out different messages under different conditions, but I wanted to keep it simple. If the 1st condition is true, the 1st line of cout will print; and if the 2nd condition is true, the 2nd line of cout will print; and so on. Code follows;
int x; cin >> x;
int y; cin >> y;
if(x<y||x>y||x==y)
{
cout << x << " is smaller than " << y << endl;
cout << x << " is bigger than " << y << endl;
cout << x << " is equal to " << y << endl;
}
Apparently there is something missing, some kind of ||s between the couts. Is it possible to keep this code as compact as it is and make it function properly?

To do what you ask, your code should be:
int x; cin >> x;
int y; cin >> y;
if(x<y)
{
cout << x << " is smaller than " << y << endl;
}
else if (x>y)
{
cout << x << " is bigger than " << y << endl;
}
else
{
cout << x << " is equal to " << y << endl;
}
In other words, your three conditions have to be in separate parts of the if-else if-else control structure. This way, one of them executes based on your inputs and the corresponding message is printed out.

What to you mean by simple? If compact, then this is correct (but not the most readable) . .
x==y?cout<<"x=y":(x<y?cout<<"x<y":cout<<"x>y");
. . or go crazy and make == the default case to save a char
x>y?cout<<"x>y":(x<y?cout<<"x<y":cout<<"x=y");

it helps to think mathematically about these situations. if there are three possible cases (<, >, and =), then you need to test twice. in the code below, two tests are done to determine if the relationship is less than, or greater than; if either, then the proper output is issued. assuming that neither of the above is true, then the only other possibility is equal. that is handled by the else. chaining if...else if...else statements together is the general solution. the switch keyword exists for a more limited approach.
#include <iostream>
using namespace std;
int main() {
int x;
cout << "Enter x: ";
cin >> x;
cout << "Enter y: ";
int y; cin >> y;
if (x < y)
cout << x << " is smaller than " << y << endl;
else if (x > y)
cout << x << " is bigger than " << y << endl;
else
cout << x << " is equal to " << y << endl;
}

You can go like this:
int x; cin >> x;
int y; cin >> y;
if(x<y) {
cout << x << " is smaller than " << y << endl;
} else if (x>y) {
cout << x << " is bigger than " << y << endl;
} else if (x==y) {
cout << x << " is equal to " << y << endl;
}
Or if you feel adventurous just:
} else {
cout << x << " is equal to " << y << endl;
}

you use the magic of ternary operator:
#include <iostream>
int main()
{
int x, y;
std::cin >> x >> y;
(x == y) ? (std::cout << x << " is equal to " << y << std::endl) :
((x < y) ? (std::cout << x << " is smaller than " << y << std::endl) :
(std::cout << x << " is bigger than " << y << std::endl));
return 0;
}

If you want to go completely overboard you could abuse the template system a little.
auto if_ = make_if(
std::greater<>{}, [](auto x, auto y){ cout << x << " is greater than " << y << endl; },
std::less<>{}, [](auto x, auto y){ cout << x << " is smaller than " << y << endl; },
std::equal_to<>{}, [](auto x, auto y){ cout << x << " is equal to " << y << endl; }
);
if_(0,0);
if_(0,1);
if_(1,0);
Would yield
0 is equal to 0
0 is smaller than 1
1 is greater than 0
live demo
Here's full implementation of this:
template<typename Pred, typename Result, typename... Others>
struct If;
namespace detail
{
template<typename... Ts>
struct IfSelector
{
using type = If<Ts...>;
};
template<>
struct IfSelector<>
{
struct EmptyIf
{
template<typename... Ts>
void operator()(Ts&&...){}
};
using type = EmptyIf;
};
template<typename... Ts>
using ParentIf = typename IfSelector<Ts...>::type;
}
template<typename Pred, typename Result>
struct IfEntry
{
Pred pred;
Result result;
};
template<typename Pred, typename Result, typename... Others>
struct If : detail::ParentIf<Others...>
{
using pred = Pred;
using result = Result;
using parent = detail::ParentIf<Others...>;
template<typename P, typename R, typename... Os>
If(P&& p, R&& r, Os&&... os):
parent{std::forward<Os>(os)...},
entry{std::forward<P>(p), std::forward<R>(r)}
{}
template<typename... Ts>
void operator()(Ts&&... ts) {
if(entry.pred(ts...)) {
entry.result(std::forward<Ts>(ts)...);
} else {
this->parent::operator()(std::forward<Ts>(ts)...);
}
}
IfEntry<Pred, Result> entry;
};
template<typename... Ts>
auto make_if(Ts&&... ts){
return If<Ts...>(std::forward<Ts>(ts)...);
}
Basically, you pass a list of predicate-result pairs to the template, and they're checked in the reverse order. If a predicate yields true, the paired action is executed.

If you really want it short, and don't care much about readability, start with an array of labels:
static char const *names[] = {" is smaller than ", " is equal to ", " is bigger than "};
Then use ugly Boolean logic to index into that:
std::cout << x << names[1 + (y<x)-(x<y)] << y << '\n';
To figure out that logic, keep in mind that a<b produces either false (which will convert to 0) or true (which will convert to 1).
So:
if x < y => y<x = 0, x<y = 1, 0-1 = -1
if y == x => y<x = 0, x<y = 0, 0-0 = 0
if y < x => y<x = 1, x<y = 0, 1-0 = 1
Then add one to get the -1...1 to be 0..2 instead, and use that to index into the array.
Seriously though: if you're going to do something like this, at least wrap the comparisons up into a cmp(x,y) or something on that order:
int cmp(int x, int y) { return y<x - x<y; }
Then use that in the other code:
std::cout << names[1+cmp(x, y)] << '\n';
That doesn't eliminate the unreadable bit of code, but at least it restricts it to one little place (and lets you replace it with more normal logic when you're sick of its excessive cuteness, without having to edit the rest of the code).
For what it's worth (not much) this cmp function is defined to produce the same type of result as expected by qsort and bsearch.

Related

less-than operator doesn't work properly after few executions

I'm a beginner to learning C++. Just today I tried to learn the boolean operator and if-else statement.
This is the code:
int main(){
//if-else statement
int a, b;
bool result = (a < b);
std::cout << "input number 1 : ";
std::cin >> a;
std::cout << "input number 2 : ";
std::cin >> b;
std::cout << std::boolalpha << result <<std::endl;
if(result == true){
std::cout << a << " is less than " << b << std::endl;
}
if(!(result == true)){
std::cout << a << " is NOT less than " << b << std::endl;
}
return 0;
}
These are the results after a few executions:
Initially the results were fine, but then after a couple times it went wrong.
Does anybody know what the cause of this is?
Your mistake is that you compare the two variables and save the result before you assign any proper values to these variables. In other words, you compare uninitialized variables a and b which have undefined values.
First, you do:
bool result = (a < b);
And then after you get the values:
std::cin >> a;
std::cin >> b;
You should do the following instead:
// ...
int a, b;
std::cout << "input number 1 : ";
std::cin >> a;
std::cout << "input number 2 : ";
std::cin >> b;
bool result = a < b; // <-- move this down here!
// ...
You expect result to be evaluate a == b when you use it later. Instead bool result = (a < b); initializes result with (a < b) once and its value does not change afterwards. As neither a nor b are initialized when you declare result your code has undefined behavior.
You can make result a function object to make it work as you expected by using a lambda expression. However, to call it you'll have to add ():
int main(){
//if-else statement
int a = 0;
int b = 0;
auto result = [&](){ return a < b; };
std::cout << "input number 1 : ";
std::cin >> a;
std::cout << "input number 2 : ";
std::cin >> b;
std::cout << std::boolalpha << result() <<std::endl;
if(result()) {
std::cout << a << " is less than " << b << std::endl;
} else {
std::cout << a << " is NOT less than " << b << std::endl;
}
}
You should always initialize variables. Using the value of uninitialized variables is undefined behavior and can happen easily (as in your code) when you do not initialize variables. Instead of if (condition) {} if (!condition){} you can use if (condition) {} else {}. Instead of if (result() == true) you can write if (result()). And return 0; is implicit in main, you need not write it.
You overall code as it should be.
Explanations in the comments:
int main() {
//if-else statement
int a, b;
std::cout << "input number 1 : ";
std::cin >> a;
std::cout << "input number 2 : ";
std::cin >> b;
bool result = (a < b); // put this here, because now a and b have
// determined values
std::cout << std::boolalpha << result << std::endl;
if (result) { // or simple if (a < b) and drop result alltogether
std::cout << a << " is less than " << b << std::endl;
}
else { // no need for testing the opposite of result
std::cout << a << " is NOT less than " << b << std::endl;
}
return 0;
}

C++ Avoid passing variable to std::cout if its value is zero

Suppose I have a variable, double x, as a result of some calculations, which can have any value, including zero, and I need it passed to std::cout. How can I avoid printing x if its value is zero?
As an example, this will print 1+<value_of_x> if x, else just 1:
std::cout << (x ? "1+" : "1") << x << '\n';
Is there a way to make the same but for x? Something like the following nonsense:
std::cout << (x ? ("1+" << x) : "1") << '\n';
I should probably add that I am not advanced in C++.
You could say
std::cout << (x ? "1+" + std::to_string(x) : "1") << '\n';
but
if (x)
std::cout << "1+" << x << '\n';
else
std::cout << "1" << '\n';
is perhaps more readable.
(I consider this largely a matter of personal preference.)
If x is 0, don't print it:
if (x != 0)
std::cout << x << '\n';
Any further variations should be self-evident.
Using an if statement would be a simple and readable approach:
if (x)
std::cout << "1+" << x;
else
std::cout << "1";
std::cout << '\n';
Or even:
std::cout << "1";
if (x) std::cout << "+" << x;
std::cout << '\n';
But, if you really want to print out the value inline, you can define a custom operator<< to format the value however you want:
struct to_coefficient_str
{
double m_value;
to_coefficient_str(double value) : m_value(value) {}
void print(std::ostream &out) const
{
out << "1";
if (m_value)
out << "+" << m_value;
}
};
std::ostream& operator<<(std::ostream &out, const to_coefficient_str &ce)
{
ce.print(out);
return out;
}
Then you can use it like this:
std::cout << to_coefficient_str(x) << '\n';

Trying to call functions using a vector of pointers to functions, but it fails to return the correct value--is it my compiler?

EDIT:
So it seems like everyone is getting the correct output, so my question is now this: Why am I getting the wrong output? Why is the second argument, y, getting changed to zero, regardless if I use a variable or a literal? And no, I didn't get confused and put the wrong variable, I double checked. I am using Visual Studio 2013.
I'm doing an exercise from the fifth edition of the C++ primer by Lippman, Lajoie, and Moo on page 250, and my code for the third exercise, 6.56, is returning incorrect values.
I made a vector of pointers to function of type int (int, int), made four functions of that type (addition, subtraction, multiplication, and division), and added pointers to them to my vector. I attempted to move through those pointers with an iterator, dereferencing them to call them, but for add2 and subtract, it returned the value of the first argument, 0 for mult, and the else clause for divide, even though y was not equal to 0.
The code is as follows:
int test(int x, int y);
int add2(int x, int y);
int subtract(int x, int y);
int mult(int x, int y);
int divide(int x, int y);
typedef decltype(test) *FuncP; //type declaration of a ptr to a function that takes two ints and returns int
int main(){
//6.7
vector<FuncP> ptrsToFuncs;
ptrsToFuncs.push_back(*add2);
ptrsToFuncs.push_back(*subtract);
ptrsToFuncs.push_back(*mult);
ptrsToFuncs.push_back(*divide);
vector<FuncP>::iterator fIter;
int test1 = 6, test2 = 8;
int test3 = 0;
cout << "Running four arithmetic functions with " << test1 << " and " << test2 << "\n\n";
for (fIter = ptrsToFuncs.begin(); fIter != ptrsToFuncs.end(); ++fIter)
{
int result = (*fIter)(test1, test2);
cout << result << endl;
}
system("PAUSE");
}
int test(int x, int y)
{
if (y != 0)
{
cout << "Modulo of one and two is: " << x % y << "\n\n";
return x % y;
}
else
{
cout << "Cannot divide by zero.\n\n";
return -1;
}
}
int add2(int x, int y)
{
cout << "Adding " << x << " and " << y << ": ";
return (x + y);
}
int subtract(int x, int y)
{
cout << "Subtracting " << x << " and " << y << ": ";
return (x - y);
}
int mult(int x, int y)
{
cout << "Multiplying " << x << " and " << y << ": ";
return (x * y);
}
int divide(int x, int y)
{
if (y != 0)
{
cout << "Dividing " << x << " and " << y << ": ";
return (x / y);
}
else
{
cout << "Cannot divide by zero.\n";
return -1;
}
}
For example, with test1 = 6 and test2 = 8, the return values would be: 6, 6, 0, "Cannot divide by zero." -1.
I also tried this: (**fIter)(test1, test2). I thought that maybe I didn't dereference enough and needed to dereference the pointer to the function as well as the iterator, but it resulted in the same output.
Thank you.
Your code works fine for me, I think possibly you mixed up your variables inside your iteration (replaced test2 to with test3)
for (fIter = ptrsToFuncs.begin(); fIter != ptrsToFuncs.end(); ++fIter)
{
int result = (*fIter)(test1, test3);
cout << result << endl;
}
would give you
6, 6, 0, "Cannot divide by zero." -1.
If you need to see what your code is doing, try replacing your variables with literals and also adding some couts to your function calls.
for (fIter = ptrsToFuncs.begin(); fIter != ptrsToFuncs.end(); ++fIter)
{
int result = (*fIter)(12, 24);
cout << result << endl;
}
int add2(int x, int y)
{
cout<<"add function called with first variable"<<x<<" and second variable"<<y<<endl;
return (x + y);
}

Variable changes value when passed to function?

I feel like an idiot. When I pass a variable to the function it results in a strange output like 6.2+e003 instead of the value that the variable holds. What am I doing wrong?
The x in main and the x in the function are different?
main:
int x, y;
while(system.WindowOpen())
{
x++;
y++;
bg.Draw2D();
bob.Think(x, y);
riley.Think(x, y);
system.Render(0);
}
class method:
void Organism::Think(double x, double y)
{
std::cout << "X: " << x << "\n";
std::vector<double> food;
food.push_back(x);
food.push_back(y);
std::cout << "VECTOR: " << food[0] << " " << food[1] << "\n";
std::vector<double> path;
if(refresh.IsTime()) {
std::cout << "\nFOOD VECTOR: \n" << food[0]
<< "\n" << food[1] << "\n";
path = brian.GetOutput(food);
organism.Translate2D(path[0], path[1]);
if(organism.IsOffScreen2D(resX, resY) == 'l' )
organism.SetPos2D(resX, organism.GetY());
if(organism.IsOffScreen2D(resX, resY) == 'r')
organism.SetPos2D(0, organism.GetY());
if(organism.IsOffScreen2D(resX, resY) == 't')
organism.SetPos2D(organism.GetX(), resY);
if(organism.IsOffScreen2D(resX, resY) == 'b')
organism.SetPos2D(organism.GetX(), 0);
};
font.DrawNumber2D(x, 50, 50);
font.DrawNumber2D(y, 50, 100);
organism.Draw2D();
}
Both x and y are uninitialized here:
int x, y;
so they can hold any value, and reading from them is undefined behaviour. You should initialize them:
int x = 0
int y = 0;
I was writing outside the bounds of a vector. I switched from using the [] operators to using the .at() and found my bug right away. Just a bit of memory corruption. I feel quite silly. Thanks all!

is_const<func-param> in function template always returns false

Is it possible to convert the is_const expressions into a test function or is this impossible because top level cv-qualifieres are ignored during template type deduction?
int main()
{
using std::is_const;
const int x = 0;
int y = 0;
// move to "bool test()"
std::cout
<< "main, x: " << is_const<decltype(x)>::value << "\n" // true
<< "main, y: " << is_const<decltype(y)>::value << "\n" // false
;
std::cout
<< "test, x: " << test(x) << "\n" // false, I wanted true
<< "test, y: " << test(y) << "\n" // false
;
}
I have unsuccessfully tried various versions similar to:
template<typename T>
bool test(T x)
{
return is_const<???>::value;
}
I want to make sure that I am not missing something and that writing such a testfunction is indeed impossible. (If it was possible, I would also like to know whether a C++03 version was possible.)
Thank you for your consideration
Update
Due to Mankarse I learned that type deduction is different in case of rvalue references:
template<typename T> void t1(T x);
template<typename T> void t2(T& x);
template<typename T> void t3(T&& x);
const int x = 42;
int y = 0;
t1(x); // T = int: t1<int>(int x)
t1(y); // T = int: t1<int>(int x)
t2(x); // T = const int: t2<const int>(const int& x)
t2(y); // T = int: t2<int>(int& x)
t3(x); // T = const int&: t3<const int&>(const int& && x)
t3(y); // T = int&: t3<int&>(int& && x)
In C++11, this can be done with perfect forwarding rvalue references:
template<typename T>
bool test(T&& x)
{
return std::is_const<typename std::remove_reference<T>::type>::value;
}
In C++03, you can instead use an lvalue reference:
template<typename T>
bool test(T& x) {
return boost::is_const<T>::value;
}
The differences between the two are demonstrated below:
typedef int const intc;
intc x = intc();
int y = int();
std::cout // C++11 C++03
<< "x: " << test(x) << "\n" // 1 1
<< "y: " << test(y) << "\n" // 0 0
<< "move(x): " << test(std::move(x)) << "\n"// 1 1 (when compiled as C++11)
<< "move(y): " << test(std::move(y)) << "\n"// 0 compilation error
<< "intc{}: " << test(intc()) << "\n" // 0 compilation error
<< "int{}: " << test(int()) << "\n" // 0 compilation error
;