Главная · Поиск книг · Поступления книг · Top 40 · Форумы · Ссылки · Читатели

Настройка текста
Перенос строк


    Прохождения игр    
Demon's Souls |#13| Storm King
Demon's Souls |#12| Old Monk & Old Hero
Demon's Souls |#11| Мaneater part 2
Demon's Souls |#10| Мaneater (part 1)

Другие игры...


liveinternet.ru: показано число просмотров за 24 часа, посетителей за 24 часа и за сегодня
Rambler's Top100
Образование - Керниган, Ричи Весь текст 454.51 Kb

Язык Си

Предыдущая страница Следующая страница
1 ... 3 4 5 6 7 8 9  10 11 12 13 14 15 16 ... 39
    Упражнение 2-2
   ---------------
    Составьте программу для функции HTOI(S), которая преоб-
разует строку шестнадцатеричных цифр в эквивалентное ей це-
лое значение. При этом допустимыми цифрами являются цифры от
1 до 9 и буквы от а до F.

     2.8. Операции увеличения и уменьшения

    В языке "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), которая приписывает строку т в конец строки S,
образуя конкатенацию строк S и т. При этом предполагается,
что в 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.

     2.9. Побитовые логические операции

    В языке предусмотрен ряд операций для работы с битами;
эти операции нельзя применять к переменным типа FLOAT или
DOUBLE.

 &    Побитовое AND
 \!    Побитовое включающее OR
 ^    побитовое исключающее OR
 <<    сдвиг влево
 >>    сдвиг вправо
 \^    дополнение (унарная операция)

"\" иммитирует вертикальную черту.

Побитовая операция AND часто используется для маскирования
некоторого множества битов; например, оператор

   C = N & 0177
передает в 'с' семь младших битов N , полагая остальные рав-
ными нулю. Операция 'э' побитового OR используется для вклю-
чения битов:

   C = X э MASK

устанавливает на единицу те биты в х , которые равны единице
в MASK.
    Следует быть внимательным и отличать побитовые операции
& и 'э' от логических связок && и \!\! , Которые подразуме-
вают вычисление значения истинности слева направо. Например,
если х=1, а Y=2, то значение х&Y равно нулю , в то время как
значение X&&Y равно единице./почему?/
    Операции сдвига << и >> осуществляют соответственно
сдвиг влево и вправо своего левого операнда на число битовых
позиций, задаваемых правым операндом. Таким образом , х<<2
сдвигает х влево на две позиции, заполняя освобождающиеся
биты нулями, что эквивалентно умножению на 4. Сдвиг вправо
величины без знака заполняет освобождающиеся биты на некото-
рых машинах, таких как PDP-11, заполняются содержанием зна-
кового бита /"арифметический сдвиг"/, а на других - нулем
/"логический сдвиг"/.
    Унарная операция \^ дает дополнение к целому; это озна-
чает , что каждый бит со значением 1 получает значение 0 и
наоборот. Эта операция обычно оказывается полезной в выраже-
ниях типа

   X & \^077

где последние шесть битов х маскируются нулем. Подчеркнем,
что выражение X&\^077 не зависит от длины слова и поэтому
предпочтительнее, чем, например, X&0177700, где предполага-
ется, что х занимает 16 битов. Такая переносимая форма не
требует никаких дополнительных затрат, поскольку \^077 явля-
ется константным выражением и, следовательно, обрабатывается
во время компиляции.
    Чтобы проиллюстрировать использование некоторых операций
с битами, рассмотрим функцию GETBITS(X,P,N), которая возвра-
щает /сдвинутыми к правому краю/ начинающиеся с позиции р
поле переменной х длиной N битов. мы предполагаем , что
крайний правый бит имеет номер 0, и что N и р - разумно за-
данные положительные числа. например, GETBITS(х,4,3) возвра-
щает сдвинутыми к правому краю биты, занимающие позиции 4,3
и 2.

 GETBITS(X,P,N)  /* GET N BITS FROM POSITION P */
 UNSIGNED X, P, N;
  {
    RETURN((X >> (P+1-N)) & \^(\^0 << N));
  }

Операция X >> (P+1-N) сдвигает желаемое поле в правый конец
слова. Описание аргумента X как UNSIGNED гарантирует, что
при сдвиге вправо освобождающиеся биты будут заполняться ну-
лями, а не содержимым знакового бита, независимо от того, на
какой машине пропускается программа. Все биты константного
выражения \^0 равны 1; сдвиг его на N позиций влево с по-
мощью операции \^0<Упражнение 2-5
    ---------------
    Переделайте GETBITS таким образом, чтобы биты отсчитыва-
лись слева направо.

    Упражнение 2-6
    ---------------
    Напишите программу для функции WORDLENGTH(), вычисляющей
длину слова используемой машины, т.е. Число битов в перемен-
ной типа INT. Функция должна быть переносимой, т.е. Одна и
та же исходная программа должна правильно работать на любой
машине.

    Упражнение 2-7
    ---------------
    Напишите программу для функции RIGHTROT(N,B), сдвигающей
циклически целое N вправо на B битовых позиций.

    Упражнение 2-8
    ---------------
    Напишите программу для функции INVERT(X,P,N), которая
инвертирует (т.е. Заменяет 1 на 0 и наоборот) N битов X, на-
чинающихся с позиции P, оставляя другие биты неизмененными.

     2.10. Операции и выражения присваивания

    Такие выражения, как

I = I + 2

в которых левая часть повторяется в правой части могут быть
записаны в сжатой форме

I += 2

используя операцию присваивания вида +=.
    Большинству бинарных операций (операций подобных +, ко-
торые имеют левый и правый операнд) соответствует операция
присваивания вида оп=, где оп - одна из операций

+  - *  /  %  <<  >>  &  \^  \!

Если е1 и е2 - выражения, то
е1 оп= е2

эквивалентно

е1 = (е1) оп (е2)

за исключением того, что выражение е1 вычисляется только
один раз. Обратите внимание на круглые скобки вокруг е2:

X *= Y + 1

то

X = X * (Y + 1)

не

X = X * Y + 1

    В качестве примера приведем функцию BITCOUNT, которая
подсчитывает число равных 1 битов у целого аргумента.

BITCOUNT(N)   /* COUNT 1 BITS IN N */
UNSIGNED N;
(
INT B;
FOR (B = 0; N != 0; N >>= 1)
   IF (N & 01)
           B++;
RETURN(B);
)

    Не говоря уже о краткости, такие операторы приваивания
имеют то преимущество, что они лучше соответствуют образу
человеческого мышления. Мы говорим: "прибавить 2 к I" или
"увеличить I на 2", но не "взять I, прибавить 2 и поместить
результат опять в I". Итак, I += 2. Кроме того, в громоздких
выражениях, подобных

 YYVAL[YYPV[P3+P4] + YYPV[P1+P2]] += 2

Tакая операция присваивания облегчает понимание программы,
так как читатель не должен скрупулезно проверять, являются
ли два длинных выражения действительно одинаковыми, или за-
думываться, почему они не совпадают. Такая операция присваи-
вания может даже помочь компилятору получить более эффектив-
ную программу.
    Мы уже использовали тот факт, что операция присваивания
имеет некоторое значение и может входить в выражения; самый
типичный пример
 WHILE ((C = GETCHAR()) != EOF)

присваивания, использующие другие операции присваивания (+=,
-= и т.д.) также могут входить в выражения, хотя это случа-
ется реже.
     Типом выражения присваивания является тип его левого
операнда.

    Упражнение 2-9
    ---------------
     В двоичной системе счисления операция X&(X-1) обнуляет
самый правый равный 1 бит переменной X.(почему?) используйте
это замечание для написания более быстрой версии функции
BITCOUNT.

     2.11. Условные выражения

     Операторы

 IF (A > B)
    Z = A;
 ELSE
    Z = B;

конечно вычисляют в Z максимум из а и в. Условное выражение,
записанное с помощью тернарной операции "?:", предоставляет
другую возможность для записи этой и аналогичных конструк-
ций. В выражении

е1 ? Е2 : е3

сначала вычисляется выражение е1. Если оно отлично от нуля
(истинно), то вычисляется выражение е2, которое и становится
значением условного выражения. В противном случае вычисляет-
ся е3, и оно становится значением условного выражения. Каж-
дый раз вычисляется только одно из выражения е2 и е3. Таким
образом, чтобы положить Z равным максимуму из а и в, можно
написать

Z = (A > B) ? A : B;   /* Z = MAX(A,B) */

    Следует подчеркнуть, что условное выражение действитель-
но является выражением и может использоваться точно так же,
как любое другое выражение. Если е2 и е3 имеют разные типы,
то тип результата определяется по правилам преобразования,
рассмотренным ранее в этой главе. например, если F имеет тип
FLOAT, а N - тип INT, то выражение

(N > 0) ? F : N

Имеет тип DOUBLE независимо от того, положительно ли N или
нет.

    Так как уровень старшинства операции ?: очень низок,
прямо над присваиванием, то первое выражение в условном вы-
ражении можно не заключать в круглые скобки. Однако, мы все
же рекомендуем это делать, так как скобки делают условную
часть выражения более заметной.
    Использование условных выражений часто приводит к корот-
ким программам. Например, следующий ниже оператор цикла пе-
чатает N элементов массива, по 10 в строке, разделяя каждый
столбец одним пробелом и заканчивая каждую строку (включая
последнюю) одним символом перевода строки.

OR (I = 0; I < N; I++)
 PRINTF("%6D%C",A[I],(I%10==9 \!\! I==N-1) ? '\N' : ' ')

Символ перевода строки записывается после каждого десятого
элемента и после N-го элемента. За всеми остальными элемен-
тами следует один пробел. Хотя, возможно, это выглядит муд-
реным, было бы поучительным попытаться записать это, не ис-
пользуя условного выражения.

    Упражнение 2-10
    ---------------
Перепишите программу для функции LOWER, которая переводит
прописные буквы в строчные, используя вместо конструкции
Предыдущая страница Следующая страница
1 ... 3 4 5 6 7 8 9  10 11 12 13 14 15 16 ... 39
Ваша оценка:
Комментарий:
  Подпись:
(Чтобы комментарии всегда подписывались Вашим именем, можете зарегистрироваться в Клубе читателей)
  Сайт:
 
Комментарии (1)

Реклама