- •7. Программирование алгоритма линейной структуры на языке Си 27
- •8. Понятие о препроцессоре языка Си 28
- •9. Операторы языка Си и приемы программирования 28
- •10. Массивы. Адресная арифметика языка Си 47
- •1.Правила записи программы на языке Си
- •2.Правила формального описания синтаксиса языка программирования
- •3.Идентификаторы языка Си
- •4.Понятие о типах данных.
- •4.1.Системы счисления. Представление данных в эвм.
- •4.2.Основные типы данных языка Си
- •4.3.Правила записи констант различных типов
- •4.4.Беззнаковый тип для целых данных
- •4.5.Символьные строки
- •5.Понятие функции
- •5.1.Стандартная функция printf
- •5.2.Стандартная функция scanf
- •6.Операции и выражения
- •6.1.Простейшие арифметические операции
- •6.2.Операция присваивания
- •6.3.Оператор-выражение
- •6.4.Использование в выражениях операндов разных типов
- •6.5.Операции преобразования типов
- •6.6.Стандартные математические функции
- •6.7.Простейшие функции, определяемые программистом
- •6.8.Дополнительные арифметические операции
- •6.9.Дополнительные операции присваивания
- •6.10.Битовые операции
- •6.11.Операции отношения
- •6.12.Логические операции
- •6.13.Операция определения размера данных
- •6.14.Приоритеты операций
- •7.Программирование алгоритма линейной структуры на языке Си
- •8.Понятие о препроцессоре языка Си
- •9.Операторы языка Си и приемы программирования
- •9.1.Оператор цикла while
- •9.2.Условный оператор и условная операция
- •1) Короткие операторы:
- •2) Группы коротких операторов:
- •3) Длинные группы операторов:
- •9.3.Запись алгоритмов с помощью диаграмм Несси - Шнейдермана (структограмм )
- •9.4.Н екоторые приемы программирования
- •9.5.Оператор прерывания цикла
- •9.6.Оператор продолжения цикла
- •9.7.Пример организации простейшего меню
- •9.8.Множественный выбор. Оператор переключения
- •9.9.Оператор цикла do-while.
- •9.10.Перечисления. Работа с клавиатурой ibm pc
- •9.11.Пример организации светового меню
- •10.Массивы. Адресная арифметика языка Си
- •10.1.Описание массива
- •10.2.Ввод-вывод массива
- •10.3.Инициализация массива
- •10.4.Программа вычисления длины строки символов
- •10.5.Двумерные массивы (массивы массивов)
- •10.6.Адресная арифметика языка Си
- •10.7.Указатели и одномерные массивы
- •10.8.Указатели и двумерные массивы
- •10.9.Указатели и функции
- •10.10.Оператор typedef
- •10.11.Дополнительные описания указателей для ibm pc
- •10.12.Непосредственная работа с экранной памятью
- •11.Дополнительные сведения о функциях
- •11.1.Области видимости и глобальные данные
- •11.2.Время жизни переменных и классы памяти языка Си
- •11.3.Передача аргументов в функцию
- •11.4.Возврат значений из функций
- •12.Работа с динамической памятью
- •12.1.Стандартные функции управления динамической памятью
- •12.2.Пример использования динамической памяти
- •12.3.Особенности работы с двумерными массивами
- •12.3.1.Пересчет индексов вручную
- •12.3.2.Массивы с постоянной длиной строки
- •12.3.3.Общий случай двумерного массива
- •12.4.Особенности работы с массивами большого размера
- •13.Модульное программирование в системе Turbo c
- •13.1.Обеспечение корректной стыковки модулей
- •13.2.Создание библиотек функций
- •14.Некоторые библиотечные функции языка Си
- •14.1.Функции консольного ввода/вывода (уникальны для tc)
- •14.2.Функции обработки строк.
- •14.3.Функции распознавания вида символа
- •14.4.Функции преобразования данных
- •15.Структуры языка c.
- •15.1.Описание структуры
- •1 Способ
- •2 Способ
- •15.2.Трактовка имени структуры.
- •15.2.1.Доступ к элементу структуры.
- •15.3.Инициализация структур.
- •15.4.Структуры и функции.
- •15.5.Поля бит в структурах.
- •16.Объединения.
- •17.Дополнительные сведения о препроцессоре языка c.
- •18.Условное выражение.
- •18.1.Приоритеты и направления операций.
- •19.Динамические данные.
- •19.1.Линейные списки.
- •19.2.Организация данных в виде стека.
- •19.3.Организация данных в виде очереди.
- •19.4.Организация данных в виде деревьев.
- •20.Библиотека ввода-вывода языка c.
- •20.1.Открытие потока.
- •20.2.Закрытие потока.
- •20.3.Предопределенные указатели потоков.
- •20.4.Функции ввода-вывода.
19.Динамические данные.
19.1.Линейные списки.
Использование указателей на структуры позволяет использовать весьма сложно организованные данные типа различного рода списков, очередей и деревьев. Рассмотрим так называемые линейные списки.
Линейный список - это упорядоченная структура данных, каждый элемент которой содержит ссылку (указатель), связывающую его со следующим элементом.
Для организации списков служат структуры, состоящие из двух смысловых частей: основной, содержащей полезную информацию, и дополнительной, содержащей ссылку на следующий элемент списка. Графически это можно представить следующим образом:
......... ......... ......... ......... ...........
: : : : : : : : : : : : : :NULL:
......... ......... ......... ......... ...........
В виде списков удобно представлять большие объемы информации, размер которых заранее неизвестен.
Рассмотрим, например, как можно было бы организовать хранение информации о товарах для программы "магазин".
typedef struct _GOODS{
char name[21];
int number;
float price;
struct _GOODS *next;
} GOODS;
Очевидно, программа должна иметь переменную - указатель на первый элемент списка. Последний элемент списка отличается тем, что в поле next имеет константу NULL - то есть пустой указатель. Тогда список может быть представлен так:
......... ......... ......... ...........
TOP : : : : : : : : : : :NULL:
......... ......... ......... ...........
Программа формирования списка товаров выглядит следующим образом:
GOODS *new_GOODS ( void)
{
GOODS *p;
p = (GOODS* ) malloc( sizeof(GOODS) );
if (p==NULL) {printf("Недостаточно памяти\n");
exit(1);}
return p;
}
GOODS *in_goods( void )
{
GOODS *top, *q;
printf("Введите характеристики товаров в виде:\n" \
"наименование количество цена\n" \
"-------окончание ввода \"end\"-------\n");
top = NULL;
while (1)
{
q = new_GOODS(); if( !in_goods1(q) ) { free(q);
return top; }
q->next = top; top = q;
}
}
Обращение к этой программе будет выглядеть так:
top = in_goods();
Вспомогательная программа new_GOODS осуществляет все необходимые действия по выделению памяти и контролю за ее наличием.
Достоинство такой организации данных в том, что используется ровно столько памяти, сколько надо (накладные расходы - поле адреса). Вместе с тем список может быть сколь угодно большим. Ограничение - память ЭВМ. Недостаток - мы не имеем возможности прямого доступа к памяти.
Рассмотрим процедуру вывода на печать содержимого списка. Обратить внимание на то, что содержимое выводится в порядке обратном вводу (в принципе можно было бы и наоборот).
void out_goods( GOODS *top)
{
printf("*--------------------------------------*\n");
printf("| Наименование | Кол-во | Цена |\n");
printf("|--------------------|--------|--------|\n");
while( top != NULL )
{
printf( "| %20s | %10.2f |\n",
top->name, top->number, top->price );
top = top->next;
}
printf("*--------------------------------------*\n");
}
Головная функция должна выглядеть следующим образом:
void main( void )
{
GOODS *top;
top = in_goods();
out_goods ( top );
}
Как же быть с сортировкой, а ее вообще не надо делать, так как можно в процессе ввода получить отсортированный список, вставляя очередную запись в нужное место.
Рассмотрим вспомогательную задачу: необходимо вставить запись, на которую указывает указатель g в список за записью, на которую указывает указатель p.
g .........
: :. :
......|..
2 ^ | 1
| V
TOP ......... ......... ......... ......... ..........
: : : : : p : : : : : : : : :NULL:
......... ......... ......... 2 ......... ..........
p
g->next = p->next; 1
p->next = g; 2
Текст программы выглядит следующим образом:
GOODS *in_goods( void )
{
GOODS *top, *q, *p;
printf("Введите характеристики товаров в виде:\n" \
"наименование количество цена\n" \
"-------окончание ввода \"end\"-------\n");
/* Получение списка из двух элементов */
top = NULL;
q=new_GOODS(); if(!in_goods1(q)) {free(q); return top;}
q->next = NULL; top = q;
q=new_GOODS(); if(!in_goods1(q)) {free(q); return top;}
if(q->price < top->price ) { q->next = top; top = q; }
else { q->next = NULL; top->next = q; }
/* Получение списка из остальных элементов */
while( 1 )
{
q=new_GOODS(); if(!in_goods1(q)) {free(q); return top;}
if(q->price < top->price )
{ q->next = top; top = q; }
else
{
p = top;
while(p->next && (q->price > p->next->price)) p=p->next;
q->next = p->next; p->next = q;
}
}
}
/* Пример использования списка # 1 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <alloc.h>
#include <math.h>
typedef struct _GOODS{
char name[21];
int number;
float price;
struct _GOODS *next;
} GOODS;
GOODS in_goods ( void );
GOODS new_goods ( void );
int in_goods1 ( GOODS *g );
void out_goods (GOODS *top );
void main( void )
{
GOODS *top;
top = in_goods();
out_goods ( top );
{ float f=0; sin(f); }
}
GOODS *new_GOODS ( void )
{
GOODS *p;
p = (GOODS*) malloc( sizeof(GOODS) );
if (p==NULL) {printf("Недостаточно памяти\n");
exit(1);}
return p;
}
GOODS *in_goods( void )
{
GOODS *top, *q;
printf("Введите характеристики товаров в виде:\n" \
"наименование количество цена\n" \
"-------окончание ввода \"end\"-------\n");
top = NULL;
while (1)
{
q = new_GOODS(); if( !in_goods1(q) ) { free(q);
return top; }
q->next = top; top = q;
}
}
int in_goods1( GOODS *g )
{
scanf( "%s", q->name );
if ( strcmp(g->name, "end")== ) return 0;
scanf( "%d%f", &g->number, &g->price );
return 1;
}
void out_goods( GOODS *top)
{
printf("*--------------------------------------*\n");
printf("| Наименование | Кол-во | Цена |\n");
printf("|--------------------|--------|--------|\n");
while( top != NULL )
{
printf( "| %20s | %10.2f |\n",
top->name, top->number, top->price );
top = top->next;
}
printf("*--------------------------------------*\n");
}
/* Пример использования списка с сортировкой */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <alloc.h>
#include <math.h>
typedef struct _GOODS{
char name[21];
int number;
float price;
struct _GOODS *next;
} GOODS;
GOODS in_goods ( void );
GOODS new_goods ( void );
int in_goods1 ( GOODS *g );
void out_goods (GOODS *top );
void main( void )
{
GOODS *top;
top = in_goods();
out_goods ( top );
{ float f=0; sin(f); }
}
GOODS *new_GOODS ( void )
{
GOODS *p;
p = (GOODS*) malloc( sizeof(GOODS) );
if (p==NULL) {printf("Недостаточно памяти\n");
exit(1);}
return p;
}
GOODS *in_goods( void )
{
GOODS *top, *q, *p;
printf("Введите характеристики товаров в виде:\n" \
"наименование количество цена\n" \
"-------окончание ввода \"end\"-------\n");
/* Получение списка из двух элементов */
top = NULL;
q=new_GOODS(); if(!in_goods1(q)) {free(q); return top;}
q->next = NULL; top = q;
q=new_GOODS(); if(!in_goods1(q)) {free(q); return top;}
if(q->price < top->price ) { q->next = top; top = q; }
else { q->next = NULL; top->next = q; }
/* Получение списка из остальных элементов */
while( 1 )
{
q=new_GOODS(); if(!in_goods1(q)) {free(q); return top;}
if(q->price < top->price )
{ q->next = top; top = q; }
else
{
p = top;
while(p->next && (q->price > p->next->price)) p=p->next;
q->next = p->next; p->next = q;
}
}
}
int in_goods1( GOODS *g )
{
scanf( "%s", q->name );
if ( strcmp(g->name, "end")== ) return 0;
scanf( "%d%f", &g->number, &g->price );
return 1;
}
void out_goods( GOODS *top)
{
printf("*--------------------------------------*\n");
printf("| Наименование | Кол-во | Цена |\n");
printf("|--------------------|--------|--------|\n");
while( top != NULL )
{
printf( "| %20s | %10.2f |\n",
top->name, top->number, top->price );
top = top->next;
}
printf("*--------------------------------------*\n");
}
