Arranjos:
parâmetros, matrizes.
David Déharbe
Ponteiros e arranjos;
•Arranjos e parâmetros;
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.
#include <stdio.h> int main() { int v[5] = { 0 }; int i; for (i = 0; i < 5; ++i)
printf("v[%i] - %p %i\n", i, &v[i], v[i]); return 0;
4 #include <stdio.h> int main() { int v[5] = { 0 }; int i; for (i = 0; i < 5; ++i)
printf("v[%i] - %p %i\n", i, &v[i], v[i]); return 0; } bash-3.2$ ./ex9 v[0] - 0x7fff5fbff260 0 v[1] - 0x7fff5fbff264 0 v[2] - 0x7fff5fbff268 0 v[3] - 0x7fff5fbff26c 0 v[4] - 0x7fff5fbff270 0
#include <stdio.h> int main() { int v[5] = { 0 }; int i; 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 #include <stdio.h> int main() { int v[5] = { 0 }; int i; for (i = 0; i < 5; ++i)
printf("v[%i] - %p %i\n", i, &v[i], v[i]);
printf("v - %p\n", &v); return 0; } bash-3.2$ ./ex10 v[0] - 0x7fff5fbff260 0 v[1] - 0x7fff5fbff264 0 v[2] - 0x7fff5fbff268 0 v[3] - 0x7fff5fbff26c 0 v[4] - 0x7fff5fbff270 0 v - 0x7fff5fbff260
#include <stdlib.h> #include <stdio.h>
void incrementa_arranjo (int v[4]) { int i;
for (i = 0; i < 4; ++i) v[i] += 1; }
void imprime_arranjo(int v[4]) { int i;
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
#include <stdlib.h> #include <stdio.h>
void incrementa_arranjo (int v[4]) { int i;
for (i = 0; i < 4; ++i) v[i] += 1; }
void imprime_arranjo(int v[4]) { int i;
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] = 3 v[3] = 4
#include <stdio.h> void f(int w[5]) {
int i;
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 }; int i; for (i = 0; i < 5; ++i)
printf("v[%i] - %p %i\n", i, &v[i], v[i]); f(v);
return 0; }
7 #include <stdio.h> void f(int w[5]) { int i; 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 }; int i; for (i = 0; i < 5; ++i)
printf("v[%i] - %p %i\n", i, &v[i], v[i]); f(v); return 0; } bash-3.2$ ./ex9b v[0] - 0x7fff5fbff260 2 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] - 0x7fff5fbff268 5 w[3] - 0x7fff5fbff26c 7 w[4] - 0x7fff5fbff270 11
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]
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 » Erro de tipagem
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
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 » Erro de tipagem » Ok - verdadeiro » Ok - verdadeiro
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.
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) { int i; for (i = 0; i < n; i = i + 1) a[i] = a[i]+1; } /* chamada */ int v[1000] = { 0 }; incrementa_arranjo(v, 1000); 10
#include <stdlib.h> #include <stdio.h>
void incrementa_arranjo (int v[], int n) { int i;
for (i = 0; i < n; ++i) v[i] += 1; }
void imprime_arranjo(int v[], int n) { int i;
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
#include <stdlib.h> #include <stdio.h>
void incrementa_arranjo (int v[], int n) { int i;
for (i = 0; i < n; ++i) v[i] += 1; }
void imprime_arranjo(int v[], int n) { int i;
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] = 3 v[3] = 4
{ 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];
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.
Escrever uma sub-rotina que calcula a soma de dois arranjos, digamos U e V, de mesmo tamanho, de valores do tipo float.
Como escrever uma rotina que tem como resultado um novo arranjo?
‣ módulo 3 da disciplina: alocação dinâmica de memória.
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
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.