Writing it for human readers can be used to argue for the original implementation if you think of for(i=0;i<expr;i++) as the C idiom for "iterate expr times" and here you want expr to equal the length of the string, which is what the (obviously pure) function yields. No unnecessary variables and assignments -- no clutter. It perfectly describes the intent.
I try to write code that is as plain and simple as possible, and make it obvious what it does and that it has no gotchas. I want my code to be understandable both for new developers, and for my future self, who will surely be less smart than I think I am today.
Here is the original code, with the loop body elided:
for( int i = 0; i < strlen(s); i++ ) {
}
It is trivial to rewrite this as: for( int i = 0, n = strlen(s); i < n; i++ ) {
}
This is a very common idiom, and now it is perfectly clear what the code actually does. Obviously, it only calls strlen() once.Of course, as I pointed out in another comment, if you're writing a loop that iterates over a C string, you never have to call strlen() at all! You can just use the canonical C string loop:
for( int i = 0; s[i] != '\0'; i++ ) {
}
Or if you like brevity (which I like too): for( int i = 0; s[i]; i++ ) {
}