Программы разветвлённой структуры
СОДЕРЖАНИЕ
Введение …………………………………………………………………………. 3
Лабораторная работа №1. Работа в интегрированной среде BORLAND C
на примере программ линейной структуры……………..……………………….. 3
Лабораторная работа № 2 Программы разветвленной структуры……..…….…5
Лабораторная работа № 3Программы циклической структуры……….….… 9
Лабораторная работа № 4Обработка статических массивов………..………..11
Лабораторная работа № 5Работа с символьными данными ………..………...13
Лабораторная работа № 6Функции …………………………………………...15
Лабораторная работа № 7Рекурсии..……..………………………….……..…...20
Лабораторная работа № 8Структуры….…………………………….……..…...21
Лабораторная работа № 9Программные средства для работы с файлами……24
Лабораторная работа № 10 Обработка бинарных файлов в прямом режиме ..27
Лабораторная работа № 11 Динамические массивы…………………………...32
Лабораторная работа № 12 Динамические структуры данных………………...36
Введение
Язык Си является универсальным языком программирования. Первоначально он появился в операционной системе UNIX, и развивался как основной язык систем, совместимых с ОС UNIX. Сам язык, однако, не связан с какой-либо одной операционной системой или машиной; и хотя его называют языком системного программирования, так как он удобен для написания операционных систем, он может использоваться для написания любых больших вычислительных программ, программ для обработки текстов и баз данных.
Лабораторная работа №1
Работа в интегрированной среде Borland С на примере программ линейной структуры
1. ЦЕЛЬ РАБОТЫ: приобретение практических навыков работы в интегрированной среде Borland C, изучение структуры программы на языке С.
ОСНОВНЫЕ СВЕДЕНИЯ
Чаще всего линейные алгоритмы используются для программирования вычислений по формулам. В этом случае удобно использовать набор стандартных функций Си, содержащихся в заголовочном файле math.h :
Sin (x) - sin x; cos (x) – cos x ; tan(x) - tg х ; log (x) - ln x; log10(x) – lg x; exp(x) - показательная функция ex ; sqrt (x)- корень квадратный от х; роw(x, y) – x в степени y; abs(x)- модуль x.; acos(x) – arccos x; asin(x) – arcsin x; atan(x)- arctg x; sinh(x)- sh x; cosh (x) – ch x; tanh(x)-th x.
Для тригонометрических функций аргумент х измеряется в радианах и имеет тип double, как и значения функций.
Пример программы линейной структуры:
Вычислить площадь и стороны прямоугольного треугольника, если известны гипотенуза c и угол x. Для вычислений воспользуемся формулами :
a=c×sin x; b=c×cos x; S=ab ;
Программа вычислений имеет вид:
//lab1_1 вычисление высот и площади треугольника
#include <stdio.h> //заголовочный файл для организации ввода-вывода
#include <math.h> //заголовочный файл математических функций
main() //главная функция
{ float a,b,c,x, S; //описание переменных вещественного типа
printf (“\n Введите гипотенузу и угол треугольника ”);
scanf (“%f%f “,&c,&x); // ввод значений вещественного типа
a=c*sin(x);
b=c*cos(x);
S=a*b;
printf (“\n Результаты: a=%7.2f b=%7.2f S=%7.2f “,a, b, S);
return 0;
}
Комментарий в программе не влияет на компиляцию программы, а служит для разъяснения действий основных блоков текста и программы в целом. Однострочный комментарий действует от двух символов // до конца строки. Многострочный комментарий заключается в пары символов /* и */.
Вторая строка программы #include <stdio.h> является директивой компилятора для включения заголовочного файла stdio.h , в котором содержатся средства ввода-вывода (связи с внешними устройствами), отсутствующие в самом языке Си. Третья строка - #include<math.h> является директивой компилятора для включения заголовочного файла math.h, обеспечивающего выполнение математических функций.
Программа на языке Си состоит из ряда функций, из которых функция main (главная) является обязательной и служит точкой входа в программу. В круглые скобки заключаются параметры функции, причем наличие круглых скобок обязательно, если даже список параметров пуст. В фигурные скобки заключаются составной оператор (несколько операторов). Для придания тексту программы наглядности открывающая и соответствующая ей закрывающая фигурные скобки печатаются на одном уровне, а заключенный между ними текст, сдвигается на 1-2 символа вправо, вложенный блок также сдвигается вправо и т.д. Образуется иерархия вложенных блоков, придающая программе на Си характерный вид.
В программе описаны переменные a, b, c, х, S вещественного типа (float). В отличие от других языков в Си учитывается регистр при определении имени переменной, т.е. s и S – разные переменные. Функции printf и scanf содержатся в заголовочном файле stdio.h и служат для вывода на экран и ввода с клавиатуры соответственно. Управляющие символы \n в функции printf служат для перевода на новую строку. Символ & в функции scanf указывает на адрес вводимой переменной. Ввод и вывод переменных вещественного типа производится в формате f. Признаком форматного вывода в функции printf является %. При выводе между знаком процента и форматной переменной f можно включить общую ширину поля вывода и число позиций после десятичной точки. Оператор return 0; служит для выхода из функции main в Интегрированную Среду, 0 является признаком успешного окончания программы. Завершает текст программы закрывающая фигурная скобка, означающая конец функции main.
ВЫПОЛНЕНИЕ РАБОТЫ
3.1. Наберите и выполните приведенную выше программу вычисления высот треугольника по заданным сторонам.
3.2. Составьте и выполните программу линейной структуры согласно вариантам заданий.
Варианты заданий
Вычислить значение функции переменных при заданных значениях параметров:
1. x=4y2/(4z-2t3) при t=1 ; z=3; y=sin t.
2 x=4y3-z/t при t=2; z=3; y=cos(t+z).
3. x=6t2-(z+1)/y2 при y=2; z=4; t=sin(2+z).
4. x=(8z2+1)/(y+t2) при z=1; t=2; y=t+z.
5 x=8z / (et+2)-y2 при t=3; z=ctg t +2; y=4.
6. x=8z/(et+2)-y2 при t=1; z=t+2; y=4.
7. x=2y+3 sh t- z при y=2; t=5 / (1+y2); z=4
8. x=3 y2/ (4 tg z-2t2) при t=0.5; z=6; y=t+2 ctg z.
9. x=4y2 /( 4y ez - 2t3) при t=1 ; z=3; y=sin t.
10. x=4 ln y3-z / t при t=2; z=3; y=cos(t+z).
11. x=6 t2- (ctg z+1)/ y2 при y=2; z=4; t=sin(2+z).
12. x=(8z2+1)/( y et +t2) при z=1; t=2; y=tg t+z.
КОНТРОЛЬНЫЕ ВОПРОСЫ
4.1. Что такое алгоритм линейной структуры, программа линейной структуры?
4.2. Для чего используются заголовочные файлы?
4.3. Структура программы на языке Си.
Лабораторная работа №2
ОСНОВНЫЕ СВЕДЕНИЯ
Алгоритм разветвленной структуры - это алгоритм, в котором вычислительный процесс осуществляется по одной из ветвей. Если количество ветвей две – то используется условный блок, если больше – то множественный выбор. В программах используют соответственно условный оператор IF или оператор SWITCH для реализации разветвленного алгоритма.
Условный оператор IF
Условный оператор в языке Си имеет формат:
if (условие)
оператор1;
else
оператор2;
(полная форма) или
if (условие) оператор1; (сокращенная форма).
Если оператор1 и оператор2 состоят из одного оператора, то в фигурные скобки они не заключаются. Если оператор1 и/или оператор2 являются составным оператором (несколько операторов), то он заключается в фигурные скобки. Условие всегда заключается в круглые скобки.
В качестве примера приведем программу вычисления наибольшего из значений функции y1=x²+1, y2=7-x² , y3=x+1 для любого х.
//lab2_1
#include <stdio.h>
main()
{ float x,y1,y2,y3,max;
printf("Введите x\n"); scanf(“%f “,&x);
y1=x*x+1; y2=7-x*x; y3=x+1;
if (y1>y2)
max=y1;
else
max=y2;
if (y3>max)
max=y3;
printf (“x=%8.2f y1=%8.2f y2=%8.2f y3=%8.2f max=%8.2f\n”,x,y1,y2,y3,max);
}
Множественный выбор
В программах с множественным выбором используется переключатель switch , который сравнивает значение выражения, указанного за ним, и выполняет один из операторов, метка которого совпадает с этим значением. Общий вид:
Switch (выражение)
{ case метка_1: список_операторов_1;
……………………………………….
case метка_n: список_операторов_n;
default : операторы; }
Значения выражения и меток должны быть целочисленными константами.
Например, определим количество дней по введенному номеру месяца.
//lab2_2 множественный выбор
#include<stdio.h>
#include<conio.h> // Заголовочный файл для работы с терминалом
int m;
main()
{
printf("\n Введите номер месяца :"); scanf("%d",&m);
printf("\n В %4d месяце дней: ",m);
switch(m){
case 1:case 3:case 5: case 7:case 8:case 10:case 12:printf("тридцать один\n");break;
case 2: printf ("двадцать восемь \n");break;
case 4: case 6: case 9: case 11: printf("тридцать\n");break;
default: printf("\n Номер месяца неверен \n");}
getch (); }
В примере программы, если номер месяца превышает 12, выводится сообщение о неверном вводе месяца, для чего используется default. Оператор break служит для прерывания цикла проверки и перехода в конец переключателя. В случае отсутствия break, происходит переход на следующую ветвь.
Функция getch, подключающаяся заголовочным файлом conio.h, ожидает нажатия любой клавиши. Это позволяет просмотреть результаты, не используя ALT+F5 для просмотра экрана пользователя.
ВЫПОЛНЕНИЕ РАБОТЫ
Составить программы разветвляющейся структуры согласно вариантам задания 1 (используя IF) и задания 2 (используя SWITCH) .
Варианты задания 1
1) Даны четыре числа. На сколько их сумма меньше их произведения?
2) Даны четыре числа. Вычислить сумму положительных среди них чисел.
3) Даны четыре числа. Вычислить произведение отрицательных среди них чисел.
4) Даны четыре числа. Все отрицательные среди них числа заменить на 0.
5) Даны четыре числа. Определить сколько среди них отрицательных и сколько положительных.
6) Даны четыре числа. Определить порядковый номер наименьшего среди них.
7) Даны два числа. Большее из этих двух чисел заменить их полусуммой, а меньшее удвоенным произведением.
8) Даны три числа. Меньшее среди них заменить на 0 .
9) Даны четыре числа. Найти разность между наибольшим и наименьшим среди них.
10) Даны три числа K, M и N. Поменять их значения местами таким образом, чтобы K < M < N.
11) Даны четыре разных числа. Найти среди них два наибольших.
12) Даны три числа. Поменять местами большее и меньшее из этих чисел.
Варианты задания 2
Предусмотреть ситуацию неправильного ввода исходных данных.
1) Вводится число программ N<=20. Напечатать фразу "Я разработал N программ", согласовав слово "программа" с числом N.
2) Вводится число экзаменов N<=20. Напечатать фразу "Мы успешно сдали N экзаменов", согласовав слово "экзамен" с числом N.
3) Вводится число лет (N<=25). Напечатать фразу "Мне N лет", согласовав слово "лет, год, года" с числом N.
4) Вводится число студентов N<=30. Вывести фразу "В нашей группе N студентов", согласовав слово "студент" с числом N.
5) Вводится число М - номер месяца. Определить номер квартала по введенному номеру месяца и номер полугодия.
6) Вводится число М - номер месяца. Определить время года по введенному номеру месяца и номер полугодия.
7) Вводится целое число С. Если -9<=c<=9 вывести величину числа в словесной форме с учетом знака, в противном случае - предупреждающее сообщение и повторный ввод.
8) Вводится номер семестра N<=10. Вывести фразу "Я проучился N семестров", согласовав слово "семестр" с числом N. Определить номер курса.
9) В китайском гороскопе года носят следующие названия: крыса, корова, тигр, заяц, дракон, змея, лошадь, овца, обезьяна, петух, собака, свинья. Учитывая, что 1996 – год крысы, написать программу, определяющую название года по его номеру.
10) Вводится число Т – порядковый день в году. Определить номер месяца М и дня недели D, соответствующих Т.(Например, если Т=365 . то М=12, а D=31)
11) Вводится номер месяца М и дня D. Определить порядковый номер дня в году Т соответсвующий этой дате.
12) Вводится номер месяца М и дня D. Определить день недели с датой М и D, считая, что год начинается с понедельника.
КОНТРОЛЬНЫЕ ВОПРОСЫ
4.1. Сравните виды условных операторов Си.
4.2. Всегда ли ставятся скобки и какие в условном операторе?
4.3. Зачем ставятся в переключателе операторы break и default?
4.4. Как будет работать программа из примера без break?
Лабораторная работа №3
ОСНОВНЫЕ СВЕДЕНИЯ
Операторы циклов
В языке Си существует 3 вида циклов: 1) цикл с параметром или цикл типа for; 2) цикл с предусловием или цикл типа while, 3) цикл с постусловием или цикл типа do ... while. Во всех этих циклах условие продолжения цикла заключается в круглые скобки. В циклах типов for и while повторяющаяся часть состоит из одного оператора, если требуется выполнить в цикле несколько операторов, они заключаются в фигурные скобки, образуя составной оператор. В цикле с постусловием тело цикла помещается между словами do и while. В отличие от цикла с предусловием, цикл с постусловием выполнится хотя бы один раз. Циклы с пред- и постусловием продолжаются, если условие продолжения истинно.
Цикл с параметром
Цикл forиспользуется тогда, когда количество повторений цикла заранее известно или может быть вычислено. Цикл forсостоит из заголовка и тела цикла. В заголовке после слова forв круглых скобках записываются через точку с запятой три выражения:
А) начальные значения: операторы присваивания, которые выполняются один раз перед выполнением цикла;
В) условие, при котором выполняется следующий шаг цикла; если условие неверно, работа цикла заканчивается; если оно неверно в самом начале, цикл не выполняется ни одного раза (говорят, что это цикл с предусловием, то есть условие проверяется перед выполнением цикла);
С)действия в конце каждого шагацикла (в большинстве случаев это операторы присваивания).
В каждой части заголовка может быть несколько операторов, разделенных запятыми.
Примеры заголовков:
for ( i = 0; i < 10; i ++ ) { ... }
for ( i = 0, x = 1.; i < 10; i += 2, x *= 0.1 ){ ... }
• Тело цикла заключается в фигурные скобки; если в теле цикла стоит всего один оператор, скобки можно не ставить.
• В тело цикла могут входить любые другие операторы, в том числе и другие циклы (такой прием называется «вложенные циклы»).
• Для того, чтобы легче разобраться в программе, все тело цикла и ограничивающие его скобки сдвигаются вправо на 2-3 символа (запись «лесенкой»).
Пример вычисления суммы квадратов натурального ряда чисел от 1 до n.
S= = 12 + 2 2 + . . . + n 2.
//lab3_1 сумма квадратов натурального ряда
#include <stdio.h>
main()
{ int S,n,i;
printf(“Введите n ”); scanf(“%d”,&n);
for (S=0, i=1; i<=n; i++)
S+=i*i; // соответствует S=S+i*i
printf (“n=%d S=%d”,n,S);
}
В разделе инициализации присваиваются начальные значения переменным S и i. При i, не превышающем n, цикл повторяется, иначе выполняется выход из цикла. Оператор инкремента i++ (или декремента i--), эквивалентен i=i +1 (i=i-1). Для досрочного выхода из цикла и перехода на следующий оператор после цикла используется оператор break. Для пропуска всех операторов, оставшихся до конца тела цикла и перехода к следующему повторению цикла используется оператор continue.
ВЫПОЛНЕНИЕ РАБОТЫ
Составить 3 варианта программ циклической структуры типа for и while, сравнить полученные результаты.
Варианты заданий
1. . 2. .
3. . 4. .
5. . 6. .
7. 8.
9. . 10. .
11. 12.
КОНТРОЛЬНЫЕ ВОПРОСЫ
4.1. Какой алгоритм является алгоритмом циклической структуры?
4.2. Типы циклов в языке Си.
4.3. Какой цикл выполнится хотя бы один раз? А какой - ни разу?
Лабораторная работа №4
ОСНОВНЫЕ СВЕДЕНИЯ
Массивы - структурированный тип данных с элементами одного и того же типа, имеющий одно имя и определенное количество элементов. Количество элементов определяет размер массива. Порядковый номер элемента массива называется его индексом. Число индексов называется размерностью массива, например, массив с двумя индексами называется двумерным массивом. Строка символов является массивом символов, вектор – массив чисел, матрица – массив векторов. Обработка массивов выполняется следующим образом: объявление, ввод или инициализация элементов массива, преобразование и вывод.
Объявление массива
Чтобы использовать массив, надо его объявить – выделить место в памяти компьютера, объём которой зависит от количества элементов и типа массива. Тип массива - это тип входящих в него элементов. Массивы могут быть разных типов:
— int, float, char, и т.д. Массив объявляют так же, как и обычные переменные, но после имени массива в квадратных скобках записывается его размер.
int A[10], B[20]; // 2 массива по 10 и 20 целых чисел
float C[12]; // массив из 12 вещественных чисел
При объявлении массива можно сразу заполнить его начальными значениями, перечисляя их внутри фигурных скобок:
int A[4] = { 2, 3, 12, 76 };
Если в списке в фигурных скобках записано меньше чисел, чем элементов в массиве, то оставшиеся элементы заполняются нулями. Если чисел больше, чем надо, компилятор сообщает об ошибке. Например,
int A[4] = { 2 }; // последние три элемента равны 0
Для повышения универсальности программы размер массива лучше определять через константу. В этом случае для переделки программы для массива другого размера надо только поменять значение этой константы:
const int N = 20; //N - константа
main()
{
int A[N]; // размер массива задан через константу
...
}
Пример обработки одномерного массива
Дан массив из 50 целых чисел. Найти наибольший элемент в массиве и его порядковый номер.
# include <stdio.h>
#include <conio.h>
# define n 50 // определение константы n=50
int i, max, nom, a[n]; //описание массива целых чисел из n элементов
main()
{ for (i=0; i<n; i++)
{ printf( “\n Введите элемент массива ”);
scanf ("%d", &a[i]) };
for (i=1,max=a[0],nom=0; i<n; i++)
if (max<a[i])
{nom=i; max=a[i];}
printf("\n Вывод элементов исходного массива : \n");
for (i=0; i<n; i++) printf ( "%6d", a[i] );
printf ("\n Максимальное число в массиве %4d, его индекс %4d " , max, nom+1);
getch();
}
ВЫПОЛНЕНИЕ РАБОТЫ
Даны вещественные числа a,b. Значения функции (согласно вариантам) записать в массив. Вычислить значение интеграла, используя:
1) Формулу трапеций
I1=h*[f(a)/2+f(a+h)+f(a+2h)+…+f(a+(n-1)h)+f(b)/2]
2) Формулу Симпсона
I2=h/3*(f(a)+f(b)+4*(f(a+h)+f(a+2h)+…+f(a+(n-1)h))+
2*(f(a+2h)+f(a+4h)+…+f(a+(n-2)h)))
h=(b-a)/n, n=100.
Варианты заданий
1. f(x)=x2/(10+x3); a=-2; b=5;
2. f(x)=(2.5x2-0.1)/(tg x+sin x); a=4; b=6;
3. f(x)=(x+1)2√lg x; a=2; b=10;
4. f(x)=x2 ln x /(1+x)2; a=1; b=20;
5. f(x)=1/((0.5+0.1x3)√x); a=0.1; b=2.1;
6. f(x)=x 2√(2+3x)3; a=0.5; b=2.5;
7. f(x)=1/√(0.02+0.01x); a=1; b=30;
8. f(x)=(1+2x+x2)/(5+2x2); a=-2; b=2;
9. f(x)=(2x+lg x)/(1+lg x); a=1; b=10;
10. f(x)=√(2+x)3/x2; a=0.2; b=10;
11. f(x)=(1+x2)/(x3+√(1+x)); a=0.5; b=5;
12. f(x)=(1-x) lg x/√(1-lg x); a=2; b=7;
КОНТРОЛЬНЫЕ ВОПРОСЫ
4.1. Что такое массив? индекс элемента массива?
4.2. Как ввести и вывести элементы вектора в строку и в столбец?
4.3. Способы описания и инициализации массивов.
Лабораторная работа №5
ОСНОВНЫЕ СВЕДЕНИЯ
Символьная константа - это символ (единственный), заключенный в одиночные кавычки, как, например, 'Х'. Значением символьной константы является численное значение этого символа в машинном представлении набора символов. Все символы упорядочены в соответствии с принятым в ПК коде (например ASCII). При этом порядковый номер символов называется кодом (например, код латинского символа 'А ' равен 65; символа '3' равен 51). Для символьных данных не определены никакие арифметические операции, но они могут сравниваться по своим кодам, участвовать в чтении, печати, операторах присваивания.
Строка - это последовательность (массив) символов, заключенная в двойные кавычки, заканчивающаяся нуль-символом (\0 – символ с кодом равным нолю). По положению нуль-символа определяется фактическая длина строки. Например, длина строки char text[ ] = "Моя программа!" равна 14 байт (включая пробел).
Для форматного ввода и вывода символьных констант используется спецификатор %с, строк - %s и специальные функции: getchar(),gets()- ввод и putchar(), puts()-вывод. Библиотека Си содержит функции обработки строк, прототипы которых определяются в заголовочном файле string.h. Например:
strlen(str) – определяет длину строки str;
strcat(str1,str2) - сцепление строк в порядке их перечисления;
strncat(str1,str2,kol) – приписывает kol символов строки str2 к строке str1;
strcmp(str1,str2) – сравнивает две строки str1 и str2 и возвращает 0, если они одинаковы; результат отрицателен, если str1<str2 и положителен, если str1>str2;
strncmp(str1, str2, kol) – сравниваются части строк str1 и str2 из kol символов. Результат равен 0, если они одинаковы.
strcpy(str1,str2) – копирует строку str2 в строку str1.
Рассмотрим пример:
// lab6_1
#include <stdio.h>
#include <conio.h>
#include <string.h>
main ( )
{ char gwords [10] [40], temp [40];
int i=0;
printf (“Введите 10 слов, начинающихся с д: \n”);
while ( i < 10 )
{ gets (temp);
if (temp [0] != ‘д’) // проверка первого символа
printf (“ %s не начинается с д! \n”, temp);
else { strcpy (gwords [i], temp); i++;}
}
puts (“Следующие слова соответствуют условию:”);
for (i=0; i< 10; i++) puts (gwords [i] );
getch();
return 0;
}
Вводятся слова, сравнивается первый символ, если это не 'д', то вводится следующее слово, иначе слово копируется в новый массив слов gwords.
ВЫПОЛНЕНИЕ РАБОТЫ
1. Выполнить приведенную выше программу с разными исходными данными.
2. Текст вводится с клавиатуры в виде массива слов. Исходный текст и результаты распечатать. Составить программы согласно вариантам заданий.
Варианты заданий
1. Вывести на печать список слов, имеющих приставку (несколько букв), задаваемую с терминала.
2. Раздвинуть заданный текст, вставив введенную с клавиатуры последовательность символов после 1-го символа каждого слова.
3. В заданном тексте слова разделены запятыми. Напечатать список слов, начинающихся с символа, введенного с клавиатуры.
4. Определить наличие слов в заданном тексте, содержащих сочетание символов, задаваемое с экрана.
5. Из заданной последовательности слов удалить слова, содержащие числа.
6. Каждое слово текста переписать наоборот.
7. Подсчитать количество слов, содержащих k гласных букв (k-задается с экрана).
8. Из введенного текста сначала распечатать слова, заканчивающиеся на согласную букву, а потом на гласную букву.
9. Во введенном тексте найти повторяющиеся слова.
10. Список фамилий вводится через запятую в виде строки. Упорядочить фамилии по алфавиту.
11. Из введенного текста распечатать отдельно гласные и согласные каждого слова.
12. Из введенного текста распечатать слова, в порядке убывания частоты повторения.
КОНТРОЛЬНЫЕ ВОПРОСЫ
4.1. Ввод и вывод символов и строк.
4.2. Функции для работы со строками.
4.3. Чем отличается инициализация символа от инициализации строки?
Лабораторная работа № 6
Функции
1. ЦЕЛЬ РАБОТЫ: Изучение методов использования функций языка Си.
ОСНОВНЫЕ СВЕДЕНИЯ
Часто в программе требуется повторить определенную последовательность операторов в разных частях программы. Для того, чтобы описывать эту последовательность один раз, а применять многократно, в языках программирования применяются подпрограммы. Подпрограмма - автономная часть программы, выполняющая определенный алгоритм и допускающая обращение к ней из различных частей общей программы.
В языке Си существует один вид подпрограмм - функции. Каждая программа в своем составе должна иметьглавную функцию main(), служащую точкой входа в программу. Кроме функции main(), в программу может входить произвольное число функций, выполнение которых инициализируется либо прямо, либо вызовами из функции main(). Каждая функция по отношению к другой является внешней. Для того, чтобы функция была доступной, необходимо, чтобы до ее вызова о ней было известно компилятору. Форма записи функции:
<тип > <имя функции>(<формальные параметры>){<тело функции >}
Если тип возвращаемого функцией значения не указан, то подразумевается int. Если с именем функции не связан результат, то нужно указать тип функции void. Параметры, записываемые в обращении к функции, называются фактическими; параметры, указанные в описании функции - формальными. Фактические параметры должны соответствовать формальным по количеству, порядку следования и типу. Объекты, объявленные вне функции, действуют в любой функции и называются глобальными. Объекты, объявленные в функции, действуют только в ней и называются локальными. В теле функции обычно присутствует оператор return <выражение>, определяющий возвращаемое функцией значение.
Все параметры функции, кроме массивов, передаются по значению, т.е. внутри функции создаются локальные копии параметров. Если необходимо передать саму переменную, а не её копию, то в функцию передаётся адрес этой переменной. Таким образом, через параметры можно передавать результат выполнения функции. То есть, параметры, с помощью которых результаты должны передаваться из функции в точку вызова, описываются как указатели. Вызов функции может быть оформлен в виде оператора, если с именем функции не связано возвращаемое значение, или в виде выражения, если возвращаемое значение связано с именем функции.
Прототип функции может указываться до вызова функции вместо описания функции для того, чтобы компилятор мог выполнить проверку соответствия типов аргументов и параметров. Прототип функции по форме такой же, как и заголовок функции. В конце него ставится «;».
Функции можно подключать с помощью директивы #include <имя файла>. Такие файлы с функциями удобно использовать в диалоговых программах с пользовательским меню, позволяющих выбрать один из режимов.
Пример 1:Функция с параметрами-значениями. Результат связан с именем функции. В программе объявляется прототип функции, а сама функция описывается ниже.
//lab8_1
#include <stdio.h>
#include <conio.h>
int max(int,int); //Прототип функции
void main()
{ int x,y,z;
printf(" input x,y ");
scanf("%d%d",&x,&y);
z=max(x,y); //Вызов функции с фактическими параметрами
printf("x=%d y=%d max=%d",x,y,z);
getch();
}
int max(int a ,int b) //Заголовок функции с формальными параметрами
{ int c;
if (a>b) c=a;
else c=b;
return c;
}
Пример 2:Функция с параметрами-указателями. Здесь передаются адреса фактических параметров, по которым и получаем результат. Функция меняет местами переменные x,y.
//lab8_2
#include <stdio.h>
#include <conio.h>
main()
{ float x,y;
void swap(float *, float *); // Прототип функции с параметрами - указателями
printf("\n введите x,y ");
scanf("%f%f",&x,&y);
swap(&x,&y); // Передаём адреса переменных
printf("\n x=%4.2f y=%4.2f ",x,y);
getch();
}
void swap(float * a, float * b)
{float c;
c=*a; // *a - содержимое по адресу a
*a=*b;
*b=c;
}
Пример 3:Подключение файлов с функциями и создание меню.
! Внимание! Следите за тем, чтобы константы, объявленные директивой #define, не переобъявлялись в функциях.
//lab8_3
#include <stdio.h>
#include <conio.h>
#include "lab3.c"
#include "lab5.c"
#include "lab6.c"
main()
{ int nom;
while(1)
{ clrscr();
printf("\n 1. Сумма ряда \n");
printf(" 2. Матрица \n");
printf(" 3. Строки \n");
printf(" 4. Выход \n");
scanf("%d",&nom);
switch(nom)
{
case 1:lab3();break;
case 2:lab5();break;
case 3:lab6();break;
case 4:return 0;
default:printf("Неверный режим");
}
}
getch();
}
Пример 4:Передача в функцию массива с использованием указателя. Результат – элементы массива возводятся в квадрат. Функция описывается до вызова, поэтому прототип не объявляется.
//lab8_4
#include <stdio.h>
#include <conio.h>
void quart(int n, float * x) // Можно void quart(int n, float x[])
{ int i;
for (i=0;i<n;i++)
x[i]=x[i]*x[i];
}
main()
{ float z[]={1,2,3,4};int j;
clrscr();
for (j=0;j<4;j++)
printf(" %6.2f",z[j]);
quart(4,z);
for (j=0;j<4;j++)
printf("\n %6.2f",z[j]);
getch();
}
ВЫПОЛНЕНИЕ РАБОТЫ
3.1. Проанализировать приведенные выше программы.
3.2. Оформить свои задания по лабораторным работам 5, 6, 7 в виде функций. Организовать меню с вызовом этих функций.
3.3. Используя функции, написать программу по своему варианту.
Варианты заданий
1. Написать функцию, выводящую в порядке возрастания элементы одномерного массива. В главной программе вызвать функцию для двух разных массивов.
2. Написать функцию вычисления произведения прямоугольной матрицы A размера k x m на прямоугольную матрицу B размера m x n. В главной программе обратиться к этой функции.
3. Написать функцию вычисления суммы ряда s=s(1)+…+s(n),
где s(n)=(-1)n x(2n-1)/(2n+1) с точностью до eps=0.001. В качестве параметров выбрать x и eps.
4. Написать функцию, которая вычисляет для заданной квадратной матрицы A её симметричную часть S(ij)=(A(ij)+A(ji))/2 и кососимметричную часть K(ij)=(A(ij)-A(ji))/2.
5. Написать функцию “шапочка” f(x), зависящую от параметров a и b: если |x| >a то f(x)=0 иначе f(x)=b*exp(-a2/(a2-|x|2)). В качестве параметров передать a,b,x.
6. Написать функцию поиска максимального и минимального элементов одномерного массива. В основной программе вызвать эту функцию для двух разных массивов.
7. Написать функцию, которая сортирует одномерный массив в порядке убывания методом пузырька. В основной программе вызвать эту функцию для двух разных массивов.
8. Написать функцию, которая по двум заданным одномерным массивам (A размера m и B размера n) вычисляет максимальное значение двумерного массива c(ij)=a(i)*b(j).
9. Написать функцию определителя квадратной матрицы A размера 3x3:
detA=a(1,1)a(2,2)a(3,3)+a(3,1)a(1,2)a(2,3)+a(2,1)a(3,2)a(1,3)-a(3,1)a(2,2)a(1,3)-a(1,1)a(3,2)a(2,3)-a(2,1)a(1,2)a(3,3).
10. Написать функцию вычисления суммы ряда y=sinx-(sin2x)/2+…
+(-1)n+1sin(nx)/n с точностью до eps=0.001. В качестве параметров передать x (в радианах) и eps.
11. Написать функцию вычисления ряда y=x+x3/3!+…+x2n+1/(2n+1)! с точностью до eps=0.0001. В качестве параметров передать x и eps.
12. Написать функцию обработки матриц A и B одинакового размера m x n. Получить матрицу C =max(a(i,j),b(i,j)), и матрицу D=min(a(i,j),b(i,j)). Матрицы C и D вывести в главной программе.
КОНТРОЛЬНЫЕ ВОПРОСЫ
4.1. Описание функции. Для чего объявляется прототип?
4.2. Что такое формальные и фактические параметры? Локальные и глобальные?
4.3. Как можно передавать массив в функцию?
4.4. Способы вызова функций.
Лабораторная работа № 7
Рекурсии
1. ЦЕЛЬ РАБОТЫ: Изучение методов использования алгоритмов и программ с рекурсиями в языке Си.
ОСНОВНЫЕ СВЕДЕНИЯ
В языке Си функции могут вызывать сами себя, т.е. обладать свойством рекурсивности. Рекурсивная функция обязательно должна содержать в себе условие окончания рекурсивности, чтобы не вызвать зацикливания программы. При каждом рекурсивном вызове создается новое множество локальных переменных. Т.о. переменные, расположенные вне вызываемой функции, не изменяются.
Пример. Составить рекурсивную функцию, вычисляющую факториал числа n следующим образом: n!= 1 , если n<= 1 и n!= ( n -1 )! · n, если n > 1
long fact( int n)
{ if (n <=1) return l;
else return (n * fact ( n -1 )); // функция fact вызывает саму себя
}
Таким образом, последовательно вызываются функции f(n), f(n-1),f(n-2)…f(1).
Достоинством рекурсий является компактная запись, а недостатком – расход времени и памяти на повторные вызовы функции и передачу ей копий параметров.
ВЫПОЛНЕНИЕ РАБОТЫ
Составить алгоритмы и программы с использованием рекурсии в соответствии с вариантом задания.
Варианты заданий
1. Ввести с клавиатуры целое число N. Используя рекурсию, распечатать сначала последовательность, состоящую из N букв 'А', а затем из N букв 'В'.
2. Напечатать в обратном порядке последовательность чисел, признаком конца которой является 0.
3. Водится любое целое число b и вещественные a, c. Вычислить z=a b +c b ,
используя рекурсивную функцию x n
1, если n = 0
x n = 1/ x n , если n < 0
x × x n-1 , если n > 0
4. Для N=12 найти числа Фибоначчи, которые вычисляются следующим образом: F(0)=1, F(1)=2, F(N)=F(N-2)+F(N-1)
5. Методом деления отрезка пополам найти с точностью EPS=0,0001 корень уравнения cos(2/x)-2*sin(1/x)+1/x=0
6. Даны целые числа m и n, где 0<=m<=n. Вычислить рекурсивно число сочетаний по формуле:
7. Дана последовательность положительных чисел, признаком конца которых служит отрицательное число. Используя рекурсию, подсчитать количество чисел и их сумму.
8. Дана последовательность ненулевых целых чисел, признаком конца которых служит 0. Используя рекурсию, напечатать сначала все отрицательные, а потом – все положительные числа этой последовательности.
9. Дан вектор Х из N вещественных чисел. Найти минимальный элемент вектора, используя вспомогательную рекурсивную функцию, находящую минимум среди последних элементов вектора Х, начиная с N-го.
10. Дана строка символов, в конце которой стоит точка. Напечатать строку в обратном порядке.
11. Задан вещественный массив из N. Упорядочить его по возрастанию методом быстрой сортировки: выбрать средний элемент массива и переставить элементы так, чтобы слева от выбранного элемента были меньшие, а справа только большие (т.о. выбранный элемент окажется на окончательном месте). Затем применить этот способ рекурсивно к левой и правой части массива.
12. Имеется 10 населенных пунктов. Дана последовательность пар чисел пар чисел I и J (I<J), указывающих, что I –ый J-ый пункты соединены дорогой. Признак конца этой последовательности - пара нулей. Используя рекурсию, определить, можно ли по этим дорогам попасть из 1-го пункта в N-ый.
КОНТРОЛЬНЫЕ ВОПРОСЫ
4.1. Что такое рекурсия?
4.2. Как меняются локальные и глобальные переменные в рекурсиях?
4.3. Где находится окончание рекурсии?
Лабораторная работа № 8
Структуры
1. ЦЕЛЬ РАБОТЫ: Приобретение практических навыков в составлении алгоритмов и программ со структурами.
ОСНОВНЫЕ СВЕДЕНИЯ
Структура – это фиксированное число элементов одного или нескольких типов. Т.е. в отличие от массивов, в которых содержатся элементы одного типа, в структурах могут содержаться элементы как одного, так и разных типов. Элементами структуры могут быть базовые типы, массивы, указатели, структуры и т.д. Элементы структуры вместе с их описанием называются полями. Над полями можно выполнять дейст