Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции 3-9 full.doc
Скачиваний:
16
Добавлен:
22.12.2018
Размер:
979.97 Кб
Скачать

5. Операторы управления

5.1 Оператор ветвления

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

Синтаксис оператора ветвления:

if(условие) составной оператор №1

else составной оператор №2

Условие - любое выражение, результат которого может интерпретироваться как логическое значение (ноль - ЛОЖЬ, не ноль - ИСТИНА). Если условие является истинным, то выполняется составной оператор №1 (прямая ветвь оператора ветвления), если же ложно - то составной оператор №2. Ветвь else оператора ветвления называется альтернативной и может отсутствовать (в таком случае, при ложности условия, никаких действий не выполняется).

Если составной оператор в основной или альтернативной ветви оператора управления содержит только один простой оператор, то фигурные скобки можно опустить. В таком случае синтаксис оператора ветвления примет вид:

if(условие) простой оператор №1;

else простой оператор №2;

Основное предназначение оператора ветвления в языке С - реализация разветвляющихся алгоритмов. Например, фрагмент программы, для вычисления функции :

double x,y;

printf(“Введите значение Х: ”);

scanf(“%lf”,&x);

if(x<0.0) y = x*x;

else y = 2.0*x;

printf(“Результат: %lf\n”,y);

При построении программ с несколькими подряд идущими операторами ветвления необходимо учитывать следующее правило: оператор else относится к последнему оператору if. Например, рассмотрим фрагмент программы:

if(x>10.0) y = 2*x+5;

if(y<z) y = fabs(x);

else y = 2.5*x;

В данном примере оператор else относится к оператору if(y<z), а не к оператору if(x>10.0). Если необходимо нарушить этот порядок (т.е. ветвь else отнести к первому оператору if), то необходимо второй оператор if включить в составной оператор прямой ветви первого оператора if:

if(x>10.0){

y = 2*x+5;

if(y<z) z = fabs(x);

} else y = 2.5*x;

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

if(условие № 1) составной оператор № 1

else if(условие № 2) составной оператор № 2

...

else if(условие № N) составной оператор № N

else составной оператор № N+1

Например, фрагмент программы, для вычисления функции

:

double x,y;

printf(“Введите значение Х: ”);

scanf(“%lf”,&x);

if(x<0.0) y = x*x;

else if(x<5) y = 2.0*x;

else y = x + 5.0;

printf(“Результат: %lf\n”,y);

При написании программ включающих операторы ветвления рекомендуется придерживаться следующих правил форматирования текста программы:

  • Альтернативная ветвь оператора ветвления всегда указывается на новой строке с отступом:

if(...) ...

else ...

  • Если в прямой или альтернативной ветви оператора ветвления находятся один простой оператор, то он указывается на той же строке:

if(...) оператор № 1;

else оператор № 2;

  • Если в прямой или альтернативной ветви оператора ветвления находятся составные операторы, то следует придерживаться следующего форматирования:

if(условие){

оператор № 1;

...

оператор № N;

}else{

оператор № N+1;

...

}

ИСКЛЮЧЕНИЕ: если операторы в прямой и альтернативной ветви имеют краткую запись, то допускается оператор ветвления записывать в одну строчку:

if(условие) оператор № 1; else оператор № 2;

ПРИМЕЧАНИЕ: Во многих современных средах разработки форматирование текста программы автоматизировано. Отступы рекомендуется делать небольшими: 2 - 5 символов.

5.2 Оператор выбора

Использование каскадной конструкции из операторов ветвления в некоторых случаях является громоздкой и не эффективной. Например, необходимо реализовать программу: дан номер дня недели (1 - понедельник, 2 - вторник и т.д.), необходимо вывести на экран название этого дня. При каскадировании операторов ветвления эта программа будет иметь вид:

int n;

printf(“Введите номер дня недели:”);

scanf(“%d”,&n);

if(n==1) printf(“Понедельник\n”);

else if(n==2) printf(“Вторник\n”);

else if(n==3) printf(“Среда\n”);

else if(n==4) printf(“Четверг\n”);

else if(n==5) printf(“Пятница\n”);

else if(n==6) printf(“Суббота\n”);

else if(n==7) printf(“Воскресенье\n”);

else printf(“Неправильный номер!\n”);

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

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

Синтаксис оператора выбора:

switch(выражение){

case константа № 1: составной оператор № 1;

case константа № 2: составной оператор № 2;

...

case константа № N: составной оператор № N;

default: составной оператор № N+1;

}

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

Алгоритм функционирования оператора выбора следующий. Сначала вычисляется значение выражения. Затем, вычисленное значение по порядку сравнивается с каждой константой в списке операторов case и, если значения совпадают, то осуществляется выполнение соответствующего составного оператора. После выполнения составного оператора осуществляется выполнение следующего по списку составного оператора и т.д. Если ни одна из констант не совпала со значением выражения, то выполняется составной оператор, указанный после оператора default.

Выполнение всех составных операторов после первого совпадения не всегда удобно. Поэтому последним оператором в составном операторе обычно является оператор безусловного перехода break, который осуществляет завершение выполнения оператора switch. Более подробно этот оператор будет рассмотрен далее в этой главе.

Вернемся к программе о днях недели. Программа с использованием оператора выбора будет выглядеть следующим образом:

int n;

printf(“Введите номер дня недели: ”);

scanf(“%d”,&n);

switch(n){

case 1: {printf(“Понедельник\n”); break;}

case 2: {printf(“Вторник\n”); break;}

case 3: {printf(“Среда\n”); break;}

case 4: {printf(“Четверг\n”); break;}

case 5: {printf(“Пятница\n”); break;}

case 6: {printf(“Суббота\n”); break;}

case 7: {printf(“Воскресенье\n”); break;}

default: printf(“Неправильной номер!\n”);

}

В каждом составном операторе после оператора case последним простым оператором указывается оператор break, который осуществляет прерывание выполнения оператора выбора. Например, выполнение программы:

Введите номер дня недели: 3

Среда

Если оператор break не указывать, то программа будет выводить названия всех дней недели, начиная со дня, номер которого введет пользователь. Пример выполнения такой программы:

Введите номер дня недели: 3

Среда

Четверг

Пятница

Суббота

Воскресенье

Неправильный номер

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

int n;

printf(“Введите номер дня недели: ”);

scanf(“%d”,&n);

switch(n){

case 1: case 2: case 3: case 4: case 5:

{printf(“Будний день!\n”); break;}

case 6: case 7:

{printf(“Выходной день!\n”); break;}

default: printf(“Неправильной номер!\n”);

}

При форматировании текста программ включающих в себя оператор выбора рекомендуется придерживаться следующих правил:

  • Общий формат оператора выбора должен быть следующий:

switch(...){

операторы

}

  • Каждый оператор case должен начинаться с новой строки с отступом относительно записи switch.

  • Если составной оператор после оператора case большой, то он записывается несколькими строками в следующем формате:

case константа:{

Оператор № 1;

...

Оператор № N;

break;

}

ИСКЛЮЧЕНИЕ: Операторы case допускается записывать в одну строку, если они содержат только константы, а составной оператор содержится только в последней из них.

5.3 Операторы циклов

Операторы циклов предназначены для реализации циклических алгоритмов. В языках программирования высокого уровня операторы циклов делятся на две группы:

  • операторы циклов со счетчиком - выполняются определенное число итераций;

  • операторы циклов с условием - выполняются пока условие истинно или ложно.

Операторы циклов с условием могут быть классифицированы по следующим признакам:

  • с предусловием или с постусловием;

  • выполнение пока условие истинно или ложно.

Операторы циклов с предусловием - сначала выполняется проверка условия, а затем тело цикла. В операторах циклов с постусловием наоборот. Циклы с условием могут выполняться пока условие истинно или пока условие ложно. Последний тип таких операторов циклов в языке С отсутствует.

В языке С оператор цикла состоит из двух основных частей:

  • непосредственно сам оператор цикла (for, while, do ... while);

  • тело цикла - простой или составной оператор.

5.3.1 со счетчиком

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

for(инициализация; условие; приращение) тело цикла

После ключевого слова for в круглых скобках осуществляется указание блоков: инициализация, условие и приращение. Все блоки разделяются точкой с запятой. Блок инициализации предназначен для установки переменной счетчика в начальное значение. В блоке условие указывается выражение, значение которого трактуется как логическое: ноль - ЛОЖЬ, не ноль - ИСТИНА. Цикл выполняется пока условие истинно. В блоке приращение производится модификация переменной счетчика, обычно здесь используются операции инкремента или декремента (в зависимости от требуемого направления изменения). После закрывающей круглой скобки указывается тело цикла, которое представляет собой либо составной, либо простой операторы. Сам цикл функционирует согласно блок-схеме, представленной на рисунке 3.1.

Рисунок 3.1 - Блок схема цикла for

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

unsigned max = 0;

printf(“Введите последовательность: ”);

for(int i=0;i<10;i++){

unsigned value;

scanf(“%u”,&value);

if(max < value) max = value;

}

printf(“Максимальное значение: %u\n”,max);

В цикле for в блоке инициализации создается и инициализируется нулем переменная-счетчик i. Цикл выполняется до тех пор, пока значение переменной i меньше 10 (десять итераций). После каждой итерации значение переменной i в блоке приращения увеличивается на единицу (операция инкремента). В теле цикла осуществляется создание переменной value, а затем ввод этой переменной. Значение введенной переменной сравнивается со значением текущего максимума (переменная max) и, в случае если значение текущего максимума меньше, осуществляется запись значения нового максимума в переменную max.

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

Рассмотрим задачу вычисления факториала числа. Пусть имеется некоторая целочисленная переменная n, содержащая значение, факториал которого необходимо вычислить. Значение факториала необходимо записать в вещественную переменную fact. Любой из ниже приведенных фрагментов программы (циклов) будет правильным:

for(int i=1, fact=1.0; i<=n; i++) fact *= i;

for(int i=1, fact=1.0; i<=n; fact *= i++);

for(int i=1, fact=1.0; i<=n;) fact *= i++;

for(fact=1.0;n>0;) fact *= n--;

В первом примере реализован классический цикл for с использованием всех блоков. В блоке инициализации создается и инициализируется единицей переменная-счетчик i, а также инициализируется единицей переменная fact. В блоке условия проверяется достижение значения переменной i значения, факториал которого вычисляется (переменная n). В блоке приращения осуществляется увеличение переменной i на единицу. Тело цикла содержит один простой оператор присвоения для вычисления факториала (накопление произведения в переменной fact). Во втором примере тело цикла перенесено в блок приращения. В третьем примере наоборот: блок приращения отсутствует, а переменная i модифицируется в теле цикла. В четвертом примере вычисление факториала осуществляется без использования дополнительной переменной i, а модифицируется (в теле цикла) непосредственно значение переменной n.

Возможность пропуска блоков в операторе for является довольно удобной, хотя в некоторых случаях вообще лишена смысла. Например, допустима следующая конструкция: for(;;); Это вечный цикл, который не выполняет никаких действий. Тем не менее, встретив такую конструкцию, программа просто никогда не выйдет из этого цикла for.

При написании программ с использованием цикла for рекомендуется придерживаться следующих правил форматирования текста программы:

  • Общий формат цикла for при составном операторе в теле цикла:

for(...){

оператор № 1;

...

оператор № 2;

}

  • Общий формат цикла for при простом операторе в теле цикла:

for(...)

оператор;

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

for(...) оператор;

for(...) {оператор № 1; ... оператор № N;}

5.3.2 с предусловием

Оператор цикла с предусловием (сначала проверяется условие, а затем выполняется тело цикла) имеет следующий синтаксис:

while(условие) тело цикла

После ключевого слова while в круглых скобках указывается условие выполнения цикла: цикл выполняется пока условие истинно. Условие должно представлять собой любое выражение, результат которого можно интерпретировать, как логическое значение в языке С. Тело цикла может быть представлено как простым, так и составным оператором. Алгоритм выполнения данного цикла можно представить в виде блок-схемы на рисунке 3.2.

Рисунок 3.2 - Блок-схема цикла while

Оператор цикла с предусловием используется тогда, когда заранее не известно число итераций. Например, в следующем фрагменте программы осуществляется вывод на экран таблицы значений функции синус, если аргумент изменяется от a до b с шагом h. Переменные a, b и h вещественные (тип double), и их значения уже введены.

while(a <= b){

printf("sin(%.4lf) = %.4lf\n",a,sin(a));

a += h;

}

Вывод таблицы осуществляется в цикле while, условием выполнения которого является истинность выражения a <= b. В качестве текущего значения аргумента функции синуса в программе используется переменная a, содержащая левую границу интервала. Постепенно, с определенным шагом (переменная h), значение переменной a приближается к значению переменной b, содержащей правую границу интервала. В теле цикла осуществляется вывод на экран аргумента и значения функции в удобном виде, а также изменяется соответствующим образом значение переменной a.

ПРИМЕЧАНИЕ: В языке С данную программу можно также реализовать и с использованием цикла for:

for(;a<=b;a+=h)

printf("sin(%.4lf) = %.4lf\n",a,sin(a));

Такое возможно благодаря гибкости оператора for. На практике выбор того или иного оператора цикла (for или while) зачастую зависит от предпочтений программиста. Тем не менее, рекомендуется использовать оператор for только как оператор цикла со счетчиком, так как это связано с возможностью оптимизации программ компилятором.

При написании программ с использованием цикла while рекомендуется придерживаться следующих правил форматирования текста программы:

  • Общий формат цикла while при составном операторе в теле цикла:

while(условие){

оператор № 1;

...

оператор № 2;

}

  • Общий формат цикла while при простом операторе в теле цикла:

while(условие)

оператор;

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

while(условие) оператор;

while(условие) {оператор № 1; ... оператор № N;}

5.3.3 с постусловием

Оператор цикла с постусловием (сначала выполняется тело цикла, а затем проверяется условие) имеет следующий синтаксис:

do тело цикла while(условие);

После ключевого слова do указывается тело цикла. После тела цикла указывается ключевое слово while, а в скобках за ним - условие выполнения цикла (цикл выполняется пока условие истинно). Условие должно представлять собой любое выражение, результат которого можно интерпретировать, как логическое значение в языке С. Тело цикла может быть представлено как простым, так и составным оператором. Алгоритм выполнения данного цикла можно представить в виде блок-схемы на рисунке 3.3.

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

Рисунок 3.3 - Блок-схема цикла do...while

Например, в следующем фрагменте программы осуществляется вычисление суммы ряда с точностью eps (вещественная переменная типа double, содержит значение погрешности вычисления). Сумма ряда записывается в вещественную переменную sum (тип double), которая предварительно инициализирована нулем.

double s = 0.0;

unsigned i = 1;

do{

s = 1.0/i;

sum += s;

i++;

}while(eps < s);

В двух первых строчках осуществляется объявление и инициализация дополнительных переменных. Вещественная переменная s содержит значение текущего члена ряда. Целочисленная переменная i содержит номер текущего члена ряда. В теле цикла осуществляется вычисление текущего члена ряда, суммирование его с уже накопленной суммой предыдущих членов ряда, и инкрементирование переменной i. В качестве условия цикла выступает выражение eps < s, которое становится ложным, когда значение текущего члена ряда станет меньше погрешности вычисления.

При написании программ с использованием цикла do...while рекомендуется придерживаться следующих правил форматирования текста программы:

  • Общий формат цикла do...while при составном операторе в теле цикла:

do{

оператор № 1;

...

оператор № 2;

}while(условие);

  • Общий формат цикла do...while при простом операторе в теле цикла:

do оператор while(условие);

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

do {оператор № 1; ... оператор № N;} while(условие);

5.4 Операторы безусловных переходов

Операторы безусловного перехода осуществляют управление потоком программы в соответствии с некоторыми правилами без каких-либо условий. Как правило, операторы безусловных переходов являются прямыми или альтернативными ветвями оператора ветвления. В языке С присутствуют следующие операторы безусловных переходов:

  • оператор прерывания выполнения тела цикла и переход к следующей итерации;

  • оператор прерывания выполнения оператора цикла или оператора выбора и переход к следующему оператору;

  • оператор безусловного перехода по метке.

Оператор continue - оператор прерывания выполнения тела цикла и переход к следующей итерации.

Рассмотрим использование этого оператора на примере фрагмента программы, вычисляющего сумму трехзначных чисел не кратных пяти или трем.

unsigned summa = 0;

for(unsigned n=100;n<1000;n++){

if((n%5==0)||(n%3==0)) continue;

summa += n;

}

В первой строчке этого фрагмента является объявление и инициализация переменной summa, которая будет содержать сумму трехзначных чисел удовлетворяющих условию задачи. Далее следует оператор цикла с переменной-счетчиком n, изменяющейся от 100 до 999 с шагом единица. В теле цикла первым оператором является оператор if, условие которого становится истинным, если значение переменной n является кратным трем или пяти, а прямой ветвью оператора if является оператор continue. Таким образом, если значение переменой n будет кратно трем или пяти, то выполнение тела цикла for будет прервано, а управление будет передано в блок приращения цикла. Данный фрагмент программы можно представить в виде блок-схемы приведенной на рисунке 3.4.

ПРИМЕЧАНИЕ: Использования оператора continue можно избежать практически в любом случае. Например, предыдущий фрагмент программы можно преобразовать к виду:

unsigned summa = 0;

for(unsigned n=100;n<1000;n++)

if((n%5!=0)&&(n%3!=0)) summa += n;

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

Рисунок 3.4 - Блок-схема фрагмента программы

Оператор continue осуществляет прерывание тела только того цикла, внутри которого он находится. Например, во фрагменте программы слева оператор continue относится к вложенному циклу, а справа - к внешнему циклу:

for(int i=0;i<N;i++){ for(int i=0;i<N;i++){

... ...

for(int j=0;j<M;j++){ for(int j=0;j<M;j++){

... ...

if(...) continue; }

... if(...) continue;

} }

}

Оператор break - оператор прерывания выполнения оператора цикла (for, while, do...while) или оператора выбора (switch).

Рассмотрим использование этого оператора на примере фрагмента программы, находящей третье по счету двухзначное число, сумма цифр которого равна семи.

unsigned num = 0;

for(unsigned i=10, j=0;i<100;i++){

if(i%10 + i/10 == 7) j++;

if(j==3) {num = i; break;}

}

В первой строчке фрагмента программы объявляется и инициализируется нулем переменная num, которая будет в результате содержать искомое число. Далее описывается цикл for с переменной-счетчиком i, которая изменяется от 10 до 99 с единичным шагом. Также в блоке инициализации объявляется и инициализируется переменная j, которая будет использоваться для подсчета найденных чисел, удовлетворяющих условию поиска. В теле цикла сначала в операторе if проверяется, является ли сумма цифр текущего значения переменной i равной 7. Если да, то значение переменной j инкрементируется. Далее в следующем операторе условия проверяется: является ли найденное число третьим по счету. Если да, то его значение записывается в переменную num и цикл завершается с помощью оператора break. В противном случае цикл продолжает выполняться.

ПРИМЕЧАНИЕ: Использования оператора break можно избежать практически в любом случае. Например, предыдущий фрагмент программы можно преобразовать к виду:

unsigned num = 0;

for(unsigned i=10, j=0;(i<100)&&(j<3);i++){

if(i%10 + i/10 == 7) j++;

num = i;

}

Использование оператора break позволяет значительно упростить текст программы, а в некоторых случаях даже оптимизировать код. Как правило, оператор break используется в тех циклах, в которых присутствует несколько условий. Одно из этих условий становится основным и указывается в блоке условия оператора цикла, а остальные - в теле цикла с использованием оператора break.

Оператор break осуществляет прерывание только того цикла, внутри которого он находится. Например, во фрагменте программы слева оператор break относится к вложенному циклу, а справа - к внешнему циклу:

for(int i=0;i<N;i++){ for(int i=0;i<N;i++){

... ...

for(int j=0;j<M;j++){ for(int j=0;j<M;j++){

... ...

if(...) break; }

... if(...) break;

} }

}

Оператор goto - оператор безусловного перехода по метке. Именем метки может выступать любой идентификатор, не использовавшийся ранее. Метка указывается на новой строке с завершающим двоеточием. После оператора goto указывается имя метки с завершающей точкой с запятой.

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

unsigned num = 100;

Next:

if(num%10 + num/100 == num/10%10) goto Exit;

num++;

goto Next;

Exit:

В первой строчке фрагмента программы осуществляется объявление переменной num и инициализация ее значением первого трехзначного числа. Во второй строчке указывается метка Next. Далее в операторе if осуществляется проверка, удовлетворяет ли текущее значение переменной num условию задачи. Если удовлетворяет, то с помощью оператора goto осуществляется переход по метке Exit. В противном случае значение переменной num увеличивается на единицу и осуществляется переход по метке Next. На выходе в переменной num будет содержаться искомое значение.

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

ПРИМЕЧАНИЕ: Чрезмерное использование оператора goto делает программу запутанной (на жаргоне программистов такая программа называется «спагетти»). Поэтому не рекомендуется и даже запрещается при программировании использовать оператор goto. В большинстве современных языков программирования данный оператор присутствует, но считается устаревшим и его использование не рекомендуется.

5.5 Примеры

Задача 3.1: Квадратное уравнение вида задается коэффициентами A, B и C. Определить корни уравнения.

Программа для задачи

#include <stdio.h> //Библиотека базового ввода и вывода

#include <math.h> //Библиотека математических функций

int main(int argc, char *argv[])

{

double A,B,C; //Объявление переменных

//Приглашение к вводу и ввод коэффициентов уравнения

printf("Введите коэффициенты A, B и C: ");

scanf("%lf %lf %lf",&A,&B,&C);

//Вычисление дискриминанта уравнения

double D = B*B - 4.0*A*C;

if(D < 0.0){ //Если дискриминант отрицательный

//Вывод сообщения об отсутствии корней

printf("Нет действительных корней уравнения!\n");

}else if(D > 0.0){ //Если дискриминант положительный

//Вычисление и вывод корней уравнения

printf("Корни уравнения: %.4lf\t%.4lf\n",

(-B-sqrt(D))/(2.0*A), (-B+sqrt(D))/(2.0*A));

}else{ //Если дискриминант равен нулю

//Вычисление и вывод значения корня

printf("Один корень: %.4lf\n",-B/(2.0*A));

}

return 0;

}

Задача 3.2: Пользователь вводит дату не високосного года в формате DD.MM, где DD - день, MM - месяц. Вывести на экран введенную дату словесно. Например, пользователь ввел: 10.05. На экране: десятое мая.

Программа для задачи

#include <stdio.h> //Библиотека базового ввода и вывода

int main(int argc, char *argv[])

{

//Объявление переменных для хранения дня и месяца

unsigned day, mon;

//Приглашение к вводу и ввод даты

printf("Введите дату: "); scanf("%u.%u",&day,&mon);

//Проверка корректности указания дня и месяца

int flag = (day<1)||(day>31)||(mon<1)||(mon>12);

//Проверка корректности указания дня в зависимости от

//месяца (30 или 31 день)

flag +=

((mon==4)||(mon==6)||(mon==9)||(mon==11))&&(day==31);

//Проверка корректности указания дня в феврале

flag += (mon==2)&&(day>28);

//Если дата указана неверно, то вывод сообщения и выход

if(flag) {printf("Неправильная дата!\n"); return 0;}

//Разложение дня на составляющие

unsigned d1 = day/10, d2 = day%10;

//Вывод словесного описания дня

switch(d1){

//Если это тридцатые числа

case 3:{

//Если тридцатое число

if(d2==0) printf("Тридцатое ");

//Если тридцать первое число

else printf("Тридцать первое ");

break;

}

//Если это двадцатые числа

case 2:{

//Если двадцатое

if(d2==0) {printf("Двадцатое "); break;}

//Если двадцать первое и далее

else printf("Двадцать ");

}

//Если это первые числа

case 0: {

switch(d2){

case 1: {printf("первое "); break;}

case 2: {printf("второе "); break;}

case 3: {printf("третье "); break;}

case 4: {printf("четвертое "); break;}

case 5: {printf("пятое "); break;}

case 6: {printf("шестое "); break;}

case 7: {printf("седьмое "); break;}

case 8: {printf("восьмое "); break;}

case 9: {printf("девятое "); break;}

}

break;

}

//Если число от десятого до девятнадцатого

case 1:{

switch(d2){

case 0: {printf("Десятое "); break;}

case 1: {printf("Одиннадцатое "); break;}

case 2: {printf("Двенадцатое "); break;}

case 3: {printf("Тринадцатое "); break;}

case 4: {printf("Четырнадцатое "); break;}

case 5: {printf("Пятнадцатое "); break;}

case 6: {printf("Шестнадцатое "); break;}

case 7: {printf("Семнадцатое "); break;}

case 8: {printf("Восемнадцатое "); break;}

case 9: {printf("Девятнадцатое "); break;}

}

break;

}

}

//Вывод на экран названия месяца в соответствии с

//его номером

switch(mon){

case 1: {printf("января"); break;}

case 2: {printf("февраля"); break;}

case 3: {printf("марта"); break;}

case 4: {printf("апреля"); break;}

case 5: {printf("мая"); break;}

case 6: {printf("июня"); break;}

case 7: {printf("июля"); break;}

case 8: {printf("августа"); break;}

case 9: {printf("сентября"); break;}

case 10: {printf("октября"); break;}

case 11: {printf("ноября"); break;}

case 12: {printf("декабря"); break;}

}

//Вывод знака перевод строки

printf("\n");

//Выход из программы

return 0;

}

Задача 3.3: Вычислить сумму ряда с первой позиции до позиции N с заданной погрешностью. Позиция N и погрешность вводятся пользователем. При реализации оптимизировать вычисления.

Программа для задачи

#include <stdio.h> //Библиотека базового ввода и вывода

int main(int argc, char *argv[])

{

//Объявление переменной для хранения конечной позиции

unsigned n = 0;

//Объявление переменной для хранения погрешности

double eps = 0.0;

//Приглашение к вводу и ввод позиции

printf("Введите позицию: "); scanf("%u",&n);

//Приглашение к вводу и ввод погрешности

printf("Введите погрешность: "); scanf("%lf",&eps);

/* ---------------------------------------------------

В переменной pow2 будет накапливаться 2 в степени i

В переменной fact будет накапливаться факториал i

В переменной summa будет накапливаться сумма ряда

--------------------------------------------------- */

double pow2 = 1.0, fact = 1.0, summa = 0.0;

//Цикл вычисления суммы

for(unsigned i=1;i<=n;i++){

//Пошаговое вычисление 2 в степени i

pow2 *= 2.0;

//Пошаговое вычисление факториала

fact *= i;

//Вычисление модуля текущего элемента ряда

double cur = pow2/fact;

/* -------------------------------------------------

Суммирование элемента ряда с уже накопленной суммой

с учетом знака: если i - четное, то плюс, в противном

случае - минус

--------------------------------------------------- */

summa += ((i%2==0)?cur:-cur);

//Выход из цикла, если достигнута заданная погрешность

if(cur < eps) break;

}

//Вывод значения суммы на экран

printf("Сумма ряда: %.5lf\n",summa);

return 0;

}

Задача 3.4: Вывести на экран таблицу значений одной из функций (sin, cos, sqrt, exp) на интервале [A,B]. Таблица состоит из двух колонок (аргумент и функция) и N строк. Значения вывести с точностью до четвертого знака после запятой. Ширина колонок: 15 символов. Значения A, B и N вводит пользователь. Функцию выбирает пользователь.

Программа для задачи

#include <stdio.h> //Библиотека базового ввода и вывода

#include <math.h> //Библиотека математических функций

int main(int argc, char *argv[])

{

/* ---------------------------------------------------

Переменная a - левая граница интервала

Переменная b - правая граница интервала

Переменная step - шаг изменения аргумента

Переменная N - количество строк в таблице

Переменная I - номер функции

---------------------------------------------------- */

double a,b,step;

unsigned N,I;

//Приглашение к вводу интервала

printf("Введите интервал:\n");

//Цикл ввода: до ввода правильного значения

do{

//Ввод интервала в формате [a,b]

scanf("[%lf,%lf]",&a,&b);

//Если введен правильно, то выход из цикла

if(a<b) break;

//Сообщение об ошибке ввода

printf("Некорректный интервал!\n");

}while(1);

/* Ввод количества строк аналогичен вводу интервала */

printf("Введите число строк:\n");

do{

scanf("%u",&N);

if(N>1) break;

printf("Слишком мало строк!\n");

}while(1);

//Вычисление шага приращения аргумента

step = (b - a)/(N - 1);

/* Ввод номера функции аналогичен вводу интервала */

printf("Выберите функцию:\

\n 1 - sin\n 2 - cos\n 3 - sqrt\n 4 - exp\n");

do{

scanf("%u",&I);

if((I>0)||(I<5)) break;

printf("Неправильный номер функции!\n");

}while(1);

//Вывод шапки таблицы

printf("--------------------------------\n");

printf(" Аргумент | Функция |\n");

printf("--------------------------------\n");

//Установка аргумента (переменной x) на начало интервала

double x = a;

//Цикл: пока не достигнута правая граница интервала

while(x<=b){

//Объявление переменной для хранения значения функции

double y = 0.0;

/* -----------------------------------------------

Вычисление значения функции в зависимости от ее

номера (переменная I)

-------------------------------------------------- */

switch(I){

case 1: {y = sin(x); break;}

case 2: {y = cos(x); break;}

case 3: {y = sqrt(x); break;}

case 4: {y = exp(x); break;}

}

//Вывод на экран аргумента и значения функции

printf(" %10.4lf | %10.4lf |\n",x,y);

//Изменение аргумента функции

x += step;

}

//Вывод завершающей рамки таблицы

printf("--------------------------------\n");

return 0;

}

Задача 3.5: Определить количество N-значных целых положительных чисел, сумма цифр которых кратна числу K. Числа N и K вводит пользователь. 0<N<10, 1< K<10.

Программа для задачи

#include <stdio.h> //Библиотека базового ввода и вывода

#include <math.h> //Библиотека математических функций

int main(int argc, char *argv[])

{

unsigned n = 0, k = 0;

//Приглашение к вводу количества знаков в числах

printf("Введите количество значащих цифр в числах: ");

//Цикл ввода: пока не будет введено корректное значение

do{

scanf("%u",&n); //Если значение корректно, то

if((n>0)&&(n<10)) break;//выход из цикла

printf("Некорректное значение!\n");

//Вечный цикл (выход внутри тела - оператор break)

}while(1);

//Ввод числа K аналогичен вводу числа N

printf("Введите число: ");

do{

scanf("%u",&k);

if((k>1)&&(k<10)) break;

printf("Некорректное значение!\n");

}while(1);

/* -------------------------------------------------

Переменная lim - верхняя граница N-значных чисел

Переменная count - счетчик чисел удовлетворяющих

условию задания

------------------------------------------------- */

unsigned lim = (unsigned)pow(10.0,n), count = 0;

//Цикл по всем N-значным числам

for(unsigned i=lim/10;i<lim;i++){

/* -----------------------------------------------

Сохранение текущего числа в переменной val

Переменная sum будет содержать суммы цифр числа

----------------------------------------------- */

unsigned val = i, sum = 0;

//Цикл вычисления суммы цифр в числе

while(val>0){sum += val%10; val /= 10;}

//Проверка выполнения условия кратности и увеличение

//счетчика чисел, удовлетворяющих условию

if(sum % k == 0) count++;

}

//Вывод количества чисел на экран

printf("Количество чисел: %u\n",count);

return 0;

}