Length is suppose to return how far along the counter went when going trough the string. However, it only returns the correct value when it is printed beforehand. If i comment out the printf
it returns 0.
Does anyone have an explanation for this?
#include<stdio.h>
#include<string.h>
#define MAX 100
int length(char *s) {
int i;
for (i = 0; s[i] != '\0'; ++i)
printf("%d ", i); //<-- here
return i;
}
int main()
{
char s[MAX];
fgets(s, (char)sizeof(s), stdin);
s[strcspn(s, "\n")]='\0';
printf("Length: %d\n", length(s));
return 0;
}
The problem is, if you comment out the printf()
statement in the length()
function, the return
statement becomes part of the loop body, and the very first iteration returns from the call and you get the the-then value of i
, which is just the entry value for the loop, 0
.
for (i = 0; s[i] != '\0'; ++i)
//printf("%d ", i); //<-- here
return i; // without brace-enfoced scope, this is the loop body.
is the same as
for (i = 0; s[i] != '\0'; ++i)
return i;
What You need is the loop to complete the execution, hit the exit criteria and then, execute the return
statement with the latest value of i
.
So, to avoid the problem, you can enforce empty execution of the loop, by something like
for (i = 0; s[i] != '\0'; ++i) ; // notice the ; here, ends the scope.
return i;
or, even better (for the readers)
for (int i = 0; i < 10; i++)
{/*nothing here*/} //indicates empty loop body
return i;
Note: As an alternative way, to enhance the readability, instead of a for
construct you can also make use of while
loop, which goes like
while (s[i] != '\0')
{
i++; //increment statement is explicit.
}
In a loop like this:
for (...)
statement1;
statement2;
statement1
will be the only thing executed in the loop. When you comment out the printf
call, return i;
is executed on the very first iteration, immediately returning zero.
Notice, however, that statement1
can be empty, so, to run a loop with no body, do:
for (...)
; // yes, a hanging semicolon
// or like this:
for (...);
If you just commnt out that printf
, you will be left with this:
int length(char *s) {
int i;
for (i = 0; s[i] != '\0'; ++i)
return i;
}
This is equal to:
int length(char *s) {
int i;
for (i = 0; s[i] != '\0'; ++i){
return i; // returns in the first iteration, without even incrementing i once
}
}
Surely this isn't what you intended. Instead, put a semicolon after the for
loop:
for (i = 0; s[i] != '\0'; ++i);
This way, for (i = 0; s[i] != '\0'; ++i);
won't accidentally affect a following statement.
You can prevent such accidents by adding explicit braces to denote your intention, for instance:
int length(char *s) {
int i;
for (i = 0; s[i] != '\0'; ++i) {
printf("%d ", i); //<-- here
}
return i;
}
Now if you remove the printf
line, it doesn't affect the program execution in any other way than omitting the print.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With