Операции увеличения и уменьшения
В языке "C" предусмотрены две необычные операции для увеличения и уменьшения значений переменных. Операция увеличения ++ добавляет 1 к своему операнду, а операция уменьшения -- вычитает 1. Мы часто использовали операцию ++ для увеличения переменных, как, например, в
if(c == '\n') ++i;
Необычный аспект заключается в том, что ++ и -- можно использовать либо как префиксные операции (перед переменной, как в ++n), либо как постфиксные (после переменной: n++). Эффект в обоих случаях состоит в увеличении n. Но выражение ++n увеличивает переменную n до использования ее значения, в то время как n++ увеличивает переменную n после того, как ее значение было использовано. Это означает, что в контексте, где используется значение переменной, а не только эффект увеличения, использование ++n и n++ приводит к разным результатам. Если n = 5, то
х = n++;
устанавливает х равным 5, а
х = ++n;
полагает х равным 6. В обоих случаях n становится равным 6. Операции увеличения и уменьшения можно применять только к переменным; выражения типа х=(i+j)++ являются незаконными.
В случаях, где нужен только эффект увеличения, а само значение не используется, как, например, в
if ( c == '\n' ) nl++;
выбор префиксной или постфиксной операции является делом вкуса. но встречаются ситуации, где нужно использовать именно ту или другую операцию. Рассмотрим, например, функцию squeeze(s,c), которая удаляет символ 'с' из строки s, каждый раз, как он встречается.
squeeze(s,c) /* delete all c from s */ char s[]; int c; { int i, j;
for ( i = j = 0; s[i] != '\0'; i++) if ( s[i] != c ) s[j++] = s[i]; s[j] = '\0'; }
Каждый раз, как встречается символ, отличный от 'с', он копируется в текущую позицию j, и только после этого j увеличивается на 1, чтобы быть готовым для поступления следующего символа. Это в точности эквивалентно записи
if ( s[i] != c ) { s[j] = s[i]; j++; }
Другой пример подобной конструкции дает функция getline, которую мы запрограммировали в лекции №1, где можно заменить
if ( c == '\n' ) { s[i] = c; ++i; }
более компактной записью
if ( c == '\n' ) s[i++] = c;
В качестве третьего примера рассмотрим функцию strcat(s,t), которая приписывает строку t в конец строки s, образуя конкатенацию строк s и t. При этом предполагается, что в s достаточно места для хранения полученной комбинации.
strcat(s,t) /* concatenate t to end of s */ char s[], t[]; /* s must be big enough */ { int i, j;
i = j = 0; while (s[i] != '\0') / *find end of s */ i++; while((s[i++] = t[j++]) != '\0') /*copy t*/ ; }
Tак как из t в s копируется каждый символ, то для подготовки к следующему прохождению цикла постфиксная операция ++ применяется к обеим переменным i и j.
Упражнение 2-3
Напишите другой вариант функции squeeze(s1,s2), который удаляет из строки s1 каждый символ, совпадающий с каким-либо символом строки s2.
Упражнение 2-4
Напишите программу для функции any(s1,s2), которая находит место первого появления в строке s1 какого-либо символа из строки s2 и, если строка s1 не содержит символов строки s2, возвращает значение -1.