Not sure if I understand the question (although I like it). Both your code snippets work, don't they? Note that we don't know what is in cs50.h
, but I tried compiling this, and it worked (both compiling and running).
#include <stdio.h>
#include <string.h>
int main(void) {
char *s = "Hello world!";
printf("Output:\n");
for (int i = 0, n = strlen(s); i < n; i++) {
printf("%c\n", s[i]);
}
}
Two things might be relevant here;
- how for
works and
- how variable declaration/initialization works.
You can think about for
like this:
for(AAA; BBB; CCC) DDD;
is the same as
{ // Important!
AAA;
while(BBB) {
{
DDD;
}
CCC;
}
} // Important!
The // Important!
braces are important because the for introduces a new scope, i.e. i
and n
won't accessible outside/after the for
loop.
The other thing is declaration/initialization. So the
int i = 0, n = strlen(s);
is an initialization of two variables: i
, n
. I'm not 100% sure about the proper vocabulary and rules (you can consult the standard), but the idea is that a declaration looks like:
TYPE VAR1, VAR2, ..., VARn
where the VARx
is a variable name declared, or an "assignment" in which case it is an initialization.
UPDATE/PART2:
Usually how I would do this is something like:
const int len = strlen(s);
// Good practice to declare const what every you know wont change
for(int i = 0; i < len; i++) {
// whatever
}
But, what if the confusing coma/semicolon could be made consistent and since the semicolon is a must let's try to make everything a semicolon, I've tried this:
for ({int i = 0; int n = strlen(s); }; i < n; i++) {
// what ever
}
This did not compile, but it also didn't make sense, since if this would have "worked" (in the sense I thought I could but actually couldn't), i
and n
would be declared in the small block and it wouldn't be accessible anywhere else, i.e. in i < n
would not be accessible. So to make them accessible we could try this:
int i, n;
for ({i = 0; n = strlen(s); }; i < n; i++) {
printf("%c\n", s[i]);
}
Now this should have worked if the for
-while
equivalency stated above would be 100% true, but it's not since apparently the the AAA
has to be a single statement (usually a declaration) and it can't be a block i.e. {...}
. Exact compiler error:
cc hola.c -o hola
hola.c: In function ‘main’:
hola.c:8:8: error: expected expression before ‘{’ token
8 | for ({
| ^
make: *** [<builtin>: hola] Error 1
but as you can see it is already very ugly and all... so yes, you need to use ,
to separate the declarations/initializations and a ;
to terminate it.