If Statements And Braces.. Different Result With/Without - c++

Alright, so I'm in the process of learning C++, and I've hit a strange effect while working with one of the tutorials, and I don't quite get while it's happening..
For the tutorial (copied from the example offered), I have written a function within a class template specialization that checks if the char is lowercase, and then makes it uppercase:
char uppercase ()
{
//checks to see if "element"(char) is a lower-case letter between 'a' and 'z'
if ((element >= 'a') && (element <= 'z'))
{
//changes value of "element" to be element + (value of A - Value of a)[-32]
element += 'A' - 'a'; //element = element + -32
return element;
};
};
Now, strangely.. even if the char is already uppercase, this code still gets triggered. So if I call the function with a value of 'j', I obviously get 'J', as intended. However, if I call with a value of 'J', the function still goes through.. so instead of the function not changing anything, it instead returns '*'.
Now, interestingly.. if I remove the brackets from the if statement, it works as intended. So, with
char uppercase ()
{
//checks to see if "element"(char) is a lower-case letter between 'a' and 'z'
if ((element >= 'a') && (element <= 'z'))
//changes value of "element" to be element + (value of A - Value of a)[-32]
element += 'A' - 'a'; //element = element + -32
return element;
};
it works completely as intended. Calling the function with the value 'J' just returns 'J', because the conditions weren't met, and thus no code was executed. Now, I know that braces are optional with if statements, but the tutorial says that braces are required for more than one statement.
It's also worth noting that adding an else to the statement using braces with just a plain return gives the desired effect, but this should be unnecessary, right?
So, basically.. am I missing something about braces, or is this just an issue with the compiler (Visual Studio 2012)?

That's per design, the if takes one statement only, the braces make a block one statement.
If you want scope by indentation use Python.
The problem with your code is that you do not return anything when the if statement does not match, which results in undefined behavior. Your compiler probably gives you a warning about that. Don't ignore compiler warnings.
The second block of code is actually what you want, only change the variable element when your if matches, but always return the variable element.

In the first case, you are not executing a return statement if the condition isn't met. Presumably the function is returning garbage.
In the second case, because there are no braces, only one line is dependent on the condition. The return statement is executed regardless. In other words, your second example is equivalent to:
char uppercase ()
{
//checks to see if "element"(char) is a lower-case letter between 'a' and 'z'
if ((element >= 'a') && (element <= 'z'))
{
//changes value of "element" to be element + (value of A - Value of a)[-32]
element += 'A' - 'a'; //element = element + -32
}
return element;
};

You have an if statement. If the statement evaluates to true, it will execute the operation immediately following it. In order to do more than one operation at once, you must enclose them in curly braces.
You're getting a strange answer with braces because if J is uppercase, your if statement is false, you skip past the braces, and you don't have a specified return value (hence the nonsense return value). You need to say what to return if your if statement isn't true.
Your second piece of code works because only the first line after the if statement is controlled by the if. This is essentially you being lucky here with - if you had two operations you had wanted to do, you'd still be getting garbage. It's generally therefore good practice to explicitly specify what code you want executed by your if statement by putting it in curly braces, even if it's one operation.

Related

Cannot understand for loop with two variables [duplicate]

This question already has answers here:
How does the Comma Operator work
(9 answers)
Closed 9 years ago.
When I use two variables in a for loop with different conditions two conditions like I have used below i<3,j<2 the for loop is always executing till the second condition fails.
#include<iostream>
#include<conio.h>
using namespace std ;
int main()
{
int i,j ;
for(i=0,j=0;i<3,j<2;i++,j++)
{
cout<<"hello" ;
}
getch() ;
return 0 ;
}
In that code, hello is printed 2 times. Why?
If I use i<3,j<10, "Hello" is printed 10 times. I can't understand why the first condition is being neglected. Is it compiler dependent or something else?
Every thing works normal if I replace with conditions like || (OR) or &&(AND).An other thing is that I cannot initialize i and j in the for loop itself, it is showing me an error, but works fine when I declare variables in C style or one variable outside the for loop, why is it so?
Compiler I have used is Orwell Dev C++.
Thanks in advance.
for(i=0,j=0;i<3,j<2;i++,j++)
is equivalent to
for(i=0,j=0;j<2;i++,j++)
The comma expression takes on the value of the last expression.
Whichever condition is first, will be disregarded, and the second one will be used only.
The for loop consists of:
for(START_STATEMENT; CONDITION_EXPRESSION, LOOP_EXPRESSION) BODY_BLOCK
Where:
START_STATEMENT is any single statement, which may include variable declaration. If you want to declare 2 variables, you can write int i=0, j=0, but not int i=0; int j=0 because the latter are actually 2 statements. Also node, that variable declaration is a part of statement, but cannot be a part of (sub) expression. That is why int i=0, int j=0 would also be incorrect.
CONDITION_EXPRESSION is any single expression that evaluates to a boolean value. In your case you are using a coma operator which has the following semantics: A, B will do:
evaluate A (it will evaluate, not just ignore)
ditch the result of A
evaluate B
return B as the result
In your case: i<3,j<2 you are comparing i<3, you are just ignoring the result of this comparison.
Comma expressions are useful when the instructions have some side effects, beyond just returning a value. Common cases are: variable increment/decrement or assignment operator.
LOOP_EXPRESSION is any single expression that does not have to evaluate to anything. Here you are using the comma expression again, ignoring the result of the left-hand-side. In this case however, you are not using the result anyway, and just using the ++ side effect - which is to increment the values of your variables.
BODY_BLOCK is either a single statement or a block, encapsulated with curly braces.
The above for can be compared to:
{
START_STATEMENT;
while(EXPRESSION) {
BODY_BLOCK;
LOOP_EXPRESSION;
}
}
The c complier always used second condition.
therefore j<2 is used.
use this for loop
for(i=0,j=0;j<10;i++,j++)

C++ if Followed by a for Loop block

I remember once I've seen somebody writing C++ code like this:
if (something is true)
for (int i = 0; i < max; i++) {
//do something
line 1;
line 2;
line 3;
....
....
}
else
....
It works the same as the following code:
if (something is true) { //note the bracket here
for (int i = 0; i < max; i++) {
//do something
line 1;
line 2;
line 3;
....
....
}
}
else
....
I'm wondering if the compiler treated the for loop block as one line nested within the if clause? Can the multiple lines of code within bracket always be treated as one line? I can't quite understand how does the compiler parse and analyse this.
This is indeed correct code, although it may easily confuse readers. The if-statement considers the first following statement as it's then statement. Code between {} is usually considered a block or compound statement, containing the statements within it. Similarly, the for statement is considered one statement, including the loop body, which is the first statement to follow it (and can again be a block).
They are not really "lines" but rather statements. For instance your
line 1;
line 2;
line 3;
could be rewritten as and would be just as valid as:
line 1; line 2; line 3;
So the compiler is not really looking at lines but rather statements.
A single statement as defined by the grammar is considered either (somewhat simplified):
1) a simple statement terminated by a semicolon (as above)
OR
2) as a statement-block which is one or more simple statements enclosed within brackets {}.
Your first case runs fine because the if statement without brackets considers the next single statement(for loop)as a part of its body to be executed. The body of the for loop is a part of the loop itself.
If there had been no brackets for the loop itself, then only the first statement of the loop would have been executed.
{} defines a compound statement or block.
With the introduction of control structures we are going to have to
introduce a new concept: the compound-statement or block. A block is a
group of statements which are separated by semicolons (;) like all C++
statements, but grouped together in a block enclosed in braces: { }:
From cplusplus.com: Control Structures
The if control structure is defined as follows:
if (condition) statement
That statement can be defined as a single instruction/statement, or a compound statement. Either way, it's the next statement to be executed.
for (;;) statement is a special type of control structure called an iteration structure.
Therefore,
//The control structure is going to apply to the next statement
if (condition)
for (;;) //This for loop is the next statement. It applies to the next statement.
{
//The next statement is a compound statement.
}
Yes if there are no brackets after the if-statement it will just process the next line if the conditions are true. Since the next line was a for statement, it treats it as one command.

How do I improve handling of if/else local variables?

I commonly have code where I want to detect some condition, and if it exists, then process that condition.
The test for the condition extracts certain information that is important to the processing half of the problem.
However, if/else constructs fail to allow one to declare local-to-the-if variables in the if construct itself(1). Hence, I have to put variable declarations before the beginning of the entire if/else chain for all of the various conditions for which information may be extracted.
For example:
else if ((EndsWithToken("d") || EndsWithToken("dsh")) &&
(p1 = find(m_input_line, '[')) &&
(p2 = find(m_input_line, ']')) &&
p2 > p1)
{
// process what we found inside of the [ ] brackets using p1 and p2...
}
This snippet is part of a long chain of if/else's, and the others don't need p1 and p2 - but they might need an integer value that was extracted from the input stream, or a double, or two points, or whatever....
The point is, there is no way that I know of introduce const TCHAR * p1 and p2 locally to the above scope, the only place it is used, that still allows for the overall structure to remain the same.
Is there some C++ language feature or a pattern that might allow for this?
(1) As some have pointed out, it is possible to declare a single variable of fundamental type, if it is the fist thing, and to test it against non-zero only. This is far too limited to be of much use as a general solution to this issue (though the occasional moment could come up where it is useful - but truly rare).
One solution would be to make each case a distinct function, that returns whether or not it succeeded.
This gives you a natural well-localized scope for the variables, and hopefully (assuming) a reasonable compiler can inline them.
You are allowed to define local variables in if and while statements; however, you can only declare a single one per statement, and you can only test the value for non-zero:
...
else if (TCHAR *p1 = find(m_input_line, '['))
{
if (TCHAR *p2 = find(m_input_line, ']'))
{
...
}
}
In this case, you could also just declare TCHAR *p1, *p2; before the chain of if/else statements, I wouldn't see any problems with that.
Similar to unwind's answer: what about using inline functions for the body of the if/then/else?
However, I guess in both cases you might need to pass quite some values.
Extract into a function.
bool validate(const string& line){
auto startIndex = line.find('[');
auto endIndex = line.find(startIndex,']');
return startIndex != -1 && endIndex != -1 && endIndex > startIndex;
}
//....
else if( EndsWith({"d","dsh"}) && validate(m_input_line) ){ ...}
I notice the prefix "m_" so I am guessing this is part of some class. So make private helper functions as necessary to make the code cleaner and easier to understand.
That's not true. You can declare a variable to the scope of the if if you initialize it there.
if ( int i = 0 )
{
i = 1;
}
else
{
i = 2;
}
This is a dumbed-down example, but it's legal.

warning: uninitialized variable //But I have initialized ! C++ Compiler bug?

Iam trying to compile this program but i get warning and when i run vc++ 2010 debugger pops up : (
Here is my code :
#include <iostream>
using namespace std;
int num;
int min(int mas[])
{
int i,minn,index; /* But I have declared them : (((( */
for(i=0;i<num;i++)
{
if(mas[i]!=0)minn=mas[i];
break;
}
if(i==num) return 0;
for(i=0;i<num;i++)
if(mas[i]!=0 && minn>mas[i])
{
minn=mas[i];
index=i;
}
mas[index]=0;
return minn;
}
int main()
{
cin>>num;
int *array=new int[num]; int tmp;
tmp=min(array);
}
and Here is a compiler log :
prog.cpp: In function ‘int min(int*)’:
prog.cpp:6: warning: ‘index’ may be used uninitialized in this function
prog.cpp:6: warning: ‘minn’ may be used uninitialized in this function
What i am doing wrong ? or its is compiler bug ? :)
Thank you :)
You have declared them, but not initialized them. Simply write int minn = 0, index = 0; to avoid the warning. If you don't initialize a variable, its default value is whatever was at that location in memory already; usually garbage.
The thing is, if num is negative, then neither of the for loops in your min() function will execute, and so minn and index will not have been assigned values. The if(i == num) test also won't break out of the function and prevent this from happening. So the last two lines of the function will have completely undefined results.
Sometimes there really isn't a path for the variables to be used uninitialized, though; sometimes the compiler just isn't quite smart enough to figure out all the subtleties. Just give them an initial value to avoid the warning.
Declaration != initialization. When you declare them the variables have random values. Just initialize them to sensible values like -1 for index and minn to a INT_MAX.
But you haven't initialized them : ))))
EX: int i,minn=0,index=0; Imagine that you pass num that equals 0, at the end you would be returning uninitialized value of minn and just before that you would set mas[unknown_number]=0; which will probably cause your app to crash since you will be referencing memory that is most likely beyond your scope. You should do a check in the beggining like if(num<1)return -1;
Suppose the entire array you pass in is 0. Both loops short-circuit and never execute, both minn and index are uninitialized.
Now if this happens, what should be happening? Set the variables to the values that accomplish just that.
As you say in your comment, yes, you have declared your variables, but you haven't initialized them. Initializing a variable means giving it a value. So in this case, you have told the compiler that you want to create three integers, but you haven't told it what values you want to store in those integers. That would be ok if, for every possible path through your function, index and minn were guaranteed to be given a value, but the problem here is that there is a path through your function where minn and index will never be initialized. First of all, here:
for(i=0;i<num;i++)
{
if(mas[i]!=0)minn=mas[i];
break;
}
If you have an array of zeros, then minn is never initialized to a value.
Then further down:
for(i=0;i<num;i++)
if(mas[i]!=0 && minn>mas[i])
{
minn=mas[i];
index=i;
}
first of all, if you had an array of zeros, well what is the value in minn? There is no value. You are asking the compiler to compare mas[i] to a number which doesn't exist. Furthermore, what if mas[i] is always equal to zero? Well now you don't initialize minn or index. Yet at the end of the function, you are attempting to use the value of index to get an integer from the array amd then you return minn (which still equals nothing).
That's the problem you're getting from the compiler. It can see this potential outcome and is warning you that your function can be broken due to these integers never getting a value. To fix it, do what the other lads have suggested and let index and minn equal zero at the start.

execution order of loops in C

this is probably a very noob question but I was what the result of this would be:
int someVariable = 1;
while (callFunction(someVariable));
if (someVariable = 1) {
printf("a1");
} else {
printf("a2");
}
callFunction (int i) {
while (i< 100000000) {
i++;
}
return 0;
}
so when you hit the while loop
while (callFunction(someVariable));
does a thread wait at that loop until it finishes and then to
if(someVariable == 1) {
printf("a1");
} else {
printf("a2");
}
or does it skip and move to the if condition, print "a2" and then after the loop has finished goes through the if condition again?
UPDATE: This isn't ment to be valid c code just psuedo, maybe I didn't word it right, basically what I'm trying to figure out is what the different between a loop like while (callFunction(someVariable)); is vs
while (callFunction(someVariable)){}
i also changed the bolded part in my code i.e ** int someVariable = 1; **, I was doing an endless loop which wasn't my intention.
The code inside a function is executed sequentially, by a single thread. Even if you send an other thread to your function it will execute it sequentually as well.
This is true to 99% of programming languages now days.
UPDATE
basically what I'm trying to figure out is what the different between a loop like while (callFunction(someVariable)); is vs while (callFunction(someVariable)){}
No practical difference. ; delimits an empty statement, { } is a scope without statements. Any compiler can be expected to produce identical code.
Of course, if you want to do something in each iteration of the loop, { } creates a "scope" in which you can create types, typedefs and variables as well as call functions: on reaching the '}' or having an uncaught exception, the local content is cleaned up - with destructors called and any identifiers/symbols use forgotten as the compiler continues....
ORIGINAL ANSWER
This...
callFunction(int i){
while (i< 100000000){
i++;
}
return 1;
}
...just wastes a lot of CPU time, if the compiler's optimiser doesn't remove the loop on the basis that it does no externally-visible work - i.e. that there are no side-effects of the loop on the state of anything other that "i" and that that's irrelevant because the function returns without using i again. If always returns "1", which means the calling code...
while (callFunction(someVariable));
...is equivalent to...
while (1)
;
...which simply loops forever.
Consequently, the rest of the program - after this while loop - is never executed.
It's very hard to guess what you were really trying to do.
To get better at programming yourself - understanding the behaviour of your code - you should probably do one or both of:
insert output statements into your program so you can see how the value of variables is changing as the program executes, and whether it's exiting loops
use a debugger to do the same
Your code contains an endless loop before any output:
while (callFunction(someVariable));
Did you mean for the ; to be there (an empty loop), or did you
mean something else? Not that it matters: callFunction
always returns 1, which is converted into true. (If you
really want the loop to be empty, at least put the ; on
a separate line where it can be seen.)
If you do get beyond the while (because you modify some code
somewhere), the if contains an embedded assignment; it's
basically the same as:
if ( (someVariable = 1) != 0 )
Which is, of course, always true. (Most C++ compilers should
warn about the embedded assignment or the fact that the if
always evaluates to true. Or both.)
If your loop completes (it would be sequentially yes, if you fix it), it will print 'a1', since you're doing an assignment in the if, which will always return 1, which evaluates to 'true' for conditionals.