CS50: For Loop Design - c

Currently doing the CS50 lectures, and in week 2, starting at about 56:45 on this video (https://video.cs50.net/2016/fall/lectures/2?t=56m50s) he mentions that the strlen function should be moved into the initialized variable section of the for loop, rather than stay in the conditions section, because leaving it in the conditions section makes the computer run the strlen function each time the for loop increments.
Ok, I get that, but the proposed solution -- to move it into the variable declaration section, doesn't solve the problem, does it? Because it's still in the for loop, it looks like the strlen function is still being checked each time the for loop iterates.
Am I wrong?

well,strlen function will not be called every time in the for loop because we stored the value of strlen before the for loop,
it will look something like this
`int n= strlen(s);
for(int i=0;i<n;i++)
{
code
}
`
once the value of strlen is stored in n ,computer just have to access n rather than accessing strlen again and again from the string.h library
Hope this answer helps :)

the 'initialize' section of a 'for()` loop is only run once.
The 'conditional' section of a for() loop is run at the beginning of each loop iteration.
The 'step' section of a for() loop is run at the end of each loop iteration.
This is why repetitive operations, like a call to strlen() should be moved to the initialization section (where is should be setting a local variable)

Related

Lua: Access the for loop variable from outside of the loop

I would like to use a for-loop in Lua, but be able to identify what the last iterated value was:
local i
for i=0,10 do
if i==5 then break end
end
print(i) --always prints nil
Is there some way to prevent "i" from being re-declared in the for loop block, instead of shadowing my upvalue of the same name?
Currently, I have to use a while loop to achieve the expected results, which defeats the clarity of the for loop's syntax. Is this just another Lua caveat one has to expect as part of its language quirks?
i is local to the for-loop, meaning that you cannot access is when the loop terminates.
If you want to know what the last iterated value was, you have to save it in another variable:
local last
for i = 0, 10 do
if i == 5 then
last = i
break
end
end
print(last) --> 5

What is the difference between an iteration and a loop?

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.

What does an "extra" semicolon means? [duplicate]

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.)

C - how does sprintf() work?

I'm new to coding in C and was writing a program which needs to create custom filenames that increment from 0. To make the filenames, I use sprintf() to concatenate the counter and file extension like so:
int main(void)
{
// do stuff
int count = 0;
while (condition == true)
{
char filename[7];
sprintf(filename, "0%02d.txt", count) //count goes up to a max of 50;
count++;
//check condition
}
return 0;
}
However, every time
sprintf(filename, "0%02d.txt", count);
runs, count gets reset to 0.
My question is, what does sprintf() do with count? Why does count change after being passed to sprintf()?
Any help would be much appreciated.
EDIT: Sorry, I haven't been too clear with the code in my question - I'm writing the program for an exercise on an online course, and count goes up to a max of 50. I've now changed my code to reflect that. Also, thanks for telling me about %04d, I was using a complicated if statement to determine how many zeroes to add to my filename to make it 3-digit.
Despite the title of the question, this has nothing to do with sprintf(), which probably works as expected, but everything with count.
If count is a global variable (i.e. outside any functions), then it should keep its value between function calls. So that is probably not the case.
If it is a local variable (declared inside the function), then it can have any value, since these lose their value when the function ends and don't get initialized when the function is run again. It can be always 0, but under different circumstances, it can just as well be something else. In other words, the value is more or less undetermined.
To have a local variable keep its value between function calls, make it static.
static int count = 0;
But note that when you stop and run the program again, it will start as 0 again. That means you would possibly overwrite 000.txt, then 001.txt, etc.
If you really want to avoid duplicate file names, you will have to be more sophisticated, and see which files are already there, determine the highest number, and increment that by one. So you don't use a variable, you check the files that already exist. That is far more work, but the only reliable way to avoid overwriting existing files with such numbered file names.
FWIW, I would use something like "00%04d.txt" as format string, so you get files 000000.txt, 000001.txt, etc. which look better in an alphabetically sorted file listing than 000.txt, 001.txt, 0010.txt, 0011.txt, 002.txt, etc. They are also easier to parse for their number.
As Weather Vane noticed, be sure to make your buffer a little larger, e.g.
char filename[20];
A buffer that is too small is a problem. One that is too large is not, unless it is huge and clobbers up the stack. That risk is very small with 20 chars.
I think it is likely the sprintf. "0%02d.txt" is 7 chars. The null at the end of the string will go in the next location, which is likely the count on the stack. On a little endian machine (x86), that likely means the bottom byte of count gets zeroed out in every sprintf().
As other folks said. Make the filename buffer larger.

Why is for(;;) used?

I have seen code (in C) which contains something similar to:
for(;;){
}
How would this work, and why is it used in any instance?
It is the idiomatic way to have an infinite loop.
In the C Programming Language book, by Kernighan & Ritchie book it was introduced in section 3.5:
for (;;) {
...
}
is an infinite loop, presumably to be broken by other means, such as a break or return.
is an infinite loop something like
while(true)
{}
This is equivalent to an infinite loop, as many other have explained. However, few of them explained why this executes as an infinite loop.
A for loop can be broken down into three parts:
for(initialization(s); condition(s); looping command(s))
None of these fields are actually required. Without a condition provided, there's nothing to stop the command from running. This is because the for loop looks for a false statement. Without conditions provided, nothing is false, therefore the loop runs indefinitely.
Therefore to cause a for loop to be infinite, all you need is to not provide a condition. This means that this is also a valid infinite loop:
for(int i = 0;; i++)
printf("Iteration: %i\n", i);
For readability, and to make sure that the second semi-colon isn't a typo, some programmers might put a space between them, or put true as the condition.
Honestly, I prefer while(true), as this is a clear infinite loop. Using while(1) works as well, but '1' is an integer, not a boolean. While it is equivalent to true, it does not always mean true.
Between these three types of infinite loops, for(;;) has the fewest characters (7). while(1) comes second at 8 characters, and while(true) at 11.
I suppose that certain programmers prefer a low byte count over a readable program, but I wouldn't recommend using for(;;). While equivalent, I believe that using while(true) is better practice.
A for loop needs three expressions, which are separated by semicolons, and are completely optional:
An initialization (e.g. int i=0)
A condition (e.g. i < 10)
An afterthought (e.g. i++)
In this case, the three expressions are empty, and thus there's no condition that will make the loop stop, thus creating an infinite loop, unless a flow control instruction like break (which will exit the loop) or return is used.
Its an infinite loop. Its equivalent to:
while (true) {
}
The C# compiler directly translates for (; ;) into the exact same construct as while (true).
Infinite loop
same as
while(true){}
the code for(;;){} or while(true){} or while(1){} all represent infinite loops.
An infinite loop is something to be expected in a software system that is expected to run and "unlimited" amount of time. Every OS has at least one - it's how a background task or idle task is implemented.
Real Time systems use infinite loops as well because the system has to handle events which are asynchronous;
Basically anything that runs software uses infinite loops in one way or another.
I don't know why no one answered why people do this instead of while(true): It's because while(true) will often generate a compilation warning that the condition of the loop is constant.
This kind of infinite loop can be used in microcontroleurs. In your main function, you initialize the basic functions of your microcontroleur, then put a while (1).
void MAIN(void)
{
Init_Device();
while(1);
}
The microcontroleur will then do nothing but wait for interrupts of internal or external devices (like a timer overflow, or UART data ready to be read), and react to these interrupts.

Resources