Структури

Структури – це набір зв’язаної інформації, можливо, різних типів, об’єднаний в один об’єкт. Структури можуть мати ім’я, що у цьому випадку буде ім’ям типу.

 

struct Call

{

short area, exchange, line;

enum {direct, oper_assist} type;

enum {day, evening, weekend} rate;

};

//...

Call collect; //оголосити змінну типу Call

 

У випадку, коли структури мають статичний клас пам’яті, можуть бути ініціалізовані значеннями, які обмежені фігурними дужками й розташовані в порядку оголошення полів структури. Якщо якісь значення наприкінці списку залишаться не ініціалізованими, то вони ініціалізуються значенням нуль (або еквівалентним).

 

Call work = {708, 555, 8887}; // work.type = direct, work.rate = day

 

Статичні вектори структур також можуть бути ініціалізовані. Якщо кількість значень дорівнює кількості полів структури, то внутрішні дужки можуть бути опущені.

 

Call record[] =

{

{516, 555, 8858},// для перших двох елементов type = direct,

{508, 555, 0516}, //rate = day

// Внутрішні дужки можуть бути опущені,

// якщо всі елементи ініціалізовані

212, 555, 5444, Call::direct, Call::weekend,

908, 555, 6012, Call::oper_assist, Call::day

};

 

Структури можуть містити бітові поля. Бітове поле – це роздроблений цілий тип. Бітові поля дозволяють заощаджувати простір, що відводиться під дані, а також здійснювати перетворення даних в інші формати.

Бітові поля без імені просто резервують зазначену кількість бітів. Бітове поле без імені з нульовим розміром указує, що наступне бітове поле починається на межі слова.

 

struct Features

{

unsigned touchTone:1;

unsigned callWait:1;

unsigned callFwd:1;

unsigned :2; //не використовується

unsigned speedDial:1;

unsigned dstnctRng:1;

};

 

Приклад:

 

// DateTest.cpp

#include <cstdio>

 

typedef struct dateStruct

{

char month;

char day;

unsigned year;

} DateStruct;

 

main()

{

DateStruct date;

printf("Date testn");

date.month = 5;

date.day = 16;

date.year = 1972;

printf("The date is: %02d/%02d/%04dn",

date.month, date.day, date.year);

return 0;

}

 

Приклад:

 

// Address.cpp

#include <iostream>

using namespace std;

 

struct address

{

char* name;

long number;

char* street;

char* town;

char state[2];

int zip;

};

 

void print_addr(address* p)

{

cout<<p->name<<'n'

<<p->number<<'n'

<<p->street<<'n'

<<p->town<<'n'

<<p->state[0]<<p->state[1]<<' '

<<p->zip<<'n';

}

 

void main()

{

address jd =

{

"Jim Dandy",

61, "South st",

"New Prowidence",

{'N','J'}, 7974

};

print_addr(&jd);

}

 

Об’єкти типу структури можна привласнювати, передавати як параметри функції та повертати з функції як результат.

 

address current;

address set_current (address next)

{

address prev = current;

current = next;

return prev;

}

 

Ім’я типу стає доступним відразу після того, як воно зустрілося, а не тільки після того, як повністю переглянуте все оголошення.

 

struct link

{

link* previous;

link* successor;

};

 

Нові об’єкти структурного типу не можуть бути оголошені, поки не переглянуте все оголошення.

 

struct no_good

{

no_good member; // помилка

};

 

Щоб дати можливість двом (або більше) структурним типам посилатися один на одного, можна просто описати ім’я як ім’я структурного типу.

 

struct list; // повинна бути описана пізніше

struct link

{

link* pre;

link* suc;

list* member_of;

};

 

struct list

{

link* head;

};

 

5. Еквівалентність типів

Два структурних типи є різними, навіть коли вони мають ті самі члени.

 

struct s1{ int a;};

struct s2 {int a;};

s1 x;

s2 y = x; // невідповідність типів

 

Структурні типи відмінні також від основних типів.

 

s1 x;

int i = x; // невідповідність типів

 

Оголошення із префіксом typedef вводить не нову змінну даного типу, а нове ім’я цього типу.

 

typedef char* Pchar;

Pchar p1, p2;

char* p3 = p1;


 

Лекція 7. Рядки й операції з ними

1. Бібліотека string.h

Ця бібліотека надає функції для обробки рядків, тобто послідовностей символів, які закінчуються нулем.

2. Визначення довжини рядків

int strlen (const char* s);

Повертає довжину рядка s, тобто кількість символів перед нуль-термінатором.

 

char* message = “Hello world!”;

int lenght = strlen(message); // lenght = 12

 

3. Копіювання й конкатенація рядків

char* strcpy (char* to, const char* from);

char* strncpy (char* to, const char* from, int limit);

Копіює рядок, на який указує from, у рядок, на котрий указує to. Область, на яку вказує to, повинна мати достатній розмір для розміщення рядка, що копіюється. strncpy() копіює не більш ніж limit символів. Скопійований рядок закінчується нульовим символом.

 

char* message = “You want it when?”;

char buf[20];

strspy(buf, message); // копіює message в buf.

 

 

char* strcat (char* to, const char* from);

char* strncat (char* to, const char* from, int limit);

Додає копію рядка, на який указує from, у кінець рядка, на котрий указує to. Область пам’яті, на яку вказує to, повинна мати достатній розмір для розміщення отриманого рядка. strncat() додає не більш ніж limit символів. Результуючий рядок закінчується нульовим символом.

 

char name[20] = “Humpty “;

strcat (name, “Dumpty”);

 

4. Порівняння рядків

int strcmp (const char* s1, const char* s2);

int strncmp (const char* s1, const char* s2, int limit);

Лексикографічно порівнює два рядки. Повертає -1, 0 або 1, якщо s1 відповідно менше, дорівнює чи більше, ніж s2. strncmp() порівнює не більш ніж limit символів.

 

for (int first=0, last=N; first< last)

{

int index = (first + last)/2;

int result = strcmp(word, dictionary[index]);

if(result < 0)

last = index - 1;

else

if(result >0)

first = index + 1;

else

break;

}

 

5. Пошук символів

char* strchr (const char* s, char c);

char* strrchr (const char* s, char c);

Відшукує перше входження в рядок s символу c. Повертає покажчик на символ c у рядку s. В іншому випадку повертає нульовий покажчик. strrchr(), (зворотна) відшукує останнє входження символу c у рядок s.

 

// crt_strchr.cpp

#include <string.h>

#include <stdio.h>

 

int ch = 'r';

 

char string[] = "The quick brown dog jumps over the lazy fox";

char fmt1[] = " 1 2 3 4 5";

char fmt2[] = "12345678901234567890123456789012345678901234567890";

 

int main( void )

{

char *pdest;

int result;

 

printf( "String to be searched:n %sn", string );

printf( " %sn %snn", fmt1, fmt2 );

printf( "Search char: %cn", ch );

 

/* Search forward. */

pdest = strchr( string, ch );

result = (int)(pdest - string + 1);

if ( pdest != NULL )

printf( "Result: first %c found at position %dn",

ch, result );

else

printf( "Result: %c not foundn" );

 

/* Search backward. */

pdest = strrchr( string, ch );

result = (int)(pdest - string + 1);

if ( pdest != NULL )

printf( "Result: last %c found at position %dn", ch, result );

else

printf( "Result:t%c not foundn", ch );

}

 

char* strpbrk (const char* s, const char* set);

Шукає перше входження кожного із символів, що знаходяться в рядку set, у рядок s. У випадку успішного пошуку повертає покажчик на символ у рядку s. В іншому випадку повертає нульовий покажчик.

 

Приклад:

 

// crt_strpbrk.cpp

#include <string.h>

#include <stdio.h>

 

void main()

{

char string[100] = "The 3 men and 2 boys ate 5 pigsn";

char *result;

printf( "1: %sn", string );

result = strpbrk( string, "0123456789" );

printf( "2: %sn", result++ );

result = strpbrk( result, "0123456789" );

printf( "3: %sn", result++ );

result = strpbrk( result, "0123456789" );

printf( "4: %sn", result );

}

int strspn (const char* s, const char* set);

int strcspn (const char* s, const char* set);

Починаючи з початку рядка s, повертає кількість символів, які знаходяться в set. Зупиняється з появою першого символу, що не знаходиться в set, strcspn() повертає кількість символів, які не входять у set. Зупиняється з появою першого символу, що знаходиться в set.

 

char* s = “2000 North Naperville Road”;

int n = strspn (s, “0123456789”); // n = 4

 

6. Пошук підрядків

char* strtok (const char* s, const char* set);

Ділить рядок на лексеми, використовуючи символи, що знаходяться в set, як обмежники. Після кожного виклику повертає покажчик на початок лексеми, що закінчується нульовим символом, або нульовий покажчик, якщо лексем більше немає.

При першому виклику strtok() їй передається адреса рядка. При другому й наступному викликах їй передається нульовий покажчик. Це вказує функції на необхідність продовження обробки даного рядка.

Коли strtok() знаходить лексему, виявляючи роздільник, вона записує замість нього нульовий символ для того, щоб відокремити дану лексему. Між викликами strtok() зберігає покажчик на наступний символ для того, щоб продовжити обробку рядка під час наступному виклику.

 

Приклад:

 

// crt_strtok.cpp

#include <string.h>

#include <stdio.h>

 

char string[] = "A stringtof ,,tokensnand some more tokens";

char seps[] = " ,tn";

char *token;

 

int main( void )

{

printf( "Tokens:n" );

/* Одержати першу лексему: */

token = strtok( string, seps );

while( token != NULL )

{

/* Поки є лексеми в рядку */

printf( " %sn", token );

/* Одержати наступну лексему: */

token = strtok( NULL, seps );

}

}

 


Частина друга. Об’єктно-орієнтоване програмування

 

Лекція 8. Вступ до об’єктно-орієнтованого програмування

 

1. Термінологія