Matrizes. Parte II (funções/alocação)
Autor: Edson JR | Publicado: 2010-01-09T17:15:00-02:00

Continuando nossa série sobre matrizes, hoje vamos ver algumas operações básicas com matrizes.Matrizes x FunçõesPor serem intimamente relacionadas com os vetores, a operações entre matrizes e funções é praticamente idêntica, salvo o fato de termos uma (ou muitas) dimensão(ões) a mais.Vamos ao código e você vai entender.#include &lt;stdio.h&gt;#include &lt;stdlib.h&gt;&nbsp;const int LINHAS = 2;const int COLUNAS = 2;&nbsp;void preenche_mat_int(int [2][2]);void exibe_mat_int(int [][2]);&nbsp;int main(){&nbsp;int matriz[2][2];&nbsp; &nbsp;preenche_mat_int(matriz);&nbsp;exibe_mat_int(matriz);&nbsp;system(&quot;pause&quot;);}&nbsp; int ler_int(){&nbsp;int digitado;&nbsp; &nbsp;printf(&quot;Digite um valor inteiro: &quot;);&nbsp;scanf(&quot;%d&quot;,&amp;digitado);&nbsp;return digitado;}&nbsp; void mostra_int(int num){&nbsp;printf(&quot;%d &quot;,num);}&nbsp;void preenche_mat_int(int mat[2][2]){&nbsp;int i, j;&nbsp; &nbsp;printf(&quot;\nPREENCHENDO A MATRIZ:\n&quot;);&nbsp;for(i = 0; i &lt; LINHAS; i++)&nbsp;&nbsp;&nbsp;&nbsp;for(j = 0; j &lt; COLUNAS; j++)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mat[i][j] = ler_int();}&nbsp; void exibe_mat_int(int mat[][2]){&nbsp;int i, j;&nbsp; &nbsp;printf(&quot;\n&quot;);&nbsp;for(i = 0; i &lt; LINHAS; i++){&nbsp;&nbsp;&nbsp;&nbsp;for(j = 0; j &lt; COLUNAS; j++)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mostra_int(mat[i][j]);&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;\n&quot;);&nbsp;}       &nbsp;printf(&quot;\n\n&quot;);}O código acima tem bastante novidade!A 1a delas é o uso de protótipos de função. Eu já deveria ter falado sobre eles, quando falei sobre funções (aqui), mas nunca é tarde (rsrs).Faça sem saber como.Em todos os códigos que vimos até agora usando funções, sempre criamos as funções antes de chamá-las na main. O código da nossa função main era sempre o último e, assim, as funções já eram 'conhecidas' dela.No entanto é possível criar a main antes das outras funções. O único requisito é informar como essas funções serão chamadas, quais o seus retornos e parâmetros.Esta é a função dos protótipos. Eles se parecem com o cabeçalho das funções, exceto que o nome dos parâmetros pode ser omitido.A 2a novidade, que já aparece nos protótipos, é a forma de passar uma matriz para uma função. Deve ser informado o tipo de dados contido na matriz e o tamanho de suas dimensões. O tamanho da 1a dimensão pode ser omitido, somente da 1a. Se a matriz tiver 3 dimensões, por exemplo, o tamanho das 2a e 3a dimensões tem que ser informado.A última é a forma de 'varrer' a matriz. Usamos um for para 'varrer' as linhas e, dentro dele, um outro for para 'varrer' todas as colunas desta linha antes de passar para a próxima. Por isso a necessidade de saber quantas linhas e colunas a matriz tem.Como as dimensões da matriz já são conhecidas é uma ótima prática criar constantes globais que armazenem estes valores, o que facilita o acesso a elas em qualquer parte do programa.Funções x MatrizesDa mesma forma que um vetor pode ser alocado dinâmicamente, uma matriz também pode ser. Observe o código abaixo:#include &lt;stdio.h&gt;#include &lt;stdlib.h&gt;&nbsp; int ler_int(){&nbsp;int digitado;&nbsp; &nbsp;printf(&quot;Digite um valor inteiro: &quot;);&nbsp;scanf(&quot;%d&quot;,&amp;digitado);&nbsp;return digitado;}&nbsp; void mostra_int(int num){&nbsp;printf(&quot;%d &quot;,num);}&nbsp; int* preenche_mat_int(int linhas, int colunas){&nbsp;int *mat=0, i, j;&nbsp; &nbsp;if ((linhas * colunas) &gt; 0)&nbsp;&nbsp;&nbsp;&nbsp;mat = (int *) malloc (linhas * colunas * sizeof(int));&nbsp;if (mat){&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;\nPREENCHENDO A MATRIZ:\n&quot;);&nbsp;&nbsp;&nbsp;&nbsp;for(i = 0; i &lt; linhas; i++)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(j = 0; j &lt; colunas; j++)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*(mat + (i * colunas) + j) = ler_int();&nbsp;}&nbsp;else&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;NAO FOI POSSIVEL ALOCAR A MATRIZ!!!\n&quot;);&nbsp;return mat;               }&nbsp;void exibe_mat_int(int* mat, int linhas, int colunas){&nbsp;int i, j;&nbsp; &nbsp;printf(&quot;\n&quot;);&nbsp;for(i = 0; i &lt; linhas; i++){&nbsp;&nbsp;&nbsp;&nbsp;for(j = 0; j &lt; colunas; j++)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mostra_int(*(mat + (i * colunas) + j));&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;\n&quot;);&nbsp;}       &nbsp;printf(&quot;\n\n&quot;);}&nbsp; int main(){&nbsp;int *matriz, linhas, colunas;&nbsp; &nbsp;printf(&quot;Digite o numero de linhas da matriz (maior que zero):\n&quot;);&nbsp;linhas = ler_int();&nbsp;printf(&quot;Digite o numero de colunas da matriz(maior que zero):\n&quot;);&nbsp;colunas = ler_int();&nbsp;matriz = preenche_mat_int(linhas, colunas);&nbsp;if(matriz){&nbsp;&nbsp;&nbsp;&nbsp;exibe_mat_int(matriz, linhas, colunas);&nbsp;&nbsp;&nbsp;&nbsp;free(matriz);&nbsp;}   &nbsp;system(&quot;pause&quot;);}A diferença básica neste código é a permitir ao usuário que defina o número de linhas e colunas da matriz, por isto não pudemos armazenar estes valores em constantes globais (observe que tivemos que passar estes valores para todas as funções). Uma vez definidas, linhas e colunas, verificamos se os valores informados foram válidos e, alocamos espaço para a matriz.Como o bloco de memória alocado não foi definido como uma matriz, ele não pode ser indexado como uma, usando os []. A solução para isso é o uso de ponteiros e da aritmética de ponteiros.A linha 25 mostra como isto é feito. Observe a multiplicação de i, que contém o número da linha atual, pela quantidade de colunas. Dá pra entender o porquê, certo?Por hoje é isto. Até o próximo post.