Почему мы не можем определить переменную в выражении условия цикла while так же, как мы можем определить в цикле for?
Например:
#include <stdio.h>
int main() {
while((int c = getchar()) != EOF)
printf("%c", c);
return 0;
}
Чат GPT 4.0 и Perplexity.ai предложили мне приведенный выше фрагмент кода. Но, видимо, это запрещено; Я узнал это методом проб и ошибок. Я также попробовал использовать оператор ,.
Пример:
#include <stdio.h>
int main() {
while((int c = getchar(), c != EOF)
printf("%c", c);
return 0;
}
Поскольку значением условной проверки будет только самое правое выражение (c != EOF), поскольку использовался оператор ,. Но даже тогда компилятор его не скомпилировал. Итак, как мы можем определить переменную в условном выражении цикла while?
«так же, как мы можем определить в цикле for?»: То, что вы написали в примерах, тоже не работает с for. В цикле for предложение init (которое может быть объявлением переменной) отделяется от условия ;, а не ,. Наличие объявления внутри выражения, как в (int c = getchar()) != EOF, совершенно невозможно в синтаксисе языка. ChatGPT предлагает вам ерунду.
ОТ: Почему вам нужно/хотите использовать while() вместо очевидного for(), которое является одновременно идиоматическим и синтаксически правильным?
«Чат GPT 4.0 и Perplexity.ai предложили…» Они не заменяют учебные материалы. Они действительно не умеют программировать. Изучение языка программирования методом проб и ошибок, скорее всего, приведет к большому разочарованию.





Цикл while (6.8.5.1) ожидает управляющее выражение (6.5), но int c = getchar() — это объявление с инициализатором (6.7). В C объявление не является выражением. Вы можете использовать оператор запятая в управляющем выражении в следующих строках:
#include <stdio.h>
int main() {
{ // scope of the variable c
int c;
while(c = getchar(), c != EOF)
printf("%c", c);
}
}
Первая часть for-цикла — это предложение, которое разрешает объявления (6.8.5.3), и вы объявляете несколько переменных одного типа, разделяя их запятой:
for(int c, y, a; ...)
По моему мнению, присваивание в управляющем выражении труднее читать, поэтому я предпочитаю более простые конструкции, такие как:
#include <stdio.h>
int main() {
for(;;) {
int c = getchar();
if (c == EOF) break;
printf("%c", c);
}
}
Я не согласен с предложенной организацией последнего примера (с использованием for (;;)). Это мнение, но я бы не рекомендовал его для общего использования.
@JonathanLeffler Спасибо за ваш комментарий. Мне казалось, что совершенно ясно (дальше переработано), что этим предложением я выражаю свое мнение; предпочтение более простым конструкциям, чем присваивание в управляющем выражении while или дублирующем вызове getchar() при использовании for-цикла.
Нет. Это запрещено синтаксисом языка, но GCCкомпилятор (а также clang) допускает это как расширение, известное как выражение оператора .
Выражение оператора GCC позволяет вам использовать локальные переменные внутри выражения. Возьмем ваш пример кода в качестве примера: мы можем объявить локальную переменную c в выражении цикла while при использовании компилятора GCC, но она не будет доступна в теле цикла, поскольку она доступна только внутри выражения.
Используя расширение выражения оператора GCC, ваш пример кода можно записать так:
#include <stdio.h>
int main() {
while(({int c = getchar(); c == EOF ? 0 : putchar(c);}))
;
return 0;
}
@AllanWind Это вопрос ОП, как мы можем определить переменную в условном выражении цикла while? - что запрещено на C языке. В своем посте я предоставил подробную информацию о расширении компилятора gcc, которое можно использовать для выполнения того, что хочет ОП, и оно имеет некоторые ограничения. Последнее - лучше с точки зрения чего?
Легче рассуждать об истине, чем лживое выражение. На самом деле мои вопросы были только для того, чтобы помочь вам улучшить свой ответ.
@AllanWind Включено ваше предложение. Спасибо.
Синтаксис оператора while не позволяет объявлять переменные в управляющем выражении (это выражение, а не объявление). Вместо этого вы можете использовать цикл for, хотя код будет повторяться:
/* ^^ preceding code ^^ */
for (int c = getchar(); c != EOF; c = getchar())
/* loop statement */;
Если повторение вызова getchar() недопустимо и переменная c должна быть изолирована, тогда цикл while можно поместить внутри включающего блока, определяющего переменную c:
/* ^^ preceding code ^^ */
{
/* local declarations for the loop */
int c;
while ((c = getchar()) != EOF)
/* loop statement */;
}
Другой вариант, упомянутый в других ответах, — использовать бесконечный цикл с условным оператором break для завершения цикла.
Потому что синтаксис языка допускает одно, но не другое.