ТОП 10:

Дополнительные сведения о препроцессоре языка 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

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

Эта конструкция языка 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);

Приоритеты и направления операций.

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

| | |

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

| () вызов функции | |

| [] выделение элемента массива | |

| . выделение элементов структуры или объеди- | -> |

| нения | |

| -> выделения элементов структуры или объеди- | |

| нения | |

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

| ! логическое отрицание | |

| ~ побитовое отрицание | |

| - изменение знака | |

| ++ увеличение на единицу | |

| -- уменьшение на единицу | <- |

| & определение адреса | |

| * обращение по адресу | |

| (тип) преобразование типа | |

| sizeof определение размера в байтах | |

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

| * умножение | |

| / деление | -> |

| % остаток от деления | |

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

| + сложение | |

| - вычитание | -> |

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

| << сдвиг влево | |

| >> сдвиг вправо | -> |

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

| < меньше | |

| <= меньше или равно | |

| > больше | |

| >= больше или равно | |

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

| == равно | |

| != не равно | -> |

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

| & побитовое и | -> |

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

| ^ побитовое исключающее или | -> |

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

| | побитовое или | -> |

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

| && логическое и | -> |

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

| || логическое или | -> |

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

| ? : условная операция | -> |

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

| = присваивание | |

| *= /= %= += -= | <- |

| <<= >>= &= ^= |= | |

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

| , операция запятая | -> |

|__________________________________________________|_____|

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

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

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

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

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

 

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

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

}







Последнее изменение этой страницы: 2016-04-08; Нарушение авторского права страницы

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.237.94.109 (0.028 с.)