Multiple if statements in C++ - c++

I'm doing the first project euler problem and I just did this
#include <iostream>
using namespace std;
int main(){
int threes =0;
int fives = 0;
int both = 0;
for (int i = 0; i < 10; i++){
if(i%3==0){
threes += i;
}
if(i%5==0){
fives += i;
}
if ( i % 5 == 0 && i % 3 == 0){
both += i;
}
}
cout << "threes = " << threes << endl;
cout << "fives = " << fives << endl;
cout << "both = " << both << endl;
cout << " threes + fives - both = " << endl;
int result = (threes + fives) - both;
cout << result<< endl;
return 0;
}
My professor recently corrected me for doing this in a different problem saying something about else statements,
but I don't understand WHY i have to add else in front of the next if. for what its worth I have another version with else if(i%5){ fives += .... }
and they both work and get me the right answer.
My question is whats inherently wrong with this way of thinking, is it stylistic or am I not thinking logically about something?
If it works, why use switch statements ever?

The only thing that I see wrong with your implementation is that in the case where the number is both a multiple of 3 and a multiple of 5 not only is the both variable incremented but the fives and threes variables are also incremented. Based on what the professor described I believe he wants you to use an else-if so that the both variable is the only one that is incremented when you pass in a number that is both a multiple of 3 and a multiple of 5.
The reason you get the correct answer both ways is because you are only going to 10 in the for loop, if you increase it to i <= 15 you will get fives and threes being 1 higher than I think he intended.
For example:
for( int i = 0; i < 10; i++ )
{
if( ( ( i % 3 ) == 0 ) && ( ( i % 5 ) == 0 ) )
{
both++;
}
else if( ( i % 3 ) == 0 )
{
threes++;
}
else if( ( i % 5 ) == 0 )
{
fives++;
}
}

The else branch in an if-else statement is only executed if the if branch is false. If you just have two if statements in a row, they'll both be executed, which can be a waste. In the below code, the else prevents the second computation from running if the first is satisfied.
if (expensive_computation1()) {
...
}
else if (expensive_computation2()) {
...
}
Additionally, it's clearer to humans reading the code whether both if statements should be allowed to run or whether only one should.

In this case, maybe you really want this:
if (i % 5 == 0 && i % 3 == 0) {
both += i;
} else if (i % 3 == 0) {
threes += i;
} else if (i % 5 == 0) {
fives += i;
}
(why you do += i instead of ++ I don't know but you didn't explain, so I just copied it)
In your code, threes and fives were incremented even if it would also increase both, which depending on your problem may not be what you want. If you do the if/else way I've just presented, only one of the three variables is increased.

Why use if-else instead of multiple if's?
if-else & if would achieve the same results but if-else achieves them in a performance enhanced way. with multiple if's every if condition will have to be checked. With if-else only one conditional check will have to be performed and the rest of the conditions just don't need to be checked at all.
This would not affect a small program like the one you have but it will sure have some impact in potentially expensive function being called repeatedly over and over again.
If it works, why use switch statements ever?
With nested if-else conditions the code is hard to read and understand. The switch-case construct helps to represent the conditions in a much easier to read & understand format.

To me it looks like stylistics. You can use some autoreformating tool that follows certain established stylistic look (K&R, ANSI, GNU, etc.)
For example astyle is such tool, http://astyle.sourceforge.net/ - just reformat your code with it, and you might have a happy professor.

Related

C++: stopping last increment in my Fizz Buzz program

So as part of a coding challenge I tried to make a Fizz Buzz program in C++ without looking at the solution. For those of you who don't know, it should be a loop that replaces any number divisible by 3 with Fizz, any number divisible by 5 with Buzz, and any number divisible by both with FizzBuzz:
1
2
Fizz
4
Buzz
6
7
8
Fizz
Buzz
11
Fizz
I'm almost there with the code below, however, i'm a little annoyed that even though I want the loop to stop entirely at 100, the way i've set up the program means that an extra 1 gets added to i after the loop has ended. Is there a way of stopping my FizzBuzz program from going past 100?
#include <iostream>
using namespace std;
int main () {
for (int i = 1; i < 100; ++i){
if (i % 3 == 0 && i % 5 == 0){
cout << "FizzBuzz\n";
i = i + 1;
}
if (i % 3 == 0){
cout << "Fizz\n";
i = i + 1;
}
if (i % 5 == 0){
cout << "Buzz\n";
i = i + 1;
}
cout << i << "\n";
}
}
So I fixed your code a little bit:
int main()
{
for (int i = 1; i < 101; ++i)
{
if (i % 3 == 0 && i % 5 == 0)
cout << "FizzBuzz\n";
else if (i % 3 == 0)
cout << "Fizz\n";
else if (i % 5 == 0)
cout << "Buzz\n";
else
cout << i << "\n";
}
}
Every time you do i = i + 1;, it's kinda useless because your loop does that. Also, I put everything is an if else chain, instead of and if if chain. That way only on statement will execute at any giving time. Also changed the max to 101 instead of 100 since the for loop will stop at 101 and not print the result of 101.
Hope this helps :)
In c++, variables have a lifetime, called their scope, and after their lifetime expires they are deleted. The i that is defined in the loop declaration has the scope constrained by the closing brace "}" of the for loop. Due to this, the variable i does not exist after the loop, only during. However in the code you have provided, the problem is that you are incrementing i multiple times. In your for loop you increment i every time the body of the for loop is executed, but within that body you increment i when it is divisible by 5 or 3 or both or neither. You can remove all of the i = i + 1; statements and remove most of the bugs.

Why does this basic while loop written in c++ not work?

I am attempting to learn C++ by tackling the Project Euler challanges. I am currently stuck on the first project where my while loop does not work. I have looked at it for over half an hour now but just can't see any issues with it, even though it's incredibly basic.
#include <iostream>
int main() {
int sum_3 = 0;
int i = 1;
while ( sum_3 < 1000 ) {
sum_3 = sum_3 + (i * 3);
i++;
return sum_3, i;
}
std::cout << sum_3 << std::endl;
return 0;
}
I am trying to sum every number which is a multiple of 3 but smaller than 1000. I have re-written the program, entered print statements to try and troubleshoot it, but I'm just going around in circles now.
The return keyword leaves the current function, not just the current scope.
return sum_3, i;
doesn't do what you think it does, either. You can only return a single object. The reason the line compiles is that C++ has a , operator which evaluates the expression on the left, discards the result, and then evaluates the expression on the right. So
return sum_3, i;
simply returns i.
Because the loop is in main, returning also ends the program.
Your code should probably just look like this:
while ( sum_3 < 1000 ) {
sum_3 = sum_3 + (i * 3);
i++;
}
You should not return unless you want to get off your function, in this case is the main function.
#include <iostream>
int main() {
int sum_3 = 0;
int i = 1;
while ( sum_3 < 1000 ) {// I'd use a 'for' here, if I were you
sum_3 += (i * 3); //is the same for sum_3 = sum_3 + (i * 3);
i++;
}
std::cout << sum_3 << std::endl;
return 0;
}
What needs to be smaller than 1000? The total or the individual multiples of 3?
If what you want is the total to not exceed 1000, then just remove the line "return sum_3, i" and you're good to go.
If what you wanted was to sum all multiples of 3 that are also smaller than 1000 (but the total can exceed 1000) then you need to also change the while condition to "(i*3)<1000" instead of "sum_3<1000".

C/C++ Macro for breaking or continuing

I am trying to code a simple macro which based on a condition either calls break or continue in the loop in which it is called. Below is the code:
#include <iostream>
#define BC_IF_EVEN(BC) if(i % 2 == 0) BC
using namespace std;
int main() {
int i = 0;
while(i++ < 30) {
if(i < 15)
BC_IF_EVEN(continue);
else
BC_IF_EVEN(break);
cout << i << " ";
}
cout << endl;
}
The output that I am looking for is: 1 3 5 7 9 11 13 15, but the above code outputs: 1 3 5 7 9 11 13 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 because the else condition in main() gets applied to the if condition in the BC_IF_EVEN macro.
A simple fix is to put scope braces for the if condition in main(), but I do not want to enforce that because the user should be allowed to code in regular way.
N.B. I cannot put a do { .. } while(false) loop in the macro (which is a standard trick to allow semicolons after macro calls in conditionals because the break and continue sent via BC get applied to this inner loop.
Is there an easy way to get the required output without modifying the main() function?
#define BC_IF_EVEN(BC) if (i % 2 != 0); else BC
but really WHY?
Don't invent obscure macros in an attempt to justify your obscure loops. Frequent use of continue and break inside loops is a certain sign of poor program design.
Here's how to fix the program:
When the amount of items you iterate through is known in advance, use a for loop, as they are usually easier to read and harder to mess up.
Since you check if a number is even no matter in which way the program branches, might as well move that check outside the if-else.
for(int i=0; i<30; i++)
{
if(i%2 == 0) // even
{
if(i < 15)
continue;
else
break;
}
cout << i << " ";
}
Now look at the conditions and what the program actually does. This doesn't make sense at all. All it does is to print the odd numbers between 0 and 14 in a very obscure way. Instead, you probably wanted a program which prints the odd numbers between 0 and 15.
Apply common sense: Loop from 0 to 15. Check each number to see if it is odd. If so, print it. Otherwise ignore it.
for(int i=0; i<=15; i++)
{
if(i%2 != 0)
cout << i << " ";
}
Alternatively, don't bother with even numbers at all:
for(int i=1; i<=15; i+=2)
{
cout << i << " ";
}
This is why functions were created, just create a function to check if it is even or odd and return a true if even and false if odd. Macros are ugly when you can do it simply another way. Please for the love all legacy maintainers make readable code.
eg:
// Example program
#include <iostream>
using namespace std;
bool checkeven(int i)
{
if( i % 2 != 0)
return false;
else
return true;
}
int main()
{
for(int i = 0; i < 30; i++) //while(i++ < 30) is readable, but I think this is even easier
{
if(i < 15)
{
if(checkeven(i))
continue;
}
else
{
if(checkeven(i))
break;
}
cout << i << " ";
}
}
Use curly brackets even if you have the only line in if/else statement. In this case you'll fully control the workflow.
The other advantage of this approach is that if you need to comment out the line in if/else statement you'll just put // in the start of the line.
// wrong workflow
if ( expr )
// commented out for debug issues
//do_when_expr();
do_whatever();
// right workflow
if ( expr )
{
// commented out for debug issues
//do_when_expr();
}
do_whatever();
In your case it would be:
#define BC_IF_EVEN( BC ) if (i % 2 == 0) { BC; }
...
if(i < 15)
{
BC_IF_EVEN(continue)
}
else
{
BC_IF_EVEN(break);
}
Try this
#define BC_IF_EVEN(BC) ( { if(i % 2 == 0) BC; } )
You just need an extra pair of curly braces to restrict the scope for your inner if block. Following should work:
#define BC_IF_EVEN(BC) {if(i % 2 == 0) BC;}
Also do not use ';' while using macro:
if(i < 15)
BC_IF_EVEN(continue) //No semicolon
Or if you want use semicolon for code consistency then an extra pair of braces has to be put:
#define BC_IF_EVEN(BC) ({if(i % 2 == 0) BC;})

If we list all the natural numbers below 10 that [C++]

The code that I did was for solving the following problem. However, the logic of the code is wrong and I as a good newbie cannot figure what is wrong.
After I compile the result of 'sum' is always 0, if I change the initialization of 'sum' for a whatever number, that whatever number is what appear as answer of 'sum'.
If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
Find the sum of all the multiples of 3 or 5 below 1000.
#include <iostream>
using std::cout;
using std::endl;
int main()
{
long sum = 0;
for( long i; i < 1000; ++i )
{
if (( i % 3 == 0 ) || ( i % 5 == 0 ))
{
sum = sum + i;
}
}
cout << "The sum is: " << sum << endl;
return 0;
}
You need to initialize i in your loop:
for (long i = 0; i < 1000; ++i )
As it is, i is probably some random number greater than 0 at the top of the loop, and the result is that the loop is never executed.
You need to initialize i to zero otherwise i's value will be whatever happens to be in memory. In this case it's > 1000.
for (long i = 0; i < 1000; ++i)
Also, a nice trick I learned. Use ii as your index variable. It's much easier to find ii than just i in your code.
You forgot to set i=O in your loop so the loop won't iterate.
All answers above are correct - you need to set your i to 0. What you might be interested in is that accessing uninitialized variable is an "undefined behaviour" (UB) and modern compilers are actually pretty good in finding the UBs and using them to optimize the code. For example, GCC 5.2 with -O2 (optimizations enabled) will generate same assembly for your code and for one without the loop at all regardless of what might happen to be in the memory at the address of i.
Try putting this code to (which is your code with additional #if for convenience) this online disassembler
#include <iostream>
using std::cout;
using std::endl;
int main()
{
long sum = 0;
#if 1
for (long i; i < 1000; ++i)
{
if ((i % 3 == 0) || (i % 5 == 0))
{
sum = sum + i;
}
}
#endif
cout << "The sum is: " << sum << endl;
return 0;
}
add the -O2 flag to compiler options on top right and try changing #if 1 to #if 0 and observe that the disassembly is the same meaning that the compiler cut out the loop completely.

value in an array doesn't seem to be incremented after a for loop c++

I know for a fact that the if statement if ( (roll == i) && (result == true) ) is true many times during the 2500 iterations but when I output winRolls[1] or any other index of winRolls after the higher level for loop completes its 2500 iterations, the value of winRolls[1] and every other index always has a maximum value of 1. Does this have something to do with a characteristic of c++ arrays or am I missing something else?
int winRolls[10]
for (int i = 0; i < 2500; i++)
{
for (int j = 1; j < 10; j++)
if ( (roll == j) && (result == true) )
{
winRolls[roll] = winRolls[roll] + 1;
}
}
cout << winRolls[1] << endl;
cout << winRolls[2] << endl;
cout << winRolls[3] << endl;
Your code has few problems.
winRolls size is [10] and you are accessing it based on i (instead of j, which has correct limit for winRolls). If roll == i is true for say 1000 then you are accessing out of array range. Which will not help you getting desired output as well as you enter an undefined behavior.
Where are you initializing winRolls? If you do not initialize but increment its contents anyway, you might end up with garbage values (values that are different in each run of the program). Also, how will roll == i be true many times during the 25000 iterations? Unless you are updating the value of roll (which I do not see in the code), this inner loop will execute either only once or maybe never depending on what value roll has.
Try cout << winRolls[roll] << endl; at the end.
You're incrementing the value in winRolls[roll] every time.
It looks like the code here is right. Your problem may lie elsewhere in your code.