Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ЛЕКЦИИ_ПО_ПРОГРАММИРОВАНИЮ_ПРЕПОД_3403_220301.doc
Скачиваний:
27
Добавлен:
06.11.2018
Размер:
845.31 Кб
Скачать

7.1 Арифметические операции

(сложение +, вычитание - ,умножение * , деление / ).

/* ПРОГРАММА:

shoes_1.c – однократное вычисление размера обуви (операции присваивания, сложения, умножения).

*/

/*#############################################*/

/*============================= include */

#include<stdio.h>

/*============================= define */

#define OFFSET 7.64

#define SCALE 0.325

/*============================= main() */

main()

{/*.---------------------------.begin main() */

/* пересчет размера обуви в размер ноги в дюймах */

float shoe; /* размер обуви мужской*/

float foot; /* размер мужской ноги в дюймах */

shoe =4.0; /* операция присваивания */

foot = SCALE*shoe + OFFSET; /* переводная формула */

printf(" Размер обуви Размер ноги\n"),

printf(" %10.lf %13.2f дюйм\n" , shoe, foot),

return 0;

}/*.---------------------------.end main() */

/*#############################################*/

РЕЗУЛЬТАТ РАБОТЫ ПРОГРАММЫ.

Размер обуви Размер ноги

4.0 8.94 дюйм

ПОЯСНЕНИЯ К ПРОГРАММЕ.

  • В этой программе выполняется умножение и сложение, т.е. берется размер обуви (например, 4.0), а вычисляется длина стопы в дюймах.

  • Вычисление производится однократно.

***************************************************************

/* ПРОГРАММА:

shoes_2.c – многократное вычисление размеров обуви (использование цикла while).

*/

/*#############################################*/

/*============================= include */

#include<stdio.h>

/*============================= define */

#define OFFSET 7.64

#define SCALE 0.325

/*============================= main() */

main()

{/*.---------------------------.begin main() */

/* пересчет размера обуви в размер ноги в дюймах */

float shoe; /* размер обуви мужской*/

float foot; /* размер мужской ноги в дюймах */

float shoe, foot;

printf("Размер обуви Размер ноги\n");

shoe = 3.0;

while(shoe < 18.5)

{/*.---------------------------.begin while */

foot = SCALE *shoe + OFFSET;

printf(" %10 lf %13 2f дюйм\n" , shoe, foot);

shoe = shoe + 1.0;

}/*.---------------------------.end while */

printf"'Ecли эта обувь годится вам, носите ее \n");

return 0;

}/*.---------------------------.end main() */

/*#############################################*/

РЕЗУЛЬТАТ РАБОТЫ ПРОГРАММЫ.

Размер обуви Размер ноги

3.01 8.61 дюйма

4.0 8.94 дюйма

... ...

17.0 13.16 дюйма

18.0 13.46 дюйма

Если эта обувь годится вам, носите ее.

ПОЯСНЕНИЯ К ПРОГРАММЕ.

  • Цикл while работает следующим образом. Когда программа в процессе выполнения впервые достигает оператора while, осушествляется проверка истинности условия, заключенного в круглые скобки. В этом случае соответствующее выражение имеет вид: shoe < 18.5, где символ < означает "меньше". Вначале переменная shoe была инициализирована значением 3.0, которое, как видно, меньше 18.5. Поэтому данное условие истинно, и осуществляется переход к следующему оператору, который переводит размер обуви в дюймы. После этого результаты выводятся на печать.

  • Смысл операции > словами выражается как "больше". Смысл операции < словами выражается как "меньше". Эти операции называются операциями отношения.

  • Следующий оператор shoe = shoe + 1.0; увеличивает значение переменной shoe на 1.0, делая его равным 4.0. В этом месте программы происходит возврат к началу фрагмента while, где вышеупомянутое условие проверяется вновь. Это происходит потому, что следующей строкой программы является закрывающая фигурная скобка } - тело цикла while заключено в фигурные скобки. Операторы, расположенные между ними, являются той частью программы, которая может выполняться повторно. 4 меньше 18.5? Безусловно. Поэтому весь набор операторов, заключенный в фигурные скобки и следующий за ключевым словом while, выполнится опять. Специалисты по вычислительной технике в этом случае говорят, что программа выполняет эти операторы "в цикле".

  • Это продолжается, пока значение переменной shoe не достигнет величины 19.0. Когда условие shoe < 18.5 станет ложным, поскольку 19.0 не меньше 18.5. При этом произойдет передача управления оператору, следующему сразу за телом цикла while. В нашем случае им является завершающий оператор printf().

***************************************************************

ПРИМЕЧАНИЕ.

Эту программу легко модифицировать, чтобы она осуществляла другие преобразования. Например:

Замените значение константы SCALE на 1.8, а константы OFFSET - на 32.0, и вы получите программу, которая переводит температуру по Цельсию TC в температуру по Фаренгейту TF.

TF=1.8 *TC + 32;

Замените значение константы SCALE на 0.6214, a константы OFFSET - на 0, тогда программа будет переводить сухопутные мили в километры.

KM=0.6214*ML;

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

/* ПРОГРАММА:

golf.c – таблица результатов игры в гольф (многократное присваивание).

*/

/*#############################################*/

/*============================= include */

#include<stdio.h>

/*============================= main() */

main()

{/*.---------------------------.begin main() */

int jane, tarzan, cheeta;

cheeta = tarzan = jane = 68; /* тройное присваивание справа налево */

printf("Cчет первой партии:\n);

printf("cheeta tarzan jane\n");

printf("%6d %6d %6d\n", cheeta, tarzan, jane);

return 0;

}/*.---------------------------.end main() */

/*#############################################*/

РЕЗУЛЬТАТ РАБОТЫ ПРОГРАММЫ.

cheetah tarzan jane

68 68 68

ПОЯСНЕНИЯ К ПРОГРАММЕ.

Присваивания выполняются справа налево. Сначала переменная jane получает значение 68, затем переменная tarzan и переменная cheeta.

/* ФРАГМЕНТ ПРОГРАММЫ:

/*============= операция сложения внутри формата printf() */

printf(“%d”,4+20);

/*=============*/

РЕЗУЛЬТАТ РАБОТЫ ФРАГМЕНТА ПРОГРАММЫ.

24

ПОЯСНЕНИЯ К ФРАГМЕНТУ ПРОГРАММЫ.

В результате работы оператора printf("%d", 4 + 20); на печать будет выведено число 24, а не выражение 4 + 20.

***************************************************************

Арифметические операции являются "бинарными", или "диадическими". Эти названия отражают тот факт, что они имеют дело с двумя операндами.

Операнды могут быть как константами, так и переменными. При выполнении оператора

income = salary + bribes;

компьютер возьмет значения двух переменных, стоящих в правой части, сложит их и присвоит затем полученную сумму переменной income.

ПРИМЕЧАНИЕ.

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

rocky = -12; smokey = -rocky;

переменной smokey будет присвоено значение 12. Когда знак минус используется подобным образом, данная oneрация называется "унарной".

Такое название указывает на то, что она имеет дело только с одним операндом.

/* ПРОГРАММА:

n_nn.c – числа и их квадраты (таблица квадратов чисел в цикле while).

*/

/*#############################################*/

/*============================= include */

#include<stdio.h>

/*============================= main() */

main()

{/*.---------------------------.begin main() */

int n = 1;

while(n < 21)

{/* ……………………….. begin while */

printf("%10d %10d", n, n*n);

n = n + 1;

}/* ……………………….. end while */

return 0;

}/*.---------------------------.end main() */

/*#############################################*/

РЕЗУЛЬТАТ РАБОТЫ ПРОГРАММЫ.

Эта программа выводит на печать первые 20 целых чисел и их квадраты.

***************************************************************

Вы, наверное, слышали историю о том, как один могущественный правитель обещал наградить ученого, оказавшего ему большую услугу. Ученый, когда его спросили, что бы он хотел получить в награду, указал на шахматную доску и сказал: "Положите одно пшеничное зерно на

первую клетку, два - на вторую, четыре на третью, восемь на следующую и т.д.". Правитель был удивлен, услышав такую скромную, по его мнению, просьбу. Программа, приведенная ниже, показывает, в какое трудное положение попал правитель. В программе вычисляется количество зерен, которое надо положить на каждую клетку, а также промежуточные результаты (суммы зерен по числу клеток). Кроме того, проводится сравнение промежуточных сумм зерен с приблизительными цифрами годового урожая пшеницы в США.

/* ПРОГРАММА:

grain.c – зерна на клетках шахматной доски (сравнение с урожаем США).

*/

/*#############################################*/

/*============================= include */

#include<stdio.h>

/*============================= define */

#define SQUARES 64 /* число клеток на шахматной доске */

#define CROP 7E14 /* урожай пшеницы, выраженный в числе зерен */

/*============================= main() */

main()

{/*.---------------------------.begin main() */

int count = 1; /* номер клетки */

/* double - описание переменных, вычисляемых с двойной точностью */

double current; /* число зерен в текущей клетке */

double total; /* сумма зерен в count клетках */

printf(" клетка число зерен сумма зерен доля от урожая ");

total = current = 1; /* начинаем с одного зерна */

printf("%4d %15.2е %13.2е %12.2e\n", count, current, total, total/CROP);

while (count < SQUARES)

{/*---------------------------- begin while */

count = count + 1;

current =2.0 * current; /* удвоение числа зерен на следующей клетке*/

total = total + current; /* коррекция суммы */

printf(" %4d %15.2е %13.2е %12 2e\n" , count, current, total, total/CROP);

}/* --------------------------- end while */

return 0;

}/*.---------------------------.end main() */

/*#############################################*/

РЕЗУЛЬТАТ РАБОТЫ ПРОГРАММЫ.

Count

Current

Total

Total/CROP

Клетка

число зерен

сумма зерен

доля от урожая

1

1.00E+00

1.00E+00

1.43E-15

……..

….….

……..

……..

10

5.12E+02

1.02E+03

1.46E-12

……..

……..

……..

……..

50

5.63E+14

1.13E+15

1.61E+00

ПОЯСНЕНИЯ К ПРОГРАММЕ.

Вначале результаты работы программы выглядят довольно безобидно. На первых 10 клетках оказалось чуть более тысячи зерен пшеницы. На пятидесяти клетках добыча ученого превысила весь годовой урожай пшеницы в США. Что окажется на 64 клетках? Решите сами.

На подобном примере можно показать явление экспоненциального роста населения земного шара. Рост использования энергетических ресурсов на Земле подчиняется тому же закону.

***************************************************************

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

числом, а во втором - числом с плавающей точкой. У целого числа нет дробной части, что делает, например, деление 5 на 3 затруднительным, поскольку результат не является целым. В языке Си принято правило, согласно которому дробная часть у результата деления целых чисел отбрасывается. Это действие называется "усечением".

/* ПРОГРАММА:

division.c - примеры деления.

*/

/*#############################################*/

/*============================= include */

#include<stdio.h>

/*============================= main() */

main()

{/*.---------------------------.begin main() */

printf(" деление целых: 5/4 это %d \n" , 5/4);

printf(" деление целых: 6/3 это %d \n" , 6/3);

printf(" деление целых: 7/4 это %d \n" , 7/4);

printf(" деление чисел: с плавающей точкой 7. /4. это %2.2f \n", 7. /4. );

printf(" смешанное деление: 7. /4 это %2.2f \n" , 7. /4);

return 0;

}/*.---------------------------.end main() */

/*#############################################*/

РЕЗУЛЬТАТ РАБОТЫ ПРОГРАММЫ.

деление целых: 5/4 это 1

деление целых: 6/3 это 2);

деление целых: 7/4 это 1);

деление чисел: с плавающей точкой 7. /4. это 1.75

смешанное деление: 7. /4 это 1.75

ПОЯСНЕНИЯ К ПРОГРАММЕ.

Результат деления целых чисел округляется не до ближайшего целого, а всегда до меньшего целого числа.

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

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

***************************************************************

7.2 АРИФМЕТИТЧЕСКАЯ ОПЕРАЦИЯ ДЕЛЕНИЕ ПО МОДУЛЮ %.

Деление по модулю (обозначается знаком %) означает остаток от деления одного целого числа на другое целое число. Эта операция, применима только к целым числам.

13%5=3; (читается: "13 по модулю 5" равно 3).

Эта операция широко применяется на практике и довольно удобна при программировании ряда задач. Одно распространенное применение - управление ходом программы.

Предположим, например, что вы пишите программу обработки счетов, которая должна предусматривать дополнительную плату раз в три месяца. Для этого нужно только вычислить остаток от деления номера месяца на 3 (т.е. month % 3), проверить, равен ли результат 0, и, если равен (только в этом случае), добавить к счету величину дополнительной платы.

/* ПРОГРАММА:

sec_min.c – перевод секунд в минуты и секунды (пример использования операции «деление по модулю»).

*/

/*#############################################*/

/*============================= include */

#include<stdio.h>

/*============================= define */

#define SM 60 /* число секунд в минуте */

/*============================= main() */

main()

{/*.---------------------------.begin main() */

int sec, min, rest;

printf(" Перевод секунд в минуты и секунды. \n");

printf(" Укажите число секунд: \n" );

scanf(" %d", &sec); /* ввод числа секунд */

/* дедение */

min = sec/SM; /* число минут */

/* дедение по модулю */

rest = sec%SM; /* оставшееся число секунд */

printf(" %d секунды это %d минуты, %d секунды \n",sec,min,rest);

return 0;

}/*.---------------------------.end main() */

/*#############################################*/

РЕЗУЛЬТАТ РАБОТЫ ПРОГРАММЫ.

Перевод секунд в минуты и секунды!

Укажите число секунд:

234

234 секунды это 3 минуты 54 секунды.

7.3 АРИФМЕТИЧЕСКИЕ ОПЕРАЦИИ ИНКРЕМЕНТ ++ И ДЕКРЕМЕНТ --.

Операция увеличения ++ (инкремент, increment) увеличивает значение своего операнда на единицу.

Операция уменьшения -- (декремент, decrement) уменьшает значение своего операнда на единицу.

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

/* ПРОГРАММА:

inc_prefpost_1.c – увеличение (префиксная и постфиксная формы).

*/

/*#############################################*/

/*============================= include */

#include<stdio.h>

/*============================= main() */

main()

{/*.---------------------------.begin main() */

int ultra = 0, super = 0;

while (super < 6)

{/*.---------------------------.begin while */

super++; ++ultra;

printf(" super = %d, ultra = %d\n", super, ultra);

}/*.---------------------------.end while */

return 0;

}/*.---------------------------.end main() */

/*#############################################*/

РЕЗУЛЬТАТ РАБОТЫ ПРОГРАММЫ.

super = 1, ultra = 1

super = 2, ultra = 2

super = 3, ultra = 3

super = 4, ultra = 4

super = 5, ultra = 5

ПОЯСНЕНИЯ К ПРОГРАММЕ.

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

super = super + 1;

ultra = ultra + 1;

***************************************************************

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

Компактная форма делает программы более изящными и легкими для понимания.

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

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

/* ФРАГМЕНТ ПРОГРАММЫ:

/*=============*/

size = 3.0;

while(size < 18.5)

{/*.---------------------------.begin while */

foot = SCALE*size + OFFSET;

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

++size;

}/*.---------------------------.end while */

/*=============*/

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

/* ФРАГМЕНТ ПРОГРАММЫ:

/*=============*/

size = 2.0;

while(++size < 18.5)

{/*.---------------------------.top while */

foot = SCALE *size + OFFSET;

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

}/*.---------------------------.bottom while */

/*=============*/

ПОЯСНЕНИЯ К ФРАГМЕНТУ ПРОГРАММЫ.

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

  • Значение переменной size изменено с 3.0 на 2.0, чтобы скомпенсировать увеличение переменной size перед ее первоначальным использованием для вычисления переменной foot.

  • При использовании оператора while(++size < 18.5) получается таблица перевода вплоть до размера 18.

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

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

***************************************************************

/* ПРОГРАММА:

inc_prefpost_2.c – увеличение (префиксная и постфиксная формы).

*/

/*#############################################*/

/*============================= include */

#include<stdio.h>

/*============================= main() */

main()

{/*.---------------------------.begin main() */

int a = 1, b = 1;

int aplus, plusb;

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

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

printf(" a aplus b plusb \n");

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

return 0;

}/*.---------------------------.end main() */

/*#############################################*/

РЕЗУЛЬТАТ РАБОТЫ ПРОГРАММЫ.

a aplus b plusb

2 1 2 2

ПОЯСНЕНИЯ К ПРОГРАММЕ.

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

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

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

***************************************************************

/* ПРОГРАММА:

inc_prefpost_2.c – увеличение (префиксная и постфиксная формы).

*/

/*#############################################*/

/*============================= include */

#include<stdio.h>

/*============================= define */

#define MAX 100

/*============================= main() */

main()

{/*.---------------------------.begin main() */

int count = MAX + 1;

while(--count > 0)

{/* ……………………….. begin while */

printf(" %d книг на полке! \n", count);

printf(" Сними одну и отдай другу. \n");

printf("%d книг! \n", count-1);

printf("--------------------------------\n", count-1);

}/* ……………………….. end while */

return 0;

}/*.---------------------------.end main() */

/*#############################################*/

РЕЗУЛЬТАТ РАБОТЫ ПРОГРАММЫ.

100 книг на полке!

Сними одну и отдай другу.

99 книг!

--------------------------------

99 книг на полке!

Сними одну и отдай другу.

98 книг!

--------------------------------

…………………………………………

1 книг на полке!

Сними одну и отдай другу.

0 книг!

--------------------------------

ПОЯСНЕНИЯ К ПРОГРАММЕ.

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

***************************************************************

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

Нельзя путать старшинство этих операций с порядком вычислений. Предположим, есть последовательность операторов:

y = 2; n = 3;

nextnum = (у + n ++ )*6;

Какое значение примет переменная nextnum? Подставляя в выражение соответствующие значения, получаем:

nextnum = (2 + 3)*6= 5*6 = 30

Только после того как выражение y+n вычислено, значение переменной n увеличивается до 4.

ПРИМЕЧАНИЕ.

Во избежание неправильных результатов:

1. Не применяйте операции увеличения или уменьшения к переменной присутствующей в более чем одном аргументе функции.

2. Не применяйте операции увеличения или уменьшения к переменной, которая входит в выражение более одного раза.

/* ФРАГМЕНТ ПРОГРАММЫ:

/*=============*/

while (num < 21)

{/* ……………………….. begin while */

printf("%10d %10d\n", num, num*num++);

}/* ……………………….. end while */

/*=============*/

ПОЯСНЕНИЯ К ФРАГМЕНТУ ПРОГРАММЫ.

Этот фрагмент выглядит разумным. Мы печатаем число num, умножаем его само на себя, чтобы получить его квадрат, а затем увеличиваем значение num на единицу. На некоторых машинах эта программа даже может работать. Но не на всех.

Проблема состоит в том, что при выполнении функции printf(), когда определяются печатаемые значения, вычисление второго аргумента (num*num++) может выполниться сначала, и приращение переменной num произойдет до того, как будет определен первый аргумент (num).

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

Другим возможным источником неприятностей служит оператор вида

ans = num/2 + 5*(1 + num++);

Проблема заключается в том, что компилятор может выполнять действия не в том порядке, который вы ожидали.

Вы можете считать, например, что сначала он определит значение num/2, а затем перейдет к другой части выражения. Но компилятор может вычислить сначала последний член, увеличить переменною num, а затем использовать новое значение при нахождении num/2. Никакой гарантии в этом случае не существует.

***************************************************************