Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
практичні алгоритмізація дл студ.docx
Скачиваний:
0
Добавлен:
01.04.2025
Размер:
6.12 Mб
Скачать

Лабораторна робота №25. Тема: Структури, об′єднання, операції з бітами і перечисленнями

Мета: Навчитися працювати зі структурами в мові програмування С. Освоїти роботу з бітами.

Хід роботи

1. Напишіть програми, на лістингах що нижче, проаналізуйте її.

Програма на лістингу 10.2 демонструє використання операцій елементу структури і покажчика структури. За допомогою операції елементу структури елементам а привласнюються значення "Асові" і "Spades" відповідно. Покажчику aPtr привласнюється адреса структури а. Оператор printf друкує елементи структури а, використовуючи операцію елементу структури з ім'ям змінної а, операцію покажчика структури з покажчиком aPtr, і операцію елементу структури з покажчиком aPtr, до якого застосована операція непрямої адресації.

/* Застосування операцій елементу структури і покажчика структури */

#include <stdio.h>

struct card {

char *face;

char *suit;

};

main ()

{

struct card a;

struct card *aPtr;

a.face ="Ace";

a.suit ="Spades";

aPtr =&a;

printf("%s%s%s\n%s%s%s\n%s%s%s\n",

a.face, " of ", a.suit,

aPtr ->face, " of ", aPtr ->suit

(*aPtr).face, " of (*aPtr).suit)

return 0;

}

Ace of Spades

Ace of Spades

Ace of Spades

Лістингу 10.2. Використання операцій елементу структури і покажчика структури

2. Приклад: моделювання високоефективного тасування і роздачі карт. Напишіть програми, на лістингах що нижче, проаналізуйте її.

Програма на лістингу 10.3 заснована на методі моделювання тасування і роздачі карт, що обговорювалося в главі 7. Програма представляє колоду карт як масив структур. Вона використовує високоефективні алгоритми тасування і роздачі. Результат виконання програми показаний на лістингу 10.4.

/* Програма тасування і здачі, що використовує структури */

#include <stdio.h>

#include <stdlib.h>

#include <time.h>

struct card {

char *face;

char *suit;

} ;

typedef struct card Card;

void fillDeck(Card *, char *[], char *[]);

void shuffle(Card *);

void deal(Card *);

main ()

{

Card deck[52];

char *face[] = ("Ace", "Deuce", "Three", "Four", "Five"

"Six", "Seven", "Eight", "Nine", "Ten"

"Jack", "Queen", "King"};

char *suit[] = ("Hearts", "Diamonds", "Clubs", "Spades"};

srand(time(NULL));

fillDeck(deck, face, suit);

shuffle(deck);

deal (deck);

return 0;

}

void fillDeck(Card *wDeck, char *wFace[], char *wSuit[])

{

int i;

for (i = 0; i < 52; i++){

wDeck[i].face = wFace[i % 13];

wDeck[i].suit = wSuit[i / 13];

}

}

void shuffle(Card *wDeck){

int i, j;

Card temp;

for (i = 0; i < 52; i++){

j = rand() 0 % 52; temp = wDeck[i]; wDeck[i] = wDeck[j]; wDeck[j] = temp;

}

}

void deal(Card *wDeck)

{

int i;

for(i=0;i<52;I++)

printf("%5s of %-8s% c", wDeck[i].face, wDeck[i].suit

((i + 1) % 2 ? '\t' : '\n');

}

Лістингу 10.3. Високоефективне моделювання тасування і роздачі карт

Eight

of

Diamonds

Ace

of

Hearts

Eight

of

Clubs

Five

of

Spades

Seven

of

Hearts

Deuce

of

Diamonds

Ace

of

Clubs

Ten

of

Diamonds

Deuce

of

Spades

Six

of

Diamonds

Seven

of

Spades

Deuce

of

Clubs

Jack

of

Clubs

Ten

of

Spades

King

of

Hearts

Jack

of

Diamonds

Three

of

Hearts

Three

of

Diamonds

Three

of

Clubs

Nine

of

Clubs

Ten

of

Hearts

Deuce

of

Hearts

Ten

of

Clubs

Seven

of

Diamonds

Six

of

Clubs

Queen

of

Spades

Six

of

Hearts

Three

of

Spades

Nine

of

Diamonds

Ace

of

Diamonds

Jack

of

Spades

Five

of

Clubs

King

of

Diamonds

Seven

of

Clubs

Nine

of

Spades

Four

of

Hearts

Six

of

Spades

Eight

of

Spades

Queen

of

Diamonds

Five

of

Diamonds

Ace

of

Spades

Nine

of

Hearts

King

of

Clubs

Five

of

Hearts

King

of

Spades

Four

of

Diamonds

Queen

of

Hearts

Eight

of

Hearts

Four

of

Spades

Jack

of

Hearts

Four

of

Clubs

Queen

of

Clubs

Лістинг 10.4. Результат тасування і роздачі карт

Програма працює таким чином. Функція fillDeck ініціалізувала масив Card в порядку від туза до короля для кожної масті. Масив Card передається функції shuffle, в якій реалізований ефективний алгоритм тасування. Функція отримує як аргумент масив з 52 структур Card. Вона звертається до кожної з 52 карт (індекси масиву від 0 до 51), використовуючи структуру for. Для кожної карти випадковим чином вибирається число між 0 і 51. Наступним кроком поточна структура Card і випадково вибрана структура міняються в масиві місцями. Повністю 52 заміни виконуються

за один прохід усього масиву, і масив структур Card перетасований! Цей алгоритм вільний від вади, пов'язаної з нескінченним відстроченням, що виникає в алгоритмі тасування з глави 7. Оскільки структури Card вже переставлені місцями, алгоритм роздачі, реалізований у функції deal, вимагає усього лише одного проходу по масиву, щоб роздати тасовані карти.

3. Об'єднання. Приклад: моделювання високоефективного тасування і роздачі карт. Напишіть програми, на лістингах що нижче, проаналізуйте її.

Програма на лістингу 10.5 оголошує змінну value типу union number і відображує значення, що зберігаються в об'єднанні, як тип int і як float. Результат виконання програми залежить від реалізації. Виведення програми свідчить, що внутрішнє представлення значення float може значно відрізнятися від представлення int.

/* Приклад об'єднання */

#include <stdio.h>

union number {

int x;

float y;

};

main ()

{

union number value;

value.x= 100;

printf("%s\n%s\n%s%d\n%s%f\n\n"

"Put a value in the integer member",

"and printf both members.",

"int: ", value.x

"float: ", value.y);

value.y= 100.0;

printf ("%s\n%s\n%s%d\n%s%f\n"

"Put a value in the floating member",

"and printf both members.",

"int: ", value.x,

"float: ", value.y);

return 0;

}

Put a value in the integer member

and print both members/

int: 100 float: 0.000000

Put a value in the floating member

and print both members,

int: 17096 float: 100.000000

Лістинг 10.5. Висновок на друк значення елементу об'єднання у форматі кожного з типів даних

4. Порозрядні операції. Об'єднання. Напишіть програми, на лістингах що нижче, проаналізуйте її.

Усі дані представляються усередині комп'ютера як послідовності бітів. Кожен біт може набувати значень 0 або 1. У більшості систем послідовність з 8 біт утворює байт - стандартну одиницю пам'яті для змінної типу char, для зберігання інших типів даних використовується більше число байтів. Порозрядні операції використовуються для операцій над бітами цілочисельних операндів (char, short, int і long; як signed, так і unsigned). У порозрядних операціях зазвичай використовуються беззнакові цілі.

/* Побітний друк беззнакового цілого */

#include <stdio.h>

main ()

{

unsigned x;

void displayBits(unsigned);

printf("Enter an unsigned integer: ")

scanf("%u", &x);

displayBits (x);

return 0;

}

void displayBits(unsigned value)

{

unsigned c, displayMask = 1 << 15;

printf("%7u = ", value);

for (c = 1; c <= 16; C++){

putchar(value & displayMask ? '1' : '0');

value <<= 1;

if (c % 8 == 0)

putchar(' ');

}

putchar('\n');

}

Enter an unsigned integer: 65000

65000 = 11111101 11101000

Bit1

Bit2

Bit1 & Вit2

0

0

0

1

0

0

0

1

0

1

1

1

Лістинг 10.8. Результати об'єднання двох бітів за допомогою порозрядної операції І (&). Використання логічної операції І (&&) замість порозрядної операції (&) і навпаки.

5. Напишіть програми, на лістингах що нижче, проаналізуйте її.

Програма на лістингу 10.9 ілюструє виконання порозрядних операцій І, що включає АБО, виключає АБО і операції порозрядного доповнення. Програма викликає функцію displayBits для виводу на друк цілих величин типу unsigned. Результати програми показані на лістингу 10.10.

/* Застосування операцій порозрядного AND, включаючого OR, OR, що виключає, і порозрядного доповнення */

#include <stdio.h>

void displayBits(unsigned);

main()

{

unsigned number1, number2, mask, setBits;

number1 = 65535;

mask = 1;

printf("The result of combining the following\n");

displayBits(number1);

displayBits(mask);

printf("using the bitwise AND operator & is\n");

displayBits(number1 & mask);

number1 = 15;

setBits = 241;

printf("\nThe result of combining the following\n");

displayBits(number1);

displayBits(setBits);

printf("using the bitwise inclusive OR operator | is\n");

displayBits(number1 | setBits);

number1 = 139;

number2 = 199;

printf ("\nThe result displayBits(number1);

dlsplayBits(number2);

printf("using the bitwise exclusive OR operator ^ is\n");

displayBits(number1 ^ number2);

number1 = 21845;

printf("\nThe one's complement of\n");

displayBits(number1);

printf ("is\n");

displayBits(~number1);

return 0;

}

void displayBits(unsigned value)

{

unsigned c, displayMask = 1 << 15;

printf ("%7u = ", value);

for (c = 1; c <= 16; c ++){

putchar(value & displayMask ? '1' : '0');

value <<=1;

if (c % 8 ==0)

putchar (' ');

}

putchar ( '\n');

}

Лістингу 10.9. Використання операцій порозрядних І, що включає АБО, виключає АБО і доповнення

The result of combining the following

65535 = 11111111 11111111

1 = 00000000 00000001

using the bitwise AND operator & is

1 = 00000000 00000001

The result of combining the following

15 = 00000000 00001111

241 = 00000000 11110001

using the bitwise inclusive OR operator | is

255 = 00000000 11111111

The result of combining the following

139 = 00000000 10001011

199 = 11000111 using the bitwise exclusive OR operator ^ is

76 = 00000000 01001100

The one's complement of

21845 = 01010101 01010101

is

43690 = 10101010 10101010

Результат виконання програми (лістинг) 10.10., програма якого приведена на лістингу 10.9.

У програмі на лістингу 10.9 цілій змінній mask привласнюється значення 1 (00000000 00000001), а змінній number1 значення 65535 (1111111111111111). Змінні mask і number1 об'єднуються у вираженні number1 & mask за допомогою операції порозрядного І (&). В результаті отримуємо 00000000 00000001. Усі біти, за винятком біта молодшого розряду в змінній number1 масковані (приховані) після застосування операції І із змінною mask.

Порозрядна включаюча операція АБО використовується для того, щоб встановити в операнді задані біти рівними 1. У програмі на лістингу 10.9 змінній number1 привласнюється значення 15 (00000000 00001111), а змінній setBits - 241 (00000000 11110001). Коли number1 і setBits об'єднуються операцією порозрядного АБО у вираженні number1 setBits, в результаті виходить 255 (00000000 11111111). На лістингу 10.11 дана звідна таблиця значень об'єднання двох бітів за допомогою порозрядної операції того, що включає АБО.

Bit1

Bit2

Bit1 | Bit2

0

0

0

1

0

1

0

1

1

1

1

1

Лістинг 10.11. Результати об'єднання двох біт за допомогою операції того, що порозрядного включає АБО

Bit1

Bit2

Bit1 ^ Bit2

0

0

0

1

0

1

0

1

1

1

1

0

Лістинг 10.12. Результати об'єднання двох біт за допомогою операції того, що порозрядного виключає АБО (^)

В результаті виконання операції порозрядного доповнення (~) усім бітам операнда, що мали значення 1, привласнюється значення. 0, а усім бітам, що мали значення 0, відповідно до 1 - по-іншому цю операцію називають доповненням до одиниці. На лістингу 10.9 змінній number1 привласнюється значення 21845 (01010101 01010101). В результаті обчислення вираження - number1 отримуємо (10101010 10101010).

6. Напишіть програми, на лістингах що нижче, проаналізуйте її.

Програма на лістингу 10.13 є приклад використання операцій зрушення вліво (<<) і зрушення управо (>>). Функція displayBits використовується для виводу на друк цілих величин типу unsigned.

Операція зрушення вліво (<<) зміщує біти лівого операнда вліво на число біт, визначене в правому операнді. Біти, що звільняються справа, замінюються нулями; що "скидаються" вліво біти втрачаються. У програмі на лістингу 10.13 змінній number1 привласнюється значення 960 (0000001111000000). В результаті виконання що задається вираженням number1 << 8 операцій зрушення вліво на 8 біт змінна number1 отримує значення 49152 (11000000 00000000).

/* Применение операций сдвига */

#include <stdio.h>

void displayBits(unsigned);

main()

{

unsigned number1 = 960;

printf("\The result of left shifting\n");

displayBits(number1);

printf("8 bit positions using the ");

printf("left shift opertor << is\n");

displayBits(number1 << 8);

printf("\nThe result of right shifting\n");

displayBits(number1);

printf ("8 bit positions using the ");

printf("right shift operator >> is\n");

displayBits(number1>> 8);

return 0;

}

void displayBits(unsigned value)

{

unsigned c, displayMask = 1 << 15;

printf("%7u = ", value);

for (c = 1; c <= 16; c++) {

putchar(value & displayMask ? '1' : '0')

value <<=1;

if (c % 8 == 0)

putchar (' ') ;

}

putchar ('\n');

}

The result of left shifting

960 = 00000011 11000000

8 bit positions using the left shift operator << is

49152 = 11000000 00000000

The result of right shifting

960 = 00000011 11000000

8 bit positions using the right shift operator >> is

3 = 00000000 00000011

Лістингу 10.13. Використання операцій порозрядного зрушення

Операція зрушення управо (>>) зміщує біти лівого операнда управо на число біт, визначене в правому операнді. Виконання зрушення управо для цілого типу unsigned призводить до того, що біти, що звільняються ліворуч, замінюються нулями; що "скидаються" управо біти втрачаються. У програмі на лістингу 10.13 в результаті виконання що задається вираженням number1 >> 8 операцій зрушення управо на 8 біт змінна number1 отримує значення 3 (00000000 00000011).

7. Напишіть програми, на лістингах що нижче, проаналізуйте її.

Спроба звернутися до окремих біт бітового поля так, як якби вони були елементами масиву. Бітові поля - це зовсім не "масиви біт".

/* Приклад застосування бітових полів */

#include <stdio.h>

struct bitCard {

unsigned face: 4;

unsigned suit: 2;

unsigned color: 1;

} ;

typedef struct bitCard Card;

void fillDeck(Card *);

void deal(Card *);

main ()

{

Card deck[52] ;

fillDeck(deck);

deal(deck);

return 0;

}

void fillDeck(Card *wDeck)

{

int i;

for (i = 0; i <= 51; i++){

wDeck[i].face = i % 13;

wDeck[i].suit = i / 13;

wDeck[i].color = i / 26;

}

}

/* Функція deal друкує колоду в дві колонки */

Лабораторна робота №1. Тема: Побудова блок-схем алгоритмів засобами програми Word 2010. 3

Лабораторна робота № 2. Тема: Робота та знайомство в середовищі програмування. Запуск програм на виконання. Редагування тексту. 5

Лабораторна робота №3. Тема: Побудова алгоритмів за допомогою DiagramDesigner. 6

Лабораторна робота №4. Тема:Створення лінійних програм. Процедури вводу та виводу в машинному коді. 8

Лабораторна робота №5. Тема: Написання програм використовуючі математичні функції. Освоєння арифметичних операторів. 10

Лабораторна робота №6. Тема: Написання програм використовуючи логічні значення Boolean. 12

Лабораторна робота №7. Тема: Типи в програмах. 15

Лабораторна робота №8. Тема: Оператор вибору в циклах середовища пргограмування. 17

Лабораторна робота №9. Тема: Використання процедур та функцiй. Звукові можливості Паскаля. 21

Лабораторна робота №10. Тема: Використання перелiчуваного та обмеженого типу даних. 25

Лабораторна робота №11. Тема: Одновимiрнi масиви. 27

Лабораторна робота №12. Тема: Використання множин. 30

ІІ семестр. Мова програмування С 34

Лабораторна робота №13. Тема: Проста програма на С: друк рядка тексту 34

Лабораторна робота №14. Тема: Арифметика в С. Використання операцій рівності і відношення 35

Лабораторна робота №15 . Тема: Структурна розробка програм. Структура вибору if. Структура вибору if/else. Структура повторення while 38

Лабораторна робота №16. Тема: Структурна розробка програм. Структура вибору if. Структура вибору if/else. Структура повторення while 41

Лабораторна робота №17. Тема: Програмні модулі в С. Функції математичної бібліотеки 47

Лабораторна робота №18. Тема: Приклади роботи з масивами 57

Лабораторна робота №19. Тема: Сортування масивів 67

Лабораторна робота №20. Тема: Покажчики 80

Лабораторна робота №21. Тема: Покажчики 97

Лабораторна робота №22. Тема: Форматоване введення/вивід 116

Лабораторна робота №23. Тема: Використання прапорів в рядку управління форматом printf 122

Лабораторна робота №24. Тема: Використання прапорів в рядку управління форматом printf 125

Лабораторна робота №25. Тема: Структури, об′єднання, операції з бітами і перечисленнями 128

Лабораторна робота №26. Тема: Створення файлу послідовного доступу 138

printf("Card:%3d Suit:%2d Color:%2d

wDeck[k1].face, wDeck[k1].suit, wDeck[k1].color);

printf("Card:%3d Suit:%2d Color:%2d\n"

wDeck[k2].face, wDeck[k2].suit, wDeck[k2].color);

}

}

Лістинг 10.16. Використання бітових полів для зберігання колоди карт

Спроба узяти адресу бітового поля (операція & непридатна до бітових полів, оскільки вони не мають адреси).

Card:

0

Suit:

0

Color:

0

Card:

0

Suit:

2

Color:

1

Card:

1

Suit:

0

Color:

0

Card:

1

Suit:

2

Color:

1

Card:

2

Suit:

0

Color:

0

Card:

2

Suit:

2

Color:

1

Card:

3

Suit:

0

Color:

0

Card:

3

Suit:

2

Color:

1

Card:

4

Suit:

0

Color:

0

Card:

4

Suit:

2

Color:

1

Card:

5

Suit:

0

Color:

0

Card:

5

Suit:

2

Color:

1

Card:

6

Suit:

0

Color:

0

Card:

6

Suit:

2

Color:

1

Card:

7

Suit:

0

Color:

0

Card :

7

Suit:

2

Color:

1

Card:

8

Suit:

0

Color:

0

Card:

8

Suit:

2

Color:

1

Card:

9

Suit:

0

Color:

0

Card:

9

Suit:

2

Color:

1

Card:

10

Suit:

0

Color:

0

Card:

10

Suit:

2

Color:

1

Card:

11

Suit:

0

Color:

0

Card:

11

Suit:

2

Color:

1

Card:

12

Suit:

0

Color:

0

Card:

12

Suit:

2

Color:

1

Card:

0

Suit:

1

Color:

0

Card:

0

Suit:

3

Color:

1

Card:

1

Suit:

1

Color:

0

Card:

1

Suit:

3

Color:

1

Card:

2

Suit:

1

Color:

0

Card:

2

Suit:

3

Color:

1

Card:

3

Suit:

1

Color:

0

Card:

3

Suit:

3

Color:

1

Card:

4

Suit:

1

Color:

0

Card:

4

Suit:

3

Color:

1

Card:

5

Suit:

1

Color:

0

Card:

5

Suit:

3

Color:

1

Card:

6

Suit:

1

Color:

0

Card:

6

Suit:

3

Color:

1

Card:

7

Suit:

1

Color:

0

Card:

7

Suit:

3

Color:

1

Card :

8

Suit:

1

Color:

0

Card :

8

Suit:

3

Color:

1

Card:

9

Suit:

1

Color:

0

Card:

9

Suit:

3

Color:

1

Card:

10

Suit:

1

Color:

0

Card:

10

Suit:

3

Color:

1

Card:

11

Suit:

1

Color:

0

Card:

11

Suit:

3

Color:

1

Card:

12

Suit:

1

Color:

0

Card:

12

Suit:

3

Color:

1

Лістингу 10.17. Результат виконання програми, представленої на лістингу 10.16

8. Константи, що перераховують. Напишіть програми, на лістингах що нижче, проаналізуйте її.

/* Застосування типу, що перераховує, */

#include <stdio.h>

enum months {JAN = 1, FEB, MAR, APR, MAY, JUN,

JUL, AUG, SEP, OCT, NOV, DEC};

main ()

{

enum months month;

char *monthName[ ] = {"", "January", "February", "March"

"April", "May", "June", "July",

"August", "September", "October",

"November", "December"};

for (month = JAN; month <= DEC; month++)

printf("%2d%lls\n", month, monthName[month]);

return 0;

}

1 January

2 February

3 March

4 April

5 May

6 June

7 July

8 August

9 September

10 October

11 November

12 December