- •Предисловие
- •Знакомство с языком C
- •Структура программы
- •Пример простой программы
- •Более сложный пример
- •Контрольные вопросы
- •Основные понятия, объявление переменных, типы данных
- •Объявление переменных
- •Примеры описаний переменных:
- •Основные типы данных
- •Производные типы.
- •Контрольные вопросы
- •Ввод/вывод с помощью функций printf() и scanf().
- •Модификаторы спецификаций преобразования используемые в функции printf()
- •Применение функции scanf()
- •Контрольные вопросы
- •Операции
- •Простейшие арифметические операции
- •Операция присваивания
- •Использование в выражениях операндов разных типов
- •Операции преобразования типов
- •Дополнительные арифметические операции
- •Дополнительные операции присваивания
- •Операции отношения
- •Логические операции
- •Приоритеты операций
- •Таблица 3. Таблица приоритетов рассмотренных выше операций
- •Контрольные вопросы
- •Операторы
- •Оператор-выражение
- •Ветвление
- •Условный оператор
- •Оператор switch
- •Оператор break
- •Циклы
- •Цикл while
- •Цикл do…while
- •Цикл for
- •Другие операторы
- •Оператор continue
- •Оператор goto
- •Оператор вызова функции
- •Контрольные вопросы
- •Обработка числовых последовательностей
- •Последовательная обработка
- •Обработка числовых последовательностей
- •Примеры
- •Контрольные вопросы
- •Последовательная обработка символьных данных
- •Символьные данные
- •Последовательная обработка символов
- •Функции getchar( ) и putchar( )
- •Контрольные вопросы
- •Обработка массивов
- •Массивы
- •Объявление массива
- •Использование и обработка массивов
- •Примеры
- •Контрольные вопросы
- •Указатели и динамические массивы
- •Указатели
- •Динамическое выделение памяти
- •Статические и динамические массивы
- •Контрольные вопросы
- •Подпрограммы
- •Описание подпрограмм
- •Параметры подпрограмм
- •Область действия переменных
- •Примеры
- •Контрольные вопросы
- •Рекурсивные функции
- •Понятие рекурсивной функции
- •Контрольные вопросы
- •Символьные строки и функции обработки строк
- •Посимвольная обработка строк
- •Пример программы
- •Контрольные вопросы
- •Структуры
- •Тип данных структура
- •Контрольные вопросы
- •Работа с файлами
- •Примеры
- •Контрольные вопросы
- •Массивы и функции как параметры
- •Указатели на функции
- •Массивы и указатели
- •Указатели и двумерные массивы
- •Пример
- •Технологии программирования
- •Структурное программирование
- •Модульное программирование
- •Объектно-ориентированное программирование
- •Компонентное программирование
- •Структурная декомпозиция задачи и разработка алгоритмов и программ методами сверху вниз и снизу вверх
- •Контрольные вопросы
- •Модульное программирование
- •Работа с графикой на языке C и модуль graphics.h
- •Типы видео мониторов и их режимы
- •Инициализация графики
- •Система координат
- •Основные графические функции
- •Функции рисования
- •Функции изменения параметров рисования
- •Шаблоны линий
- •Шаблоны закраски
- •Задание на расчетно-графическую работу
- •Порядок выполнения работы
- •Задание
- •Задание для вариантов 1-11
- •Задание для вариантов 12-20
- •Задание для вариантов 21-40
- •Пример исходных данных для вариантов 12-16
- •Задание для вариантов 41-60
- •Варианты индивидуальных заданий
- •Вариант 1
- •Вариант 2
- •Вариант 3
- •Вариант 4
- •Вариант 5
- •Вариант 6
- •Вариант 7
- •Вариант 8
- •Вариант 9
- •Вариант 10
- •Вариант 11
- •Вариант 12
- •Вариант 13
- •Вариант 14
- •Вариант 15
- •Вариант 16
- •Вариант 17
- •Вариант 18
- •Вариант 19
- •Вариант 20
- •Вариант 21
- •Вариант 22
- •Вариант 23
- •Вариант 24
- •Вариант 25
- •Вариант 26
- •Вариант 27
- •Вариант 28
- •Вариант 29
- •Вариант 30
- •Вариант 31
- •Вариант 32
- •Вариант33
- •Вариант 34
- •Вариант 35
- •Вариант 36
- •Вариант 37
- •Вариант 38
- •Вариант 39
- •Вариант 40
- •Вариант 41
- •Вариант 42
- •Вариант 43
- •Вариант 44
- •Вариант 45
- •Вариант 46
- •Вариант 47
- •Вариант 48
- •Вариант 49
- •Вариант 50
- •Вариант 51
- •Вариант 52
- •Вариант 53
- •Вариант 54
- •Вариант 55
- •Вариант 56
- •Вариант 57
- •Вариант 58
- •Вариант 59
- •Вариант 60
- •Задания на курсовую работу
- •Требования к курсовой работе
- •Этапы разработки программ
- •Содержание отчета по курсовой работе
- •Задания к курсовой работе
- •Литература
- •Функции консольного ввода/вывода
- •Функции обработки строк
- •Функции преобразования данных
(прототип функции). Прототип функции – это заголовок функции, завершающийся символом ‘;’.
Например,
float f (int n, float m[ ]); - прототип вещественной функции f от целочисленного входного параметра n и вещественного массива m.
Параметры подпрограмм
Параметры предназначены для передачи входных и выходных данных (переменных) подпрограммы.
В заголовке подпрограммы объявляется тип каждого формального параметра. При вызове указываются аргументы вызова – фактические параметры.
При вызове подпрограммы происходит согласование параметров:
- порядок и типы формальных параметров в объявлении и определении подпрограммы должны совпадать с порядком и типами фактических параметров при вызове подпрограммы.
После вызова подпрограммы выполняются ее операторы, где фактические параметры подставляются вместо формальных параметров.
Передача параметров и согласование формальных и фактических параметров может осуществляться
•по значению;
•по ссылке (по адресу).
Передача параметров по значению. При передаче параметра по значению фактический параметр может быть выражением, в частном случае переменной или константой. Формальному параметру присваивается значение выражения, тип которого должен совпадать с типом формального параметра. В подпрограмме используется только значение фактического параметра, любые изменения параметра в подпрограмме не влияют на его значение в вызывающей программе. Таким способом можно передавать
89
только входные параметры, т.е. можно передать данные от вызывающей программы к подпрограмме.
Передача параметров по ссылке. При передаче параметра по ссылке фактический параметр может быть только переменной, тип которой должен совпадать с типом формального параметра. Передается не значение фактического параметра, а его адрес. При выполнении подпрограммы фактический параметр заменяет формальный параметр, действия выполняются над фактическим параметром. Изменения параметра в подпрограмме меняют его значение в вызывающей программе. Таким способом можно передавать и входные, и выходные параметры, т.е. можно передать данные от вызывающей программы к подпрограмме и в обратном направлении.
В языке С параметры всегда передаются по значению, т.е. непосредственно можно использовать только входные параметры. Передачу выходных параметров по ссылке можно реализовать с помощью указателей (ссылок, адресов). При передаче параметра по ссылке в вызове функции нужно получить его адрес с помощью операции &, например &x, а в заголовке функции тип параметра должен быть указатель, например int *x.
Упрощенное правило:
Для передачи параметра по ссылке в заголовке и теле подпрограммы перед именем параметра необходимо указывать символ *, а при вызове - символ &.
Массивы всегда передаются по ссылке. Имя массива является адресом его первого элемента, поэтому на параметры – массивы правило не распространяется (т.е. не нужны символы * и &). Размер массива рекомендуется передавать отдельным параметром. В случае со строкой (символьным массивом) размер строки обычно не передают, т.к. конец строки определяется завершающим нуль символом –‘\0’.
Пример заголовка функции с параметром массив:
90
float f (int n, float m[]) - вещественная функция f от целочисленного параметра n (количество элементов массива) и вещественного массива m[].
Пример вызова этой функции:
int |
k; float z[100], t; |
t = |
f (k, z); |
Область действия переменных
Каждая переменная до использования должна быть описана. Локальные переменные. Переменные, объявленные в теле функции,
являются локальными переменными этой функции. Формальные параметры подпрограммы, также считаются локальными для этой подпрограммы. Областью действия локальной переменной является блок, в котором эта переменная объявлена.
Глобальные переменные. Глобальные переменные объявляются до всех функций или между определениями функций. Областью действия глобальной переменной является вся программа.
Глобальные переменные доступны из любой функции программы, где не объявлены локальные переменные с такими же именами. Однако не рекомендуется использовать их для обмена данными между функциями, т.к. это затрудняет отладку программы. Могут возникнуть трудно обнаруживаемые ошибки из-за того, что любая функция может изменить любую глобальную переменную. Рекомендуется, чтобы прототип функции полностью определял ее сопряжение с другими функциями.
Примеры
Задача. Составить программу вычисления c = n! / (m! * (m-n)!)
В вычисляемом выражении требуется трижды вычислять факториал вида k!, где k! = 1*2*...*k при целом k > 0, 0! = 1.
Вычисление факториала удобно оформить как подпрограмму. Решение А. Использование подпрограммы, не возвращающей значение.
Решение Б Пусть вызов подпрограммы p_fakt (k, f) обозначает действие - операцию присваивания f = k!;. Здесь k - исходные данные, а f - результат.
91
Таким образом, подпрограмма p_fakt() имеет входной параметр k и выходной параметр f.
Обозначим факториалы: n!, m! и (n-m)! через f1, f2 и f3, соответственно. Получим программу, приведенную ниже.
Подпрограмма вычисления факториала p_fakt содержит повторение умножений, т. е. имеет циклическую структуру. Текущим множителем служит вспомогательная переменная j, изменяющаяся с шагом +1.
/* Вариант А. Вычисление c=n!/(m!*(m-n)!) |
*/ |
|||||
/* с |
помощью подпрограммы, не возвращающей значение*/ |
|||||
#include <stdio.h> |
|
|
|
|
||
void |
p_fakt (int k, long *f); /* прототип функции */ |
|||||
/* |
|
Вычисление c = n! / (m! * (n-m)!) |
|
*/ |
||
void |
main(void) |
/* исходные данные и результат */ |
||||
{ |
int n, m, c; |
|||||
long f1, f2, f3; |
/* n!, m!, (n-m)! |
|
*/ |
|||
printf("\nВведите два исходных целых числа "); |
||||||
scanf("%d %d", &n, &m); |
/* f1 = n! |
*/ |
|
|||
p_fakt (n, &f1); |
|
|
||||
p_fakt (m, &f2); |
|
/* f2 = m! |
*/ |
|
||
p_fakt (n-m, &f3); |
|
/* f3 = (n-m)! */ |
|
|||
c = f1 / (f2 * f3); |
|
|
|
|
||
printf ("\n c = %d", c); |
|
|
|
|||
} |
|
Подпрограмма: f = k!; |
*/ |
|
||
/* |
|
|
||||
void p_fakt (int k, long *f) |
|
*/ |
||||
{ |
int j; |
/* текущий множитель |
||||
*f=1; |
|
|
|
|
|
|
for (j=2; j<=k; j++) |
|
|
|
|
||
*f = (*f )* j; |
/* здесь не обязателен |
*/ |
||||
return; |
||||||
} |
|
|
|
|
|
*/ |
/* Вариант Б. Вычисление c=n!/(m!*(m-n)!) |
||||||
/* с помощью функции, |
возвращающей значение |
*/ |
||||
#include <stdio.h> |
|
/* прототип функции |
||||
long fakt (int k); |
|
|||||
|
|
*/ |
|
|
|
|
/* |
|
Вычисление c = n! / (m! * (n-m)!) |
|
*/ |
||
void main(void) |
|
/* исходные данные и результат |
||||
{ |
int n, m, c; |
|
||||
|
|
*/ |
|
|
|
|
printf("\nВведите два исходных целых числа "); scanf("%d %d", &n, &m);
c = fakt(n) / (fakt (m) * fakt (n-m)); printf ("\n c = %d", c);
} |
Функция k! |
*/ |
/* |
||
long |
fakt (int k) |
|
92
{ long f; |
/* k! |
|
*/ |
/* текущий множитель |
*/ |
int j; |
||
f=1; |
|
|
for (j=2; j<=k; j++) |
|
|
f = f * j; |
/* значение функции |
*/ |
return f; |
||
} |
|
|
Пояснения к программе.
1.В программах А, Б вызовы подпрограмм расположены в тексте программы раньше, чем определения этих подпрограмм. Поэтому в начале программы объявлены функции, т.е. записаны их прототипы.
2.В программе Б результат работы подпрограммы fakt передается как значение функции. Поэтому переменная f является не параметром, а
вспомогательной локальной переменной и записывается без звездочки.
3.В программе А вызов функции p_fakt, не обладающей значением, может записываться только как самостоятельный оператор. В программе Б вызов функции fakt, обладающей значением, может являться операндом в выражении.
4.В программе А при выводе результата можно заменить строки:
c = f1 / (f2 * f3); printf ("\n c = %d", c);
строкой:
printf ("\n c = %d", f1/(f2*f3));
Тогда переменная c и ее объявление становятся ненужными. В
программе Б также можно обойтись без переменной с. |
|
Задача. Даны две строки длиной до 80 символов. |
Определить число |
латинских букв в каждой строке. |
|
#include <stdio.h> |
|
/*------------------------------------------------------------ |
*/ |
93
/* Функция определения количества лат. букв в заданной строке */
/*------------------------------------------------------------ |
KolLatBukv (char s[]) |
|
*/ |
||
int |
|
|
|||
{ |
i, |
/* индекс очередного символа строки s */ |
|||
int |
|||||
k=0; |
/* количество лат. букв */ |
||||
for ( i = 0; s[i] != '\0'; |
i++ ) |
||||
if(s[i]>='a'&&s[i]<='z'||s[i]>='A'&&s[i]<='Z') k++; |
|||||
return k; |
|
|
|
|
|
} |
|
|
|
|
|
/*----------------- |
|
|
*/ |
|
|
/* Главная функция */ |
|
|
|||
/*----------------- |
|
|
*/ |
|
|
void main() |
|
|
|
|
|
{ |
|
|
|
|
/* заданные строки */ |
char s1[81], s2[81]; |
|
||||
printf ("\nВведите две строки символов\n"); |
|||||
gets (s1); |
|
|
|
|
|
gets (s2); |
|
|
|
|
|
printf ("В |
1-й |
строке |
%d |
лат. букв\n", KolLatBukv (s1)); |
|
printf ("Во |
2-й |
строке |
%d |
лат. букв\n", KolLatBukv (s2)); |
|
} |
|
|
|
|
|
Пример результата выполнения программы:
Введите |
две |
строки |
символов |
|
AaBbcd |
123 |
Zz |
|
|
t = x + y * z / 10 ; |
||||
В 1-й |
строке |
8 |
лат. букв |
|
Во 2-й |
строке |
4 |
лат. букв |
Задача. Описать функцию, которая для заданного числового массива определяет сумму и количество положительных элементов.
#include <stdio.h> |
|
|
/*---------------------------------------------------- |
Функция определения суммы и количества |
*/ |
/* |
*/ |
|
/* |
положительных элементов заданного массива |
*/ |
/*---------------------------------------------------- |
|
*/ |
void |
SumPos (float m[], int n, float *s, int |
*k) |
/* Вх. параметры:
m – указатель на заданный массив, n – число элементов массива. Вых. параметры:
*s – сумма положительных элементов массива,
94