wskazniki,tablice


Ćwiczenie 4
Wskazniki, tablice
4.1. Wskaznik na zmiennÄ…
Deklaracja int *pa; oznacza, że pa jest wskaznikiem na obiekt typu int. Zmienna pa zawiera
adres pamięci, zarezerwowanej na zmienną typu int. Chcąc dostać się do zmiennej wskazywanej
przez pa używamy operatora wyłuskania (dereferencji) *.
Tak więc wyrażenie *pa jest zmienną, która jest wskazywana przez wskaznik pa.
Deklaracja int p, y; oznacza, że p jest zmienną typu int. Stosując operator adresu & można
dowiedzieć się, jaki jest adres zmiennej p. Adres ten można przypisać zmiennej pa (która jest
wskaznikiem na obiekt typu int): pa = &p;
Teraz *pa i p są tym samym obiektem. Tak więc instrukcje
y = p + 1; i y = *pa + 1; są równoważne.
Wartości wskazników można wyprowadzić w postaci szesnastkowych liczb o wartościach segmen-
tu i offsetu przy użyciu kodu konwersji %p np. printf("%p", pa);
Na wskaznikach tego samego typu - innego niż void - można wykonywać następujące operacje:
- porównanie dwóch wskazników,
- podstawienie jednego wskaznika pod drugi,
- odjęcie od siebie dwóch wskazników,
- dodanie lub odjęcie liczby całkowitej od wskaznika. lub podstawienie dwóch wskazników.
Program 4.1. //zmienna a wskaznik
#include
#include
int a, b; //zmienne globalne
int *pa, *pb; //wskazniki globalne
void main(void)
{
clrscr();
printf("\n podaj wartosc liczby a\n");
scanf("%d",&a);
pa=&a; //podstawienie adresu pod wskaznik
printf("\n a= %d",a); //wypisanie wartości zmiennej a
printf("jest pod adresem pa=%p", pa); //wypisanie adresu zmiennej a
*pa=*pa+2; //zwiększenie zmiennej a o 2
printf("\n a teraz a= %d",a);
printf("\n podaj wartosc liczby b\n");
scanf("%d",&b);
pb=&b; //podstawienie adresu pod wskaznik
printf("\n b= %d",b);
printf(" jest pod adresem pb= %p",pb);
printf("\n pb-pa= %d",pb-pa); //odjęcie dwóch wskazników od siebie
getch();
}
4.2. Wskaznik na tekst
Stała łańcuchowa jest ciągiem znaków zawartych pomiędzy znakami cudzysłowu. Na jej końcu
kompilator dodaje automatycznie znak '\0' oznaczający koniec tekstu. Stałe łańcuchowe mogą
Laboratorium Podstawy Programowania
być definiowane za pomocą dyrektywy #define. Stałe łańcuchowe należą do klasy statycznej,
tzn. są przechowywane przez cały czas działania programu i tylko w jednej kopii. Całe zdanie
w cudzysłowie jest równocześnie stałym wskaznikiem do miejsca, w którym jest zapisane. Można
więc użyć zapisu wskaznikowego char *tekst =" O co chodzi?" lub zadeklarować ta-
blicÄ™ znakowÄ… zainicjowanÄ… char tab[] = "O co chodzi?"
Do przeprowadzania operacji na tekstach można wykorzystywać następujące funkcje zawarte
w pliku string.h:
strcpy(char *s1,char *s2) - kopiowanie tekstu z s2 do s1;
strcat(char *s1, char *s2) - dołączenie do tekstu z s1 tekstu z s2;
strcmp(char *s1,char *s2) - porównanie tekstów s1 i s2;
strchr(char *s1,char c)- odszukanie znaku c w tekście s1;
strstr(char *s1,char *s2)- odszukanie tekstu s2 w tekście s1;
strlen(char *s) - obliczenie długości tekstu s;
Program 4.2
#include
#include
#include
void main(void)
{ clrscr();
char pan[]="KAROL"; //deklaracja i inicjacja tablicy 6-znakowej
char *wsk="INKA"; // wskaznik na tekst
puts(pan); //wypisanie tekstu z tablicy pan
puts(wsk); //wypisanie tekstu wskazywanego przez wsk
printf("\nrozmiar tablicy pan: %d\n", sizeof(pan));
printf("\ndlugosc tekstu wskazywanego przez wsk: %d\n",
strlen(wsk));
printf("%c\n", pan[0]); //pierwszy znak w tekscie
printf("%s\n", &pan[0]); //tekst pod adresem &pan[0]
printf("adres poczatku tablicy pan %p\n", pan);
printf("%s\n", pan+3); //tekst pod adresem pan+3
printf("%c\n", wsk[2]); //trzeci znak w tekście
printf("%c\n", *(wsk+2)); //trzeci znak w tekście
printf("%s\n", wsk+2); //tekst pod adresem wsk+2
strcat(wsk, "OLA"); //dołączenie tekstu
printf("%s\n",wsk);
strcpy(wsk, "OLA"); //przekopiowanie tekstu
printf("%s\n",wsk);
strcpy(wsk, pan); //przekopiowanie tekstu
printf("%s\n",wsk);
strcpy(pan, "OLA"); //przekopiowanie tekstu
printf("%s\n",pan);
wsk=pan; //podstawienie adresu
puts (wsk);
puts(++wsk);
getch();
}
4.3. Tablice jednowymiarowe
Tablice jednowymiarowe deklaruje się podając typ elementów, nazwę tablicy i liczbę elementów
ujętą w nawiasy kwadratowe: np. char t[10]; double tab[2]; Elementy tablicy numeru-
je siÄ™ zaczynajÄ…c od zera.
Politechnika Opolska
2
Laboratorium Podstawy Programowania
Tablica może być zainicjowana podczas deklaracji:
char t[10] = { a , b , c , d , e ,'\o'};.
Para nawiasów [] jest dwuargumentowym, lewostronnie łącznym operatorem indeksacji, którego
wynikiem jest element tablicy.
Program 4.3 //deklaracje i inicjacje tablic
#include
#include
#define r 10
void main()
{ char c1[r] = {'b','i','a','l','y','\0'}; // lub {"zielony"};
int i1[r] = {1,2,3,4,5,4,5,4,6}; //tablica będzie uzupełniona zerami
float f1[r] = {1.25,0,0,23,-3.33,333,34.23,1};
clrscr();
for(int i=0;i<10;i++)
printf("\nc1[%d] = %c i1[%d] = %d f1[%d] =
%8.2f",i,c1[i],i,i1[i],i,f1[i]);
getch();
}
4.4. Wskaznik a tablica
W C istnieje ścisła zależność między wskaznikami a tablicami. Każda operacja, która może być
przeprowadzona przez indeksowanie tablicy, może być również dokonana za pomocą wskaznika.
Deklaracja int A[10]; definiuje tablicę dziesięciu liczb typu int, a więc blok 10 kolej-
nych obiektów nazywających się A[0], A[1], ..., A[9]. Zapis A[i] oznacza element
tablicy oddalony o i pozycji od jej poczÄ…tku.
Jeżeli pa będzie wskaznikiem do obiektów całkowitych zadeklarowanym jako int *pa; wów-
czas przypisania takie, jak
pa = &A[0]; lub pa = A;
ustawiają pa tak, aby wskazywał na zerowy element tablicy A; to znaczy pa będzie zawierać adres
elementu A[0].
Instrukcje *pa = 10; i A[0] = 10; są równoważne.
Jeśli pa wskazuje na pewien element tablicy A, to z definicji pa+1 wskazuje na element następny.
Ogólnie pa-i wskazuje na i-ty element przed pa, a pa+i na i-ty element po pa. Zatem, jeżeli pa
wskazuje na A[0], to *(pa+1) odnosi się do zawartości A[1]; pa+i jest adresem A[i], a
*(pa+i) jest wartością A[i].
Istnieje jednak istotna różnica między nazwą tablicy a wskaznikiem. Wskaznik jest zmienną, wiec
operacje pa=A i pa++ mają sens. Natomiast nazwa tablicy jest stałą wskaznikową, a nie zmienną
czyli konstrukcje takie, jak A = pa, A++ lub pa=&A sÄ… niedopuszczalne!!!
Jeśli uzupełnimy program 4.1 instrukcjami:
int *pa;
pa=i1;
puts("wyświetlenie zawartości tablicy i1 ");
for (i=0;i<10;i++) printf(" %d",*(pa+i));
to wyświetlimy zawartość tablicy i1 używając notacji wskaznikowej.
Politechnika Opolska
3
Laboratorium Podstawy Programowania
4.5. Tablice wielowymiarowe
Tablice wielowymiarowe sÄ… reprezentowane jako tablice tablic. Np. deklaracja
char A[2][5];
wprowadza tablicę A z dwoma elementami, z których każdy jest tablicą typu char [5]. Tablica
taka może być zainicjowana podczas deklaracji:
char A[2][5] = { { a , b , c }, {'0', '1', '2', '3', '4'}};
Nazwa tablicy A jest stałą wskazującą na pierwszy wiersz tablicy, czyli jej pierwszy element A[0].
A+i wskazuje na i-ty wiersz tablicy, czyli A[i]. Natomiast A[i]+j wskazuje na j-ty element i-tego
wiersza, czyli A[i][j].
Program 4.5.
#include
#include
#define M 10
void main ()
{
int A[M][M], i, j, w,k;
clrscr();
printf("Podaj ilosc wierszy ");
scanf("%d",&w);
printf("Podaj ilosc kolumn ");
scanf("%d",&k);
for(i=0;i{
for (j=0;j {
printf("A[%d",i);
printf(",%d",j);
printf("]=");
scanf("%d",&A[i][j]);
}
}
clrscr();
for(i=0;i{
for (j=0;j {
gotoxy(5+4*j,10+i);
printf("%d",A[i][j]);
}
}
getch();
}
Sprawdzić, że poniższe zapisy są równoważne:
A[0][0] i *A[0] i **A
A[1][2] i *(A[1]+2) i *(*(A+1)+2)
&A[1][2] i A[1]+2 i *(A+1)+2
4.6. Alokacja (przydział) pamięci na tablice dynamiczne
Wszystkie dane w programie należą do jednej z trzech klas: statycznych, automatycznych lub dy-
namicznych. Dane statyczne są definiowane w czasie kompilacji. Pamięć dla danych automatycz-
Politechnika Opolska
4
Laboratorium Podstawy Programowania
nych jest przydzielana, niewidocznie dla użytkownika, w chwili ich utworzenia. Tylko dane dyna-
miczne mają przydzielaną pamięć (na stercie) na żądanie programisty. Stosuje się je głównie wtedy,
gdy ich rozmiar nie jest znany w chwili pisania programu.
Przydziału pamięci na tablicę n liczb całkowitych dokonuje się za pomocą funkcji
void * malloc(n*sizeof(int)), lub void *calloc(n, sizeof(int)), zdefinio-
wanych w pliku nagłówkowym alloc.h, które zwracają wskaznik do początku przydzielonego
obszaru lub wskazanie puste NULL, gdy alokacja się nie powiodła. Ponadto funkcja calloc zeruje
przydzieloną pamięć. Do zwalniania wcześniej przydzielonej pamięci służy funkcja free(wsk).
Zwalnianie pamięci nie przydzielonej jest błędem.
Program 4.6.1 /*dynamiczne przydzielanie pamięci na tablicę jednowymiarową */
#include
#include
#include
#include
#include
main()
{
int n,i, *wsk;
randomize();
clrscr();
printf("liczba elementow tablicy n=");
scanf("%d",&n);
wsk=(int*)calloc(n,sizeof(int));
if (wsk == NULL)
{
printf("brak miejsca w pamieci\n");
exit (1);
}
else
for (i=0;i {
*(wsk+i)=random(100);
printf("%5d",*(wsk+i));
}
getch();
free(wsk);
return 0;
}
Program 4.6.2 /*dynamiczne przydzielanie pamięci na tablicę dwuwymiarową */
# include
# include
# include
void tworz_tab(int *a[10],int *w,int *k);
void wydruk_tab(int *a[10], int *w, int *k);
void main()
{
int w,k, nr;
int *tab[10]; //deklaracja tablicy zawierającej wskazniki do początków wierszy
clrscr();
printf("liczba wierszy=");scanf("%d",&w);
printf("liczba kolumn=");scanf("%d",&k);
Politechnika Opolska
5
Laboratorium Podstawy Programowania
for (int i=0;i tab[i]=(int *)calloc(k,2); //alokacja wierszy
tworz_tab(tab,&w,&k);
clrscr();
wydruk_tab(tab,&w,&k);
for (i=0;i getch();
}
void tworz_tab(int *a[10], int *w, int *k)
{
int i,j;
for (i=0;i<*w;i++)
for (j=0;j<*k;j++)
{
printf("tab[%d,%d]=",i,j);
scanf("%d",*(a+i)+j); // lub *(*(a+i)+j)=random(100);
}
}
void wydruk_tab(int *a[10], int *w, int *k)
{
int i, j;
for (i=0;i<*w;i++)
{
for(j=0;j<*k;j++)
printf("%5d",*(*(a+i)+j)); // *(a+i) - adres pocz. i-tego wiersza
printf("\n"); // *(a+i)+j - adres j-tego elementu i-tego wiersza
// *(*(a+i)+j) - wartość pod powyższym adresem
}
}
4.7. Wskaznik a funkcja
Argumenty wywołania funkcji (parametry aktualne) są przekazywane przez wartość. Jeśli argument
ma być wykorzystany do wyprowadzenia wyniku, to ten argument musi być typu wskaznikowego
np. funkcja void fun(int *a, int*b) {int t=*a; *a=*b; *b=t;} wykonuje za-
mianę wartości wskazywanych przez wskazniki będące jej argumentami.
Nazwa funkcji jest stałą wskaznikową do tej funkcji. Jeśli funkcja ma prototyp
void fun(int*t, int r), to wskaznik do niej musi mieć ten sam typ i identyczną listę ar-
gumentów: void (*wsk_fun)(int *t1, int r1). Możliwe jest wtedy przypisanie
wsk_fun=fun. Zapisując wywołanie funkcji określonej przez wskaznik, nie trzeba poprzedzać
wskaznika operatorem wyłuskania.
Program 4.7.
#include
#include
int minimum(int *t, int n) //tablicÄ™ przekazuje siÄ™ jako wskaznik do zerowego elementu tablicy
{ int min=t[0];
for (int i=0;i if(min>t[i]) min=t[i];
return min;
}
const int r=6;
Politechnika Opolska
6
Laboratorium Podstawy Programowania
int (*wsk_min)(int*,int) = minimum; //deklaracja wskaznika do funkcji i zainicjowanie go
int tab[r]={3,5,7,4,1,7};
void main()
{ clrscr();
printf("\n 1 wywolanie: %d",minimum(tab,r));
printf("\n 2 wywolanie: %d",wsk_min(tab,r));
printf("\n 3 wywolanie: %d",(*wsk_min)(tab,r));
getch();
}
Wskazniki do funkcji można przekazywać jako argumenty innym funkcjom, zwracać jako wyniki
funkcji, porównywać ze wskazaniem pustym NULL. Nie wolno wykonywać na nich operacji aryt-
metycznych.
Stosuje się także tablice wskazników do funkcji np. int(*rodzaje_Testów[10])(); jest
deklaracją tablicy zawierającej 10 elementów, z których każdy jest wskaznikiem do funkcji.
Programy do samodzielnego napisania:
1. Wskaznik t wskazuje na tekst. Napisać funkcję hist(char *t, int *litery, int *cyfry), która poli-
czy histogramy (liczbę wystąpień) wszystkich małych liter samogłosek i cyfr w podanym tek-
ście. Funkcja jako pierwszy parametr dostaje wskaznik do tekstu, który ma być analizowany,
a jako drugi i trzeci wskazniki do tablic, w których należy umieścić liczebności wystąpień liter
i cyfr.
2. Dana jest tablica A zawierająca n liczb całkowitych. Do tablicy B przepisać z tablicy A elemen-
ty o indeksach parzystych. Do tablicy C przepisać z A elementy parzyste.
3. Dany jest ciąg n liczb rzeczywistych. Obliczyć wartość średnią jego elementów i wstawić ją na
poczÄ…tek tego ciÄ…gu.
4. Zdefiniować funkcję znajdującą pozycję i wartość maksymalnego elementu danego ciągu licz-
bowego. Napisać program sprawdzający jej działanie.
5. Uporządkować rosnąco ciąg n liczb całkowitych używając notacji wskaznikowej. Wskazania do
trzech największych elementów umieścić w tablicy wskazników.
6. Dwa uporządkowane rosnąco ciągi liczb scalić w jeden ciąg uporządkowany rosnąco.
7. Utworzyć tablicę dwuwymiarową o wymiarze n n wypełnioną kolejnymi liczbami naturalny-
mi w następujący sposób:
1 2 3 n
îÅ‚ Å‚Å‚
ïÅ‚ śł
2n 2n -1 2n - 2 n +1
ïÅ‚ śł
ïÅ‚ śł
2n +1 2n + 2 2n + 3 3n
ïÅ‚
4n 4n -1 3n +1śł
ïÅ‚ śł
ïÅ‚ śł
ðÅ‚ ûÅ‚
Następnie wyzerować jej elementy leżące poniżej głównej przekątnej.
8. Napisać funkcję sklej, której parametrami są dwa wskazniki na tekst s i t. Funkcja ma dopisać
do tekstu s tekst t, inaczej mówiąc ma je połączyć. Funkcja ma operować na wskaznikach do
tekstu, a nie na tablicach i indeksowaniu.
9. Do programu 4.6.2 dopisać:
a) funkcjÄ™ usuwajÄ…cÄ… wiersz z tablicy
b) funkcję dodającą jako ostatni wiersz zawierający sumy elementów poszczególnych kolumn
Sprawdzić działanie tych funkcji.
10. Napisać (przy użyciu wskazników) program wykonujący operacje dodawania, odejmowania
i mnożenia dwóch macierzy dwuwymiarowych.
Politechnika Opolska
7


Wyszukiwarka

Podobne podstrony:
mb C E wyswietlacz tablicy wskaznikow
W10 wskazniki na tablice wielowymiarowe i funkcje
Demontaż tablicy wskaźników Astra F
C w5 tablice wskazniki
Cinquecento demontaż deski rozdzielczej tablicy wskaźników poradnik
C w3 tablice wskazniki funkcje
Historia państwa i prawa Polski Testy Tablice
et wskazniki empiryczne
1 Wskaźniki techniczno ekonomiczne wiercenia otworuid049
1 parametry technniczne wymiary tablic zal nr1id?43
Tablice Dystrybuanta rozkładu normalnego
NADMA 6 TABLICA OIa

więcej podobnych podstron