Вы находитесь на странице: 1из 290

Linguagem C

Prof. Elda Regina


elda_etec@hotmail.com Fevereiro/2011

Introduo

Introduo

C - Dennis Ritchie (Laboratrios Bell)


Inicialmente para mquinas do tipo PDP-1

(com UNIX).

Depois para os IBM PC e compatveis (ambientes MS DOS, e MS Windows)

O Standard ANSI-C

Verso C que segue a norma da American National Standard Institute (ANSI), e da International Standards Organization (ISO).
Os Compiladores da Borland foram os primeiros a oferecer compatibilidade com esta norma (os compiladores de Turbo C a partir da verso 2.0).

Caractersticas

A linguagem C muito famosa e muito utilizada:


pela conciso de suas instrues; pela facilidade de desenvolvimento de Compiladores C; pela rapidez de execuo de programas;

e principalmente pelo fato que o poderoso sistema operacional Unix foi escrito em C.

Um Programa Simples
#include <stdio.h>
/* um programa bem simples que imprima: Ate logo.

*/

void { }
6

main ()

printf("Ate logo. ");

Exemplo 1
#include <stdio.h> #define B 20 int a,s; int somar (int x, int y) { return (x+y); } void main () { scanf("%d",&a); s=somar(a,B); printf("%d",s); }
7

/* 1 */ /* 2 */ /* 3 */ /* 4 */

/* 5 */ /* 6 */ /* 7 */ /* 8 */

Comentrios Ex1
/* 1 */
/* 2 */
incluso de um arquivo da biblioteca de C que implementa as funes printf, scanf... b deve ser substitudo por 20 declarao de duas variveis inteiras: a e s definio de uma funo somar definio da funo principal: main

/* 3 */
/* 4 */ /* 5 */

/* 6 */
/* 7 */ /* 8 */
8

leitura do valor de a entrado pelo usurio


chamada da funo somar com argumentos a e b impresso do resultado s da soma de a e b

Estrutura de um Programa C
Um
A

conjunto de funes

funo principal main

obrigatria.

A funo main o ponto de entrada principal do programa.

main
void main () { declaraes
instrues 1 instrues 2 ... instrues n }
10

As outras funes
Tipo nome (declarao-de-parmetros)

{ declaraes; instrues 1; instrues 2; ... instrues n; }


11

Consideraes sobre as funes

O tipo da funo = tipo do valor que a funo retorna

Ele pode ser predefinido, ou definido pelo usurio.

Por default o tipo de uma funo int.

12

Compilao

Pre-Processadores:
Transformao lexical do texto do programa.

Compiladores:
Traduo do texto gerado pelo pre-processador e sua transformao em instrues da mquina.

Observao
Geralmente, o pre-processador considerado como fazendo parte integrante do compilador.
13

Tipos Bsicos

14

Principais tipos de Dados


int float double char

famlia dos nmeros inteiros famlia dos nmeros pontoflutuantes (pseudo-reais) famlia dos caracteres

Observao: No tem o tipo Boolean!


15

Inteiros

Podem receber dois atributos:


de preciso (para o tamanho) de representao (para o sinal)

Atributos de preciso:

short int int long int

: : :

representao sobre 1 byte representao sobre 1 ou 2 palavra(s) representao sobre 2 palavras

16

Inteiros

Atributos de representao

unsigned signed

: :

somente os positivos positivos e negativos

17

Combinao de Atributos - Inteiros



18

unsigned short int : rep. sobre 8 bits [0, 255] signed short int : rep. sobre 7 bits
[-128, 127]

unsigned int

: rep. sobre 16 bits [0, 65535] signed int : rep. sobre 15 bits [-32768, 32767] unsigned long int : rep. sobre 32 bits [0, 4294967295] signed long int : rep. sobre 31 bits [-2147483648, 2147483647]

Os Inteiros

Em Resumo, temos seis tipos de inteiros:


int; short int; long int;

todos signed

e

19

unsigned int; unsigned short int; unsigned long int;

Pseudo-Reais
(representao da forma: M * 10EXP)

Os flutuantes podem ser:

float : representao sobre 7 algarismos

[-3.4*10-38, 3.4*1038 ] double : representao sobre 15 algarismos [-1.7*10-308, 1.7*10308 ] long double : representao sobre 19 algarismos [-3.4*10-4932, 3.4*104932 ]
20

Caracteres

Um caracter representado por


seu cdigo ASCII (cdigo numrico).

Ele pode ser manipulado como um inteiro. Um caracter codificado sobre um byte podemos representar at 256 caracteres.

21

Caracteres
O

tipo : Char
char c,b;

c = \65;
b = c;

22

E o tipo String?

No existe em C o tipo string propriamente dito.

Um substituo:
os vetores de caracteres:
char nome[20]

23

E o tipo Boolean?

Ateno: O Boolean no existe em C!


Isto geralmente substitudo pelo tipo int:
0 1 : : false true

24

Em sistemas 32 bits

25

char signed char unsigned char short unsigned short int unsigned int long unsigned long float double long double

1 1 1 2 2 4 4 4 4 4 8 10

-128 a 127 -128 a 127 0 a 255 -32,768 a 32,767 0 a 65,535


-2,147,483,648 a 2,147,483,647

0 a 4,294,967,295 -2,147,483,648 a 2,147,483,647 0 a 4,294,967,295 3.4E+/-38 (7 dgitos) 1.7E+/-308 (15 dgitos) 1.2E+/-4932 (19 dgitos)

DECLARAO DE VARIVEIS

26

Identificadores

Um identificador um meio para manipulao da informao


Um nome que indica uma varivel, funo, tipo de dados, etc.

27

Identificadores

Formado por uma combinao de caracteres alfanumricos


Comea por uma letra do alfabeto ou um sublinhado, e o resto pode ser qualquer letra do alfabeto, ou qualquer dgito numrico (algarismo), ou um sublinhado.

28

Exemplos de identificadores
Exemplo:

nome_1; _a; Nota; nota; imposto_de_renda; !x;

4_nota;

Ateno:

Os identificadores Nota e nota por exemplo representam duas variveis diferentes.


29

Regras para a nomeao


Como os compiladores ANSI usam variveis que comeam por um sublinhado, melhor ento no us-las. De acordo com o standard ANSI-C:

somente 32 caracteres podem ser considerados pelos compiladores, os outros so ignorados.

30

No usar as palavras chaves da linguagem.

Palavras Chaves
(so 32 palavras)
auto break case char const continue default do
31

double else enum extern float for goto if

int long register return short signed sizeof static

struct switch typedef union unsigned void volatile while

Declaraes
tipo

lista-de-nomes-de-variveis

Exemplo:

int i,a;
double d1, d2;

char c;
32

Inicializao de Variveis

C no inicializa automaticamente suas variveis.


Isto pode ser feito no momento da declarao: int i=1,j=2, k=somar(4,5); short int l=1; char c=\0;

33

Operaes

34

Atribuio

Exemplo:

i=4; a=5*2; d=-b/a; raiz=sqrt(d);

35

Exemplos de Atribuio
i = (j = k) - 2; 5 3 (caso k=5) j=5 i=3

Atribuio

mltipla:

a=b=c=8;
36

Converso de Tipos (1)

O compilador faz uma converso automtica float r1,r2=3.5; int i1,i2=5; char c1,c2=A;
r1=i2; i1=r2; i1=c2; c1=i2; r1=c2; c1=r2; /* /* /* /* /* /* r1 5.0 */ i1 3 */ i1 65 */ c1 5 */ r1 65.0 */ c1 3 */

37

Converso de Tipos (2)


int a = 2; float x = 17.1, y = 8.95, z; char c; c c c c = = = = (char)a + (char)x; (char)(a + (int)x); (char)(a + x); a + x;

z = (float)((int)x * (int)y); z = (float)((int)(x * y)); z = x * y;


38

Adio/subtrao/multiplicao
Expresso1 + expresso2 Expresso1 - expresso2 Expresso1 * expresso2

As duas expresses so avaliadas, depois a adio/subtrao/multiplicao realizada, e o valor obtido o valor da expresso.
Pode ter uma converso de tipos, depois da avaliao das expresses: float x,y; int z; x=y+z;

39

Diviso (1)
Expresso1 / expresso2

Em C, o / designa no mesmo tempo a diviso dos inteiros e dos reais. Isto depende ento dos valores retornados pelas expresses:

Se os dois so inteiros ento a diviso inteira, mas se um deles real ento a diviso real.

40

Diviso

(2)

Caso os dois operandos inteiros so positivos, o sistema arredonda o resultado da diviso a zero:
7 / 2 retorna 3

Caso os dois operandos inteiros so de sinais diferentes, o arredondamento depende da implementao mas geralmente feito a zero:
-7 / 2 ou 7 / -2 retornam -3 ou -4 (mas geralmente -4)

41

O Mdulo %
Expresso1 % Expresso2

Retorna o resto da diviso inteira.


7 % 2 retorna 1

Caso um dois operadores seja negativo, o sinal do mdulo depende da implementao, mas geralmente o sinal do primeiro
7 % 2 -7 % 2 7 % -2 retornam 1 retornam -1 retornam 1

42

Operadores Relacionais

Expresso1 op-rel Expresso2 Onde op-rel um dos seguintes smbolos: Operador Semntica == igual != diferentes > superior >= superior ou igual < inferior <= inferior ou igual
O resultado da comparao um valor lgico: 1 (se a comparao verificada) e 0 (seno)

43

Operadores Lgicos

Para combinar expresses lgicas


Operador Semntica

&& || !

e ou negao

Exemplos:
a >= b (a = = 0) || (b != 0) ! ((a = = 0) && (b<3))

44

Operador & Inflao


o operador de endereamento (ponteiro): &a o endereo da varivel a

acesso ao contedo da varivel a.

45

Incremento/decremento
x = x + 1;
x++; ++x; s+=i; z = y++; z = ++y;

46

/* isto incrementa x */
/* isto incrementa x */

/* isto incrementa x */
/* s=s+i*/ /* z = y e depois y++ */ /* y++ e depois z = y (novo) */

O decremento de igual modo

Regra
v = v operador expresso v operador= expresso

47

Condicional
a = (b >= 3.0 ? 2.0 : 10.5 );
if (b >= 3.0) a = 2.0; else a = 10.5;

c = (a > b ? a : b); c = (a > b ? b : a);


48

/* c=maior(a,b) */
/* c=menor(a,b) */

Entradas e Sadas

49

Sadas

Printf("Bom dia");
puts("Bom dia"); putch(a) printf
idade)

/* para imprimir um string */ /* para imprimir um char */

("Meu nome : %s\ne tenho %d anos.", nome,

50

Entradas
gets(s);
char c; c = getch();
/* leitura de um string */

c = getchar();

/* com echo */

scanf ("%d",&nome);
/* para a leitura da var. nome */

51

Constantes utilizados no printf


\n \t \v \b \r \a \\ \% \{} \?
52

nova linha tabulao (horizontal) tabulao vertical um espao para trs um return um bip backslash o caracter % um apostrofo um ponto de interrogao

Converso de Tipos
d o x e u c s f
53

notao de decimal notao octal notao hexadecimal notao matemtica notao sem sinal notao de caracter notao de string notao de flutuante

Formatao

Cada um desses caracteres de converso utilizado depois do % para indicar o formato da sada (da converso)
Mas, entre os dois podemos entrar outros argumentos:

54

Formatao
+ n 0n n.m

justificar a esquerda
o sinal sempre aparente o comprimento mnimo da sada (seno brancos) o comprimento mnimo da sada (seno 0s esquerda) para separar as partes antes e depois da virgula total de n dgitos, cujo m so depois da virgula. para indicar um long

l
55

Exemplo
#include <stdio.h>
int main() { int a; long int b; short int c; unsigned int d; char e; float f; double g; a = 1023; b = 2222; c = 123; d = 1234; e = X; f = 3.14159; g = 3.1415926535898; ... }

56

Exemplo
{
printf("a = %d\n", a); a = 1023 printf("a = %o\n", a); a = 1777
printf("a = %x\n", a); a = 3ff printf("b = %ld\n",b); b = 2222 printf("c = %d\n", c); c = 123 printf("d = %u\n", d); d = 1234

printf("e = %c\n", e); e = X


printf("f = %f\n", f); f = 3.141590 printf("g = %f\n", g); g = 3.141593
57

Exemplo
{ printf("\n");

printf("a = %d\n", a);


printf("a = %7d\n", a); printf("a = %-7d\n", a); c = 5; d = 8; printf("a = %*d\n", c, a); printf("a = %*d\n", d, a);

}
58

Exemplo
{
printf("\n"); printf("f = %f\n", f); printf("f = %12f\n", f); printf("f = %12.3f\n", f); printf("f = %12.5f\n", f);

printf("f = %-12.5f\n", f);

}
59

Exemplo
As sadas so:

f f f f f

= 3.141590 = 3.141590 = 3.142 = 3.14159 = 3.14159

60

Diretivas de Compilao

61

Diretivas de compilao

So instrues para o pre-processador.


Elas no so instrues C, portanto elas no terminam por uma virgula. Para diferenci-las das instrues C, elas so precedidas pelo smbolo especial #
#include #define #if,

Temos principalmente as seguintes diretivas:


#else, #endif

62

Incluso de Fontes: #include


#include <nome de arquivo>

Para a incluso de um arquivo. A busca do arquivo feita em primeiro no diretrio atual e depois no local das bibliotecas:

Em Unix:
Em DOS:

/usr/lib/include

APPEND (~ PATH, mas para os arquivos de dados e no para os executveis) Em Windows: isto especificado no ambiente
63

Incluso de Fontes: #include


#include

nome-de-arquivo

Para a incluso de um arquivo usurio.


Neste caso, a busca do arquivo feita apenas no diretrio atual. Seno, pode se especificar o caminho completo do arquivo

64

Exemplo de incluso
... #include "f2.c" ...

f2.c
for (i=0;i<5;i++)

printf("Oi");

f1.c f1.c
... for (i=0;i<5;i++) printf("Oi"); ...
65

Arquivos headers (.h)

Arquivos headers standards:


stdlib, stdio.h, conio.h, etc.

Um arquivo header contm um conjunto de declaraes de variveis e funes. Observao: Os headers includos podem tambm incluir outros arquivos (mas no pode existir uma referencia mtua)

66

Substituies: #define

#define MAX 60
#define TRUE 1 #define FALSE 0 #define BOOLEAN int BOOLEAN a=FALSE; if (a = = TRUE) ...; else ...;

(uma conveno: usar os masculos)


67

Macro Substituies: #define


#define maior(A,B) ((A)>(B)?(A):(B))
f() { ... maior(i+1,j-1); ... } A instruo maior(i+1,j-1) ser compilada como se nos escrevemos: ((i+1)>(j-1)?(i+1):(j-1))
68

Outros Macros
#define quadrado(a) (a)*(a) #define quadrado(a) a*a #define adicionar(a,b) ((a)+(b)) #define adicionar(a,b) (a)+(b)
quadrado(3-2); (3-2)*(3-2) = 1 5*adicionar(2+1,4); 5*((2+1)+(4)) = 35
regra geral: colocar todas as variveis entre parnteses e o resultado tambm
69

Substituies parciais
#define MAX 60 ... #undef MAX #define MAX 45
...
/*aqui MAX=45*/ /*aqui MAX=60*/

70

Compilao condicional (1)


Objetivo: a otimizao
#if (condio) corpo 1 [#else corpo 2] #endif

71

Compilao condicional (2)


#ifdef identificador corpo 1 #endif
#ifndef identificador corpo 1 #endif
72

O const

Para declarar variveis constantes podemos usar a palavra chave const const int N 20
Isto proibe que N seja modificado no programa (toda tentativa de modificao vai dar erro)

Diferena para o #define: - Usando o const teremos uma reserva de um espao


na memria. Ele se aplica sobre qualquer tipo de var.
- O #define serve somente para o pre-processador que faz as substituies necessrias antes da compilao.

73

Estruturas de Controle

74

Blocos de instrues
{
declaraes instruo_1 ..... } instruo_2 Em um bloco pode-se declarar variveis, que ficam visveis somente no bloco.
75

/*um bloco de instrues delimitado por duas chaves*/

Instruo if...else (1)


If (condio) instruo_1;
[else instruo_2;] Exemplos: if (a>=b) max=a; else max=b;
76

if (a!=0) x=-b/a;

Instruo if...else (2)

Qualquer instruo simples C pode ser substituda por uma instruo composta: if (d>0) {
x1=(-b-sqrt(d))/2*a; x2=(-b+sqrt(d))/2*a; }

77

Instruo if...else (3)


Observao: o else refere-se ao ltimo if
If (condio_1) instruo_1;

else

if (condio_2) instruo_2; else if (condio_3) instruo_3; else instruo_4;

78

Instruo if...else (4)


int a=3, b=2, c=1, d=0;
if (a>b) if (c<d) b=2*a; else a=2*b; seno, tem que escrever: if (a>b) { if (c<d) b=2*a; } else a=2*b;
79

Instruo if...else (5)


Observao: o else refere ao ltimo if
seno tem que usar chaves (bloco) If (condio_1) { instruo_1; if (condio_2) instruo_2; } else if (condio_3) instruo_3;
80

Observao

A condio no obrigatoriamente uma comparao. Pode ser qualquer expresso retornando um valor que pode ser comparado a zero.

int b=0; if (b) { }

/* equiv. a: if(b!=0)*/ ...

81

Instruo switch (1)


escolha mltipla
switch (expresso) { case constante_1: instrues break; case constante_2: instrues break; ... default: instrues }

82

Instruo switch (2)

Quando as mesmas instrues devem ser executadas no caso de um conjunto de valores:


switch (expresso) { case val_1: ... case val_n:

}
83

instrues break; case val_3: instrues break; default: instrues

Instrues de Repetio

84

while
while (condio) instruo
instruo Exemplo: c=s; while (c!=f) { c=getch(); }
85

pode ser simples ou composta.

fim do while

condio!=0 ? sim instrues

no

do...while (1)
do instruo(es) while (condio)

o equivalente de repeat do Pascal. A instrues do lao de repetio so executadas pelo menos uma vez.

86

do...while
do
c=getch(); while (c==s)

(2)

instruo
fim do do sim condio!=0 ?

no

87

for

(1)

for (expresso1, condio, expresso2) instruo(es)


expresso1 avaliada s uma vez depois a condio

se condio OK, as instrues so executadas

depois a expresso2, antes de voltar a avaliar novamente a condio


for (i=1; i<=10; i++) { printf(Vasco da Gama); }

Exemplo:

88

for

(2)
expresso1 inicializao fim do for

condio!=0 ?
sim

no

instrues
expresso2
89

for

(3)

A novidade que as expresses podem ser instrues mltiplas (separadas por virgula)
Exemplo: for (i=1,j=10; i<=j; i++,j--) { instrues;

90

break
O break permite parar a instruo de repetio (for, do ou while)
Se temos vrios nveis, o controle volta penltima estrutura de repetio. for (i=0;i<20;i++) if (vet[i]==10) break;

91

continue

Utilizada dentro de uma instruo for, while ou do


O continue permite parar a iterao atual e passar iterao seguinte. Exemplo: for (i=1;i<20;i++) { if (vet[i]<0) continue; ... }

92

Instruo: goto
goto <identificador> ;
permite quebrar a seqncia do programa Exemplo: mais:

...
If condio goto mais;
93

Funes

94

Definio de uma funo

Alm das funes predefinidas nos arquivos header da biblioteca (no diretrio LIB, usando o #include)
O usurio pode definir novas funes. Exemplos de funes predefinidas da biblioteca: stdio.h, math.h, conio.h, stdlib.h e dos.h

95

Ex. de funes: (stdio.h)


Principalmente:
puts gets printf scanf

96

Ex. de funes: (math.h)


abs fabs exp ceil floor pow pow10 mdulo de int. mdulo de real exponencial arredondar ao max arredondar ao min xy 10x
double

int

abs(int)

double fabs(double) double exp(double) double double double double ceil(double) floor(double)

pow(double x,double y)

pow10(double) sqrt(double)

hypot
sqrt
97

hipotenusa
raiz quadrada

double hypot(double, double)

Ex. de funes: (conio.h)


clrscr
clreol delline insline gotoxy kbhit

apaga a tela
apaga o resto da linha apaga a linha atual insere uma linha
posiciona o cursor

void clrscr ()
void clreol () void delline () void insline ()
void gotoxy (int x, int y)

testa se tecla

int
int

kbhit ()
putch (int c)

putch imprima um char c

getch leia char sem echo int


herex posio x do cursor herey
98

putch ()
int int wherex () wherey ()

posio y do cursor

Ex. de funes: (stdlib.h)


min
max rand exit
retorna o min
retorna o max ret. num. alea.

type min(type, type)


type max(type, type) int rand()

ret. nvel de erro void exit(int) int random(int n)

random ret. num. alea de 0 a n-1

randomize inicializa o gen. al.

int randomize()

precisa tambm de <time.h>


99

Ex. de funes: dos.h


delay sound nosound parar o som sleep suspende em seg void sleep(unsigned s)
exemplo:

sound(300); /* emitir um som de 300 Hz*/ delay(2000); /* esperar 2 segundos */ nosound(); /* antes de parar */

100

Exemplos de funes

graphics.h
rectangle desenha um retngulo void rectangle (int e, int c, int d, int b)

string.h

101

Definio de uma funo


tipo identificador ([lista de id.])
[lista de declaraes 1] { [lista de declaraes 2] lista de instrues }
102

Semntica
tipo:
o tipo do valor devolvido pela funo

identificador: nome da funo lista dos identificadores: os parmetros


formais

lista de declaraes 1: a lista de declarao


dos parmetros formais

lista de declaraes 2: declarao das


variveis locais a funo

lista de instrues: so as instrues a executar


103

quando a funo chamada.

Exemplo
float media (a,b) float a,b; /* declarao dos
parmetros formais */

{ float resultado; /* var. locais */ resultado=(a+b)/2;

return (resultado);
}
104

/* retornar o res. ao remetente */

Os parmetros formais - opcionais


double pi () /* no temos param.
formais */

/* no temos var. locais */ return (3.14159);

105

Observao

A prototipagem da funo pode ser feita de uma vez:

int min (int a, int b)

{
if (a<b) return (a);

else
return (b); }
106

Chamada de uma funo


identificador (lista de expresses)
As expresses so avaliadas, depois passadas como parmetros efetivos funo de nome identificador.
{ int m_1, m_2; float p, d=4.5; m_1 = max (4,3); m_2 = max(6*2-3,10); p = d * pi(); }
107

Procedimentos

Funes que no retornam valores: usando o tipo especial void


void linha ()
{
printf("-------------------------\n"); }

Observao: no temos aqui a instruo return (o tipo especial void no existia nas primeiras verses da linguagem)
108

Omisso do tipo da funo!

C considera por defaut o tipo int.

somar (int a, int b) { return (a+b); }

Melhor no usar esta possibilidade.

109

Passagem dos Parmetros


int somar (int x, int y) { return (x+y); }
void main () { int a=8, b=5, s; s = somar(a,b); /*os parmetros efetivos*/ }
110

Passagem por Valor


Na chamada temos passagem de parmetros.
Mas, as modificaes dos parmetros formais

no afetam os parmetros efetivos.

111

Passagem por Referncia


(ou por endereo)

Usar o operador de endereamento

&

void somar (int x, int y, int * som) { *som = x+y; } void main () { int a=5, b=6, s; somar(a,b, &s); printf("%d + %d = %d",a,b,s); }
112

Outro uso do void


void f (void) { ... }
para indicar que a funo no tem

parmetros

113

Declarao de Funes

Uma funo F conhecida implicitamente por uma outra funo G se elas so definidas no mesmo arquivo, e que F definida antes de G.
Fora desse caso, e para um controle de tipo e um bom link, preciso declarar as funes antes de usar.

114

Exemplo
void { } ... int maior (int x, int y) { return (x>y?x:y); }
/*a main pode ser definida antes*/
115

main

(void)

int maior (int, int); maior (2,8);

Dois formatos para a declarao


int maior (); 1a

int maior (int x, int y); 2a Mas, melhor usar o segundo formato

que mais completo

116

Funes Iterativas
exemplo do fatorial
long int fat (long int n) { long int i,res=1; for (i=1;i<=n;i++) res=res*i; return (res); }
117

Funes Recursivas
exemplo do fatorial
long int fat (long int n) { if (n == 1) return 1; else return (n*fat(n-1)); }
118

Exerccios

Escreva as funes real_dlar e dlar_real de converses Real-Dlar e vice versa.


Escreva as verses recursiva e iterativa da funo soma que retorna a soma dos n primeiros termos:
S(n) = 1 + 1/2 + 1/3 + ... + 1/(n-1) + 1/n

119

Escreve a funo S(n) tal que:


S(n) = 1/n - 2/(n-1) +3/(n-2) + ... - (n-1)/2 + n/1

Declaraes

120

Escopo das declaraes


so 4 escopos:

Um identificador declarado fora das funes, tem um escopo em todo o programa.

Um parmetro formal de uma funo, tem um escopo local funo.


Um identificador declarado em um bloco tem um escopo local ao bloco. Uma etiqueta de instruo, tem escopo em toda a funo onde ela declarada.

121

Visibilidade dos identificadores


int i=1; int j=1; void p() { int i=2; int k;

/* este i cobre o precedente */

if (a==b) { int i=3; }


int j=2; int k;

/*cobre o i precedente*/

/* cobre o j precedente*/
/*cobre o k precedente*/

}
122

Durao vida de uma varivel

Variveis Estticas:
Alocao no incio do programa e liberao no final da execuo do programa.

Variveis Automticas
Alocao na entrada de uma instruo composta (um bloco) e liberao na sada.

Variveis Dinmicas
A declarao e liberao so explicitamente realizadas pelo programador (usando malloc e free). Mas, essas funes so da biblioteca e no fazem parte integrante da linguagem.

123

Durao vida de uma varivel


A durao de vida de uma varivel depende
normalmente de seu escopo de declarao: varivel global varivel local var. esttica var. automtica

124

Durao vida de uma varivel


As variveis globais so variveis estticas. As variveis locais podem ser estticas ou automticas (dependendo do programador), usando os qualificadores de classes de armazenagem: static e auto. Por default, uma varivel local automtica.

125

Indicadores de classes de memria


Em C, temos quatro indicadores de classes
de memria:

auto
static register extern
126

auto
{auto int i;

... }

Este tipo de indicador autorizado somente para as variveis locais a uma instruo composta (um bloco). Ele indica que a varivel tem uma durao de vida local ao bloco.

O uso deste indicador quase inexistente, pois


por default toda varivel local automtica

127

static
{static int i;

... }

O static indica que a varivel tem uma durao de vida ao longo da execuo do programa. Mas que ela fica local ao bloco (ela fica desconhecida fora de seu bloco). Portanto, a varivel guardar seu valor para

cada chamada ao bloco.

128

Este indicador pode ser usado para as


declaraes de variveis e funes.

exemplo de uso de static


void f () { static int num_chamadas = 0; num_chamadas++; /* para contar
}

quantas vezes f foi chamada */

A varivel num_chamada inicializada somente uma vez. Tem durao de vida ao longo da execuo do programa. Mas ela tem escopo local.

129

register
{register int a,b;

... }

Este tipo de indicador autorizado somente para as variveis locais a uma instruo composta (um bloco) e para as declaraes de parmetros de funes. Ele tem o significado do auto, alm de provocar o armazenamento da varivel em um registro e no na memria. acesso mais rpido. Claro que isto depende das capacidades da mquina (nmero e tamanho dos registros)

130

extern
int a; void f() {...

extern int a; ...}

Os outros indicadores so relacionados s variveis locais. Uma varivel global definida fora de qualquer corpo de funo. O extern permite usar (acessar) uma varivel que definida fora.

131

Este indicador autorizado para as


declaraes de variveis e funes.

Classes de memria (1)

Na execuo de um programa, existe trs zonas de memria:

Zona das variveis estticas ;

Zona das variveis automticas


(organizada em forma de pilhas, pois as funes podem ser recursivas)

Zona das variveis dinmicas (organizada em forma de


monto ou tas / stack)

132

Classes de memria (2)

Esta diviso existe nas outras linguagens,


mas a alocao feita pelo compilador. Ao contrrio, em C a declarao da classe da varivel feita pelo prprio programador.

auto, static e register so indicadores de classe de memria (mas o extern no realmente)

133

Tabelas

134

Tabelas

O objetivo da estrutura de tabela agrupar um conjunto de informaes de mesmo tipo em um mesmo nome.

Uma tabela pode ser multidimensional ou unidimensional (vetor).

135

Declarao
float vet[10]; long int v1[8], v2[15];
/* v1 um vetor de 8 long int e v2 um vetor de 15 long int */

Os elementos so indexados de 0 a N-1

136

Dimenso

Na prtica, recomendado definir sempre


uma constante que indica o nmero de elementos: #define N 60 short int v[N];
/* declara um vetor de 60 inteiros indexado de 0 a 59 */

137

Acesso aos elementos


Sintaxe: nome-varivel [expresso]
expresso deve retornar um inteiro (o indexador)

Exemplos: vet[0]=6; vet[4+1]=-2; x=3*vet[2*a-b];


138

Inicializao
#define N 4 int v[N]={1,2,3,4};

Incializao de somente uma parte do vetor:

#define N 10 int v[N]={1,2}; //o resto ser zerado

Inicializao pelo mesmo valor:

for (i=0;i<=9;i++) v[i]=2; for (i=0;i<=9;i++) scanf("%d",&v[i]);

Inicializao pelo usurio:

139

Operadores abrangentes
lembramos que:
x++ incrementa x mas retorna o valor inicial ++x incrementa x e retorna o valor incrementado i=0; v[i++]=0; /* v[0]=0 e i=i+1 */ v[i++]=0; /* v[1]=0 e i=i+1 */ i=1; v[++i]=0; v[++i]=0;

140

/* i=i+1 e v[2]=0 */ /* i=i+1 e v[3]=0 */

idem para o operador --

Uso da instruo nula

Inicializao de um vetor:
for (i=0;i<10;v[i++]=1); Isto equivalente a: for (i=0;i<10;i++) v[i]=1;

Pesquisar em um vetor:
for (i=0; i<N && t[i]!=10; i++);
/* usando a instruo nula */

141

Isto equivalente a: for (i=0; i<N; i++) if t[i]==10 break;

Tabelas MultiDimensionais
Matrizes
Declarao:
int mat [3][4];
/* matriz bidimensional de 3 linhas 4 colunas */

Inicialiazao:
int mat [3][4] = { {5,6,8,1}, {4,3,0,9}, {12,7,4,8}, }

142

Exemplo
/* Declarao: */
#define L 4; #define C 3; int mat[L][C];

/* leitura: */
for (i=0;i<=L;i++) for (j=0;j<=C;j++) { printf("digite o elemento [%d,%d]: ",i,j); scanf("%d",&mat[i][j]); }

143

Observao 1
for (i=0,j=0;i<L && j<C;i++,j++) {
printf("digite o elemento [%d,%d]: ",i,j); scanf("%d",&mat[i][j]);

}
no a mesma coisa que:
for (i=0;i<=L;i++) for (j=0;i<=C;j++) { printf("digite o elemento [%d,%d]: ",i,j); scanf("%d",&mat[i][j]); }
144

Observao 2
int sum (int n) { int res=0; for (;n>0;n--) /*n inicializada na chamada*/ res=res+n; return (res); }
chamada: sum(5)

O que faz este cdigo?


145

Exerccios

A.1 Escreva o procedimento ini_num_dias que inicializa um vetor num_dias[12] que indica para cada ms do ano seu nmero de dias: (num_dias[i] indica o nmero de dias do ms i do ano), sabendo que:
Se i=2 ento num_dias=28; Se (i par e i<=7) ou (se i impar e i>7) ento num_dias=30 Seno num_dias=31.

A.2 Escreva o procedimento imp_num_dias que imprima os nmeros de dias de todos os meses do ano.

146

B. Escreva a funo ordenar que ordena um vetor. C. Escreva a funo palindromo que determina se um vetor um palindromo.

Tipos Enumerados

147

enum

A enumerao permite de agrupar um conjunto de constantes (compartilhando a mesma semntica)

exemplos:
enum dias {Domingo, Segunda, Tera, Quarta, Quinta, Sexta, Sbado};

declarao:
dias d1,d2=Quinta;

enum defini um novo tipo cujo os elementos so numerados automaticamente de pelo compilador: 0 1 2 ...

148

Exemplo
#include <stdio.h> enum dias {Segunda,Tera,Quarta,Quinta, Sexta,Sbado,Domingo} d; // d uma varivel declarada de tipo dias
void main (void) { // dias d; uma outra maneira de declarar for(d = Segunda ; d < Domingo ; d++) printf(O cdigo do dia : %d\n", d); }
Vai imprimir os valores dos dias:
149

0, 1 at 6.

enum

Essa numerao permite comparar os elementos do tipo: if (d1<=d2) ... Portanto podemos mudar essa numerao:
enum boolean {true=1,false=0};

Quando um item no numerado ele pega o valor de seu precedente:


enum temperatura {baixa=2,media=4,alta};

150

Ponteiros

151

Variveis Dinmicas

Todas as variveis vistas at agora so


estticas (reserva imediata na memria), contudo precisamos de variveis dinmicas

Um ponteiro uma referncia sobre um objeto na memria ( um endereo).

152

Variveis Dinmicas

Exemplo de Declarao de Ponteiros: float * pf


/* declara que pf um ponteiro sobre um real */

pf 4.6
153

Os Operadores & e * (1)

O operador de endereamento & se aplica sobre uma varivel e permite retornar seu endereo memria

O operador de indireo * se aplica sobre um ponteiro e permite retornar (manipular) o objeto apontado.
154

Os Operadores & e * (2)


*P

P
(Ponteiro)

V
(Varivel)

&v
155

Exemplo
int i,j; int *pi;
/* pi um ponteiro sobre um inteiro */

i=5;
pi=&i; *pi=6; j=*pi-2; pi=&j;
156

pi &i &j

56 i 4 j

Exerccio
1. Declare um inteiro i e um ponteiro p sobre um inteiro
2. Inicialize o inteiro com um valor qualquer 3. Aponte o ponteiro sobre a varivel i 4. Imprima o valor de i

5. Modifique o valor de i usando o ponteiro


6. Imprima o novo valor de i
157

int i; int * p; i=8; p=&i; printf("i= %d\n",i); *p=5; printf("novo i= %d\n",i);


158

/* 1 */ /* 1 */ /* 2 */ /* 3 */ /* 4 */ /* 5 */ /* 6 */

Passagem de Parmetros

Passagem de parmetros (dois tipos):


por valor por referncia (passar o endereo da varivel)

Estratgias adotadas pelas linguagens:


Todo feito por referncia

(FORTRAN, PL/1)

Temos a escolha entre a passagem por valor ou por referncia (caso de PASCAL) Toda passagem feita por valor (caso de C)

159

Estratgia de C

Em C, toda passagem de parmetros portanto feita por valor.


Como ento fazer as passagens por referncia? A soluo de declarar os parmetros formais de tipo ponteiro. Isto feito pelo uso do operador & (usado na chamada a funo).

160

Exemplo
void
{ }

adicionar (int a, int b, int * res)


observe a declarao de res como um ponteiro sobre um inteiro: um endereo

*res=a+b;

void main (void) { int i,j,k; adicionar (i,j,&k); }


161

observe que na chamada tem que passar o endereo da varivel onde deseja-se recuperar o resultado

Um outro exemplo
A funo troca
void troca (int * x, int * y) { int temp; temp=*x; *x=*y; *y=temp; }

chamada da funo troca(&a,&b);


162

/* passagem por referncia */

Funes Genricas
O problema que esta funo troca que ns definimos se aplica somente sobre os inteiros
void troca (void * x, void * y) { int temp; temp=*x; *x=*y; *y=temp; } Infelizmente isto no pode ser feito em C Mas o problema resolvido em C++
163

Tabelas e Ponteiros

164

Relao entre Tabela e Ponteiros

O nome de uma tabela no um identificador de


dados mas um ponteiro:
#define N 45 int t[N];

o endereo do primeiro elemento: t[0] t=&t[0] t[i] = *(t + i)

t + i: Incrementa de i vezes o tamanho dos objetos do vetor (e no de i unidades)


165

Conseqncia 1

Trs conseqncias principais da considerao que uma tabela um ponteiro:


O operador de indexao [ ] no til: Mas ele foi adotado pela linguagem parar no quebrar os costumes dos programadores

166

Conseqncia 2
Manipulao de sub-tabelas:
int t[10]; int * p; p=&t[2];
0 1 2 3 9

p t

podemos escrever ento p[0], p[1]...


(p[0]=t[2],...)
167

Conseqncia 3
O operador de indexao comutativo: t[i] = i[t]
isto porque a adio comutativa:
t[i] i[t]

*(t+i) *(i+t)

Mas, por razes de legibilidade do programa esta possibilidade muito pouco utilizada.

168

Aritmtica dos Ponteiros

Podem ser efetuadas operaes de adio


e de subtrao sobre os ponteiros ou entre ponteiros e inteiros.

Esta possibilidade usada para manipulao de tabelas

169

Ilustrao do Clculo de Ponteiros


#define N 10 int t[N]; int *p, *q, *r, *s;
p=&t[0]; q=p+(N-1);
/*aponta sobre o 1o elem do vetor*/ /*aponta sobre o ltimo elem do vetor*/

r=&t[N-1]; s=r-(N-1);
170

/*aponta sobre o ltimo elem do vetor*/


/*aponta sobre o 1o elem do vetor*/

Passagem de Parmetros

Em C uma tabela pode ser passada como parmetro a uma funo


Quando isto feito, em realidade, o endereo do primeiro elemento que passado como parmetro. A passagem ento feita por referncia. O parmetro formal da funo chamada deve ento ser declarado de tipo ponteiro

171

1a Abordagem
void imp_tabela (int * t, int num_elem)

{ int i;

for (i=0;i<num_elem;i++)
printf("%d",*(t+i)); }
chamada: imp_tabela(tab,N);
/* que equiv. a: */

imp_tabela(&tab[0],N);
172

Crtica
Este mtodo apresenta inconvenientes:

A declarao e a chamada no parecem muitos naturais para os programadores


Na declarao int * t no mostra se t aponta sobre um inteiro ou sobre uma zona de inteiros (a tabela)

173

2a Abordagem

Por esta razo, C permite uma declarao mais natural dos parmetros formais:

void imp_tabela (int t[],int n) { int i; for (i=0;i<n;i++) printf("%d",t[i]); }

Ateno: No preciso conhecer o tamanho exato da tabela. o tamanho geralmente passado como parmetro separado.
chamada:
174

imp_tabela(tab,L);

Tabelas Multi Dimensionais

No caso de uma tabela multidimensional somente a primeira dimenso pode no estar especificada:
int min (int m[][C], int l) { int i,j,min=m[0][0]; for(i=0,j=0;i<l&&j<C;i++,j++) if (m[i][j]<min) min=m[i][j]; return(min); }

175

chamada: min(mat,L);

Algumas consideraes

A funo min aplicada a uma tabela que tem qualquer nmero de linhas, mas deve ter um exato C de colunas.
As outras dimenses ( 1a), devem ser especificadas por que o compilador precisa para gerar o cdigo que permite o acesso aos elementos: No caso de uma matriz binria t por exemplo, o endereo de t[i][j] : t+(i*C+j)*T (T o tamanho de um elemento de t, C o nmero de colunas) Representao da tabela na memria:
11 12 13 14 21 22 23 24 31 32 33 34 41...

176

Modificao dos elementos


void f (int t[],int nb_elem) { int i; for (i=0;i<nb_elem;i++) t[i]++;
}
a chamada: f(tab,L);

/* j que a passagem de parmetros feita por referncia ento qualquer modificaes sobre o vetor fsica */
O que faz esta funo?
177

Tabelas de ponteiros
possvel declarar uma tabela de ponteiros:

exemplo: #define N 15 char * tab[N]; /* declara um vetor de ponteiros


sobre elementos de tipo caracter */

acesso:

*tab[i]

tab

178

*tab[i]

Objeto apontado

Ponteiro de Ponteiro

179

Ortogonalidade do operador *

J que um ponteiro uma varivel como as outras, muito normal que um ponteiro aponte sobre um ponteiro
Um exemplo um ponteiro sobre um ponteiro sobre mais um inteiro

declarao: int **ppint


ppint
180

int

Argumentos do main

Um programa C pode ser chamado externamente com alguns parmetros:


A funo main recebe sempre dois parmetros:

argc (argument count) que determine o nmero de argumentos da linha de comando; e argv (argument vector), que um ponteiro sobre uma tabela de ponteiros sobre strings:

181

argv

um ponteiro sobre um vetor de ponteiros sobre strings:


char * argv[];

argv[0] aponta sobre o nome do arquivo


(nome do programa)
argv[i] vai apontar sobre os argumentos passados ao programa na linha de comandos.

182

exemplo

Suponha: programa achar_max pega como parmetros um conjunto qualquer de strings e que deve determinar e imprimir a maior string:

argv achar_max\0 \0

\0
\0

183

argv[0] o nome do programa: achar_max,e os outros argv[i] so os argumentos passados ao programa na linha de comandos.

#include <stdio.h> #include <string.h> void main (int argc, char * argv[]) { int com_max=0, arg_max=0; argc--; while (argc>=1) { if (strlen(argv[argc])>com_max) { com_max=strlen(argv[argc]); arg_max=argc; } argc--; } if (arg_max) printf("O string maior : %s", argv[arg_max]); } 184

Strings

185

String ~ Vetor

Um string um conjunto de caracteres.


Em C, um string uma estrutura equivalente estrutura de vetor, A nica diferena que o string termina sempre pelo caractere \0 Isto para facilitar o tratamento dos strings (para poder detectar o fim do string)

186

Declarao

O tipo string no existe em C,


Portanto existe duas maneiras para

simular este tipo de variveis:

Como um vetor de char, ou

Como um ponteiro sobre uma zona


de chars

187

Como Vetor de Caracteres

Declarao: #define N 20 char ch [N];

Os strings declarados como vetor de chars tm um tamanho limite fixo (o tamanho do vetor).

188

Se o tamanho do string menor do que o tamanho do vetor, o compilador C completa pelo caractere especial \0 para indicar o fim do string.

Inicializao de Vetor de Caracteres

A inicializao de um vetor de char pode ser feita, no momento da declarao, de duas maneiras:
1. Atribuindo um conjunto de caracteres:
char ch [20]={e,x,e,m,p,l,o}; (como normalmente feito para inicializar qualquer tipo de vetor).

2. Atribuindo um string ( mais prtica):

char ch[20]= "exemplo"; O tamanho pode ou no estar especificado: char nome[]="este tem 23 caracteres";
189

Acesso aos Elementos

feito de uma maneira normal, como para qualquer tipo de vetor:


#define N 3 char ch [N]={O,i}; ch[0]= H /* refere ao 1o caractere */ ch[1] /* refere ao 2o caractere */

O i

\0

...
ch[N-1]
190

H i

\0

/* refere ao Nsimo caractere */

Como Ponteiro sobre Caracteres

A manipulao dos strings como vetores de caracteres pode aparecer como pouco prtica.
Portanto, podemos criar strings de tamanho dinmico usando um ponteiro sobre um char: char * ch = "exemplo";

Contrariamente outra maneira, a reserva do espao memria no feita no momento da declarao, mas dinamicamente no momento da atribuio.

191

Inicializao e Atribuio
A Inicializao feita diretamente por uma string:

char * ch = "exemplo"; C completa o string pelo caracter \0 indicando


o fim do string.

A Atribuio tambm direta (contrariamente ao vetor de char):

ch ch = "uma mudana"; ch = "outra mudana"; uma mudana\0 outra mudana\0


Isto no uma copia mas uma atribuio de ponteiros.
192

Manipulao de Strings
As funes de manipulao de strings so definidas no arquivo da biblioteca string.h

Temos principalmente as seguintes funes: strcpy, strlen strcat, strcmp, strchr,


193

strncpy

strncat strncmp strrchr

Strcpy/strncpy

A funo especial strcpy permite atribuir um valor texto a uma varivel de tipo texto:
O strcpy apresenta dois formatos de uso:
strcpy(string1,string2); strncpy(string1,string2,N);

exemplo:
char *ch1="boa", *ch2="noite"; strcpy(ch1,"isto um exemplo"); strncpy(ch2,ch1,4); /* ch2 vai pegar "isto" */
194

strlen
strlen permite retornar o tamanho de um string: nmero de chars que compem o string (o \0 no faz parte)
exemplo:
int a; char * nome; strcpy(nome,brasil"); a=strlen(nome); /* a=6 */
195

strcat/strncat
strcat se aplica sobre dois strings e retorna um ponteiro sobre a concatenao dos dois.
exemplo:
char *ch1="boa", *ch2="noite", *ch3, *ch4;

ch3=strcat(ch1,ch2); ch4=strncat(ch1,ch2,3); printf("%s %s",ch3,ch4);


/* vai imprimir boanoite boanoi*/

196

strcmp/strncmp
Lembramos que as letras so ordenadas dando seu cdigo: a< ... z< A...<Z

strcmp compara dois strings s1 e s2 e retorna um valor: negativo se s1 < s2


0 positivo se s1 == s2 se s1 > s2

exemplo:
char

*ch1="boa tarde", *ch2="boa noite"; int a,b; a=strcmp(ch1,ch2); b=strncmp(ch1,ch2,4);


197

/* a vai receber um valor >0 e b 0*/

strchr/strrchr
strchr procura por um caractere em um string e retorna um ponteiro sobre sua ltima ocorrncia, seno retorna null. exemplo:
char ch[]="informtica"; char *pc, c='f';

pc=strchr(ch,c);
if (pc) /* i.e. if pc!=null */ printf("%d",*pc); else printf("Caractere inexistente"); O strrchr faz a busca no senso inverso.
198

touppar/tolower
toupper converte um caractere minsculo em maisculo. tolower faz o contrrio. # include <ctype.h>
char c='a';

c=toupper(c); c=toupper(c); c=tolower(c);


199

/* c= 'A'

*/

/* c j esta ='A' */ /* c volta a ser 'a' */

Exerccios 1
A. Defina a funo ocorrncia que retorna o
nmero de ocorrncias de um caractere em um string.

B.1 Defina a funo tamanho1 que pega como


parmetro um vetor de caracteres e retorna seu comprimento.

B.2 Defina tamanho2 que implementa a mesma funo


mas que pega como parmetro um ponteiro sobre uma zona de caracteres.

B.3 Defina o main que chama essas duas funes.


200

int tamanho1 (char s[]) /* com um vetor */ { int i=0; while (s[i]) /* equiv. while (s[i]!= '\0' ) */ i++; return (i); }
int tamanho2 (char * s) /*com os ponteiros*/ { int i=0; while (*s) /* equiv. while (*s!= '\0 ') */ {i++;s++;} return (i); }
201

void

main (void)

{
char ch[]="So Luis"; int a,b; a=tamanho1(ch); b=tamanho2(ch); /* a= 8*/ /* b= 8*/

printf("O tamanho de %s : %d\n",ch,a); printf("O tamanho de %s : %d\n",ch,b);

202

Exerccios 2: Criptografia Simples


1. Defina as funes Criptar e Decriptar que codificam e decodificam um caractere aplicando o seguinte algoritmo de criptografia: - Um caractere substitudo por um outro aplicando um shift de 3 (por exemplo a seria substitudo por D). - Apenas os caracteres do alfabeto so codificados. - Os masculos passam a ser minsculos e vice-versa.
2. Defina a funo main que leia e codifica ou decodifica uma mensagem usando as funes definidas acima.

203

Tipos usurios

204

typedef
Podemos definir novos tipos usando o typedef: typedef <tipo> <sinnimo>

exemplo:
typedef float largura; typedef float comprimento;

largura l; comprimento c=2.5; l=c; //* warning *//


205

typedef e struct

O typedef se usa mais com o tipo struct (as estruturas)

206

Estruturas

207

Declarao: mtodo 1
struct cliente { int cpf; char nome [20]; char endereco[60]; };

struct cliente c1,c2,c3;


208

Declarao: mtodo 2
Podemos criar estruturas sem nome: struct { int cpf; char nome [20]; char endereco[60]; } c1,c2; Problema: para criar uma outra varivel de mesmo tipo em outro lugar do programa preciso rescrever tudo.
209

Declarao: mtodo 3
Podemos, no mesmo tempo, dar um nome estrutura e declarar as variveis:
struct cliente { int cpf; char nome [20]; char endereco[60]; } c1,c2;

struct cliente c3;


210

Declarao: mtodo 4
Definindo um tipo estrutura typedef struct { int cpf; char nome [20]; char endereco[60]; } Cliente;
Cliente
211

c1,c2={28400,"Maria","Rua Liberdade, N. 140"};

Acesso aos Campos


Usando o operador de seleo: . (o ponto)
nome-estrutura.nome-do-campo exemplo: c2.nome retorna o campo nome da estrutura c1: Maria c2.nome=" Jeane" Muda o contedo de nome
212

Exemplo
void { imprimir_cliente (Cliente c)

printf("cpf: %d\n%s\n%s", c.cpf,c.nome,c.endereco); }

chamada da funo: imprimir_cliente (c2);


213

Combinao de Estruturas
Podemos definir estruturas de estruturas, estruturas de vetores, vetores de estruturas.... exemplo

typedef

struct {int num; char * rua; char * bairro; int cep} End; struct {int cpf; char * nome; End endereco} Pessoa;

typedef
214

Vetores de Estruturas

Podemos criar um vetor de estruturas (dois mtodos):

exemplo: struct cliente vet[100]; /* seguindo o mt. 1*/ Cliente vet[100]; /*seguindo o mt. 4*/ declara um vetor de 100 clientes.

Referencia aos elementos: Para referenciar o nome do isimo cliente do vetor: vet[i].nome
215

Exerccio
Escreve um programa C que:

Declara um vetor de alunos: turma (um aluno definido pelo cpd, nome, trs notas, mdia, e conceito) Preenche esse vetor (campos: cpd, nome, e notas). Preenche os campos mdia e conceito (bom se mdia8, regular se 7 e ruim seno); Define a funo que imprime todos o elementos do vetor. Define a funo que pesquisa um elemento do vetor (pesquisa pelo nome, pelo cpd, ou pelo conceito).

216

Estruturas e Ponteiros

217

Estruturas dinmicas
Usando as estruturas e os ponteiros podemos entrar no mundo das estruturas auto referenciais: Listas, Arvores, Grafos, etc.

218

Ponteiros sobre uma Estrutura


typedef struct {
char * nome; int idade; } Pessoa ; Pessoa pess; /* pess uma varivel de tipo pessoa */ Pessoa *pp; /* p um ponteiro sobre uma pessoa */ pp=&pess; /* p agora aponta sobre a pessoa pess */
219

Ponteiros sobre uma Estrutura


pess.idade=18; pess.nome="joao";

Para acessar aos campos da estrutura apontada por pp usamos o operador -> pp->nome; /* equiv. a pess.nome */ pp->idade=25; /* pess.idade=18 */

printf("%s",pp->nome); // escreveria Joo


printf("%d",pp->idade); // escreveria 25
220

Observao sobre o acesso

221

Para acessar o campo nome de pessoa apontada por um ponteiro pp: *pp.nome Mas o operador de seleo . mais prioritrio do que o operador de indireo * isto equiv. a: *(pp.nome) o que est errado (pois pp no uma estrutura). Deveremos escrever: (*pp).nome Mas esta notao um pouco complicada. Por isso temos um novo operador -> (pp->nome)

Estrutura apontando sobre uma outra Estrutura (1)


exemplo:
struct pessoa { ... struct pessoa * next; } ;
/* next um ponteiro sobre uma outra pessoa */
222

Estrutura apontando sobre uma outra Estrutura (1)


exemplo:
typedef struct pessoa * PtrPessoa; // PtrPessoa um ponteiro sobre a estrutura pessoa

typedef struct pessoa { char nome[30]; int idade; PtrPessoa next; } Pessoa;
/* next um ponteiro sobre uma outra pessoa */

PtrPessoa
223

pp;

Ilustrao
CPF
nome endereco next CPF nome endereco next
224

Acessos aos elementos de uma Estrutura Apontada


PtrPessoa p;

... printf("Entra com o nome: "); scanf("%s",&p->nome); printf("Entra com a idade: "); scanf("%d",&p->idade); p->next=NULL;
225

Tamanho alocado uma Estrutura

O tamanho alocado a um tipo pode ser conhecido usando o operador sizeof (a medida feita em nmero de bytes).
sizeof pode ser usada de duas maneiras (aplicao a um tipo ou uma varivel) exemplos: int tamanho,i; tamanho=sizeof i; tamanho=sizeof (short i); tamanho=sizeof (Pessoa);

226

Listas

O fato de que uma estrutura pode apontar para uma outra permite criar listas encadeadas.
Uma lista encadeada til principalmente quando ns no sabemos a priori (no momento da compilao) o nmero de seus elementos, o que uma necessidade no caso do uso do tipo vetor.

Contrariamente aos vetores, uma lista encadeada uma estrutura dinmica: os elementos so criados dinamicamente:

227

Alocao e Liberao de Memria

Para poder criar listas preciso poder alocar memria dinamicamente:


A alocao e liberao de memria feita

usando as funes malloc e calloc:

malloc para a alocao do espao memria para um elemento; e calloc para a alocao do espao memria para um conjunto de elementos.

228

malloc
malloc
um nico parmetro que o tamanho (em bytes) do espao memria do elemento que ns desejamos criar, e retorna um ponteiro sobre o elemento criado. Obs. O tamanho do elemento obtido usando o operador sizeof. exemplo: Pessoa * p; p=malloc(sizeof(Pessoa));
229

pega

p=malloc(sizeof(char));

calloc

calloc pega dois parmetros: - o nmero de elementos que desejamos criar; - e o tamanho de um elemento (em bytes).
O objetivo de alocar espaos para vrios elementos de s uma vez.

230

calloc

exemplo: Pessoa * p; int num_elementos=4; ... p=calloc(num_elemenetos,


sizeof(Pessoa)); Podemos, depois, usar p[0], p[1], ... P[num_elementos - 1]

231

Observao
As funes malloc e calloc so definidas no arquivo <alloc.h> da biblioteca.
Geralmente antes do malloc tem que especificar o tipo da estrutura cujo o ponteiro que ser criado vai apontar:
pat=(PtrPessoa)malloc(sizeof(Pessoa));

p=(char *)malloc(sizeof(char));
232

null
Quando no tem mais espao livre, as
funes malloc e calloc retornam o valor null Este valor pode servir tambm para

inicializar uma ponteiro exprimindo


que ele aponta sobre nada.
233

Liberao de Memria
Podemos liberar o espao memria alocado para
uma varivel dinmica: free(nome-do-ponteiro); int * p; ... p=(int *)malloc(sizeof(int));

... free(p); /* liberao de p */

// 2 bytes

234

As Estruturas como Parmetros

C no permite passar uma estrutura como


parmetro uma funo.

Mas nada proibe passar um ponteiro sobre uma estrutura:

235

Exemplo
typedef struct {int dia,mes,ano;} data;

/* funo de comparao entre duas datas */ int comp_datas(data * d1, data * d2) { if (d1->ano==d2->ano) && ... return 1; else return 0; } data d1,d2; ... comp_datas (&d1,&d2);
236

Funes retornando Estruturas


Uma funo no pode retornar uma estrutura mas pode retornar um ponteiro sobre uma estrutura:
/ * funo retornando um ponteiro sobre uma data 01/01/2000 */

data * d2001 () { data * p; p=malloc(sizeof(data)); p->dia=1; p->mes=1; p->ano=2000; return (p); } data * d; d=d2001();
237

Observao
Pessoa * p; p=malloc(...)
Normalmente o malloc no retorna um ponteiro sobre uma estrutura. Isto pode causar um warning. Uma maneira correta de escrever :
p=(Pessoa*)malloc(sizeof(Pessoa))

Uma outra soluo : Pessoa * malloc();


238

Exerccio

Defina a funo proximo_aniv que pega

em entrada a data de nascimento de uma


pessoa e retorna uma estrutura designando a data de seu prximo aniversrio.

239

data * proximo_anniv (data * p) { data * anniv; anniv=(data*)malloc(sizeof(data)); anniv->ano=p->ano + 1; anniv->mes=p->mes; anniv->dia=p->dia;

return (anniv);
} data d_nasci,d_anniv; ... d_anniv=proximo_anniv(&d_nasci);
240

Criao de Listas
typedef struct {
char nome[20]; int peso; Pessoa * seguinte; } Pessoa;
nome, peso nome, peso

Cabea

nome,peso

next
241

next

...

NULL

Pessoa * cabeca,pant,patu; char resp; patu=(Pessoa *)malloc(sizeof(Pessoa)); patu->peso=30; ... cabeca=patu; puts("mais uma pessoa (s/n): "); resp=getch(); while (toupper(resp)!=N) { pant=patu; patu=(Pessoa *)malloc(sizeof(Pessoa)); ... /* leitura dos dados da nova pessoa */ pant->seguinte=patu; patu->seguinte=NULL: puts("mais uma pessoa (s/n): ");resp=getch(); }

242

Modos FIFo Vs. LIFO


Existe dois modos para a criao das listas: FIFO: First In First Out LIFO: Last In First Out
Exerccio: 1. Qual o modo de criao de listas aplicado no cdigo da pgina anterior? 2. Cria uma lista usando o outro modo.
243

Listas

Conjunto de elementos individualizados


em que cada um referencia um outro elemento distinto como sucessor

244

Listas
Lista de Tarefas
Comeo em 3 Item 1. Pagar as contas no banco 2. Comprar os livros na livraria 3. Deixar o carro no estacionamento 4. Pegar algumas fitas na videolocadora Prximo 6 4 8 Final

5. Enviar carta pelo correio


6. Buscar as fotos reveladas 7. Autenticar documentos no cartrio 8. Passa na banca de jornais
245

1
2 5 7

Insero no meio da Lista


Antes

Farmcia (9)
Foto (6) Livraria (2)

246

Insero no meio da Lista


1 passo

Farmcia (9)
Foto (6) Livraria (2)

247

Insero no meio da Lista


2 passo

Farmcia (9)
Foto (6) Livraria (2)

248

Insero no meio da Lista

Inserir o item farmcia entre Foto e


Livraria

1 Passo

lista[9].prox = lista[6].prox;

2 Passo

Lista[6].prox = 9;

249

Insero no fim da Lista


Antes

Farmcia (9)
Locadora (4) 0

250

Insero no fim da Lista


1 passo

Farmcia (9)
Foto (6) 0

251

Insero no fim da Lista


2 passo

Farmcia (9)
Foto (6) 0

252

Insero no fim da Lista

Inserir o item farmcia depois de


locadora

1 Passo

lista[9].prox = lista[4].prox;

2 Passo

Lista[4].prox = 9;

253

Insero no incio da Lista


Antes

Farmcia (9)
comeo Estacionam (3)

254

Insero no incio da Lista


1 passo

Farmcia (9)
comeo Estacionam (3)

255

Insero no incio da Lista


2 passo

Farmcia (9)
comeo Estacionam (3)

256

Insero no fim da Lista

Inserir o item farmcia no inicio da


lista (antes do primeiro item)

1 Passo

lista[9].prox = comeco;

2 Passo

comeco = 9;

257

Insero em uma lista


void insere(int novo, int antecessor) { lista[novo].prox = antecessor; antecessor = novo; }

258

Remoo em uma Lista


Antes

Farmcia (9)
comeo Estacionam (3)

259

Remoo em uma Lista


1 passo

Farmcia (9)
comeo Estacionam (3)

260

Remoo em uma lista


void remove(int velho, int antecess) { antecess = lista[velho].prox; }

261

Filas (FIFO)
tambm uma Lista Regra: todo o elemento que entra na lista, entra no final e todo o elemento que sai da lista, sai do incio dela. FIFO (First In, First Out)

262

Filas (FIFO)
#define MAX 100 char *p[MAX]; int rpos=0, spos=0;
void armazena(char *c) { if (spos==MAX) { printf(Lista Cheia\n); else p[spos] = c; spos++; } }
263

Filas (FIFO)
char *retira() { if (rpos==spos) printf(Sem eventos\n); return NULL; else rpos++; return(p[rpos-1]); }

264

PILHA (LIFO)
o inverso de uma fila Regra: todo o elemento que entra na lista, entra no final e todo o elemento que sai da lista, sai do final dela. ltimo a entrar, primeiro a sair LIFO (Last In, First Out) push/pop (empilha/desempilha)

265

PILHA (LIFO) - vetor


int p[100], top=0;
void push(int i) { if (top>=100) printf("pilha cheia\n"); else { p[top] = i; top++; } }

266

PILHA (LIFO) - vetor


int pop(); { top--; if (top<0) { printf("pilha vazia"); return 0; } else return(p[top]); }
267

PILHA (LIFO) - ponteiro


int *p, *top, *b;
p = (int*)malloc(MAX*sizeof(int)); top = p; b = p+MAX-1;

268

PILHA (LIFO) - ponteiro


void push(int i) { if (p>b) printf("pilha cheia\n"); else { *p = i; p++; } }
269

PILHA (LIFO) - ponteiro


int pop(); { p--; if (p<top) { printf("pilha vazia"); return 0; } else return(*p); }
270

rvores Binrias

Rapidez na pesquisa, incluso e excluso (qdo ordenadas)


info

info
271

info
0 0 0

rvores - conceitos
Raiz Ns N terminal Sub-rvore Altura

272

Transversalizao
d
b a

f c e g

Ordenada Preordenada Ps-ordenada


273

abcdefg dbacfeg acbegfd

Unies de Tipos

274

Objetivo

Todas variveis que nos vimos at agora possuam um nico tipo. As vezes interessante atribuir vrios tipos a uma varivel (uma mesma zona memria).
Isto pode ser feito atravs do mecanismo de unies de tipos usando a palavra chave union. Portanto, uma varivel teria, a um dado instante, um nico tipo, porm pode mudar.

275

Declarao
Exemplo:
/* declarao de um tipo que una os inteiros e os reais */
typedef union { int i; float f; } nmero;

numero n; Podemos ento escrever:


n.i=20; /* para atribuir um inteiro */ n.f=3.14159; /* para atribuir um real
276

*/

Observao

A declarao parecida s estruturas, mas nas unies somente um campo atribudo um valor. O problema que nos no podemos saber a um dado instante do programa, qual o tipo do atual valor da varivel. Por isso que na prtica a unio associada a um indicador de tipo (o tipo atual) e os dois so combinados em uma estrutura:

277

Utilizao Prtica das Unies


#define #define INTEIRO REAL 1 0

typedef struct { int tipo_var; union { int i; float f; } nmero; aritmtica;

}
278

Utilizao Prtica das Unies


/* declarao */
aritmtica a1,a2;

a1.tipo_var=INTEIRO;
a1.tipo_var=REAL a1.nmero.i=10; a1.nmero.i=10;
279

Facilitar o acesso aos campos


O acesso aos campos da unio dentro da estrutura no muito prtico: a1.nmero.i=10; Isto pode ser resolvido usando as substituies e o define:
#define #define I nmero.i; R nmero.f;

Agora podemos escrever: a1.I=10; ou a2.R=8.5;


280

Arquivos

281

Streams

Stream de texto

Sequncia de caracteres

Stream binria

Sequncia de bytes com uma

correspondncia de 1 para 1 com aqueles


encontrados no dispositivo externo
282

Funes mais comuns


Nome
Funo

fopen() fclose() putc(), fputc() getc(), fgetc()


283

Abre um arquivo Fecha um arquivo Escreve um caractere em um arquivo L um caractere em um arquivo #include <stdio.h>

Funes mais comuns


Nome
fseek()

Funo
Posiciona o arquivo em um bytes especfico

fprintf()
fscanf() feof() ferror() rewind() remove()

= printf console
= scanf console Final de arquivo? Ocorreu um erro? Indicador de posio no incio do arquivo Apaga um arquivo

284

Ponteiro de arquivo

Ponteiro para informaes que


definem vrias coisas sobre o

arquivo:

Nome, Status, Posio atual, ...

Ponteiro do tipo FILE


FILE *fp;

285

Abrindo um arquivo
FILE *fopen(nomearq, modo);

fopen devolve um ponteiro de

arquivo (em caso de erro o ponteiro


retornado nulo)

286

Abrindo um arquivo

287

r
w a rb

r+
w+

a+
r+b

wb ab

w+b
a+b

Abrindo um arquivo
file *fp;
if ((fp=fopen(test,w))==null)

{
printf(no pode ser aberto);

exit(1);
}
288

Fechando um arquivo

Funo fclose()
Exite uma quantidade mxima de

arquivos que podem ser abertos


FOPEN_MAX (exemplo: 20)

289

Lendo / Escrevendo
void carrega_arquivo(char s[10000], char nome_arquivo[1000]) { FILE *fp; int i=0; if ((fp = fopen(nome_arquivo,"r"))==NULL) { printf("erro\n"); exit(1); } for (i=0; i<9999 && s[i]!=EOF;i++) s[i] = getc(fp); fclose(fp); }
290