Язык программирования Си. Издание 3-е, исправленное
Шрифт:
Упражнение 2.3. Напишите функцию htol(s), которая преобразует последовательность шестнадцатеричных
2.8 Операторы инкремента и декремента
В Си есть два необычных оператора, предназначенных для увеличения и уменьшения переменных. Оператор инкремента ++ добавляет 1 к своему операнду, а оператор декремента – - вычитает 1. Мы уже неоднократно использовали ++ для наращивания значения переменных, как, например, в
Необычность операторов ++ и -- в том, что их можно использовать и как префиксные (помещая перед переменной: ++n), и как постфиксные (помещая после переменной: n++) операторы. В обоих случаях значение n увеличивается на 1, но выражение ++n увеличивает n до того, как его значение будет использовано, а n++ - после того. Предположим, что n содержит 5, тогда
установит x в значение 5, а
установит x в значение 6. И в том и другом случае n станет равным 6. Операторы инкремента и декремента можно применять только к переменным. Выражения вроде (i+j)++ недопустимы.
Если требуется только увеличить или уменьшить значение переменной (но не получить ее значение), как например
то безразлично, какой оператор выбрать - префиксный или постфиксный. Но существуют ситуации, когда требуется оператор вполне определенного типа. Например, рассмотрим функцию squeeze(s, c), которая удаляет из строки s все символы, совпадающие с c:
Каждый раз, когда встречается символ, отличный от c, он копируется в текущую j-ю позицию, и только после этого переменная j увеличивается на 1, подготавливаясь таким образом к приему следующего символа. Это в точности совпадает со следующими действиями:
Другой пример - функция getline, которая нам известна по главе 1. Приведенную там запись
можно переписать более компактно:
В качестве третьего примера рассмотрим стандартную функцию strcat(s,t), которая строку t помещает в конец строки s. Предполагается, что в s достаточно места, чтобы разместить там суммарную строку.
При копировании очередного символа из t в s постфиксный оператор ++ применяется и к i, и к j, чтобы на каждом шаге цикла переменные i и j правильно отслеживали позиции перемещаемого символа.
Упражнение 2.4. Напишите версию функции squeeze(s1,s2), которая удаляет из s1 все символы, встречающиеся в строке s2.
Упражнение 2.5. Напишите функцию any(s1,s2), которая возвращает либо ту позицию в s1, где стоит первый символ, совпавший с любым из символов в s2, либо -1 (если ни один символ из s1 не совпадает с символами из s2). (Стандартная библиотечная функция strpbrk делает то же самое, но выдает не номер позиции символа, а указатель на символ.)
2.9 Побитовые операторы
В Си имеются шесть операторов для манипулирования с битами. Их можно применять только к целочисленным операндам, т. е. к операндам типов char, short, int и long, знаковым и беззнаковым.
Оператор & (побитовое И) часто используется для обнуления некоторой группы разрядов. Например
обнуляет в n все разряды, кроме младших семи.
Оператор | (побитовое ИЛИ) применяют для установки разрядов; так,
устанавливает единицы в тех разрядах x, которым соответствуют единицы в SET_ON.
Оператор ^ (побитовое исключающее ИЛИ) в каждом разряде установит 1, если соответствующие разряды операндов имеют различные значения, и 0, когда они совпадают.
Поразрядные операторы & и | следует отличать от логических операторов && и ||, которые при вычислении слева направо дают значение истинности. Например, если x равно 1, а y равно 2, то x & y даст нуль, а x && y - единицу.
Операторы ‹‹ и ›› сдвигают влево или вправо свой левый операнд на число битовых позиций, задаваемое правым операндом, который должен быть неотрицательным. Так, x ‹‹ 2 сдвигает значение x влево на 2 позиции, заполняя освобождающиеся биты нулями, что эквивалентно умножению x на 4. Сдвиг вправо беззнаковой величины всегда сопровождается заполнением освобождающихся разрядов нулями. Сдвиг вправо знаковой величины на одних машинах происходит с распространением знака ("арифметический сдвиг"), на других - с заполнением освобождающихся разрядов нулями ("логический сдвиг").