Subsecções

19 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 <stdio.h>       

#define ALTURA 5
#define LARGURA 5

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

   /* preenche a matriz com zeros  */
   y = 0;
   while(y < ALTURA)
   {
     x = 0;
     while(x < LARGURA)
     {
        matriz[y][x] = 0;
        x+=1;
     }
     y+=1;
   }

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

   printf("\nEntre coordenadas na forma y,x (2,4).\n");
   printf("Use valores negativos para sair do programa.\n");

   printf("Coordenadas: ");
   scanf("%d,%d", &y, &x);    

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

      y = 0;
      while (y < ALTURA)   /* imprime o array todo */
      {
        x = 0;
        while (x < LARGURA)
        {
             printf("%d ", matriz[y][x] );
             x += 1;
        }
        printf("\n\n");
        y += 1;
      }

      printf("\n");
      printf("Coordenadas: ");
      scanf("%d,%d", &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.

ATENÇÃO: a partir daqui os exemplos usam a estrutura de controle for. Veja a explicação sobre esta estrutura (uma variação do while()) na Seção 15.1.

/* Exemplo de array 2-D - taboada */

#include <stdio.h>

#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;
  
  printf("\n         Tabela de Multiplicacao\n");
  
  /* Imprime o numero das colunas */
  
  printf("%6d", 0);
  for (x=1; x < COL; x+=1)
    printf("%3d", x);
  printf("\n");
  
  /* Imprime uma linha horizontal */
  printf("   ");
  for (x=0; x < 3*COL; x+=1)
    printf("-");
  printf("\n");
  
  /* Imprime as linhas da tablea.
     Cada linha a precedida pelo indice de linha e uma barra vertical */
  
  for (y=0; y < LIN; y+=1) {
    printf("%2d|", y);
    for(x=0; x < COL; x+=1)
      printf("%3d", tabela[y][x]);
    printf("\n");
  }
  
}

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

19.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 */
                     };

19.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}

19.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 <stdio.h>
#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);

   printf("\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+=1)
       for(x=0; x < COL; x+=1)
           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 */

   printf("%6d", 0);
   for (x=1; x < COL; x+=1)
       printf("%3d", x);
   printf("\n");


   /* imprime uma linha horizontal */
   printf("   ");
   for (x=0; x < 3*COL; x+=1)
       printf("_");
   printf("\n");

   /* imprime as linhas do array.  cada linha e' precedida
      pelo numero da linha e uma barra vertical */
    
   for (y=0; y < nlin; y+=1) {
       printf("%2d|", y);
       for(x=0; x < COL; x+=1)
           printf("%3d", arr[y][x]);
       printf("\n");
   }
}

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

/* funcoes com argumentos tipo array 2-D */

#include <stdio.h>       
#define ALTURA 5
#define LARGURA 5

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

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

/* funcao que preenche uma matriz nlin X LARGURA com pontos */
void pontos( int 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(int matriz[][LARGURA], int nlin)
{
   int x, y;

   printf("\nEntre com as coordenadas na forma y,x (2,4).\n");
   printf("Use numeros negativos para terminar.\n");

   while (1)              
      {
      printf("Coordenadas: ");
      scanf("%d,%d", &y, &x);    
      if (x >= 0 && y >= 0)
         {
         matriz[y][x]='\xB1';            /* preenche o elemento com quadrado */
         imprime_matriz(matriz, nlin);   /* imprime a matriz */
         }
      else
         break;
      }  
 }

/* funcao que marca todos os elementos abaixo da diagonal principal de
 * um array nlin X LARGURA com quadrados
 */
void marca_triang(int matriz[][LARGURA], int nlin)
{
  int x, y;

  printf("Triangulo\n");
  pontos(matriz, nlin);
  for (y = 0; y < nlin; y+=1)
    for (x = 0; x <= y; x+=1)
      matriz[y][x] = '\xB1';
}

/* funcao que imprime um array 2-D nlin X LARGURA */
void imprime_matriz(int matriz[][LARGURA], int nlin)
{
  int x,y;

  for(y=0; y<nlin; y+=1)
	{
	for(x=0; x<LARGURA; x+=1)
	   printf("%c ", matriz[y][x] );
	printf("\n\n");
	}
  printf("\n");
}

/* funcao que flipa um array ao longo da diagonal principal */
void flip(int matriz[][LARGURA], int nlin)
{
  int x, y;
  int temp;

  printf("Flipado ao longo da diagonal principal.\n");
  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 seja digitada */
void espera_entrada( void ) {
   getchar(); }

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

/* alguns exemplos de chamadas de funcoes com argumentos array 2-D */
int main()
{
   int matriz [ALTURA] [LARGURA];

   pontos(matriz, ALTURA);
   seleciona_elem(matriz, ALTURA);
   espera_entrada();

   flip(matriz, ALTURA);
   imprime_matriz(matriz,ALTURA);
   espera_entrada();

   marca_triang( matriz, ALTURA);
   imprime_matriz( matriz, ALTURA);
   espera_entrada();

   flip( matriz, ALTURA);
   imprime_matriz(matriz, ALTURA);
   espera_entrada();
}

Armando Luiz Nicolini Delgado
2013-10-21