Правила записи программы на языке Си 5 Правила формального описания синтаксиса языка программирования 6

Вид материалаЛекции

Содержание


15.3.Организация данных в виде стека.
15.4.Организация данных в виде очереди.
15.5.Организация данных в виде деревьев.
16.Библиотека ввода-вывода языка C.
16.1.Открытие потока.
16.2.Закрытие потока.
16.3.Предопределенные указатели потоков.
Подобный материал:
1   ...   20   21   22   23   24   25   26   27   28

15.3.Организация данных в виде стека.


Понятие стека ("магазина"): первый пришел, последний ушел.

LIFO (LAST IN FIRST OUT)

Описание стека как списка:

typedef struct _LIST {

info_t info; /* тип данных для информации */

struct _LIST *next;

} LIST;

В вызывающей функции стек должен быть описан так:

LIST *head = NULL; /* голова списка */

Действия со стеком определяется несколькими функциями:
  1. Помещение элемента в стек (в голову списка)

void add_head (LIST *head, info_t a)

{

LIST *t;

if (t=(LIST*) malloc (sizeof (LIST)))

{

t->info = a; /* 1 */

t->next = (*head); /* 2 */

(*head) = t; /* 3 */

}

}


t .......... 2

: 1 a : :

..........

......... ......... ..........

3 : : : : : : : :NULL:

......... ......... ..........

head 3

  1. Извлечение из стека (из головы списка)

info_t get_head (LIST *head)

{

LIST *t; info_t a;

if ( *head)

{

a = (*head)->info; /* 1 */

t = (*head); /* 2 */

(*head) = (*head)->next; /* 3 */

free (t);

}

return a;

}


t 2

.......... ......... ..........

: 1 a : : : : : : :NULL:

.......... ......... ..........

3

head 3

15.4.Организация данных в виде очереди.



Понятие очереди: первый пришел, первый ушел.

FIFO (FIRST IN FIRST OUT).

Описание очереди: такое же, что и стека, но надо хранить и начало и хвост очереди.


.......... ......... ..........

head : : : : : : : :NULL:

.......... ......... ..........

tail


Тогда в вызывающей программе очередь описывается так:

LIST *head = NULL, *tail = NULL;

Помещение элемента в очередь (в хвост списка):


1-ый элемент: head

3 ..........

: :NULL:

5 ..........


tail t


Остальные: ......... ......... .........

: : : : : : : : :

......... ......... .........

head 5 4

tail ...........

5 :1 a:NULL:

...........

t 2


void add_tail (LIST*head, LIST*tail, info_t a)

{

LIST*t;

if (t = (LIST*) malloc (sizeof (LIST)))

{

t->info = a; /* 1 */

t->next = NULL; /* 2 */

if (*head) == NULL) (*head) = t; /* 3 */

else (*tail)->next = t;/* 4 */

(*tail) = t; /* 5 */

}

}

15.5.Организация данных в виде деревьев.


Схематически данные в виде дерева можно представить в следующем виде:

root .

. .

. . . .

.

root

.....................

: : : :

.....................


.................. ............

: : : : : : : :

.................. ............


........... .......... .......... ..........

: : :0: : :0:0: : :0:0: : :0:0:

........... .......... .......... ..........


..............

: :0 :0 :

..............


Каждая вершина дерева представляет собой структуру, имеющую информационное поле и указатели поддеревья, исходящие из этой вершины. Максимальное количество поддеревьев, сходящихся в одной вершине, называется порядком дерева. В данном случае порядок дерева равен двум, т. е. изображено бинарное дерево.

Описать это дерево можно следующим образом:

typedef struct _NODE {

info_t info;

struct _NODE*left;

struct _NODE*right;

} NODE;

.

.

.

NODE *tree = NULL;

При организации работы с деревом программист с помощью функции malloc получает необходимые вершины дерева и, заполняя поля left и right, организует необходимые связи вершины дерева.

16.Библиотека ввода-вывода языка C.


Прототипы функций описаны в файле . Основные идеи:
  1. В C отсутствуют встроенные средства ввода-вывода. Весь ввод-вывод осуществляется через функции, находящеся в библиотеке и легко замещаемые.
  2. Каждый файл рассматривается как непрерывный поток байт (stream). Никакой внутренней структуры файла не поддерживается.
  3. Не делается никаких различий между файлами на дисках и на других внешних устройствах.

16.1.Открытие потока.


Перед работой с любым файлом его надо предворительно открыть, т. е. связать с некоторой структурой предопределенного типа FILE, в которой находится вся необходимая информация для работы с потоком. Открытие потока осуществляется с помощью функции fopen, которая в случае успешного завершения возвращает указатель на структуру типа FILE, а в случае аварии - NULL. Полный ее прототип:

FILE *fopen (const char *filename, const char *mode);

где, filename - строка символов, содержащая имя файла (полное или простое), записанное по правилам DOS;

mode - режим работы файла, тоже строка символов;

mode = "r" - открыть существующий файл для чтения;

"w" - создать файл для записи, информация из существующего файла теряется;

"a" - открытие для записи в конец существующего файла или создание для записи, если файла нет;

"r+" - открытие существующего файла для чтения и записи;

"w+" - создание нового файла для чтения и записи;

"a+" - откратие или создание для обновления в конец;

16.2.Закрытие потока.


После того как была выполнени вся работа с файлом, его необходимо закрыть. Это необходимо сделать по крайней мере по двум причинам:
  1. если программа обрабатывает большое количество файлов, то в конце концов может не хватить на все системных ресурсов;
  2. незакрытый файл может в случае сбоя пропасть.

Файл закрывается функцией:

int fclose (FILE *stream);

где, stream - указатель потока.

Функция возвращает 0 в случае успеха и EOF - если нет. EOF - (End Of File) - специальная константа из .

Функция fcloseall закрывает все потоки:

int fcloseall (void);

В случае успеха функция возвратит количество закрытых потоков, иначе - EOF.

Если программист забыл закрыть какие-либо потоки, то все равно они будут закрыты системой MS DOS по завершению работы программы.

Типичный пример работы с файлом:



.

.

.

void main (void)

{

FILE *my_file; static char *fn = "d:\\USER\\f.dat";

.

.

.

if ((my_file = fopen (fn, "r")) == NULL)

{ printf ("Не могу открыть файл %s\n", fn);

return; }

.

.

.

fclose (my_file);

}

16.3.Предопределенные указатели потоков.


С началом выполнения C-программы автоматически открывается пять потоков. Их указатели имеют предопределенные имена и представляют константы типа указателя на структуру FILE.

stdin - стандартный поток ввода;

stdout - стандартный поток вывода;

stdprn - стандартный поток вывода на печать;

stdaux - стандартный дополнительный поток;

stderr - стандартный вывод сообщений об ошибке.

Имена этих потоков можно использовать везде, где допускаются имена потоков без предварительного открытия соответствующего потока.

Имеется целый ряд специальных функций работы со стандартными потоками ввода-вывода (в основном stdin и stdout). Мы их частично рассматривали (например, printf).

Поскольку указатели стандартных потоков являются константами, им нельзя присваивать значений. Но любой стандартный поток может прерываться с помощью функции freopen.

FILE *freopen (const char *fn, const char *mode, FILE *stream);

stream - указатель существующего потока, в том числе стандартного.

Функция возвращает stream в случае успеха, иначе - NULL.

Пример:

if (fopen ("d:\\a.std", "w", stdout) == NULL)

{ ... обработка ошибки открытия ... }

/* переназначение стандартного вывода на диск */

if (freopen ("CON", "w", stdout) == NULL)

{ ... обработка ошибки переназначения ... }

/* возврат стандартного вывода на консоль */

16.4.Функции ввода-вывода.


---------------------------------------------------------

Opens a stream

FILE *fopen(const char *filename, const char *mode);

Returns a pointer to the newly open stream if successful;

otherwise it returns NULL.

-------------