Arranjos: parâmetros, matrizes. David Déharbe 1 1
Roteiro da aula Ponteiros e arranjos; Arranjos e parâmetros; Sub-rotinas para arranjos de tamanho qualquer. 2 2
Ponteiros e arranjos Um arranjo é um bloco de memória que pode armazenar uma certa quantidade (chamada capacidade) de valores de um certo tipo. Todos os valores estão armazenados em compartimentos vizinhos da memória. O endereço do arranjo é o endereço do primeiro elemento do arranjo. o arranjo não armazena outra informação que os elementos em particular não armazena a sua capacidade, ou o tamanho da representação dos seus elementos. As sub-rotinas que tem arranjo como parâmetros recebem o endereço do primeiro elemento Isto expliqua porque sub-rotinas alteram diretamente os arranjos. 3 3
Exemplo #include <stdio.h> int main() int v[5] = 0 ; for (i = 0; i < 5; ++i) printf("v[%i] - %p %i\n", i, &v[i], v[i]); return 0; 4 4
Exemplo #include <stdio.h> int main() int v[5] = 0 ; for (i = 0; i < 5; ++i) bash-3.2$./ex9 printf("v[%i] - %p %i\n", i, &v[i], v[i]); v[0] - 0x7fff5fbff260 0 return 0; v[1] - 0x7fff5fbff264 0 v[2] - 0x7fff5fbff268 0 v[3] - 0x7fff5fbff26c 0 v[4] - 0x7fff5fbff270 0 4 4
Exemplo #include <stdio.h> int main() int v[5] = 0 ; for (i = 0; i < 5; ++i) printf("v[%i] - %p %i\n", i, &v[i], v[i]); printf("v - %p\n", &v); return 0; 5 5
Exemplo #include <stdio.h> int main() int v[5] = 0 ; for (i = 0; i < 5; ++i) bash-3.2$./ex10 printf("v[%i] - %p %i\n", i, &v[i], v[i]); printf("v - %p\n", &v); return 0; v[0] - 0x7fff5fbff260 0 v[1] - 0x7fff5fbff264 0 v[2] - 0x7fff5fbff268 0 v[3] - 0x7fff5fbff26c 0 v[4] - 0x7fff5fbff270 0 v - 0x7fff5fbff260 5 5
Exemplo #include <stdlib.h> #include <stdio.h> void incrementa_arranjo (int v[4]) for (i = 0; i < 4; ++i) v[i] += 1; void imprime_arranjo(int v[4]) for (i = 0; i < 4; ++i) printf("v[%i] = %i\n", i, v[i]); int main (void) int v[4] = 0, 1, 2, 3 ; imprime_arranjo(v); incrementa_arranjo(v); imprime_arranjo(v); return 0; 6 6
Exemplo #include <stdlib.h> #include <stdio.h> void incrementa_arranjo (int v[4]) for (i = 0; i < 4; ++i) v[i] += 1; void imprime_arranjo(int v[4]) for (i = 0; i < 4; ++i) printf("v[%i] = %i\n", i, v[i]); int main (void) int v[4] = 0, 1, 2, 3 ; imprime_arranjo(v); incrementa_arranjo(v); imprime_arranjo(v); return 0; bash-3.2$./ex3 v[0] = 0 v[1] = 1 v[2] = 2 v[3] = 3 v[0] = 1 v[1] = 2 v[2] = 6 3 v[3] = 4 6
Exemplo #include <stdio.h> void f(int w[5]) for (i = 0; i < 5; ++i) printf("w[%i] - %p %i\n", i, &w[i], w[i]); int main() int v[5] = 2, 3, 5, 7, 11 ; for (i = 0; i < 5; ++i) printf("v[%i] - %p %i\n", i, &v[i], v[i]); f(v); return 0; 7 7
Exemplo #include <stdio.h> void f(int w[5]) for (i = 0; i < 5; ++i) printf("w[%i] - %p %i\n", i, &w[i], w[i]); int main() int v[5] = 2, 3, 5, 7, 11 ; bash-3.2$./ex9b for (i = 0; i < 5; ++i) v[0] - 0x7fff5fbff260 2 printf("v[%i] - %p %i\n", i, &v[i], v[i]); f(v); return 0; v[1] - 0x7fff5fbff264 3 v[2] - 0x7fff5fbff268 5 v[3] - 0x7fff5fbff26c 7 v[4] - 0x7fff5fbff270 11 w[0] - 0x7fff5fbff260 2 w[1] - 0x7fff5fbff264 3 w[2] - 7 0x7fff5fbff268 5 w[3] - 0x7fff5fbff26c 7 w[4] - 0x7fff5fbff270 11 7
Exercício Suponha que v é um arranjo e p é um apontador. Considere que a atribuição p = v; foi realizada previamente. Quais das expressões abaixo não são permitidas? Das restantes, quais têm valor verdadeiro? p == v[0] p == &v[0] *p == v[0] 8 8
Exercício Suponha que v é um arranjo e p é um apontador. Considere que a atribuição p = v; foi realizada previamente. Quais das expressões abaixo não são permitidas? Das restantes, quais têm valor verdadeiro? p == v[0]» Erro de tipagem p == &v[0] *p == v[0] 8 8
Exercício Suponha que v é um arranjo e p é um apontador. Considere que a atribuição p = v; foi realizada previamente. Quais das expressões abaixo não são permitidas? Das restantes, quais têm valor verdadeiro? p == v[0] p == &v[0] *p == v[0]» Erro de tipagem» Ok - verdadeiro 8 8
Exercício Suponha que v é um arranjo e p é um apontador. Considere que a atribuição p = v; foi realizada previamente. Quais das expressões abaixo não são permitidas? Das restantes, quais têm valor verdadeiro? p == v[0] p == &v[0] *p == v[0]» Erro de tipagem» Ok - verdadeiro» Ok - verdadeiro 8 8
Exercício motivador Escreva uma função que tem como parâmetro um arranjo de 1000 ints, digamos a, e inverte o conteúdo do arranjo: ou seja o primeiro e último são trocados, o segundo e penúltimo são trocados, etc. interface: void inverte_arranjo (int a[1000]); Escreva um programa que lê 1000 inteiros, digamos a, e imprime eles em ordem inversa. O programa deve usar a função inverte_arranjo. Escreva um programa que lê um número, digamos n, seguido de uma linha com n inteiros i1... in e imprime eles em ordem inversa in...i1. Porque não pode mais usar a função inverte_arranjo? 9 9
Arranjos como parâmetros (c99) Podemos definir uma sub-rotina que tem como parâmetro um arranjo de qualquer tamanho. O arranjo O tamanho do arranjo Exemplo: /* definicao */ void incrementa_arranjo (int a[], int n) for (i = 0; i < n; i = i + 1) a[i] = a[i]+1; /* chamada */ int v[1000] = 0 ; incrementa_arranjo(v, 1000); 10 10
Exemplo #include <stdlib.h> #include <stdio.h> void incrementa_arranjo (int v[], int n) for (i = 0; i < n; ++i) v[i] += 1; void imprime_arranjo(int v[], int n) for (i = 0; i < n; ++i) printf("v[%i] = %i\n", i, v[i]); int main (void) int v[4] = 0, 1, 2, 3 ; imprime_arranjo(v, n); incrementa_arranjo(v, n); imprime_arranjo(v, n); return 0; 11 11
Exemplo #include <stdlib.h> #include <stdio.h> void incrementa_arranjo (int v[], int n) for (i = 0; i < n; ++i) v[i] += 1; void imprime_arranjo(int v[], int n) for (i = 0; i < n; ++i) printf("v[%i] = %i\n", i, v[i]); int main (void) int v[4] = 0, 1, 2, 3 ; imprime_arranjo(v, n); incrementa_arranjo(v, n); imprime_arranjo(v, n); return 0; bash-3.2$./ex4 v[0] = 0 v[1] = 1 v[2] = 2 v[3] = 3 v[0] = 1 v[1] = 2 v[2] = 11 3 v[3] = 4 11
Arranjos como parâmetros: exemplo motivador void inverte_arranjo_1000 (float a[1000]) int i, j; for (i = 0, j = 999; i < j; ++i, --j) float tmp = a[i]; a[i] = a[j]; a[j] = tmp; void inverte_arranjo (float a[], int size) int i, j; for (i = 0, j = size - 1; i < j; ++i, --j) float tmp = a[i]; a[i] = a[j]; a[j] = tmp; 12 12
Arranjos como parâmetros: passagem por referência Quando uma sub-rotina tem um arranjo como parâmetro, é o arranjo passado como parâmetro efetivo que é acessado dentro da função. Passagem de parâmetro por referência. Passagem de parâmetro por valor. = Passagem de parâmetro por valor do endereço. 13 13
Exercício para pensar Escrever uma sub-rotina que calcula a soma de dois arranjos, digamos U e V, de mesmo tamanho, de valores do tipo float. 14 14
Questão em aberto Como escrever uma rotina que tem como resultado um novo arranjo? módulo 3 da disciplina: alocação dinâmica de memória. 15 15
Exercício Escreva uma sub-rotina com a seguinte interface: void soma_arr (int n, float u[], float v[], float w[]); Tem como parâmetros: um inteiro n, três arranjos u e v e w de floats, tais que: n é a capacidade dos arranjos u, v e w. A sub-rotina deve guardar na posição i de w a soma dos elementos nas posições i de u e v. 16 16
Exercícios Escreva uma sub-rotina que tem como parâmetro um arranjo de floats e retorna a soma dos elementos do arranjo. Escreva uma sub-rotina que tem como parâmetro um arranjo de floats e retorna o maior deles. Escreva uma sub-rotina que tem como parâmetros um arranjo a de doubles e um double i, e retorna 1 se i é elemento de a, e 0 caso contrário. Escreva uma sub-rotina que tem como parâmetros um arranjo a de doubles e retorna 1 se os valores de a estão em ordem estritamente crescente, e 0 caso contrário. Escreva uma sub-rotina que tem como parâmetros um arranjo a de doubles e retorna o tamanho da maior subsequência estritamente crescente de a. 17 17