Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

книги / Практикум по программированию на языке Си

..pdf
Скачиваний:
24
Добавлен:
12.11.2023
Размер:
3.53 Mб
Скачать

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

Линейная последовательность действий представляется в языке Си либо составным оператором, либо блоком. Отличие между ними в наличии определений и описаний в начале каждого блока. Пример блока приведен в программе 04_05.с (тема 4).

5.1. Условный оператор

Сокращенная форма условного оператора: if (условие) оператор;

Полная форма условного оператора:

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

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

ЗАДАЧА 05-01. Введите три целых числа и выведите на печать (на экран дисплея) минимальное из введенных значений. Используйте для решения условные операторы.

Следующая программа решает задачу:

/* 05_01.c - минимум из трех значений. Условный оператор */

#include <stdio.h> #define READI(VARIABLE) \

{printf(#VARIABLE"="); scanf("%d",&VARIABLE);} int main ()

{

int x, y, z, res;

131

READI(x);

READI(y);

READI(z);

res=x;

if (res > y) res=y; if (res > z) res=z;

printf("min=%d", res); return 0;

}

Результат выполнения программы:

x=16<ENTER>

y=38<ENTER>

z=9<ENTER>

min=9

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

ЗАДАНИЕ. В данном примере применение условного оператора может быть исключено, если воспользоваться условным (тернарным) выражением. Решите задачу: 1) используя два условных (тернарных) выражения; 2) используя сложное выражение, включающее две тернарные операции. (Особенности тернарных выражений рассмотрены в предыдущей теме.)

ЗАДАЧА 05-02. Введите целое число и проверьте его одновременную кратность двум другим целым числам, также вводимым с клавиатуры. В качестве проверяемого условия в условном операторе примените арифметическое выражение.

Задачу решает следующая программа:

/* 05_02.c - арифметическое выражение в качестве условия */

#include <stdio.h> #define READI(VARIABLE) \

{printf(#VARIABLE"="); scanf("%d",&VARIABLE);} int main ()

{

132

int number,a,b; READI(number); READI(a); READI(b);

if (number%a)

puts("Not divisible!"); else

if (number%b)

puts("Not divisible!"); else

puts("Divisible!"); return 0;

}

Результаты выполнения программы:

number=87 <ENTER> a=3<ENTER> b=5<ENTER>

Not divisible!

Результаты второго выполнения программы:

number=75 <ENTER> a=5<ENTER> b=3<ENTER> Divisible!

(По-английски divisible – делящийся без остатка.)

ЗАДАНИЕ. Замените арифметические управляющие выражения в операторе if логическими выражениями.

ЗАДАЧА 05-03. Ввести три целых числа и вывести их на печать (на экран дисплея) в порядке возрастания.

Задачу решает следующая программа:

/* 05_03.c - упорядочение трех значений */ #include <stdio.h>

#define READI(VARIABLE) \

{printf(#VARIABLE"="); scanf("%d",&VARIABLE);}

133

#define PRINTI(EXPRESSION) \ printf(#EXPRESSION"=%d\n",EXPRESSION)

int main ()

{

int x, y, z, res; READI(x); READI(y); READI(z);

printf("Result:\n"); if (x > y)

if (y > z)

{PRINTI(z); PRINTI(y); PRINTI(x); }

else

{PRINTI(y);

if (x > z) {

PRINTI(z);

PRINTI(x);

}

else

{

PRINTI(x);

PRINTI(z);

}

}

else

if (x > z)

{PRINTI(z); PRINTI(x); PRINTI(y); }

else

{PRINTI(x);

if (y > z) { PRINTI(z); PRINTI(y); }

else

{ PRINTI(y); PRINTI(z); }

}

 

return 0;

 

}

Результат выполнения программы:

x=3<ENTER>

y=44<ENTER>

z=15<ENTER>

Result:

x=3

z=15

y=44

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

134

ax2 + bx +c = 0

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

a==0, b==0, c==0 – неопределенное решение; a==0, b==0, c!=0 – противоречие;

a==0, b!=0, c==0 – нулевое решение, один корень; a==0, b!=0, c!=0 – линейное уравнение, один корень; a!=0, b×b–4×a×c>=0 – два действительных корня; a!=0, b×b–4×a×c<0 – два комплексных корня.

В случаях, когда а!=0 справедлива формула:

x

=

b

±

b2 4ac

.

1,2

 

2a

 

4a2

 

 

 

 

 

С ее помощью при положительном дискриминанте b2 4ac > 0 вычисляются два действительных корня. При отрицательном дис-

криминанте, т.е. когда b2

4ac <

0 ,

комплексные корни можно

определить так:

 

 

 

 

b

b2

4ac

,

x1,2 = 2a ± i

4a2

 

где i – мнимая единица.

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

ЗАДАЧА 05-04. Составьте программу для решения квадратного уравнения в соответствии с приведенными соотношениями. Исходные данные – значения коэффициентов a, b, c, вводимые пользователем с клавиатуры.

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

135

/* 05_04.c – решение квадратного уравнения

(if + return) */ #include <stdio.h>

#include <math.h>

#define READD(VARIABLE) \

{printf(#VARIABLE"="); scanf("%le",&VARIABLE);} int main ()

{

double a, b, c, discri, di_sqr, abs_di_sqr; READD(a);

READD(b);

READD(c);

if (a == 0.0 && b == 0.0 && c == 0.0)

{printf("The undefined solution!"); return 0;

}

if (a == 0.0 && b == 0.0 && c != 0.0) { printf("The contradiction!");

return 0;

}

if (a == 0.0 && b != 0.0 && c == 0.0) { printf("The solution: x=%f", 0.0);

return 0;

}

if (a == 0.0 && b != 0.0 && c != 0.0)

{printf("The solution: x=%f", -c/b); return 0;

}

discri = b*b - 4*a*c;

if (a != 0.0 && discri >= 0.0)

{di_sqr=sqrt(discri); printf("The solution: x1=%f",

-b/(2*a)+di_sqr/(2*a)); printf("\n x2=%f",

-b/(2*a)-di_sqr/(2*a)); return 0;

}

if (a != 0.0 && discri < 0.0)

{abs_di_sqr=sqrt(fabs(discri)); printf("The solution: x1=%f + i%f",

-b/(2*a),abs_di_sqr/(2*a)); printf("\n x2=%f - i%f",

136

-b/(2*a),abs_di_sqr/(2*a)); return 0;

}

}

Результаты выполнения программы c разными данными.

Первое исполнение:

a=0<ENTER>

b=0<ENTER>

c=0<ENTER>

The undefined solution!

Второе исполнение:

a=0<ENTER>

b=0<ENTER> c=-15<ENTER>

The contradiction!

Третье исполнение:

a=0<ENTER>

b=40<ENTER>

c=0<ENTER>

The solution: x=0.000000

Четвертое исполнение:

a=0<ENTER>

b=12<ENTER>

c=6<ENTER>

The solution: x=-0.500000

Пятое исполнение:

a=2<ENTER> b=-1<ENTER> c=-6<ENTER>

The solution: x1=2.000000 x2=-1.500000

137

Шестое исполнение:

a=34<ENTER>

b=4<ENTER>

c=2<ENTER>

The solution: x1=-0.058824 + i0.235294 x2=-0.058824 - i0.235294

ЗАДАНИЕ. Составьте программу для решения той же задачи, используя полные условные операторы и только один опера-

тор return.

ЗАДАЧА 05-05. Ввести время суток в виде целого числа от 0 до 24, напечатать соответствующее времени английское приветствие:

22 – 3 – Good Night!

4 – 10 – Good Morning!

11 – 14 – Good Day!

15 – 16 – Good Afternoon!

17 – 21 – Good Evening!

Вариант 1. Использовать сокращенный условный оператор. Вариант 2. Использовать сокращенный условный оператор и

операторы return, прерывающие исполнение программы при нахождении нужного условия.

Вариант 3. Использовать вложение полных условных операторов.

Вариант 2 реализует следующая программа:

/* 05_05.c - английские приветствия (if + return) */ #include <stdio.h>

int main ()

{int time;

printf("Print time (from 0 to 24): "); scanf("%d",&time);

if (time>=22 && time<=24 || time<4 && time>=0)

{puts("Good Night!");

return 0;

}

if (time >= 4 && time < 11)

138

{puts("Good Morning!"); return 0;

}

if (time >= 11 && time < 15)

{puts("Good Day!"); return 0;

}

if (time >= 15 && time < 17) { puts("Good Afternoon!");

return 0;

}

if (time >= 17 && time < 22)

{puts("Good Evening!"); return 0;

}

puts("Error!!!"); return 0;

}

Результат выполнения программы:

Print time (from 0 to 24): 20<ENTER>

Good Evening!

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

ЗАДАЧА 05-06. Испытуемый при тестировании может получить некоторое количество очков от 0 до 100. По результатам тестирования выставляется оценка в баллах:

от 0 до 20 – 2 балла; от 21 до 40 – 3 балла; от 41 до 80 – 4 балла; от 81 до 100 – 5 баллов.

Ввести количество очков тестирования, вывести соответствующий балл.

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

139

/* 05_06.c - очки тестирования и оценки в баллах */ #include <stdio.h>

int main ()

{

int testPoints;

printf("Input points (from 0 to 100): "); scanf("%d",&testPoints);

if (testPoints >= 0 && testPoints < 21) puts("The mark is 2!");

else

if (testPoints >= 21 && testPoints < 41) puts("The mark is 3!");

else

if (testPoints >= 41 && testPoints < 81) puts("The mark is 4!");

else

if (testPoints >= 81 && testPoints < 101) puts("The mark is 5!");

else puts("Error!!!");

return 0;

}

Результат первого выполнения программы:

Input points (from 0 to 100): -12<ENTER> Error!!!

Результат второго выполнения программы:

Input points (from 0 to 100): 47<ENTER>

The mark is 4!

5.2. Переключатели (switch)

Применение переключателей (оператор switch) наиболее целесообразно в том случае, когда ветвления нужно выполнить на основе сравнения значения некоторого выражения (например, переменной) с фиксированным набором значений. Часто это удобно при программировании меню. В качестве упражнения рассмотрим следующую задачу, в некотором смысле обратную 05-05 и 05-06.

140