Выделенное запятыми выражение в цикле while в C - PullRequest
12 голосов
/ 06 декабря 2010

Я никогда раньше не видел такого оператора в то время как .

while(printf("> "), fgets(str, 100, stdin), !feof(stdin)) {
..
..
}

Я читал в Интернете, что условие выхода из цикла while является самым правым [! Feof (stdin)].Тогда какой смысл использовать приведенный выше оператор while в отличие от

while(!feof(stdin))
{
       printf("> ");
       fgets(str, 100, stdin);
       ...
       ...
}

Кроме того, оператор while принимает выражение, так же как и 1,1,1допустимое выражение в C?

Ответы [ 5 ]

17 голосов
/ 06 декабря 2010

Два приведенных цикла не имеют одинакового значения.Используя оператор запятой таким образом, автор смог указать код, который должен выполняться на каждой итерации, даже если сам цикл никогда не вводится.Это больше похоже на цикл do ... while () или что-то вроде следующего:

 printf("> ");
 fgets(str, 100, stdin);
 while(!feof(stdin)) {
    ..
    ..

    printf("> ");
    fgets(str, 100, stdin);
 }
4 голосов
/ 06 декабря 2010

Оператор с запятыми лучше всего рассматривать как оператор. Точно так же, как + является оператором, так что 2 + 3 является выражением (которое может привести к значению 5), так и , является оператором, и, следовательно, 0, 1 является допустимым выражением ( что приводит к значению 1, так как это был последний операнд).

2 голосов
/ 06 декабря 2010

Ваш второй пример имеет поведение, отличное от первого, и содержит ошибку.

Если строка кода:

fgets(str, 100, stdin);

терпит неудачу, потому что это было чтение в конце файла, тогда остальная часть блока будет выполнена.

В первом наборе кода тест feof() выполняется после fgets(), который вызывает условие EOF, поэтому блок while() не будет выполнен.

Поскольку fgets() возвращает NULL, если он достиг EOF (и не считал данные в буфер), я мог бы закодировать цикл как:

while (fgets(str, 100, stdin)) {
    printf("> ");

    // ...
}

, который по-прежнему немного отличается по поведению (будет напечатано на один ">" меньше). Если бы это было важно, я бы поставил дополнительный экземпляр этого printf() перед циклом.

В общем, поскольку это имеет тенденцию вызывать путаницу, я бы избегал оператора запятой, за исключением случаев, когда он действительно, действительно необходим или где он не вызовет путаницы. Например, он иногда используется в предложениях цикла for не путающим образом, чтобы позволить нескольким переменным обновляться на каждой итерации цикла.

2 голосов
/ 06 декабря 2010

Ваша предложенная модификация не эквивалентна.Это:

while (1) {
  printf("> ");
  fgets(str, 100, stdin);
  if (feof(stdin)) { break; }
  ...
  ...
}

Я бы предложил вместо этого разбить работу на функцию:

int get_input(char* buffer, int size) {
  printf("> ");
  fgets(buffer, size, stdin);
  return !feof(stdin);
}

while (get_input(str, 100)) {
  ...
  ...
} 
1 голос
/ 18 октября 2017
while(printf("> "), fgets(str, 100, stdin), !feof(stdin)) {
..
..
}

Запятые внутри некоторое время ведут себя примерно так:

int feof_wrapper(FILE * stream)
{
   printf("> ");
   fgets(str, 100, stream);
   return feof(stream);
}

while(!feof_wrapper(stdin)) {
..
..
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...