Reputation: 47
Why can't we define a variable in while
loop's condition expression in the same way as we can define in a for
loop?
For example:
#include <stdio.h>
int main() {
while((int c = getchar()) != EOF)
printf("%c", c);
return 0;
}
Chat GPT 4.0 and Perplexity.ai had suggested me the above piece of code. But apparently that's not allowed; I found out that through trail and error. I also tried using ,
operator too.
Example:
#include <stdio.h>
int main() {
while((int c = getchar(), c != EOF)
printf("%c", c);
return 0;
}
As the value of the conditional test is only going to be the right most expression (c != EOF
) because ,
operator was used. But even then the compiler didn't compile it. So, how can we define a variable in the while loop's conditional expression?
Upvotes: 0
Views: 168
Reputation:
A while
-loop (6.8.5.1) expects a controlling expression (6.5) but int c = getchar()
is a declaration with an initializer (6.7). In C a declaration is not an expression. You can use the comma operator in the controlling expression along these lines:
#include <stdio.h>
int main() {
{ // scope of the variable c
int c;
while(c = getchar(), c != EOF)
printf("%c", c);
}
}
The first part of a for
-loop is a clause which permits declarations (6.8.5.3) and you declare multiple variables of the same type by comma separating them:
for(int c, y, a; ...)
In my opinion, assignment in the controlling expression is harder to read, so I favor simpler constructs like:
#include <stdio.h>
int main() {
for(;;) {
int c = getchar();
if(c == EOF) break;
printf("%c", c);
}
}
Upvotes: 3
Reputation: 17513
The syntax of the while
statement does not allow variables to be declared in the controlling expression (it's an expression, not a declaration). You could use a for
loop instead, although there will be some code repetition:
/* ^^ preceding code ^^ */
for (int c = getchar(); c != EOF; c = getchar())
/* loop statement */;
If the repetition of the call to getchar()
is unacceptable and the variable c
must be isolated, there are various options. As pointed out by user tstanisl in the comments below, the assignment could be combined with the test in the controlling expression of the for
loop:
/* ^^ preceding code ^^ */
for (int c; (c = getchar()) != EOF; )
/* loop statement */;
The controlling expression of the loop could also be a comma expression to separate the assignment from the test:
/* ^^ preceding code ^^ */
for (int c; c = getchar(), c != EOF; )
/* loop statement */;
Another option mentioned in the answer by user Allan Wind is to place the while loop inside an enclosing block that defines the variable c
:
/* ^^ preceding code ^^ */
{
/* local declarations for the loop */
int c;
while ((c = getchar()) != EOF)
/* loop statement */;
}
The above use of an enclosing block is useful if several declarations are required to define the variables local to the loop and its condition test, whether that be a while
loop, a do
while
loop, or a for
loop.
Another option mentioned in the answer by user Allan Wind is to use an infinite loop with a conditional break
statement to terminate the loop. The local variables can be defined in the compound statement that forms the body of the infinite loop:
/* ^^ preceding code ^^ */
for (;;)
{
int c = getchar();
if (c == EOF)
{
break;
}
/* remainder of loop */
}
Upvotes: 2
Reputation: 12679
No. Its not allowed by language syntax but GCC
compiler (and clang
as well) allow it as an extension, known as statement expression.
GCC
's statement expression allow you to use local variables within an expression. Take your sample code as example, we can declare local variable c
in while
loop expression if using GCC
compiler, but it will not be accessible in loop body as it is only available within expression.
Using GCC
's statement expression extension, your sample code can be written as:
#include <stdio.h>
int main() {
while(({int c = getchar(); c == EOF ? 0 : putchar(c);}))
;
return 0;
}
Upvotes: 1