Лекции по обектно-ориентирано програмиране


Вложени структури. Рекурсивно използване на структури



страница2/16
Дата25.07.2016
Размер0.95 Mb.
#6568
ТипЛекции
1   2   3   4   5   6   7   8   9   ...   16

2. Вложени структури. Рекурсивно използване на структури.

Тип на структура може да включва като полета други структури; те от своя страна също могат да притежават структурни полета и т.н.

например:

struct person

{ char name[30];

int born, died;

};

struct book



{ char name[40];

struct person author;

int year;

float price;

};
ако вложената структура е дефинирана предварително (както по-горе), тя може да се използва за дефиниране на отделни структурни променливи;
struct book b1, b2, *pb;

struct person per1, per2, *ptrper;


има възможност самата дефиниция да е вложена:

struct book

{ char name[40];

struct person

{ char name[30];

int born, died;

} author;

int year;

float price;

}
в този пример имаме вложена дефиниция, като областта на видимост на вложени я тип структура е дефиницията на включващата го структура и той не може да се използва за дефиниране на самостоятелни структурни променливи; в такъв случай става безсмислено указването на име на вложения тип структура;


достигане на полетата при вложени структури:

b1.author.name, b1.author.born – прилагане на операцията ‘.’ два пъти (тя е ляво-асоциативна);

pb = &b1;

int p;


p = pb->author.born; - комбиниране на операция ‘->’ с операция ‘.’;
реално операцията ‘->’ тук не е нужна; има случаи, когато е нужно използването на ‘->’ - когато е известен адресът, но не и името на променливата;

поле на структура може да бъде указател;

пример:

struct point



{ int k;

int *p;


int *q;

} ;


struct point var; //дефиниране на структурна променлива от тип

point;


обръщането към полетата на променливата var, които са указатели се осъществява по общоприетия начин: var.p, var.q; полетата, които са указатели могат да участват във всички допустими адресни операции; например:

*var.p – това е стойността, записана в адреса, сочен от указателя p; не поставяме скоби, защото операция ‘.’ е с по-голям приоритет;


типът на указателите, описани в тялото на структурата може да е всеки допустим тип, включително и структура; C и C++ не допускат поле от една структура да бъде структура от същия тип;

няма проблеми поле, което е указател да сочи към структура от същия тип; например:

struct linkedlist

{ int field;

struct linkedlist *next;

} ;


в такъв случай говорим за рекурсивно използване на структура; чрез него могат да се създават и обработват данни, организирани в списъци, или имащи дървовидна структура; обикновено, при тях се използва динамично заделяне на памет;

3. Функции и структури.

Указател към структура може да се предаде като параметър на функция; по този начин се осигурява достъп в тялото на функцията до полетата на структурна променлива, дефинирана извън функцията; обръщението към самите полета се осъществява с указателната операция ‘->’;

върната величина от една функция може да е указател към структура;

примерна програма:

#include

struct type

{ int a[5];

int k;


};

void main ()

{ struct type ksi = { 1, 6, 3, 7, 2, 1}, eps = { 2, 8, 9, 0, -5, 2},

*p = &ksi, *q = &eps;

struct type *maxi (struct type *, struct type *);

// функцията maxi има параметри два указателя към структурата

// type и връща указател към тази структура;

printf ( “ Стойността на k е: %d\n”, maxi(p, q)->k);

}

struct type *maxi (struct type *u, struct type *v)



{ int i, s1 = 0, s2 = 0;

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

{ s1 += u->a[i];

s2 += v->a[i];

}

if (s1>s2) return u;



else return v;

}
в тази реализация, ако променим формалния параметър, това ще промени и съответния фактически параметър;


изложеният начин за предаване на структури като параметри (чрез указатели) е универсален – той се поддържа в K&R C, в ANSI C и в C++;
в ANSI C и в C++ може директно да се предава структура като параметър на функция; формалният параметър се описва в заглавието като структура; обръщението към полетата на структурата в тялото се осъществява с операцията ‘.’;
в ANSI C и C++ структура може да бъде върната като резултат от изпълнението на функция; в този случай типът на връщания резултат се описва като структура;

извикването на функция с параметър структура е свързано с допълнителен разход на време и памет, защото се записва копие на цялата структура в програмния стек; при това промяната на копието не влияе на структурата, която е фактически параметър; по същата причина, когато връщаната стойност на една функция е структура се губи време и памет за записване в програмния стек на копие на тази структура;

ако масив е поле на структура, то предавайки структурата по стойност ние подаваме и масива по стойност – това е начинът за предаване на масив по стойност;

примерната програма (с предаване по стойност):

#include

struct type

{ int a[5];

int k;


};

void main ()

{ struct type ksi = { 1, 6, 3, 7, 2, 1}, eps = { 2, 8, 9, 0, -5, 2} ;

struct type maxi (struct type, struct type);

printf ( “ Стойността на k е: %d\n”, maxi(ksi, eps).k);

}

struct type maxi (struct type u, struct type v)



{ int i, s1 = 0, s2 = 0;

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

{ s1 += u.a[i];

s2 += v.a[i];

}

if (s1>s2) return u;



else return v;

}
в тази реализация, ако променим формалния параметър, това не засяга съответния фактически параметър;


само в C++ има още един начин за предаване на структура като параметър и връщане на структура като резултат от функция; в C++ може да се предава структура по име като параметър на функция, като формалният параметър се опише като псевдоним; обръщението към полетата на структурата в тялото на функцията се осъществява с операцията ‘.’; също така само в C++ име на структура може да бъде върнато като резултат от функция; в този случай типът на връщания резултат се описва като псевдоним;
#include

struct type

{ int a[5];

int k;


};

void main ()

{ struct type ksi = { 1, 6, 3, 7, 2, 1}, eps = { 2, 8, 9, 0, -5, 2} ;

struct type &maxi (struct type &, struct type &);

printf ( “ Стойността на k е: %d\n”, maxi(ksi, eps).k);

}

struct type &maxi (struct type &u, struct type &v)



{ int i, s1 = 0, s2 = 0;

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

{ s1 += u.a[i];

s2 += v.a[i];

}

if (s1>s2) return u;



else return v;

}
съпоставяне на трите подхода:



  • с указатели - поддържа се от K&R C, ANSI C, C++; предимства – оптимален по време и памет; недостатъци – работи с указатели;

  • с предаване по стойност (директно) – поддържа се от ANSI C и C++; предимства – по-естествен запис, по-просто за програмиране; недостатъци – разход на време и памет;

  • с псевдоними – поддържа се от C++; обединява предимствата на предните два подхода;






Сподели с приятели:
1   2   3   4   5   6   7   8   9   ...   16




©obuch.info 2024
отнасят до администрацията

    Начална страница