Baixe o app para aproveitar ainda mais
Prévia do material em texto
02/03/2013 Laboratório de Programação I VARIÁVEIS COMPOSTAS HOMOGÊNEAS (Vetores e Matrizes) 02/03/2013 Jair Alves Barbosa 02/03/2013 Um vetor (ou matriz) é um conjunto de posições de armazenamento de dados do mesmo tipo. Cada posição de armazenamento é chamado de elemento da matriz (ou do vetor). No conteúdo deste material estará apresentando-se esta estrutura com o termo matriz, apesar da tradução de array , em algumas obras, aparecerem como vetor. Na declaração de uma matriz escreve-se o tipo, seguido do nome (identificador) e o tamanho da matriz (número de elementos que ela contém) entre os colchetes ([ ]). <tipo de dado> <identificador> [<quantidade de elementos>] Exemplo: float valor[10]; Vetores e Matrizes 02/03/2013 TERMINOLOGIA: Vetores e Matrizes As duas expressões (vetor e matriz) são sinônimos para alguns casos, onde estes casos são diferenciados por uma outra expressão que complementa e diferencia uma matriz de um vetor especificamente. Esta outra expressão referencia a quantidade de dimensões que esta matriz possui. Dimensão será abordado mais a frente nesta aula, mas por enquanto: • expressão vetor: referencia sempre uma matriz com uma única dimensão (unidimensional); • expressão matriz: referencia uma matriz com uma ou mais dimensões, sendo identificada corretamente pelas expressões: – Unidimensional: somente uma dimensão – prateleiras de uma estante simples de aço – Multidimensional: mais que uma dimensão – tabuleiro de xadrez (2 dimensões) 02/03/2013 Vetores e Matrizes Observe o exemplo a seguir: int teste[25]; Neste exemplo, declara-se uma matriz unidimensional (ou vetor) de 25 inteiros com o nome de TESTE, onde o compilador reservará um espaço, em memória contígua, suficiente para conter estes 25 elementos da matriz. A memória contígua significa que os dados serão armazenados em seqüência contínua (um seguido do outro). 02/03/2013 3 MATRIZ No exemplo anterior tem-se 25 elementos declarados na matriz, porém a sua representação para cada um deles vai ser de zero (0) a vinte e quatro (24), contendo assim 25 elementos. Esta representação para cada elemento consiste em um índice que permite manipular todos os elementos da matriz. A alimentação de uma matriz é feita por meio da atribuição de valores compatíveis com o seu tipo, estipulado em sua declaração. Cada elemento recebe um valor por meio do seu nome e índice (ou posição). 2 1 0 vetor Para acessar cada elemento de uma matriz faz-se referência a um deslocamento do nome da matriz. O principal cuidado que se deve ter é que a primeira posição de um elemento é a posição zero (0), ou seja, uma matriz é iniciada no elemento zero. 02/03/2013 MATRIZ Exemplo: #include<stdio.h> #include<conio.c> int main (void) { int x,vetor[5]; // Armazenando valores na matriz for(x=0; x<5; x++) { printf("Matriz [%d] = ",x+1); scanf("%d",&vetor[x]); } printf("\n Matriz\n\n"); // Apresentando os valores armazenados for(x=0; x<5; x++) printf("Posicao %d =%3d\n",x+1, vetor[x]); getch(); return 0; } Saída em tela Matriz [1] = 1 Matriz [2] = 2 Matriz [3] = 3 Matriz [4] = 4 Matriz [5] = 5 Matriz Posicao 1 = 1 Posicao 2 = 2 Posicao 3 = 3 Posicao 4 = 4 Posicao 5 = 5 02/03/2013 MATRIZ A declaração de matrizes diferencia-se da declaração de variáveis comuns pelo uso dos colchetes (‘[ ]’) preenchidos com números inteiros. Este número entre os colchetes indica o tamanho da matriz. Os valores dentro dos colchetes são diferentes de acordo com o contexto que estão sendo empregados. O primeiro é a declaração das variáveis, que indica o tamanho da matriz. O segundo é a referência de um elemento específico dentro da matriz. int nota[5] nota[3] 7 5 3 8 9 NOTA 0 1 2 3 4 cria uma matriz de cinco elementos posiciona no elemento três que é o quarto na matriz 02/03/2013 MATRIZ A declaração e a referência a um elemento demonstram situações diferentes, pois a declaração apresenta a quantidade de elementos que uma matriz terá, enquanto que a referência apresenta o número do índice da matriz que se deseja o elemento int nota[5]; declaração da matriz de cinco valores nota[3] referência ao elemento 3 que é o quarto valor na matriz A solicitação de gravação de um elemento, além da matriz declarada, pode provocar conseqüências inesperadas, pois o compilador calcula a posição de memória onde este elemento seria armazenado e grava-o. No caso do exemplo anterior, suponha que seja informado o sexto valor (nota[5]) mantendo a declaração de somente cinco elementos nesta matriz. 02/03/2013 MATRIZ O compilador multiplica o deslocamento (5) pelo tamanho de cada elemento (2 bytes no exemplo). Então ele passa por todos os bytes desde o início da matriz e grava o novo valor na posição calculada. Não é verificado o tamanho máximo da matriz e o compilador grava baseado em seus cálculos, não importando sobre o que ele vai estar gravando, mas sobrepõe os valores. 02/03/2013 MATRIZ Exemplo: #include <stdio.h> #include<conio.c> int main (void) { float vetor[5]; int x; for ( x=0; x < 10; x++) vetor[x] = x * x + 5; for ( x=0; x < 10; x++) printf(“Vetor[%d] = %2.1f\n", x+1,vetor[x]); getch(); } Saída em tela: Vetor[1] = 5.0 Vetor[2] = 6.0 Vetor[3] = 9.0 Vetor[4] = 14.0 Vetor[5] = 21.0 Vetor[6] = 0.0 Vetor[7] = 0.0 Vetor[8] = 0.0 Vetor[9] = 0.0 Vetor[10] = 0.0 Diversidade de problemas e erros a partir do uso desta posição não declarada. 02/03/2013 MATRIZ A inicialização de uma matriz, de tipos fundamentais (inteiros ou caracteres), pode ser feita na sua declaração. int matriz[5] = {10,20,30,40,50}; A omissão do tamanho da matriz ocasionará a criação de uma matriz de tamanho suficiente para conter os elementos inicializados que foram atribuídos a ela. int matriz[ ] = {10,20,30,40,50}; Esta declaração criará uma matriz igual a anterior. Não se pode inicializar mais elementos do que foi declarado na matriz. Caso deseje saber o tamanho da matriz, pode se colocar o compilador para encontrá-lo. O retorno deste cálculo será exatamente a quantidade de elementos da matriz. const int tam = sizeof(matriz) / sizeof(matriz[0]); Os elementos não inicializados na matriz são nulos. int matriz[5] = {10,20}; 02/03/2013 MATRIZ #include <stdio.h> #include<conio.c> int main (void) { char vetor[5]; int x; for (x=0; x<5; x++) { vetor[X] = 'A' + x; printf("Matriz[%d] = %c -> ”,x+1,vetor[x]); printf(“Endereco = %x\n“, &vetor[x]); getch(); } } Saída em tela: Matriz[1]= A->Endereço 12ff84 Matriz[2]= B->Endereço 12ff85 Matriz[3]= C->Endereço 12ff86 Matriz[4]= D->Endereço 12ff87 Matriz[5]= E->Endereço 12ff88 Endereço(&) Conteúdo Elemento Qualquer objeto fundamental ou definido pelo usuário pode ser armazenado em uma matriz. Ao declarar a matriz é informado ao compilador qual o tipo e a quantidade de objetos a serem armazenados. O armazenamento na memória é feito de maneira contígua, conforme seu índice. Veja o exemplo a seguir: 02/03/2013 Saída em Tela Nota do aluno 0: 5.5 Nota do aluno 1: 3.8 Nota do aluno 2: 7.5 Nota do aluno 3: 9.2 Nota do aluno 4: 4.8 Media: 6.2 MATRIZ Exemplo: Suponha que será armazenado cinco notas de alunos variando de 0 a 10 sem desprezar as casas decimais. Assim cria-se o seguinte programa específico para esta situação. #include<stdio.h> #include<conio.c> int main(void) { float soma,notas[5]; int i; for (i=0;i<5;i++) { printf("Nota do aluno %d:",i+1); scanf("%f",¬as[i]);} soma = 0.0; for (i=0;i<5;i++) soma = soma + notas[i]; printf("Media: %2.1f",soma /5.0); getch(); } #include<stdio.h> #include<conio.c> int main(void) { float soma,notas[5]; int i; for(i=0,soma=0.0;i<5;soma+=notas[i++] ) { printf("Nota do aluno %d:",i+1); scanf("%f",¬as[i]); } printf("Media: %2.1f ",soma / 5.0); getch(); } Versão Otimizda 02/03/2013 MATRIZ O uso da diretiva define é comum em matrizes, pois com o passar do tempo a matriz pode sofrer alterações (aumentar ou diminuir), o que resultaria em uma grande manutenção pelo programa. Com o intuito de agilizar a manipulação dos valores da matriz em um programa, esta diretiva coerentemente garante ações mais seguras e organizadas em seu código (programa). #include<stdio.h> #include<conio.c> #define MAX 5 int main(void) { float soma,notas[MAX]; int i; for(i=0,soma=0.0; i < MAX ; soma+=notas[i++]) { printf("Nota do aluno %d:",i+1); scanf("%f",¬as[i]); } printf("Media: %.1f ",soma / MAX); getch(); } // fim do programa Procurar utilizar sempre esta diretiva : : 02/03/2013 MATRIZ Como já foi comentado anteriormente, a linguagem C não verifica se o limite da matriz foi ultrapassado. O programa continua guardando informações mesmo que a matriz já tenha sido superada, provocando resultados imprevisíveis, pois pode armazenar valores em trechos de memória que estejam sendo usados, danificando execuções. A responsabilidade do que o programa esta fazendo é do programador, por isso é necessário sempre verificar se o tamanho da matriz está sendo respeitado ou interromper a ação solicitada. Entre as diversas soluções possíveis para esta verificação, sugere-se uma para o exemplo das notas, comentado anteriormente. Imagine que tem-se a necessidade de armazenar mais que as cinco notas, a qual o programa foi elaborado. Observe o resultado do programa a seguir. 02/03/2013 MATRIZ Exemplo: #include<stdio.h> #include<conio.c> #define MAX 5 int main(void) { float soma,notas[MAX]; int i =0; do { if (i>= MAX) { printf("Matriz cheia.\n"); break; } printf("Nota do aluno %d:",i+1); scanf("%f",¬as[i]); if(notas[i] > 0) soma+=notas[i]; } while(notas[i++] > 0); Saída em Tela Nota do aluno 1:1 Nota do aluno 2:2 Nota do aluno 3:3 Nota do aluno 4:4 Nota do aluno 5:5 Matriz Cheia Media: 3.0 printf("Media: %.1f ",soma / MAX); getch(); //fim do programa } 02/03/2013 MATRIZ Uma matriz pode ser inicializada em tempo de compilação ou de execução. Cada uma destas situações apresentam as suas vantagens e desvantagens. *Aumenta o tempo de compilação *Ganha tempo de execução *Aumenta o tempo de execução *Ganha tempo de compilação *Tamanho do programa aumenta Tempo de Compilação Tempo de Execução Em C a inicialização é feita em tempo de compilação para as classes static e extern. Sem inicialização estas variáveis terão os seus valores iniciais iguais a zero (0), inclusive para os outros elementos de uma matriz inicializada parcialmente. Para os elementos de uma matriz do tipo auto os valores serão indefinidos, ou seja lixo de memória. 02/03/2013 MATRIZ Exemplos: #include<stdio.h> #include<conio.c> int main(void) { // Declaração int i; int vet[5]; printf("Elemento 3 da matriz: "); scanf("%d",&vet[2]); // apresentando a matriz clrscr( ); for(i=0;i<5;i++) printf("\nVet[%d]= %d",i+1,vet[i]); getch(); } #include<stdio.h> #include<conio.c> int main(void) { // Declaração int i; static int vet[5]; printf("Elemento 3 da matriz: "); scanf("%d",&vet[2]); // apresentando a matriz for(i=0;i<5;i++) printf("\nVet[%d]= %d",i+1,vet[i]); getch(); } Saída em Tela Vet[1]= 0 Vet[2]= 0 Vet[3]= 6 Vet[4]= 0 Vet[5]= 0 Saída em Tela Vet[1]= ??????? Vet[2]= ??????? Vet[3]= 6 Vet[4]= ??????? Vet[5]= ??????? 02/03/2013 Exercício Proposto 1) Elabore um programa que armazene a idade de até 50 pessoas, apresente a média de todas as idades informadas, quantas idades são maiores que 18 anos e a posição do vetor onde as idades maiores de 18 anos ocorrem. Utilize pelo menos 3 funções. MATRIZ 02/03/2013 Exercício de Fixação 2) Elabore um programa que forneça os valores distintos de um vetor inteiro informado pelo usuário. Verifique com este usuário qual deveria ser a quantidade de elementos para este vetor. 3) Desenvolva um programa que armazene valores inteiros em um vetor. Depois de todos os valores informados, separe-os em outros dois vetores chamados Par e Impar, em uma função, onde os valores pares serão colocados em somente um vetor e os impares em outro. Apresente os valores dos dois vetores criados pelo seu programa separadamente e a quantidade de elementos existentes em cada vetor, através de uma outra função (apresentaVetoresParImpar). 4) Faça um programa que solicite um valor real e uma posição de inserção deste valor em uma matriz unidimensional de 100 elementos. Inclua este valor na posição solicitada pelo usuário e solicite outro valor e posição, enquanto o usuário desejar. A leitura do valor e da posição deverão ser feitas por uma outra função chamada obtemValorPosicao.Após a leitura dos dados fornecidos pelo usuário, informe para cada posição do vetor o valor fornecido ou se não fornecido valor. 02/03/2013 As matrizes podem ter várias dimensões. Imagine um tabuleiro de jogar xadrez. Ele possui duas dimensões, onde uma representa as linhas e a outra as colunas do tabuleiro. Uma posição deverá possuir duas orientações para se colocar uma pedra do jogo de xadrez no tabuleiro. As matrizes com mais que uma dimensão devem ser representadas por índices que identifiquem exatamente a posição. Em um tabuleiro de xadrez, tem-se uma matriz bidimensional, sendo ela declarada da seguinte forma: int tabuleiro[8] [8]; MATRIZ MULTIDIMENSIONAL 02/03/2013 O rei inicia o jogo na quarta coluna da primeira linha do tabuleiro, onde seu posicionamento é assim descrito: tabuleiro [0] [3]; tendo a primeira posição como a linha e a segunda como a coluna. É importante lembrar que os índices são iniciados de zero, por isso a primeira linha é a zero e a quarta coluna é a três. MATRIZ MULTIDIMENSIONAL 02/03/2013 MATRIZ Inicializando Matrizes Multidimensionais Em uma matriz definida com duas dimensões (bidimensional) sua inicialização seria: int matriz[5][3]; int matriz[5][3] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; int matriz[5][3] = {{1,2,3},{4,5,6},{7,8,9},{10,11,12},{13,14,15}}; A segunda inicialização ocorre de forma que todos os elementos vão ser preenchidos na matriz declarada. As chaves internas, na terceira inicialização, são desconsideradas pelo compilador, mas servem para esclarecer melhor ao programador Matriz bidimensional sua inicialização consiste de uma matriz de uma dimensão, onde cada elemento é outra matriz 1º elemento de uma matriz bidimensional matriz[0][0]; 02/03/2013 MATRIZ Exemplo: char inimigo[5][10]; // declaração de uma matriz bidimensional Inimigo é uma matriz de 5 elementos, portanto: inimigo[0] inimigo[1] estes elementos são nomes de outras matrizes inimigo[2] inimigo[3] estas matrizes também devem ser colocadas inimigo[4] em ordem de chaves e vírgula Cada elemento é uma matriz, supondo que inicializada, o elemento zero poderá possuir {0,0,0,0,0,0,0,0,0,0} { , , , ... , , } elemento[0] elemento[1] elemento[2] : elemento[8] elemento[9] 02/03/2013 MATRIZ #include <stdio.h>#include <conio.c> int main (void) { const int linha = 4; //qtde. linhas const int coluna = 2; //colunas int x,y; int mat[linha][coluna]; /*Calculando a matriz*/ for (x=0;x<linha;x++) for (y=0;y<coluna;y++) mat[x][y]=(x*2)+(y*3); printf(" Apresenta a Matriz\n\n"); /*Montando a matriz */ for (y=0;y<coluna;y++) { if (y= =0) printf(" L %4d",y+1); else printf("%4d",y+1); } printf(" Colunas\n i | --------\n"); /*Apresentando os elementos*/ for (x=0;x<linha;x++) { if (x= =0) printf(" n%3d|",x+1); else if (x= =1) printf(" h%3d|",x+1); else if (x= =2) printf(" a%3d|",x+1); else printf(" s%3d|",x+1); for (y=0;y<coluna;y++) printf("%4d“,mat[x][y]); printf("\n\n"); };getch(); /*Errando a matriz*/ mat[6][3] = 999; printf("Matriz[6][3]=%d\n", mat[6][3]); getch(); } 02/03/2013 MATRIZ MULTIDIMENSIONAIS A declaração pode ser representada por: tipo <identificador>[tamanho_1] [tamanho_2] ... [tamanho_n]; Exemplo: int matriz[2][3][3]; // declaração de uma matriz valor=matriz[1][3][2]; // valor da posição da matriz Para se conhecer o tamanho (em bytes) alocado na memória para criação de uma tabela multidimensional pode-se calculá-lo da seguinte forma: Qtde_bytes= Tamanho_1*Tamanho_2*...*Tamanho_n*sizeof(tipo) 02/03/2013 MATRIZ Exercício Proposto 5) Desenhe a matriz proposta pela inicialização a seguir. Identifique qual o tipo desta matriz e a posição do único zero existente nela. Faça uso da sintaxe em C para mostrar onde este zero esta posicionado. int matriz[3][4][2] = {{{1,5},{2,6},{3,7},{4,8}},{{3,7},{4,9}, {5,4},{6,5}},{{1,0},{4,6},{6,7},{7,8}}}; Resolução: int matriz[3][4][2] ; 1,2,3,4 5,6,7,8 3,4,5,6 7,9,4,5 1,4,6,7 0,6,7,8 L i n h a Coluna páginas Matriz tridimensional 3x4x2 Posição do único zero: matriz[2][0][1]; 02/03/2013 MATRIZ COMO ARGUMENTO A criação de uma variável ocasiona as seguintes atribuições na memória. Observe a representação: Criação da variável NUMERO int numero = 25; Simulação da memória 4 OBJETOS A CONSIDERAR nome da variável = numero endereço = &numero conteúdo = 25(numero=25 ) endereço inicial=1543 (&numero=1543) 1542 1543 1544 25 numero nome conteúdo endereço 02/03/2013 Criação da matriz Vetor int vetor[5] = {2,4,7,6,25}; Simulação da memória 1542 1546 1550 1554 1558 Vetor[0] Vetor[1] Vetor[2] Vetor[3] Vetor[4] elemento conteúdo endereço 2 4 7 6 25 Vetor MATRIZ COMO ARGUMENTO Somente o nome da matriz, desacompanhado dos colchetes, equivale ao endereço da matriz. Observe a representação: OBJETOS A CONSIDERAR elementos =vetor[0]...vetor[4] endereço da matriz = vetor conteúdo dos elementos = 2 ... 25 endereço inicial da matriz = 1542 endereços elementos = 1542 ... 1558 • O elemento da matriz possui nome como: vetor[2] e seu valor é 7 02/03/2013 MATRIZ COMO ARGUMENTO O endereço da matriz é igual ao endereço do primeiro elemento (vetor[0]), enquanto que o endereço dos outros elementos são diferentes. O operador de endereço (&) não é usado para o endereço de uma matriz, pois somente o nome da matriz (Vetor) já trata- se do seu endereço. O nome vetor não é usado como nome de endereço de uma simples variável, mas sim de uma matriz. vetor se refere a endereço se vetor for matriz se refere a conteúdo se vetor for variável 02/03/2013 CHAMADA POR VALOR Quando o nome é usado como argumento na chamada de uma função, a função traz o valor contido nesta variável e o armazena em uma nova variável com um novo endereço. É feito uma cópia da variável que é acessada para atualizações, entre outros acessos. A variável original se mantém intacta, não sofrendo nenhum efeito do que venha a ocorrer com sua cópia. MATRIZ COMO ARGUMENTO CHAMADA POR REFERÊNCIA Na passagem do endereço como argumento, é acessado o valor original (não sua cópia). Como as matrizes normalmente são grandes, o acesso a matriz em uma função é realizada sem criação de cópia.As matrizes são sempre passadas por referência. 02/03/2013 •Em C não é possível a passagem de uma matriz inteira como argumento (chamada por valor). O que pode ser feito é a passagem de um endereço para a função( passagem por referência), especificando o nome da matriz sem índice.O tamanho da matriz não importa à função (C não realiza verificação de limites).A função acessa os dados da matriz a partir do endereço passado Matriz Unidimensional como argumento #include <stdio.h> #include <conio.c> void par_tipo1(int z[10]); void par_tipo2(int z[]); void main (void) { int x[10], i; for (i=0;i<10;i++) x[i] = i*i; printf("tipo 1\n"); par_tipo1(x); printf("tipo 2\n"); par_tipo2(x); getch();} // matriz dimensionada void par_tipo1(int z[10]) { int i; for (int i=0;i<10;i++) printf("x[%d] = %d\n",i,z[i]); } // matriz não dimensionada void par_tipo2(int z[]) { int i; for (int i=0;i<10;i++) printf("x[%d] = %d\n",i,z[i]); } 02/03/2013 Acontece de forma idêntica a unidimensional, onde o endereço da matriz é passado para a função. A declaração da matriz como parâmetro da função é : int p [ ] [mes]; Uma função que recebe uma matriz bidimensional terá que conhecer o tamanho da segunda dimensão para localizar a posição de memória onde um elemento esta armazenado. Sem o comprimento da linha (colunas) é impossível localizar um elemento. Para localizar um elemento a função multiplica o índice da linha pelo número de elementos por linha e adiciona o índice da coluna. Matriz Bidimensional como argumento como não há verificação de limites, uma matriz com qualquer número de linhas pode ser passada para a função chamada 02/03/2013 Matriz Bidimensional como argumento #include <stdio.h> #include <conio.c> #define CINCO 5 void imprime(int x[][CINCO]); void main (void) { int x[10][CINCO], i,j; for (i=0;i<10;i++) for (j=0;j<CINCO;j++) x[i][j] =( i+1)+(j+1); printf(“imprime matriz \n “); imprime (x); printf(“ x[9][4] = %d\n”,x[9][4]); getch(); } void imprime(int z[][CINCO]) { int i,j; for ( j=0;j<CINCO;j++) printf("%5d",j+1); printf("\n"); for (i=0;i<10;i++) { printf("%5d",i+1); for (j=0;j<CINCO;j++) printf("%5d",z[i][j]); printf("\n");} z[9][4] = 9999; } 02/03/2013 Exercícios de Fixação 6) Escrever um programa que leia uma matriz 4x4, multiplique os elementos da sua diagonal principal por uma constante K , também lida, e escreva a matriz resultante no formato de matriz. 7) Desenvolva um programa que permita que o cliente solicite os móveis disponíveis em uma fábrica (sofá, mesa, estante, escrivaninha). Este programa elaborará um pedido específico para cada cliente, contendo nele todos os produtos solicitados, suas respectivas quantidades e o preço a ser pago por todos os itens, mostrando o valor unitário para cada um deles. Também deverá fazer parte deste pedido os móveis que ele possa ter solicitado e a fábrica ainda não os disponibilizou. Neste caso, somente a descrição do móvel deverá ser apresentada. 8) Elabore um programa que armazene em uma matriz dez tipos de carros diferentes. Faça uma comparação e identifique quais carros são Astra, Omega, Vectra e Silverado. Mostre todos os carros informados por um usuário e apresente a string “indisponível” para as outras solicitações que não se tratam dos carros identificados. ATENÇÃO! Todosos exercícios a seguir não poderão usar as variáveis globais 02/03/2013 Referência de Criação e Apoio ao Estudo Material para Consulta e Apoio ao Conteúdo • Universidade Federal de Minas Gerais - site ead1.eee.ufmg.br/cursos (escolha a opção ‘C’) • SCHILDT, H., C Completo e Total, Editora Makron Books do Brasil Editora Ltda, 1996. Capítulo 4 • EVARISTO, J., Aprendendo a programar programando em C, Book Express, 205 p., 2001. Capítulo 6 e 7 • MIZRAHI, V. V., Treinamento em Linguagem C, Curso Completo, Módulo 2, Makron Books do Brasil Editora Ltda,1990. Capítulo 7
Compartilhar