- •Основы алгоритмизации и программирования, язык Си
- •Введение
- •Блок-схема алгоритма Общие требования к блок-схеме алгоритма
- •Линейные и разветвляющиеся процессы
- •Циклические процессы
- •Итерационные процессы
- •Комментарии
- •Типы данных
- •Данные целого типа
- •Данные вещественного типа
- •Модификатор const
- •Переменные перечисляемого типа
- •Константы
- •Операции и выражения
- •Операция присваивания
- •Арифметические операции
- •Операции поразрядной арифметики
- •Логические операции
- •Операции отношения
- •Инкрементные и декрементные операции
- •Операция sizeof
- •Порядок выполнения операций
- •Приоритет операций
- •Преобразование типов
- •Операция приведения
- •Операция запятая
- •Ввод и вывод информации
- •Директивы препроцессора Директива #include
- •Директива #define
- •Понятие пустого и составного операторов
- •Условные операторы
- •Операторы организации цикла
- •Оператор цикла for
- •Оператор цикла while
- •Оператор цикла do … while
- •Вложенные циклы
- •Операторы перехода (break, continue, return, goto)
- •Примеры программ
- •Массивы Одномерные массивы
- •Примеры программ
- •Многомерные массивы (матрицы)
- •Примеры программ
- •Указатели Понятие указателя
- •Описание указателей
- •Операции с указателями
- •Связь между указателями и массивами
- •Массивы указателей
- •Многоуровневые указатели
- •Примеры программ
- •Символьные строки
- •Ввод/вывод строк.
- •Функции работы со строками.
- •Примеры программ
- •Функции
- •Прототип функции.
- •Определение функции.
- •Параметры функции
- •Параметры по умолчанию
- •Передача массива в функцию
- •Inline функции
- •Класс памяти
- •Автоматические переменные
- •Статические переменные
- •Регистровые переменные
- •Блочная структура
- •Примеры программ
- •Указатели на функции
- •Примеры программ
- •Рекурсия
- •Примеры программ
- •Аргументы в командной строке
- •Функции с переменным числом параметров
- •Примеры программ
- •Сортировка
- •Пузырьковая сортировка.
- •Шейкер сортировка
- •Сортировка вставкой
- •Сортировка выбором
- •Метод Шелла
- •Метод Хора
- •Структуры
- •Доступ к элементам структуры
- •Инициализация структур
- •Указатели на структуры.
- •Структуры и функции
- •Примеры программ
- •Поля бит
- •Объединения
- •Переменные с изменяемой структурой
- •Примеры программ
- •Организация списков и их обработка
- •Операции со списками при связном хранении
- •Построение обратной польской записи
- •Односвязный линейный список, очередь
- •Двусвязный линейный список
- •Циклический список, кольцо
- •Двусвязный циклический список
- •Примеры программ
- •Деревья
- •Потоки и файлы
- •Файлы Основные сведения о файловой системе
- •Организация посимвольного ввода и вывода
- •Определение конца файла feof()
- •Организация ввода и вывода строк
- •Удаление файлов
- •Дозапись потока
- •Позиционирование в файле
- •Текстовые и двоичные файлы
- •Функции fread() и fwrite()
- •Примеры программ
- •Хеширование
- •Схемы хеширования
- •Метод открытой адресации с линейным опробыванием
- •Метод цепочек
- •Машинное представление графов
- •Примеры программ
- •Литература
Примеры программ
Пример . Используя поля бит, написать программу вычисляющую остаток от деления целого числа на 4.
#include<stdio.h>
struct pole
{ unsigned int p1:1; // младший бит числа
unsigned int p2:1;
int p3:14;
}*p ;
int main()
{ int n=26;
p=(pole*)&n; // указатель р содержит адрес числа n
printf("\nостаток от деления числа на 2 = ");
if(p->p1) puts(" 1");
else puts(" 0");
printf("\nостаток от деления числа на 4 = ");
if(p->p1 && p->p2) puts(" 3");
else if(!p->p1 && p->p2) puts(" 2");
else if(p->p1 && !p->p2) puts(" 1");
else puts(" 0");
return 0;
}
Пример . Используя поля бит и объединения можно изменить рассмотренную выше программу вычисляющую остаток от деления целого числа на 2 и 4.
#include <stdio.h>
#include<conio.h>
int main(int) // вычисление остатка от деления на 2 , 4
{ struct pole
{ union
{ struct
{ unsigned i1:1;
int:1;
} st1;
struct
{ unsigned i1:2;
}st2;
} un;
int:14;
};
pole *pl;
int k;
scanf("%d",&k);
pl=(pole *)&k;
clrscr();
printf("\nостаток от деления на 2 =%d",pl->un.st1.i1);
printf("\nостаток от деления на 4 =%d",pl->un.st2.i1);
}
Организация списков и их обработка
Динамические переменные чаще всего реализуются как связанные структуры, списки.
Список – это набор динамических элементов (чаще всего структурных переменных) связанных между собой каким либо способом.
Списки бывают линейными и кольцевыми, односвязными и двусвязными.
Динамические переменные, как правило, имеют тип “структуры”, так как должны содержать помимо значения (целого, вещественного и т.д.), ссылку на другую динамическую переменную. Чтобы связать динамические переменные в цепочку, надо в каждой компоненте иметь ссылку на предыдущую компоненту, так как это не массив и различные компоненты могут быть размещены в произвольных областях памяти.
Описание структуры и указателя в этом случае может иметь вид:
typedef struct element // структура элемента хранения
{ float val; // элемент списка
element *n ; // указатель на элемент хранения
} SPIS;
SPIS *p; // указатель текущего элемента
SPIS *dl; // указатель на начало списка
Для выделения памяти под элементы хранения необходимо пользоваться функцией malloc(sizeof(element)) или calloc(l,sizeof(element)). Формирование списка в связанном хранении может осуществляется операторами:
p=( SPIS*)malloc(sizeof(SPIS);
p->val=10; p->n=NULL;
dl=( SPIS*)malloc(sizeof(SPIS));
dl->val=7; dl->n=p;
В последнем элементе хранения (конец списка) указатель на соседний элемент имеет значение NULL. Получаемый список изображен на рис.11.
Рис. 11 . Связное хранение линейного списка.
При работе со списками на практике чаще всего приходится выполнять следующие операции:
- поиск элемента с заданным свойством;
- определение первого элемента в линейном списке;
- добавление нового элемента до или после указанного узла;
- исключение определенного элемента из списка;
- упорядочивание узлов линейного списка.
Ниже приведены фрагменты программ и схемы демонстрирующие некоторые из операций над списками.