B.I.Березін,С.Б.Березін(С.83) МАСИВИ І ПОКАЖЧИКИ
Раніше ми ввели типи даних в мові С, які називаються іноді базовими або
вбудованими. На основі цих типів даних мова С дозволяє будувати інші типи
даних і структури даних. Масив - один з найбільш простих і відомих структур
даних. Під масивом в мові С розуміють набір даних одного і того ж типу,
зібраних під одним ім'ям. Кожний елемент масиву визначається ім'ям масиву і
порядковим номером елемента, який називається індексом. Індекс в мові С
завжди ціле число.
ОГОЛОШЕННЯ МАСИВУ В ПРОГРАМІ
Основна форма оголошення масиву розмірності N така:
тип <эээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээ) |#include #include |
|{ int i,j,a[10], max. nmax, min, |#' nclude void main() { int |
|nmin, temp; clrscr(); for (i=0; i<10;|temp, і, j, a[ 1 0]; clrscr(); for |
|i++) сіп » a[i]; max=min=a[0]; |(i=0;i<10;i++) сіп » a [ і ]; for |
|nmax=nmin=0; for (i=0; i<10; i++) |(i=0;i<9;i++) for (j=i+1 ;j<10;j++) if |
|if(a[i]>max) { max=a[i]; nmax=i;} |(a[i]>a[j]) { temp=a[i]; a[i]=a[j]; |
|else if(a[i]<1 0;i++) { cout|
|tern p= a[n m ax]; a[n max]=a[nm і |« a[i]«" "; sound(a[i]*80); delay(500);|
|n]; a[nm і n]=temp; for (i=0; i<10; |nosou nd(); } getch(); } |
|i++) cout « a[i] «" "; } | |
МАСИВИ СИМВОЛІВ. РЯДКИ
Однак масиви типу char - символьні масиви - займають в мові особливе
місце. У багатьох мовах е спеціальний тип даних - рядок символів (string).
У мові С окремого типу рядка символів немає, а реалізована робота з рядками
шляхом використання одновимірних масивів типу char. У мові С символьний
рядок - це одновимірний масив типу char, що закінчується нульовим байтом.
Нульовий байт - це байт, кожний біт якого рівний нулю. Для нульового байта
визначена спеціальна символьна константа ' ' . Це потрібно враховувати
при описі відповідного масиву символів. Так, якщо рядок повинен містити N
символів, то в описі масиву потрібно указати N+1 елемент.
Наприклад, опис
char str[11] ;
передбачає, що рядок містить 10 символів, а останній байт зарезервований
під нульовий байт. Звичайно, ми задали звичайний одновимірний масив, але
якщо ми хочемо трактувати його як рядок символів, то це буде рядок максимум
з 10 елементів.
Хоча в мові С немає спеціального типу рядка, мова допускає рядкові
константи. Рядкова константа - це список літер, взятих в подвійні лапки.
Наприклад,
"Borland C++ ", "Це рядкова константа".
У кінець рядкової константи не треба ставити символ ''. Це зробить
компілятор, і рядок "Borland C++" в пам'яті буде вигляда-
|В |о |г |1 |а n |d | |С |+ |+ | |
Є два простих способи ввести рядок з клавіатури. Перший спосіб
-скористатися функцією scanf() зі специфікатором введення %s. Треба
пам'ятати, що функція scanf() вводить символи до першого пропуско-вого
символа. Другий спосіб - скористатися спеціальною бібліотечною функцією
gets(), оголошеною в файлі stdio.h. Функція gets() дозволяє вводити рядки,
що містять пропуски. Введення закінчується натисненням клавіші Enter.
Обидві функції автоматично ставлять в кінець рядка нульовий байт. Не
забудьте зарезервувати для нього місце. Як параметр в цих функціях
використовується просто ім'я масиву.
|#i ncl ude void main () { char s1[80], |#i nclude
void |
|s2[80]; scanf( %s, "s1); І" можна об'єднати 2 scanf |main () { char s1[80],
|
|в один s c a n f ( % s % s , " s 1 , s 2); * / |s2[80]; gets(s1); gets(s2)
|
|scanf("%S", s2); printf("%sn", s1); printf("%s", |puts(s1); puts(s2);
|
|s2); } ввели: Hello! Good I uck! Резул ьтат: Hello! |} ввели: Hello! Good luck!
|
|Good |Результат: Hello! Good
luck!|
Виведення виробляється функціями printf() або puts(). Обидві функції
виводять вміст масиву до першого нульового байта. Функція puts() додає в
кінці рядка, що виводиться символ нового рядка. У функції printf()
перехід на новий рядок треба передбачати в рядку формату самим.
ФУНКЦІЇ ДЛЯ РОБОТИ З РЯДКАМИ
Для роботи з рядками існує спеціальна бібліотека, опис якої
знаходиться в файлі string.h. Найчастіше використовуються функції
strcpyO, strcat(), strlenQ, strcmpO.
Виклик функції strcpy() має вигляд
strcpy(si, s2) ;
Функція strcpy() використовується для копіювання вмісту рядка s2 в
рядок s1. Масив s1 повинен бути досить великим, щоб в нього вмістився
рядок s2. Якщо місця мало, компілятор не видає вказівки на помилку або
попередження; це не перерве виконання програми, але може привести до
псування інших даних або самої програми і неправильній роботі програми
надалі. Виклик функції strcat() має вигляд
strcat(sl, s2) ;
Функція strcat() приєднує рядок s2 до рядка s1 і вміщує його в масив, де
знаходився рядок s1, при цьому рядок s2 не змінюється. Нульовий байт,
який завершував рядок s1, буде замінений першим символом рядка s2. їв
функції strcpyO, і в функції strcat() рядок, що виходить, автоматично
завершується нульовим байтом.
Розглянемо простий приклад використання цих функцій.
Резул ьтат:
Hello, World!
Hello, World! World!
#include
#і ncl ude
main () {
char s1[20], s2[20];
strcpy(s1 , "Hello, ");
strcpy(s2, "World!");
puts(s1);
puts(s2);
strcat(s1, s2);
puts(s1);
puts(s2);
}
Виклик функції strcmpO має вигляд
strcmp(sl, s2);
Функція strcmpO порівнює рядки si і s2 і повертає значення О, якщо рядки
однакові, тобто містять одне і те ж число однакових символів. Під
порівнянням рядків ми розуміємо порівняння в лексикографічному значенні,
так як це відбувається, наприклад, в словнику. Звичайно, в функції
відбувається посимвольне порівняння кодів символів. Код першого символа
одного рядка порівнюється з кодом символа другого рядка. Якщо вони
однакові, розглядаються другі символи тощо. Якщо зі лексикографічно (в
значенні словника) більше s2, то функція strcmpO повертає додатне значення,
якщо менше -від'ємне значення.
Виклик функції strlen() має вигляд
strlen(s) ;
Функція strlen() повертає довжину рядка з, при цьому завершальний
нульовий байт не враховується. Виклик length("Hello") поверне
значення 5.
Розглянемо застосування цієї функції для обчислення довжини рядка, що
вводиться з клавіатури.
#include
#incl ude m а і n () { char s(80], printf( "Введіть
рядок:");
gets(s);
printf( "Рядокп%зп має довжину %d символів n", s, strlen(s)); }
ДВОВИМІРНІ МАСИВИ
Як ми вже зазначали, мова С допускає багатовимірні масиви, найпростішою
формою яких е двовимірний масив (two-dimentional array). Можна сказати, що
двовимірний масив - це масив одновимірних масивів .
Двовимірний масив int a[3][4] можна подати у вигляді таблички:
Другий індекс
Перший індекс
|а[0] [0] |а[0][1] |а[0][2] |а[0] [3] |
|а[1] [0] |а[1][1] |а[1][2] |а[1][3] |
|а[2][0] |а[2] [1] |а[2][2] |а[2] [3] |
Перший індекс - номер рядка, другий індекс - номер стовпця. Кількість байт
пам'яті, яке необхідне для зберігання масиву, обчислюється по формулі
Кільк.байтів = <эээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээээmain() { |
|int *p, *g, x; p=&x; |int *p, *g, x; p=&x; |
|g=p; |g=p; |
|printf("nnnp=%p", p); P= P + 8; |p r і n t f (" n n n p = % p ", |
|printf(" p+5=%p", p); printf(" g=%p",|p); P= P + 8; printf(" p+5=%p", p); |
|g); printf(" p-g=%p", p-g); |printf(" g=%p", g); printf(" p+g=%p", |
|} Результат: p=07DO p+5=07EO g=07DO |p+g); } Результат: Error UKAZAT2.CPP |
|p-g=0008 |14: Invalid pointer addition |
Покажчики можна порівнювати. Застосовні всі 6 операцій:
<, >, <=, >=, =, == і !=.
Порівняння р < g означає, що адреса, що знаходиться в р, менше адреси,
що знаходиться в g.
Якщо рід вказують на елементи одного масиву, то індекс елемента, на
який вказує р, менше індексу масиву, на який вказує g.
ЗВ'ЯЗОК ПОКАЖЧИКІВ І МАСИВІВ
Будь-який доступ до елемента масиву за допомогою операції
індексування може бути виконаний за допомогою покажчика (що в загальному
випадку працює швидше).
Декларація
int a[10]
визначає масив а розміру 10:
[pic]
Запис а[і] посилає нас до і-му елемента масиву. int *р;
р=&а[0]; /* р вказує на нульовий елемент а або містить адресу елемента а[0]
*/
[pic]
х = *р; => х = а[0], У= *(Р+1); => У = а[1];
Значення змінної типу масив (ім'я масиву) є адреса
нульового елемента масиву.
р = &а[0]; => р = а;
*(а+і) ^ а[і] &а[і] => а+і
Результат буде один і той же. Перевага використання другого варіанту
полягає в тому, що арифметичні операції над покажчиками виконуються швидше,
якщо ми працюємо з підряд йдучими елементами масиву. Якщо ж вибір елементів
масиву випадковий, то швидше і більш наочна робота з індексами.
Між ім'ям масиву і покажчиком,-виступаючим в ролі імені масиву, існує
одна відмінність. Покажчик змінна, тому можна написати р = а або р++. Але
ім'я масиву не є змінною, і записи типу а = р або а++ не допускаються.
Дуже часто доводиться працювати над обробкою текстів, т. е. з масивами
рядків. Як ми пам'ятаємо, в мові С рядок - це масив символів, що
закінчується нульовим байтом. Розглянемо дві програми, що реалізовують
практично, одні і ті ж дії.
#incl ude
#include
void main()
{ char *p, str[]="String From Letters in Different Registers";
/* Рядок, що Складається з Букв в Різних Регістрах; */ int і=0; printf(
"Рядок Буде Надрукований Заголовними Буквами");
while (str[i]) printf("%c", toupper(str[i++]));
p=str; printf(" Рядок Буде Надрукований Малими Буквами");
while (*p) printf("%c", tolower(*p++)); }
Якщо в цих прикладах замінити рядок на англійській мові на рядок,
набраний російськими буквами, то ніякого перетворення букв в рядкові або,
навпаки, в прописні не станеться. Це пов'язано з тим, що стандартні функції
toupper() і tolower () аналізують значення
|