M.A. Jankowska, G. Sypniewska-Kamińska
LABORATORIUM NR 01
TEMAT : TABLICE JAKO ARGUMENTY FUNKCJI
1. Tablice statyczne
Prototypy dwóch funkcji, których parametrem formalnym jest statyczna jednowymiarowa tablica n-elementowa: double srednia1(double x[], const int& n);
void show_vec(double * x, int n);
W obu przypadkach przy wywołaniu funkcji zostanie jej przekazany wskaźnik, którego wartością jest adres pierwszego elementu tablicy. Informacja o liczbie elementów tablicy przekazana jest do funkcji przez drugi parametr. Na przykład, jeżeli zgodnie z nazwą, funkcja show_vec służy do wyświetlania elementów jednowymiarowej tablicy na ekranie monitora, to jej wywołanie show_vec(w,15)
spowoduje wyświetlenie 15 elementów jednowymiarowej tablicy w, której elementy są typu double.
Prototypy dwóch funkcji, których parametrem formalnym jest statyczna dwuwymiarowa tablica o n wierszach i 5 kolumnach: double srednia2(double a[][5], const int& n);
void show_array(double (*x)[5], int n);
albo
const int ic = 5;
double srednia2(double a[][ic], const int& n);
void show_array(double (*x)[ic], int n);
Uwaga 1. Liczba kolumn musi być określona za pomocą literału albo stałej, której nazwa została zdefiniowana przed prototypem funkcji. Tak więc przy przekazywaniu tablicy dwuwymiarowej (wielowymiarowej) do funkcji można pominąć jedynie pierwszy wymiar, natomiast drugi (pozostałe) musi być podany.
Uwaga 2. Przez pojęcie tablicy dwuwymiarowej możemy rozumieć tablicę, które elementami są tablice. W naszym przykładzie mamy do czynienia z tablicą, której elementami są tablice 5-elementowe wartości typu double. Zauważmy, że x jest tutaj nazwą tablicy o liczbie elementów, która jest określona przez parameter n. Identyfikator x określa adres pierwszego elementu tablicy (której elementami są 5-elementowe tablice wartości typu double).
Przykład
#include "stdafx.h"
#include <iostream>
using namespace std;
const int ic = 4;
double srednia1(double x[], const int& n);
double srednia2(double a[][ic], const int& n);
void show_vec(double * x, int n);
void show_array(double (*x)[ic], int n);
int _tmain(int argc, _TCHAR* argv[])
{
double tab[] = {5,-6,9,-16,12,60,23,-2};
int np = sizeof(tab)/sizeof(double);
double am[][ic] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};
show_vec(tab, np);
cout << endl << "srednia arytmetyczna elementow tablicy : " << srednia1(tab,np) << endl; int iw = sizeof am/sizeof am[0];
cout << endl;
Laboratorium 1
1
M.A. Jankowska, G. Sypniewska-Kamińska
show_array(am,iw);
cout << endl << " srednia arytmetyczna elementow macierzy: " << srednia2(am,iw) << endl; return 0;
}
double srednia1(double x[], const int& n) // 1. tablica jest przekazana przez wskaźnik
{
double suma=0.0;
for (int i=0; i<n; i++)
suma = suma + x[i];
return suma/n;
}
double srednia2(double a[][ic], const int& n)
// 2. argument przekazany przez referencję do
zmiennej
{
double suma = 0.0;
for (int i=0; i<n; i++)
{
for (int j=0;j < ic;j++)
{
suma = suma + a[i][j];
}
return suma/(n*ic);
}
}
void show_vec(double * x, int n)
// tablica jest przekazana przez wskaźnik
{
for (int i=0; i<n; i++)
cout << x[i]<<" ";
cout << endl;
}
void show_array(double (*x)[ic], int n)
// tablica jest przekazana przez wskaźnik
{
for (int i=0; i<n; i++)
{
for(int j=0; j<ic; j++)
{
cout << x[i][j]<<" ";
}
cout << endl;
}
}
2. Tablice dynamiczne
Prototypy funkcji, których argumentami są tablice lokowane dynamicznie int Funkcja1 (int m, double * a);
int oblicz(int * A[], int N);
int oblicz(int ** Array, int N);
Przykład
#include "stdafx.h"
#include <iostream>
using namespace std;
int oblicz(int *A[], int N);
Laboratorium 1
2
M.A. Jankowska, G. Sypniewska-Kamińska
int _tmain(int argc, _TCHAR* argv[])
{
int rows, cols;
cout << "Padaj liczbe wierszy i kolumn macierzy: \n"; cout << " rows = "; cin >> rows;
cout << " cols = "; cin >> cols;
// Krok 1: Definicja wskaźnika do typu int *
int ** A = 0;
// Krok 2: Przypisanie wskaźnikowi A adresu początku obszaru pamięci
// przeznaczonego do zapamiętania rows wartości typu int *
A = new int * [rows];
// Krok 3: W kolejnych krokach petli przydzielana jest pamiec dla odpowiednio rows tablic.
for (int i=0; i<=rows-1; i++)
A[i] = new int[cols]; // albo *(A+i)= new int[col]
for (int i = 0; i<= rows-1; ++i)
{
for (int j = 0; j<= cols-1; ++j)
{
A[i][j] = 2*i + j; //
*(*(A+i)+j) = 2*i + j ;
cout <<"A["<< i <<","<<j<<"] = "<< A[i][j] << " " << *(*(A+i)+j) << endl;
}
}
cout << "\nSuma elementow w drugiej kolumnie: "<< oblicz(A,rows)<<endl;
// Zwolnienie pamięci zarezerwowanej dla tablicy dwuwymiarowej reprezentowanej przez
//wskaźnik A
for (int i = 0; i<= rows-1; ++i)
delete [] A[i];
delete [] A;
return 0;
}
int oblicz(int ** Array, int N)
{
int suma = 0;
for (int j=0; j<N; j++)
suma = suma + Array[j][1];
return suma;
}
ZADANIA
Zadanie 1
Napisać program, który umożliwi pracę z danymi typu double przechowywanymi w jednowymiarowej tablicy alokowanej dynamicznie. Niech wskaźnik do pierwszego elementu tej tablicy ma nazwę q a liczba elementów tej tablicy ma nazwę n ( n jest wartością całkowitoliczbową określaną przez użytkownika). Zadaniem programu jest wykonanie następujących zadań:
- wczytanie z klawiatury liczby n, zarezerwowanie miejsca w pamięci dla tablicy q oraz wczytanie z klawiatury odpowiednio n
elementów do tablicy q,
- wywołanie trzech zdefiniowanych przez programistę funkcji, które obliczą odpowiednio: liczbę elementów tablicy o wartościach większych od 2.5 (funkcja pierwsza), sumę elementów o wartościach z przedziału [-1,1] (funkcja druga) oraz sumę elementów o indeksach mniejszych od 4 (funkcja trzecia),
- wypisanie wyników na ekranie,
- zwolnienie miejsca przeznaczonego na tablicę q.
#include "stdafx.h"
#include <iostream>
using namespace std;
int Funkcja1 (int m, double * a);
double Funkcja2 (int m, double * b);
double Funkcja3 (int m, double * x);
Laboratorium 1
3
M.A. Jankowska, G. Sypniewska-Kamińska
int _tmain(int argc, _TCHAR* argv[])
{
int n;
cout <<"Ile elementow ma tablica ? n = "; cin >> n; double * q;
q = new double [n];
for (int i=0; i<n; i++)
{
cout << "q[" << i << "] = "; cin >> q[i];
}
int liczba_elem;
liczba_elem = Funkcja1(n,q);
cout << "Liczba elementow wiekszych od 2.5 = " << liczba_elem << endl; cout << "Suma elementow z przedzialu [-1,1] = " << Funkcja2(n,q) << endl; cout << "Suma elementow o indeksach mniejszych niz 4 = " << Funkcja3(n,q) << endl; delete [] q;
_getch();
return 0;
}
int Funkcja1 (int m, double * a)
{
int s = 0;
for (int i=0; i<m; i++)
{
if (a[i] > 2.5)
s++;
}
return s;
}
double Funkcja2 (int m, double * b)
{
double s = 0.0;
for (int i=0; i<m; i++)
{
if (b[i] >= -1.0 && b[i] <= 1.0)
s = s + b[i];
}
return s;
}
double Funkcja3 (int m, double * x)
{
double s = 0.0;
int k = 4;
if (m < 4) k = m;
for (int i=0; i<k; i++)
{
s = s + x[i];
}
return s;
}
Zadanie 2
W pliku o nazwie „macierz_dane.txt” zapisane są elementy pewnej macierzy. W pierwszej linii tego pliku, albo jak odtąd będziemy mówić – w pierwszym jego rekordzie, zapisane są dwie liczby całkowite określające rozmiar macierzy. Pierwsza z podanych liczb określa liczbę wierszy macierzy, druga – liczbę jej kolumn. W następnych rekordach pliku zapisane są elementy pierwszego, drugiego i kolejnych wierszy macierzy. Mówimy, że macierz w tym pliku zapisana jest wierszami.
Uwaga!
Liczby zapisane w jednym wierszu powinny być oddzielone spacjami. Nie można stosować przecinków jako separatorów.
Napisać program, który wykonuje następujące działania:
a) po odczytaniu danych zapisanych w pierwszym rekordzie pliku przydziela pamięć dla dynamicznej tablicy dwuwymiarowej o elementach typu double,
Laboratorium 1
4
M.A. Jankowska, G. Sypniewska-Kamińska
b) odczytuje z dysku elementy danej macierzy i zapisuje je w dwuwymiarowej tablicy; program powinien być na tyle uniwersalny, by odczytać dowolną macierz dwuwymiarową, zapisaną w pliku według wyżej określonych zasad, c) oblicza sumę elementów każdego wiersza macierzy, zapamiętując wynik w jednowymiarowej dynamicznej tablicy mającej tyle elementów, ile wierszy ma dana macierz,
d) oblicza sumę kwadratów elementów każdej kolumny macierzy, zapamiętując wynik w jednowymiarowej dynamicznej tablicy mającej tyle elementów, ile kolumn ma dana macierz, e) oblicza sumę wszystkich elementów macierzy,
f) sprawdza czy macierz jest kwadratowa i
- jeżeli tak, to oblicza sumę elementów na przekątnej głównej macierzy (tzw. ślad macierzy),
- jeżeli nie, to wyprowadza na ekran monitora i do pliku informację, że macierz nie jest macierzą kwadratową, g) znajduje największy co do wartości bezwzględnej element każdego wiersza macierzy, zapamiętując wynik w jednowymiarowej dynamicznej tablicy mającej tyle elementów ile wierszy ma dana macierz, h) znajduje największy co do wartości bezwzględnej element całej macierzy, i) tworzy nową macierz zapisaną w tablicy dynamicznej, która od danej macierzy różni się jedynie tym, że w wierszu i kolumnie wybranych przez użytkownika programu ma wszystkie elementy równe zeru. Użytkownik programu powinien zostać poinformowany o aktualnym rozmiarze tablicy, aby mógł w prawidłowy sposób dokonać wyboru wiersza i kolumny. Program powinien jednak być tak napisany, aby w sytuacji, gdy podane wartości są nieprawidłowe, umożliwić użytkownikowi skorygowanie błędu,
j) zwalnia pamięć przydzieloną dynamicznie wszystkim tablicom.
Wymagania dotyczące struktury programu:
1. Zadania opisane w punktach c) - e) oraz g) - i) powinny zostać zaprogramowane w postaci oddzielnych funkcji.
2. Wyniki działań zrealizowanych w punktach c) - i) powinny być zapisane na dysku w pliku o nazwie „macierz.wyniki”.
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <cmath>
using namespace std;
void funkcja_1(int n, int m, double ** a, double *b);
void funkcja_2(int n, int m, double ** a, double *b);
double funkcja_3(int n, int m, double ** a);
double funkcja_4(int n, double ** a);
void funkcja_5(int n, int m, double ** a, double *b);
double funkcja_6(int n, double * z);
void funkcja_7(int n, int m, int nw0, int nk0, double ** a, double **b); int _tmain(int argc, _TCHAR* argv[])
{
ifstream plik;
plik.open("macierz_dane.txt",ios_base::in);
if (!plik)
{
cout << "Plik nie zostal otwarty do odczytu." << endl; return 0;
}
ofstream plikw;
plikw.open("wyniki.txt", ios_base::out);
if (!plikw)
{
cout << "Plik nie zostal otwarty do odczytu." << endl; return 0;
}
int iw, ik;
plik >> iw >> ik;
Laboratorium 1
5
M.A. Jankowska, G. Sypniewska-Kamińska
cout <<"Tablica zapisana w pliku ma "<<iw<<" wiersze/y i "<<ik <<" kolumn(y)."<< endl; plikw <<"Tablica zapisana w pliku ma "<<iw<<" wiersze/y i "<<ik <<" kolumn(y)."<< endl; double ** y = NULL;
double ** v = NULL;
y = new double * [iw];
v = new double * [iw];
for (int j = 0; j <iw; j++)
{
y[j] = new double [ik];
v[j] = new double [ik];
}
for (int k = 0; k < iw; k++)
{
for (int p = 0; p < ik; p++)
plik >> y[k][p];
}
for (int k = 0; k < iw; k++)
{
for (int p = 0; p < ik; p++)
{
cout <<"a["<<k<<"]["<<p<<"]="<< y[k][p]<<"\t";
}
cout << endl;
}
double * x;
x = new double [iw];
funkcja_1(iw, ik, y, x);
for (int k = 0; k <iw; k++)
{
cout << "suma elementow w " <<k<<". wierszu : " << x[k] <<endl; plikw << "suma elementow w " <<k<<". wierszu : " << x[k] <<endl;
}
delete [] x;
cout << endl;
plikw <<endl;
x = new double[ik];
funkcja_2(iw,ik,y,x);
for (int k = 0; k <ik; k++)
{
cout << "suma elementow w " <<k<<". kolumnie : " << x[k] <<endl; plikw << "suma elementow w " <<k<<". kolumnie : " << x[k] <<endl;
}
delete [] x;
cout << endl<< "suma elementow macierzy" << funkcja_3(iw,ik,y) <<endl; plikw << endl<< "suma elementow macierzy" << funkcja_3(iw,ik,y) <<endl; if(iw == ik)
{
cout << endl<< "slad macierzy (trace)" << funkcja_4(iw,y) <<endl; plikw << endl<< "slad macierzy (trace)" << funkcja_4(iw,y) <<endl;
}
else
{
cout<<endl<<"Macierz nie jest kwadratowa." <<endl; plikw<<endl<<"Macierz nie jest kwadratowa." <<endl;
}
x = new double [iw];
funkcja_5(iw, ik, y, x);
for (int k = 0; k <iw; k++)
{
cout << "najwiekszy co do wartosci bezwzglednej element w " <<k<<". wierszu : " << x[k]<<endl; Laboratorium 1
6
M.A. Jankowska, G. Sypniewska-Kamińska
plikw << "najwiekszy co do wartosci bezwzglednej element w " <<k<<". wierszu : " << x[k]<<endl;
}
cout << endl<< "najwiekszy co do wartosci bezwzglednej element macierzy " << funkcja_6(iw,x)<<endl;
plikw<< endl<< "najwiekszy co do wartosci bezwzglednej element macierzy " << funkcja_6(iw,x)<<endl;
delete [] x;
cout <<"\n\nTablica zapisana w pliku ma "<<iw<<" wiersze/y i "<<ik <<" kolumn(y)."<< endl; cout <<"Okresl numery wiersza i kolumny, w ktore program wpisze wartosc 0."; int nw=-1, nk=-1;
do
{
cout << "\nnumer wiersza : ";cin >> nw; cout<<"numer kolumny :"; cin >>nk;
} while(nw<0 || nw>=iw || nk<0 || nk>=ik);
funkcja_7(iw, ik, nw, nk, y, v);
cout << endl << "Macierz z zerami w wybranym wierszu i kolumnie"<< endl; plikw << endl << "Macierz z zerami w wybranym wierszu i kolumnie"<< endl; for (int k = 0; k < iw; k++)
{
for (int p = 0; p < ik; p++)
{
cout <<"b["<<k<<"]["<<p<<"]="<< v[k][p]<<"\t"; plikw <<"b["<<k<<"]["<<p<<"]="<< v[k][p]<<"\t";
}
cout << endl;
plikw << endl;
}
for (int i=0; i<iw; i++)
{
delete [] y[i];
delete [] v[i];
}
delete y;
delete v;
return 0;
}
void funkcja_1(int n, int m, double ** a, double *b)
{
for (int i = 0; i < n; i++)
{
double s = 0.0;
for (int j = 0; j < m; j++)
s = s + a[i][j];
b[i] = s;
}
}
void funkcja_2(int n, int m, double ** a, double *b)
{
for (int i = 0; i < m; i++)
{
double s = 0.0;
for (int j = 0; j < n; j++)
s = s + a[j][i]*a[j][i];
b[i] = s;
}
}
double funkcja_3(int n, int m, double ** a)
{
double s = 0.0;
for (int i = 0; i < n; i++)
Laboratorium 1
7
M.A. Jankowska, G. Sypniewska-Kamińska
{
for (int j = 0; j < m; j++)
s = s + a[i][j];
}
return s;
}
double funkcja_4(int n, double ** a)
{
double s = 0.0;
for (int i = 0; i < n; i++)
{
s = s + a[i][i];
}
return s;
}
void funkcja_5(int n, int m, double ** a, double *b)
{
for (int i = 0; i < n; i++)
{
double smax = abs(a[i][0]);
for (int j = 1; j < m; j++)
if(abs(a[i][j])>smax) smax = abs(a[i][j]);
b[i] = smax;
}
}
double funkcja_6(int n, double * z)
{
double smax = abs(z[0]);
for (int i = 1; i < n; i++)
{
if(abs(z[i])>smax) smax = abs(z[i]);
}
return smax;
}
void funkcja_7(int n, int m, int nw0, int nk0, double ** a, double **b)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
b[i][j] = a[i][j];
}
for (int i = 0; i < m; i++)
b[nw0][i] = 0.0;
for (int i = 0; i < n; i++)
b[i][nk0] = 0.0;
}
Laboratorium 1
8