As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
I'm looking for a good tutorial on writing and designing loops. I understand the basics of loops but nested loops give me a lot of trouble. To give you and idea, the following pattern below was kind of difficult for me to figure out.
1
12
123
1234
12345
123456
Loops
A loop is a construct that enables a set of instructions to be executed more than once.
There are several loop constructions:
zero or more
These loops have the check at the begining of an iteration and as such will be executed 0 or more times. A while loop is an example.
one or more
These loops have the check at the end of the iteration and as such will be executed at least once. A do while loop is an example.
Loops with counters
These loops have a counter that counts from a certain number to an other number. The number can be used inside the loop (for example to access a field of an array).
Loops with an iterator
These loops use an iterator to loop through a certain structure.
Endless loops
These loops have no end. But of course nothing is forever, so the loop often contains a hidden mechanism.
Nested loops
If you understand single loops, nested loops can be difficult. But you need to focus on one loop at a time.
Lets take your example:
1
12
123
1234
12345
123456
Ok, lets first look at the lines.
The first line has a single 1
The second line counts from 1 to 2
The third line counts from 1 to 3
...
Generally: the n th line counts from 1 to n.
Great, no we have the individual line. But let's now look at all lines.
the first has n=1
the second has n=2
the third has n=3
...
Hm, so we can use the loop counter of the outer loop as the n in the inner loop:
for n = 1 to 6
s = ''
for i = 1 to n // use the loopcounter of the outer loop
s = s + char(i)
end for
out s
end for
Check out:
http://mathbits.com/mathbits/compsci/looping/nested.htm
http://tldp.org/LDP/abs/html/nestedloops.html
http://www.actionscript.org/resources/articles/5/1/The-power-of-nested-loops/Page1.html
In general (language-neutral) terms, the basic logic is quite straightforward. Where it can get more complex is if an inner loop terminates early & the manner of the break. It may cause the outer loop to move to the next value, or it may completely exit the outer loop as well.
The best way to learn this is to try out different cases to see how they behave, and read up on the ways to exit from loops.
How about these:
Nested Loops
The Power of Nested Loops
or on YouTube "SQL Joins, nested loops and all that in less than 6 minutes" at http://www.youtube.com/watch?v=SmDZaH855qE
I don't remember seeing any "loop design" centred tutorials when I was learning to program.
You will get a grasp of loops if you just start tackling on different problems and algorithms. Look for matrix problems, you will need nested loops there for instance...
I'm unaware of any tutorials on this subject, but I suggest you try Google. Also, the fact that you were able to figure out your example probably means that you don't need a tutorial as much as you need practice. Nested loops are somewhat mind-warping when you first encounter them. You might also want to look for references/tutorials pertaining to recursion, which is a related concept. Remember, practice makes perfect!
Check out the MIT Course Material. Also consider getting a Safari subscription, a cheap way of getting some good learning books.
This MIT course points to Loops on the python wiki.
I found that working it out on paper, listing the variables helps in learning how this works.
declare
s varchar2(10);
begin
for n in 1..5 loop
s:='';
for i in 1..n loop
s:=s||(i);
end loop;
dbms_output.put_line(s);
end loop;
end;
Related
I am doing Cs50 Harvard University online and I'm on week 3 but while watching the video I noticed that I iterations and loops seem the same, as they repeat things over and over. But there must be a difference or else they wouldn't have two names for the same thing. No matter how many times I re-watch the video I can't find a difference. Please help me understand.
"Loop" refers to language constructs that are used to repeatedly execute some code. (for loops, while loops, etc.)
"Loop" can also refer to code being executed repeatedly. (e.g. "It's stuck in a loop.")
Iterating is the process of doing something repeatedly. (e.g. "This loop iterates over the elements of the array.")
An iteration is a single pass of a loop. (e.g. "In the first iteration of that for loop, i will be 0.")
Usually "loop" refers to the code and "iteration" refers to the conceptual process of repeating some steps. In this case, they are more or less the same. Additionally, you could use "iteration" to refer to a single repetition within a loop which gives it a different meaning.
A case example for the first usage of "iteration" would be:
You can print a linked list either by using iteration or recursion. If you use iteration, simply create a while-loop that propagates a "current" node through the list and stops when it becomes NULL.
And an example refering to specific repetitions:
The following loop outputs numbers 1 to 10 in reverse order. At the k-th iteration, 10-k+1 is printed:
for (i=10; i>=1; i--){
printf("%d\n", i);
}
That's how I would define it:
"Loop" - A control flow statement that iterates the code in the loop's body dependent upon a provided loop condition. It is a language construct and in C we have three kinds of these constructs: for, while and do-while.
"Iteration" - One specific walkthrough of the code inside of the loop's body after the first walkthrough. In other words, a single repetition of the execution of the loop body's code.
When doing looping/iterating (as verb they can be seen equal indeed), you repeat over the code in the loop's body. Every single repetition is an iteration.
A loop's purpose is the capability to do iterations. Without being able to do iterations the loop construct is useless.
So, both terms are closely related, but not the same.
This question already has answers here:
Two semicolons inside a for-loop parentheses
(4 answers)
Endless loop in C/C++ [closed]
(12 answers)
Closed 4 years ago.
I was searching for an explanation for the "double semicolon" in the code:
for(;;){}
Original question.
I do not have enough reputation to even leave a comment so I need to create a new question.
My question is,
What does an "extra" semicolon means. Is this "double semicolon" or "extra semicolon" used for "something else"?
The question comes from a person with no knowledge of programing, just powered on my first arduino kit and feel like a child when LED blinked.
But it is the reality that the questions, like general occurence, are radiating the actual knowledge of the person asking the question.
And beyond "personal preference" in using while(1) or for(;;) is it helpful in using for(;;) where you do not have enough room for the code itself?
I have updated the question.
Thank you for the quick explanation. You opened my eyes with the idea of not using anything in for loop = ). From basic high school knowledge I am aware of for loop so thank you for that.
So for(;;) returns TRUE "by default"?
And my last line about the size of the code?
Or it is compiled and using for or while actually does not affect the compiled code size?
A for loop is often written
int i;
for (i = 0; i < 6; i++) {
...
}
Before the first semicolon, there is code that is run once, before the loop starts. By omitting this, you just have nothing happen before the loop starts.
Between the semicolons, there is the condition that is checked after every loop, and the for loop end if this evaluates to false. By omitting this, you have no check, and it always continues.
After the second semicolon is code that is run after every cycle, before that condition is evaluated. Omitting this just runs additional code at that time.
The semicolons are always there, there is nothing special about the face that they are adjacent. You could replace that with
for ( ; ; )
and have the same effect.
While for (;;) itself does not return true (It doesn't return anything), the second field in the parentheses of the for always causes the loop to continue if it is empty. There's no reason for this other than that someone thought it would be convenient. See https://stackoverflow.com/a/13147054/5567382. It states that an empty condition is always replaced by a non-zero constant, which is the case where the loop continues.
As for size and efficiency, it may vary depending on the compiler, but I don't see any reason that one would be more efficient than the other, though it's really up to the compiler. It could be that a compiler would allow the program to evaluate as non-zero a constant in the condition of a while loop, but recognise an empty for loop condition and skip comparison, though I would expect the compiler to optimize the while loop better. (A long way of saying that I don't know, but it depends on a lot.)
program not stopping to read "ar". help please. even after allocating that it has definite number of elements. what may be the reason? is there something a could have missed?
program summer_a39
implicit none
integer:: n, i, l, k
integer, allocatable, dimension(:)::ar
print*, 'Enter size of array:'
read*, n
allocate (ar(n))
print*, 'Enter values:'
read*, ar
l=1
3 do i=l,n-1
if (l==n) then
goto 4
end if
if (ar(i)<=ar(i+1)) then
goto 1
else
goto 2
end if
end do
1 do i=l,n-1
do while (ar(i)<=ar(i+1))
k=k+1
end do
l=k
end do
print*, 'Increases to', l
goto 3
2 do i=l,n
do while (ar(i)>=ar(i+1))
k=k+1
end do
l=k
end do
print*, 'Decreases to', l
goto 3
4 print*, 'The End'
deallocate(ar)
end program
Uhm... Wow... Well...
That code makes no sense at all.
I hate to say it, but you still have a lot of learning and understanding to do.
First of all: STOP USING GOTO. It breaks the code flow and makes reading it a mess.1)
Secondly: Even without checking, I'm confident that the read statement is not the reason your program hangs. It hangs between the various loops.
Even without the goto statements, this snippet alone is a surefire way to get the program to hang:
do while (ar(i)>=ar(i+1))
k=k+1
end do
This loop keeps repeating for as long as ar(i) is larger or equal to ar(i+1) -- but in the body of the loop, neither value changes (only k, but k is not part of the condition). So if the condition is true once, it will stay true forever, and the loop will never ever terminate.
Then you keep jumping back to the beginning of a loop. Each time you do that, the loop starts again from scratch. Again, you never come to a conclusion.
I contemplated showing how to use subroutines to do what I think you want to do, but I thought better of it. You need a lot more time to understand what's going on, and I suggest you find some dedicated resources that teach programming.
It doesn't have to be Fortran specific, any tutorial for any procedural language will help you understand program flow, which is what you need to analyse this mess.
1) a good programmer might know when to use goto. You are not a good programmer yet.
After your comments to my previous answer, I got a better idea of your situation.
Here's what I understand so far:
You have an exercise for a Fortran training/lessons/etc.
The exercise is to create a program that takes as input an array of arbitrary length, and then prints out the final values of each monotonic sequence in that array. So for example, if the input were 4 3 7 2 1 4 6 3 5 10, then the output should be something like:
Starts with 4
Decreases to 3
Increases to 7
Decreases to 1
Increases to 6
Decreases to 3
Increases to 10
The end
Part of the exercise is that you should make use of the GOTO command.
So here's my updated answer:
This is not a homework service, we won't solve the issue for you. Then again, you didn't ask for that, so that's okay.
Your issue is not the read*, ar command. You can test this out easily by just adding a print*, ar right below it, it will print.
Your issue is that there is an infinite loop inside your code (actually, there are several), some because you use DO WHILE loops where the condition never changes in the iteration, some because you jump out of one loop to the beginning of another, which resets the initial conditions.
Here are some hints for your exercise:
Create a single variable for the index of the array that you're currently looking at.
Create two loops, one for increasing this index as long as the next value in the array is larger, and one as long as the next value is smaller. Check that you don't increase the index beyond the range of the array.
Do not jump from inside of any loop
Do not jump into the middle any loop.
At the end of either loop, think about what you learned about the array, and were to jump to from there.
Make sure that you know that the algorithm will eventually stop.
And finally, there's no harm in using lots of print* statements during debugging to make you understand what the program is actually doing.
This question already has answers here:
Is it a bad practice to use break in a for loop? [closed]
(19 answers)
Closed 5 years ago.
I have a fairly simple structure:
do i = 1,x
if (condition) then
do_stuff
exit
end if
end do
If the do-loop gets big enough, the exit statement wouldn't be good anymore (I look at it approx. like I look at go to statements).
I'm looking for a cleaner way to exit the loop when appropriate so that it is also more clear what is happening for somebody else looking over my code.
One thing I thought of that might clean up would be something along the lines of
lkeepgoing = .true.
iterator = 1
while (lkeepgoing) then
if (condition) then
do_stuff
lkeepgoing = .false.
end if
iterator = iterator+1
end while
While I think it clears up why I want to exit the loop without having to look through the whole loop, it looks overly complicated I think.
So the question: How do you exit do-loops when a condition is met in a clear, clean way that doesn't use spaghetti-code-prone statements?
There's nothing wrong with the way your first code snippet uses exit. A little jump such as that is hardly spaghetti code. And compared with your second snippet it's considerably clearer that you are making a disciplined early exit from a loop when a certain condition is met.
Bear in mind that exit is very confined in where it can jump to, while go to can be used to jump all over the place.
Don't adhere to one-size-fits-none rules such as never use goto too strictly, certainly not when they make code worse.
I just found ... AGAIN ... a real time wastage bug as follows
for (int i = 0; i < length; i++)
{ //...Lots of code
for (int j = 0; i < length; j++)
{
//...Lots of code
}
}
Did you notice straight ahead the inner i which SHOULD BE j ? Neither did I. So from now on I am going to use:
for (int i = 0; i < length; i++)
{
for (int i1 = 0; i1 < length; i1++)
{
}
}
What are your tips for inner and outer while and for loops ?
Edit: Thanks for the valuable responses. Herewith short summary of the proposed tips:
use meaningful variables names for index variables ( instead i use SomeObjCollectionLength )
place the contents of the inner loop into a separate method and call that method from the outer loop
not manageable amount of lines of code between the outer and inner loop is a strong signal for code smell
avoid copy pasting and rushing , write the index vars with care
You might want to check the summary by LBushkin for the following
use foreach and iterators whenever possible
initialize the variables just before entering the loops
Make each loop perform only one function. Avoid mixing responsibilities in a single loop
When possible, make your loops short enough to view all at once
Don't use i & j (or any other single letter variable) as index names. Use proper names and you will not get into this type of problems.
One of the simplest and cleanest solutions is to place the contents of the inner loop into a method so it becomes:
for (int i = 0; i < length; i++)
{
DoSomething();
}
private void DoSomething(int outerValue)
{
for (int i = 0; i < length; i++)
{
// Do something else
}
}
For me, the 'code smell' here is 'lots of code'.
If the amount of code in the loops is particularly large, the distance between the inner and outer loops means that they're not as likely to be compared against each other for correctness.
Admittedly, looking at the start of the inner loop in isolation should bring the issue to your attention, but having the main structure in as small a section of code as possible gives your brain less to digest.
It may be possible to extract the 'lots of code' sections into separate functions/methods, in order to reduce the size of the main structure - but this may not alway be practical.
Also, I'd say that 'i1' isn't a particulary good choice of variable name, as that tends to encourage 'i2', 'i3' etc, which doesn't really lead to understandable code. Maybe replacing all of the loop variables with something more meaningful would help the clarity of the code, and reduce the chances of the original error.
My top advice (in no particular order) for writing better loop code (much of this is from the excellent book Code Complete):
Avoid multiple exit points for loops.
Use continue/break sparingly.
Refactor nested loops into separate routines, when possible.
Use meaningful variable names to make nested loops readable.
Use foreach() loops when possible, rather than for(i=...) loops.
Enter the loop from one location only. Don't jump into a loop with goto's. Ever.
Put initialization code immediately before the loop.
Keep loop initialization statements with the loop they are related to.
Avoid reusing variables between non-nested loops.
10.Limit the scope of loop-index variables to the loop itself.
Use while(true) for infinite loops, rather than for(;;)
In languages that provide block constructs (e.g. '{' and '}') use them rather than indenting to enclose the statements of a loop. Yes, even for single line loops.
Avoid empty loops.
Avoid placing housekeeping chores in the middle of a loop, place them at the beginning and/or end instead.
Make each loop perform only one function. Avoid mixing responsibilities in a single loop.
Make loop termination conditions obvious.
Don't monkey with the loop index variable of a for() loop to make it terminate.
Avoid code that depends on the loop indexer's final value.
Consider using safety counters in complex loops - they can be checked to make sure the loop doesn't execute too many, or too few times.
Use break statements, when possible, to terminate while loops.
When possible, make your loops short enough to view all at once.
That's a copy-paste mistake, avoid copy paste.
As for your solution, its not much better. The mistake can still slip between tons of code. I tend to use meaningful names even for loop temporary variables.
leverage your IDE, on VS, try to use this: http://msdn.microsoft.com/en-us/library/z4c5cc9b(VS.80).aspx
sample: type for, then press Tab Tab successively
I came here to be smart and say "I just write it right the first time". But then I saw your example and, well, I've done that too many times myself.
When you need nested loops like that, my only solution is to be alert and thinking when you write the code.
Where possible, using iterators and for each loops are nice.
Also, I can't see how your suggested solution is going to be any better. And it doesn't look as nice either.
First of all, reduce the loop body size, i.e. move stuff to separate functions. It is generally a bad idea to have functions longer than what can fit into the screen, so loops should be even smaller.
Secondly, use meaningful variable names in cases like this. I would only use i and j in simple loops with a few lines of code. For instance, if you are going through a two-dimensional array, "col" and "row" would make much more sense, make the code easier to read ("which was which?") and easier to spot mistakes like this.
You just have to take extra care of such issues, there's no magic bullet against this. Even with "better naming" you propose you will once in a while lose track of whether this is Nth or (N+M)th level of nested loop and make an error.
If nested loop is necessary write it carefully. If it can be avoided by extracting the outer loop body into a function that would be a good guard against indices misuse.
As in this as in many things, there's some excellent advice in Steve McConnell's Code Complete. It would be well worth your time to read what he's got to say about building good looping code. I don't have my copy of the book handy here but the whole book is worth your time.
I use 'ii' and 'jj' for transient loop counters if I really need them - they are easier to search for than 'i' and 'j' and also easier to spot in examples like the above. To go one better you can actually use a real variable name. If you're looping over a string then you can call it characterIndex or something. It's more typing, but it documents itself and saves time on debugging obscure problems later.
Better still would be to avoid numerical counters and use named iterators over a collection. They make the intent clearer, in my opinion.
Finally, if possible it's nice to do away with the loop entirely: Boost::Foreach is one way of doing this in C++, although I generally prefer to use languages such as Python which natively allow direct iteration over the contents of a container without a need for incrementing an index value or iterator.
Try to use more declarative loop constructs. For instance, if you don't really need indices (those is and js) and your programming environment allows for it, you can use a foreach construct to iterate over the collection.