- •Основы алгоритмизации и программирования, язык Си
- •Введение
- •Блок-схема алгоритма Общие требования к блок-схеме алгоритма
- •Линейные и разветвляющиеся процессы
- •Циклические процессы
- •Итерационные процессы
- •Комментарии
- •Типы данных
- •Данные целого типа
- •Данные вещественного типа
- •Модификатор const
- •Переменные перечисляемого типа
- •Константы
- •Операции и выражения
- •Операция присваивания
- •Арифметические операции
- •Операции поразрядной арифметики
- •Логические операции
- •Операции отношения
- •Инкрементные и декрементные операции
- •Операция sizeof
- •Порядок выполнения операций
- •Приоритет операций
- •Преобразование типов
- •Операция приведения
- •Операция запятая
- •Ввод и вывод информации
- •Директивы препроцессора Директива #include
- •Директива #define
- •Понятие пустого и составного операторов
- •Условные операторы
- •Операторы организации цикла
- •Оператор цикла for
- •Оператор цикла while
- •Оператор цикла do … while
- •Вложенные циклы
- •Операторы перехода (break, continue, return, goto)
- •Примеры программ
- •Массивы Одномерные массивы
- •Примеры программ
- •Многомерные массивы (матрицы)
- •Примеры программ
- •Указатели Понятие указателя
- •Описание указателей
- •Операции с указателями
- •Связь между указателями и массивами
- •Массивы указателей
- •Многоуровневые указатели
- •Примеры программ
- •Символьные строки
- •Ввод/вывод строк.
- •Функции работы со строками.
- •Примеры программ
- •Функции
- •Прототип функции.
- •Определение функции.
- •Параметры функции
- •Параметры по умолчанию
- •Передача массива в функцию
- •Inline функции
- •Класс памяти
- •Автоматические переменные
- •Статические переменные
- •Регистровые переменные
- •Блочная структура
- •Примеры программ
- •Указатели на функции
- •Примеры программ
- •Рекурсия
- •Примеры программ
- •Аргументы в командной строке
- •Функции с переменным числом параметров
- •Примеры программ
- •Сортировка
- •Пузырьковая сортировка.
- •Шейкер сортировка
- •Сортировка вставкой
- •Сортировка выбором
- •Метод Шелла
- •Метод Хора
- •Структуры
- •Доступ к элементам структуры
- •Инициализация структур
- •Указатели на структуры.
- •Структуры и функции
- •Примеры программ
- •Поля бит
- •Объединения
- •Переменные с изменяемой структурой
- •Примеры программ
- •Организация списков и их обработка
- •Операции со списками при связном хранении
- •Построение обратной польской записи
- •Односвязный линейный список, очередь
- •Двусвязный линейный список
- •Циклический список, кольцо
- •Двусвязный циклический список
- •Примеры программ
- •Деревья
- •Потоки и файлы
- •Файлы Основные сведения о файловой системе
- •Организация посимвольного ввода и вывода
- •Определение конца файла feof()
- •Организация ввода и вывода строк
- •Удаление файлов
- •Дозапись потока
- •Позиционирование в файле
- •Текстовые и двоичные файлы
- •Функции fread() и fwrite()
- •Примеры программ
- •Хеширование
- •Схемы хеширования
- •Метод открытой адресации с линейным опробыванием
- •Метод цепочек
- •Машинное представление графов
- •Примеры программ
- •Литература
Указатели на структуры.
Как и для других структурированных типов данных, указатели могут быть использованы и для структур. Это имеет следующие положительные черты:
- указателями на структуры легче пользоваться, чем самими структурами (например, в задаче сортировки);
- ряд данных удобно представлять в виде структур, полями которых являются указатели на другие структуры.
Рассмотрим пример, показывающий, как определять указатель на структуру и использовать его для работы с элементами структуры.
#include <stdio.h>
#define DL 30 // max число символов в строке char
struct name{char fio[DL];}; // ФИО объекта
struct inform{ name nm; // поле ссылка на структуру name
char prof[DL]; // поле профессия
int god; // поле год рождения
float okl; // поле оклад
};
void main(void)
{ static inform mas[2]=
{ "Иванов","конструктор",1965,15000.50,
"Петров","оператор",1967,12350.50};
inform *him; // указатель на структуру
printf("адрес mas[0]: %u mas[1]: %u \n",&mas[0],&mas[1]);
him=mas; // him содержит адрес mas[0]
printf("адрес mas[0]: %u mas[1]: %u \n",him,him+1);
printf("him->okl = %.2f (*him).okl = %.2f \n",him- >okl, (*him)okl);
him++; // him содержит адрес следующей стр-ры
printf("him->okl = %.2f (*him).okl = %.2f \n",him- >okl, *him).okl);
++him->okl; // увеличение значения поля okl на 1
printf("him->okl = %.2f (*him).okl = %.2f \n",him- >okl, *him).okl);
}
Синтаксис, используемый при описании указателя на структуру, такой же, как и для других структурированных данных:
struct имя_структуры * имя_указателя;
Таким образом, раз him - указатель на структуру inform, то *him есть сама структура, а (*him).okl - одно из полей структуры.
В выражении (*him).okl используются скобки, так как приоритет операции « . » выше чем « * ». Для упрощения доступа к элементам структуры (избежания ошибок, связанных с учетом приоритета) была введена операция -> (операция косвенного получения элемента). Эта операция имеет следующую форму записи:
имя_указателя -> имя_поля_структуры;
Этот оператор состоит из двух знаков - и >. Операция -> имеет наивысший приоритет, наряду с операциями () [ ] и, таким образом, чтобы перейти к полю okl следующей структуры, необходимо записать:
(++him)->okl; или (him++)->okl;
Рассмотрим еще один пример объявления структуры:
struct
{ char * str;
float f;
} *pr;
Как и выше, *pr->str есть содержимое объекта, на который ссылается str; *pr->str++ передвинет указатель pr->str после считывания объекта, на который он указывал; (*pr->str) ++ увеличит значение объекта, на который ссылается str; *pr ++->str передвинет указатель pr после получения значения, на которое указывает str.
Структуры и функции
В функцию можно наряду со стандартными типами данных передавать и структуры.
struct men // обьявление структуры men
{ char *String;
int Number;
int Marks[10];
};
men sum(men); // первый прототип функции sum
void sum (men*); // второй прототип функции sum
Выше приведены два прототипа функции sum. В первом описывается функция, в которой создается локальная структурная переменная, в которую и производится копирование значения переменной типа структура men. Все изменения выполняемые над полями этой локальной структурной переменной локальны в функции и следовательно, что бы были видны за пределами функции sum должны быть возвращены.
Второй прототип описывает функцию, в которую передается указатель на некоторую структурную переменную. В функции преобразования, выполняются над полями структуры расположенной в памяти по указателю, который в нее передан. Поэтому функция может ничего не возвращать. Этот вариант функции лучше, нежели первый, он будет работать быстрее и требует меньшего количества памяти.
При передаче структуры в функцию по значению она может быть передана либо вся структура целиком, либо по полям (компонентам) структуры.
Передача функции компонент структуры. В общем случае, элемент структуры является переменной (массивом) некоторого типа, и может быть передан как аргумент функции. Рассмотрим следующую несложную программу, выполняющую суммирование окладов нескольких профессий, и нахождение max из них:
#include <stdio.h>
float summa(float,float *);
struct str
{ char *prof[5]; // профессия
float okl[5],sm; // оклад и сумма
} ok= {"проф1","проф2","3","4","", 1.5,2.06,31.4,3.0,0,0};
void main(void)
{ float max;
int i;
for(i=0;i<5;i++) max=summa(ok.okl[i],&ok.sm);
printf("max значение =%5.2f\n сумма = %5.2f",max,ok.sm);
}
float summa(float i,float *j)
{ static float max=0;
*j+=i; // вычисление суммы
max=(max>i)?max:i; // поиск max значения
return max;
}
Рассматриваемая программа состоит из двух функций: main() и summa(). Функции summa() в качестве параметров передаются один из суммируемых окладов (ok.okl[i]) и адрес элемента структуры, куда помещается сумма (&ok.sm). Функция summa() также возвращает вычисленное максимальное значение оклада.
Передача всей структуры в функцию. В этом случае выполняется передача данных всей структуры в функцию (в стек) со всеми полями, которые в нее входят (массивы, другие структуры и т. д.).
При этом никакие изменения структуры внутри функции не влияют на структуру, используемую в качестве аргумента. При использовании структуры в качестве параметра, тип аргумента должен соответствовать типу параметров. Это можно сделать определив структуру глобально, а затем использовать ее для объявления необходимых структурных переменных и параметров.
#include <stdio.h>
float sr_ball(struct str );
struct str
{ char prof[15];
int oc[4];
};
main()
{ float bl;
struct str s= {"Иванов",5,4,3,5};
bl=sr_ball(s);
printf("средний балл =%5.2f",bl);
return 0;
}
float sr_ball(struct str st)
{
return (st.oc[1]+st.oc[2]+st.oc[3]+st.oc[4])/4;
}