Основы программирования

Изучение основных правил формального описания синтаксиса языка программирования. Ознакомление с требованиями к байту перед вызовом функции. Исследование процесса организации данных в виде стека. Рассмотрение и характеристика примеров работы с файлами.

Рубрика Программирование, компьютеры и кибернетика
Вид курс лекций
Язык русский
Дата добавления 12.10.2016
Размер файла 156,4 K

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

/* Пример использования структур */

#include <stdio.h>

#include <string.h>

#include <math.h>

typedef struct {

char name[21];

int number;

float price;

} GOODS;

void in_goods ( GOODS gs[], int *n );

int in_goods1 ( GOODS *g );

void out_goods ( GOODS gs[], int n );

void sort_goods ( GOODS gs[], int n);

void main( void )

{

int n; GOODS goods[100];

in_goods ( goods, &n );

sort_goods ( goods, n );

out_goods ( goods, n );

{ float f=0; sin(f); }

}

void in_goods( GOODS gs[], int *n)

{

printf("Введите характеристики товаров в виде:\n" \

"наименование количество цена\n" \

"-----окончание ввода \"end\"-------\n");

*n=0;

while( in_goods1(&gs[*n]) ) (*n)++;

}

int in_goods1( GOODS *g )

{

scanf( "%s", g->name );

if ( strcmp(g->name, "end")==0 ) return 0;

scanf( "%d%f", &g->number, &g->price );

return 1;

}

void out_goods( GOODS gs[], int n )

{

int i;

printf("*----------------------------------*\n");

printf("| Наименование | Кол-во | Цена |\n");

printf("|---------------|--------|--------|\n");

for( i=0; i<n; i++)

printf( "| %20s | %6d | %10.2f |\n",

gs[i].name, gs[i].number, gs[i].price );

printf("*-------------------------------*\n");

}

void sort_goods( GOODS gs[], int n )

{

int i, j, GOODS r;

for (i=0; i<n-1; i++)

for(j=i+1; j<n; j++)

if( gs[i].price )

{ r=gs[j]; gs[j]=gs[i]; gs[i]=r; }

}

15. Объединения

Объединяются ключевым словом union. Способы описания такие же, как и в случае структур, только вместо слова struct используется слово union.

union {int a; long b;} pr;

Для переменной pr выделяется память, достаточная для хранения самого длинного элемента объединения, т. е. в нашем примере - 4 байта.

Если использовать pr.a, то выделенная память будет использоваться как int, в случае pr.b как long. Однако, участок памяти один и тот же. Поэтому одновременно существовать pr.a и pr.b не могут. Ответственность за некорректное использование памяти лежит на программисте. Объединения используются для экономии памяти:

union {int bc[100]; double kk[20];} cc;

На все отводится 200 байт.

int bc[100] 200 байт

______________________________

|----------------------------|

double kk[20] (160 байт)

Одновременно работать с массивом cc.bc и cc.kk нельзя.

Объединения нельзя инициализировать.

16 Дополнительные сведения о препроцессоре языка C

Препроцессор обрабатывает текст программы перед компиляцией.

1. Включение файлов (рассмотрено ранее):

#include <conio.h> - файл из специального каталога;

#include "d:\\user\\ff.h" - файл ищется по правилам MS DOS.

2. Текстовые подстановки (рассматривалось ранее):

#define N 21

#define ABC (a*b*c+\

d*sin(x))

\ - переход на следующую строку.

3. Создание макросов.

#define SQR(x) ((x)*(x))

В результирующую строку подставляется фактическая строка x. Например, если в тексте программы встречается SQR(y), то после макрораскрутки получим ((y)*(y)). Скобки нужны для того, чтобы не получилось недоразумений, например

#define SQR(x) x*x

SQR(y+2); превратится в

y+2*y+2;

Конечно, это не то, что хотелось.

4. Отмена ранее созданного имени:

#undef SQR.

5. Условная компиляция:

#if константное выражение

строки программы

#else

строки программы

#endif

Если константное выражение истинно, то в программу будут включены строки из первого блока, иначе из второго.

Пример:

#define DEBUG 1

#if DEBUG

printf("%d", x);

#endif

Можно проверить наличие или отсутствие какого-либо имени:

#ifdef имя (если имя определено, то истина)

#else

#endif

#ifndef имя (если имя не определено)

#else

#endif

Это свойство широко используется в библиотечных включаемых файлах, чтобы избежать противоречия. Например, в conio.h имеются следующие строки:

#ifndef COLORS

enum COLORS {BLACK, ...};

#endif

17. Условное выражение

Эта конструкция языка C в некоторых случаях позволяет заменить оператор if и сократить запись программы.

БНФ:

условное выр = выр0 "?" выр1 ":" выр2

Значение условного выражения равно выр1, если выр0 не равно 0 и выр2 впротивном случае.

Пример:

a = b>c ? b:c; тоже самое, что

if (b>c) a=b; else a = c;

С помощью условного выражения можно, например, определить макросы max и min:

#define max(x,y) ((x)>(y) ? (x):(y))

#define min(x,y) ((x)<(y) ? (x):(y))

При этом макросы max и min будут работать для любых типов арифметических данных.

Например:

a = max(b,c);

18. Динамические данные

18.1 Линейные списки

Использование указателей на структуры позволяет использовать весьма сложно организованные данные типа различного рода списков, очередей и деревьев. Рассмотрим так называемые линейные списки.

Линейный список - это упорядоченная структура данных, каждый элемент которой содержит ссылку (указатель), связывающую его со следующим элементом.

Для организации списков служат структуры, состоящие из двух смысловых частей: основной, содержащей полезную информацию, и дополнительной, содержащей ссылку на следующий элемент списка.

В виде списков удобно представлять большие объемы информации, размер которых заранее неизвестен.

Рассмотрим, например, как можно было бы организовать хранение информации о товарах для программы "магазин".

typedef struct _GOODS{

char name[21];

int number;

float price;

struct _GOODS *next;

} GOODS;

Очевидно, программа должна иметь переменную - указатель на первый элемент списка. Последний элемент списка отличается тем, что в поле next имеет константу 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.

Текст программы выглядит следующим образом:

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");

}

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

Понятие стека ("магазина"): первый пришел, последний ушел. 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 */

}

}

head 3

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

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

head 3

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

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

FIFO (FIRST IN FIRST OUT).

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

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

LIST *head = NULL, *tail = NULL;

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

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

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

typedef struct _NODE {

info_t info;

struct _NODE*left;

struct _NODE*right;

} NODE;

NODE *tree = NULL;

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

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

Прототипы функций описаны в файле <stdio.h>. Основные идеи:

1. В C отсутствуют встроенные средства ввода-вывода. Весь ввод-вывод осуществляется через функции, находящеся в библиотеке и легко замещаемые.

2. Каждый файл рассматривается как непрерывный поток байт (stream). Никакой внутренней структуры файла не поддерживается.

3. Не делается никаких различий между файлами на дисках и на других внешних устройствах.

19.1 Открытие потока

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

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

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

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

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

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

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

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

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

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

19.2 Закрытие потока

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

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

2. незакрытый файл может в случае сбоя пропасть.

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

int fclose (FILE *stream);

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

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

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

int fcloseall (void);

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

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

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

<stdio.h>

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);

}

19.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)

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

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

19.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.

Размещено на Allbest.ru


Подобные документы

  • Цели и задачи дисциплины "Технология программирования". Программные средства ПК. Состав системы программирования и элементы языка. Введение в систему программирования и операторы языка Си. Организация работы с файлами. Особенности программирования на С++.

    методичка [126,3 K], добавлен 07.12.2011

  • Понятие математического программирования. Класс как тип структуры, позволяющий включать в описание типа не только элементы данных, но и функции. Рассмотрение основных особенности языка программирования C++. Характеристика среды MS Visual Studio 2008.

    контрольная работа [318,0 K], добавлен 13.01.2013

  • Особенности способов описания языков программирования. Язык программирования как способ записи программ на ЭВМ в понятной для компьютера форме. Характеристика языка Паскаль, анализ стандартных его функций. Анализ примеров записи арифметических выражений.

    курсовая работа [292,0 K], добавлен 18.03.2013

  • История создания языка Java. Основные принципы объектно-ориентированного программирования. Структура, особенности синтаксиса и примеры прикладных возможностей использования языка Java, его преимущества. Перспективы работы программистом на языке Java.

    курсовая работа [795,9 K], добавлен 14.12.2012

  • Изучение способов организации консольного ввода/вывода данных в режиме черного экрана. Ознакомление со стандартными типами данных (целый, вещественный, символьный, логический) и методами описания переменных, использующихся на языке программирования С++.

    презентация [2,2 M], добавлен 17.04.2010

  • Изучение теоретических основ разработки программы и правил выбора языка программирования. Рассмотрение основных задач по созданию сайта автоклуба. Основы разработки базы данных, создания web-дизайна, текстового наполнения сайта и его публикации.

    курсовая работа [687,9 K], добавлен 07.04.2014

  • Изучение общей структуры языка программирования Delphi: главные и дополнительные составные части среды программирования. Синтаксис и семантика языка программирования Delphi: алфавит языка, элементарные конструкции, переменные, константы и операторы.

    курсовая работа [738,1 K], добавлен 17.05.2010

  • Рассмотрение и ознакомление с одним из наиболее используемых языков программирования - С++. Его применение в процессе работы со строковыми типами данных и символами. Исследование кодов написания программ в режиме разработки консольного приложения.

    курсовая работа [6,1 M], добавлен 20.01.2016

  • Ознакомление с ситуацией распространения на рынке языков программирования. Определение плюсов и минусов Pascal, C++, VBA. Сравнение и анализ синтаксиса программ на основе одной задачи. Выявление лучшего языка для освоения первоначальных навыков.

    курсовая работа [1022,0 K], добавлен 13.10.2014

  • Исследование базовых концепций программирования приложений под операционную систему Windows. Изучение истории создания универсального языка программирования Си. Разработка графического пользовательского интерфейса. Обзор правил игры и алгоритма работы.

    курсовая работа [58,2 K], добавлен 09.11.2012

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.