A apresentação está carregando. Por favor, espere

A apresentação está carregando. Por favor, espere

Capítulo IX – Ponteiros 9.1 – Introdução 9.2 – Relação entre ponteiros e variáveis indexadas 9.3 – Alocação dinâmica de memória 9.4 – Variáveis indexadas,

Apresentações semelhantes


Apresentação em tema: "Capítulo IX – Ponteiros 9.1 – Introdução 9.2 – Relação entre ponteiros e variáveis indexadas 9.3 – Alocação dinâmica de memória 9.4 – Variáveis indexadas,"— Transcrição da apresentação:

1 Capítulo IX – Ponteiros 9.1 – Introdução 9.2 – Relação entre ponteiros e variáveis indexadas 9.3 – Alocação dinâmica de memória 9.4 – Variáveis indexadas, ponteiros e estruturas como parâmetros e elementos de retorno 9.5 – Subprogramas como parâmetros 9.6 – Encadeamento de estruturas

2 9.3 – Alocação Dinâmica de Memória 9.3.1 – Dispositivos para alocação dinâmica Muitas vezes é desejável reservar espaço para vetores e matrizes somente em tempo de execução Muitas vezes é desejável reservar espaço para vetores e matrizes somente em tempo de execução Exemplo: seja a seguinte declaração: Exemplo: seja a seguinte declaração: int A[100][100];

3 Neste exemplo, supõe-se que o número de linhas e colunas de A devam ser lidos durante a execução desse programa Neste exemplo, supõe-se que o número de linhas e colunas de A devam ser lidos durante a execução desse programa Caso eles sejam bem menores que 100, haverá grande desperdício de memória Caso eles sejam bem menores que 100, haverá grande desperdício de memória Caso sejam maiores que 100, o espaço reservado não será suficiente para guardar os elementos de A Caso sejam maiores que 100, o espaço reservado não será suficiente para guardar os elementos de A É conveniente alocar espaço para os elementos dessa variável depois de conhecidos os números de linhas e de colunas É conveniente alocar espaço para os elementos dessa variável depois de conhecidos os números de linhas e de colunas

4 Na Linguagem C, a alocação de espaço em tempo de execução para vetores e matrizes só pode ser feita se esses forem declarados como ponteiros Na Linguagem C, a alocação de espaço em tempo de execução para vetores e matrizes só pode ser feita se esses forem declarados como ponteiros Esse tipo de alocação denomina-se alocação dinâmica Esse tipo de alocação denomina-se alocação dinâmica Há uma região da memória ocupada pelo programa denominada heap, destinada a essas alocações dinâmicas Há uma região da memória ocupada pelo programa denominada heap, destinada a essas alocações dinâmicas

5 A alocação pode ser feita pela função malloc do arquivo stdlib.h A alocação pode ser feita pela função malloc do arquivo stdlib.h malloc recebe como argumento o número de bytes a ser alocado malloc recebe como argumento o número de bytes a ser alocado malloc então reserva na heap esse número de bytes de forma contígua malloc então reserva na heap esse número de bytes de forma contígua O valor retornado por malloc é o endereço do primeiro desses bytes (um ponteiro) O valor retornado por malloc é o endereço do primeiro desses bytes (um ponteiro) Esses bytes ficam indisponíveis para novas alocações Esses bytes ficam indisponíveis para novas alocações

6 Exemplo: para alocar um vetor de 7 elementos do tipo int: Exemplo: para alocar um vetor de 7 elementos do tipo int: int *V; V = (int *) malloc (7 * sizeof (int)); heap V A conversão (int *) é necessária pois malloc retorna um ponteiro do tipo void int 4 bytes 28 bytes V pode ser usada como vetor

7 #include #include typedef int *vetor; void main () { int m, i; vetor A, B, C; printf ("Tamanho dos vetores: "); scanf ("%d", &m); A = (int *) malloc (m*sizeof(int)); B = (int *) malloc (m*sizeof(int)); C = (int *) malloc (m*sizeof(int)); printf ("\nVetor A: "); for (i = 0; i < m; i++) scanf ("%d", &A[i]); printf ("\nVetor B: "); for (i = 0; i < m; i++) scanf ("%d", &B[i]); printf ("\nVetor C: "); for (i = 0; i < m; i++) C[i] = (A[i] > B[i])? A[i]: B[i]; for (i = 0; i < m; i++) printf ("%5d", C[i]); printf ("\n\nDigite algo para encerrar: "); getch (); printf ("\n\nDigite algo para encerrar: "); getch ();} Exemplo: seja o programa à esquerda Tamanho dos vetores: 7 Vetor A: 28 39 84 27 82 49 10 Vetor B: 94 27 68 17 83 72 39 Vetor C: 94 39 84 27 83 72 39 Digite algo para encerrar: No vídeo

8 O lay-out da área ocupada pelo programa é planejado pelo compilador O lay-out da área ocupada pelo programa é planejado pelo compilador O gerenciamento durante a execução fica por conta do próprio programa O gerenciamento durante a execução fica por conta do próprio programa A área total reservada para o programa é fixa A área total reservada para o programa é fixa As regiões das instruções e das variáveis globais também tem tamanho fixo As regiões das instruções e das variáveis globais também tem tamanho fixo

9 As outras regiões tem tamanho variável durante a execução As outras regiões tem tamanho variável durante a execução A área de dados das funções destina-se a guardar os parâmetros, as variáveis locais e informações operacionais das versões ativas de funções num dado momento A área de dados das funções destina-se a guardar os parâmetros, as variáveis locais e informações operacionais das versões ativas de funções num dado momento Essa área varia de tamanho, pois essas versões de funções não ficam ativas o tempo todo Essa área varia de tamanho, pois essas versões de funções não ficam ativas o tempo todo

10 Quando uma versão de função é chamada para execução, sua área de dados é carregada na memória Quando uma versão de função é chamada para execução, sua área de dados é carregada na memória O carregamento é feito a partir da fronteira com a área desocupada O carregamento é feito a partir da fronteira com a área desocupada Quando sua execução é encerrada, sua área é retirada da memória, aumentando a área desocupada Quando sua execução é encerrada, sua área é retirada da memória, aumentando a área desocupada

11 A área heap aumenta a partir de sua fronteira com a área desocupada A área heap aumenta a partir de sua fronteira com a área desocupada Isso acontece quando uma alocação dinâmica de memória é feita (malloc ou outras do gênero) Isso acontece quando uma alocação dinâmica de memória é feita (malloc ou outras do gênero) A área de dados das funções aumenta para baixo e a heap aumenta para cima A área de dados das funções aumenta para baixo e a heap aumenta para cima

12 Nesse processo, se o programador não tomar cuidado, essas duas áreas podem se encontrar Nesse processo, se o programador não tomar cuidado, essas duas áreas podem se encontrar Aí, esgota-se a capacidade da área desocupada Aí, esgota-se a capacidade da área desocupada Novas chamadas de funções e novas alocações dinâmicas ficam impossibilitadas Novas chamadas de funções e novas alocações dinâmicas ficam impossibilitadas

13 A função free torna a deixar disponível a área reservada numa alocação dinâmica A função free torna a deixar disponível a área reservada numa alocação dinâmica Seu parâmetro é um ponteiro Seu parâmetro é um ponteiro Ela re-disponibiliza a área previamente alocada e apontada por ele Ela re-disponibiliza a área previamente alocada e apontada por ele Deve-se usar essa função toda vez que uma alocação não tiver mais utilidade para o programa Deve-se usar essa função toda vez que uma alocação não tiver mais utilidade para o programa

14 9.3.2 – Alocação dinâmica de matrizes Usa-se ponteiro para vetor de ponteiros: Usa-se ponteiro para vetor de ponteiros: Ver programa a seguir

15 #include #include typedef int **matriz; void main () { int m, n, i, j; matriz A; printf ("Dimensoes de uma matriz: "); scanf ("%d%d", &m, &n); A = (int **) malloc (m * sizeof(int*)); for (i = 0; i < m; i++) A[i]= (int *) malloc (n * sizeof(int)); printf ("\nElementos da matriz:\n\n"); for (i = 0; i < m; i++) { printf ("\tLinha %d: ", i); for (j = 0; j < n; j++) scanf ("%d", &A[i][j]); } printf ("\nConfirmacao: \n\n"); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) printf ("%5d", A[i][j]); printf ("\n"); } printf ("\n\nDigite algo para encerrar: "); getch (); printf ("\n\nDigite algo para encerrar: "); getch ();} matriz é o tipo ponteiro para ponteiros de int A partir deste ponto, A pode ser usada como uma matriz comum

16 Capítulo IX – Ponteiros 9.1 – Introdução 9.2 – Relação entre ponteiros e variáveis indexadas 9.3 – Alocação dinâmica de memória 9.4 – Variáveis indexadas, ponteiros e estruturas como parâmetros e elementos de retorno 9.5 – Subprogramas como parâmetros 9.6 – Encadeamento de estruturas

17 9.4 – Variáveis Indexadas, Ponteiros e Estruturas como Parâmetros e Elementos de Retorno 9.4.1 – Variáveis indexadas e ponteiros como parâmetros Em C, quando um dos parâmetros de uma função for declarado como variável indexada, na realidade ele será um ponteiro Em C, quando um dos parâmetros de uma função for declarado como variável indexada, na realidade ele será um ponteiro

18 Caso o argumento correspondente seja o nome de uma variável indexada: Caso o argumento correspondente seja o nome de uma variável indexada: O endereço correspondente aos seu nome é passado ao ponteiro-parâmetro O endereço correspondente aos seu nome é passado ao ponteiro-parâmetro Os elementos da variável-argumento não são copiados para a função Os elementos da variável-argumento não são copiados para a função Então essa passagem de argumento é por referência Então essa passagem de argumento é por referência Toda alteração nos elementos da variável-parâmetro terá efeito sobre aqueles da variável-argumento Toda alteração nos elementos da variável-parâmetro terá efeito sobre aqueles da variável-argumento Outros possíveis argumentos: ponteiros e endereços Outros possíveis argumentos: ponteiros e endereços

19 #include #include void Alterar (int B[]) { B[1] = B[3] = 7; } void main () { int i, A[10] = {0}; printf ("Vetor inicial : "); for (i = 0; i <= 9; i++) printf ("%3d", A[i]); Alterar (A); printf ("\n\nVetor intermediario: "); for (i = 0; i <= 9; i++) printf ("%3d", A[i]); Alterar (&A[4]); printf ("\n\nVetor final : "); for (i = 0; i <= 9; i++) printf ("%3d", A[i]); printf ("\n\nDigite algo para encerrar: "); getch (); printf ("\n\nDigite algo para encerrar: "); getch ();} Exemplo: seja o programa à esquerda O parâmetro B de Alterar é um ponteiro Não é necessário colocar a dimensão Poderia ser int *B

20 #include #include void Alterar (int B[]) { B[1] = B[3] = 7; } void main () { int i, A[10] = {0}; printf ("Vetor inicial : "); for (i = 0; i <= 9; i++) printf ("%3d", A[i]); Alterar (A); printf ("\n\nVetor intermediario: "); for (i = 0; i <= 9; i++) printf ("%3d", A[i]); Alterar (&A[4]); printf ("\n\nVetor final : "); for (i = 0; i <= 9; i++) printf ("%3d", A[i]); printf ("\n\nDigite algo para encerrar: "); getch (); printf ("\n\nDigite algo para encerrar: "); getch ();} A A[0]A[1]A[2]A[3]A[4]A[5]A[6]A[7]A[8]A[9] 0000000000 B B[0]B[1]B[2]B[3]B[4]B[5]B[6]B[7]B[8]B[9] 77 B[0]B[1]B[2]B[3]B[4]B[5] 77

21 #include #include void Alterar (int B[]) { B[1] = B[3] = 7; } void main () { int i, A[10] = {0}; printf ("Vetor inicial : "); for (i = 0; i <= 9; i++) printf ("%3d", A[i]); Alterar (A); printf ("\n\nVetor intermediario: "); for (i = 0; i <= 9; i++) printf ("%3d", A[i]); Alterar (&A[4]); printf ("\n\nVetor final : "); for (i = 0; i <= 9; i++) printf ("%3d", A[i]); printf ("\n\nDigite algo para encerrar: "); getch (); printf ("\n\nDigite algo para encerrar: "); getch ();} Vetor inicial : 0 0 0 0 0 0 0 0 0 0 Vetor intermediario: 0 7 0 7 0 0 0 0 0 0 Vetor final : 0 7 0 7 0 7 0 7 0 0 Digite algo para encerrar: Resultado

22 #include #include void ImprimirMatriz (int V[][10], int x, int y) { int i, j; int i, j; printf ("Endereco(V) = %d; Conteudo(V) = %d;\n\n", &V, V); printf ("Endereco(V) = %d; Conteudo(V) = %d;\n\n", &V, V); printf ("Endereco(V[0][0]) = %d\n\n", &V[0][0]); printf ("Endereco(V[0][0]) = %d\n\n", &V[0][0]); for (i = 0; i < x; i++) { for (i = 0; i < x; i++) { for (j = 0; j < y; j++) { for (j = 0; j < y; j++) { printf ("%5d", V[i][j]); printf ("%5d", V[i][j]); } printf ("\n"); printf ("\n"); }} void main () { int A[10][10], i, j, m = 5, n = 7; printf ("A = %d\n\n", A); printf ("Endereco(A[0][0]) = %d\n\n", &A[0][0]); printf ("Endereco(A[0][0]) = %d\n\n", &A[0][0]); for (i = 0; i < m; i++) for (i = 0; i < m; i++) for (j = 0; j < n; j++) for (j = 0; j < n; j++) A[i][j] = (i+1)*(j+1); A[i][j] = (i+1)*(j+1); ImprimirMatriz (A, m, n); getch (); } Exemplo com matriz bidimensional

23 #include #include void ImprimirMatriz (int V[][10], int x, int y) { int i, j; int i, j; printf ("Endereco(V) = %d; Conteudo(V) = %d;\n\n", &V, V); printf ("Endereco(V) = %d; Conteudo(V) = %d;\n\n", &V, V); printf ("Endereco(V[0][0]) = %d\n\n", &V[0][0]); printf ("Endereco(V[0][0]) = %d\n\n", &V[0][0]); for (i = 0; i < x; i++) { for (i = 0; i < x; i++) { for (j = 0; j < y; j++) { for (j = 0; j < y; j++) { printf ("%5d", V[i][j]); printf ("%5d", V[i][j]); } printf ("\n"); printf ("\n"); }} void main () { int A[10][10], i, j, m = 5, n = 7; printf ("A = %d\n\n", A); printf ("Endereco(A[0][0]) = %d\n\n", &A[0][0]); printf ("Endereco(A[0][0]) = %d\n\n", &A[0][0]); for (i = 0; i < m; i++) for (i = 0; i < m; i++) for (j = 0; j < n; j++) for (j = 0; j < n; j++) A[i][j] = (i+1)*(j+1); A[i][j] = (i+1)*(j+1); ImprimirMatriz (A, m, n); getch (); } No parâmetro V, a 1ª dimensão é dispensada Resultado

24 #include #include void ImprimirMatriz (int V[][10], int x, int y) { int i, j; int i, j; printf ("Endereco(V) = %d; Conteudo(V) = %d;\n\n", &V, V); printf ("Endereco(V) = %d; Conteudo(V) = %d;\n\n", &V, V); printf ("Endereco(V[0][0]) = %d\n\n", &V[0][0]); printf ("Endereco(V[0][0]) = %d\n\n", &V[0][0]); for (i = 0; i < x; i++) { for (i = 0; i < x; i++) { for (j = 0; j < y; j++) { for (j = 0; j < y; j++) { printf ("%5d", V[i][j]); printf ("%5d", V[i][j]); } printf ("\n"); printf ("\n"); }} void main () { int A[10][10], i, j, m = 5, n = 7; printf ("A = %d\n\n", A); printf ("Endereco(A[0][0]) = %d\n\n", &A[0][0]); printf ("Endereco(A[0][0]) = %d\n\n", &A[0][0]); for (i = 0; i < m; i++) for (i = 0; i < m; i++) for (j = 0; j < n; j++) { for (j = 0; j < n; j++) { A[i][j] = (i+1)*(j+1); A[i][j] = (i+1)*(j+1); } ImprimirMatriz (A, m, n); ImprimirMatriz (A, m, n); getch (); } Resultado A A[0][0] V

25 Exemplo: Fusão de 2 vetores ordenados O programa a seguir realiza as seguintes operações: O programa a seguir realiza as seguintes operações: Lê os dados sobre os dois vetores Lê os dados sobre os dois vetores Ordena-os pelo Bubble-Sort Ordena-os pelo Bubble-Sort Funde os dois vetores pelo método Merge-Sort, obtendo um terceiro vetor ordenado Funde os dois vetores pelo método Merge-Sort, obtendo um terceiro vetor ordenado O método Merge-Sort apresentado só funciona quando os 2 vetores já estão ordenados O método Merge-Sort apresentado só funciona quando os 2 vetores já estão ordenados

26 O Método Merge-Sort: 3588111316456789 V1 V2 V3 i j k V3[k] = (V1[i] < V2[j]) ? V1[i] : V2[j];

27 O Método Merge-Sort: 33588111316456789 V1 V2 V3 i j k V3[k] = (V1[i] < V2[j]) ? V1[i] : V2[j];

28 O Método Merge-Sort: 343588111316456789 V1 V2 V3 i j k V3[k] = (V1[i] < V2[j]) ? V1[i] : V2[j];

29 O Método Merge-Sort: 3453588111316456789 V1 V2 V3 i j k V3[k] = (V1[i] < V2[j]) ? V1[i] : V2[j];

30 O Método Merge-Sort: 34553588111316456789 V1 V2 V3 i j k V3[k] = (V1[i] < V2[j]) ? V1[i] : V2[j];

31 O Método Merge-Sort: 345563588111316456789 V1 V2 V3 i j k V3[k] = (V1[i] < V2[j]) ? V1[i] : V2[j];

32 O Método Merge-Sort: 3455673588111316456789 V1 V2 V3 i j k V3[k] = (V1[i] < V2[j]) ? V1[i] : V2[j];

33 O Método Merge-Sort: 34556783588111316456789 V1 V2 V3 i j k V3[k] = (V1[i] < V2[j]) ? V1[i] : V2[j];

34 O Método Merge-Sort: 345567883588111316456789 V1 V2 V3 i j k V3[k] = (V1[i] < V2[j]) ? V1[i] : V2[j];

35 O Método Merge-Sort: 3455678883588111316456789 V1 V2 V3 i j k V3[k] = (V1[i] < V2[j]) ? V1[i] : V2[j];

36 O Método Merge-Sort: 34556788893588111316456789 V1 V2 V3 i j k V3[k] = (V1[i] < V2[j]) ? V1[i] : V2[j];

37 O Método Merge-Sort: 34556788891113163588111316456789 V1 V2 V3 i j k V3[k] = (V1[i] < V2[j]) ? V1[i] : V2[j]; A seguir, o programa

38 /*Declaracoes globais */ #include #include typedef char logic; const logic TRUE = 1, FALSE = 0; typedef int vetor[20]; /*Prototipos das funcoes auxiliares*/ void LerVetor (vetor, int*); void EscreverVetor (vetor, int); void BubbleSort (vetor, int); void MergeSort (vetor, vetor, vetor, int, int, int*); O tipo dos parâmetros dos protótipos devem ser os mesmos nas definições das funções

39 void main () { int m, n, p; vetor V1, V2, V3; printf ("FUSAO DE DOIS VETORES ORDENADOS"); printf ("FUSAO DE DOIS VETORES ORDENADOS"); /*Leitura dos dois vetores*/ printf ("\n\nLeitura do vetor V1: \n"); LerVetor (V1, &m); LerVetor (V1, &m); printf ("\nLeitura do vetor V2: \n"); LerVetor (V2, &n); LerVetor (V2, &n); /*Escrita dos dois vetores lidos*/ printf ("\n\nVetor V1 inicial: \n\n"); printf ("\n\nVetor V1 inicial: \n\n"); EscreverVetor (V1, m); printf ("\n\nVetor V2 inicial: \n\n"); printf ("\n\nVetor V2 inicial: \n\n"); EscreverVetor (V2, n); V1, V2 e V3 são variáveis indexadas Passagem de V1, V2, m e n: por referência Eles serão alterados pela função LerVetor Passagem de V1 e V2 : por referência Os elementos não precisam ser copiados para a função

40 /*Ordenacao e escrita dos dois vetores ordenados */ BubbleSort (V1, m); BubbleSort (V2, n); printf ("\n\nVetor V1 ordenado: \n\n"); printf ("\n\nVetor V1 ordenado: \n\n"); EscreverVetor (V1, m); printf ("\n\nVetor V2 ordenado: \n\n"); printf ("\n\nVetor V2 ordenado: \n\n"); EscreverVetor (V2, n); /*Fusao dos dois vetores num terceiro */ MergeSort (V1, V2, V3, m, n, &p); Passagem de V1 e V2: por referência Eles serão alterados pela função BubbleSort Passagem de V1 e V2: por referência Os elementos não precisam ser copiados para a função Passagem de V3 e p: por referência Eles serão alterados pela função MergeSort

41 /*Escrita do vetor resultado da fusao */ printf ("\n\nFusao V3 dos vetores V1 e V2:\n\n"); printf ("\n\nFusao V3 dos vetores V1 e V2:\n\n"); EscreverVetor (V3, p); /*Fechamento da tela */ printf ("\n\nDigite algo para encerrar: "); getch (); getch ();}

42 /*Funcao LerVetor para ler os elementos de um vetor */ void LerVetor (vetor V, int *n) { int i; int i; printf ("\n\tNumero de elementos: "); scanf ("%d", n); printf ("\n\tSeus %d elementos: ", *n); for (i = 0; i <= *n-1; i++) scanf ("%d", &V[i]); } /*Funcao EscreverVetor para escrever os elementos de um vetor */ void EscreverVetor (vetor V, int n) { int i; for (i = 0; i <= n-1; i++) printf ("%4d", V[i]); } Na função main: LerVetor (V1, &m); LerVetor (V2, &n); Não é &n, pois n já é o endereço alvo Local apontado por n V[i] coincide com os elementos V1[i] e V2[i] dos argumentos V1 e V2

43 /*Funcao BubbleSort para ordenar os elementos de um vetor */ void BubbleSort (vetor V, int n) { int i, p, aux; logic trocou; p = n-2; trocou = TRUE; while (p>=0 && trocou) { trocou = FALSE; i = 0; while (i <= p) { if (V[i] > V[i+1]) { aux = V[i]; V[i] = V[i+1]; V[i+1] = aux; trocou = TRUE; } i = i+1; } p = p-1; }} V[i] e V[i+1] coincidem com os elementos correspondentes dos argumentos V1 e V2 Na função main: BubbleSort (V1, m); BubbleSort (V2, n);

44 /*Funcao MergeSort para fundir dois vetores ordenados num terceiro tambem ordenado*/ void MergeSort (vetor V1, vetor V2, vetor V3, int m, int n, int *p) { int i, j, k; *p = m + n; *p = m + n; for (i = j = k = 0; i < m && j < n; k++) if (V1[i] < V2[j]) { V3[k] = V1[i]; i++; } else { V3[k] = V2[j]; j++; } for (; i < m; i++, k++) V3[k] = V1[i]; for (; j < n; j++, k++) V3[k] = V2[j]; } Na função main: MergeSort (V1, V2, V3, m, n, &p); O tamanho do vetor final é calculado pela MergeSort Percurso em V1 e V2 ainda não acabou Percurso em V1 ou V2 acabou

45 9.4.2 – Variáveis indexadas e ponteiros como valores retornados Quando se deseja produzir uma variável indexada dentro de uma função e retornar seus elementos, deve-se usar um ponteiro Quando se deseja produzir uma variável indexada dentro de uma função e retornar seus elementos, deve-se usar um ponteiro O programa a seguir faz alocação dinâmica de uma matriz dentro de uma função auxiliar O programa a seguir faz alocação dinâmica de uma matriz dentro de uma função auxiliar As dimensões são passadas por referência e lidas na própria função As dimensões são passadas por referência e lidas na própria função O ponteiro para os elementos da matriz é o valor de retorno O ponteiro para os elementos da matriz é o valor de retorno

46 #include #include typedef int **matriz; matriz LerMatriz (int*, int*); void EscreverMatriz (matriz, int, int); void main () { int m, n; matriz A; printf ("Leitura da matriz A\n\n"); A = LerMatriz (&m, &n); A = LerMatriz (&m, &n); printf ("\nMatriz A lida:\n\n"); EscreverMatriz (A, m, n); EscreverMatriz (A, m, n); printf ("\n\nDigite algo para encerrar: "); printf ("\n\nDigite algo para encerrar: "); getch (); getch ();} O valor retornado de LerMatriz é atribuído a A

47 matriz LerMatriz (int *nlin, int *ncol) { matriz MatRetorno; int i, j; printf ("Digite as 2 dimensoes: "); printf ("Digite as 2 dimensoes: "); scanf ("%d%d", nlin, ncol); MatRetorno = (int **) malloc (*nlin * sizeof(int*)); for (i = 0; i < *nlin; i++) MatRetorno[i]= (int *) malloc (*ncol * sizeof(int)); printf ("\nDigite os elementos da matriz\n\n"); for (i = 0; i < *nlin; i++) { printf ("\tLinha %d: ", i); for (j = 0; j < *ncol; j++) scanf ("%d", &MatRetorno[i][j]); } return MatRetorno; return MatRetorno;} Na função main: A = LerMatriz (&m, &n); Alocação do vetor de ponteiros O valor retornado é um ponteiro

48 void EscreverMatriz (matriz Mat, int m, int n) { int i, j; for (i = 0; i < m; i++) { for (j = 0; j < n; j++) printf ("%5d", Mat[i][j]); printf ("\n"); }} Na função main: EscreverMatriz (A, m, n);

49 9.4.3 – Estruturas como parâmetros e valores retornados Em C, estruturas podem ser declaradas como parâmetros, passadas como argumentos por valor e por referência e seus valores podem ser retornados de funções Em C, estruturas podem ser declaradas como parâmetros, passadas como argumentos por valor e por referência e seus valores podem ser retornados de funções Na passagem de argumento por valor e no retorno de uma função, há uma cópia de toda a estrutura, de um módulo para outro Na passagem de argumento por valor e no retorno de uma função, há uma cópia de toda a estrutura, de um módulo para outro O programa a seguir realiza operações com números complexos O programa a seguir realiza operações com números complexos É usada uma estrutura com a parte real e a parte imaginária de um complexo É usada uma estrutura com a parte real e a parte imaginária de um complexo

50 #include #include struct complexo {float real, imag;}; typedef struct complexo complexo; void WriteMenu (void); complexo Soma (complexo, complexo); complexo Subtracao (complexo, complexo); complexo Multiplicacao (complexo, complexo); complexo Divisao (complexo, complexo); Nas funções para operações com complexo, todos os parâmetros e os valores retornados são estruturas

51 void main () { complexo a, b, r; char c; WriteMenu (); c = getche (); clrscr (); while (c != '0') { switch (c) { switch (c) { case '1': case '1': printf ("Soma de complexos\n\n"); printf ("Soma de complexos\n\n"); printf ("\tDigite os dois operandos: "); printf ("\tDigite os dois operandos: "); scanf ("%f%f%f%f", &a.real, &a.imag, &b.real, &b.imag); scanf ("%f%f%f%f", &a.real, &a.imag, &b.real, &b.imag); r = Soma (a, b); r = Soma (a, b); printf ("\n[(%g)+j(%g)] + [(%g)+j(%g)] = [(%g)+j(%g)]", printf ("\n[(%g)+j(%g)] + [(%g)+j(%g)] = [(%g)+j(%g)]", a.real, a.imag, b.real, b.imag, r.real, r.imag); a.real, a.imag, b.real, b.imag, r.real, r.imag); break; break;

52 case '2': case '2': printf ("Subtracao de complexos\n\n"); printf ("Subtracao de complexos\n\n"); printf ("\tDigite os dois operandos: "); printf ("\tDigite os dois operandos: "); scanf ("%f%f%f%f", &a.real, &a.imag, &b.real, &b.imag); scanf ("%f%f%f%f", &a.real, &a.imag, &b.real, &b.imag); r = Subtracao (a, b); r = Subtracao (a, b); printf ("\n[(%g)+j(%g)] - [(%g)+j(%g)] = [(%g)+j(%g)]", printf ("\n[(%g)+j(%g)] - [(%g)+j(%g)] = [(%g)+j(%g)]", a.real, a.imag, b.real, b.imag, r.real, r.imag); a.real, a.imag, b.real, b.imag, r.real, r.imag); break; break; case '3': case '3': printf ("Multiplicacao de complexos\n\n"); printf ("Multiplicacao de complexos\n\n"); printf ("\tDigite os dois operandos: "); printf ("\tDigite os dois operandos: "); scanf ("%f%f%f%f", &a.real, &a.imag, &b.real, &b.imag); scanf ("%f%f%f%f", &a.real, &a.imag, &b.real, &b.imag); r = Multiplicacao (a, b); r = Multiplicacao (a, b); printf ("\n[(%g)+j(%g)] * [(%g)+j(%g)] = [(%g)+j(%g)]", printf ("\n[(%g)+j(%g)] * [(%g)+j(%g)] = [(%g)+j(%g)]", a.real, a.imag, b.real, b.imag, r.real, r.imag); a.real, a.imag, b.real, b.imag, r.real, r.imag); break; break;

53 case '4': case '4': printf ("Divisao de complexos\n\n"); printf ("Divisao de complexos\n\n"); printf("\tDigite os dois operandos: "); printf("\tDigite os dois operandos: "); scanf ("%f%f%f%f", &a.real, &a.imag, &b.real, &b.imag); scanf ("%f%f%f%f", &a.real, &a.imag, &b.real, &b.imag); if (b.real == 0 && b.imag == 0) if (b.real == 0 && b.imag == 0) printf ("\nO divisor eh zero!!!"); printf ("\nO divisor eh zero!!!"); else { else { r = Divisao (a, b); r = Divisao (a, b); printf("\n[(%g)+j(%g)] / [(%g)+j(%g)] = [(%g)+j(%g)]", printf("\n[(%g)+j(%g)] / [(%g)+j(%g)] = [(%g)+j(%g)]", a.real, a.imag, b.real, b.imag, r.real, r.imag); a.real, a.imag, b.real, b.imag, r.real, r.imag); } break; break; default: default: printf ("Operacao invalida!!!"); printf ("Operacao invalida!!!"); } printf ("\n\nDigite algo para continuar"); getch (); printf ("\n\nDigite algo para continuar"); getch (); WriteMenu (); c = getche (); clrscr (); WriteMenu (); c = getche (); clrscr ();} printf ("Fim das operacoes!!!\n\nDigite algo: "); printf ("Fim das operacoes!!!\n\nDigite algo: "); getch(); getch();}

54 void WriteMenu () { clrscr (); printf ("OPERACOES COM NUMEROS COMPLEXOS\n\n"); printf ("\n\t1 - Soma"); printf ("\n\t2 - Subtracao"); printf ("\n\t3 - Multiplicacao"); printf ("\n\t4 - Divisao"); printf ("\n\nDigite a operacao desejada (Zero para encerrar): "); } complexo Soma (complexo a, complexo b) { complexo r; r.real = a.real + b.real; r.imag = a.imag + b.imag; return r; } complexo Subtracao (complexo a, complexo b) { complexo r; r.real = a.real - b.real; r.imag = a.imag - b.imag; return r; }

55 complexo Multiplicacao (complexo a, complexo b) { complexo r; r.real = a.real*b.real - a.imag*b.imag; r.imag = a.real*b.imag + a.imag*b.real; return r ; } complexo Divisao (complexo a, complexo b) { complexo r; float denominador; denominador = pow (b.real, 2) + pow (b.imag, 2); r.real = (a.real*b.real + a.imag*b.imag) / denominador; r.imag = (a.imag*b.real - a.real*b.imag) / denominador; r.imag = (a.imag*b.real - a.real*b.imag) / denominador; return r ; }

56 Como já foi visto, não é possível passar como argumentos por valor nem como valores a serem retornados de uma função todos os elementos de uma variável indexada Como já foi visto, não é possível passar como argumentos por valor nem como valores a serem retornados de uma função todos os elementos de uma variável indexada Se você não pode passar um elefante por debaixo de uma porta, coloque-o dentro de um envelope e passe-o Se você não pode passar um elefante por debaixo de uma porta, coloque-o dentro de um envelope e passe-o Se você não pode passar uma variável indexada como argumento por valor ou como valor de retorno de uma função, coloque-o dentro de uma estrutura e passe-o Se você não pode passar uma variável indexada como argumento por valor ou como valor de retorno de uma função, coloque-o dentro de uma estrutura e passe-o A seguir, um programa para elevar uma matriz a um expoente A seguir, um programa para elevar uma matriz a um expoente Ele invoca uma função para multiplicar duas matrizes Ele invoca uma função para multiplicar duas matrizes

57 /*Declaracoes globais */ #include #include typedef struct matriz matriz; struct matriz { int nlin, ncol; int elem[10][10]; }; /*Prototipos das funcoes auxiliares*/ void LerMatrizQuadrada (matriz *); void EscreverMatriz (matriz Mat); matriz MultMat (matriz, matriz);

58 void main () { int p, i, j, k; matriz M, Mpot; printf ("POTENCIACAO DE MATRIZ\n\n"); /*Leitura do expoente */ printf ("Digite o expoente: "); scanf ("%d", &p); while (p < 0) { printf ("\tExpoente < 0; Digite novamente: "); scanf ("%d", &p); } /*Leitura e escrita da matriz base*/ printf ("\nLeitura da matriz base: \n"); LerMatrizQuadrada (&M); printf ("\nMatriz lida: \n\n"); EscreverMatriz (M); printf ("\nExpoente de potenciacao: %d\n", p); O argumento é o endereço de uma estrutura

59 /*Inicializacao da matriz potencia com a matriz identidade */ Mpot.nlin = Mpot.ncol = M.nlin; for (i = 1; i <= Mpot.nlin; i++) for (j = 1; j <= Mpot.ncol; j++) Mpot.elem[i][j] = (i == j) ? 1 : 0; /* Calculo da matriz potencia*/ for (k = 1; k <= p; k++) Mpot = MultMat (Mpot, M); /* Escrita da matriz potencia*/ printf ("\nMatriz potencia: \n\n"); EscreverMatriz (Mpot); printf ("\n\nDigite algo para encerrar: "); printf ("\n\nDigite algo para encerrar: "); getch (); } Os argumentos e o valor retornado são estruturas

60 /*Funcao LerMatrizQuadrada: ler a matriz argumento pelo teclado*/ void LerMatrizQuadrada (matriz *Mat){ int i, j, n; printf ("\nDigite a dimensao da matriz: "); scanf ("%d", &n); while (n <= 0) { printf ("\tDimensao < 1; Digite novamente: "); scanf ("%d", &n); } (*Mat).ncol = (*Mat).nlin = n; for (i = 1; i <= (*Mat).nlin; i++) { printf ("\tLinha %d: ", i); for (j = 1; j <= (*Mat).ncol; j++) scanf ("%d", &(*Mat).elem[i][j]); }} Na função main: LerMatrizQuadrada (&M); Mat é um ponteiro para estrutura *Mat é uma estrutura

61 /*Funcao EscreverMatriz: escrever a matriz argumento no video*/ void EscreverMatriz (matriz Mat) { int i, j; for (i = 1; i <= Mat.nlin; i++) { for (j = 1; j <= Mat.ncol; j++) printf ("%10d", Mat.elem[i][j]); printf ("\n"); }} Na função main: EscreverMatriz (M); EscreverMatriz (Mpot);

62 matriz MultMat (matriz M1, matriz M2) { int i, j, k, aux; matriz M3; M3.nlin = M1.nlin; M3.ncol = M2.ncol; if (M1.ncol == M2.nlin) { for (i = 1; i <= M3.nlin; i++) for (j = 1; j <= M3.ncol; j++) { aux = 0; for (k = 1; k <= M1.ncol; k++) aux += M1.elem[i][k]*M2.elem[k][j]; M3.elem[i][j] = aux; M3.elem[i][j] = aux;}}else for (i = 1; i <= M3.nlin; i++) for (j = 1; j <= M3.ncol; j++) M3.elem[i][j] = 0; return M3; } Na função main: Mpot = MultMat (Mpot, M);

63 9.4.4 – Recursividade com variáveis indexadas Exemplo: formulação recursiva para a procura binária Exemplo: formulação recursiva para a procura binária ProcBinaria (x, inf, sup, Vet) = FALSO se (x Vet[sup]) VERDADE se (x == Vet[med]) ProcBinaria (x, inf, med-1, Vet) se (x < Vet[med]) ProcBinaria (x, med+1, sup, Vet) se (x > Vet[med]) -5 0 1 4 2 7 3 10 4 14 5 15 6 17 7 21 8 23 9 24 10 30 11 32 12 38 13 45 14 50 15 53 16 Vet med inf sup x

64 - - - - - typedef int *vetor; - - - - - logic ProcBinaria (int, int, int, vetor); void main () { int - - - -, n, num; vetor A; logic estah; - - - - - logic estah; - - - - - Alocacao, leitura e ordenacao do vetor A estah = ProcBinaria (num, 0, n-1, A); - - - - - } logic ProcBinaria (int x, int inf, int sup, vetor Vet) { int med; logic r; if (x Vet[sup]) r = FALSE; if (x Vet[sup]) r = FALSE; else { else { med = (inf + sup) / 2; if (x == Vet[med]) r = TRUE; else if (x < Vet[med]) r = ProcBinaria (x, inf, med-1, Vet); else r = ProcBinaria (x, med+1, sup, Vet); } return r; return r;} A Vet A[0] Os ponteiros Vet de todas as chamadas recursivas apontarão para A[0]

65 Exercícios 9.4: 1.Um conjunto de números inteiros não repetidos pode ser representado por uma estrutura com dois campos: um vetor guardando seus elementos e um inteiro contendo o número de elementos do conjunto Considerando como Universo o conjunto de números inteiros no intervalo [1.. 20], fazer: a)Uma função que tenha como parâmetro um conjunto e que retorne esse conjunto sem elementos repetidos e sem elementos que não pertençam ao referido universo b)Uma função que tenha dois conjuntos como parâmetros e que retorne o conjunto união desses conjuntos c)Uma função análoga à do item b, para o conjunto interseção

66 d)Uma função que receba um conjunto como parâmetro e que retorne o seu conjunto complemento, em relação ao referido universo. e)Uma função que receba um conjunto como parâmetro e que o liste no seguinte formato: {elemento, elemento,..., elemento}, ou, se for vazio, {conjunto vazio} f)Um programa principal que leia uma expressão contendo vários conjuntos e vários operadores de conjuntos (U = união, I = interseção, C = complemento), que use a função do item a para limpá-la, exibindo- a em seguida, e que calcule e escreva o valor do conjunto resultado da expressão, usando as funções dos outros itens Exemplo: se os dados de entrada forem: {9 11 3 7 6 3} U {3 11 15 22 10 5 9} I {18 1 3 9 -5 14 7 5} C I {7 2 15} A saída deve ser do tipo: {9 11 3 7 6} U {3 11 15 10 5 9} I {18 1 3 9 14 7 5} C I {7 2 3 11 13 15} = {2 11 13 15}

67 Capítulo IX – Ponteiros 9.1 – Introdução 9.2 – Relação entre ponteiros e variáveis indexadas 9.3 – Alocação dinâmica de memória 9.4 – Variáveis indexadas, ponteiros e estruturas como parâmetros e elementos de retorno 9.5 – Subprogramas como parâmetros 9.6 – Encadeamento de estruturas

68 9.5 – Subprogramas como Parâmetros Em C, o nome de uma função é encarado pelo compilador como sendo um ponteiro para o código dessa função Em C, o nome de uma função é encarado pelo compilador como sendo um ponteiro para o código dessa função É uma variável que guarda o endereço da função na memória É uma variável que guarda o endereço da função na memória Esse fato possibilita, entre outras coisas, que nomes de funções sejam passados como argumentos para outras funções Esse fato possibilita, entre outras coisas, que nomes de funções sejam passados como argumentos para outras funções Seja o programa da Regra do Trapézio visto no Capítulo II Seja o programa da Regra do Trapézio visto no Capítulo II

69 #include #include double f (double x) {return (log10(x) + 5);} int main () { long n, i; float a, b, p; double S1, S2, STrap, Dx; scanf ("%f%f%f", &a, &b, &p); S2 = 0; n = 5; do { S1 = S2; n = 2*n; Dx = (b-a)/n; S2 = 0; i = 1; while (i <= n) { STrap = Dx * (f(a+(i-1)*Dx) + f(a+i*Dx)) / 2; S2 = S2 + STrap; i = i + 1; } } while (fabs (S1-S2) > p); printf ("\nA Integral de f(x) no intervalo [%g, %g]", a, b); printf (" com precisao %g eh %g", p, S2); printf ("\n\nDigite algo para encerrar"); getch (); } Este programa calcula a integral de uma só função: log 10 x + 5 Pode-se fazer uma função integradora em que um dos parâmetros é o nome da função a ser integrada

70 #include<stdio.h>#include<conio.h>#include<math.h> /* Declaracoes das 3 funcoes a serem integradas: log10(x) + 5, x^3 - x, sen(x) + 2 */ double f1 (double x) { return (log10(x)+5); } double f2 (double x) { return (pow(x,3)-x); } double f3 (double x) { return (sin(x)+2); }

71 /*Declaracao da funcao integradora*/ double integral (double f (double),float a, float b, float p) { double s1, s2, si, dx; int n, i; s2 = 0; n = 5; do { s1 = s2; n = 2*n; dx = (b-a)/n; s2 = 0; for (i = 1 ; i <= n; i = i+1) { si = dx * (f(a+(i-1)*dx)+f(a+i*dx)) / 2; s2 = s2 + si; } } while (fabs(s1 - s2) >= p); return s2; } A função f será substituída por aquela que vier como argumento

72 void main () { float a, b, p; printf ("Integral de log10(x):\n\n\tlimite inferior: "); scanf ("%f", &a); printf ("\tlimite superior: "); scanf ("%f", &b); printf ("\tprecisao: ");scanf ("%f", &p); printf ("\n\tValor da integral: %lf\n\n", integral (f1, a, b, p)); printf ("Integral de x**3 - x:\n\n\tlimite inferior: "); scanf ("%f", &a); printf ("\tlimite superior: "); scanf ("%f", &b); printf ("\tprecisao: ");scanf ("%f", &p); printf ("\n\tValor da integral: %lf\n\n", integral (f2, a, b, p)); printf ("Integral de sen(x)+2:\n\n\tlimite inferior: "); scanf ("%f", &a); printf ("\tlimite superior: "); scanf ("%f", &b); printf ("\tprecisao: ");scanf ("%f", &p); printf ("\n\tValor da integral: %lf\n\n", integral (f3, a, b, p)); printf("\n\nDigite algo para encerrar: "); getch(); printf("\n\nDigite algo para encerrar: "); getch();}

73 Integral de log10(x): limite inferior: 1 limite inferior: 1 limite superior: 20 limite superior: 20 precisao: 0.0001 precisao: 0.0001 Valor da integral: 112.768974 Valor da integral: 112.768974 Integral de x**3 - x: limite inferior: 3 limite inferior: 3 limite superior: 20 limite superior: 20 precisao: 0.001 precisao: 0.001 Valor da integral: 39784.250269 Valor da integral: 39784.250269 Integral de sen(x)+2: limite inferior: 0 limite inferior: 0 limite superior: 6.28 limite superior: 6.28 precisao: 0.00001 precisao: 0.00001 Valor da integral: 12.560005 Valor da integral: 12.560005 Resultado de uma execução

74 Subprogramas como parâmetros são usados em problemas científicos envolvendo funções: Subprogramas como parâmetros são usados em problemas científicos envolvendo funções: Tabelas, gráficos, máximos e mínimos, equações diferenciais, etc. Tabelas, gráficos, máximos e mínimos, equações diferenciais, etc.

75 Exercícios 9.5: 1.Fazer uma função para imprimir tabelas de funções de uma variável. Seus parâmetros devem ser: A função f(x) cuja tabela deve ser impressa, os extremos a e b do intervalo a ser impresso e uma variável inteira n contendo o número desejado de linhas da tabela. Cada linha da tabela deve conter um valor de x e o correspondente valor de f(x). O primeiro valor de x da tabela deve ser o valor de a e o último deve ser o valor de b. O número total de linhas deve ser o valor de n. Fazer um programa que chame a referida função para imprimir tabelas para as seguintes funções: Os intervalos e o número de linhas de cada tabela devem ser lidos. As três funções acima devem ser também programadas

76 2.Fazer uma função para traçar gráficos de funções de uma variável no modo gráfico do vídeo do computador. Seus parâmetros devem ser a função f(x) cujo gráfico deve ser desenhado e os extremos a e b do intervalo de variação de x nesse gráfico. O gráfico deve ocupar a tela inteira, portanto a variação da abscissa deve ser ajustar ao tamanho do intervalo Fazer um programa que chame a referida função para desenhar gráficos para as seguintes funções: Nesse programa, os intervalos devem ser lidos

77 Capítulo IX – Ponteiros 9.1 – Introdução 9.2 – Relação entre ponteiros e variáveis indexadas 9.3 – Alocação dinâmica de memória 9.4 – Variáveis indexadas, ponteiros e estruturas como parâmetros e elementos de retorno 9.5 – Subprogramas como parâmetros 9.6 – Encadeamento de estruturas

78 9.6 – Encadeamento de Estruturas Estruturas também podem ser alocadas dinamicamente Estruturas também podem ser alocadas dinamicamente Por exemplo, sejam as seguintes declarações: Por exemplo, sejam as seguintes declarações: typedef struct st st; struct st {int a; float b;}; st *p; O comando O comando p = (st *) malloc (sizeof(st)); aloca espaço para uma estrutura st, cujo endereço é atribuído à variável p

79 typedef struct st st; struct st {int a; float b;}; st *p; p = (st *) malloc (sizeof(st)); Representação gráfica: Representação gráfica: Os parêntesis são necessários pois. tem precedência sobre * Os parêntesis são necessários pois. tem precedência sobre * Outra forma de referenciar os campos de uma estrutura apontada: Outra forma de referenciar os campos de uma estrutura apontada: ab p Atribuindo: (*p).a = 5; (*p).b = 17.3; 517.3 (*p).a = 5; (*p).b = 17.3; p->a = 5; p->b = 17.3; equivalem a (*p) é uma estrutura sem nome

80 Exemplo: sejam as seguintes declarações: Exemplo: sejam as seguintes declarações: typedef struct st st; struct st {int a; st *prox;}; st *p, *q; e os seguintes comandos: p = (st *) malloc (sizeof(st)); p->a = 2; p->prox = (st *) malloc (sizeof(st)); p->prox->a = 3; p->prox->prox = (st *) malloc (sizeof(st)); p->prox->prox->a = 5; p->prox->prox->prox = NULL; for (q = p; q != NULL; q = q->prox) printf ("%4d", q->a); Um dos campos da estrutura st é um ponteiro para uma estrutura de mesmo tipo (st)

81 Seja a execução dos comandos: Seja a execução dos comandos: typedef struct st st; struct st {int a; st *prox;}; st *p, *q; p = (st *) malloc (sizeof(st)); p->a = 2; p->prox = (st *) malloc (sizeof(st)); p->prox->a = 3; p->prox->prox = (st *) malloc (sizeof(st)); p->prox->prox->a = 5; p->prox->prox->prox = NULL; for (q = p; q != NULL; q = q->prox) printf ("%4d", q->a); p aprox 2 a 3 a 5 Formou-se um encadeamento de estruturas

82 Seja a execução dos comandos: Seja a execução dos comandos: typedef struct st st; struct st {int a; st *prox;}; st *p, *q; p = (st *) malloc (sizeof(st)); p->a = 2; p->prox = (st *) malloc (sizeof(st)); p->prox->a = 3; p->prox->prox = (st *) malloc (sizeof(st)); p->prox->prox->a = 5; p->prox->prox->prox = NULL; for (q = p; q != NULL; q = q->prox) printf ("%4d", q->a); p aprox 2 a 3 a 5 q

83 Seja a execução dos comandos: Seja a execução dos comandos: typedef struct st st; struct st {int a; st *prox;}; st *p, *q; p = (st *) malloc (sizeof(st)); p->a = 2; p->prox = (st *) malloc (sizeof(st)); p->prox->a = 3; p->prox->prox = (st *) malloc (sizeof(st)); p->prox->prox->a = 5; p->prox->prox->prox = NULL; for (q = p; q != NULL; q = q->prox) printf ("%4d", q->a); p aprox 2 a 3 a 5 q 2 Vídeo

84 Seja a execução dos comandos: Seja a execução dos comandos: typedef struct st st; struct st {int a; st *prox;}; st *p, *q; p = (st *) malloc (sizeof(st)); p->a = 2; p->prox = (st *) malloc (sizeof(st)); p->prox->a = 3; p->prox->prox = (st *) malloc (sizeof(st)); p->prox->prox->a = 5; p->prox->prox->prox = NULL; for (q = p; q != NULL; q = q->prox) printf ("%4d", q->a); p aprox 2 a 3 a 5 q 2 Vídeo q

85 Seja a execução dos comandos: Seja a execução dos comandos: typedef struct st st; struct st {int a; st *prox;}; st *p, *q; p = (st *) malloc (sizeof(st)); p->a = 2; p->prox = (st *) malloc (sizeof(st)); p->prox->a = 3; p->prox->prox = (st *) malloc (sizeof(st)); p->prox->prox->a = 5; p->prox->prox->prox = NULL; for (q = p; q != NULL; q = q->prox) printf ("%4d", q->a); p aprox 2 a 3 a 5 2 Vídeo q

86 Seja a execução dos comandos: Seja a execução dos comandos: typedef struct st st; struct st {int a; st *prox;}; st *p, *q; p = (st *) malloc (sizeof(st)); p->a = 2; p->prox = (st *) malloc (sizeof(st)); p->prox->a = 3; p->prox->prox = (st *) malloc (sizeof(st)); p->prox->prox->a = 5; p->prox->prox->prox = NULL; for (q = p; q != NULL; q = q->prox) printf ("%4d", q->a); p aprox 2 a 3 a 5 2 3 Vídeo q

87 Seja a execução dos comandos: Seja a execução dos comandos: typedef struct st st; struct st {int a; st *prox;}; st *p, *q; p = (st *) malloc (sizeof(st)); p->a = 2; p->prox = (st *) malloc (sizeof(st)); p->prox->a = 3; p->prox->prox = (st *) malloc (sizeof(st)); p->prox->prox->a = 5; p->prox->prox->prox = NULL; for (q = p; q != NULL; q = q->prox) printf ("%4d", q->a); p aprox 2 a 3 a 5 2 3 Vídeo qq

88 Seja a execução dos comandos: Seja a execução dos comandos: typedef struct st st; struct st {int a; st *prox;}; st *p, *q; p = (st *) malloc (sizeof(st)); p->a = 2; p->prox = (st *) malloc (sizeof(st)); p->prox->a = 3; p->prox->prox = (st *) malloc (sizeof(st)); p->prox->prox->a = 5; p->prox->prox->prox = NULL; for (q = p; q != NULL; q = q->prox) printf ("%4d", q->a); p aprox 2 a 3 a 5 2 3 Vídeo q

89 Seja a execução dos comandos: Seja a execução dos comandos: typedef struct st st; struct st {int a; st *prox;}; st *p, *q; p = (st *) malloc (sizeof(st)); p->a = 2; p->prox = (st *) malloc (sizeof(st)); p->prox->a = 3; p->prox->prox = (st *) malloc (sizeof(st)); p->prox->prox->a = 5; p->prox->prox->prox = NULL; for (q = p; q != NULL; q = q->prox) printf ("%4d", q->a); p aprox 2 a 3 a 5 2 3 5 Vídeo q

90 Seja a execução dos comandos: Seja a execução dos comandos: typedef struct st st; struct st {int a; st *prox;}; st *p, *q; p = (st *) malloc (sizeof(st)); p->a = 2; p->prox = (st *) malloc (sizeof(st)); p->prox->a = 3; p->prox->prox = (st *) malloc (sizeof(st)); p->prox->prox->a = 5; p->prox->prox->prox = NULL; for (q = p; q != NULL; q = q->prox) printf ("%4d", q->a); p aprox 2 a 3 a 5 2 3 5 Vídeo q q q == NULL: Fim!!! O ponteiro q percorreu o encadeamento com o comando q = q->prox

91 Seja a execução dos comandos: Seja a execução dos comandos: typedef struct st st; struct st {int a; st *prox;}; st *p, *q; p = (st *) malloc (sizeof(st)); p->a = 2; p->prox = (st *) malloc (sizeof(st)); p->prox->a = 3; p->prox->prox = (st *) malloc (sizeof(st)); p->prox->prox->a = 5; p->prox->prox->prox = NULL; for (q = p; q != NULL; q = q->prox) printf ("%4d", q->a); p aprox 2 a 3 a 5 q A constante NULL é muito usada para teste de final de percurso O ponteiro q percorreu o encadeamento com o comando q = q->prox

92 p aprox 2 a 3 a 5 q Duas formas de referenciar este local p->prox->prox->a (*(*(*p).prox).prox).a Qual delas é mais cômoda???

93 Encadeamento de estruturas é a principal razão para incorporação de variáveis-ponteiros nas linguagens de programação Encadeamento de estruturas é a principal razão para incorporação de variáveis-ponteiros nas linguagens de programação A disciplina CES-11 Algoritmos e Estruturas de Dados mostra a grande variedade de alternativas de armazenamento de informações oferecida por encadeamentos desse gênero A disciplina CES-11 Algoritmos e Estruturas de Dados mostra a grande variedade de alternativas de armazenamento de informações oferecida por encadeamentos desse gênero Modelos como listas lineares, árvores, grafos, estruturas multi-ligadas muito se beneficiam da inclusão de um ou mais ponteiros em variáveis do tipo struct. Modelos como listas lineares, árvores, grafos, estruturas multi-ligadas muito se beneficiam da inclusão de um ou mais ponteiros em variáveis do tipo struct. O último capítulo, Noções de Estruturas de Dados, oferece uma pequena amostra da utilidade desses modelos O último capítulo, Noções de Estruturas de Dados, oferece uma pequena amostra da utilidade desses modelos

94 No exemplo anterior, a estrutura tinha apenas um campo- ponteiro No exemplo anterior, a estrutura tinha apenas um campo- ponteiro Estruturas com mais campos-ponteiros permitem construções bem mais complexas Estruturas com mais campos-ponteiros permitem construções bem mais complexas Exemplo: sejam as declarações: Exemplo: sejam as declarações: typedef struct celula celula; typedef struct celula *noh; struct celula { informacao info; noh pai, fesq, idir; }; Elas possibilitam construções de árvores (próximo slide) Elas possibilitam construções de árvores (próximo slide) infopai fesqidir Célula

95 infopai fesqidir Célula Aplicações: Organogramas Resolução de expressões aritméticas Jogos eliminatórios de um campeonato etc.


Carregar ppt "Capítulo IX – Ponteiros 9.1 – Introdução 9.2 – Relação entre ponteiros e variáveis indexadas 9.3 – Alocação dinâmica de memória 9.4 – Variáveis indexadas,"

Apresentações semelhantes


Anúncios Google