Читать интересную книгу Язык Си - руководство для начинающих - M. УЭИТ

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 18 19 20 21 22 23 24 25 26 ... 98

     Во-первых, компактная форма делает ваши программы более изящными и легкими для понимания. Эти операции придают им блеск, что приятно само по себе.

Например, мы можем переписать часть программы "размер обуви2" следующим образом.

size = 3.0;

while(size < 18.5) {foot = SCALE*size + OFFSET;printf("%10.1f %20.2f дюймовn", size, foot);++size;}

     При этом способе мы еще не воспользовались всеми преимуществами операции увеличения. Мы можем сократить данный фрагмент так

size = 2.0;while(++size < 18.5) {

foot = SCALE *size + OFFSET;

printf( %10.1f  %20.2f дюймаn" , size, foot);

 }

     Здесь мы объединили в одном выражении операцию увеличения переменной на 1 и проверку истинности условия в операции while. Подобного типа конструкция настолько часто встречается в языке Си, что заслуживает более подробного рассмотрения. Во-первых, как она работает. Очень просто значение переменной size увеличивается на единицу, а затем сравнивается с 18.5. Если оно меньше, то выполняются операторы, заключенные в фигурные скобки. После этого переменная size увеличивается на единицу один раз и т. д. Данный цикл повторяется до тех пор, пока значение переменной size не станет слишком большим. Мы изменили значение переменной size с 3.0 на 2.0, чтобы скомпенсировать увеличение переменной size перед ее первоначальным использованием для вычисления переменной foot.

  

                                                        РИС. 5.4. Выполнение одного шага цикла

     Во-первых, чем нас привлекает этот способ? Своей компактноcтью. Кроме того (что еще более важно), с его помощью можно объединить в одном выражении два процесса, управляющие циклом. Первый процесс - это проверка, можно продолжать или нет? В данном случае проверяется, меньше ли размер обуви 18.5. Второй процесс заключается в изменении переменной, значение которой проверяется, - в данном случае размер обуви увеличивается на 1. Предположим, мы забыли изменить ее значение. Тогда переменная size всегда будет меньше 18.5, и выполнение цикла никогда не закончится. При выполнении программы компьютер, "пойманный в бесконечный цикл", будет выводить на печать одну за другой идентичные строки. В конце концов вы можете потерять интерес, ожидая результатов, и должны будете каким-то образом прекратить выполнение программы. Наличие проверки и изменения параметра цикла в одном выражении помогает программистам не забывать вводить в программу коррекцию параметра цикла.

     Дополнительное преимущество использования операции увеличения заключается в том, что обычно в результате компиляции получается несколько более эффективный объектный код, поскольку она идентична соответствующей машинной команде.

     И, наконец, эти операции имеют еще одну особенность, которую можно использовать в ряде затруднительных ситуаций. Чтобы узнать, что это за особенность, попробуйте выполнить следующую программу:

main( )

{

int a = 1, b = 1;

int aplus, plusb;

aplus = a++;  /* постфикснаяформа*/

plusb = ++b; /* префикснаяформа*/

printf(" a aplus b plusb n");

printf("%5d %5d %5d %5dn", a, aplus, b, plusb);

}

     Если вы все сделали правильно, то, насколько мы помним, в качестве результата вы должны получить следующие строки

а   aplus   b   plusb

2   1         2    2

     Как и предполагалось, значения обеих переменных, а и b, увеличились на 1. Однако переменной aplus значение а было присвоено перед изменением а, в то время как переменной plusb значение b было присвоено после изменения b. В этом и заключается разница между префиксной и постфиксной формами.

aplus = а++ - постфикс: переменная а изменяется после того как ее значение используется

plusb = ++b - префикс: переменная b изменяется перед тем как ее значение используется

  

                                                   РИС. 5.5. Префиксная и постфиксная формы.

     В тех случаях, когда одна из этих операций увеличения используется сама по себе, как, например, в операторе ego++, не имеет значения, какой формой вы пользуетесь. Выбор приобретает смысл, когда операция, и ее операнд являются частью некоторого "высшего" выражения, как, например, в операторах присваивания, которые мы только что рассматривали. В подобной ситуации необходимо иметь представление о результате, который вам хотелось бы получить. Напомним, например, следующий оператор:

while(++size < 18.5)

     При его использовании мы получили таблицу перевода вплоть до размера 18. Но, если бы мы вместо этого записали операцию увеличения в виде size++, в таблицу попал бы и размер 19, поскольку значение переменной size увеличивалось бы после сравнения, а не до этого.

     Конечно, вы могли бы использовать менее красивый способ - оператор присваивания

size = size +1;

     Тогда никто не поверит вам, что вы умеете по-настоящему программировать на языке Си.

     Думаем, что при чтении книги вы уже обратили внимание на приведенные примеры использования операций увеличения. Как вы думаете, могли ли мы всегда пользоваться любой из них или внешние условия диктовали нам конкретный выбор? Говоря о примерах, нам необходимо привести еще один.

     Спят ли когда-нибудь компьютеры? Конечно, спят, но они обычно не рассказывают нам об этом. Программа, приведенная ниже показывает, что происходит в действительности.

/* овцы */

#define MAX 40

main( )

 {

 int count = 0,

printf(" Я считаю овец, чтобы уснуть n");

while(++ count < MAX)

printf(" %d миллионов овец, а я еще не уснул n", count);

printf(" %d миллионов овец, а я хр-р-р р   n" , count);

}

     Попробуйте выполнить ее и посмотрите, работает ли она так, как должна по вашему мнению. Конечно, значение константы МАХ для вашего компьютера можно взять другим. (Кстати, что произойдет при замене префиксной формы операции увеличения постфиксной формой?)

Операция уменьшения: --

     Каждой операции увеличения соответствует некоторая операция уменьшения, при этом вместо символов ++ мы используем --

-- count, /* префиксная форма операции уменьшения */

count --, /* постфиксная форма операции уменьшения */

     Ниже приводится пример, иллюстрирующий, как машины могут быть законченными лириками

/* бутылки*/

#define MAX 100

main( )

 {

int count = MAX + 1;

while(--  count > 0)

 {

     printf(" %d бутылок пива на полке, %d бутылок пива!n", count, count);

    printf(" Сними одну и пусти ее по кругу, n");

    printf("%d бутылок пива! n n", count-1); }}

Начальные результаты выглядят так:

100 бутылок пива на полке, 100 бутылок пива!

Сними одну и пусти ее по кругу,

99 бутылок пива!

99 бутылок пива на полке, 99 бутылок пива!

Сними одну и пусти ее по кругу,98 бутылок пива!

Постепенно количество бутылок сходит на нет, и программа завершит свою работу следующим образом

1 бутылок пива на полке, 1 бутылок пива!

Сними одну и пусти ее по кругу,

0 бутылок пива!

     По-видимому, у нашего законченного лирика имеются трудности со склонением существительных с количественными числительными, но это можно устранить, используя условные операторы, показываемые в гл. 7. Необходимо заметить, что смысл операции > словами выражается как "больше". Так же как и операция <, она является "операцией отношения". Подробнее операции отношения мы рассмотрим внизу.

Старшинство операций

     В соответствии с принятым в языке Си порядком вычислений операции увеличения и уменьшения имеют очень высокий уровень старшинства; только круглые скобки обладают более высоким приоритетом. Поэтому выражение x*y++ означает (x)*(y++), а не (x*y)++, что очень удобно, поскольку последнее выражение смысла не имеет. (Операции увеличения и уменьшения применяются к переменной, в то время как произведение х*у само по себе не является переменной в отличие от сомножителей).

1 ... 18 19 20 21 22 23 24 25 26 ... 98
На этом сайте Вы можете читать книги онлайн бесплатно русская версия Язык Си - руководство для начинающих - M. УЭИТ.

Оставить комментарий