Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Архив WinRAR / 2_Посібник_С_002.doc
Скачиваний:
39
Добавлен:
17.05.2015
Размер:
2.7 Mб
Скачать

5.6 Копіювання рядка

Для ілюстрації основних аспектів застосування покажчиків в Сі розглянемо функцію копіювання рядка s1 в рядок s2. Спочатку наведемо версію, засновану на роботі з масивами. Для порівняння поруч поміщена версія з використанням покажчиків .

Приклад 10.копіювання рядка s1 в рядок s2 звичайним способом.

/ * копія рядка * /

void copy (char s1 [],char s2 []){

int i = 0;

while ((s2[i] = s1[i])!='\0')

i ++;

}

Приклад 11.копіювання рядка s1 в рядок s2 із використанням покажчиків.

/ * копія рядка * /

void copy (char * s1, char * s2){

while ((* s2 =* s1)! = '\ 0')

s2 ++; s1 ++;

}

Тут операція копіювання поміщена безпосередньо в умові, що визначає момент циклу: while((*s2 =*s1)! = '\ 0'). Просування вздовж масивів аж до тих пір, поки не зустрінеться "\ 0", забезпечують оператори s2++ та s1++. Їх, однак, теж можна помістити в перевірку.

Приклад 12.копіювання рядка s1 в рядок s2 із використанням циклу while

/ * копія рядка * /

void copy (char * s1, char* s2){

while ((*s2 ++ =*s1 ++)!=' \ 0 ');

}

Ще раз нагадаємо, що унарні операції типу * і ++ виконуються справа наліво. Значення *s++ це символ, на який вказує s до його збільшення. Так як значення "\ 0" є нуль, а цикл while провірит, чи не нуль вираз в дужках, то це дозволяє опустити явне порівняння з нулем. Так поступово функція копіювання стає все більш компактною і ... все менш зрозумілою. Але в системному програмуванні перевагу частіше віддають саме компактним і, отже, більш ефективним за швидкодією програмам.

Приклад 13.

/ * копія рядка * /

void copy (char * s1, char* s2){

while (* s2 ++ =* s1 ++);

}

У мові Сі, що деяка символьна стрічка, виражена як "рядок", фактично розглядається як покажчик на нульовий елемент масиву "рядок". Допускається, наприклад, такий цікавий запис:

Приклад 14. Вираження символьної стрічки як "рядок".

char * uk; uk = "ІНФОРМАТИКА";

Останній оператор присвоює покажчиком адресу нульового елемента рядка, тобто символу "І". Виникає питання, де знаходиться масив, що містить символи "ІНФОРМАТИКА"? Ми його ніде не описували. Відповідь така: цей рядок - константа, вона є частиною функції, в якій зустрічається, точно так саме, як ціла константа 4 або символьна константа "А" в операторах i = 4; c = "A".

Приклад 15. Друкування рядка символів у зворотному порядку.

# include <stdio.h>

int main () {

char * uk1, * uk2;

uk1 = uk2 = "ІНФОРМАТИКА";

while (* uk2! = '\ 0')

putchar (* uk2 + +);

putchar ('\ n');

while (--uk2> = uk1)

putchar (* uk2);

putchar ('\ n');

}

На самому початку покажчиками uk1 і uk2 присвоюється початкові адреси рядка "ІНФОРМАТИКА". Потім рядок посимвольно друкується і одночасно покажчик uk2 зміщується вздовж рядка. В кінці висновку uk2 вказує на останній символ вихідного рядка. У другому циклі while все той же покажчик uk2 починає змінюватися в зворотному напрямку, зменшуючись до тих пір, поки він не буде вказувати на нульовий елемент масиву, забезпечуючи видачу рядка в зворотному порядку.

5.7 Посилання та оператор &

Як тільки ми оголошуємо змінну, виділяється необхідний обсяг пам'яті, призначається для неї в певному місці в ОЗП (адреса в пам'яті). Як правило, ми не вибираємо це місце розташування змінної, це завдання автоматично виконується ОС під час виконання. Однак у деяких випадках нам потрібно знати адресу, за якою наша змінна буде зберігатися під час виконання програми.

Використання покажчиків в якості альтернативного способу доступу до змінних таїть в собі небезпеку - якщо було змінено адресу, що зберігається в покажчику, то цей покажчик більше не посилається на потрібне значення.

Мова C пропонує альтернативу для більш безпечного доступу до змінних через покажчики. Оголосивши змінну посилання , можна створити об'єкт, який, як покажчик, посилається на інше значення, але, на відміну від покажчика, постійно прив'язаний до цього значення. Таким чином, посилання на значення завжди посилається на це значення.

Головне що варто знати це те, що при ініціалізації посилання вона повинна бути проініціалізована(!).

Приклад 16. Синтаксис запису.

int &reference (NULL); /*операція неможлива!*/

int &reference = variable; /*правильна ініціалізація */

Приклад 17. Використання посилань(рис. 5.10).

int main(){

int first = 1111; /*Присвоєно значення змінній.*/

int *p = &first; /*Покажчику присвоєно адресу ivar.*/

int &link = first; /*Посилання асоційовано з ivar.*/

int *sp = &link; /*Покажчику присвоєно адресу iref.*/

printf( "first = %i \n", first);

printf("*p = %i \n ", *p);

printf( "link = %i \n ",link );

printf("*sp = %i \n ", *sp );

}

Результат роботи програми:

Рисунок 5.10 - Схема роботи:

Якщо linkприсвоювати якісь значення(link++,link-=3 …) то будуть змінюватись значення змінної на яку вона вказує.

Якщо функція в якості параметра приймає посилання, то вона змінює безпосередньо ці значення.

Приклад 18. Використання посилань.

void chage (int &c,int &d){

int var=c;

c = d; d = var;

}

int main (){

int a=1,b=0;

change(a, b);

printf(“a = %i, b = %i \n”, a, b);

}

Результат роботи програми:

В якості параметра функції беруться посилання, тобто синоніми змінних a i b, тому виходить ,що функція працює не з копіями, а з самими змінними.

Соседние файлы в папке Архив WinRAR