Can somebody tell me how this code working with no curly braces between two if? - c++

If I am enclosing the code after first if upto second return in curly braces it is not giving me desired output.
static int comparator(Player a, Player b) {
if(a.score == b.score)
if(a.name == b.name)
return 0;
else
return (a.name > b.name)? -1:1;
return (a.score < b.score)? -1:1;
}

Your code has if() and else statements. Each will execute one line of code that comes after them. This means that it will only execute a single statement and end after the first ; that it finds.
for() loops, while() loops, if-else blocks can be used without curly braces if the statement you want to execute consists of only one line of code following them.
Your code works as -
static int comparator(Player a, Player b) {
// if statement without braces- means just one statement executes
if(a.score == b.score)
// Remember if-else will be considered as a single code block so both will run
if(a.name == b.name)
return 0;
else
return (a.name > b.name)? -1:1;
// This statement will run only when the above if condition is not satisfied
return (a.score < b.score)? -1:1;
}
This can be considered to be same as -
static int comparator(Player a, Player b) {
if(a.score == b.score) {
if(a.name == b.name) {
return 0;
} else {
return (a.name > b.name) ? -1 : 1;
}
}
return (a.score < b.score) ? -1 : 1;
}
NOTE : It is generally better if you use the braces as it will be good for readability as well as maintainability of the code. There can actually be two way of parsing it - Dangling else(though most compiler will associate the else with closest if).
In this coding style, there's no way to differentiate between below two code -
if(condition1)
if(condition2)
foo1();
else
foo2();
and,
if(condition1)
if(condition2)
foo1();
else
foo2();
Since, in C/C++, it doesn't consider the indentation in code, so it might create ambiguity while reading the code. So its always better to use curly braces instead of doing it like above. Drop them only when you have a single line and it won't create any confusion reading the code later on...
Hope this helps !

Without curly braces, only the next statement is executed. With proper indentation it becomes easier to see what's going on:
static int comparator(Player a, Player b) {
if(a.score == b.score)
if(a.name == b.name)
return 0;
else
return (a.name > b.name) ? -1 : 1;
return (a.score < b.score) ? -1 : 1;
}
This is actually the same as:
static int comparator(Player a, Player b) {
if(a.score == b.score) {
if(a.name == b.name) {
return 0;
} else {
return (a.name > b.name) ? -1 : 1;
}
}
return (a.score < b.score) ? -1 : 1;
}
You have maybe used the braceless else variant without noticing it when writing something like:
if(condition) {
//
} else if(another_condition) {
//
} else {
//
}
Which is actually the same as
if(condition) {
//
} else {
if(another_condition) {
//
} else {
//
}
}

Without curly braces, the if guard only applies to the immediate next statement.
It's just how the language works. :/

Related

C++ runtime error: addition of unsigned offset?

I wrote the following to check if text is palindrome, I run it on leetcode and I am getting errors:
class Solution {
public:
bool isPalindrome(string s) {
int l=0,r=s.length()-1;
while(l<r)
{
while (!isalpha(s[r]))
{
--r;
}
while (!isalpha(s[l]))
{
++l;
}
if (tolower(s[r])!=tolower(s[l]))
return false;
--r;
++l;
}
return true;
}
};
Line 1061: Char 9: runtime error: addition of unsigned offset to
0x7ffc7cc10880 overflowed to 0x7ffc7cc1087f (basic_string.h) SUMMARY:
UndefinedBehaviorSanitizer: undefined-behavior
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/basic_string.h:1070:9
what's the problem with my code?
You're going out of bounds here:
while (!isalpha(s[r]))
and here
while (!isalpha(s[l]))
r can became negative and l can become >= s.length().
You should add some checks like
while (l < r && !isalpha(s[r]))
and
while (l < r && !isalpha(s[l]))
The same problem in this line
if (tolower(s[r])!=tolower(s[l]))
This should be
if (l < r && tolower(s[r])!=tolower(s[l]))
Different approach (C++20)
A different approach is to erase all non-alpha characters from s with
std::erase_if(s, [](char c) { return !isalpha(c); });
and remove the inner while loops.
I think you were very close to the solution. The pitfall here are that:
you are modifying the loop control variable more than once in the loop
(as consequence) you are using the loop control variable after changing their values without further checks.
The easy way to fix this kind of issue is to do one single action for every iteration. you can achieve this just using "else".
class Solution {
public:
bool isPalindrome(string s) {
int l=0,r=s.length()-1;
while(l<r)
{
if(!isalpha(s[r]))
{
--r;
}
else if(!isalpha(s[l]))
{
++l;
}
else if (tolower(s[r])!=tolower(s[l]))
{
return false;
}
else
{
--r;
++l;
}
}
return true;
}
};

Error: control may reach end of non-void function in C++

I cannot figure out why this error is happening: error: "control may reach end of non-void function" even when "else" statement is present at the end.
Here is the code:
bnode* binsert(bnode *h,int k){
bnode *temp=new bnode;
if(h==NULL)
{
temp->num=k;
temp->L=NULL;
temp->R=NULL;
h=temp;
return h;
}
else if(h->L==NULL && k<h->num)
{
temp->num=k;
temp->L=NULL;
temp->R=NULL;
h->L=temp;
return h;
}
else if(h->R==NULL && k>h->num)
{
temp->num=k;
temp->L=NULL;
temp->R=NULL;
h->R=temp;
return h;
}
else if(h->L!=NULL && k<h->num)
{
h->L=binsert(h->L,k);
}
else
{
h->R=binsert(h->R,k);
}
}
You need to return the results of recursive calls, it's not done automatically.
You can also simplify your code a bit by adding a constructor:
bnode::bnode(int v)
: num(v),
L(nullptr),
R(nullptr)
{
}
and since you're already handling the case of a null parameter, you don't need special cases for null children:
bnode* binsert(bnode *h,int k)
{
if(h == nullptr)
{
h = new bnode(k);
}
else if(k < h->num)
{
h->L = binsert(h->L, k);
}
else if(k > h->num)
{
h->R = binsert(h->R, k);
}
return h;
}
because this last 2 conditions:
else if(h->L!=NULL && k<h->num)
{
h->L=binsert(h->L,k);
}
else
{
h->R=binsert(h->R,k);
}
may occur and no return is given...
you need to be sure the function returns a value no matter what the condition evaluates....
else if(h->L!=NULL && k<h->num)
{
h->L=binsert(h->L,k);
}
else
{
h->R=binsert(h->R,k);
}
In the else if and else cases for your code, if you reach here, you do not return a value, and the behavior is undefined if you try to use this value.
You probably want to add a return h; in the two branches.

function returning something strange

I have a function to get a grade point value from a grade object and return it as a double as implemented below:
double Grade::getNumGrade()
{
double value;
if (strGrade == "A")
{
return 4.0;
}
else if (strGrade == "A-")
{
return 3.7;
}
else if (strGrade == "B+")
{
return 3.3;
}
else if (strGrade == "B")
{
return 3.0;
}
else if (strGrade == "B-")
{
return 2.7;
}
else if (strGrade == "C+")
{
return 2.3;
}
else if (strGrade == "C")
{
return 2.0;
}
else if (strGrade == "C-")
{
return 1.7;
}
else if (strGrade == "D+")
{
return 1.3;
}
else if (strGrade == "D")
{
return 1.0;
}
else if (strGrade == "D-")
{
return 0.7;
}
else if (strGrade == "F")
{
return 0.0;
}
}
With strGrade being the string representation of the grade. However with the code here:
Grade jon = Grade("A+");
cout << jon.getNumGrade();
outputs :
-1.#IND
The constructor just makes sure the first letter is uppercase and then saves the string provided as strGrade. Not sure why this is happening or how to fix it?
As NathanOliver pointed out,
You never handle A+ in your if statements.
See
double value;
if (strGrade == "A")
{
return 4.0;
}
else if (strGrade == "A-")
{
return 3.7;
}
No conditional for when strGrade == A+.
But since this was answered in a comment, I'll attempt to justify writing this as an answer by giving you some advice.
Your final conditional,
else if (strGrade == "F")
{
return 0.0;
}
shouldn't be an else if. There's plenty of good ways to deal with error handling (like an unexpected input) but a very easy yet efficient practice is to end your conditionals with an else. For example,
//if all other conditionals thus far have returned false
else
{
... error handling here ...
}
In the event that you fall into this else, log an error and/or gracefully exit the program; at the least, return a value and handle it appropriately.
Also consider applying your if else in a logical ordered based on the likelihood of a certain conditional being evaluated to true. More specifically, if you know that a majority of students are going to get a B+, make that the first expression that gets evaluated in your if else series. If a B- is the next most common grade, make that the second expression that gets evaluated; and so on. Additionally, if you know that a grade is least likely to be passed through, make that the last conditional you check.
Not sure why this is happening or how to fix it?
That's happening because your function doesn't return a value for the "A+" case and exposes undefined behavior.
As mentioned in comments you should have seen a compiler warning about that stating
Not all of your code paths return a value.
You can fix that providing always a (reasonable) return value before your last brace in the function, or throwing an exception for unexpected cases of strGrade.
BTW the much easier solution would be to use a std::map<std::string,double> to hold the associative values:
double Grade::getNumGrade() {
static std::map<std::string,double> numGrades = {
{ "A", 4.0 } ,
{ "A-", 3.7 } ,
{ "B+", 3.3 } ,
// ...
};
auto found = numGrades.find(strGrade);
if(found != numGrades.end()) {
return found->second;
}
return 0.0;
}
It also looks that this should be a free or static function rather than a class member function:
double getNumGrade(const std::string& strGrade) {

Refactor several nested if with same else

This is not about an existing piece of code but I'm looking for some pattern that may exist in the case that some nested if perform the same thing in their else statement.
if(condition1(a)) {
doSomethingWith1(a);
if(condition2(a)) {
doSomethingWith2(a);
} else {
elseFn();
}
} else {
elseFn();
}
The doSomethingWith... functions are changing the value of a, making it complex to have all the condition in one if.
So I'm just wondering if there is a clearer way to write it (in C, if possible).
Thanks guys
in your case, looks like the first if, if(condition1(a)), is absolutely necessary to test for the value of a before calling doSomethingWith1(a); to avoid an exception. so, no, there is no other way to do it.
if(condition1(a)) {
doSomethingWith1(a);
if(condition2(a)) {
doSomethingWith2(a);
} else {
elseFn();
}
} else {
elseFn();
}
You could just keep a count of the "doSomethings" and invoke the elseFn unless all were executed.
int count = 0;
if (condition1(a)) {
doSomethingWith1(a);
count++;
if (condition2(a)) {
doSomethingWith2(a);
count++;
if (condition2(a)) {
doSomethingWith2(a);
count++;
}
}
}
if (count < 3) {
elseFn();
}
I find it more readable, though less efficient, to double-check the first condition. This refactoring eliminates nesting, without multiple functions. It also more clearly shows three distinct paths of execution by grouping each logical path into a single code block.
if (condition1(a) && condition2(a)) {
doSomethingWith1(a);
doSomethingWith2(a);
}
else if (condition1(a)) {
doSomethingWith1(a);
elseFn();
}
else {
elseFn();
}
I don't know in C but in Java you could write this as the following:
void function(int a) {
boolean b1 = condition1(a);
if (b1) {
doSomethingWith1(a);
boolean b2 = condition2(a);
if (b2) {
doSomethingWith2(a);
}
}
if (b1 || b2) {
return;
}
elseFn();
}

Nested IF statements vs IF-ELSE

I'm learning C language usnig Turbo C++ compiler and just in time I encountered the two statements:
IF (nested with many IFs)
IF-else(not nested but continuing else,else and so on)
I was wondering if my idea is correct or not that IF (nested with many IFs) and IF-else(not nested) are the same? Suggestions are well appreciated.
That's only basic logic behind that:
Nested if conditions:
IF first condition's value is true, go into the second condition.
if(a > 0)
{
printf("A is greater than 0\n");
if(a > 2) printf("A is greater than 0 and 2\n");
}
if-else condition:
IF first condition's value is false, go to the next:
if(a > 0) printf("A is greater than zero\n");
else if(a < 0) printf("A is lesser than zero\n");
else printf("A is zero\n");
There is one more instruction that you should know, switch:
switch(a)
{
case 0: printf("A is zero\n"); break;
case 1: printf("A is one\n"); break;
case 5: printf("A is five\n"); break;
default: printf("A is not 0, 1 or 5\n"); break;
}
Nested if is not equivalent to if-else. It can be equivalent to single if with a combined condition, for instance:
if (a == 1) {
if (b == 2) {
...
}
}
is equivalent to:
if (a == 1 && b == 2) {
...
}
I guess you rather mean if this:
if(expression){
//code
}
else{
if(expression){
//code
}
}
is equivalent to this:
if(expression){
//code
}
else if(expression){
//code
}
and yes it's absolutely the same. Second one is just better looking way of doing this.
The else if blocks are in fact nested else’s since C and C++ don’t have any special support for “elseif” or “elif” concept (not speaking about the preprocessor directives now). It gets obvious with strict use of blocks and indentation:
if(something) { doSomething(); }
else {
if(anotherThing) { doAnotherThing(); }
else {
if(yetAnotherThing) { doYetAnotherThing(); }
else
{ doSomethingElse(); }
}
}
The same code written with the usual else if notation:
if(something) { doSomething(); }
else if(anotherThing) { doAnotherThing(); }
else if(yetAnotherThing) { doYetAnotherThing(); }
else { doSomethingElse(); }
And as Mateusz Kwaśniak has mentioned, you should prefer switch over else if when possible. However, it’s not available for string comparison, for example.