Страницы

Ярлыки

ДШИ-200 (1) КСВУ-6 (1) ЛЧМ (1) МДР-23 (1) микроконтроллер (1) перенаправление (1) С (1) структуры (1) учебный курс (1) AC/DC (1) ADC (1) ADS1248 (1) Altium (1) Altuim (1) Amolifer (1) ARM (1) assembler (2) Asynchronous (1) at command (3) at#eaddr (1) at#epassw (1) at#esmtp (1) at#euser (1) at#gprs (1) at#selint=2 (1) at#sgact (1) at#tcpatcmdseq (1) ATX (1) AVR (2) bit (1) boost (1) boot (2) bootlloader (1) C (6) C# (7) C++ (1) CMSIS (1) command (1) CP2101 (1) CSD (1) Danfoss (6) DBGMCU (1) debug (1) debug.ini (1) delegate (1) Discovery (1) DMA (1) DRV8805 (1) DWT (1) e-mail (1) email (1) Exel (1) exFAT (1) FC-051 (1) gl868-dual (2) gl868-dual cmux (1) GPIO (2) GSM (1) I2C (1) IAR (1) ID (1) Invoke (1) Keil (3) LabVIEW (1) Linux (1) LMP7721 (1) LoRa (3) mdmread (1) memory (1) MODBUS (1) Operation Amplifer (1) pack (1) printf (2) printf() (1) RCC (1) retargetting (1) RFM95/96/87/98(W) (1) RS232 (4) RS485 (1) RSAPI.DLL (1) RSS (1) RTC (2) send (2) SerialPort (1) Silabs (1) spl (1) standard peripherals library (1) startup (1) stepper (2) STlink (1) STlink/V2 (2) STM32 (10) stm32 stm32f10x (1) STM32DBG.IN (1) STM32F (19) STM32F103 (4) struct (1) Structure (1) system (1) SystemInit (1) Task (1) telit (5) thread (4) TIM (1) Type Cast (1) UART (1) uni-trend (1) USART (6) USB (1) UT61B (1) viewer (1)

четверг, 18 декабря 2014 г.

Структуры в Си

Структура - это переменная, которая содержит в себе набор других переменных, которые могут быть разных типов.
Пример:
struct
{
  char sym;
  int num;
}myvar;
Тут определена переменная myvar, которая представляет собой структуру. Доступ к элементам структуры осуществляется через точку:
myvar.sym = 4;
myvar.num = 40;
Если имеется указатель на структуру, то доступ к элементам с помощью указателя происходит через стрелку. Для этого нужно создать тип нашей структуры с помощью typedef, и объявить указатель с типом нашей структуры:
typedef struct
{
  char sym;
  int num;
}tMyStruct;
tMyStruct myvar;
tMyStruct* p;
...
p = &myvar;
p->sym = 5;
p->num = 500;

С помощью структур можно применять битовые поля, которые упаковываются в число, при этом память экономится. Компилятор IAR для AVR определяет минимальный объем памяти, который выделяется под структуру, в 2 байта, даже если количество бит в структуре меньше или равно 8 (для 8 бит было бы достаточно одного байта). Далее, когда объем бит превышает 16, выделяется уже 4 байта, и т. д. - объем выделяемой для битовой структуры памяти почему-то всегда кратен 2 байтам. Примеры битовых структур:
typedef struct
{
  unsigned A : 1;
  unsigned B : 1;
} t2;

typedef struct
{
  unsigned A : 1;
  unsigned B : 1;
  unsigned C : 1;
  unsigned D : 1;
} t4;

typedef struct
{
  unsigned A : 1;
  unsigned B : 1;
  unsigned C : 1;
  unsigned D : 1;
  unsigned E : 1;
  unsigned F : 1;
  unsigned G : 1;
  unsigned H : 1;
} t8;

typedef struct
{
  unsigned A : 1;
  unsigned B : 1;
  unsigned C : 1;
  unsigned D : 1;
  unsigned E : 1;
  unsigned F : 1;
  unsigned G : 1;
  unsigned H : 1;
  unsigned Y : 1;
} t9;

typedef struct
{
  unsigned A : 1;
  unsigned B : 1;
  unsigned C : 1;
  unsigned D : 1;
  unsigned E : 1;
  unsigned F : 1;
  unsigned G : 1;
  unsigned H : 1;
  unsigned Y : 8;
} t16;

typedef struct
{
  unsigned A : 1;
  unsigned B : 1;
  unsigned C : 1;
  unsigned D : 1;
  unsigned E : 1;
  unsigned F : 1;
  unsigned G : 1;
  unsigned H : 1;
  unsigned Y : 9;
} t17;

t2 _A2;    //выделяется 2 байта, хотя достаточно одного
t4 _A4;    //выделяется 2 байта, хотя достаточно одного
t8 _A8;    //выделяется 2 байта, хотя достаточно одного
t9 _A9;    //выделяется 2 байта
t16 _A16; //выделяется 2 байта
t17 _A17; //выделяется 4 байта, хотя достаточно 3-х
Очень интересен тип данных union, который позволяет один выделенный блок памяти интерпретировать по-разному, что позволяет удобно манипулировать данными и одновременно экономить память. Например, 
union
{
  uint i;
  t9  bf;
}myunion;
Переменная myunion может выступать либо как целое myunion.i, либо как структура myunion.bf типа t9 (см. ранее определение типа t9), то есть набор битов myunion.bf.A, myunion.bf.B и т. д., что позволяет, например, менять переменную myunion.i, манипулируя битами myunion.bf. Младший D0 бит i будет всегда равен myunion.bf.A, D1 будет равен myunion.bf.B, и т. д.


a->b == (*a).b



Создание новых типов

Тип переменной определяет: её размер в памяти, тип данных, которые она может хранить и операции, которые можно производить с этой переменной.
Тип данных является категорией. В языке С++ программист может создать любой тип данных на основе базовых типов.  Новые типы данных необходимо создавать для решения конкретных практических задач. Например: реализация работы деканата.
Успех программы часто зависит от удачного выбора способа представления данных. С помощью структур возможно моделировать сложные объекты, возникающие  при  решении  задач.  Структуры представляют средство для доступа к записям, которые содержат поля одного или нескольких типов.
Для использования структуры необходимо:
1. установить шаблон для структуры
2. объявить переменную, соответствующую этому шаблону
3. осуществить доступ к компонентам структуры.

Шаблон структуры

Шаблон - это схема, описывающая содержание структуры. Установка структурного шаблона телефонный справочник:
struct sprav {
                    char fio[20];
                    long num;
                  };
Данный шаблон описывает структуру с именем  типа  структуры sprav, состоящую из двух компонентов: строки fio и целой переменной num типа long. Имя типа структуры sprav необязательно и  используется  для ссылки на эту структуру. Компоненты структуры - данные любого типа, включая и другие структуры. Имя внутри структуры может быть  таким  же,  как  имя объекта вне структуры. Если шаблон описан внутри функции - он доступен только  этой функции, если шаблон описан вне функции - он  доступен любой функции программы. Установка шаблона не вызывает никаких действий в программе.

Структурные переменные

     Объявление структурных переменных приводит  к  выделению памяти для компонент структуры, куда можно записать данные или откуда можно прочитать их. Для объявления структурных переменных имеются несколько  способов.
1. Установить структурный шаблон:
     struct sprav {
                    char fio[20];
                    long num;
                  };
Объявить простую переменную, массив структур, указатель на структуру:      struct sprav tel1, tel2[5], *tel3;
2. Установить структурный шаблон с помощью  макроопределения:
     #define SPRAV struct sprav
     SPRAV {
             char fio[20];
             long num;
           };
Объявить переменные:
     SPRAV sp1, sp2[6], *sp3;
3. Объявить переменные одновременно с установкой шаблона (если на данную структуру вы больше не ссылаетесь):
     struct {
              char fio[20];
              long num;
            } tel1, tel2[3], *tel3;
4. Ввести новый тип данных (TEL)-структура определенного вида:
     typedef struct {
                      char fio[20];
                      long num;
                    } TEL;
Объявить переменные нового типа:
     TEL tel1, tel2[6], *tel3;
Если программа достаточно объемна, представляется более удобным четвертый способ.

Инициализация структуры               

Инициализировать можно только внешние или статические структуры.
     static struct {
                     char fio[20];
                     long num;
                   } tel[2]={
                              "Иванов Ф.А.", 456756,
                              "Петров В.П.", 632345
                            };

Доступ к компонентам структуры

Доступ к компонентам структуры продемонстрируем с помощью примеров.
Пример 1.
/* Обращение к элементам структуры через имя переменной */
#include <stdio.h>
#include <conio.h>
 void main(void)
{
   struct{
             char fio[20];  /* фамилия */
             long num;      /* телефон */
         } tel1, tel2;
   clrscr();
   puts("введите фио абонента-");
   gets(tel1.fio);
   puts("введите его номер-");
   scanf("%ld",&tel1.num);
   tel2=tel1;  /* нельзя так же сравнивать структуры */
   puts("Введено:");
   printf("Фамилия :%s   номер: %ld\n",tel2.fio,tel2.num);
}

Пример 2.
/* Динамическое выделение памяти для структуры */
/* Обращение к элементам структуры через указатель */
#include <stdio.h>
#include <conio.h>
#include <alloc.h>
  struct sprav {
                 char fio[20];
                 long num;
               };
 void main(void)
{
  struct sprav *tel1, *tel2;
  clrscr();
/* Выделение памяти для структуры */
   tel1=(struct sprav *)malloc(sizeof(struct sprav));
   tel2=(struct sprav *)malloc(sizeof(struct sprav));
   puts("введите фио абонента-");
   gets(tel1->fio);
   puts("введите его номер-");
   scanf("%ld",&tel1->num);
   *tel2= *tel1;
   puts("Введено:");
   printf("Фамилия :%s   номер: %ld\n",(*tel2).fio,(*tel2).num);
}

  Массив структур

Пример 3.
/* Массив структур. Обращение к элементам структуры через */
/* имя элемента массива */
#include <stdio.h>
#include <conio.h>
#include <string.h>
#define SPRAV struct sprav
void main(void)
{
 SPRAV{
        char fio[20];
        long num;
      };
 SPRAV tel[5];    /* массив структур - 5 элементов */
 char fio_tek[20];
 int i;
 clrscr();
/* ввод данных в массив структур */
   for(i=0; i<5; i++)  
   {
        puts("введите фио абонента-");
        gets(tel[i].fio);
        puts("введите его номер-");
        scanf("%ld",&tel[i].num);
        getchar();
   }
   puts("Выбор телефона по фамилии");
   gets(fio_tek);
/* поиск структуры по фамилии абонента */
   for(i=0; i<5; i++)
        if(!strcmp(fio_tek,tel[i].fio)) break;
   if(i!=5)    /* цикл закончен по break */
        printf("номер абонента %s равен %ld\n",fio_tek, \
                                  tel[i].num);
   else        /* цикл выполнился полностью */
        puts("Абонент не найден");
 }

Пример 4.
/* Массив структур. Память выделяется динамически. */
/* Обращение к элементам структуры через указатель */
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <alloc.h>
typedef struct{
                char fio[20];
                long num;
              } TEL;
 void main(void)
{
 TEL *tel;
 char fio_tek[20];
 int i;
 clrscr();
/* Выделение памяти для массива - 3 элемента */
 tel=(TEL *)malloc(sizeof(TEL)*3);
   for(i=0; i<3; i++)
   {
        puts("введите фио абонента-");
        gets((tel+i)->fio);
        puts("введите его номер-");
        scanf("%ld",&(tel+i)->num);
        getchar();
   }
   puts("Выбор телефона по фамилии");
   gets(fio_tek);
   for(i=0; i<5; i++,tel++)
        if(!strcmp(fio_tek,tel->fio)) break;
   if(i!=5)
        printf("номер абонента %s равен %ld\n",fio_tek, \
                              tel->num);
   else
        puts("Абонент не найден");
 }

Передача структуры в функцию

Непосредственный доступ к компонентам структуры - плохой стиль программирования. Все операции, которые разрешены применительно к структуре, должны быть при этом реализованы в виде отдельных функций. Не все компиляторы языка Си позволяют передавать структуры  в функцию по значению, поэтому в примерах передача структуры идет через указатель.
Пример 5.
/* Передача структуры в функцию через указатель на структуру */
/* Определение комплексного числа через структуру и действия */
/* над комплексными числами ( ввод, вывод, вычисление суммы) */
#include <stdio.h>
typedef struct { float a;   /* действительная часть */
                 float b;   /* мнимая часть */
               } COMPLEX;
void vvod(COMPLEX *,float,float);     
void sum(COMPLEX *,COMPLEX *,COMPLEX *);
void out(COMPLEX *);
void main(void)
{
   COMPLEX x,y,z;
   vvod(&x,2.5,6.7);
   vvod(&y,6.89,8.45);
   puts("Введены числа:");
   out(&x);
   out(&y);
   sum(&x,&y,&z);
   puts("Сумма комплексных чисел равна:");
   out(&z);
}
/* Вывод комплексного числа */
void out( COMPLEX *p)
{
   printf("(%.2f,%.2f)\n", (*p).a,(*p).b);
   return;
}
/* Вычисление суммы двух комплексных чисел */
void sum(COMPLEX *p1,COMPLEX *p2,COMPLEX *p3)
{
   (*p3).a=(*p1).a+(*p2).a;
   (*p3).b=(*p1).b+(*p2).b;
   return;
}
/* Ввод значений для элементов структуры */
void vvod(COMPLEX *p,float a, float b)
{
   p->a=a;
   p->b=b;
   return;
}

Вложенные структуры 

     Структура, являющаяся компонентом другой структуры, называется вложенной.
Пример 6.
/* Даны четыре точки - центры четырех окружностей.    Заполнить структуру окружность, если все окружности    проходят через начало координат.    */
#include<conio.h>
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
struct POINT {
                float x;
                float y;
              };
struct CIRCLE {
            struct POINT point;  /* вложенная структура */
            double r;
          } circle[2], *p;
void main (void)
{
  int i,j; 
  float a,b,c,d;
  clrscr();
  gotoxy(17,1);
  cputs("ВВЕДИТЕ КООРДИНАТЫ ТОЧЕК :\r\n");
  for(i=0;i<2;i++) 
  { 
      cprintf ("\n\n ВВЕДИТЕ X: ");
      cprintf ("X[%d]= ",i+1);
      cscanf("%f",&circle[i].point.x);
      cprintf ("\n ВВЕДИТЕ Y: ");
      cprintf ("Y[%d]= ",i+1);
      cscanf ("%f",&circle[i].point.y);
  }
  p=circle;
  gotoxy(17,12);
  cputs("РЕЗУЛЬТАТ:\r\n\n");
  for(i=0;i<2;i++)
  {
     a=p->point.x;
     b=p->point.y;
     c=sqrt(a*a+b*b);
     p->r=c;
     cprintf("\nРАДИУС : %lf ЦЕНТР (%f,%f)\r\n",p->r,a,b);
     p++;
  }

Комментариев нет:

Отправить комментарий

ваше мнение...