Книга: Язык программирования Си. Издание 3-е, исправленное
2.8 Операторы инкремента и декремента
2.8 Операторы инкремента и декремента
В Си есть два необычных оператора, предназначенных для увеличения и уменьшения переменных. Оператор инкремента ++ добавляет 1 к своему операнду, а оператор декремента -- вычитает 1. Мы уже неоднократно использовали ++ для наращивания значения переменных, как, например, в
if (c == 'n')
++nl;
Необычность операторов ++ и -- в том, что их можно использовать и как префиксные (помещая перед переменной: ++n), и как постфиксные (помещая после переменной: n++) операторы. В обоих случаях значение n увеличивается на 1, но выражение ++n увеличивает n до того, как его значение будет использовано, а n++ - после того. Предположим, что n содержит 5, тогда
x = n++;
установит x в значение 5, а
x = ++n;
установит x в значение 6. И в том и другом случае n станет равным 6. Операторы инкремента и декремента можно применять только к переменным. Выражения вроде (i+j)++ недопустимы.
Если требуется только увеличить или уменьшить значение переменной (но не получить ее значение), как например
if (c=='n')
nl++;
то безразлично, какой оператор выбрать - префиксный или постфиксный. Но существуют ситуации, когда требуется оператор вполне определенного типа. Например, рассмотрим функцию squeeze(s, c), которая удаляет из строки s все символы, совпадающие с c:
/* squeeze: удаляет все c из s*/
void squeeze(char s[], int с)
{
int i, j;
for (i = j =0; s[i] != ''; i++)
if (s[i] != c)
s[j++] = s[i];
s[i] = '';
}
Каждый раз, когда встречается символ, отличный от c, он копируется в текущую j-ю позицию, и только после этого переменная j увеличивается на 1, подготавливаясь таким образом к приему следующего символа. Это в точности совпадает со следующими действиями:
if (s[i] != с)
{
s[j] = s[i];
j++;
}
Другой пример - функция getline, которая нам известна по главе 1. Приведенную там запись
if (c =='n') {
s[i] = c;
++i;
}
можно переписать более компактно:
if (с == 'n')
s[i++] = с;
В качестве третьего примера рассмотрим стандартную функцию strcat(s,t), которая строку t помещает в конец строки s. Предполагается, что в s достаточно места, чтобы разместить там суммарную строку. Мы написали strcat так, что она не возвращает никакого результата. На самом деле библиотечная strcat возвращает указатель на результирующую строку.
/* strcat: помещает t в конец s; s достаточно велика */
void strcat (char s[], char t[])
{
int i, j;
i = j = 0;
while (s[i] != '') /* находим конец s */
i++;
while ((s[i++] = t[j++]) != '') /* копируем t */
;
}
При копировании очередного символа из 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.1 Имена переменных
- 2.2 Типы и размеры данных
- 2.3 Константы
- 2.4 Объявления
- 2.5 Арифметические операторы
- 2.6 Операторы отношения и логические операторы
- 2.7 Преобразования типов
- 2.8 Операторы инкремента и декремента
- 2.9 Побитовые операторы
- 2.10 Операторы и выражения присваивания
- 2.11 Условные выражения
- 2.12 Приоритет и очередность вычислений
- Арифметические операторы
- А7.4.1. Префиксные операторы инкремента и декремента
- Операции инкремента и декремента
- 5. Операции, выражения и операторы
- Операторы
- A7.3.4. Постфиксные операторы инкремента и декремента
- А7.4. Унарные операторы
- 1.2.4. Операторы и приоритеты
- Условные операторы
- Поразрядные операторы
- Логические операторы
- Выполняемые операторы