Subsecções

14 Matrizes ou Arrays Multidimensionais

Nas notas de aula anteriores, apresentamos arrays unidimensionais. Em C++ , é possível também definir arrays com 2 ou mais dimensões. Eles são arrays de arrays. Um array de duas dimensões podem ser imaginado como uma matriz (ou uma tabela).

Como você deve ter imaginado, para definir e acessar arrays de dimensões maiores, usamos colchetes adicionais ([ e ]). Por exemplo:

      int tabela[3][5];

Define um array bidimensional chamado tabela que é uma matriz 3 por 5 de valores do tipo int (15 valores no total). Os índices da primeira dimensão vão de 0 a 2, e os índices da segunda dimensão vão de 0 a 4.

Abaixo apresentamos um programa que imprime os elementos de um array bidimensional.

#include <iostream>
using namespace std;

#define ALTURA 5
#define LARGURA 5

int main()
{
   int x;                            //  numero da coluna 
   int y;                            //  numero da linha 
   char matriz [ALTURA] [LARGURA];   //  array 2-D [num_lins, num_cols] 
 

   //  preenche a matriz com zeros  

   for(y = 0; y < ALTURA; y += 1)
   {
     for(x = 0; x < LARGURA; x += 1)
     {
        matriz[y][x] = 0;
     }
   }

   //  Imprime a matriz com zeros e a coordenada escolhida com 1

   cout << endl << "Entre coordenadas na forma \"y x\"." << endl;
   cout << "Use valores negativos para sair do programa." << endl;

   cout << "Coordenadas: ";
   cin >> y >> x;

   while (x >= 0 && y >= 0)
   {
      matriz[y][x] = 1;      //  coloca 1 no elemento escolhido 

      for(y = 0; y < ALTURA; y += 1)  // imprime o array todo
      {
        for(x = 0; x < LARGURA; x += 1)
        {
             cout << matriz[y][x] << " ";
        }
        cout << endl << endl;
      }

      cout << endl;
      cout << "Coordenadas: ";
      cin >> y >> x;
   }
}
Neste exemplo, matriz é um array bidimensional. Ela tem número de elementos igual a ALTURAxLARGURA, sendo cada elemento do tipo int.

O exemplo abaixo preenche os elementos de um array bidimensional com os valores que representam a taboada e imprime a matriz.

//  Exemplo de array 2-D - taboada 

#include <iostream>
#include <iomanip>
using namespace std;

#define LIN 10
#define COL 10

int main()
{
  int x;                          //  numero da coluna 
  int y;                          //  numero da linha  
  int tabela[LIN] [COL];          //  tabela de taboada  
  
  //  preenche a tabela 
  
  for (y=0; y < LIN; y+=1)
    for(x=0; x < COL; x+=1)
      tabela[y][x] = y*x;
  
  cout << "\n         Tabela de Multiplicacao\n";
  
  //  Imprime o numero das colunas 
  
  cout << setw(6) << 0;
  for (x=1; x < COL; x+=1)
    cout << setw(3) << x;
  cout << endl;
  
  //  Imprime uma linha horizontal 
  cout << "   ";
  for (x=0; x < 3*COL; x+=1)
    cout << "-";
  cout << endl;
  
  //  Imprime as linhas da tablea.
  //  Cada linha a precedida pelo indice de linha e uma barra vertical 
  
  for (y=0; y < LIN; y+=1) {
    cout << setw(2) << y << "|";
    for(x=0; x < COL; x+=1)
      cout << setw(3) << tabela[y][x];
    cout << endl;
  }
}

A saída do programa é:

         Tabela de Multiplicacao
     0  1  2  3  4  5  6  7  8  9
   ------------------------------
 0|  0  0  0  0  0  0  0  0  0  0
 1|  0  1  2  3  4  5  6  7  8  9
 2|  0  2  4  6  8 10 12 14 16 18
 3|  0  3  6  9 12 15 18 21 24 27
 4|  0  4  8 12 16 20 24 28 32 36
 5|  0  5 10 15 20 25 30 35 40 45
 6|  0  6 12 18 24 30 36 42 48 54
 7|  0  7 14 21 28 35 42 49 56 63
 8|  0  8 16 24 32 40 48 56 64 72
 9|  0  9 18 27 36 45 54 63 72 81

14.1 Inicialização

Arrays multidimensionais podem ser inicializados usando listas aninhadas de elementos entre chaves. Por exemplo, um array bidimensional tabela com três linhas e duas colunas pode ser inicializado da seguinte forma:
double tabela[3][2] = { {1.0,  0.0},      //  linha 0 
                        {-7.8, 1.3},      //  linha 1 
                        {6.5,  0.0}       //  linha 2 
                      };
Quando o array é inicializado, o tamanho da primeira dimensão pode ser omitido. A definição de array abaixo é equivalente a dada anteriormente.
double tabela[][2] = { {1.0,  0.0},      //  linha 0 
                       {-7.8, 1.3},      //  linha 1 
                       {6.5,  0.0}       //  linha 2 
                     };

14.2 Arrays Multidimensionais - arrays de arrays

O formato da definição de um array de dimensão $k$, onde o número de elementos em cada dimensão é $n_0, n_1, \ldots,
n_{k-1}$, respectivamente, é:

\begin{displaymath}
nome\verb+_+tipo \ nome\verb+_+array[n_0][n_1]...[n_{k-1}];
\end{displaymath}

Isto define um array chamado $nome\_array$ consistindo de um total de $n_0\times n_1\times\ldots\times n_{k-1}$ elementos, sendo cada elemento do tipo $nome\verb+_+tipo$.

Arrays multidimensionais são armazenados de forma que o último subscrito varia mais rapidamente. Por exemplo, os elementos do array

int tabela[2][3];
são armazenados (em endereços consecutivos de memória) como
tabela[0][0], tabela[0][1], tabela[0][2], tabela[1][0], tabela[1][1], tabela[1][2].
Um array de dimensão k, onde o número de elementos em cada dimensão é $n_0,n_1,\ldots,\ldots,n_{k-1}$, respectivamente, pode ser imaginado como um array de dimensão $n_0$ cujos elementos são arrays de dimensão $k-1$.

Por exemplo, o array bidimensional tabela, com 20 elementos do tipo int

int tabela[4][5] = { {13, 15, 17, 19, 21},
                     {20, 22, 24, 26, 28},
                     {31, 33, 35, 37, 39},
                     {40, 42, 44, 46, 48} };
pode ser imaginado como um array unidimensional de 4 elementos do tipo int[], ou seja, arrays de int; cada um dos 4 elementos é um array de 5 elementos do tipo int:
tabela[0]  ---> {13, 15, 17, 19, 21}
tabela[1]  ---> {20, 22, 24, 26, 28}
tabela[2]  ---> {31, 33, 35, 37, 39}
tabela[3]  ---> {40, 42, 44, 46, 48}

14.3 Arrays Multidimensionais como argumento para funções

Quando o parâmetro formal de uma função é um array multidimensional (um array com dimensão maior que um), todas as dimensões deste array, exceto a primeira, precisa ser explicitamente especificada no cabeçalho e protótipo da função.

\begin{displaymath}
tipo\verb+_+do\verb+_+resultado \ \, nome\verb+_+da\verb+_+f...
...\,nome\verb+_+do\verb+_+array[\ ][n_1]...[n_{k-1}],... ...\, )
\end{displaymath}

Quando uma função com um parâmetro formal do tipo array é chamada, na chamada da função somente o nome do array é passado como parâmetro real. O tipo (e portanto a dimensão) do array passado como parâmetro real deve ser consistente com o tipo (e portanto a dimensão) do array que é o parâmetro formal. O programa abaixo mostra o exemplo da tabela de multiplicação escrita usando funções.

//  Exemplo de array 2-D - tabela de multiplicacao 

#include <iostream>
#include <iomanip>
using namespace std;

#define LIN 10
#define COL 10

void inicializa_arr (int arr[][COL], int);
void imprime_arr (int arr[][COL], int);

int main()
{
  int  tabela[LIN] [COL];   
  
  inicializa_arr(tabela, LIN);
  
  cout << "\n         Tabela de Multiplicacao\n";
  
  imprime_arr(tabela, LIN);
}

//  Inicializa o array com a tabela de multiplicacao 

void inicializa_arr (int arr[][COL], int nlin)
{
  int x;                          //  numero da coluna 
  int y;                          //  numero da linha     
  
  //  preenche o array 
  
  for (y=0; y < nlin; y++)
    for(x=0; x < COL; x++)
      arr[y][x] = y*x;
}

//  imprime um array LIN x COL 

void imprime_arr(int arr[][COL], int nlin)
{
  int x;                          //  numero da coluna 
  int y;                          //  numero da linha     
  
  //  imprime o numero das colunas 
  
  cout << setw(6) << 0;
  for (x=1; x < COL; x++)
    cout << setw(3) << x;
  cout << endl;
  
  
  //  imprime uma linha horizontal 
  cout << "   ";
  for (x=0; x < 3*COL; x++)
    cout << "_";
  cout << endl;
  
  //  imprime as linhas do array.  cada linha e' precedida
  //  pelo numero da linha e uma barra vertical 
  
  for (y=0; y < nlin; y++) {
    cout << setw(2) << y << "|";
    for(x=0; x < COL; x++)
      cout << setw(3) << arr[y][x];
    cout << endl;
  }
}

Outro exemplo com funçoes de manipulação de arrays bidimensionais:

//  funcoes com argumentos tipo array 2-D 

#include <iostream>
using namespace std;

#define ALTURA 7
#define LARGURA 7

void seleciona_elem    (char [][LARGURA], int);
void pontos       (char [][LARGURA], int);
void imprime_matriz  (char [][LARGURA], int);
void marca_triang (char [][LARGURA], int);
void flip       (char [][LARGURA], int);
void espera_entrada(void);

// *** DEFINICAO DE FUNCOES *******

//  funcao que imprime um array 2-D nlin X LARGURA 
void imprime_matriz(char matriz[][LARGURA], int nlin)
{
  int x,y;
  
  for(y=0; y<nlin; y+=1)
    {
      for(x=0; x<LARGURA; x+=1)
	cout <<  matriz[y][x] << " ";
      cout << endl << endl;
    }
  cout << endl;
}

//  funcao que preenche uma matriz nlin X LARGURA com pontos 
void pontos( char matriz[][LARGURA], int nlin)
{
  int x,y;
  
  for(y=0; y<nlin; y+=1)
    for(x=0; x<LARGURA; x+=1)
      matriz[y][x] = '.';
  
}

/*  funcao que preenche os elementos selecionados da matriz com um
 * quadrado e imprime a matriz
 */
void seleciona_elem(char matriz[][LARGURA], int nlin)
{
  int x, y;
  
  cout << "\nEntre com as coordenadas na forma \"y x\"." << endl;
  cout << "Use numeros negativos para terminar." << endl;
  
  cout << "Coordenadas: ";
  cin >> y >> x;    
  while (x >= 0 && y >= 0) 
  {
    matriz[y][x]='@';        // preenche o elemento com quadrado
    imprime_matriz(matriz, nlin);   // imprime a matriz
    cout << "Coordenadas: ";
    cin >> y >> x;    
  }
}

/*  funcao que marca todos os elementos abaixo da diagonal principal de
 * um array nlin X LARGURA com quadrados
 */
void marca_triang(char matriz[][LARGURA], int nlin)
{
  int x, y;
  
  cout << "Triangulo" << endl;
  pontos(matriz, nlin);
  for (y = 0; y < nlin; y+=1)
    for (x = 0; x <= y; x+=1)
      matriz[y][x] = '@';
}

//  funcao que rotaciona  ('flip') cada linha array tendo  o elemento da
//  diagonal principal como centro da rotação
void flip(char matriz[][LARGURA], int nlin)
{
  int x, y;
  int temp;
  
  cout << "Flip ao longo da diagonal principal." << endl;
  for (y = 0; y < nlin; y+=1)
    for (x = 0; x <= y; x+=1){
      temp = matriz[y][x];
      matriz[y][x] = matriz[x][y];
      matriz[x][y] = temp;
    }
}

//  funcao que espera ate que uma tecla qualquer seja digitada 
void pausar() {
  char c;
  cin.get(c);
}

// ********* MAIN ***********

//  alguns exemplos de chamadas de funcoes com argumentos array 2-D 
int main()
{
  char matriz [ALTURA] [LARGURA];
  
  pontos(matriz, ALTURA);
  seleciona_elem(matriz, ALTURA);
  pausar();
  
  flip(matriz, ALTURA);
  imprime_matriz(matriz,ALTURA);
  pausar();
  
  marca_triang( matriz, ALTURA);
  imprime_matriz( matriz, ALTURA);
  pausar();
  
  flip( matriz, ALTURA);
  imprime_matriz(matriz, ALTURA);
  pausar();
}


Créditos: Documento produzido pelo Prof. Armando L.N. Delgado (DINF/ET/UFPR), baseado em revisão sobre material de Prof. Carmem Hara e Prof. Wagner Zola (DINF/ET/UFPR).

Esta obra está licenciada com uma Licença Creative Commons Atribuição-NãoComercial-CompartilhaIgual 4.0 Internacional.  Licença Creative Commons

Armando Luiz Nicolini Delgado
2020-10-20