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

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

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

ЗАДАЧА 05-07. Выведите на экран список вида:

1 – night;

2 – morning;

3 – day;

4 – afternoon;

5 – evening. ֽ

Вводя номер пункта списка, напечатайте временные пределы, ограничивающие соответствующее время суток: 22–3 (night); 4–

10 (morning); 11–14 (day); 15–16 (afternoon); 17–21 (evening).

/* 05_07.c - время суток (switch...break) */ #include <stdio.h>

int main ()

{

int item;

puts("1. Night;"); puts("2. Morning;"); puts("3. Day;"); puts("4. Afternoon;"); puts("5. Evening.");

puts("Print item number:"); scanf("%d",&item);

switch(item)

{ case 1: puts("From 22 to 3 - Night"); break;

case 2: puts("From 4 to 10 - Morning"); break;

case 3: puts("From 11 to 14 - Day"); break;

case 4: puts("From 15 to 16 - Afternoon"); break;

case 5: puts("From 17 to 21 - Evening"); break;

default: puts("Error!");

}

return 0;

}

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

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

1.Night;

2.Morning;

141

3.Day;

4.Afternoon;

5.Evening.

Print item number: 3<ENTER>

From 11 to 14 - Day

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

1.Night;

2.Morning;

3.Day;

4.Afternoon;

5.Evening.

Print item number: 7<ENTER>

Error!

ЭКСПЕРИМЕНТ. Удалите из программы все операторы break. После трансляции введите не последний номер списка и объясните результат.

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

ЗАДАЧА 05-08. Реализуйте указанный подход (переключатель с номером варианта) для печати английского приветствия:

Часы суток

Номер интервала

Приветствие

22

– 3

интервал 1

Good Night!

4 – 10

интервал 2

Good Morning!

11

– 14

интервал 3

Good Day!

15

– 16

интервал 4

Good Afternoon!

17

– 21

интервал 5

Good Evening!

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

/* 05_08.c - английские приветствия (swith + номер варианта:) */

142

#include <stdio.h> int main ()

{

int time;

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

switch(time<0 ? 0: time<4 ? 1: time<11 ? 2: time<15 ? 3: time<17 ? 4: time<22 ? 5: time<24 ? 1:0)

{ case 1: puts("Good Night!"); break;

case 2: puts("Good Morning!"); break;

case 3: puts("Good Day!"); break;

case 4: puts("Good Afternoon!"); break;

case 5: puts("Good Evening!"); break;

default: puts("Error!");

}

return 0;

}

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

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

Good Evening!

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

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

Error!

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

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

143

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

// 05_08_1.c - несколько меток ветви переключателя

#include <stdio.h> int main ()

{

int time;

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

switch(time)

{case 22: case 23: case 24:

case 0: case 1: case 2: case 3: puts("Good Night!"); break;

case 4: case 5: case 6: case 7: case 8: case 9: case 10:

puts("Good Morning!"); break;

case 11: case 12: case 13: case 14: puts("Good Day!");

break; case 15: case 16:

puts("Good Afternoon!"); break;

case 17: case 18: case 19: case 20: case 21: puts("Good Evening!");

break;

default: puts("Error!");

}

return 0;

}

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

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

Good Evening!

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

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

Good Day!

144

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

!управляющее выражение должно формировать целочисленное значение;

!после case (в метке варианта) может находиться только целочисленная константа (константное выражение);

!целочисленные константы, определяющие ветви одного переключателя, должны быть различны.

Придумать эксперимент, нарушающий приведенные правила.

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

ЗАДАЧА 05-09. Вводите целые числа и вычислите сумму положительных и сумму отрицательных чисел. Окончание работы – ввод нулевого числа.

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

/* 05_09.c - суммы положительных и отрицательных чисел */

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

{ printf(#VARIABLE"="); scanf("%d",&VARIABLE); } #define PRINTI(EXPRESSION) \

printf(#EXPRESSION"=%d\n",EXPRESSION) int main ()

{

int x, sumPlus=0, sumMinus=0; do { READI(x);

if (x < 0) sumMinus+=x;

else sumPlus+=x;

}

while(x != 0); PRINTI(sumPlus); PRINTI(sumMinus); return 0;

}

145

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

x=2<ENTER>

x=55<ENTER> x=-9<ENTER> x=6<ENTER> x=-23<ENTER> x=7<ENTER> x=0<ENTER> sumPlus=70 sumMinus=-32

В программе использован оператор цикла с постусловием.

ЗАДАНИЕ. Напишите программу для решения рассмотренной задачи с применением:

1) оператора цикла с предусловием (оператор while);

2) оператора параметрического цикла (оператор for).

Соответствующие программы 05_09_1.с и 05_09_2.с есть в электронном виде, но мы не стали приводить здесь их тексты из-за их простоты.

ЗАДАЧА 05-10. Введя значения двух целых чисел n и k, вычислить и напечатать (в три столбца) значения i, i2, i3, где i = n, k .

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

/* 05_10.c - числа, их квадраты и кубы */ #include <stdio.h>

#define READI(VARIABLE) \

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

{int i, n, k; READI(n); READI(k);

for (i=n; n<=k ? i<=k:i>=k; i += n <= k ? 1: -1) printf("\n%d\t%d\t%d",i,i*i,i*i*i);

return 0;

}

146

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

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

n=2<ENTER>

k=8<ENTER>

2

4

8

3

9

27

4

16

64

5

25

125

6

36

216

7

49

343

8

64

512

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

n=-4<ENTER> k=-10<ENTER>

-4

16

-64

-5

25

-125

-6

36

-216

-7

49

-343

-8

64

-512

-9

81

-729

-10

100

-1000

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

n=6<ENTER>

k=1<ENTER>

6

36

216

5

25

125

4

16

64

3

9

27

2

4

8

1

1

1

147

В программе использован параметрический цикл, параметр которого по-разному изменяется в зависимости от соотношения введенных значений переменных n и k. Если nk, то приращение параметра +1. В противном случае –1. Условие прекращения цикла также зависит от значений n и k. Если nk, то цикл следует продолжать, пока истинно условие ik. В противном случае условием продолжения цикла служит истинность отношения ik. Перечисленные правила воспроизведены в заголовке цикла с помощью условных выражений.

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

ЗАДАНИЕ. В заголовке цикла предыдущей программы измените следующим образом проверку продолжения итераций:

n<k ? i<=k : i>=k

Результаты выполнения программы, приведенные выше, не изменятся. Однако попытка выполнить программу при условии, когда n==k, приведет к зацикливанию.

ЭКСПЕРИМЕНТ. Выполните указанное в предыдущем задании изменение в программе, проверьте ее работоспособность при n не равном k, затем введите, например, n=3 и k=3.

Чтобы прервать исполнение программы, придется использовать сочетание двух клавиш: Ctrl+C.

ЗАДАНИЕ. Напишите программу для решения той же задачи с применением:

1) оператора цикла с предусловием (while);

2) оператора цикла с постусловием (do….while).

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

148

ЗАДАНИЕ. Сконструируйте другую программу для решения той же задачи на основе принципов поэтапной детализации алгоритма (нисходящее проектирование).

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

Ввести значение n Ввести значение k Если n<=k

Цикл от n до k с шагом 1 Печать i, i2, i3

Конец-цикла Иначе

Цикл от n до k с шагом –1 Печать i, i2, i3

Конец-цикла Все-если

Приведенный псевдокод можно непосредственно перевести в операторы языка Си:

/* 05_10_1.c - числа, их квадраты и кубы */ #include <stdio.h>

#define READI(VARIABLE) \

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

{

int i, n, k; READI(n); READI(k); if(n<=k)

for (i=n; i<=k; i++) printf("\n%d\t%d\t%d",i,i*i,i*i*i);

else

for (i=n; i>=k; i--) printf("\n%d\t%d\t%d",i,i*i,i*i*i);

return 0;

}

149

Результаты выполнения программы при тех же исходных данных полностью совпадают с результатами программы 05_10.с:

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

ЗАДАЧА 05-11. Определите "машинный нуль" относительно вводимого с клавиатуры вещественного числа. При вводе вещественного числа выполните проверку его положительности. При нарушении этого условия напечатайте предупреждающее сообщение и повторите ввод.

В следующей программе задача решена для чисел, представляемых в программе переменными типа double.

/* 05_11.c - машинный ноль для числа типа double */ #include <stdio.h>

int main ()

{

double real, estimate, zero; do { printf("\nreal=");

scanf("%le",&real);

if (real > 0.0) break; printf("real<=0 !!!");

}

while(1);

for (zero=real,estimate=real; estimate=real+zero, estimate != real; zero/=2) printf("\nestimate=%e\tzero=%e",

estimate,zero);

return 0;

}

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

real=-16<ENTER> real<=0 !!!

real=0<ENTER> real<=0 !!!

150