13. Масиви

План:
Дефиниране и използване на масиви
Mасивите като параметри на функции
Масиви от символи
Двумерни масиви
Двумерни масиви като параметри на функции
Многомерни масиви


** Дефиниране и използване на масиви.

Пример:  Дефиниция на масив с 10 елемента тип double: 
double salaries[10];
 

Сравни с дефиниция на вектор  с 10 елемента тип double:
vector<double> salaries(10);

* Индекси на елементите на масив
Пример: На елементът с индекс 4 се задава стойност 355: 
salaries[4] = 355;

Елементите на масива се номерират (индексират), започвайки от 0: 
salaries[0] - първи елемент 
salaries[1] - втори елемент 
salaries[2] - трети елемент 
salaries[3] - четвърти елемент 
... 
salaries[9] - десети елемент

Индекс
0
1
2
3
4
5
6
7
8
9
Стойност
    ?
    ?
    ?
    ?
355
    ?
    ?
    ?
    ?
    ?

* Достъп до елементите на масива дава операция индекс (subscript).
* Границите на индексите на масива са от 0 до размера на масива минус 1.
* Задаване на стойности на елементите на масив

Пример: Масив със заплати.

const int SAL_MAXSIZE = 10; 
double sal[SAL_MAXSIZE]; /* фиксираме дължината на масива */ 
int sal_size = 0;        /* брой на използваните елементи на масива */ 
bool more = true; 
/* необходими са 2 условия за прекратяване на цикъла:
- спиране на въвеждането или
- запълване на всички елементи на масива
*/ 
while (more and sal_size < SAL_MAXSIZE) 
{
  cout << "Enter salary or 0 to quit";
 
  double x; 
  cin >> x; 
  if (cin.fail()) more = false 
  else 
  { sal[sal_size] = x; /* задаване на стойност на елемент на масива */ 
    sal_size++;        /* увеличаване с 1 на използваните елементи */ 
  } 
}

Вектор със заплати (за сравнение).

    vector<double> salaries;
    bool more = true;
    while (more)
    { 
       cout << "Please enter a salary, 0 to quit: ";
       double s;
       cin >> s;
       if (s == 0) more = false;
       else salaries.push_back(s);
    }


** Mасивите като параметри на функции. 

Пример: Намиране на максимален елемент на масив (сравни с вектоp).

double maximum(const double a[], int a_size)

   if (a_size == 0) return 0;
   double highest = a[0];
   for (int i = 1; i < a_size; i++)
      if (a[i] > highest) highest = a[i];
   return highest;
}

double maximum(vector<double> a) 

   if (a.size() == 0) return 0;
 
   double highest = a[0];
   for (int i = 1; i < a.size(); i++) 
      if (a[i] > highest) highest = a[i]; 
   return highest; 
}

Пример: Следващата програма чете заплати от стандартен вход и отпечатва максималната заплата. 

// salarray.cpp
 
#include <iostream> 
using namespace std;

void read_data(double a[], int a_maxsize, int& a_size) 
{ a_size = 0; 
  double x; 
  while (a_size < a_maxsize and (cin >> x)) 
  { a[a_size] = x; a_size++; } 
}

double maximum(const double a[], int a_size) 
{ if (a_size == 0) return 0; 
  double highest = a[0]; 
  int i; 
  for (i = 1; i < a_size; i++) 
     if (a[i] > highest) highest = a[i]; 
  return highest; 
}

int main() 
{ const int SALARIES_MAXSIZE = 10; 
  double salaries[SALARIES_MAXSIZE]; 
  int salaries_size = 0;

  cout << "Please enter all salary data: "; 
  read_data(salaries, SALARIES_MAXSIZE, salaries_size);

  if (salaries_size == SALARIES_MAXSIZE and not cin.fail()) 
     cout << "Sorry - extra data ignored\n";

  double maxsal = maximum(salaries, salaries_size); 
  cout << "The maximum salary is " << maxsal << "\n"; 
  return 0; 
}

nkirov@cpp % c++ salarray.cpp
nkirov@cpp % ./a.out
Please enter all salary data: 2000 3000 2100 1800
q
The maximum salary is 3000
nkirov@cpp % ./a.out
Please enter all salary data: 1 2 3 4 5 6 7 8 9 10 11 12
Sorry--extra data ignored
The maximum salary is 10

** Масиви от символи.

char ch = 'w';
ch = 126;

Всеки C-низ завършва със специален символ с ASCII код 0.

char greeting[6] = "Hello"; 
char greeting[] = "Hello"; 
char greeting[10] = "Hello";
Символ H e l l o '\0'
Индекс 0 1 2 3 4 5

Пример: Добавяне на елементи на един С-низ към друг С-низ.

// append.cpp
01: #include <iostream> 02: using namespace std;  03: /** 04:    Appends as much as possible from a string to another string 05:    @param s the string to which t is appended 06:    @param s_maxlength the maximum length of s (not counting '\0') 07:    @param t the string to append 08: */              09: void append(char s[], int s_maxlength, const char t[]) 10: {  int i = strlen(s); 11:    int j = 0; 12:    /* append t to s */ 13:    while (t[j] != '\0' and i < s_maxlength) 14:    {  s[i] = t[j]; 15:       i++; j++; 16:    } 17:    /* add zero terminator */ 18:    s[i] = '\0'; 19: } 20:  21: int main() 22: {  const int GREETING_MAXLENGTH = 10; 23:    char greeting[GREETING_MAXLENGTH + 1] = "Hello"; 24:    char t[] = ", World!"; 25:    append(greeting, GREETING_MAXLENGTH, t); 26:    cout << greeting << "\n"; 27:    return 0; 28: }
nkirov@cpp % c++ append.cpp
nkirov@cpp % ./a.out
Hello, Wor
nkirov@cpp %

* Превръщането С-низ в типа string и обратно става по следния начин:

const string s = "ABCD"; 
s.c_str();
char c[] = "1234"; 
string s = static_cast<string>(c);

Пример: Използване на функцията atoi от библиотеката cstdlib за превръщане на низ в число.
string year = "1999"; 
int y = atoi(year.c_str());
C_str.cpp

Важно е да не се забравя символа за край на низ при използване на масиви от символи (С-низове), защото много функции, които работят със С-низове и операция изходен поток определят дължината на низа по този символ.



** Двумерни масиви.
 
За съхранение и обработка на матрици (таблици) се използват двумерни масиви.
При дефиниране на двумерен масив се задават броя на редовете и броя на стълбовете.

Пример:
Двумерен масив съхранява съдбата на 10 хиляди щатски долара, инвестирани с различни лихвени проценти за различен брой години (7. Управяващи оператори - Вложени цикли)
const int BALANCE_ROWS = 11;
const int BALANCE_COLS = 6;
double balances[BALANCE_ROWS][BALANCE_COLS];
Достъп до елементите на двумерния масив се осъществява с два индекса.



** Двумерни масиви като параметри на функции
Пример: Отпечатване на матрица с използване на двумерен масив.
// matrix.cpp
01: #include <iostream> 02: #include <iomanip> 03: #include <cmath>  04: using namespace std; 05:  06: const int BALANCES_ROWS = 11; 07: const int BALANCES_COLS = 6; 08:  09: const double RATE_MIN = 5; 10: const double RATE_MAX = 10; 11: const double RATE_INCR =  12:    (RATE_MAX - RATE_MIN)/(BALANCES_ROWS - 1); 13: const int YEAR_MIN = 5; 14: const int YEAR_MAX = 30; 15: const int YEAR_INCR =  16:    (YEAR_MAX - YEAR_MIN)/(BALANCES_COLS - 1); 17:   18: /** 19:    Prints a table of account balances. 20:    @param the table to print 21:    @param table_rows the number of rows in the table. 22: */ 23: void print_table(const double table[][BALANCES_COLS],  24:                                        int table_rows) 25: {  const int WIDTH = 10; 26:    cout << setiosflags(ios::fixed) << setprecision(2); 27:    for (int i = 0; i < table_rows; i++) 28:    {  for (int j = 0; j < BALANCES_COLS; j++) 29:          cout << setw(WIDTH) << table[i][j]; 30:       cout << "\n"; 31:    } 32: }  33: /** 34:    Computes the value of an investment with compound interest 35:    @param initial_balance the initial value of the investment 36:    @param p the interest rate per period in percent 37:    @param n the number of periods the investment is held 38:    @return the balance after n periods 39: */ 40: double future_value(double initial_balance, double p, int n) 41: {  double b = initial_balance * pow(1 + p / 100, n); 42:    return b; 43: } 44:  45: int main() 46: {  double balances[BALANCES_ROWS][BALANCES_COLS]; 47:    for (int i = 0; i < BALANCES_ROWS; i++) 48:       for (int j = 0; j < BALANCES_COLS; j++) 49:          balances[i][j] = future_value(10000,  50:             RATE_MIN + i * RATE_INCR, 51:             YEAR_MIN + j * YEAR_INCR); 52:  53:    print_table(balances, BALANCES_ROWS); 54:  55:    return 0
; 56: }
nkirov@cpp % c++ matrix.cpp
nkirov@cpp % ./a.out
  12762.82  16288.95  20789.28  26532.98  33863.55  43219.42
  13069.60  17081.44  22324.76  29177.57  38133.92  49839.51
  13382.26  17908.48  23965.58  32071.35  42918.71  57434.91
  13700.87  18771.37  25718.41  35236.45  48276.99  66143.66
  14025.52  19671.51  27590.32  38696.84  54274.33  76122.55
  14356.29  20610.32  29588.77  42478.51  60983.40  87549.55
  14693.28  21589.25  31721.69  46609.57  68484.75 100626.57
  15036.57  22609.83  33997.43  51120.46  76867.62 115582.52
  15386.24  23673.64  36424.82  56044.11  86230.81 132676.78
  15742.39  24782.28  39013.22  61416.12  96683.64 152203.13
  16105.10  25937.42  41772.48  67275.00 108347.06 174494.02
nkirov@cpp %


** Многомерни масиви

Пример: Тримерен масив

int a[10][10][2];
a[0][0][0] = 100;