- •Введение
- •Блок-схема алгоритма
- •Общие требования к блок-схеме алгоритма
- •Линейные и разветвляющиеся процессы
- •Циклические процессы
- •Итерационные процессы
- •Основные понятия языка С(С++)
- •Комментарии
- •Типы данных
- •Данные целого типа
- •Данные вещественного типа
- •Модификатор const
- •Переменные перечисляемого типа
- •Константы
- •Структура программы на языке С(С++)
- •Операции и выражения
- •sizeof
- •Операция присваивания
- •Арифметические операции
- •Операции поразрядной арифметики
- •Логические операции
- •Операции отношения
- •Инкрементные и декрементные операции
- •Операция sizeof
- •Порядок выполнения операций
- •Приоритет операций
- •Преобразование типов
- •Операция приведения
- •Операция запятая
- •Ввод и вывод информации
- •Директивы препроцессора
- •Директива #include
- •Директива #define
- •Операторы языка С(С++)
- •Понятие пустого и составного операторов
- •Операторы организации цикла
- •Оператор цикла for
- •Оператор цикла while
- •Оператор цикла do … while
- •Вложенные циклы
- •Примеры программ
- •Массивы
- •Одномерные массивы
- •Примеры программ
- •Многомерные массивы (матрицы)
- •Примеры программ
- •Указатели
- •Понятие указателя
- •Описание указателей
- •Операции с указателями
- •Связь между указателями и массивами
- •Массивы указателей
- •Многоуровневые указатели
- •Примеры программ
- •Символьные строки
- •Ввод/вывод строк.
- •Функции работы со строками.
- •Примеры программ
- •Функции
- •Прототип функции.
- •Определение функции.
- •Параметры функции
- •Передача массива в функцию
- •inline функции
- •Класс памяти
- •Автоматические переменные
- •Статические переменные
- •Регистровые переменные
- •Блочная структура
- •Примеры программ
- •Указатели на функции
- •Примеры программ
- •Рекурсия
- •Примеры программ
- •Аргументы в командной строке
- •Функции с переменным числом параметров
- •Вершина стека
- •Примеры программ
- •Сортировка
- •Пузырьковая сортировка.
- •Шейкер сортировка
- •Сортировка вставкой
- •Сортировка выбором
- •Метод Шелла
- •Метод Хора
- •Структуры
- •Указатели на структуры.
- •Структуры и функции
- •Примеры программ
- •Поля бит
- •Объединения
- •Переменные с изменяемой структурой
- •Организация списков и их обработка
- •Операции со списками при связном хранении
- •Стек
- •Построение обратной польской записи
- •Односвязный линейный список, очередь
- •Двусвязный линейный список
- •Циклический список, кольцо
- •Двусвязный циклический список
- •Примеры программ
- •Деревья
- •Файлы
- •Примеры программ
- •Литература
int sr = ms[(l+r)/2]; |
// срединный элемент |
|
i = l; |
j = r; |
// начальные значения границ массива |
do |
|
|
{ while(ms[i] < sr) i++; |
// ищем слева элемент больше среднего |
|
while(ms[j] > sr) |
j--; // ищем справа элемент меньше среднего |
|
if(i <= j) |
// если левая граница не прошла за правую |
|
{ k = ms[i]; |
// перестановка элементов |
|
ms[i] = ms[j]; |
|
|
ms[j] = k; |
|
|
i++; |
j--; |
// переходим к следующим элементам |
} |
|
|
} while(i <= j); |
// пока границы не совпали |
|
|
|
// массив разбит на два подмножества |
if(i < r) |
|
// если есть что-нибудь справа |
hoar(ms,i,r); |
// сортируем правый подмассив |
|
if(j>l) |
|
// если есть что-нибудь слева |
hoar(ms,l,j); |
// сортируем левый подмассив |
}
Еще один вариант программы сортировки Хоора:
void hoor(int *a,int l,int r) |
|
||
{ int i,las; |
|
|
|
if(l>=r) return; |
|
|
|
swap(a,l,(l+r)/2); |
// |
делящий эл-т переносится в a[l] (a[l]<->a[(l+r)/2]) |
|
las=l; |
// |
позиция последнего элемента большего |
|
|
// |
чем делящий |
|
for(i=l+1;i<=r;i++) |
// |
деление [l,r] на [l,las-1] и [las+1,r] |
|
if(a[i]<a[l]) swap(a,++las,i); |
|
||
swap(a,l,las); |
|
|
|
hoor(a,l,las-1); |
// |
сортировка для |
[l, las-1] |
hoor(a,las+1,r); |
// |
сортировка для |
[las+1, r] |
} |
|
|
|
void swap(int *a,int i,int j)
{ int tmp; // функция замены i и j элементов в массиве a tmp=a[i];
a[i]=a[j];
a[j]=tmp;
}
Структуры
Как отмечалось ранее, массив предназначен для работы с данными, имеющими один тип. Рассматриваемые ниже объекты используются для снятия этого ограничения.
Структуры - это составной объект, в который входят элементы любых типов, за исключением функций. В отличие от массива, который является однородным объектом, структура может быть неоднородной. Для удобства работы с этими данными они сгруппированы под одним именем. При разработке программ структуры помогают в организации хранения и обработке сложных данных, не разобщая их по различным объектам, а группируя в одном. Кроме того, объекты, входящие в структуру сами могут быть структурой, т.е. структуры могут быть вложенными. Структуры позволяют группу связанных между собой переменных использовать как множество отдельных элементов, а также как единое целое. Как и массив, структура представляет собой совокупность данных, но отличается от него тем, что к ее элементам (компонентам) необходимо обращаться по имени и ее элементы могут быть различного типа. Структуры целесообразно использовать там, где необходимо объединить разнообразные данные, относящиеся к одному объекту.
Примером использования структуры может служить, например, строка платежной ведомости. В ней должна содержаться информация о служащем: ФИО, адрес, табельный номер, зарплата и т.д.
Как и другие объекты в С(С++) (переменные, массивы и т.д.) структуры должны быть определены. Для этого создается (объявляется) некоторый тип являющийся структурой, а затем по мере необходимости определяются переменные этого типа (типа структура).
Объявление структуры осуществляется с помощью ключевого слова struct, за которым следует имя, называемое тегом (именем) структуры и списка элементов, заключенных в фигурные скобки. Тег дает название структуре данного вида и в дальнейшем служит кратким обозначением той части описания структуры, которая заключена в фигурные скобки, то есть является спецификатором. В общем виде определение структуры может быть представлена в следующем виде:
struct [имя типа структуры]
{ тип элемента 1 имя элемента 1;
. . . . . . . . . . . . .
тип элемента n имя элемента n; }[имя переменной стр-ры];
Имена структур должны быть уникальными в пределах их области видимости (действия), для того, чтобы компилятор мог различать различные типы шаблонов.
Именем элемента структуры может быть любой идентификатор. Как и ранее, при описании нескольких идентификаторов одного типа в структуре они могут быть описаны через запятую. Имена элементов структуры (полей) могут совпадать с именами обычных переменных (не являющихся элементами структуры), так как они всегда различимы по контексту. Более того, одни и те же имена элементов могут встречаться в объявлениях различных структур.
Задание только типа не влечет выделения “под него” памяти компилятором. Описание типа структуры предоставляет компилятору
необходимую информацию об элементах структурной переменной для резервирования места в оперативной памяти и организации доступа к ней при определении структурной переменной и использовании отдельных элементов структурной переменной.
Определение переменной имеющей тип структура аналогично определению переменных рассмотренных ранее типов, например:
struct inform |
|
{ char fam[30]; |
// фалилия |
int god; |
// год рождения |
float stag; |
// стаж работы |
}; |
|
inform rab; // определение переменной rab типа struct inform
С синтаксической точки зрения эта запись аналогична записи вида:
char fam[30]; |
// фалилия |
int god; |
// год рождения |
float stag; |
// стаж работы |
Вобоих случаях компилятор выделит под каждую переменную количество байтов памяти, требуемое согласно определения этой переменной (элемента структуры).
Описание шаблона и определение структурной переменной могут быть совмещены в одной записи, например:
struct book
{ char title [20]; char autor [30]; int page;
} bk1, bk2, *ptr_bk=&bk1;
Вэтом случае если имя структуры (тег) book более ни где не используется, то оно может быть опущено.
Ранее мы уже рассматривали процедуру инициализации переменных и массивов. Как и обычные переменные, элементы, входящие в состав структуры (определяющие структурную переменную), могут быть инициализированы. При этом можно инициализировать, как только все элементы, определяющие структурную переменную при ее декларировании:
struct st{char c; int i1,i2}; struct st a={‘a’,105,25};
так и некоторые из них в процессе работы с ними: a.c=‘a’;
a.i2=25;
При выполнении инициализации структурных переменных необходимо следовать некоторым правилам:
-присваиваемые значения должны совпадать по типу с соответствующими полями структуры;
-можно объявлять меньшее количество присваиваемых значений, чем количество полей. Компилятор присвоит нули остальным полям структуры;
-список инициализации последовательно присваивает значения полям
структуры вложенных структур и массивов. Например:
struct comp
{char nazv[20]; float speed;
int cena;
} cp[3]={ {“Celeron”,0.6,525}, {“Duron”,1.0,547}, {“Atlon”,1.4,610}
};
Доступ к элементам структуры. Доступ к полям структуры осуществляется с помощью оператора «точка» - при непосредственной работе со структурой и "->" - при использовании указателей на структуру. Возможны три вида спецификации доступа к элементам структуры:
имя_переменной_структуры . имя_поля; имя_указателя -> имя_поля; (*имя_указателя) . имя_поля; например:
struct str
{int i; float j;
} st1, st2[3],*st3,*st4[5];
а) Прямой доступ к элементу (оператор “ .”) st1.i=12;
st2[1].j= .52;
б) Доступ по указателю (оператор “->”). st3->i=12;
(st4+1)->j=1.23; *(st3).j=23; *(st4[2]).i=123;
Шаблон структуры в качестве одного из полей не может содержать переменные своего типа, т.е. неправильным будет следующее объявление
шаблона: |
|
struct str |
|
{ char pole_1; |
|
double pole_2; |
|
str pole_3; |
// ошибка |
}; |
|
Однако структура может включать в себя элементы, являющиеся |
|
указателями на шаблон этой же структуры: |
|
struct str |
|
{ char pole_1; |
|
double pole_2; |
|
str *pole_3; |
// верно |
};
Так же как и массив, структура может быть введена поэлементно. Например, для описанной выше структуры st
gets(a.c);
scanf(”% d % f”, &a.i1, &a.i2);
Как отмечалось выше, структуры могут быть вложены дуг в друга: struct FIO {char F[15], I[10], O[12]} f;
struct rab { struct FIO fio; int tab; float zarpl} rb;
Структура rab содержит структуру FIO. Доступ к элементам структуры FIO и rab осуществляется следующим образом:
f. F=''Петров''; f.I ='' '';
rb.fio.O= "Иванович'';
Единственно возможные операции над структурами - это их копирование, присваивание, взятие адреса с помощью & и осуществление доступа к ее элементам (полям). Следует отметить, что оператор присваивания выполняет то, что называется поверхностной копией в применении к структурампеременным. Поверхностная копия представляет собой копирование бит за битом значений полей переменной-источника в соответствующие поля переменной-приемника. При этом может возникнуть проблема с такими полями, как указатели, поэтому использовать поверхностное копирование структур надо осторожно.
Копирование всех полей одной структуры в другую может быть выполнено как поэлементно, так и целиком, как это показано ниже:
#include <stdio.h>
struct book |
|
{ char avt[10]; |
|
int izd; |
|
} st1,st2; |
|
void main(void) |
|
{ gets(st1.avt); |
// ввод структуры st1 |
scanf("%d",&st1.izd); |
|
st2=st1; |
// копия всех полей структуры st1 в st2 |
}
Необходимо отметить, что копирование структур (st2=st1) допустимо, только если st1 и st2 являются структурными переменными соответствующими одному структурному типу.
Структуры нельзя сравнивать, то есть выражение if (st1==st2) неверно. Сравнение структур требуется выполнять поэлементно.
Если данные, объединенные в структуры, должны содержать информацию не об одном объекте, а о некотором их множестве, например, каталог библиотеки, телефонный справочник и т.д., то удобно использовать массивы структур.