Главная Рефераты по авиации и космонавтике Рефераты по административному праву Рефераты по безопасности жизнедеятельности Рефераты по арбитражному процессу Рефераты по архитектуре Рефераты по астрономии Рефераты по банковскому делу Рефераты по сексологии Рефераты по информатике программированию Рефераты по биологии Рефераты по экономике Рефераты по москвоведению Рефераты по экологии Краткое содержание произведений Рефераты по физкультуре и спорту Топики по английскому языку Рефераты по математике Рефераты по музыке Остальные рефераты Рефераты по биржевому делу Рефераты по ботанике и сельскому хозяйству Рефераты по бухгалтерскому учету и аудиту Рефераты по валютным отношениям Рефераты по ветеринарии Рефераты для военной кафедры Рефераты по географии Рефераты по геодезии Рефераты по геологии Рефераты по геополитике Рефераты по государству и праву Рефераты по гражданскому праву и процессу Рефераты по кредитованию Рефераты по естествознанию Рефераты по истории техники Рефераты по журналистике Рефераты по зоологии Рефераты по инвестициям Рефераты по информатике Исторические личности Рефераты по кибернетике Рефераты по коммуникации и связи Рефераты по косметологии Рефераты по криминалистике Рефераты по криминологии Рефераты по науке и технике Рефераты по кулинарии Рефераты по культурологии |
Лабораторная работа: Вказівки, масиви і символьні рядки в мові CЛабораторная работа: Вказівки, масиви і символьні рядки в мові CЛабораторна роботаВказівки, масиви і символьні рядки в мові Cпрограма вказівка масив символ рядок1. Мета роботиМетою лабораторної роботи є отримання практичних навиків в роботі з вказівниками і з адресною арифметикою в мові С. 2. Теоретичні відомостіВ С++ існує надзвичайно потужний інструмент для роботи зі складними агрегатами даних, який надає загальний підхід до різних на перший погляд програмних об’єктів таких як масив та рядок. Цей і нструмент базується на широкому використанні вказівника. Вказівник - це символічне представлення адреси. Він використовується для непрямої адресації змінних і об'єктів. В мові С++ є операція визначення адреси — &, за допомогою якої визначається адреса комірки пам’яті, що містить задану змінну. Наприклад, якщо vr — ім’я змінної, то &vr — адреса цієї змінної. В С++ також існують і змінні типу вказівник. Значенням змінної типу вказівник є адреса змінної або об'єкта. Нехай змінна типу вказівник має ім'я ptr, тоді в якості значення їй можна присвоїти адресу за допомогою наступного оператора: ptr=&vr; В мові С++ при роботі з вказівниками велике значення має операція непрямої адресації — *. Операція * дозволяє звертатися до змінної не напряму, а через вказівник, який містить адресу цієї змінної. Ця операція є одномісною і має асоціативність зліва направо. Цю операцію не слід плутати з бінарною операцією множення. Нехай ptr — вказівник, тоді *ptr — це значення змінної, на яку вказує ptr. Опис змінних типу вказівник здійснюється за допомогою операторів наступної форми: <тип> *<ім'я вказівника на змінну заданого типу>; Кожна змінна в програмі це об'єкт, що має ім'я і значення по імені можна звернутися до змінного й одержати її значення. Оператор присвоювання ( = ) виконує зворотну дію: імені змінної ставиться у відповідність значення. a=10;
Вираз &a дозволяє одержати адресу ділянки пам'яті, виділеного змінній а. Операція & застосовна тільки до об'єктів, що мають ім'я і розміщених у пам'яті. Маючи можливість визначити адреси змінної за допомогою &, треба мати можливість працювати з цією адресою: зберігати його, передавати, перетворювати. Для цього вводиться поняття вказівника. Вказівник - це змінна, значенням якої служить адреса об'єкта конкретного типу. Нульова адреса позначається константою NULL, що визначена в заголовному файлі stdio.h. Щоб визначити вказівник треба повідомити на об'єкт якого типу посилається цей вказівник. char *z; int *k,*i; float *f; * - це операція разіменування. Операндом цієї операції завжди є вказівник. Результат операції - це той об'єкт, що адресує вказівник_операнд. *z=’$ ‘;
*k=*i=0; Приклад: int e, c, b, *m; . . . . . . . . . m = &e ; *m = c + b ; Операції над вказівниками. присвоювання (=); одержання значення об'єкта, на який посилається вказівник (*); одержання адреси самого вказівника (&). Приклад: int date = 10; int *i, *k;; i = &date; k = i; z = NULL; Подібно будь-яким змінної змінна типу вказівник має ім'я, арес у пам'яті і значення.
За допомогою унарних операцій ++ і –і числові значення змінних типу вказівник міняються по різному, у залежності від типу даних, з яким зв'язані ці змінні. Приклад: char *z; int *k,*i; float *f; . . . . . . . z++; // значення змінюється на 1 і++; // значення змінюється на 2 f++; // значення змінюється на 4 Тобто при зміні вказівника на 1, вказівник переходить до початку наступного (попереднього) поля тієї довжини, що визначається типом об'єкта, який адресується вказівником. 2.1 Використання вказівників при роботі з масивами Ім'я масиву без індексу є вказівником-константою, тобто адресою першого елемента масиву (a[0]). a *a = = a[0] ; *(a+1) = = a[1]; . . . . . . . . . *(a+і) = =a[і]; Відповідно до синтаксису в С існують тільки одномірні масиви, але їх елементами , у свою чергу, теж можуть бути масиви. int a[5][5]; Для двовимірного масиву: a[m][n] = = *(a[m]+n) = = *(*(a+m)+n); Приклад1. Опис вказівників. int *ptri; //вказівник на змінну цілого типу char *ptrc; //вказівник на змінну символьного типу float *ptrf; //вказівник на змінну з плаваючою точкою Такий спосіб оголошення вказівників виник внаслідок того, що змінні різних типів займають різну кількість комірок пам'яті. При цьому для деяких операцій з вказівниками необхідно знати об'єм відведеної пам'яті. Операція * в деякому розумінні є оберненою до операції &. Вказівники використовуються для роботи з масивами. розглянемо оголошення двовимірного масиву: int mas[4][2]; int *ptr; Тоді вираз ptr=mas вказує на першу колонку першого рядка матриці. Записи mas і &mаs[0][0] рівносильні. Вираз ptr+1 вказує на mas[0][1], далі йдуть елементи: mas[1][0], mas[1][1], mas[2][0] і т. д.; ptr+5 вказує на mas[2][1]. Двовимірні масиви розташовані в пам’яті так само, як і одновимірні масиви, займаючи послідовні комірки пам’яті
Розміщення двовимірного масиву в пам’яті Динамічним називається масив, розмірність якого стає відомою в процесі виконання програми. В С++ для роботи з динамічними об’єктами використовують спеціальні операції new і delete. За допомогою операції new виділяється пам’ять під динамічний об’єкт (який створюється в процесі виконання програми), а за допомогою операції delete створений об’єкт видаляється з пам’яті. Приклад. Виділення пам’яті під динамічний масив. Нехай розмірність динамічного масиву вводиться з клавіатури. Спочатку необхідно виділити пам’ять під цей масив, а потім створений динамічний масив треба видалити. … int n; scanf(n; // n — розмірність масиву int *mas=new int[n]; // виділення пам’яті під масив delete [] mas; // звільнення пам’яті … В цьому прикладі mas є вказівником на масив з n елементів. Оператор int *mas=new int[n] виконує дві дії: оголошується змінна типу вказівник, далі вказівнику надається адреса виділеної області пам’яті у відповідності з заданим типом об’єкта. Для цього ж прикладу можна задати наступну еквівалентну послідовність операторів: … int n, *mas; scanf(n;// n - розмірність масиву mas=new int[n];// виділення пам’яті під масив delete [] mas;// звільнення пам’яті … Якщо за допомогою операції new неможливо виділити потрібний об’єм пам’яті, то результатом операції new є 0. Іноді при програмуванні виникає необхідність створення багатовимірних динамічних об’єктів. Програмісти-початківці за аналогією з поданим способом створення одновимірних динамічних масивів для двовимірного динамічного масиву розмірності n*k запишуть наступне mas=new int[n][k]; // Невірно! Помилка! Такий спосіб виділення пам’яті не дасть вірного результату. Наведемо приклад створення двовимірного масиву. #include<iostream.h> #include<conio.h> int main() { int n;const m=5; printf("input the number"; scanf(&n); int** a; //a - вказівник на масив вказівників на рядки a=new int* [n]; //виділення пам’яті для масиву вказівників на n рядків for(int i=0;i<n;i++) a[i]=new int [m]; //виділення пам’яті для кожного рядка масиву розмірністю nxm … for(int i=0;i<n;i++) {for(int j=0;j<m;j++) printf(a[i][j]); } for(int i=0;i<n;i++) delete [] a[i]; //звільнення пам’яті від кожного рядка delete [] a; //звільнення пам’яті від масиву вказівників getch(); return 0; } 2.2 Використання вказівників при роботі з рядками Символьна константа складається з одного символа ASCII між апострофами (''). Приклади спеціальних символів:
Символьні дані в С предствляють у вигляді стрингів. Стринги є одним з найбільш корисних та важливих типів даних мови С. Символьний рядок (стринг) — це масив символів, що закінчується у лапки ("). Він має тип char. Нульовий символ (\0) автоматично додається останнім байтом символьного рядка та виконує роль ознаки його кінця. Кількість елементів у масиві дорівнює кількості символів у стрингу плюс один, оскільки нульовий символ також є елементом масива. Кожна стрингова константа, навіть у випадку, коли вона ідентична іншій стринговій константі, зберігається у окремому місці пам'яті. Якщо необхідно ввести у рядок символ лапок ("), то перед ним треба поставити символ зворотного слешу (\). У стринг можуть бути введені будь-які спеціальні символьні константи, перед якими стоїть символ \. Прототипи всіх функцій, що працюють з рядками символів, містяться у файлі string.h. Всі функції працюють з рядками, що закінчуються нульовим символом. Ось деякі з них: int strcat( char *, char *) — з'єднати два стринги; int strcpy(char *s1, char *s2) — копіювати рядок s2 у рядок s1; int strlen(char *s) — визначити довжину рядку (кількість символів без нульового символа). Для роботи з масивом символів, що не має у кінці нульового байта, можна користуватися функціями перетворення буферів. Протипи цих функцій знаходяться у файлі mem.h. Ці функції дозволяють присвоювати кожному байту в межах вказаного буфера задане значення, а також використовуються для порівняння вмісту двох буферів. Наприклад: memcpy() — копіювання символів з одного буфера у другий, поки не буде скопійований заданий символ або не буде скопійовано визначену кількість символів memcmp() — порівнює вказану кількість символів з двох буферів У файлі ctype.h описано прототипи функцій, що призначені для перевірки літер. Ці функції повертають ненульове значення (істина), коли її аргумент задовольняє заданій умові або належить вказаному класу літер, та нуль в іншому випадку. Наприклад: int islower(int с) — символ с є малою літерою; int isupper(int c) — символ с є великою літерою; int isalnum(int c) — символ с є буквою або цифрою; int isalpha(int c) — символ с є буквою; int tolower(int c) — перетворення літери у нижній регістр; int strtol(int c) — перетворення стрингу у довге ціле число; ПрикладОбчислити вираз з дужками, десятковими цифрами та знаками +, -, *, /. #include <ctype.h> #include <math.h> isdig(char c) double val(char **); double getdig(char ** s) { double res; if(**s=='(') res=val(++*s); else {res=atof(*s); while(isdig(*++*s));}; return res; } double multi(char** s) while((**s=='*') double val(char** s) { double res=multi(s); while((**s!=')') && (**s!='\0')) if(**s=='+') res+=multi(++*s); else res-=*(++*s); if(**s==')') ++*s; return res; } double getsvalue(char* s) {char** l; *l=s; return val(l);} main() { char* s="2-4/2+25/(2+3)/5+(-1)*(2*4/8-2)*(-1)+5"; cout << getsvalue(s); } 3.Порядок виконання роботиПроаналізувати умову задачі. Розробити алгоритм та створити програму розв’язання задачі згідно з номером варіанту. Результати роботи оформити протоколом |
||||||||||||||||||||||||||||||||||||||||||||
|