How do I refactor duplicate control structures? - c++

I have duplicated control structures which are exactly the same, and the difference is how things happen inside. In particular, I don’t know how to deal with break, continue, and return. For example:
int f() {
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
if (isFoo(i, j)) {
// doSomethingF1
} else {
// doSomethingF2
}
}
}
}
int g() {
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
if (isFoo(i, j)) {
// doSomethingG1
} else {
// doSomethingG2
}
}
}
}
where doSomethings rely on i and j, and need to break or continue through the j loop, and return out of the function. How do I factor this out to get rid of the duplication?
I thought of writing a function that would take the doSomethings as arguments, but I'm not sure how to deal with the breaks, continues, or returns.
[I'm not fine with the duplication since there are some checks on i and j in f(), g(), and like four other functions that are exactly the same; the only difference is a few lines of code.]

If you really want/insist to have the same inner control in the loop context with break, continue, and return then the proposed solution is macros :-(.
On the other hand, if the doSomethingFG12 functions all have a defined interface, then compliment your generic control structure to handle the case with break, continue, and return to make a choice from there return values.

Related

What does third 'for' mean in #define for for(int z=0;z<2;++z)for

I have found a piece of code in a C++ program, it seems that it loops two times every for() loop in this program, but why does it need this third for in such preprocessor definition?
#define for for(int z=0;z<2;++z)for
It replaces for with for(int z=0;z<2;++z)for. Obviously, that would turn
for (int i = 0; i < N; ++i) {
// ...
}
into
for (int z=0;z<2;++z) for (int i = 0; i < N; ++i) {
// ...
}
Thus creating two nested loops. Without that extra for it would be
for (int z=0;z<2;++z) (int i = 0; i < N; ++i) {
// ...
}
Which is obviously incorrect.
Note that even though it's “correct” in the form you gave in your question, it doesn't mean it's a “good practice”. This is an example of excessive macro abuse and must be avoided. Here is one of the numerous examples how it could go wrong:
for (int z = 0; z < 5; ++z) {
for (int i = 0; i < 3; ++i) {
std::cout << z << std::endl; // this will never print 2, 3, 4
}
}
This will expand into
for (int z=0;z<2;++z) for (int z = 0; z < 5; ++z) {
for (int z=0;z<2;++z) for (int i = 0; i < 3; ++i) {
std::cout << z << std::endl; // this will never print 2, 3, 4
}
}
Meaning that you now have four nested loops, and that the inner loop will print the “invisible” z instead of the z you have declared in the outer loop (which becomes the second-level loop in the expanded code).
Another reason: as pointed by #stefan, it's a very bad idea to use keywords or other well-known identifiers as macro names. Makes one think of the infamous #define true false. And, as #HolyBlackCat mentions, it's also undefined behavior, meaning that as far as the standard is concerned, anything could happen. Ranging from the code “seemingly working” to a full-blown World War III with Martians (who invaded Earth to cleanse it from ugly code).
Firstly, that macro is the ugliest thing I've ever seen. I don't recommend ever doing something like this.
The top answer from Sergey Tachenov is really great, but it should also be mentioned that this macro really makes every for loop run twice. This means the doubly nested loops shown below will execute 400 times (not 200 times)! This might be unexpected.
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
// I'll be executed 100 times without the macro
}
}
becomes
for (int z=0;z<2;++z) for (int i = 0; i < 10; i++) {
for (int z=0;z<2;++z) for (int j = 0; j < 10; j++) {
// I'll be executed 400 times with the macro
}
}
It only gets worse from here. Consider an infinte loop like
int some_condition = 0;
for(;;) {
// insert logic here for calculating whether to break out
if (some_condition) {
some_condition = 0; // set back to false for use down the line
break;
}
}
turns into
int some_condition = 0;
for (int z=0;z<2;++z) for (;;) {
// insert logic here for calculating whether to break out
if (some_condition) {
some_condition = 0; // set back to false for use down the line
break; // gets me out of for(;;)...but the outer loop repeats
}
}
which bumps you out of the inner infinite loop if the condition is met....only to go right back in it. Now you might be stuck in an infinite loop.
Unexpected behavior is a good reason to avoid something, and macro shenanigans like this is very dangerous, and could be a real b**ch to debug. Imagine if some include directive had this ported in several header files deep...
Preprocessor substitution occurs in a single pass and does not support recursion. So the second "for" is probably for some zany idea of chaining existing "for" loops, prepending them with the macro "for" loop portion.
#define for for(int z=0;z<2;++z)for
Thus it replaces
for (int i = 0; i < N; ++i)
{
// ...
}
with
for(int z=0;z<2;++z)
for (int i = 0; i < N; ++i)
{
// ...
}
Which is a pretty crazy use of the preprocessor.

C++ Tetris: A function that deletes lines

I've been studying this tetris tutorial and I've come across the function that deletes lines and brings the row/s down one level. I'm kind of understanding what is going on with these functions, but some parts are confusing me. I'll try and explain it best I can, but here is the link to the lesson if you need it: http://javilop.com/gamedev/tetris-tutorial-in-c-platform-independent-focused-in-game-logic-for-beginners/
This, to me, looks like a function to get the array to start at the last number of a line:
void Board::DeleteLine (int pY)
{
// Moves all the upper lines one row down
for (int j = pY; j > 0; j--)
{
for (int i = 0; i < BOARD_WIDTH; i++)
{
mBoard[i][j] = mBoard[i][j-1];
}
}
}
Then, there is the function that is causing me problems, which I will explain:
void Board::DeletePossibleLines ()
{
for (int j = 0; j < 20; j++)
{
int i = 0;
while (i < 10)
{
if (mBoard[i][j] != 1) break;
i++;
}
if (i == 10) DeleteLine (j);
}
}
In case you're not familiar, the idea here is to delete a row that consists entirely of 1. But if (mBoard[i][j] != 1) break; would stop the loop if the first line wasn't 1. How would the loop reach a 1 that is somewhere in the middle of the mBoard[][] array if break stops it from doing anything possible straight away?
Am I missing something here? This is my interpretation of it. Perhaps somebody sees something I do't?
Edit:
Thanks for the replies, appreciated.
You could structure the code like this aswell:
for (int j = 0; j < 20; j++)
{
int i = 0;
while (i < 10)
{
if (mBoard[i][j] != 1)
{
break; //only breaks the while loop and will continue with if (i == 10)
}
else
{
i++;
}
}
if (i == 10)
{
DeleteLine (j);
}
}
Now you can clearly see, that the break; is only interrupting your while loop but not your for loop.
The break will jump out of the while loop. So if you encounter a line which has a non-1 somewhere in the middle, i will be the index in the line, and the for loop will continue with the next line (j), starting with i=0 again.
break only interrupts one loop, the while loop in your case. The for loop continues happily.
On a side note, this while could easily (and should) be refactored into a for, and can be compacted according to its recognizable for-if-break pattern :
for (int j = 0; j < 20; ++j)
{
int i;
for(i = 0; i < 10 && mBoard[i][j] == 1; ++i);
if (i == 10) DeleteLine (j);
}

How to stop a nested for loop

I want both loops to stop as soon as I find an object that has the same position in x.
Here is my C++ code:
for(int i = 0; i < sizeArray; ++i){
for(int j = i; j > 0; --j){
if (s[i].positionX == s[j-1].positionX){
s[i].positionY = s[j-1].positionY;
}
}
}
If I use break; it only breaks out of the inner for loop. What is the best way to stop both?
Options:
Set the indexes of the loops to max value (or min value) to terminate the loop.
Put all this inside a function and use return.
Use a goto
Use a Lambda
Set a boolean stop code to true, break, then listen for break and break out of other loop?
?
To break out of the innermost for loop, use break.
To break out of the outermost one, either use goto or use a combination of break and a "should stop" flag.
I would suggest lambda:
auto do_work = [&] {
for(int i = 0; i < sizeArray; ++i){
for(int j = i; j > 0; --j){
if (s[i].positionX == s[i-1].positionX){
s[i].positionY = s[i-1].positionY;
return;
}
}
}
};
do_work(); //you can call this multiple times if you need to!
No break, no goto. :-)
It serves the same purpose as break and goto in this case, but the technique seems to be clean, at least to me. Also, once you have the lambda with a name (a good name), you can use it multiple times if you need to — so this technique increases the code readability and encourages code-reuse.
Of course, if you don't need to call this multiple times, then probably you don't need a name. You just could do this:
[&]
{
//your code with the added return statement.
}();
But as I said, name increases readability even if you don't call it multiple times.
If you cannot use lambda for some reason, then you could still avoid using an extra variable such as stop and the extra work involving it (as #ssantos's answer suggested):
for(int i = 0; i < sizeArray; ++i){
for(int j = i; j > 0; --j){
if (s[i].positionX == s[i-1].positionX){
s[i].positionY = s[i-1].positionY;
i = sizeArray; //it will break the outer loop!
break;
}
}
}
Hope that helps.
I'm guessing you ask for stopping a for loop. The keyword you're looking for is break. However, if you want to exit both for loops, you'll need to add a variable to your code.-
bool stop = false;
for(int i = 0; i < sizeArray; ++i){
for(int j = i; j > 0; --j){
if (s[i].positionX == s[i-1].positionX){
s[i].positionY = s[i-1].positionY;
stop = true;
break;
}
}
if (stop) {
break;
}
}
Put the code you posted in its own function and return out of it after the assignment.
You can stop a for loop with break.
With nested for loops, things are not so easy. You can achieve your goal
either with setting a flag (done = 1; and use it with for(int j = i; j > 0 && !done; --j))
or with goto. Although goto is frowned upon by some people, it can, if used correctly and with care, be a legitimate solution for some problems, such as error handling, or in general, "finished handling".
Try the following
bool match = false;
for(int i = 0; i < sizeArray && !match; ++i){
for(int j = i; j > 0 && !match; --j){
if ( match = ( s[i].positionX == s[i-1].positionX ) ){
s[i].positionY = s[i-1].positionY;
}
}
}
Another way is the following
for(int i = 0; i < sizeArray; ++i){
int j = i;
while ( j != 0 && s[i].positionX != s[i-1].positionX ) --j;
if ( j != 0 ) {
s[i].positionY = s[i-1].positionY;
break;
}
}

How to exit (go to next element of parent loop) a for loop inside a for loop

for (int i = 0; i<10; i++)
{
//do some validation for record length
//if it is not valid
continue; // goes to the next iteration in for loop for 'i'
for (int j = 0; j<5; j+=2)
{
//do some more validation for individual record
//if it is not valid
Here it should go to the next i if i use continue. Here it will go to the next j
Can anyone please let me know how to do this?
You need to specifically test for a flag in the outer loop if there is something after the inner loop:
for(some_outer_vars){
bool should_skip = false;
// ...
for(some_inner_vars){
// ...
if(your_condition){
should_skip = true;
break;
}
}
if(should_skip)
continue;
// ...
}
Using break; inside the j loop will exit the j loop completely.
But at least spend a couple minutes deciding if an alternate algorithm, approach, or termination condition could remove the need to break in the middle of a loop.
Do you have anything after the inner loop? If not, you can just use break:
for (i = 0; i < 10; i++)
{
if (i is no good)
continue;
for (j = 0; j < 5; j++)
{
if (j is no good)
break;
}
}
If you do need to do something later, you can use break in combination with some other flag.
Place break; instead. This should get you out of the inner loop.
for (int i = o; i<10; i++)
{
}
for (int j = 0; j<5; j+=2)
{
break;
}
"break;" will end your current j loop and go to the next i.
If you can't arrange the logic so that break in the inner loop gets straight to continuing the outer loop, then do this:
for (int i = 0; i<10; i++)
{
if (!valid(i)) continue;
for (int j = 0; j<5; j+=2)
{
if (!valid(i,j)) goto continue_i;
do_whatever_with_i_and_j()
}
more_stuff_here();
continue_i:
}
There, I've said it. The code is shorter, simpler, easier to read and easier to analyse than the version that sets a flag, then breaks, then immediately checks the flag again and conditionally continues.
Another option is this
void inner_loop(int i) {
if (!valid(i)) return;
for (int j = 0; j<5; j+=2)
{
if (!valid(i,j)) return;
do_whatever_with_i_and_j()
}
more_stuff_here();
}
for (int i = 0; i<10; i++)
{
inner_loop(i);
}
Depending what the inner loop does, though, you might find yourself building quite a mechanism to give it access to whatever it's supposed to modify.
Community wiki, because this (or situations like it) has been argued so many times on SO as to practically define "subjective and argumentative".
I try to avoid break and continue when dealing with loops because they are easy to miss and their meanings change if you have to restructure the code later. You can use j=5; when you need to exit the inner loop. If you add a third loop or a switch the meaning of that line doesn't change. Sometimes you will need to add if statements inside your loops testing i and j or even a new variable like bool iIsInvalid but I think that makes the control flow easier to read.

Can I use break to exit multiple nested 'for' loops?

Is it possible to use the break function to exit several nested for loops?
If so, how would you go about doing this? Can you also control how many loops the break exits?
No, don't spoil it with a break. This is the last remaining stronghold for the use of goto.
AFAIK, C++ doesn't support naming loops, like Java and other languages do. You can use a goto, or create a flag value that you use. At the end of each loop check the flag value. If it is set to true, then you can break out of that iteration.
Just to add an explicit answer using lambdas:
for (int i = 0; i < n1; ++i) {
[&] {
for (int j = 0; j < n2; ++j) {
for (int k = 0; k < n3; ++k) {
return; // yay we're breaking out of 2 loops here
}
}
}();
}
Of course this pattern has a certain limitations and obviously C++11 only but I think it's quite useful.
Another approach to breaking out of a nested loop is to factor out both loops into a separate function, and return from that function when you want to exit.
Of course, this brings up the other argument of whether you should ever explicitly return from a function anywhere other than at the end.
break will exit only the innermost loop containing it.
You can use goto to break out of any number of loops.
Of course goto is often Considered Harmful.
is it proper to use the break function[...]?
Using break and goto can make it more difficult to reason about the correctness of a program. See here for a discussion on this: Dijkstra was not insane.
How about this?
for(unsigned int i=0; i < 50; i++)
{
for(unsigned int j=0; j < 50; j++)
{
for(unsigned int k=0; k < 50; k++)
{
//Some statement
if (condition)
{
j=50;
k=50;
}
}
}
}
Although this answear was already presented, i think a good approach is to do the following:
for(unsigned int z = 0; z < z_max; z++)
{
bool gotoMainLoop = false;
for(unsigned int y = 0; y < y_max && !gotoMainLoop; y++)
{
for(unsigned int x = 0; x < x_max && !gotoMainLoop; x++)
{
//do your stuff
if(condition)
gotoMainLoop = true;
}
}
}
A code example using goto and a label to break out of a nested loop:
for (;;)
for (;;)
goto theEnd;
theEnd:
One nice way to break out of several nested loops is to refactor your code into a function:
void foo()
{
for(unsigned int i=0; i < 50; i++)
{
for(unsigned int j=0; j < 50; j++)
{
for(unsigned int k=0; k < 50; k++)
{
// If condition is true
return;
}
}
}
}
I know this is an old thread but I feel this really needs saying and don't have anywhere else to say it. For everybody here, use goto. I just used it.
Like almost everything, goto is not 100% either/xor "bad" or "good". There are at least two uses where I'd say that if you use a goto for them - and don't use it for anything else - you should not only be 100% okay, but your program will be even more readable than without it, as it makes your intention that much clearer (there are ways to avoid it, but I've found all of them to be much clunkier):
Breaking out of nested loops, and
Error handling (i.e. to jump to a cleanup routine at the end of a function in order to return a failure code and deallocate memory.).
Instead of just dogmatically accepting rules like "so-so is 'evil'", understand why that sentiment is claimed, and follow the "why", not the letter of the sentiment. Not knowing this got me in a lot of trouble, too, to the point I'd say calling things dogmatically "evil" can be more harmful than the thing itself. At worst, you just get bad code - and then you know you weren't using it right so long as you heard to be wary, but if you are wracking yourself trying to satisfy the dogmatism, I'd say that's worse.
Why "goto" is called "evil" is because you should never use it to replace ordinary ifs, fors, and whiles. And why that? Try it, try using "goto" instead of ordinary control logic statements, all the time, then try writing the same code again with the control logic, and tell me which one looks nicer and more understandable, and which one looks more like a mess. There you go. (Bonus: try and add a new feature now to the goto-only code.) That's why it's "evil", with suitable scope qualification around the "evil". Using it to short-circuit the shortcomings of C's "break" command is not a problematic usage, so long as you make it clear from the code what your goto is supposed to accomplish (e.g. using a label like "nestedBreak" or something). Breaking out of a nested loop is very natural.
(Or to put it more simply: Use goto to break out of the loop. I'd say that's even preferable. Don't use goto to create the loop. That's "evil".)
And how do you know if you're being dogmatic? If following an "xyz is evil" rule leads your code to be less understandable because you're contorting yourself trying to get around it (such as by adding extra conditionals on each loop, or some flag variable, or some other trick like that), then you're quite likely being dogmatic.
There's no substitute for learning good thinking habits, moreso than good coding habits. The former are prior to the latter and the latter will often follow once the former are adopted. The problem is, however, that far too often I find, the latter are not explicated enough. Too many simply say "this is bad" and "this needs more thought" without saying what to think, what to think about, and why. And that's a big shame.
(FWIW, in C++, the need to break out of nested loops still exists, but the need for error codes does not: in that case, always use exceptions to handle error codes, never return them unless it's going to be so frequent that the exception throw and catch will be causing a performance problem, e.g. in a tight loop in a high demand server code, perhaps [some may say that 'exceptions' should be 'used rarely' but that's another part of ill-thought-out dogmatism: no, at least in my experience after bucking that dogma I find they make things much clearer - just don't abuse them to do something other than error handling, like using them as control flow; effectively the same as with "goto". If you use them all and only for error handling, that's what they're there for.].)
goto can be very helpful for breaking nested loops
for (i = 0; i < 1000; i++) {
for (j = 0; j < 1000; j++) {
for (k = 0; k < 1000; k++) {
for (l = 0; l < 1000; l++){
....
if (condition)
goto break_me_here;
....
}
}
}
}
break_me_here:
// Statements to be executed after code breaks at if condition
I'm not sure if it's worth it, but you can emulate Java's named loops with a few simple macros:
#define LOOP_NAME(name) \
if ([[maybe_unused]] constexpr bool _namedloop_InvalidBreakOrContinue = false) \
{ \
[[maybe_unused]] CAT(_namedloop_break_,name): break; \
[[maybe_unused]] CAT(_namedloop_continue_,name): continue; \
} \
else
#define BREAK(name) goto CAT(_namedloop_break_,name)
#define CONTINUE(name) goto CAT(_namedloop_continue_,name)
#define CAT(x,y) CAT_(x,y)
#define CAT_(x,y) x##y
Example usage:
#include <iostream>
int main()
{
// Prints:
// 0 0
// 0 1
// 0 2
// 1 0
// 1 1
for (int i = 0; i < 3; i++) LOOP_NAME(foo)
{
for (int j = 0; j < 3; j++)
{
std::cout << i << ' ' << j << '\n';
if (i == 1 && j == 1)
BREAK(foo);
}
}
}
Another example:
#include <iostream>
int main()
{
// Prints:
// 0
// 1
// 0
// 1
// 0
// 1
int count = 3;
do LOOP_NAME(foo)
{
for (int j = 0; j < 3; j++)
{
std::cout << ' ' << j << '\n';
if (j == 1)
CONTINUE(foo);
}
}
while(count-- > 1);
}
The break statement terminates the execution of the nearest enclosing do, for, switch, or while statement in which it appears. Control passes to the statement that follows the terminated statement.
from msdn.
I do think a goto is valid in this circumstance:
To simulate a break/continue, you'd want:
Break
for ( ; ; ) {
for ( ; ; ) {
/*Code here*/
if (condition) {
goto theEnd;
}
}
}
theEnd:
Continue
for ( ; ; ) {
for ( ; ; ) {
/*Code here*/
if (condition) {
i++;
goto multiCont;
}
}
multiCont:
}
Break any number of loops by just one bool variable see below :
bool check = true;
for (unsigned int i = 0; i < 50; i++)
{
for (unsigned int j = 0; j < 50; j++)
{
for (unsigned int k = 0; k < 50; k++)
{
//Some statement
if (condition)
{
check = false;
break;
}
}
if (!check)
{
break;
}
}
if (!check)
{
break;
}
}
In this code we break; all the loops.
Other languages such as PHP accept a parameter for break (i.e. break 2;) to specify the amount of nested loop levels you want to break out of, C++ however doesn't. You will have to work it out by using a boolean that you set to false prior to the loop, set to true in the loop if you want to break, plus a conditional break after the nested loop, checking if the boolean was set to true and break if yes.
I know this is old post . But I would suggest a bit logical and simpler answer.
for(unsigned int i=0; i < 50; i++)
{
for(unsigned int j=0; j < conditionj; j++)
{
for(unsigned int k=0; k< conditionk ; k++)
{
// If condition is true
j= conditionj;
break;
}
}
}
bool found = false;
for(int i=0; i < m; ++i){
for(int j=0; j < n; ++j)
if(grid[i][j] == '*'){
q.push(make_pair(i,j));
found = true;
break;
}
if(found)
break;
}
My suggestion is use a check variable to break a desired loop. The result code may not be so pleasant.
You can use preprocessors in order to make desired breaking under the hood. This approach can hides ugly codes and extra complexity.
For example, I created my custom break mechanism as follow:
Wanted code:
for (int i = 0; i < 100; i++) {
for (int j = 0; j < 100; j++) {
for (int k = 0; k < 100; k++) {
//do something
if (desiredCondition) {
breakToLevel = 0;
}
if (breakToLevel < 3) {
break;
}
}
if (breakToLevel < 2) {
break;
}
}
if (breakToLevel < 1) {
break;
}
}
Defined macros:
#define BREAK_TO(L) breakToLevel = (L);
#define CHECK_BREAK(L) if (breakToLevel < (L)) break;
and result:
for (int i = 0; i < 100; i++) {
for (int j = 0; j < 100; j++) {
for (int k = 0; k < 100; k++) {
//do something
if (desiredCondition) {
BREAK_TO(0)
}
CHECK_BREAK(3)
}
CHECK_BREAK(2)
}
CHECK_BREAK(1)
}
while (i<n) {
bool shouldBreakOuter = false;
for (int j=i + 1; j<n; ++j) {
if (someCondition) {
shouldBreakOuter = true;
}
}
if (shouldBreakOuter == true)
break;
}
you can use "goto" to leave nested loops
below is my original code including "goto"
int main()
{
string str;
while (cin >> str)
{
if (str == "0")
break;
int sum = 0;
for (auto ch : str)
{
if (ch <= 'z' && ch >= 'a')
sum += (ch - 'a' + 1);
else if (ch >= 'A' && ch <= 'Z')
sum += (ch - 'A' + 1);
else
{
cout << "Fail" << endl;
goto fail;
}
}
cout << sum << endl;
fail:
}
return 0;
}
however, I could avoid "goto" by adding a function "calculate"
void calculate(const string &str)
{
int sum = 0;
for (auto ch : str)
{
if (ch <= 'z' && ch >= 'a')
sum += (ch - 'a' + 1);
else if (ch >= 'A' && ch <= 'Z')
sum += (ch - 'A' + 1);
else
{
cout << "Fail" << endl;
return;
}
}
cout << sum << endl;
}
int main()
{
string str;
while (cin >> str)
{
if (str == "0")
break;
calculate(str);
}
return 0;
}
You can use try...catch.
try {
for(int i=0; i<10; ++i) {
for(int j=0; j<10; ++j) {
if(i*j == 42)
throw 0; // this is something like "break 2"
}
}
}
catch(int e) {} // just do nothing
// just continue with other code
If you have to break out of several loops at once, it is often an exception anyways.
Breaking out of a for-loop is a little strange to me, since the semantics of a for-loop typically indicate that it will execute a specified number of times. However, it's not bad in all cases; if you're searching for something in a collection and want to break after you find it, it's useful. Breaking out of nested loops, however, isn't possible in C++; it is in other languages through the use of a labeled break. You can use a label and a goto, but that might give you heartburn at night..? Seems like the best option though.