50395 (Вказівки, масиви і символьні рядки в мові C)
Описание файла
Документ из архива "Вказівки, масиви і символьні рядки в мові C", который расположен в категории "". Всё это находится в предмете "информатика" из 1 семестр, которые можно найти в файловом архиве . Не смотря на прямую связь этого архива с , его также можно найти и в других разделах. Архив можно найти в разделе "лабораторные работы", в предмете "информатика, программирование" в общих файлах.
Онлайн просмотр документа "50395"
Текст из документа "50395"
Размещено на http://www.allbest.ru/
Лабораторна робота
Вказівки, масиви і символьні рядки в мові 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 ;
Операції над вказівниками.
присвоювання (=);
одержання значення об'єкта, на який посилається вказівник (*);
одержання адреси самого вказівника (&).
Приклад:
i nt 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].
Двовимірні масиви розташовані в пам’яті так само, як і одновимірні масиви, займаючи послідовні комірки пам’яті
ptr | ptr+1 | ptr+2 | ptr+3 | ptr+4 | ptr+5 |
mas[0][0] | mas[0][1] | mas[1][0] | mas[1][1] | mas[2][0] | 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
#include
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 a[i]=new int [m]; //виділення пам’яті для кожного рядка масиву розмірністю nxm … for(int i=0;i {for(int j=0;j printf(a[i][j]); } for(int i=0;i delete [] a[i]; //звільнення пам’яті від кожного рядка delete [] a; //звільнення пам’яті від масиву вказівників getch(); return 0; } 2.2 Використання вказівників при роботі з рядками Символьна константа складається з одного символа ASCII між апострофами (''). Приклади спеціальних символів: Новий рядок '\n' Горизонтальна табуляція '\t' Повернення каретки '\r' Апостроф '\'' Лапки '\"' Нульовий символ '\0' Зворотний слеш '\\' Символьні дані в С предствляють у вигляді стрингів. Стринги є одним з найбільш корисних та важливих типів даних мови С. Символьний рядок (стринг) — це масив символів, що закінчується у лапки ("). Він має тип 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 #include isdig(char c) {return ((isdigit(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) { double res=getdig(s); while((**s=='*') || (**s=='/')) if(**s=='*') res*=getdig(++*s); else res/=getdig(++*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); } Проаналізувати умову задачі. Розробити алгоритм та створити програму розв’язання задачі згідно з номером варіанту. Результати роботи оформити протоколом Размещено на Allbest.ru 14
Приклад
3.Порядок виконання роботи