Министерство образования Республики Беларусь
Министерство образования и науки Российской федерации
ГУВПО «Белорусско-Российский университет»
Институт повышения квалификации и переподготовки кадров
Кафедра "Совершенствование профессиональных знаний"
Дисциплина
«Основы алгоритмизации и программирования на языках высокого уровня»
Лабораторная работа № 4
Циклические алгоритмы.
Работа с функциями, возвращающими значения.
2011
Цель работы
Получение навыков в написании программ с использованием функций, возвращающих значение.
Изучение механизма передачи данных по значению.
Техническое обеспечение
Персональная ЭВМ IBM PC/286 и более поздних моделей.
Клавиатура.
Дисплей.
Печатающее устройство.
Программное обеспечение
Операционная система MS DOS версия 5.0 и более поздние версии.
Система программирования Borland C++ версия 3.1 и более поздние версии.
Постановка задачи
Вывести таблицу значений функции на заданном отрезке.
Вычисление значений конечной суммы или произведения.
Вычисление значений бесконечной суммы или произведения с точностью .
Содержание отчета
5.1. Тема и цель работы.
5.2. Схема алгоритма решения задачи.
5.3. Текст программы.
5.4. Результаты выполнения программы.
Общие сведения
В языке С и в других современных языках программирования операторы цикла (итераций) позволяют выполнять набор инструкций до тех пор, пока не выполнится некоторое условие.
Оператор цикла for
Стандартный вид цикла for следующий:
for(инициализация; условие; увеличение) оператор;
Оператор for имеет три главные части:
1) Инициализация – это место, где обычно находится оператор присваивания, используемый для установки начального значения переменной цикла.
2) Условие – это место, где находится выражение, определяющее условие работы цикла.
3) Увеличение – это место, где определяется характер изменения переменной цикла на каждой итерацию.
Эти три важные части разделяются точкой с запятой. Цикл for работает до тех пор, пока условие истинно. Когда условие становится ложным, выполнение программы продолжается с оператора, следующего за циклом for.
В ниже приведенном простом примере осуществляется вывод чисел от 1 до 100 включительно:
#include <stdio.h>
int main(void)
{
int x;
for(x=1; x<=100; x++) printf(“%d “, x);
return 0;
}
В программе переменная x изначально установлена в 1. Поскольку x меньше 100, вызывается функция printf() для вывода текущего значения x, после чего x увеличивается на 1 и проверяется условие: по-прежнему ли x меньше либо равно 100. Данный процесс продолжается до тех пор, пока x не станет больше 100, и в этот момент цикл прервется. В данном примере x является переменной цикла, которая изменяется и проверяется на каждой итерации цикла.
Ниже приведен пример цикла for, повторяющего сразу несколько операторов:
for(x=100; x!=65; x=5) {
z = sqrt(x);
printf(“Корень квадратный из %d равен %f\n);
}
Как sqrt(), так и printf(), вызываются и выполняются, пока x не равно 65. Следует обратить внимание, что в цикле переменная x уменьшается: сначала она получает значение 100 и на каждой итерации цикла происходит уменьшение на 5.
Важно понять, что в цикле for проверка условия выполняется в самом начале. Это означает, что код в цикле может вообще не выполняться, если условие изначально ложно. Например:
x = 10;
for(y=10; y!=x; ++y) printf(“%d”,y);
printf(“%d”,y);
Данный цикл никогда не выполняется, поскольку x и y равны между собой на момент начала цикла. Поскольку условие ложно, не выполняется ни тело цикла, ни часть увеличения. Следовательно, y по-прежнему будет содержать значение 10 и в результате на экране мы увидим число 10.
Вариации цикла for. Имеется несколько вариаций цикла for, увеличивающих гибкость и мощь в некоторых ситуациях.
Одна из наиболее типичных вариаций достигается с использованием операции «запятая», тем самым позволяя иметь две или более переменных цикла. Например, данный цикл использует переменные x и y для управления циклом и обе эти переменные инициализируются в операторе for:
for(x=0, y=0; x+y<10; ++x) {
scanf(“%d”, &y);
.
.
.
}
Здесь операция «запятая» разделяет два инициализационных оператора. При каждом увеличении x цикл повторяется и значение y вводится с клавиатуры. Как x, так и y должны иметь корректное значение для окончания цикла. Необходимо инициализировать переменную y нулем, поэтому ее значение определяется перед первым вычислением выражения условия. Если бы y не была определена, то имелся бы шанс, что в результате предыдущей работы программы она содержала 10, тем самым делая условие проверки ложным и запрещая выполнение тела цикла.
Другой пример использования нескольких переменных цикла можно найти в показанной функции reverse(). Она предназначена для копирования содержимого первого строкового аргумента во второй строковый аргумент в обратном порядке.
/* Копирование s в r в обратном порядке */
void reverse(char *s, char *r)
{
int i, j;
for(i=strlen(s)-1, j=0; i>=0; j++, i--) r[i] = s[j];
r[j] = ‘\0’; /* присоединение завершающего символа */
}
Здесь strlen() – это стандартная библиотечная функция, возвращающая количество символов в строке.
Не обязательно в качестве условия использовать простое сравнение переменной цикла с некоторым целевым значением. Фактически условием может выступать любое выражение отношения или логическое выражение. Например, данная функция может быть использована для отметки пользователя на удаленной системе. Пользователю предоставляется три шанса ввести пароль. Цикл оканчивается в случае использования трех попыток или введения правильного пароля:
void reg_on(void)
{
char str[20];
int x;
for(x=0; x<3 && strcmp(str,”password”); x++) {
printf(“Введите, пожалуйста, пароль: ”);
gets(str);
}
if(x==3) hang_up();
}
Следует помнить, что strcmp() – это стандартная библиотечная функция, выполняющая сравнение двух строк и возвращающая 0 в результате их совпадения.
Другая интересная вариация цикла for основана на том, что любая из трех частей цикла может содержать любое корректное выражение. Эти выражения могут и не выполнять действий, характерных для данной части. Рассмотрим следующий пример:
#include <stdio.h>
int readnum(void), prompt(void);
int sqrnum(int num);
int main(void)
{
int t;
for(prompt(); t=readnum(); prompt())
sqrnum(t);
return 0;
}
int prompt(void)
{
printf(“==> “
}
int readnum(void)
{
int t;
scanf(“%d”, &t);
return t;
}
int sqrnum(int num)
{
printf(“%d\n”, num*num);
return 0;
}
Если внимательно посмотреть на цикл for в main(), то можно увидеть, что каждая часть цикла содержит вызовы функций, которые осуществляют подсказку (prompt()) и чтение вводимого с клавиатуры числа (readnum()). Если введенное число равно нулю, цикл оканчивается, поскольку условие ложно, иначе число возводится в квадрат (sqrnum()). Следовательно, в данном цикле части инициализации и увеличения используются не традиционно, но абсолютно корректно.
Еще один интересный момент цикла for – это необязательность наличия какой-либо части. Практически можно опустить любую часть. Например, следующий цикл работает до тех пор, пока не будет введено 123:
for(x=0; x!=123;) scanf(“%d”, &x);
Следует обратить внимание, что часть увеличения отсутствует. Это означает, что на каждой итерации цикла x проверяется на совпадение с числом 123, но больше ничего не выполняется. Если ввести с клавиатуры 123, условие станет ложным и цикл прекратится.
Часто можно видеть часть инициализации вне цикла for. Это встречается, когда начальное состояние переменной цикла вычисляется неким сложным образом. Например:
gets(s); /* чтение строки s */
if(*s) x = strlen(s); /* получение длины строки */
for( ; x<10; )
printf(“%d”, x);
++z;
}
Здесь часть инициализации пуста и x инициализируется до входа в цикл.
Бесконечный цикл. Одним из наиболее интересных аспектов использования цикла for является создание бесконечного цикла. Поскольку не требуется ни одна из частей, можно создать бесконечный цикл путем удаления части проверки условия. Например:
for( ; ; ) printf(“Это бесконечный цикл\n”);
Хотя можно использовать части инициализации и увеличения, наиболее типично использование for(;;) без выражений для создания бесконечного цикла.
На самом деле конструкция for(;;) не обязательно создает бесконечный цикл, поскольку в теле цикла может присутствовать оператор break, при достижении которого цикл оканчивает работу. Нижеприведенная программа контролирует нажатие клавиш и, в случае достижения необходимого условия, бесконечный цикл прерывается:
for( ; ; ) {
ch = getchar(); /*n ввод символа */
if(ch == ‘A’) break; /* выход из цикла */
}
printf(“Введен символ А”);
Цикл будет работать до тех пор, пока на клавиатуре не будет набран символ А.
Циклы for без тела. Оператор может быть пустым. Это означает, что тело цикла for (или любого другого цикла) может быть пустым. Это можно использовать для улучшения эффективности некоторых алгоритмов, а также для создания задержек.
Одной из наиболее типичных задач программирования является удаление пробелов из потока ввода. Следующий цикл удаляет все пробелы из потока, на который указывает str:
for( ; *str == ‘ ‘; str++);
Как видно, в цикле отсутствует тело.
В программах также часто используются циклы задержек. Это показывает следующий пример:
for(t=0; t<SOME_VALUE; t++);
