You are on page 1of 22

1

SUMRIO
1 Apresentao .........................................................................................................2 2 Introduo .............................................................................................................2 2.1 - O que so Ponteiros, e como Funcionam ...............................................2 2.2 - Declarando Ponteiros .............................................................................2 2.3 Ponteiros em Funes: Chamada por Referncia ................................4 2.4 - Ponteiros e Vetores .................................................................................6 2.4.1 - Vetores como ponteiros ............................................................6 2.4.2 - Ponteiros como vetores .............................................................8 2.4.3 Vetores de Ponteiros ...................................................................8 2.4.4 -Ponteiros para Ponteiros ...........................................................8 3 Exerccios .............................................................................................................. 8 4 Introduo a Alocao dinmica de memria ...................................................12 4.1- Alocao dinmica de memria ..............................................................12 4.1.1 malloc ......................................................................................13 4.1.2 calloc .......................................................................................14 4.1.3 realloc ........................................................................................ 14 4.1.4 free ...........................................................................................14 5 Exerccios ...........................................................................................................15 6 REFERNCIAS BIBLIOGRFICAS ..............................................................22

1- Apresentao Vamos, neste micro curso, aprender alguns conceitos da linguagem de programao C, a qual tem se tornado cada dia mais popular, devido sua variedade de possibilidades e robustez. Uma das grandes vantagens do C que ele possui tanto caractersticas de alto nvel quanto de baixo nvel. Sero apresentados, nesta breve apostila, conceitos importantes como a utilizao de ponteiros, e a alocao dinmica de memria. Por se tratar dos conceitos j mencionados, necessrio que o leitor apresente algum conhecimento prvio a cerca da linguagem em questo. 2- Introduo Nesta etapa discutiremos um dos recursos mais poderosos da linguagem de programao em C, o ponteiro. Os ponteiros esto entre as capacidades mais difceis de dominar na linguagem em C. Eles permitem que os programas simulem uma chamada por referncia e criem e manipulem estruturas dinmicas de dados, ou seja, estruturas de dados que podem crescer e encolher no tempo de execuo, por exemplo, listas, pilhas e rvores. 2.1 - O que so Ponteiros, e como Funcionam Os ints guardam inteiros. Os floats guardam nmeros de ponto flutuantes. Os chars guardam caracteres. Ponteiros guardam endereos de memria. Quando voc anota o endereo de um colega voc est criando um ponteiro. O ponteiro este seu pedao de papel. Ele tem anotado um endereo. Qual o sentido disto? Simples. Quando voc anota o endereo de um colega, depois voc vai usar este endereo para ach-lo. O C funciona assim. Voc anota o endereo de algo em uma varvel ponteiro para depois usar. Da mesma maneira, uma agenda, onde so guardados endereos de vrios amigos, poderia ser vista como uma matriz de ponteiros C. Um ponteiro tambm tem tipo. Veja: quando voc anota um endereo de um amigo voc o trata diferente de quando voc anota o endereo de uma empresa. Apesar do endereo dos dois locais ter o mesmo formato (rua, nmero, bairro, cidade, etc.) eles indicam locais cujos contedos so diferentes. Ento os dois endereos so ponteiros de tipos diferentes. No C quando declaramos ponteiros ns informamos ao compilador para que tipo de varivel vamos apont-lo. Um ponteiro int aponta para um inteiro, ou seja, guarda o endereo de um inteiro. 2.2 - Declarando Ponteiros

A declarao de ponteiros bem parecida com a declarao de variveis. Assim como uma varvel comum, ponteiros, como visto acima, precisam ter tipos (como int, float, long, etc.) para indicar ao compilador qual o tipo de valor para o qual o ponteiro aponta. Alm disso, utilizamos o asterisco * antes do nome do ponteiro, para indicar ao compilador que estamos declarando um ponteiro e no uma varivel simples. A sintaxe da declarao de um ponteiro vista a seguir: tipo_do_ponteiro *nome_da_varivel; Abaixo temos alguns exemplos de declarao de ponteiro: int *pt; char *temp, *pt2; O primeiro exemplo declara um ponteiro para um inteiro. O segundo declara dois ponteiros para caracteres. Eles ainda no forma inicializados (como toda varivel do C que apenas declarada). Isto significa que eles apontam para um lugar indefinido. Este lugar pode estar, por exemplo, na poro da memria reservada ao sistema operacional do computador. Usar o ponteiro nestas circunstncias pode levar a um travamento do micro, ou a algo pior. O ponteiro deve ser inicializado (apontado para algum lugar conhecido) antes de ser usado!. Isto de suma importncia. Para atribuir um valor a um ponteiro recm-criado poderamos igual-lo a um valor de memria. Mas, como saber a posio da memria de uma varivel do nosso programa? Seria muito difcil saber o endereo de cada varivel que usamos, mesmo porque estes endereos so determinados pelo compilador da hora da compilao e realocados na execuo. Podemos ento deixar que o compilador faa este trabalho por ns. Para saber o endereo de uma varivel basta usar o operador &.Vejamos o exemplo: int count=10; int *pt; pt=&count; Criamos um inteiro count com o valor 10 e um apontador para um inteiro pt. A expresso &count nos d o endereo de count, o qual armazenamos em pt. Repare que no alteramos o valor de count, que continua valendo 10. Como ns colocamos um endereo em pt, ele est agora liberado para ser usado. Podemos, por exemplo, alterar o valor de count usando pt. Para tanto vamos usar o operador inverso do operador &. o operador *. No exemplo acima, uma vez que fizemos pt=&count a expresso *pt equivalente ao prprio count. Vamos fazer uma pausa e voltar nossa analogia para ver o que est acontecendo. Digamos que exista uma empresa. Ela como uma varivel que j foi declarada. Voc

tem um papel em branco onde vai anotar o endereo da firma. O papel um ponteiro do tipo empresa. Voc ento liga para a empresa e o seu endereo, o qual voc vai anotar no papel. Isto equivalente, no C, a associar o papel empresa com o operador &. Ou seja, o operador & aplicado a empresa equivalente a voc ligar para a mesma e pedir o endereo. Uma vez de posse do endereo no papel voc poderia, por exemplo, fazer uma visita a empresa. No C voc faz uma visita a empresa aplicando o operador * ao papel. Uma vez dentro da empresa voc pode copiar seu contedo ou modifica-lo. Uma observao importante: apesar do smbolo ser o mesmo, o operador * (multiplicao) no o mesmo que o * (referncia dos ponteiros). Para comear o primeiro binrio, e o segundo unitrio pr-fixado. 2.3 Ponteiros em Funes: Chamada por Referncia Na linguagem podemos criar funes que utilizam dois tipos de chamada de parmetros: a chamada por valor, onde a funo recebe uma cpia do valor de uma varivel e a varivel em si no alterada pela funo, e a chamada por referncia, onde a funo recebe o endereo da varivel, que tem seu valor alterado, durante a execuo da funo. Nesta seo explicaremos como feira a chamada por referncia. A chamada por referncia acontece quando passamos um ponteiro como parmetro de uma funo. J sabemos que o ponteiro armazena um endereo de uma varvel: assim a funo recebe o endereo de uma varivel, e pode alterar o valor armazenado neste endereo da maneira que precisar. preciso uma srie de cuidados quando criamos funes que usam chamada por referncia. A primeira delas declarar os ponteiros que sero utilizados como parmetros da funo. Por exemplo: void soma (int *parcela1, int*parcela2) { //corpo da funo } A declarao de ponteiros como parmetros feita da mesma forma que declararamos ponteiros em um programa, declarando o tipo e utilizando o asterisco para indicar que se trata de um ponteiro. Ao escrever o corpo da funo, tambm preciso ateno. Como estamos trabalhando com um ponteiro, preciso lembrar que um ponteiro indica um endereo. Quando precisamos do valor guardado neste endereo, preciso usar o asterisco antes do ponteiro. Assim, qualquer operao envolvendo o valor indicado pelo ponteiro deve conter o ponteiro acompanhado do asterisco. Caso utilizemos o prprio ponteiro, no estamos alterando o valor, e sim o endereo. De forma resumida:

ponteiro endereo *ponteiro valor muito importante ter isso ao criar funes que utilizem ponteiros. A confuso entre o uso de um ponteiro como endereo ou como valor a principal fonte de erros nestas situaes. O cdigo abaixo corpo de uma funo que utiliza ponteiros. Note que utilizamos um ponteiro e uma varivel normal como parmetros. Alm disso, sempre que utilizamos o valor referenciado pelo ponteiro durante a funo, utilizamos o asterisco antes do nome do ponteiro. void potencia (int *varivel, int elevado){ int original = 2; if (elevado ==0){ *varivel=1; Return; } If (elevado ==1) return; for (i;i<=elevado;i++){ *varivel=*varivel*original; } Quando utilizamos uma funo deste tipo, preciso que o programa passe um ponteiro como parmetro desta funo. Isto pode ser feito de duas maneiras: indicando um ponteiro que contenha o endereo, ou indicando simplesmente o endereo de uma varivel. Como j vimos, utilizamos o operador & antes do nome de uma varivel para obter o seu endereo. Assim, uma funo que utiliza ponteiros aceita em seu parmetro um ponteiro ou o endereo de uma varivel (&varivel). O programa abaixo mostra a utilizao de uma funo com chamada por referncia, tende em mente os cuidados descritos anteriormente. #include<stdio.h> void potencia (int *varivel, int elevado){ int original =2; if (elevado ==0){ *varivel=1;

Return; } if (elevado ==1) return; for (i=2;i<=elevado;i++){ *variavel=*variavel*original; } } int main ( ) { int dois=2; int j=5; potencia (&dois,j); printf(dois elevado a %d e: %d,j,dois); return(0); } 2.4 - Ponteiros e Vetores Veremos nestas sees que os ponteiros e vetores tm uma ligao muito forte. 2.4.1 - Vetores como ponteiros Vamos dar agora uma ideia de como o C trata vetores. Quando voc declara uma matriz da seguinte forma: Tipo_de_varivel nome_da_varivel [tam1][tam2]...[tamN]; o compilador C calcula o tamanho, em bytes, necessrio para armazenar a matriz. Este tamanho : tam1 X tam2 X tam3....X tamN X tamanho_do_tipo O compilador ento aloca este nmero de bytes em um espao livre de memria. O nome da varivel que voc declarou na verdade um ponteiro para o tipo de varivel da matriz. Este conceito fundamental. Eis porque: tendo alocado na memria o espao para a matriz, ele toma o nome da varivel (que um ponteiro) e aponta para o primeiro elemento da matriz.

Vamos ver agora um dos usos mais importantes dos ponteiros: a varredura sequencial de uma matriz. Quando temos que varrer todos os elementos de uma matriz de uma forma sequencial, podemos usar um ponteiro, o qual vamos incrementando. Qual a vantagem? Considere o seguinte programa para zerar uma matriz main( ) { float matrx [50][50]; int i,j; for (i=0;i<50;i++) for (j=0;j<50;j++); matrx [i][j] = 0.0; } Podemos reescrev-lo de uma maneira muito mais eficiente como sendo: main( ) { float matrx [50][50]; float *p; int count; p=matrx[0]; for (count=0;count<2500;count++) { *p=0.0; } } Voc consegue ver porque o segundo programa mais eficiente? Simplesmente porque cada vez que se faz matrx[i][j] o programa tem que calcular o deslocamento para dar ao ponteiro. Ou seja, o programa tem que calcular 2500 deslocamentos. No segundo programa o nico clculo que deve ser feito o de um incremento de ponteiro. Fazer 2500 incrementos em um ponteiro muito mais rpido que calcular 2500 deslocamentos completos.

2.4.2 - Ponteiros como vetores Sabemos agora que, na verdade, o nome de um vetor um ponteiro constante. Sabemos tambm que podemos indexar o nome de um vetor. Como consequncia podemos tambm indexar um ponteiro qualquer. Vejamos o programa a seguir: #include <stdio.h> main( ) { int matrx [10] = {1,2,3,4,5,6,7,8,9,10}; int *p; p=matrx; printf(O terceiro elemento do vetor e: %d,p[2]); return (0); } 2.4.3 Vetores de Ponteiros Podemos construir vetores de ponteiros como declaramos vetores de qualquer outro tipo. Uma declarao de um vetor de ponteiros poderia ser: int *pmatrx[10]; No caso acima, pmatrx um vetor que armazena 10 ponteiros para inteiros.

2.4.4 -Ponteiros para Ponteiros Podemos ento criar ponteiros que apontam para o endereo de outro ponteiro, como vemos no cdigo exemplo abaixo: int inteiro=1024; int *pontinteiro =&inteiro; int **pontponteiro=&pontinteiro; 3-Exerccios 3.1 Elabore um programa genrico de utilizao de ponteiro, no qual haja passagem de valor para o mesmo por meio de varivel comuns.

1 /* Exercicio 3.1 */ 2 #include <stdio.h> 3 4 int main( ) 5{ 6 int num,valor; 7 int *p; 8 num=55; 9 p=&num; /* Pega o endereo de num */ 10 valor=*p; /* valor igualado a num de maneira indireta */; 11 printf (\n\n%d\n,valor); 12 printf (Endereo para onde o ponteiro aponta: %p\n,p); 13 printf (Valor de variavel apontada: %d\n,*p); 14 15 return(0); 16} TELA
55 Endereco para onde o ponteiro aponta: 0028FF04 Valor de variavel apontada:55

No programa acima vemos um primeiro exemplo do funcionamento dos ponteiros. No programa, o cdigo %p usado na funo printf( ) indica funo que ela deve exibir um endereo. 3.2 Elabore um programa qualquer que apresente a utilizao de ponteiro e a passagem de valor para o ponteiro a partir de outra varivel. Mostre tambm o carter complementar dos operadores de ponteiros & e *. 1 /* Exercicio 3.2 */ 2 #include <stdio.h> 3 4 int main ( void ) 5 { 6 int a; /* a um inteiro*/ 7 int *aPtr; /* aPtr um ponteiro para um inteiro*/ 8 a = 7; 9 10 aPtr = &a; /* aPtr definido para o endereo de a*/ 11 12 printf (O endereo de a %p,&a); 13 printf ( \n O endereo de aPtr %p,aPtr); 14 15 printf (\n\n O valor de a %d,a); 16 printf (\n O valor de *aPtr %d,*aPtr); 17

10

18 19 20 21 22} TELA

printf (\n\n Mostrando que * e & so complementos um do outro \n &*aPtr = %p \n*&aPtr = %p\n,&*aPtr,*&aPtr); return (0); /* indica concluso bem-sucedida */; /* fim do main */

O endereo de a 0012FF7C O endereo de aPtr 0012FF7C O valor de a 7 O valor de *aPtr 7 Mostrando que * e & so complementos um do outro. &*aPtr = 0012FF7C *&aPtr = 0012FF7C

Observe que o endereo de a e o valor de aPtr so idnticos na sada, confirmando assim, que o endereo a realmente atribudo varivel de ponteiro aPTR. Os operadores & e * so complementos um do outro, quando ambos so aplicados consecutivamente a aPtr em qualquer ordem, o mesmo resultado impresso. 3.3 Elabore um programa genrico que demonstre a utilizao de ponteiros apontado para outros ponteiros. 1 /* Exerccio 3.3 */ 2 3 #include <stdio.h> 4 5 int main ( ) 6{ 7 8 // Uma varivel int. 9 int iVar=1000; 10 // Um ponteiro para int, 11 //inicializando com o endereo de iVar. 12 int *iPtr=&iVar; 13 14 // Um ponteiro para ponteiro para int, inicializando com o endereo de iPtr. 15 int **iPtrPtr = &iPtr; 16 17 //Exibe o valor da varivel, acessando-a via iPtr. 18 printf (Acessando valor via ponteiro\n); 19 printf ( \n iVar = %d,*iPtr); 20 // Exibe o valor da varivel, acessando-o via iPtrPtr. 21 22 printf (Acessando valor via ponteiro para ponteiro\n); 23 printf (\n iVar= %d,**iPtrPtr);

11

24 return(0); 25} //fim de main ( )

TELA
Acessando o valor via ponteiro iVar=1000 Acessando o valor via ponteiro para ponteiro iVar=1000

3.4 Elabore um programa que calcule o cubo de uma varivel utilizando ponteiro. 1 /* Exerccio 3.4*/ 2 3 #include <stdio.h> 4void cubebyreference (int *nPtr); 5 6 int main ( ) 7{ 8 int number=5; /* inicializa nmero */ 9 printf ( O valor original do numero e %d:, number); 10 11 /* passa endereo do nmero a cubebbyreference */ 12 cubebyreference (&number); 13 14 printf (\n O novo valor do numero e %d\n, number); 15 return (0); /* indica concluso bem-sucedida */ 16} /* fim de main */ 17 18 /* Calcula o cubo de *nPtr; modifica varivel number em main */ 19 void cubebyreference (int *nPtr) 20{ 21 *nPtr= *nPtr * *nPtr * *nPtr; /* cubo de *nPtr */ 22} /* fim da funo cubebyreference */ TELA
O valor original do numero e 5 O novo valor do nmero e 125

Observamos no programa a passagem por referncia. O endereo de number passado funo cubebyreference. A funo cubebyreference usa como parmetro um ponteiro para int chamado nPtr. A funo desreferencia o ponteiro e calcula o cubo do valor para o qual nPtr aponta, e depois atribui o resultado a *nPtr (que na realidade number na funo main), mudando assim o valor de number em main.

12

3.5 Elabore um programa que acesse os elementos de um vetor a partir de um ponteiro. 1 /* Exerccio 3.5 */ 2 3 #include <stdio.h> 4 5 // Ilustra o uso de um ponteiro para vetor. 6 7 // Declara um vetor de inteiro. 8 intvetor [] = {10,15,29,36,18}; 9 int main ( ) 10{ 11 // Declara e inicializa um ponteiro para inteiros. 12 int *vetorpont = intvetor; 13 // o mesmo que: int *vetorpont=&intvetor[0]; 14 int i; 15 16 // Exibe os elementos do vetor, acessando-os via ponteiro. 17 18 for (i=0; i < 5; i++) 19 { 20 printf ( intvetor [%d] = %d,i+1,*vetorpont++\n); 21 return (0); 22 } 23} // fim de main ( ) TELA
Intvetor[1]=10 Intvetor[2]=15 Intvetor[3]=29 Intvetor[4]=36 Intvetor[5]=18

A principal ideia que se tira desse programa a possibilidade de inicializar um ponteiro para o primeiro elemento do vetor, tal fato pode ser notado nas passagens da linha 12 e 13 do cdigo fonte. 4-Introduo a Alocao dinmica de memria Nesta etapa iremos aprender como funciona a alocao dinmica de memria, bem como o porqu de sua utilizao e os benefcios trazidos por tal ferramenta.

4.1- Alocao dinmica de memria Criar e manter estruturas dinmicas de dados exige uma alocao dinmica de memria a capacidade que um programa tem de obter mais espao de memria durante a execuo para manter novos ns, e para liberar espao do qual no se precisa mais. O limite para alocao dinmica de memria pode ser to grande quanto a quantidade de

13

memria fsica disponvel no computador, ou a quantidade de memria virtual disponvel em um sistema de memria virtual. Frequentemente, os limites so muito baixos, porque a memria disponvel deve ser compartilhada entre muitas aplicaes. O padro C ANSI define apenas 4 funes para o sistema de alocao dinmica, disponveis na biblioteca stdlib.h. No entanto, existem diversas outras funes que so amplamente utilizadas, mas dependentes do ambiente e compilador. Nas sees posteriores sero abordadas apenas estas funes bsicas. 4.1.1 malloc A funo malloc( ) serve para alocar memria e tem a seguinte sintaxe: varivel= (tipo*) malloc (tamanho*, sizeof(tipo)) varivel: varivel declarada inicialmente como um ponteiro; malloc: funo responsvel por alocar memria. Tamanho*: quantidade de posies do vetor; sizeof: operador que retorna o nmero de bytes demandado pelo vetor; tipo: refere-se ao tipo da varivel. Podendo ser: float, int, e char. Depende de como o usurio a declarou inicialmente. Vejamos um exemplo de alocao dinmica com malloc( ): #include <stdio.h> #include <stdlib.h> main (void) { int *p; int a; ... /* determina o valor de a em algun lugar */ p = (int *)malloc(a,sizeof,(int)); if (p==NULL) { Printf (Erro! Memoria nao alocada\n); return(0); } .... return(0);

14

} No exemplo acima. alocada memria suficiente para se colocar a nmeros inteiros. O operador sizeof retorna o nmero de bytes de um inteiro. Ele til para se saber o tamanho de tipos. O ponteiro que malloc( ) retorna convertido para um int* pelo cast e atribudo a p. A declarao seguinte testa se a operao foi bem sucedida. Se no tiver sido, p ter valor nulo. 4.1.2 calloc A funo calloc( ) tambm serve para alocar memria, mas possui um proposito um pouco diferente: varivel = (tipo*) calloc(tamanho,sizeof(tipo)) A principal diferena entre malloc( ) e calloc( ) que calloc apaga a memria que aloca, e malloc no. 4.1.3 realloc A funo realloc( ) altera o tamanho de um objeto alocado anteriormente por uma chamada a malloc, a callloc ou a realloc. O contedo original do objeto no modificado, desde que a memria alocada seja maior que a quantidade alocada anteriormente. Caso contrrio, o contedo se mantm inalterado at alcanar o tamanho do novo objeto. Tal funo tem a seguinte sintaxe: void *realloc (void *ptr, size_t size) A funo realloc recebe dois argumentos um ponteiro para o objeto original (ptr) e o novo tamanho do objeto (size). Se ptr for NULL, realloc funcionar da mesma forma que malloc. Se size for 0 e ptr for diferente de NULL, a memria para objeto ser liberada. Por outro lado, se ptr for diferente de NULL e size for maior que zero, realloc tentar alocar um novo bloco de memria para o objeto. Se o novo espao no puder ser alocado, o objeto apontado por ptr no ser alterado. A funo realloc retornar ou um ponteiro para a memria realocada ou um ponteiro NULL para indicar que a memria no foi realocada. 4.1.4 free Quando alocamos memria dinamicamente necessrio que ns a liberemos quando ela no for mais necessria. Para isto existe a funo free( ) cuja sintaxe : free (varivel) A funo free libera memria ou seja, a memria retornada ao sistema, de modo que possa ser realocada no futuro. Vamos ver o exemplo mostrado anteriormente usando a funo free: #include <stdio.h> #include <stdlib.h> main (void) {

15

int *p; int a; ... /* determina o valor de a em algun lugar */ p = (int *)malloc(a,sizeof,(int)); if (p==NULL) { Printf (Erro! Memoria nao alocada\n); return(0); } .... free(p); return(0); } 5. Exerccios 5.1 Elabore um programa genrico que crie um vetor e imprima na tela o quadrado dos primeiros 40 nmeros deste vetor 1 #include <stdio.h> 2 #include <stdlib.h> 3 4 main( ) 5{ 6 int *v,t; /* declarao de uma varivel ponteiro do tipo inteiro */ 7 8 v=(int*)calloc(80, sizeof(int)); /* alocao dinmica de memria */ 9 if (v ==NULL){ /* Condio para verificao de alocao */ 10 printf (Erro de alocacao de memoria); exit;} 11 else 12 { 13 for (t=0;t<40;t++) /* lao de repetio para limitao dos 40 primeiros nmeros */ 14 v[t]=t*t; 15 for (t=0;t<40;t++) 16 printf (%d, v[t]); 17 } 18 19 free (v); /* liberando a memria alocada anteriormente para utilizao do sistema */ 20 return(0); 21}

16

O programa acima mostra a utilizao de forma bastante simples da ferramenta de alocao dinmica de memria. O cdigo acima poderia ter sido feito de forma tradicional, isto , fazendo uso do lao de repetio com o nmero ,previamente definido, de elementos. Nos prximos exerccios sero mostrados os benefcios e a real relevncia da ferramenta de alocao dinmica de memria. 5.2 Crie um programa que faz a alocao dinmica de memria para alocao de um vetor de dimenso n, e o imprima na ordem inversa. 1 /* Exerccio 5.1 */ 2 3 #include <stdio.h> 4 #include <stdlib.h> 5 6 int main (void) 7{ 8 int i, n, *vetor, *pt; 9 10 printf (Informe a dimensao do vetor: ); 11 scanf (%d,&n); 12 13 vetor = (int*)calloc(n,sizeof(int)); /* alocao dinmica de memria */ 14 if (vetor == NULL){ 15 printf (Erro de alocacao de memoria!); 16 return(0); 17 } 18 for (i=0;i<n;i++) { 19 printf (Informe o elemento %d: , i); 20 scanf (%d, (vetor + i)); 21 } 22 printf (\n Vetor : ); 23 24 for (pt=vetor;pt < (vetor + n); pt++ 25 printf (%d,*pt); 26 27 printf (\n Vetor invertido: ); 28 for (i=n-1;i>=0;i--){ 29 printf (%d, vetor[i]); 30 printf (\n); 31 } 32 free (vetor); 33 return(0); 34 } 5.3 Crie um programa genrico que faz a alocao dinmica de memria para alocao de um matriz. 1 /* Exerccio 5.3 */ 2

17

3 #include <stdio.h> 4 #include <stdlib.h> 5 6 int main (void) 7{ 8 int i, j, m, n, **matriz, **pt; 9 10 printf (Informe a dimensao da matriz: ); 11 scanf (%d%d, &m,&n); 12 13 matriz = (int**)malloc(m*n,sizeof(int*)); 14 if (matriz == NULL){ 15 printf (Erro de alocacao de memoria); 16 return(0); 17 } 18 for (pt = matriz, i=0; i< m; i++;pt++) { 19 *pt = (int*)malloc(n*m,sizeof(int)); 20 if (*pt == NULL) { 21 printf (Erro de alocacao de memria); 22 return(0); 23 } 24 } 25 26 for (i=0;i<m;i++) { 27 for ( j=0;j<n;j++) { 28 printf (Informe o elemento (%d,%d): , i,j); 29 scanf (%d, &matriz[i][j]); 30 } 31 } 32 33 printf (\n Matriz: \n); 34 pt = matriz 35 for (i=0;i<m;i++){ 36 for (j=0;j<n;j++) { 37 printf (%d, *(*(pt+i)+j)); 38 printf (\n); 39 } 40 } 41 printf (\n); 42 43 for (i=0;i<m;i++) 44 free (matriz[i]); 45 46 free (matriz); 47 return(0); 48 } Observe por fim que as linhas em que ocorrem a alocao dinmica de memria no programa acima podem ser substitudas de forma equivalente pelas linhas a seguir:

18

matriz = (int**) malloc(m*n,sizeof(int*)); for (i=0;i<m;i++) matriz[i] = (int*) malloc(m*n,sizeof(int));

5.4 Elabore um programa que leia e multiplique um vetor coluna de dimenso (Nx1) por um vetor linha de dimenso (1xP). As dimenses mximas so 30x1 e 1x30. N e P so conhecidos em tempo de execuo. 1 #include <stdio.h> 2 #include <conio.h> 3 #include <stdlib.h> 4 5 main (void) 6 7{ 8 9 float *VetorLinha, *VetorColuna, *MatrizResultado; 10 int N, P, linha, coluna; 11 12 do { 13 printf (Qual a dimensao de P?); 14 scanf (%d,&P); 15} while ( (P>30) || (P<0)); 16 17 VetorLinha = (float *) calloc( P, sizeof(float)); /* alocao dinmica */ 18 19 do { 20 printf (Qual a dimensao de N?); 21 scanf (%d,&N); 22 } while ( (N>30) || (N<0)); 23 24 VetorColuna = (float *) calloc( N, sizeof(float)); /* alocao dinmica */ 25 MatrizResultado = (float *)calloc( N*P, sizeof(float)); /*alocao dinmica */ 26 27 // teste de alocao dinmica 28 if (!MatrizResultado || !VetorLinha || !VetorColuna) 29 { 30 printf (Erro de alocacao de memoria. Programa terminado); 31 getch( ); 32 exit; 33 } 34 35 for (linha=0;linha<N;linha++){ 36 printf ( Elemento %d: , linha); 37 scanf (%f, (VetorLinha + linha)); /* uso com ponteiros */ 38 } 39 40 for (coluna=0; coluna<P;coluna++){

19

41 42 43 } 44 45 46 47

printf (Elemento %d: , coluna); scanf (%f, (VetorColuna + coluna)); /* uso com ponteiros */ for (linha=0;linha<N;linha++){ for (coluna=0;coluna<P;coluna++){ /* produto utilizando ponteiros */ *(MatrizResultado + linha*P + coluna) = *(VetorLinha+linha) * *(VetorColuna+coluna); }

48 49 } 50 51 for (linha=0;linha<N;linha++){ 52 for (coluna=0;coluna<P;coluna++){ 53 printf (%f, *(MatrizResultado + linha*P + coluna)); /* ponteiros */ 54 } 55 printf (\n); 56 } 57 getch( ); 58 free (VetorLinha); 59 free (VetorColuna); 60 free (MatrizResultado); 61} 62 return(0); TELA
Qual a dimensao de P?2 Qual a dimensao de N?2 Elemento 0: 10 Elemento 1: 11 Elemento 0: 13 Elemento 1: 14 130.000000 140.000000 143.000000 154.000000

Percebe-se o quanto importante a real aprendizagem e domnio do conhecimento de ponteiros neste programa. Isso se evidencia, por exemplo, nas linhas 47 e 53. Em tais linhas necessria a combinao da correta aplicao de operaes entre ponteiros, passagem de valor e o cuidado com a sintaxe. 5.5 Elabore um programa que leia e ordene um vetor de estruturas contendo N valores reais e N nomes (N mximo 1000. Os nomes no ultrapassam 50 caracteres). O vetor resultante deve ser ordenado pelos valores numricos, de forma crescente, a partir da primeira posio do vetor. Para ordenar o vetor compare cada elemento com o seguinte e troque-os de posio se necessrio. Faa isto da primeira at a ltima posio do vetor. Se, nesta varredura, houver ao menos uma troca de posies, ser necessrio repetir o procedimento. 1 /* Exerccio 5.5 */

20

2 3 #include <stdio.h> 4 #include <conio.h> 5 #include <stdlib.h> 6 #include <string.h> 7 8 /* A diretiva de compilao abaixo define a constante TAM_MAX como 1000. 9 Este valor s pode ser alterado antes da compilacao do programa. Para testar o progra 10 ma altere TAM_MAX para um valor pequeno e compile o programa com este valor. 11 Uma vez funcionando, retorne ao valor original e compile novamente o programa */ 12 # define TAM_MAX 1000 13 14 struct Prova { 15 float Valor; 16 char Nome[51]; /* Lembrar de declarar sempre um posio a mais */ 17 }; 18 19 void main (void) 20 { 21 struct Prova *Vetor; 22 int i, troca; 23 float aux_valor; 24 char aux_nome[51]; 25 26 Vetor = (struct Prova *)calloc(TAM_MAX,sizeof(struct Prova)); 27 if (!Vetor) { 28 printf (Erro na locacao de memoria.); 29 getch( ); 30 exit; 31 } 32 for (i=0;i<TAM_MAX;i++){ 33 printf (Digite o nome [%d]: ,i); 34 scanf (%s, (Vetor + i) Nome); 35 printf (Digite o valor [%d]: , i); 36 scanf (%f, &(Vetor +i) Valor); 37 } 38 39 do { 40 troca=0; 41 for (i=0;i<TAM_MAX -1;i++) { 42 if ((*Vetor+i)).Valor > (*(Vetor+i+1)).Valor) { 43 troca=1; 44 aux_valor = (*(Vetor+i)).Valor; 45 (*(Vetor+i+1)).Valor = (*(Vetor+i+1)).Valor; 46 (*(Vetor+i+1)).Valor = aux_valor; 47 48 strcpy (aux_nome, (Vetor+i) Nome); 49 strcpy ((Vetor+i) Nome, (Vetor+i+1)Nome); 50 strcpy ((Vetor+i+1)Nome,aux_nome); 51 }

21

52 } 53 } while (troca==1); 54 for (i=0;i<TAM_MAX;i++) { 55 printf (%s \t %f \n, (Vetor+i)Nome, (Vetor+i)Valor); /* ponteiros */ 56 } 57 getch( ); 58 free (Vetor); 59 return(0); 60 } Nota-se um maior grau de complexidade neste programa j que o mesmo associa elementos como alocao dinmica de memria, vetor de estrutura contendo campos como Nome e Valor Alm disso, ressaltamos a passagem que ocorre de modo diferenciado, vistas nas linhas 49 e 55, atravs do operador ao se tratar de campos de uma varivel do tipo estrutura.

22

6 - REFERNCIAS BIBLIOGRFICAS Deitel, P.J. C: como programar / Paul Deitel, Harvey Deitel; traduo Daniel Vieira; reviso tcnica Csar Caetano. 6 ed So Paulo: Pearson Prentice Hall, 20011. Andrade Cava, R. Algoritmos e Programao do Curso de Cincia da Computao; Universidade Catlica de Pelotas, 1999, Rio Grande do Sul. Cardoso Mesquita, R. Apostila do Curso de Linguagem C. Universidade Federal de Minas gerais, Outubro de 1988, Goinia. Mesquita Filho, J. Introduo Cincia da Computao Curso de C++ Bsico. Departamento de matemtica, Universidade Estadual Paulista Faculdade de Engenharia de Ilha Solteira, 2010, Ilha Solteira.

You might also like