Linguagem C: Vetores e Matrizes
Links relacionados: Programação em C
Ponteiros e Arrays
Ponteiros são muito utilizados para a navegação de arrays, principalmente de arrays alocados de maneira dinâmica. A idéia geral é alocar o array usando ou o método estático ou o dinâmico e então criar uma variável do tipo ponteiro que apontará para a primeira posição do ponteiro. Utilizando aritmética de ponteiros (incremento, decremento, saltos) é possível percorrer o array sem ter que se preocupar com quantos bytes devem ser acessados, pois a tipagem do ponteiro cuidará deste detalhe.
É importante ressaltar que a utilização de ponteiros para indexação de arrays apresenta um risco intrínseco. Como C não é uma linguagem fortemente tipada, arrays não possuem um marcador de fim de alocação de memória tal como acontece em PASCAL. Ponteiros permitirão que a memória continue sendo acessada sequencialmente mesmo após o final da área previamente alocada para o array tenha sido toda percorrida.
Aritmética de Ponteiros
Uma das grandes vantagens decorrentes da utilização de ponteiros é a possibilidade de indexar posições de memória de maneira fácil e intuitiva. Tal endereçamento é alcançado a partir de operações aritméticas simples que tem como objetos variáveis do tipo ponteiro.
Operandos unários:
- ++ incremento unitário;
- -- decremento unitário.
Suponha que p é um ponteiro do tipo inteiro e suponha que o tipo inteiro na arquitetura de destino do exemplo sejam representados por 2 bytes cada. Considere o seguinte trecho de código:
1int vet[10];
2int *iptr;
3iptr = vet;
4iptr++;
Exemplo 4 – navegação de arrays usando ponteiros
Assumindo que o array “vet” seja alocado pelo “loader” do sistema operacional iniciando na posição 00H, iptr erá apontar para a posição 00H inicialmente. Ao se executar a operação iptr++, o endereço apontado por iptr será incrementado em uma unidade, o que corresponderá, dado o fato de que inteiros são representados por dois bytes, ao endereço 02H. (veja figura1 para exemplo)
Exemplo Estático
1#include <stdio.h>
2
3#define SIZE 3
4
5void main() {
6 int i, valor[SIZE];
7 printf("Entre com %d valores inteiros...\n", SIZE);
8 for (i = 0; i < SIZE; i++) {
9 printf("Valor %d: ", i);
10 scanf("%d", &valor[i]);
11 }
12 printf("Os valores entrados foram: ");
13 for (i = 0; i < SIZE; i++) {
14 printf("%d ", valor[i]);
15 }
16 printf("\n");
17}
Exemplo vetor de duas dimensões
1#include <stdio.h>
2
3int jogo[3][3];
4
5void mostrar() {
6 int linha, coluna;
7 for (linha = 0; linha < 3; linha++) {
8 for (coluna = 0; coluna < 3; coluna++) {
9 printf("%5d ", jogo[linha][coluna]);
10 }
11 printf("\n");
12 }
13}
14
15void ler() {
16 printf("Entre com a linha, a coluna e o valor: ");
17 int l, c, v;
18 scanf("%d %d %d", &l, &c, &v);
19 jogo[l][c] = v;
20}
21
22int main() {
23 for(;;) {
24 mostrar();
25 ler();
26 }
27}
Exemplo Dinâmico
1#include <stdio.h>
2#include <stdlib.h>
3
4#define SIZE 10
5
6int main() {
7 int *iptr = (int*) malloc(SIZE * sizeof(int));
8 int i;
9 for (i = 0; i < SIZE; i++) {
10 iptr[i] = i * 10;
11 }
12 for (i = 0; i < SIZE; i++) {
13 printf("Elemento %d = %d\n", i, iptr[i]);
14 }
15 return 0;
16}
Alocação de vetores de Strings
1#include <stdio.h>
2#include <stdlib.h>
3
4#define SIZE 2
5
6int main() {
7 int i;
8 // Vetor estatico de strings estaticas
9 char vet1[SIZE][255] = { "Estatico-0", "Estatico-1" };
10 for (i = 0; i < SIZE; i++) {
11 printf("%s\n", vet1[i]);
12 }
13
14 // Vetor dinamico de strings dinamicas
15 char **vet;
16 vet = (char**) malloc (SIZE * sizeof(char*));
17 for (i = 0; i < SIZE; i++) {
18 vet[i] = malloc (255 * sizeof(char));
19 sprintf(vet[i], "Dinamico-%d", i);
20 }
21 for (i = 0; i < SIZE; i++) {
22 printf("%s\n", vet[i]);
23 }
24}
Exercícios
1. Qual será a saída do programa supondo que i ocupa o endereço 4094H na memória?
1int main( void ) {
2 int i=5, *p;
3 p=&i;
4 printf(“%d %d %d %d %d\n”, p, *p+2, **&p, 3**p, **&p+4);
5}
2. Assumindo que Pulo[] é um array do tipo int, quais das seguintes expressões referenciam o valor do terceiro elemento do array?
a) *(pulo+2)
b) *(pulo+4)
c) pulo+4
d) pulo+2
3. Suponha a declaração:
1int mat[4], *p, x;
Quais das expressões abaixo são válidas? Justifique:
a) p = mat+1;
b) p = mat++;
c) p = ++mat;
d) x = (*mat)++;
4. Explique a diferença entre os comandos abaixo: (assuma que p é um ponteiro do tipo int)
a) p++;
b) (*p)++;
c) *(p++);
5. Faça programas em C para resolver os seguintes problemas:
a) Somar a diagonal principal da matriz.
b) Mostrar o maior valor de cada linha
c) Criar a matriz transposta
d) Verificar se uma matriz é simétrica
e) Considerando uma matriz de notas com 10 linhas (uma para cada aluno) e 3 colunas (uma para cada prova), imprimir a tabela com a média de cada aluno, a média de cada prova e a média geral da turma.