Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

книги / Программирование на языке Си

..pdf
Скачиваний:
15
Добавлен:
12.11.2023
Размер:
17.16 Mб
Скачать

402

Программирование на языке Си

struct person

 

*prior;

 

/* Указатель

на

 

 

*/

struct person

 

 

предыдущий элемент

списка

 

*next;

 

/* Указатель

на

 

 

*/

} st[100];

 

 

 

следующий элемент

списка

 

/* Определен массив структур

*/

 

 

/* Управляющие

переменные: */

 

*/

 

 

 

/* Число элементов в массиве структур:

 

 

 

const

int М=100;

 

 

 

 

 

 

 

 

 

struct

control

 

 

 

 

 

 

 

 

 

 

int nb;

/*

Число

занятых элементов

*/

*/

 

 

int nf;

/*

Число

свободных элементов

 

 

/* Указатели

на структуры: */

списка

 

 

 

struct person

*bbeg;

/*

Начало

 

*/

struct person

*bend;

/*

занятых

элементов

Конец списка

 

 

*/

struct person

*fbeg;

/*

занятых

элементов

Начало

списка

 

 

*/

struct person

*fend;

 

свободных элементов

/* Конец списка

 

 

 

 

} Ctrl;

 

 

 

 

 

свободных элементов

*/

 

 

 

 

функций:

*/

 

 

 

 

/*

Прототипы вызываемых

 

 

 

 

int

init(void);

 

 

 

 

 

 

 

 

 

 

int input(void);

 

 

 

 

 

 

 

 

int delete(void);

 

 

*nam);

 

 

 

 

 

struct person *find(char

 

 

 

 

 

int fr(struct person

*ptr);

 

 

 

 

 

int print(void);

 

 

 

 

 

 

 

 

int save(void);

 

 

 

 

 

 

 

 

 

int'load(void);

 

 

 

 

 

 

 

 

 

/*

Текст главной

функции:

*/

 

 

 

 

 

void main(void)

 

 

 

 

 

 

 

 

 

 

{

 

numb[10];

/* Номер работы из меню

 

 

 

char

*/

 

/* Вывод меню на экран:

 

*/

 

 

 

 

 

while

(1)

 

 

 

 

 

 

 

 

 

 

 

{ /* Бесконечный цикл работы с базой данных*/ printf("1.Ввод сведений о новом сотруднике \п") ; printf("2.Удаление сведений о сотруднике \п"); printf("3.Печать содержимого базы данных \п"); printf("4.Сохранение базы данных в файле \п");

Глава 8. Примеры разработки программ

403

printf("5.Загрузка базы данных иэ файла \п"); printf("6.Инициализация базы данных \п"); printf("7.Окончание работы \п");

/* Ввод и обработка номера работы */ printf("\п\п Введите номер пункта меню\п"); scanf("%s", numb );

switch( numb[0] )

{

case '1':

input( );/* Ввод данных о новом сотруднике*/ break ;

case 2 ':

delete( );/*Удаление сведений о сотруднике*/ break ;

case '3':

print( );/* Печать содержимого базы данных*/ break ;

case '4' :

save( );/* Сохранение базы данных в файле */ break ;

case ’5':

load( ); /* Загрузка базы данных из файла */ break ;

case 'б ' :

init( ); /* Инициализация базы данных */ break ;

case '7' :

return ; /* Выход из программы */ default:

printf("Неверно указан номер пункта меню\п");

>

} /* Конец цикла */

}

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

Функция init() - "Инициализировать базу данных". Пер­ вое действие, которое должен выполнить пользователь при ра­ боте с базой данных, - это подготовить ее к работе (инициали-

26*

404

Программирование на языке Си

зировать). Функция init() связывает все элементы массива структур в "список свободных элементов" и устанавливает на­ чальные значения управляющих переменных.

В тексте функции для доступа к элементам структуры ис­ пользована операция ("стрелка"). Напомним, что она изо­ бражается двумя символами: ("минус") и ">" ("больше, чем") и называется операцией косвенного выбора элемента структуры, адресуемой указателем. Операция используется с указателем на структуру для доступа к элементу структуры.

Выражение point -> prior обеспечивает доступ к элементу prior той структуры, которую адресует указатель point. Иными словами, point -> prior эквивалентно st[i],prior, если ранее вы­ полнен оператор point=&st[i]; Ниже приводится текст функции init():

int init(void)/* Инициализировать базу данных */

{

struct person

*point=st;

/* Указатель на

int

i ;

 

 

 

текущий

элемент */

/* Число занятых элементов */

ctrl.nb = 0 ;

ctrl.nf = 0 ;

/* Число свободных элементов */

Ctrl.bbeg=NULL;

/*

Списка

занятых

 

C t r l .bend=NULL;

 

 

 

 

 

элементов нет */

 

C t r l . f b e g = s t ;

/ * s t - а д р е с н а ч а л а

*/

Ctrl.fend = st;

массива

структур

 

 

 

 

point = st;

Инициализация массива. \n");

printf("\n\n

for

(i=0; i<M-l;

i++ )

 

 

{

( ctrl.nf!=0

)

/* He

первый элемент: */

if

t

 

 

 

 

 

 

point -> prior = point-1;

 

point -> next = point+1;

 

>

 

/* Первый элемент:

*/

else

{

point -> prior = NULL; point —> next = point+1;

Глава 8. Примеры разработки программ

405

>

point++;

C t r l .nf++;

Ct r l .fend++;

}/* Конец цикла инициализации (М-1) элементов массива */

/ * И н и ц и а л и з а ц и я п о с л е д н е г о э л е м е н т а в м а с с и в е * / c t r l . n f + + ;

point -> prior=point-l; point -> next= NULL; return 0;

}

В этой функции для каждого элемента массива в цикле зада­ ются значения указателей на предыдущий и следующий элемен­ ты. Для первого элемента указатель prior устанавливается рав­ ным NULL. Для последнего элемента указатель next устана­ вливается также равным NULL (для этих элементов нет соот­ ветственно предыдущего и следующего элементов).

Функция delete() - "Удалить все сведения о сотруднике из базы данных". В работе функции delete() можно выделить два этапа:

поиск нужного элемента в списке занятых элементов;

удаление найденного элемента (возврат элемента в список свободных элементов).

Действия по поиску нужного элемента в списке целесообраз­ но оформить в виде отдельной функции Find(), текст которой приводится ниже. Аргументом (ключом) поиска элемента явля­ ется фамилия сотрудника, Для сравнения строк (фамилия, вве­ денная с терминала, и фамилия в структуре) используется стан­ дартная библиотечная функция strcm p(), параметрами которой являются указатели на сравниваемые строки. Функция strcm p(), описанная в заголовочном файле string.h, возвращает 0, если строки совпадают. Для сравнения строк можно было бы использовать функцию row(), текст которой приведен в §5.3, где рассматриваются строки как параметры функций.

Функция поиска элемента в списке занятых Find() должна возвращать указатель на найденный элемент либо NULL, если

/* Перемещаем указатель на следующий элемент списка */
/* nb - число занятых элементов */

406

Программирование на языке Си

элемент в списке не обнаружен. Конструкция struct person * перед именем функции find() сообщает компилятору языка Си, что функция возвращает указатель именно на структуру типа person. Приведем текст функции Fmd():

#±nclude <string.h> /* Для функции strcmp’*/ struct person *find(char *nam)

{

int i;

struct person *ptf; /* Вспомогательный указа­ тель на начало списка занятых элементов */

ctrl.ptf = bbeg;

for (i=0; Kctrl.nb; i++)

{

if ((strcmp(nam, ptf->name)) == 0) return ptf;

ptf = ptf->next;

}

/* Просмотрен весь список Занятых элементов */ return NULL;

}

При выполнении функции delete() удаления элемента из списка занятых производятся следующие действия:

запрос фамилии;

поиск фамилии в списке занятых элементов;

удаление найденного элемента из списка занятых;

возврат освобожденного элемента в список свободных.

Текст функции delete() может быть таким:

/* Удаление элемента из списка занятых: */ int delete(void)

{

char nam[20]; /* фамилия */ int i ;

struct person *ptr; /* Указатель на удаляемый элемент */

printf("\n\n Функция удаления элемента \п"); if (ctrl.nb = = 0)

Глава 8. Примеры разработки программ

407

{

printf(" список занятых элементов пуст \п"); return -1;

}

/* Запрос фамилии */

printf(" Введите : Ф.И.О. \п"); scanf("%s", пат);

/* Поиск фамилии: */

if ((ptr=find(nam))==0)/* Фамилия не найдена*/

{

printf(" фамилия не найдена\п"); return -1;

>

Фамилия

элемент:

*/

/*

найдена, удалить

if

(ptr ==

Ctrl.bbeg)

*/

 

{

/* Это

первый элемент

 

i f

( C t r l . n b = = 1)

 

 

{/* Единственный элемент в списке занятых */

'Ctrl.bend = NULL; fr(ptr);

return 0;

)

else

( /* He единственный элемент */

C t r l . b b e g = p t r - > n e x t ;

Ctrl.bbeg->prior = NULL; fr (ptr) ;

return 0;

)

)

else

{/* Это не первый элемент */

if

( p t r

= = C t r l . bend)

{/*

Это

последний элемент (не единственный)*/

ptr->prior->next = NULL;

C t r l . b e n d = p t r - > p r i o r ; f r ( p t r ) ;

r e t u r n 0 ;

{ /* Элемент в середине */ ptr->prior->next = ptr—>next; ptr->next->prior = ptr->prior;

408

Программирование на языке Си

f г ( p t r )

;

r e t u r n

0 ;

}

>

>

В функции delete() использовано обращение к функции fr(), текст которой приведен ниже. Функция fr() "привязывает" ос­ вобожденный элемент к списку свободных элементов, делая его головным, и корректирует глобальные управляющие перемен­ ные и указатели. Встретившийся в функции delete() оператор

p t r - > p r i o r —> n e x t = p t r - > n e x t ;

имеет следующий смысл (рис. 8.6 ч- 8.9). Так как операция "стрелка" (->) выполняется слева направо, то оператор можно записать так:

( p t r - > p r i o r ) - > n e x t = p t r - > n e x t ;

Это означает, что в поле next элемента, стоящего слева от удаляемого, заносится адрес элемент», который находится спра­ ва от удаляемого (рис. 8.7 ч- 8.9). На рис. 8.7 изображено исход­ ное состояние массива структур, а на рис. 8.8 и рис. 8.9 - изме­ нение значений указателей после удаления элемента из списка занятых элементов и возврата его в список свободных эле­ ментов.

Аналогично следует понимать и выражение

p t r - > n e x t - > p r i o r = p t r - > p r i o r ;

I

ptr

Р и с . 8 . 6 . С в я з и э л е м е н т а , н а к о т о р ы й с с ы л а е т с я у к а з а т е л ь p tr (N - n e x t, Р - p r io r )

, 8. Примеры разработки программ 409

bbeg

bend

fbeg

fend

|NULL| |N {— ►|p |

 

LT

|N 1— »|p Г |NDLL|

INOUJ

IN -ft -T»|P | INUIJLI

Рис. 8.7. Исходное Состояние массива структур (N - next, Р - prior)

bbeg

bend

fend

 

 

i

 

INULLI

I N K - TH P I 1NULL)

 

 

t.J

Рис. 8.8. Изменение значений указателей после удаления элемента

Рис. 8.9. Изменение значений указателей после возврата элемента в список свободных

410

Программирование на языке Си

Функция fr() - "Возвратить освобожденный элемент в список свободных элементов". Эта вспомогательная функция используется в функции delete():

/* Освобождение удаляемого элемента: */ int fг (struct person *ptr)

{

if (ctrl.nb == M ) /* Были Заняты все элементы

p t r - > p r i o r

= NULL;

p t r - > n e x t

= NULL;•

Ctrl.fbeg->prior = ptr;

C t r l . f b e g = p t r ;

>

e l s e

{

ptr->prior = NULL; ptr—>next = ctrl.fbeg;

C t r l . f b e g - > p r i o r = p t r ; c t r l . f b e g = p t r ;

}

C t r l . n b — c t r l . n f + + ; r e t u r n 0 ;

}

Функция input() - "Ввести в базу данных сведения о но­ вом сотруднике". Функция input() должна вводить информа­ цию о новом сотруднике, сохраняя алфавитный порядок записей в базе данных. При реализации этой функции возникают труд­ ности: буквы национального алфавита (в данном случае кирил­ лицы) в международной таблице кодов не упорядочены по возрастанию внутренних кодов, что требует для операций упо­ рядочения дополнительных перекодировок с применением про­ межуточных словарей. Чтобы в рассматриваемой задаче не отвлекаться на решение этой проблемы, договоримся, что при вводе новой записи в уже существующую базу данных добав­ ляемый элемент подсоединяется к хвостовому элементу списка занятых элементов. Однако при этом необходимо помнить, что

Глава 8. Примеры разработки программ

411

алфавитный порядок в списке занятых элементов будет нару­ шен.

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

/* Вставка нового элемента в список занятых элементов: */

int input(void)

{

struct person *ptr; /* Вспомогательный указатель */

printf("\n\n Функция вставки элемента \п "); if (ctrl.nf = = 0)

{

printf(" Свободных элементов нет\п"); return -1;

>

ptr = fbeg;

/* Запрос Ф .И .О . */

printf(" Введите: Ф.И.О. \п"); scanf("%s", fbeg->name); printf("Введите код отдела \п");

printf("l - Маркетинг\п 2 - Реклама\п"); printf("3 - Бухгалтерия\п "); scanf("%d", &ptr->depnumh); printf("Введите название отдела: \п"); scanf("%s", ptr->depname); printf("Введите оклад \n");

scanf("%d", &ptr->price); printf("Введите код должности: \n"); printf("1 - менеджер\n 2 — агент\п");

printf("3 - эксперт\п 4 - ст. консультант\п"); scanf("%d", &ptr->job);

printf("Введите наименование должности: \n"); scanf("%s", ptr->jobname);

printf ("Введите дату поступления на работу: \n") ; printf("по формату: ДД.ММ.ГГ\п");

scanf("%s", ptr->date);

/* Подключение элемента к списку занятых элементов */

Соседние файлы в папке книги