МІНІСТЕРСТВО ОСВІТИ І НАУКИ, МОЛОДІ ТА СПОРТУ УКРАЇНИ
НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ «ЛЬВІВСЬКА ПОЛІТЕХНІКА»
Кафедра САПР
Звіт
до лабораторної роботи №6
на тему «ВКАЗІВНИКИ В МОВІ ПРОГРАМУВАННЯ С»
з курсу «Проблемно-орієнтовані мови програмування»
ЛЬВІВ 2011
Мета роботи
Навчитися використовувати вказівники при роботі з масивами символів.
Теоретичні відомості
Вказівник - особливий вид змінної, котра зберігає адресу елемента пам'яті, де може бути записане значення інший змінної.
Визначення вказівника: type *varіable_name;
де type - тип даних вказівника; * - зірочка, що визначає тип 'вказівник'; varіable_name - ім'я змінної.
Наприклад:
іnt varіable, *poіnt; // Змінна цілого типу (varіable)
//.. і вказівник на цілий тип (*poіnt)
Існує операція, нерозривно пов'язана з вказівниками: Це унарна операція взяття адреси: &.
Наприклад:
poіnt=&varіable; де poіnt - вказівник, varіable - змінна деякого типу.
У даному прикладі в poіnt записується адреса змінної varіable. Результатом застосування операції & є адреса змінної в пам'яті. Результат має тип "вказівник" на тип змінної. Операція & може використовуватися практично з усіма типами даних, крім констант і бітових полів. Вказівники часто використовуються для обміну даними з функціями. У той час як у функцію можна передавати стільки аргументів, скільки потрібно, за допомогою оператора return вертається тільки одне значення. Як альтернатива можна використовувати глобальні змінні, однак у цьому випадку можуть з'явитися помилки, які тяжко виявити. Коли виникає необхідність повернути у функцію, яка викликає, більше одного значення, то використовуються вказівники.
Вказівник типу voіd* визначає місце в оперативній пам'яті (адреса деякого байту), але не містить інформації про тип об'єкту. До використання значення, що перебуває по цій адресі, обов'язково повинна бути виконана операція приведення вказівника до деякого типу, тому що в протилежному випадку компіляторові буде невідома довжина поля пам'яті, яке використовується в операції. До вказівника типу voіd* застосовуються наступні операції:
= - просте присвоювання;
= =, !=, >, <, <=, >= - операції порівняння.
Тому що мова C/З++ не підтримує елементи типу рядок, то для роботи з рядками звичайно використовуються вказівники типу char*. Якщо стрічкова константа використовується для ініціалізації вказівника типу char*, то адреса першого символу змінної буде початковим значенням вказівника. Наприклад:
char *str="cat";
Тут описується тільки вказівник str, і вказівник одержує початкове значення, рівне адресі першого елемента (символу 'с') стрічкової константи. Компілятор виділить пам'ять як для рядка (чотири байти), так і для розміщення значення вказівника.
Нехай функція повинна повернути два значення типу іnt. Таку функцію реалізувати неможливо, але можна повернути не значення, а записати його в певну адресу пам'яті. Для цього необхідно передати у функцію інформацію про те, за якою адресою пам'яті помістити результат. Передавати адресу цієї комірки будемо за допомогою вказівника.
У C/C++ при обробці елементів масиву зручно використовувати вказівник на цей масив. Будь-який доступ до елемента масиву, здійснюваний операцією індексування, може бути виконаний і за допомогою вказівника.
При оголошенні масиву
float fmast2] [3]
fmas - це вказівник-константа на матрицю. Вираз frnas[0] і fmas[l], у свою чергу, також є вказівниками- константами на нульовий і перший рядки. Значеннями цих двох вказівників є адреси першого елемента кожного рядка матриці, тобто адреси fmas[0][0] і fmas[1][0]. Дані вказівники визначають початкову адресу розміщення в пам'яті двох масивів, кожний з яких призначений для запису трьох елементів типу float.
У C/C++ можна оголошувати змінні, що мають тип 'вказівник на вказівник'. Ознакою такого оголошення є повторення символу * при оголошенні змінної. Число зірочок визначає число ‘рівнів’ вказівника. Фактично вказівник на вказівник - це адреса комірки пам'яті, що зберігає адресу вказівника. Під вказівник на вказівник виділяється два або чотири байти, це залежить від моделі пам'яті. При визначенні вказівник на вказівник може ініціалізуватися.
Індивідуальне завдання
6. Задано масив стрічок, кількість стрічок . Використовуючи вказівник, відсортувати Їх (по спаданню ASCII кодів). Ознака кінця вводу – пуста стрічка.
Текст програми
#include<stdio.h>
int main()
{
char m[4][100];
long int s[4]={0},a,h,v;
int i,j,n,k[4];
printf("Vvedite 4 linii\n");
for(i=0;i<4;i++)
{
if(fgets(m[i],100,stdin))
{
k[i]=strcspn(*(m+i),"\n");
m[i][k[i]]='\0';
for(n=0; n<k[i]; n++)
s[i]+=(int)*(*(m+i));
}
}
printf("+++++++++++++++++++++++++\n");
printf("Vidsortovan linii\n");
printf("+++++++++++++++++++++++++\n");
for(i=0;i<4;i++)
for(j=0;j<3;j++)
if(s[j]<s[j+1])
{
a=s[j];
s[j]=s[j+1];
s[j+1]=a;
h=j;
for(j=0;j<4;j++)
{
v=m[h][j];
m[h][j]=m[h+1][j];
m[h+1][j]=v;
}
}
for(i=0;i<4;i++)
{
for(j=0; j<k[i]; j++)
printf("%c", m[i][j]);
printf("\n");
}
return 0;
}
Результати обчислень
Висновок: Я навчився використовувати вказівники при роботі з масивами символів.