Язык Си - руководство для начинающих - M. УЭИТ
Шрифт:
Интервал:
Закладка:
(ch = getchar( )) != EOF
Сами операции отношения можно разбить на две группы в соответствии с назначенными приоритетами:
группа операций более высокого приоритета: < <= => >
группа операций более низкого приоритета: = = !=
Подобно большинству остальных операций операции отношения выполняются слева направо. Поэтому под записью:
ех != wye == zee
подразумевается
(ex != wye) == zee
Следовательно, в соответствии с правилами языка Си сначала проверяется, равны ли значения переменных ех и wye. Результирующая величина, равная 1 или 0 (истина или ложь), затем сравнивается со значением zee. Мы не видим реальной необходимости использовать подобного сорта конструкцию, но считаем своим долгом указать на возможные следствия принятого порядка выполнения операций.
Читателю, озабоченному сохранением своего высокого приоритета, хотим напомнить, что полный список всех операций вместе с их приоритетами приведен в приложении В в конце книги.
Резюме: операции отношения и выражения
1. Операции отношения
С помощью каждой из приведенных ниже операции величина слева от знака сравнивается с величиной справа от него:
2. Больше
3. Больше или равно
4. Равно
5. Меньше или равно
6. Меньше
7. Не равно
УСЛОВHЫЕ ВЫРАЖЕНИЯ
Понятие условное выражение состоит из знака операции отношения и операндов, расположенных слева и справа от него. Если отношение истинно, значение условного выражения равно 1, если отношение ложно, значение условного выражения равно 0.
Примеры:
Отношение 5 > 2: истинно и имеет значение 1.
Отношение (2 + а) = = а: ложно и имеет значение 0.
ЛОГИЧЕСКИЕ ОПЕРАЦИИ
Иногда бывает полезным объединить два или более условных выражения. Например, предположим, нам требуется программа, которая подсчитывает только "непустые" символы, т. е. мы хотим знать число символов, не являющихся пробелами, символами "новая строка" и табуляции. Для этого мы можем использовать "логические" операции. Ниже приводится короткая программа иллюстрирующая этот способ подсчета:
/* число символов */
/* подсчитывает не пустые символы */
main( )
{
int ch;
int charcount = 0;
while ((ch = getchar( )) != EOF)
if(ch !=' ' && ch ='n' && ch != 't') charcount++;
printf(" Всего %d непустых символов. n", charcount);
}
Так же как это обычно происходило в наших предыдущих программах, данная программа начинает свое выполнение с чтением символа и проверки, является ли он признаком конца файла. Дальше появляется нечто новое - оператор, использующий логическую операцию "и", обозначаемую &&. Смысл действий, осуществляемых оператором if в данном случае, можно пояснить следующим образом:
Если прочитанный символ не пробел, И не символ "новая строка", И не символ табуляции, то происходит увеличение значения переменной charcount на единицу.
Все выражение будет истинным, если указанные три условия истинны. Логические операции имеют меньший приоритет, чем операции отношения, поэтому не было необходимости использовать дополнительные скобки для выделения подвыражений.
В языке Си имеются три логические операции:
Операция Смысл && И || ИЛИ ! НЕПредположим, что expl и ехр2 - два простых условных выражения типа cat > rat или debt = = 1000. Тогда:
1. expl && ехр2: истинно в том и только в том случае, когда оба выражения expl и ехр2 истинны.
2. expl || ехр2: истинно в том случае, если какое-нибудь из выражений expl или ехр2 истинно или оба истинны.
3. !expl: истинно, если выражение expl ложно, и наоборот.
Ниже приведено несколько конкретных примеров:
5 > 2 && 4 > 7: ложно, поскольку истинно только одно подвыражение.
5 > 2 || 4 > 7: истинно, поскольку по крайней мере одно из подвыражений истинно.
!(4 > 7): истинно, потому что 4 не больше 7.
Последнее выражение к тому же эквивалентно следующему:
4 < = 7.
Если вы совсем не знакомы с логическими операциями или испытываете трудности при работе с ними, помните, что практика && время = = совершенство.
Приоритеты
Операция ! имеет очень высокий приоритет, он выше, чем у умножения, такой же, как у операций увеличения, и только круглые скобки имеют более высокий приоритет. Приоритет операции && больше чем операции ||, а обе они имеют более низкий приоритет, чем операции отношения, но более высокий, чем операция присваивания. Поэтому выражение:
а > b && b > c || b > d
интерпретировано так:
((a > b) && (b > с)) || (b > d)
т. е. b содержится между с и а или b больше d.
Порядок вычислений
Обычно в языке Си не определяется, какие части сложного выражения будут вычисляться вначале. Например, в операторе:
apples = (5 + 3)*(9 + 6);
выражение 5 + 3 может быть вычислено до вычисления выражения 9 + 6, или наоборот (Приоритеты, присвоенные операциям гарантатируют, что оба выражения будут вычислены перед выполнением операции умножения.) Эта неопределенность была оставлена в языке, чтобы создатели компилятора имели возможность в конкретной системе осуществлять наиболее эффективный выбор. Исключением из этого правила (или его нарушением) является выполнение логических операций. Язык Си гарантирует, что логические выражения вычисляются слева направо. Более того, гарантируется также, что, как только обнаруживается элемент, значение которого устанавливает ложность всего выражения как целого, вычисление данного выражения прекращается. Это дает возможность использовать конструкции типа:
while((c = getchar( )) != EOF && с != 'n')
В результате вычисления первого подвыражения переменная с получает свое значение, которое затем можно использовать во втором подвыражении. Если бы такой порядок вычислений не гарантировался, при выполнении программы компьютер, возможно, проверял бы истинность второго выражения перед нахождением значения переменной с.
Приведем еще один пример:
if (number !=0 && 12/number ==2) printf(" Число равно 5 или 6.n" );
Если значение переменной number равно 0, то все выражение ложно, и поэтому дальнейшее вычисление данного условного выражения прекращается. Это избавляет компьютер от последствий деления на нуль. Многие языки не обеспечивают выполнения подобного требования, и, выяснив, что number равно 0, компьютер переходит к проверке следующего условия.
Резюме: логические операции и выражения
1. ЛОГИЧЕСКИЕ ОПЕРАЦИИ
Операндами логических операций обычно являются условные выражения. У операции != имеется только один операнд. Остальные имеют по два - один слева от знака и другой справа от него.
&& И|| ИЛИ! НЕ
II. ЛОГИЧЕСКИЕ ВЫРАЖЕНИЯ
выражение1 && выражение2: истинно тогда и только тогда, когда оба выражения истинны
выражение1 || выражение2: истинно, если какое-нибудь одно или оба выражения истинны
!выражение: истинно, если выражение ложно, и на оборот
ПОРЯДОК ВЫЧИСЛЕНИИ
Логические выражения вычисляются слева направо; вычисления прекращаются, как только устанавливается истинность или ложность всего выражения.
ПРИМЕРЫ
Выражение: 6 > 2 && 3 = = 3: истинно
Выражение: !(6 > 2 && 3 = = 3): ложно
Выражение: х != 0 && 20/х < 5: второе выражение вычисляется только при условии, что х не равен нулю.
ПРОГPAMMA ПОДСЧЕТА СЛОВ
Теперь у нас есть возможности для написания программы подсчета числа слов в тексте. (Она может также подсчитывать символы строки.) Решающим моментом является разработка способа, с помощью которого программа будет распознавать слова. Мы будем придерживаться сравнительно простого подхода и определим слово как последовательность символов, которая не содержит "пуcтых символов". Поэтому "glymxck" и "r2d2" - это слова. Пeременная word будет использоваться для хранения указания о том, является ли введенный символ частью данного слова или началом следующего. Появление "пустого символа" (которым может быть пробел, табуляция или "новая строка") служит признаком конца слова. Тогда следующий "непустой" символ будет означать начало нового слова, и мы сможем увеличить значение счетчика слов на 1.