Post on 14-Nov-2018
Ponteiros e Tabelas
Endereços e ponteiros
Ponteiros e argumentos de funções
Ponteiros e tabelas
Aritmética de endereços
Ponteiros para caracteres
Tabelas de ponteiros e ponteiros para ponteiros
Tabelas multi-dimensionais
Inicialização de tabelas de ponteiros
Argumentos da linha de comandos
Ponteiros para funções
AED 2003/2004 – p.1/37
Ponteiros e Endereços
Um ponteiro representa um endereço de memória
O operador unário & aplicado a x representa oendereço de x
#include <stdio.h>
main ()
{
int y,x=3;
int *px = &x;
y = *px;
*px = 0;
printf("%d %d\n",x,y);
}
AED 2003/2004 – p.2/37
Utilização de Ponteiros
*px pode ser usado em vez de x
A declaração int *xpto() significa que xpto() retorna umponteiro para um inteiro
A declaração void abcd(char *) significa que a função abcdaceita como argumento um ponteiro para caracteres
A prioridade de & e * é superior à dos operadoresaritméticos
y = *px + 1 funciona como esperado
++*px incrementa o valor de x
(*px)++ (os parênteses são necessários)
AED 2003/2004 – p.3/37
Passagem de Parâmetros para Funções
Em C, os parâmetros são passados por valor
swap(int a, int b)
{
int aux;
aux = a;
a = b;
b = aux;
}
Não funciona como pretendido
AED 2003/2004 – p.4/37
Passagem de Parâmetros por Referência
Passagem por referência consegue-se enviando osendereços
swap(int *a, int *b)
{
int aux;
aux = *a;
*a = *b;
*b = aux;
}
Chamada deverá ser swap(&x, &y)
AED 2003/2004 – p.5/37
Leitura de um Inteiro#include <ctype.h>
#include <stdio.h>
int getch(void);
void ungetch(int);
/* getint: get next integer from input into *pn */
int getint(int *pn) {
int c, sign;
while (isspace(c = getch())) ; /* skip white space */
if (!isdigit(c) && c != EOF && c != ’+’ && c != ’-’) {
ungetch(c); /* it is not a number */
return 0;
}
sign = (c == ’-’) ? -1 : 1;
if (c == ’+’ || c == ’-’) c = getch();
for (*pn = 0; isdigit(c); c = getch())
*pn = 10 * *pn + (c - ’0’);
*pn *= sign;
if (c != EOF) ungetch(c);
return c;
}AED 2003/2004 – p.6/37
Ponteiros e Tabelas
Em C, existe uma relação entre ponteiros e tabelas
int a[10];
int *pa;
int x;
int i = 3;
pa = &a[0]; /* pa fica a apontar para a[0] */
x = *pa; /* Copia o conteudo de a[0] para x */
x = *(pa+1); /* Copia para x o conteudo de a[1] */
x = *(pa+i); /* Copia para x o conteudo de a[i] */
strlen(”Hello world”); /* string constant */
strlen(arr); /* char array[100] */
strlen(ptr); /* char *ptr */
AED 2003/2004 – p.7/37
Exemplo
/* strlen: return length of string s */int strlen(char *s){
int n;
for (n = 0; *s != ’\0’; s++)n++;
return n;}
AED 2003/2004 – p.8/37
Representação do Endereço Zero
Ponteiro especial para representar zero.
int *y;
y = NULL;...if (!y) { /* problem handling code */ ...
AED 2003/2004 – p.9/37
Ponteiros e Tabelas
Nos argumentos de uma função, a declaração int *p;declara o mesmo que int p[];
A declaração int p[100]; declara uma tabela com 100inteiros;
A declaração int *p não aloca qualquer espaço;
A função malloc(int size) aloca um espaço de dimensãosize
A declaração int *p = malloc(100*sizeof(int)); é equivalentea int p[100];
O espaço pode ser libertado com a chamada free(p);
AED 2003/2004 – p.10/37
Ponteiros para Caracteres
Uma constante do tipo string "Hello world" é uma tabelade caracteres
char *pmessage;
pmessage = "Hello world";/* Copia apenas os ponteiros */
As declarações
char amessage[] = "Hello world";char *pmessage = "Hello world";
São diferentes. Porquê ?AED 2003/2004 – p.11/37
Ponteiros para Caracteres
/* strcpy: copy t to s; array subscript version */
void strcpy(char *s, char *t) {
int i;
i = 0;
while ((s[i] = t[i]) != ’\0’)
i++;
}
/* strcpy: copy t to s; pointer version */
void strcpy(char *s, char *t) {
while ((*s = *t) != ’\0’) {
s++;
t++;
}
}
AED 2003/2004 – p.12/37
Strcpy: Versão 3
/* strcpy: copy t to s; pointer version 2 */
void strcpy(char *s, char *t) {
while ((*s++ = *t++));
}
AED 2003/2004 – p.13/37
Mais Funções para Strings
/* strcmp: return <0 if s<t, 0 if s==t, >0 if s>t */
int strcmp(char *s, char *t)
{
for ( ; *s == *t; s++, t++)
if (*s == 0)
return 0;
return *s - *t;
}
AED 2003/2004 – p.14/37
Aritmética de Endereços
Operações válidas sobre ponteiros:Adição/subtração de inteiro:
p1 + k;p1 - k;
Subtração de ponteiros (numa mesma tabela):p1 - p2;
Atribuição de 0 ou de ponteiro:p1 = 0;p1 = p2;
Comparação com 0 ou com ponteiro:p1 == 0;p1 == p2;
AED 2003/2004 – p.15/37
Tabelas de Ponteiros
Exemplo: ordenação de cadeias de caracteres
Usa-se mesmo algoritmo que para ordenação deinteiros
Evita-se copiar strings usando tabelas de ponteiros
int i;
/* Representa uma tabela de ponteiros para caracteres */
char *lineptr[MAXLINES];
readlines(lineptr,MAXLINES);
for (i=0; i< MAXLINES; i++)
printf("Linha %d e %s\n",i,lineptr[i]);
AED 2003/2004 – p.16/37
Ler e Guardar Linhas/* readlines: le linhas de entrada */
int readlines(char *lineptr[], int maxlines)
{
int len, nlines;
char *p, line[MAXLEN];
nlines = 0;
while ((len = getline(line, MAXLEN)) > 0)
if (nlines >= maxlines || (p = malloc(len)) == NULL)
return -1;
else {
line[len-1] = ’\0’; /* delete newline */
strcpy(p, line);
lineptr[nlines++] = p;
}
return nlines;
}
AED 2003/2004 – p.17/37
Ler, Ordenar e Imprimir linhas
#include <stdio.h>
#include <string.h>
#define MAXLINES 5000
char *lineptr[MAXLINES]; /* Tabela de ponteiros */
int readlines(char *lineptr[], int nlines);
void writelines(char *lineptr[], int nlines);
void qsort(char *lineptr[], int left, int right);
main() {
int nlines;
if((nlines = readlines(lineptr, MAXLINES)) >= 0){
qsort(lineptr, 0, nlines-1);
writelines(lineptr, nlines);
return 0;
} else {
printf("error: input too big to sort\n");
return 1;
}
}AED 2003/2004 – p.18/37
Quicksort para Strings
void qsort(char *v[], int left, int right)
{
int i, last;
void swap(char *v[], int i, int j);
if(left >= right)
return;
swap(v, left, (left + right)/2);
last = left;
for(i = left+1; i <= right; i++)
if(strcmp(v[i], v[left]) < 0)
swap(v, ++last, i);
swap(v, left, last);
qsort(v, left, last-1);
qsort(v, last+1, right);
}
AED 2003/2004 – p.19/37
Troca e Impressão de Linhas
/* swap: swap v[i] and v[j] */
void swap(char *v[], int i, int j)
{
char *tmp;
tmp = v[i];
v[i] = v[j];
v[j] = tmp;
}
void writelines(char *lineptr[], int nlines)
{
int i;
for(i=0; i<nlines; i++)
printf("%s\n", lineptr[i]);
}
AED 2003/2004 – p.20/37
Tabelas Multi-Dimensionais
A declaração int x[NROWS][NCOLS] declara uma matriz
É equivalente a int *x[NROWS]
Elemento na linha i e coluna j é x[i][j]
int x[NROWS][NCOLS] aloca o espaço NROWS*NCOLS
int *x[NROWS] aloca o espaço para NROWS ponteiros
Na prática, ponteiros para tabelas são mais usados
Qualquer número de dimensões pode ser usado
Primeira dimensão pode não ser especificada
AED 2003/2004 – p.21/37
Inicialização de Tabelas de Ponteiros
/* month_name: devolve nome do i-esimo mes */
char *month_name(int n)
{
/* Inicializa tabela de ponteiros */
static char *name[] = {
"Illegal month",
"January", "February", "March",
"April", "May", "June",
"July", "August", "September",
"October", "November", "December"
};
return (n < 1 || n > 12) ? name[0] : name[n];
}
AED 2003/2004 – p.22/37
Argumentos da Linha de Comandos
argv[0] é o nome do programa
argv[i] é i-ésimo argumento
Programa "echo"
echo hello world gera hello world
main(int argc, char *argv[]) {int i;
for(i=1; i<argc; i++)printf("%s ",argv[i]);
printf("\n");return 0;
}
AED 2003/2004 – p.23/37
Ponteiros para Funções
É possível declarar ponteiros para funções
Uma função pode ser passada como argumento paraoutra
/* Funcao qsort generica */
void qsort(char *v[],int left, int right, int (*comp)(char *, char *);
...
if ((*comp)(v[i],v[j])) {
...
}
/* Uso da funcao qsort */
char *lineptr[MAXLINES]; /* Tabela de ponteiros */
int strcmp(char *, char *);
...
qsort(lineptr, 0, nlines-1, strcmp); /*Funcao strcmp como argumento*/
AED 2003/2004 – p.24/37
Multiplicação de Matrizes
#include <stdlib.h>
#define MATDIM 500
int matA[MATDIM][MATDIM], matB[MATDIM][MATDIM], matC[MATDIM][MATDIM];
void init()
{
int i, j;
for (i=0; i<MATDIM; ++i)
for (j=0; j<MATDIM; ++j) {
matA[i][j] = i+j; matB[i][j] = i-j;
}
}
void prod()
{
/* funcao para multiplicar matrizes A e B */
}
(cont.)
AED 2003/2004 – p.25/37
Multiplicação de Matrizes
int sum()
{
int i, j, sum = 0;
for (i=0; i<MATDIM; ++i)
for (j=0; j<MATDIM; ++j)
sum += matC[i][j];
return sum;
}
main()
{
init();
prod();
printf("Soma: %d\n", sum());
}
AED 2003/2004 – p.26/37
Versão 1void prod()
{
int i, j, k;
for (i=0; i<MATDIM; ++i)
for (j=0; j<MATDIM; ++j) {
matC[i][j] = 0;
for (k=0; k<MATDIM; ++k)
matC[i][j] += matA[i][k] * matB[k][j];
}
}
AED 2003/2004 – p.27/37
Versão 2 – Utilização da Transposta
void init()
{
int i, j;
for (i=0; i<MATDIM; ++i)
for (j=0; j<MATDIM; ++j) {
matA[i][j] = i+j;
matB[j][i] = i-j;
}
}
void prod()
{
int i, j, k;
for (i=0; i<MATDIM; ++i)
for (j=0; j<MATDIM; ++j) {
int *pC = &(matC[i][j]);
int *pA = &(matA[i][0]);
int *pB = &(matB[j][0]);
*pC = 0;
for (k=0; k<MATDIM; ++k)
*pC += *(pA++) * *(pB++);
}
}
AED 2003/2004 – p.28/37
Versão 3 – Optimizar Acessos
void prod()
{
int i, j, k, t;
int *pA, *pB;
for (i=0; i<MATDIM; ++i)
for (j=0; j<MATDIM; ++j) {
pA = matA[i];
pB = matB[j];
t = 0;
for (k=0; k<MATDIM; ++k)
t += *(pA++) * *(pB++);
matC[i][j] = t;
}
}
AED 2003/2004 – p.29/37
Versão 4 – Comparar Ponteiros
void prod()
{
int i, j, k, t;
int *pA, *pB, *pF;
for (i=0; i<MATDIM; ++i)
for (j=0; j<MATDIM; ++j) {
pA = &(matA[i][0]);
pB = &(matB[j][0]);
pF = pA + MATDIM;
t = 0;
for (; pA<pF; )
t += *(pA++) * *(pB++);
matC[i][j] = t;
}
}
AED 2003/2004 – p.30/37
Tempos de Execução
Versão 1: 1.65s
Versão 2: 0.61s
Versão 3: 0.38s
Versão 4: 0.35s
AED 2003/2004 – p.31/37
Stack de Inteiros com Tabela Dinâmica
Utilizar tabela dinâmica para implementar stack devalores inteiros com tamanho arbitrário
AED 2003/2004 – p.32/37
istack.hextern void st_init();
extern void st_push(int value);
extern int st_pop();
extern int st_is_empty();
AED 2003/2004 – p.33/37
istack.c – Versão 1#include <stdlib.h>
#define MAXVALUE 5
static int *st_value;
static int st_top;
static int st_max;
static void increase_stack_size()
{
int i, *ptmp = st_value, *pa, *pb, *pf;
st_max = 2 * st_max;
st_value = (int*) malloc(st_max * sizeof(int));
for (pa=ptmp, pb=st_value, pf=st_value+st_top; pb<=pf; )
*(pb++) = *(pa++);
free(ptmp);
}
(cont.)AED 2003/2004 – p.34/37
istack.c – Versão 1void st_init()
{
st_top = -1;
st_max = MAXVALUE;
st_value = (int*) malloc(st_max*sizeof(int));
}
void st_push(int value)
{
if (st_top >= st_max-1) increase_stack_size();
st_value[++st_top] = value;
}
int st_pop()
{
if (!st_is_empty()) return st_value[st_top--];
return -1;
}
int st_is_empty() {
return st_top == -1;
}
AED 2003/2004 – p.35/37
istack.c – Versão 2#include <stdlib.h>
#define MAXVALUE 5
static int *st_value;
static int *st_sup;
static int st_max;
static void increase_stack_size()
{
int i, *ptmp = st_value, *pa, *pb;
int diff = st_sup - st_value;
st_max = 2 * st_max;
st_value = (int*) malloc(st_max * sizeof(int));
for (pa=ptmp, pb=st_value; pa<st_sup; )
*(pb++) = *(pa++);
free(ptmp);
st_sup = st_value + diff;
}
AED 2003/2004 – p.36/37
istack.c – Versão 2void st_init()
{
st_max = MAXVALUE;
st_value = (int*) malloc(st_max*sizeof(int));
st_sup = st_value;
}
void st_push(int value)
{
if (st_sup == st_value+st_max)
increase_stack_size();
*(st_sup++) = value;
}
int st_pop()
{
if (!st_is_empty()) return *(--st_sup);
return -1;
}
int st_is_empty() {
return st_sup == st_value;
}AED 2003/2004 – p.37/37