Trouble with Continue and Break statements

Pages: 12
Hello there, I am having trouble with some continue and break statements. I just want to understand these examples the book gave us and make sure I got the concept down. For the first piece of code, it's breaking inside the inner loop. This means that if (star == 10) it will be 10, in other words it will be 10 no matter what, because we used the "break" statement correct? I am just having a bit of trouble with the concept of "break" statements and was wondering if someone could give me further examples on these types of break statements. Even though the book does not recommend me to use break or continue statements, I just want to get to know them better.

Also another question I have with the first piece of code is why the "cout << endl;" is there? It reads from top to bottom, so why is the cout << endl; there. Shouldn't it be in the first loop on the top? I included comments on what I mean here.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <fstream>
#include <cmath>
#include <iomanip>
using namespace std;

int main()
{
	for (int row = 0; row < 5; row++)
	{
		// cout << endl; // Shouldn't this go here?
		for (int star = 0; star < 20; star++)
		{
			cout << "*";
			if (star == 10)
				break;
		}
		cout << endl; // I thought the code reads from top to bottom, why does this go here? The cout << endl; is being repeated 5 times but it comes after the inner loop. Shouldn't it go on top?
	}

	return 0;
}


For the second piece of example they gave us, I was also confused on this also. I am having mainly trouble on continue statements and was wondering if you could also give me additional examples on what continue statements actually do. For this specific program example, I have no idea what the continue statement does here. Does it actually skip the block of statements it's in? I included comments of what I am talking about. Thanks so much.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <iostream>
#include <fstream>
#include <cmath>
#include <iomanip>
using namespace std;

int main()
{
	int dvdCount = 1;
	int numDVDs;
	double total = 0.0;
	char current;

	// Get the number of DVDs.
	cout << "How many DVDs are being rented? ";
	cin >> numDVDs;

	do
	{
		if ((dvdCount % 3) == 0) // Does the continue statement actually skip all this?
		{
			cout << "DVD #" << dvdCount << " is free!\n";
			continue; // Immediately starts the next iteration
		} // Through this?

		cout << "Is DVD #" << dvdCount;
		cout << " a current release? (Y/N) ";
		cin >> current;
		if (current == 'Y' || current == 'y')
			total += 3.50;
		else
			total += 2.50;
	} while (dvdCount++ < numDVDs);

	cout << fixed << showpoint << setprecision(2);
	cout << "The total is $" << total << endl;

	return 0;
}
Last edited on
closed account (48T7M4Gy)
In the first sample:
break causes the program to jump outside the loop when star = 10. However outside the loop printing star causes an out of scope error. star no longer exists.

If you declare star outside the for loop, let the loop run, let the break occur, then print it out, it will have the value 10.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <fstream>
#include <cmath>
#include <iomanip>
using namespace std;

int main()
{
	for (int row = 0; row < 5; row++)
	{
		cout << endl; // Shouldn't this go here?
		int star = 0;
		for (star = 0; star < 20; star++)
		{
			cout << "*";
			if (star == 10)
				break;
		}
		cout << "Star =" << star << endl;
		
	}

	return 0;
}


Place the endl's where you need them depending on what output you want. There is no special or magical best or worst place.

See http://en.cppreference.com/w/cpp/language/break
Last edited on
closed account (48T7M4Gy)
Opinions will vary but continue isn't used as much as break.
http://en.cppreference.com/w/cpp/language/continue
Let's start with what they do. It's actually pretty simple. This:
1
2
3
4
5
for(init; test; increment) {
    statements;
    break;
    statements;
}

is equivalent to:
1
2
3
4
5
6
for(init; test; increment) {
    statements
    goto 1;
    statements;
}
1:

In other words, control transfers to the statement immediately after the for statement.

And this:
1
2
3
4
5
for(init; test; increment) {
    statements
    continue;
    statements;
}

is equivalent to:
1
2
3
4
5
6
for(init; test; increment) {
    statements
    goto 1;
    statements;
1:
}

In other words, control transfers to the bottom of the loop. What this means is that the increment statement in the for executes, followed by the test.

The break example in your post shows how it works, but you'd never use it that way. Obviously you'd have the loop run from 0 to 10.

You use break when a condition to exit the loop is best tested in the middle of the loop. Continue is handy when you decide that there's no need to continue processing the current loop iteration.

the book does not recommend me to use break or continue statements

I've been programming professionally for decades. In that time I've seen many cases where spaghetti code could be easy untangled by using a break or continue statement. I've never seen a case where the use of break or continue made the code harder to understand.
> Even though the book does not recommend me to use break or continue statements,
> I just want to get to know them better.

Yes, it is a sound recommendation; still you would want to get to know them.

The language does offer four jump statements (statements that perform unconditional transfer of control to some other part of the code): return, goto, continue and break.

return is the only jump statement that allows unrestricted transfer of control; with the other three, the jump is limited to some place within the same function. This is fine; a function is a unit of encapsulation, which can (and usually should be) be looked at in isolation.

The problem with the other three jump statements - goto, continue and break - is that they break the linear flow of program logic (note that the jump is unconditional). break is usually used in switch statements and goto is sometimes used when we want to break out of the outermost loop when loops are nested.

We would still want to get to know them well, because there are situations when the use of one of these jump statements can make the code more readable. Even if, in many more cases, needless, indiscriminate use of goto, continue or break would make the code less readable.
Does throw count as a jump too?
closed account (48T7M4Gy)
https://stackoverflow.com/questions/9549493/throw-exception-and-return-result-from-a-function
https://msdn.microsoft.com/en-us/library/hh279678.aspx
Last edited on
A throw-expression, if evaluated, does unconditionally transfer control to the nearest handler with a matching type; however, it is not a jump statement or even a statement.
For example: return arg>16 ? throw std::invalid_argument("value of arg is too high") : factorial(arg) ;

Though I suppose we could consider an expression-statement where the discarded-value expression is a throw-expression as a kind of jump (after-stack-unwind) statement, somewhat akin to the the jump statement return.
Ok, I am trying to get the format about the first one I made. I understand the break statements now, but just a logic confusion I am stuck on here. I always thought the outer loop tests out first, so is the "cout << "g" << endl;" going out first? Or not? Is it going after the inner loop is executed? I decided to put g there because "endl;" is actually breaking up the stars into the parts here. I am confused on why this happens.

I understand that the stars in the inner loops are getting repeated 10 times * 5 because of the outer loop. I am confused because I know the "cout << endl" is supposed to repeat 5 times, I just am confused on how these two things are connected, because I read that the outer loop goes first?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <fstream>
#include <cmath>
#include <iomanip>
using namespace std;

int main()
{
	for (int row = 0; row < 5; row++)
	{
		for (int star = 0; star < 20; star++)
		{
			cout << "*";
		}

		cout << "g" << endl; // How does this line break up the stars into 5 sections? Doesn't it read from top to bottom?
	}

	return 0;
}


Comparing to this, where the "cout << "g" << endl;" is on top of it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <fstream>
#include <cmath>
#include <iomanip>
using namespace std;

int main()
{
	for (int row = 0; row < 5; row++)
	{
		cout << "g" << endl; // How does this line break up the stars into 5 sections? Doesn't it read from top to bottom?
		for (int star = 0; star < 20; star++)
		{
			cout << "*";
		}
	}

	return 0;
}


I am going to continue to work on the "continue" statements also because I am a bit confused on this still and will post on here soon in regards to that. Thanks for the help so far!



Your
1
2
3
4
for (int star = 0; star < 20; star++)
{
  cout << "*";
}

produces the same as
cout << "********************";

You do thus ask the difference of these:
1
2
3
4
5
6
7
8
9
10
11
12
13
// A
for (int row = 0; row < 5; row++)
{
  cout << "********************";
  cout << "g" << endl;
}

// B
for (int row = 0; row < 5; row++)
{
  cout << "g" << endl;
  cout << "********************";
}

********************g
********************g
********************g
********************g
********************g
g
********************g
********************g
********************g
********************g
********************


I'm not sure, what "going out first" means.
What I mean is that I don't understand why the star break up into 5 sections. I know it has something to do with the cout << endl; but I just don't understand the logic behind it. The outer loops executed first, correct? Then the inner loop? Or does it all execute at the same time hence that is the reason the cout << endl; breaks up the stars?

I understand loops in general and nested loops, but that specific part I am confused on. I decided to do further tests on it actually because this should be really simple, but I am just over thinking it for some reason.. Anyways here it what I have so far:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <fstream>
#include <cmath>
#include <iomanip>
using namespace std;

int main()
{
	for (int row = 0; row < 5; row++)
	{
		 // How does this line break up the stars into 5 sections? Doesn't it read from top to bottom?
		for (int star = 0; star < 20; star++)
		{
			cout << "*";
		}
		cout << "g";
	}

	return 0;
}


As you can see, the "g" is going between the 20 starts. I understand why the "20" stars here are being repeated 100 times, because the 20 starts gets executed 100 times because of the outer loop (5 * 20), I understand this. I understand the "g" gets executed 5 times because it's in the outer loop. I don't understand why the g goes between the 20 set of stars. Thanks.

closed account (48T7M4Gy)
The program enters the first loop which in turn enters the inner loop. Once the inner loop ends control goes back to the outer loop which then proceeds to the inner loop and so it goes on until the outer loop is completed.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <iostream>

using namespace std;

int main()
{
    // A
    for (int col = 0; col < 5; col++)
    {
        cout << 'a';
    }
    cout << "That's A done." << endl;
    
    // B
    for (int row = 0; row < 5; row++)
    {
        cout << 'b' << endl;
    }
    cout << "That's B done." << endl;
    
    // C
    for (int row = 0; row < 20; row++)
    {
        cout << '*';
    }
    cout << "That's C done." << endl;
    
    // B{ (C) }
    for (int row = 0; row < 5; row++)
    {
        cout << 'b' << endl;
        
        {
            for (int row = 0; row < 20; row++)
            {
                cout << '*';
            }
            cout << "That's C done." << endl;
        }
        
    }
    cout << "That's B done." << endl;
    
    cout << "That's B{ (C) } done." << endl;
    
    return 0;
}

aaaaaThat's A done.
b
b
b
b
b
That's B done.
********************That's C done.
b
********************That's C done.
b
********************That's C done.
b
********************That's C done.
b
********************That's C done.
b
********************That's C done.
That's B done.
That's B{ (C) } done.
Program ended with exit code: 0

I understand loops in general and nested loops

I'm not sure you do.

The outer loops executed first, correct? Then the inner loop?

No. That would be the same as:

1
2
3
4
5
6
7
8
9
10
11
	for (int row = 0; row < 5; row++)
	{
		 // How does this line break up the stars into 5 sections? Doesn't it read from top to bottom?
		cout << "g";
	}


	for (int star = 0; star < 20; star++)
	{
		cout << "*";
	}


If we look at your code:

9
10
11
12
13
14
15
16
17
	for (int row = 0; row < 5; row++)
	{
		 // How does this line break up the stars into 5 sections? Doesn't it read from top to bottom?
		for (int star = 0; star < 20; star++)
		{
			cout << "*";
		}
		cout << "g";
	}

The outer loop iterates 5 times. That means the entire block from lines 11 - 16 runs 5 times.

So, on the first iteration, all that stuff runs once. Your inner loop outputs 20 stars, and then line 16 prints a 'g'.

Then, on the second iteration, all that stuff runs again. Your inner loop outputs another 20 stars, and then line 16 prints another 'g'.

On the 3rd iteration, another 20 starts and another 'g.

Again on the 4th.

Again on the 5th.

Is that clear now?
Last edited on
Another angle:

these statements (not including return, which is necessary for many functions) are going to interrupt your CPU(s) pipeline(s). One way that the hardware gets high performance is to assume it knows what the next statements in the code will be (machine language statements) and it queues them up. If you do an unconditional jump (which is a bit of a misnomer, most of these are tied to an if statement block) behind a conditon, the hardware can have trouble guessing the next statements and has to restart the pipeline, which costs a number of cpu cycles every time it happens. It depends on the code whether this happens and whether it matters (doing it once to handle an error is one thing, doing it frequently as part of "normal" logic can be a problem).

If the statement happens every time, the compiler or (cpu?) may be smart enough to manage the jump to as the next pipeline statement without problems. Not sure how smart it may be about this, I have not played with it as these statements are unusual outside of error handling.
Last edited on
these statements (not including return, which is necessary for many functions) are going to interrupt your CPU(s) pipeline(s).

I believe that most modern CPUs do speculative execution so that the pipeline stays full.

A really cool trick in the ARM processor (the one in most cell phones), is that every instruction is conditional and will only execute if a specified set of CPU flags are set. So if there's a small amount of code inside and if statement, the code might have NO branch, and simply set the flags so the instructions only execute when the if condition is true.
They can only speculate up to a point though. If there are more paths in the code than the potential paths buffers in the cpu, sometimes it breaks the pipe, and these statements add +2 paths (jump or no jump) straight up every time.

There are a lot of ifs to meet before its a problem, for sure. Depends on target cpu family, how cpu intense the code is around the jump, what else is going on in the code in that area, and more.

As I said, I haven't studied it though. Its a potential gotcha, under the right circumstances. I do know that the branch prediction and pipelines were amazing when it came out... code that had unrolled loops or forced inline functions became obsolete overnight nearly.


First of all, just would like to thank you for the help and your right @MikeyBoy, I do need more practice with them. I got it now thanks to your explanation however, so thanks for that.

I have an additional problem with break and continue statements, but I would like to start with break here. I kind of got a sense on what they do, but would like an explanation that if a break statement here is actually needed here? In other words, can this program be done without needed a break statement? I know I need to get a handle on using these statements in general but just out of curiosity if it's possible to use it without that.

The program problem states: The program asks the user
for a number and then displays the value of that number raised to the powers of 0 through
10. The user can stop the loop at any time by entering Q.

Thanks again!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <cmath>
using namespace std;

int main()
{
	double value;
	char choice;

	cout << "Enter a number: ";
	cin >> value;
	cout << "This program will raise " << value << " to the power of 0 through 10.\n";

	for (int count = 0; count <= 10; count++)
	{
		cout << value << " raised to the power of " << count << " is " << pow(value, count) << endl;
		cout << "Enter Q to quit or any other key ";
		cin >> choice;
		if (choice == 'Q' || choice == 'q')
			break; // Any other way of removing the break statement and using something else?
	}

	return 0;
}

Your line 19 has a condition. What is evaluated next, if that condition is false?

The condition on line 14.

You can combine multiple tests into one expression. You can test on line 14 both whether the user wants to do an additional iteration and whether count is still valid.
You're welcome :)

can this program be done without needed a break statement?

Yes, it can. You could instead use a boolean flag, and check for the value of that flag in the loop condition, to control whether or not the loop continues iterating. If the user enters 'Q', change the value of the flag, so that the loop condition is no longer true, and the loop stops iterating.

Last edited on
closed account (48T7M4Gy)
And along those lines the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>
#include <cmath>

using namespace std;

int main()
{
    double value;
    char choice;
    
    cout << "Enter a number: ";
    cin >> value;
    cout
    << "This program will raise " << value
    << " to the power of 0 through 10.\n";
    
    for (
         int count = 0;
         
         count <= 10 &&
         (cout << "Enter Q to quit or any other key ") &&
         (cin >> choice) &&
         toupper(choice) != 'Q';
         
         count++
         )
    {
        cout
        << value << " raised to the power of "
        << count << " is " << pow(value, count) << endl;
    }
    
    cout << "Finished\n";
    
    return 0;
}
Last edited on
Pages: 12