Лабораторная работа: Вказівки, масиви і символьні рядки в мові C
Динамічним називається
масив, розмірність якого стає відомою в процесі виконання програми.
В С++
для роботи з динамічними об’єктами використовують спеціальні операції 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 між апострофами (''). Приклади спеціальних символів:
Новий рядок |
'\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
<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.Порядок виконання роботи
Проаналізувати
умову задачі.
Розробити
алгоритм та створити програму розв’язання задачі згідно з номером варіанту.
Результати
роботи оформити протоколом
|