4.02M
Category: programmingprogramming

Лекция_10_ОАИП_2020

1.

Программирование с
использованием
подпрограмм.
Лекция №10
Лектор: Романькова Татьяна Леонидовна
13.04.2026
1

2.

Управление консольным окном в «текстовом» режиме
Консольное окно Windows является интерфейсом, который
предоставляет Windows для ввода и вывода данных приложениям,
работающим в символьном режиме, которые не имеют
собственного графического интерфейса.
Есть возможность использовать функции Windows API для
управления консольным вводом – выводом.
Чтобы использовать такие функции, нужно включить в
программу заголовочный файл windows.h
Функция SetConsoleTitle
консольного окна. Например,
устанавливает
заголовок
Префикс L делает строку строкой wchar_t – широкосимвольная
строка для кодировки Unicode.
13.04.2026
2

3.

Функция
SetConsoleCursorPosition
устанавливает
положение текстового курсора в консольном окне.
Первым аргументом она принимает дескриптор
консольного окна, а вторым – переменную типа COORD (это
структура с двумя полями X и Y), в которой должны находиться
координаты текстового курсора.
Для
получения
идентификатора/дескриптора
консольного окна (HANDLE) можно использовать функцию
GetStdHandle:
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
Константа STD_OUTPUT_HANDLE говорит, что нужно
получить дескриптор стандартного устройства ввода/вывода
stdout.
13.04.2026
3

4.

Функция
SetConsoleTextAttribute
устанавливает
атрибуты цвета текста (цвет букв и цвет фона ячеек с
буквами).
BOOL SetConsoleTextAttribute(HANDLE,WORD);
Вторым аргументов в функцию SetConsoleTextAttribute
передается число, биты которого управляют цветами фона и
текста.
Он использует младший байт слова WORD, биты которого:
Ib Rb Gb Bb If Rf Gf Bf
Этот аргумент удобнее конструировать из набора флагов.
Эти
флаги
включают
BACKGROUND_
и
FOREGROUND_, которые обозначают цвет фона и текста
соответственно.
13.04.2026
4

5.

13.04.2026
5

6.

Понятие подпрограммы.
При программировании часто возникают ситуации,
когда одну и ту же группу действий нужно выполнять
несколько раз в разных частях программы.
Например, пусть известны результаты сдачи сессии
студентами 3-х групп (для каждого студента группы известен
средний балл). Требуется определить, какая группа имеет
самый высокий общий средний балл.
Обозначим Sb1 – массив из средних баллов
студентов 1-й группы, n1- количество студентов в ней.
Для оставшихся двух групп аналогичные обозначения.
Схема алгоритма решения этой задачи могла бы выглядеть
так:
13.04.2026
6

7.

Начало
A
B
Ввод n1
Ввод n2
Ввод n3
i=0
i=0
i=0
нет
i<n1
да
i<n2
нет
i<n3
да
Ввод Sb1[i]
да
Ввод Sb2[i]
Ввод Sb3[i]
i=i+1
i=i+1
i=i+1
A
B
С
13.04.2026
нет
7

8.

C
D
S =0
S =0
i =0
i =0
нет
13.04.2026
нет
i < n1
i < n2
да
да
S = S+Sb1[i]
S = S+Sb2[i]
i =i+1
i =i+1
Sb_gr1=S/n1
Sb_gr2=S/n2
D
E
8

9.

E
S =0
i =0
нет
i < n3
да
S = S+Sb3[i]
i =i+1
Sb_gr2=S/n3
13.04.2026
F
9

10.

F
да
Вывод :
1-я группа лучше
Sb_gr1>Sb_gr2
Sb_gr1>Sb_gr3
да
Вывод :
2-я группа лучше
нет
нет
Sb_gr2>Sb_gr1
Sb_gr2>Sb_gr3
нет
Вывод :
3-я группа лучше
Конец
13.04.2026
10

11.

Так как фрагмент ввода одномерного массива повторяется
три раза, то вместо того чтобы в программе три раза
использовать одни и те же операторы (только с разными
переменными), можно создать «инструмент» - подпрограмму
для ввода одномерного массива и воспользоваться им нужное
количество раз.
Схема
алгоритма
подпрограммы
оформляется
аналогично схеме основной программы, только вместо блока
«Начало» используется блок с именем подпрограммы, а
вместо блока «Конец» используется блок «Выход».
13.04.2026
11

12.

VVOD
Ввод n
i:=1
нет
i n
да
Ввод Sb [i]
i:=i+1
передача выходных
параметров n и Sb
13.04.2026
Возврат
12

13.

Для каждой группы вычисляется общий средний балл,
поэтому вместо повторения одних и тех же действий в
программе можно создать «инструмент» для вычисления
среднего балла: подпрограмму, которая в качестве исходных
данных ( входных параметров) будет получать количество
студентов группы и одномерный массив баллов студентов.
13.04.2026
13

14.

передача
входных
параметров n и Sb
Average_Mark
S =0
I =1
нет
I ≤ n
да
S = S+Sb [i]
I =I+1
Sb_gr = S/n
13.04.2026
Возврат
передача выходного
параметра Sb_gr
14

15.

В схеме алгоритма блок, в котором
использование подпрограмм, имеет вид:
отражается
Предопределенный процесс
Итак, при наличии подпрограмм ввода массива и
вычисления среднего балла группы схема алгоритма
решения задачи примет вид
13.04.2026
15

16.

Начало
Ввод Sb1 с
помощью VVOD
Ввод Sb2 с
помощью VVOD
Ввод Sb3 с
помощью VVOD
Вычисление
Sb_gr1 с помощью
Average_Mark
A
13.04.2026
16

17.

A
Вычисление
Sb_gr2 с помощью
Average_Mark
Вычисление
Sb_gr3 с помощью
Average_Mark
да
Вывод :
1-я группа лучше
Sb_gr1 > Sb_gr2
Sb_gr1 > Sb_gr3
да
Вывод :
2-я группа лучше
13.04.2026
Конец
нет
Sb_gr2 > Sb_gr1
Sb_gr2 > Sb_gr3
нет
Вывод :
3-я группа лучше
17

18.

Подпрограмма – это именованная, логически законченная,
особым образом оформленная часть программы, которую
можно вызвать для выполнения по имени любое количество
раз.
Преимущества использования подпрограмм:
• Экономия времени разработки программы
• Уменьшение размера программы
• Возможность
программистов
разработки
программы
коллективом
• Повышение надежности программы
13.04.2026
18

19.

В отличие от многих других языков в С нет деления на
процедуры и функции. Си-программа состоит только из
функций..
Функции делятся на встроенные (стандартные) и
определенные программистом.
Первые входят в состав языка и располагаются
специализированных библиотечных модулях.
Вторые
разрабатываются
(программистом).
и
именуются
в
пользователем
Функция - самостоятельная единица программы,
разработанная для выполнения некоторого функционально
законченного действия.
13.04.2026
19

20.

Описание (определение) функции
Описание функции описания:
это ее текст на языке Си. Синтаксис
Заголовок функции
тип-возвращаемого-значения имя-функции (список-параметров)
{
объявления и операторы;
}
Имя функции — это любой правильно написанный
идентификатор. Оно является особым типом указателя, значение
которого – точка входа в функцию.
Тип возвращаемого значения — это тип данных
результата, возвращаемого из функции в точку ее вызова.
Тип возвращаемого значения void указывает, что функция
не возвращает никакого значения.
13.04.2026
20

21.

Список-параметров — это список разделенных запятыми
объявлений тех параметров, которые получает функция при ее
вызове.
Если функция не получает никаких значений, списокпараметров задается как void или отсутствует.
Тип должен быть указан явно для каждого параметра в
списке параметров.
Пример функции, которая вычисляет и возвращает в
точку вызова сумму двух чисел:
13.04.2026
21

22.

Объявления и операторы внутри фигурных скобок образуют тело
функции.
Тело функции - составной оператор,
операторы, определяющие действия функции.
содержащий
Все переменные, объявленные в теле функции, имеют
класс памяти auto, если они не объявлены иначе, и являются
локальными. Когда вызывается функция, то для локальных
переменных отводится память в стеке и производится их
инициализация (если она задана).
Процесс выполнения функции продолжается до тех пор,
пока не встретится оператор return или конец тела функции.
Управление при этом возвращается в точку вызова функции.
13.04.2026
22

23.

Результат функции может быть любого стандартного типа,
а также типа, определенного пользователем (структура,
объединение, класс и др.). Функция возвращает явно только
одно значение указанных типов.
Передача (возврат) значения из вызванной функции в
вызывающую осуществляется посредством использования
оператора возврата return, имеющего следующий вид:
return выражение;
Например,
return -5;
return (x+y);
В теле функции может быть несколько операторов return.
13.04.2026
23

24.

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

25.

Пример функции с несколькими операторами return:
Если тип выражения в операторе return не соответствует
типу значения, возвращаемому функцией, то будут выполнены
автоматически соответствующие преобразования типа выражения
к типу возвращаемого функцией значения. В случае
невозможности таких преобразований выводится сообщение об
ошибке.
13.04.2026
25

26.

Объявление (прототип) функции
Прототип функции – это ее имя с указанием типа
возвращаемого результата и перечислением в круглых скобках
(через запятую) типов передаваемых параметров. Прототип
функции завершается точкой с запятой.
Например,
double step(float x, int n);
int min(int , int );
Стандарт языка С требует, чтобы функции, возвращающие
отличные от int значения, были объявлены до первой ссылки на
них.
Прототип является предварительным объявлением
данных функции: имени функции, количества и типов
параметров, типа результата.
13.04.2026
26

27.

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

28.

Для определения прототипов встроенных функций нужно
подключить заголовочные файлы, в которых эти прототипы
написаны. Например,
#include <stdio.h>
#include <windows.h>
#include <time.h>
Хорошая практика – помещение прототипов своих функций в
заголовочный файл и подключение его директивой #include
13.04.2026
28

29.

В большинстве компиляторов использование "" сначала проверяет ваш локальный каталог, а
если он не находит совпадения, то переходит к проверке системных путей.
Использование <> запускает поиск с системными заголовками.
13.04.2026
29

30.

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

31.

Механизм передачи параметров
Передача параметров может быть двух видов:
По значению (например, sum(int first, int second))
По ссылке – через указатель (по адресу, например,
sum(int first, int* second))
Если аргументы функции передаются по значению, то их
значения копируются в формальные параметры в при выходе из
функции теряются. Поэтому в этом случае в теле функции
нельзя изменить значение аргумента, так как функция работает
с копиями аргументов.
В случае передачи указателя функция работает с копией
адреса и имеет доступ к ячейке памяти, в которой хранится
значение аргумента, а значит может его изменить.
13.04.2026
31

32.

Например,
Вызов:
13.04.2026
32

33.

При каждом вызове функции в памяти создается её копия, то есть
вызов функции расходует память.
Если функция имеет небольшой размер и часто вызывается, то её
можно объявить как inline (встроенную). Объявленная
таким
образом
функция не вызывается каждый раз, вместо этого текст функции
подставляется в то место программы где она вызвана.
При этом экономится память, но увеличивается размер кода.
Объявление inline функции:
inline тип_результата имя_функции(аргументы);
inline int sum(int first, int* second)
{
*second += 2;
int s = first + *second;
return s;
}
13.04.2026
33

34.

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

35.

Если добавить в эту функцию вывод размера параметра
array, то можно увидеть, что полученная величина будет 4 байта.
13.04.2026
35

36.

Тогда, если передать в качестве аргумента в эту функцию
статический массив A[20] из значений типа int, и вывести размер
переменной A, результат будет следующий:
Причина в том, что array представляет собой не сам
массив, а указатель на первый элемент массива A.
Нужно заметить, что для хранения адресов в разных
системах может использоваться разное количество байтов.
13.04.2026
36

37.

Другой способ передачи массива в функцию: передавать в
функцию параметр-указатель. Например,
Пример. Вычислить значение выражения
Y=sin a+2b,
где a, b - произведение отрицательных элементов массивов целых
чисел A, B соответственно. Массив A объявить как статический, а
B - динамический
13.04.2026
37

38.

input_array
Ввод count
i=0
нет
i < count
да
Ввод array [i]
i=i+1
13.04.2026
Возврат
38

39.

13.04.2026
39

40.

output_array
Вывод заголовка
i=0
нет
i < count
да
Вывод array [i]
i=i+1
13.04.2026
Возврат
40

41.

13.04.2026
41

42.

prod
p=1
isOk=false
i =0
нет
i < n
да
да
i <0
нет
p = p*array [i]
isOk=true
i =i+1
13.04.2026
Возврат
42

43.

13.04.2026
43

44.

Начало
count_A =
input_array(A, "A")
count_B =
input_array(B, “B")
output_array(A,
count_A, "А:");
output_array(B,
count_B, “B:");
A
13.04.2026
44

45.

A
prod(A, count_A, &a)
prod(B, count_B, &b)
Вывод :
a, b
F=sina+2b
Вывод :
F
Конец
13.04.2026
45

46.

13.04.2026
46

47.

13.04.2026
47

48.

13.04.2026
48

49.

Передача двумерного массива в функцию
1-й способ: описание соответствующего аргумента функции
должно содержать количество столбцов; количество строк –
несущественно (например, int matrix[][3]).
int arr[3][4] = {
{2, 4, 6,8},
{3, 5, 7,9},
{12,10,8,6}
};
13.04.2026
int sum = summa(arr, 3, 4);
49

50.

2-й способ: описание соответствующего аргумента функции
нужно представить как указатель на начало массива, а матрицу
представлять как одномерный массив в памяти. К элементам
обращаться через указатель.
int arr[3][4] = {
{2, 4, 6,8},
{3, 5, 7,9},
{12,10,8,6}
};
13.04.2026
int sum = summa(arr, 3, 4);
50

51.

3-й способ: использовать массив указателей на массивы.
Описание соответствующего аргумента функции нужно
представить как указатель на указатель.
Массив указателей на линейные массивы переменных
является двумерной структурой данных и использует двойную
индексацию. Функционально она является эквивалентом
двумерного массива.
13.04.2026
51

52.

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

53.

Пример. Сформировать одномерные массивы V1 и V2 из сумм
элементов строк матриц A и B соответственно.
13.04.2026
53

54.

13.04.2026
54

55.

Функцию для ввода матрицы можно реализовать иначе:
13.04.2026
55

56.

13.04.2026
56

57.

13.04.2026
57

58.

13.04.2026
58

59.

13.04.2026
59

60.

В главной функции:
13.04.2026
60

61.

13.04.2026
61

62.

Указатели на функцию
Указатель на функцию содержит адрес первого байта в
памяти, по которому располагается выполняемый код функции.
Функция - это не переменная, но она имеет физическое
положение в памяти, которое может быть присвоено указателю.
Адрес, присвоенный указателю, является входной точкой в
функцию. Указатель может использоваться вместо имени
функции.
Имя функции, как и имя массива, является указателем на
функцию.
Указатель на функцию можно определять в виде отдельной
переменной:
тип (*имя_указателя) (параметры);
Скобки обязательны!!!
13.04.2026
62

63.

Например, определим указатель на функцию, которая не
принимает параметров и не возвращает результат:
void(*printFunction)(void);
Тогда указатель printFunction может содержать адреса,
например, таких функций:
13.04.2026
63

64.

Указателю на функцию можно присвоить функцию, которая
соответствует указателю по возвращаемому типу и
спецификации параметров
printFunction = hello;
printFunction();//вызов функции, на которую указывает printFunction
printFunction = bye;
Пример указателя на функцию с двумя параметрами
типа int, возвращающую целое число:
int (*func)(int,int);
Тогда указатель func может содержать адрес, например, такой
функции
13.04.2026
64

65.

Указатели на функцию можно записывать в массив,
чтобы иметь возможность обращаться к функции по номеру или
вызывать поочередно несколько функций.
тип (*имя_массива[размер]) (параметры)
13.04.2026
65

66.

Можно определить имя типа указателя на функцию с
помощью ключевого слова typedef.
typedef тип результата (*имя типа)(параметры);
Например,
typedef double (*Function)(double);
13.04.2026
66

67.

Указатели на функции как параметры функций
Указатель на функцию можно передавать в другую
функцию в качестве параметра.
Это позволяет создавать более универсальные функции.
Например, алгоритм поиска не зависит от критерия поиска.
Приведем пример функции, которая выводит элементы
массива, удовлетворяющие заданному условию.
13.04.2026
67

68.

Можно сначала для типа указателя задать имя:
13.04.2026
68

69.

Тогда
в
качестве
аргумента-критерия
использовать, например, такие функции:
13.04.2026
можно
69

70.

Пример использования функции find:
13.04.2026
70

71.

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

В главной функции:
1) инициализировать массив из пунктов меню;
2) вызывать функцию, запускающую меню, управляющее работой программы.
13.04.2026
71
в

72.

Создание светового меню
13.04.2026
72

73.

В заголовочном файле Menu.h определяем все, что
необходимо для работы меню, в том числе прототип функции для
запуска меню.
13.04.2026
73

74.

Реализация в файле Menu.с:
13.04.2026
74

75.

13.04.2026
75

76.

13.04.2026
76

77.

13.04.2026
77

78.

13.04.2026
78

79.

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

80.

13.04.2026
80

81.

Реализация в файле исходного кода:
13.04.2026
81

82.

13.04.2026
82

83.

13.04.2026
83

84.

В главном файле нужно описать глобальный указатель на
массив структур и описать обработчики для пунктов меню.
13.04.2026
84

85.

13.04.2026
85

86.

В функции main нужно создать массив структур,
инициализировать массив из пунктов меню и вызвать функцию,
которая запускает меню.
13.04.2026
86

87.

13.04.2026
87

88.

13.04.2026
88
English     Русский Rules