Объединение оператора ||
с несколькими значениями, такими как (str[i]=='u'||'o'||'i'||'e'||'a')
или (str[i]==('u'||'o'||'i'||'e'||'a'))
, не используется для проверки, является ли значение одним из набора значений.
Оператор ||
является оператором логического ИЛИ . Он обрабатывает оба своих операнда как логические значения и оценивает их как 0 или 1 в зависимости от операндов. Использование этого оператора подробно описано в разделе 6.5.14 стандарта C :
2 Каждый из операндов должен иметь скалярный тип.
3 Оператор ||
должен выдавать 1, если один из его операндов не равен 0; в противном случае он возвращает 0. Результат имеет тип int
.
4 В отличие от побитового оператора |
, оператор ||
гарантирует оценку слева направо; если вычисляется второй операнд, между оценками первого и второго операндов существует точка последовательности. Если первый операнд сравнивается с неравным 0, второй операнд не оценивается.
Поскольку C не имеет истинного логического типа, любое целочисленное значение (включая символьные константы) может быть операндом ||
. Таким образом, любое ненулевое значение считается истинным, а ноль - ложным. Кроме того, обратите внимание на пункт 4 выше, что этот оператор имеет оценку «короткого замыкания», что означает, что правая сторона не будет оцениваться, если результат оператора известен, просто взглянув на левую сторону.
Теперь давайте применим это к вашим выражениям. Во-первых:
if (str[i]=='u'||'o'||'i'||'e'||'a')
Поскольку здесь мы имеем дело с несколькими операторами, нам нужно применить правила приоритета операторов, детально здесь . Поскольку оператор сравнения на равенство ==
имеет более высокий приоритет, чем оператор логического ИЛИ ||
, он анализируется следующим образом:
if ((str[i]=='u')||'o'||'i'||'e'||'a')
Итак, сначала мы оценим str[i]=='u'
. Это будет 0 или 1 в зависимости от того, str[i]
равно 'u'
или нет. Затем мы оцениваем первое значение ||
, поэтому имеем либо 1||'o'
, либо 0||'o'
.
В первом случае левый операнд равен 1, так как согласно пункту 4 над правой стороной не оценивается, что включает в себя другие операторы ||
, поэтому конечный результат равен 1, т. Е. True, что является желаемым результатом. Во втором случае 0 ложно, поэтому мы смотрим на правую сторону, которая является 'o'
. Это символьная константа, значением которой является значение, используемое для кодирования символа 'o'
. Если ваша система использует ASCII (что наиболее вероятно), это значение равно 111. Поскольку это ненулевое значение, все выражение 0||'o'
оценивается как 1, т.е. Опять же из-за поведения короткого замыкания ||
следующий оператор ||
не оценивается, так как левая сторона истинна. Это означает, что приведенное выше выражение всегда верно.
Теперь переходим ко второму выражению:
if (str[i]==('u'||'o'||'i'||'e'||'a'))
Первое, что оценивается, это 'u'||'o'
. Символ 'u'
имеет код ASCII 117, который не равен нулю, поэтому первый ||
приводит к 1, а правая часть, которая включает в себя остальные операторы ||
, не оценивается. Итак, теперь у вас есть str[i] == 1
. Если str
не содержит непечатаемых символов, вы никогда не найдете символ с кодировкой 1, поэтому это выражение всегда будет иметь значение 0, т. Е. False.
C не имеет встроенного оператора, который проверяет, является ли значение членом набора, что означает, что вам либо нужно явно проверить str[i]
каждый символ:
if ((str[i]=='u') || (str[i]=='o') || (str[i]=='i') || (str[i]=='e') || (str[i]=='a'))
Или вы можете создать массив символов для проверки и циклического просмотра:
char vowels[5] = "aeiou"; // an array of char, but NOT a string
int found = 0;
for (int j = 0; j < sizeof(vowels); j++) {
if (str[i] == vowels[j]) {
found = 1;
break;
}
}
if (found) {
...
Или вы можете использовать strchr
для просмотра значений:
if (strchr("aeiou", str[i]))
Или используйте switch
с падениями:
switch(str[i]) {
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
// do something
break;
default:
// do something else
}