Оценка экспрессии в С - PullRequest
0 голосов
/ 04 июля 2011
while ((x[num++] = getchar()) != ' ');

Это читает символ за раз и останавливается, если он встречает пробел. Но как он оценивает скобки с пробелом? Каков результат скобок? Итак, в принципе, каково это (x[num++] = getchar()), чтобы сравнить его с пробелом?

Я нашел этот пример в одной из моих учебников, он был другим, и я получил предупреждение, поэтому я думаю, что это не очень хорошая практика, не так ли? Как проходит оценка? Присваивает ли оно сначала значение чтения для x[num], а затем сравнивает его с пробелом?

while(x[num++] = getchar() != ' ');

Ответы [ 2 ]

3 голосов
/ 04 июля 2011

В C a = b является выражением . Он присваивает b a, а затем возвращает a. Следовательно, условие в цикле while означает:

  1. Позвоните getchar(), чтобы получить ввод пользователя
  2. Назначить результат от getchar до x[num].
  3. Увеличение num на 1
  4. Проверьте, не равен ли x[num] пробел ' '.

1025 * т.е. *

while (true) {
  x[num] = getchar();
  num ++;
  if (!(x[num] != ' '))
    break;
}

Второй пример имеет совершенно другое поведение. Это связано с тем, что выражение != будет оцениваться до присваивания = без скобок. Следовательно, второй пример означает

  1. Позвоните getchar(), чтобы получить ввод пользователя
  2. Проверьте, не равен ли x[num] пробел ' '.
  3. Назначьте результат на шаге 2 (true или false) на x[num]
  4. Увеличение num на 1

Предупреждение состоит в том, что легко ошибочно написать while (a = b), что означает while (a == b).

2 голосов
/ 04 июля 2011

Ни одна из версий не является хорошим кодированием; оба игнорируют возможность достижения EOF перед чтением пробела, и оба игнорируют возможность переполнения буфера перед чтением пробела.

Во-первых, правильно. Содержит назначение:

x[num++] = getchar()

Результатом присваивания является присвоенное значение. Таким образом, если getchar() возвращает «X», результатом присваивания будет «X». Затем результат присваивания сравнивается с пробелом; они разные, и петля повторяется. Если getchar() возвращает пробел, то результатом присваивания также является пробел, и пробел равняется пробелу, поэтому цикл завершается.

Второй явно неисправен. Поскольку присваивание имеет более низкий приоритет, чем !=, в результате код выглядит так:

while (x[num++] = (getchar() != ' '))
    ;

То есть символ читается getchar() и сравнивается с пробелом, генерируя значение 1, если символ не пустой, и 0, если это пустой. Это 0 или 1 присваивается x[num++], а затем оценивается как логическое условие. Если результат был 0, цикл завершается; если результат был 1, цикл продолжается. Обратите внимание, что прочитанные символы не записываются в этой версии - именно поэтому компилятор выдает предупреждение. Это почти всегда ошибка; в тех странных случаях, когда это не является ошибкой, вы можете сказать компилятору, что, предоставив дополнительные скобки, чтобы сделать ваше намерение кристально ясным для компилятора и для вашей человеческой аудитории, других людей, которые будут читать ваш код. (Помните: если вы вернетесь через 6 месяцев или даже через 6 недель, вы будете другим человеком, и у вас могут возникнуть трудности с запоминанием таких тонкостей. Объясните это всем. Необходимо установить тонкий баланс между чрезмерными скобками и код в скобках.)

Код, вероятно, должен читать:

int c;
int max = sizeof(x) - 1;
int num = 0;

while ((c = getchar()) != EOF && num < max && (x[num++] = c) != ' ')
    ;

Обратите внимание, в частности, что c должно быть int, а не char.

...