Você está na página 1de 66

Escola Estadual de Educao Profissional Dr.

Solon Tavares
Tcnico em Gerenciamento de Redes
Tcnico em Sistemas de Informao

Apostila de

Linguagens de Programao I
e
Estruturas de Dados

Prof. Alan Malta Rodrigues


Guaba, 2007.

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados

Sumrio
CAPTULO 1 CONCEITOS BSICOS .................................................................................... 4
1.1.
INTRODUO
1.2.
COMPILAO DE PROGRAMA C
1.3 .
IMPLEMENTAO
1.4.
ESTRUTURA DE UM PROGRAMA C
1.5.
ANLISE E SOLUO DE PROBLEMAS
CAPTULO 2 EXPRESSES ................................................................................................... 6
2.1.
DADO, INSTRUO E PROGRAMA
2.2.
TIPOS DE DADOS
2.3.
VARIVEIS
2.4.
IDENTIFICADORES DE VARIVEIS EM C
2.5.
CONSTANTES
2.6.
ATRIBUIO
2.7.
OPERADORES ARITMTICOS
2.8.
OPERADORES RELACIONAIS
2.9.
OPERADORES LGICOS
2.10.
OPERADOR BIT A BIT
2.11.
OPERADOR ?
2.12.
OPERADOR SIZEOF
2.13.
PRECEDNCIA
2.14.
CASTS
2.15.
PARNTESES E ESPAAMENTOS
EXERCCIOS
CAPTULO 3 ENTRADA E SADA DE DADOS .................................................................... 11
3.1.
E/S PELO KONSOLE
3.2.
PRINTF()
3.3.
SCANF()
EXERCCIOS
CAPTULO 4 COMANDOS DE SELEO ........................................................................... 13
4.1.
DECISES COM IF
4.2.
DECISES COM SWITCH
4.3.
COMANDOS DE DESVIO INCONDICIONAL
EXERCCIOS
CAPTULO 5 COMANDOS DE REPETIO ........................................................................ 18
5.1.
COMANDO DE REPETIO WHILE
5.2.
COMANDO DE REPETIO FOR
5.3.
COMANDO DE REPETIO DO-WHILE
EXERCCIOS
CAPTULO 6 VETORES E MATRIZES ................................................................................. 22
6.1.
VETORES
6.2.
VETORES BIDIMENSIONAIS - MATRIZES
EXERCCIOS
CAPTULO 7 CADEIA DE CARACTERES ........................................................................... 25
7.1.
CARACTERES
7.2.
CADEIA DE CARACTERES - STRINGS
7.3.
SADA DE DADOS COM STRINGS
7.4.
ENTRADA DE DADOS COM STRINGS
7.5.
FUNES DE STRINGS
7.5.1. FUNO STRCPY()
7.5.2. FUNO STRLEN()
7.5.3. FUNO STRCAT()
7.5.4. FUNO STRCMP()

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens


7.6.
7.6.1.
7.6.2.
7.6.3.
7.6.4.
7.6.5.
7.6.6.
7.6.7.
7.6.8.
7.6.9.

de Programao I e Estruturas de Dados

FUNES DE CARACTERES
FUNO ISALNUM()
FUNO ISALPHA()
FUNO ISDIGIT()
FUNO ISLOWER()
FUNO ISUPPER()
FUNO ISPRINT()
FUNO ISPUNCT()
FUNO TOUPPER()
FUNO TOLOWER()
EXERCCIOS

CAPTULO 8 FUNES ........................................................................................................ 32


8.1.
DECLARAO DE FUNES
8.2.
PROTTIPO DE FUNES
8.3.
VARIVEIS LOCAIS E GLOBAIS
8.4.
ARGUMENTOS DE FUNES
8.5.
COMANDO RETURN
EXERCCIOS
CAPTULO 9 PONTEIROS (APONTADORES) ..................................................................... 35
9.1.
DECLARAO DE PONTEIROS
9.2.
OPERADORES DE PONTEIROS & E *
9.3.
PONTEIROS PARA VETORES
9.4.
VETORES DE PONTEIROS
9.5.
CUIDADOS COM PONTEIROS
9.6.
PONTEIROS COMO PASSAGEM DE PARAMETROS
9.7.
FUNES DE ALOCAO DINMICA EM C
EXERCCIOS
CAPTULO 10 ESTRUTURAS (STRUCTS) .......................................................................... 40
10.1.
DECLARAO DE ESTRUTURAS
10.2.
OPERADORES PONTO (.) E SETA ()
EXERCCIOS
CAPTULO 11 ARQUIVOS .................................................................................................... 43
11.1. FUNES PARA ABRIR E FECHAR ARQUIVOS
11.2. ARQUIVOS EM MODO TEXTO
11.2.1. FUNES PARA LEITURA DE DADOS EM ARQUIVOS
11.2.2. FUNES PARA ESCRITA DE DADOS EM ARQUIVOS
11.3. ARQUIVOS EM MODO BINRIO
11.3.1. FUNO DE LEITURA DE ARQUIVOS BINRIOS
11.3.2. FUNO DE ESCRITA EM ARQUIVOS BINRIOS
CAPTULO 12 - LISTAS ENCADEADAS ................................................................................ 50
12.1. LISTA ENCADEADA
12.2. FUNES DE MANIPULAO
12.3. LISTAS CIRCULARES
12.4. LISTAS DUPLAMENTE ENCADEADAS
EXERCCIOS
CAPTULO 13 PILHAS .......................................................................................................... 58
13.1.
IMPLEMENTAO DE PILHA COM VETOR
13.2.
IMPLEMENTAO DE PILHA COM LISTA ENCADEADA
EXERCCIOS
ANEXO A FUNES MATEMTICAS ................................................................................. 63
ALGUMAS FUNES IMPORTANTES
EXERCCIOS

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados


Objetivo

Esta apostila foi construda com o intuito de facilitar o ensino da linguagem de


programao C, a ser aplicado na disciplina de Estruturas de Dados do segundo mdulo na
Escola Solon Tavares. Poderemos acompanhar o contedo atravs dela, a qual ser composta
pelos comandos bsicos de C e muitos exemplos e exerccios, pois sem a prtica da
programao, o ensino e a compreenso se tornam mais complexo.

1. Conceitos bsicos
1.1. Introduo
A linguagem C foi criada por Dennis Ritchie, implementada em UNIX. O nome da linguagem se
deve a uma linguagem anterior que tinha o nome de B. A linguagem segue um padro
estabelecido em 1983 pelo ANSI (American National Standards Institute). C considerada uma
linguagem de mdio nvel, podendo trabalhar com bits, bytes e endereos.
Cdigos escritos em C so altamente portveis, ou seja, programas aplicados em um sistema
operacional funcionaro normalmente em outros sistemas operacionais, com pouca ou
nenhuma alterao. O C uma linguagem estruturada, ou seja, um programa pode ser dividido
em varias sub-rotinas (mini-programa), onde cada sub-rotina cria suas prprias variveis e
executa determinada funo.
Quando voc cria um programa em C, voc obtm o cdigo-fonte, mas para esse programa ser
executado pela mquina necessrio compila-lo. Um compilador tem como funo ler um
cdigo-fonte e atravs da converso deste criar um cdigo-objeto, ento este cdigo-objeto
(tambm conhecido como cdigo-binrio ou cdigo de mquina) pode ser executado pela
mquina.
Em Estruturas de Dados sero discutidas diversas tcnicas de programao, introduzindo os
conceitos bsicos da linguagem de programao C, que sero utilizadas para a implementao
das estruturas de dados apresentadas. A linguagem C tem sido amplamente utilizada na
elaborao de programas e sistemas nas diversas reas em que a informtica atua.
Utilizaremos nas aulas de programao C o sistema operacional Kubuntu GNU/Linux, os
programas sero digitados no Editor de texto Kate e o programa ser compilado e executado
atravs do Konsole. Para quem preferir programar no Windows h uma ferramenta muito boa,
na qual voc edita o cdigo fonte, compila e tambm executa, chamado de Devc++.
1.2. Compilao de programas C
Para compilar um programa em C ser necessrio seguir basicamente trs passos:

Criar o programa (cdigo fonte);


Compilar o cdigo fonte (gerar o cdigo objeto);
Executar o cdigo objeto.

Para estes processos ser necessrio um editor de textos e um compilador. Com o editor
escreveremos os programas fontes, que devem ser salvos com a extenso .c. Com o
compilador geramos o cdigo objeto atravs do cdigo fonte, para poderem ser executados.
Para compilar um programa, com o nome p.e. prog.c, digite no Konsole:
gcc prog.c o prog

//pode ser assim: gcc -o prog prog.c

Se no houver erro de compilao no arquivo fonte, ser gerado um executvel com nome
prog. Podemos ento executar o programa da seguinte forma:
./prog
1.3. Implementao

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados

Traduo do algoritmo para linguagem de programao. Programa um roteiro que orienta o


computador, mostrando-lhe a seqncia de operaes necessrias para executar uma
determinada tarefa.
1.4. Estrutura de um programa C
#include<stdio.h>
main() {
bloco de comandos;
}

#include<stdio.h>: esta linha mostra ao compilador que ser usado o arquivo


cabealho stdio.h. Este arquivo contm declaraes de funes teis de entrada e
sada de dados (std = standard, padro em ingls, io = input/output, entrada/sada em
ingls).
main: define o inicio da execuo em um programa C. a nica funo obrigatria em
qualquer programa C e uma palavra reservada da linguagem.
{ }: indicam, respectivamente, o inicio e o termino da funo main.
( ): contem os parmetros da funo (se existir).
a palavra reservada main, os parnteses e as chaves so os nicos elementos
obrigatrios.
as palavras reservadas tm um significado pr-definido na linguagem.

Podem-se inserir comentrios no cdigo fonte, iniciados com /* e finalizados com */, assim
como pode ser utilizado tambm o // (mas este s comenta a linha correspondente).
Declaraes e comandos em C so terminados pelo caractere ponto-e-vrgula (;).
1.5. Anlise e soluo de problemas
A programao consiste de um problema que lanado a ns, o qual temos que resolver
computacionalmente, sendo desta forma, temos que guiar o computador para a soluo deste
problema, assim seguimos algumas etapas:

Primeiramente devemos especificar claramente o problema;


o O que deve ser resolvido?
o Quais os dados e tipos de dados meu programa deve receber (entrada de
dados)?
o Qual a sada e o tipo de dado que o programa deve enviar (sada de dados)?
Aps analisado os dados de entrada e sada, devemos descobrir uma soluo, criar um
algoritmo para a resoluo do problema. Transformar o que deve ser resolvido em
como resolve-lo. Um problema computacional geralmente tem mais de uma soluo.
Escrever a soluo em uma linguagem de programao.
Por fim, testar a soluo, ou seja, testar o programa. Se o programa no se comportar
como deveria, rever o algoritmo aplicado no problema.

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados


2. Expresses

A combinao de variveis, constantes e operadores constituem uma expresso.


2.1. Dado, instruo e programa
Um computador manipula informaes ou dados. Uma instruo algo que manipula dados.
Isto , uma instruo executa uma determinada operao sobre um ou mais dados. Um
programa composto por uma serie de instrues.
2.2. Tipos de dados
Em C podemos encontrar cinco tipos bsicos de dados: inteiro, ponto flutuante, ponto flutuante
de dupla preciso, caractere e vazio (int, float, double, char e void). Dados do tipo inteiro
geralmente so compostos de quatro bytes, mas isto pode variar de acordo com a arquitetura
da mquina. Valores do tipo caractere geralmente apresentam o tamanho de 1 byte, definido
de acordo com a tabela ASCII. Os dados do tipo ponto flutuante so caracterizados de acordo
com sua faixa de preciso. Por fim, o tipo vazio significa que a funo no retorna valores. Os
tipos de dados devem ser definidos para cada varivel, sendo que ele define um conjunto de
valores que uma varivel pode receber e quais operaes podem ser executadas com ela.
Tipo
int
float
char
unsigned char
double

Tamanho
32 bits
32 bits
8 bits
8 bits
64 bits

Faixa
-2.147.483.648 a 2.147.483.647
6 dgitos de preciso
-128 a 127
0 a 255
10 dgitos de preciso

2.3. Variveis
Correspondem a uma posio de memria;
contedo pode variar ao longo do tempo;
armazenam um s valor por vez;
armazenam valores de um s tipo (logo, tem tipo definido);
devem ser declaradas antes de serem utilizadas;
valor inicial imprevisvel (posio de memria);
Uma varivel uma entidade que possui um valor, sendo conhecida no programa por um nome
(identificador). As variveis so declaradas em trs lugares bsicos: no campo de parmetros
de funes, no incio de funes e fora de todas as funes. A forma geral de declarao de
variveis :
tipo lista_de_variveis;
Onde tipo um tipo de dado em C, e lista_de_variveis pode ser composta de apenas 1
varivel ou vrias, separadas por vrgulas.
Exemplo:
int reta, curva, a, b;
char nome, turma;
short int lado;
Em C possvel inicializar as variveis junto a declarao, ou seja, no momento que a varivel
estiver sendo declarada, ela poder receber um valor inicial, para isto deve-se colocar um sinal
de igualdade e uma constante logo aps o nome, por exemplo:
int reta = 10, curva = 5;
char letra = z;
2.4. Identificadores de variveis em C
Para identificar corretamente variveis e funes, os seguintes itens so necessrios:

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados

o primeiro caractere deve ser uma letra ou _ (sub-linha) e as demais podem ser letras,
numero ou caracteres (sub-linha);
em C os primeiros 32 caracteres so significativos, ou seja, no adianta colocar
identificadores muito extensos porque sero ignorados pelo compilador;
o C distingue letras maisculas de minsculas;
no deve ser utilizado as palavras reservadas da linguagem, assim como no deve ser
dado nomes a variveis iguais a identificadores de funes.

2.5. Constantes
As constantes se caracterizam por valores fixos que no podem ser alterados. As constantes
satisfazem os cinco tipos de dados em C, variando sua representao de acordo com o tipo.
Para nmeros inteiros e ponto flutuante basta colocar o valor (p.e.: 7, -2.13, 25423).
Constantes do tipo caractere so envolvidas por aspas simples (p.e.: a, A, !). Constantes do
tipo string so representadas entre aspas duplas (p.e.: ola, ola novamente amigo).
Constantes em octal so representadas com um 0 na frente (e seguidas de 0 a 7) e constantes
em hexadecimal so representadas com um 0x na frente ( e seguidas de 0 a 9 ou de a at f).
Em C as constantes podem ser definidas atravs do comando #define. Dessa forma, todas as
vezes que o smbolo ou palavra definido logo aps ao #define for encontrado no programa, ele
ser automaticamente substitudo pelo valor definido no final do comando #define. Podemos
definir vrias constantes em um programa. Sua forma geral :
#define nome_da_constante valor
Exemplo:
#define PI 3.141592
#define AREA 0.0
2.6. Atribuio
A operao de atribuio especifica que a uma varivel ser dado um valor ou o resultado de
uma expresso. A atribuio em C indicada pelo smbolo de igualdade =. O lado esquerdo
da igualdade ser o destino do valor e deve ser uma varivel ou um ponteiro, o lado direito
pode ser uma constante, uma expresso ou uma varivel.
Exemplo:
varivel = expresso;
a = 5;
c = 10.3;
a = b = c = 10;

// varivel recebe valor da expresso


/* armazena o valor 5 em a */
/* armazena o valor 10.3 em c */
// todas as variveis recebem o valor 10

2.7. Operadores Aritmticos


Operadores aritmticos so usados para desenvolver operaes matemticas.
+
*
/
%
++
--

Adio
Subtrao
Multiplicao
Diviso
Mdulo (devolve o resto da diviso inteira, e s aceita operandos inteiros).
Incremento
Decremento

Exemplo:
c = a + b;
i = i + 2;
n++;
n--;

/* armazena a soma do contedo de a e b em c */


// varivel i recebe contedo de i + 2
// n recebe n + 1;
// n recebe n 1;

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens


a = 3 % 2;
b = 127 % 10;
recebe 7
c = b % a;

de Programao I e Estruturas de Dados

//devolve resto da diviso inteira de 3 por 2, ou seja, a recebe 1


//devolve resto da diviso inteira de 127 por 10, ou seja, b
//devolve resto da diviso inteira do contedo de b (7) pelo
//contedo de a (1), ou seja, 7 mdulo 1 igual a 0, c recebe 0

Tambm temos operadores reduzidos em C, simplificando a codificao de certas operaes


de atribuio. Sua forma geral :
//

varivel operador = expresso;


expresso;
Exemplo:
x += 10;
y *= (10 + 25);

varivel

varivel

operador

// igual a x = x + 10;
// igual a y = y * (10 + 25)

2.8. Operadores Relacionais


Os operadores relacionais realizam comparaes entre duas ou mais variveis. O resultado
gerado por um operador relacional ou operador lgico um (1) ou zero (0) (verdadeiro ou
falso). Em C no existe o tipo booleano (verdadeiro ou falso). O valor zero interpretado como
falso e qualquer valor diferente de zero considerado verdadeiro.
>
>=
<
<=
==
!=

Maior que
Maior ou igual a
Menor que
Menor ou igual a
Igual a
Diferente de

2.9. Operadores Lgicos


Os operadores lgicos realizam comparaes e retornam verdadeiro ou falso. Normalmente
so utilizados para tomada de decises e para atribuir valores a variveis.
&&
||
!

Operador lgico E
Operador lgico OU
Negao

2.10. Operador Bit a Bit


Como C foi projetada para substituir o assembly em muitas tarefas de programao, ela
suporta manipulao de bits. As operaes bit a bit testam, atribuem ou deslocam bits em 1
byte ou uma palavra, portanto, s podem ser utilizados em dados do tipo int e do tipo char.
&
|
^
~
>>
<<

Operador lgico E
Operador lgico OU
Operador lgico XOR (ou exclusivo)
Complemento de um
Deslocamento direita
Deslocamento esquerda

2.11. Operador ?
O operador ternrio ? utilizado para substituir uma instruo de desvio condicional como ifthen-else. Sua forma geral :
(expresso1) ? expresso2 : expresso3;

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados

Onde expresso1 a expresso que est sendo testada, se ela for verdadeira a expresso2
ser validada, caso contrrio a expresso3 ser validada.
Exemplo:
resultado = (nota>6) ? 10 : 0;

// resultado recebe 10 ou 0

2.12. Operador sizeof


Este operador unrio retorna o tamanho, em bytes, de uma determinada varivel ou
especificador de tipo, porm este ltimo deve estar entre parnteses.
Exemplo:
int a;
char b;
a = sizeof
a = sizeof
printf(Um
printf(Um
printf(Um
printf(Um

(float);
// armazena o valor 4 em a
(b);
// armazena o valor 1 em a
int possui %d bytes.\n,sizeof (int));
float possui %d bytes.\n,sizeof (float));
double possui %d bytes.\n,sizeof (double));
char possui %d byte.\n,sizeof (char));

2.13. Precedncia
Maior precedncia

()
!
*
+
<
==
&&
||

->
++
/
<=
!=

-%
>

>=

Menor precedncia

2.14. Casts
Quando utilizamos tipos de dados diferentes em expresses, o compilador faz converses de
operandos que possuem tamanho menor em maiores, se existirem na expresso, porm,
podemos garantir um tipo de dado final da expresso com Casts. Este comando ir forar uma
expresso a ser de determinado tipo. Onde tipo qualquer tipo de dado vlido em C. Sua
forma geral :
(tipo) expresso;
2.15. Parnteses e Espaamentos
Visando tornar expresses e o programa mais legvel, podemos acrescentar espaamentos e
tabulaes no cdigo fonte. Assim como parnteses adicionais facilita a compreenso de uma
expresso e d mais controle ao programador referente s precedncias de operaes.
Exerccios:
1) Resolva as expresses abaixo e descubra se o resultado 1 (Verdadeiro) ou 0 (Falso).
a) 10 > 3
b) 10 != 10
c) (10 >= 9) || (10 >= 11)
d) (10 <= 11) && (10 >= 9)
e) !(7

>3) || !(5 < 7)

f) !(9 < 0) && (9 > 0)


g) (23 >= 2) || ! !(13 < 6)

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados

2) Determine o valor das seguintes expresses aritmticas:


a) 15 * 14 -3 * 7
b) (10 + 2 * 6) / 5
c) 8 * 23 % 14 + 86 23 + 78 / 12
d) 2 + 3 * (4 * (4 (4 8) / 2))

3) Determine o valor das seguintes expresses aritmticas:


a) 15 / 12

e) 15 % 12

b) 24 / 12

f) 24 % 12

c) 123 / 100

g) 123 % 100

d) 200 / 100

h) 200 % 100

4) Transcreva as seguintes funes matemticas na linguagem de programao C.

10

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados


3. Entrada e Sada de dados

Em C h dois tipos de E/S de dados, a primeira pelo Konsole e a segunda por arquivos.
3.1. E/S pelo Konsole
Em C, tudo feito atravs de funes, inclusive as operaes de entrada e sada. Na
linguagem C temos uma biblioteca padro que possui as funes bsicas normalmente
necessrias. Para isso, devemos incluir o prottipo destas funes no inicio do cdigo.
#include <stdio.h>
A linguagem C contm um conjunto de instrues que permitem ao operador interagir com o
programa fornecendo dados e recebendo mensagens. As funes printf( ) e scanf( ) so
responsveis pela entrada e sada de dados, podendo ler e escrever dados em vrios
formatos.
3.2. printf()
Esta funo escreve dados no vdeo e sua forma geral :
printf (string_de_controle,lista_de_argumentos);
A string_de_controle descreve o que a funo printf( ) vai imprimir na tela. Ela mostra no
somente a mensagem que deve ser colocada na tela, mas tambm quais as variveis e suas
respectivas posies, isto feito usando-se os cdigos de controle que usam a notao %. Na
string de controle indicamos quais, de qual tipo e em que posies esto as variveis a serem
impressas. Para cada cdigo de controle deve haver uma varivel na lista_de_argumentos,
estes dois so combinados na ordem da esquerda para a direita.
Cdigos de Controle:

%d
%c
%f
%s
%o
%x
%%
%p

Inteiro
Caracter
Ponto flutuante
String
Octal
Hexadecimal
Imprime o caractere %
Imprime o endereo da varivel

Exemplo:
int b = 8;
float a = 10.4;
printf(\n\tO inteiro eh %d e o real eh %f \n, b, a);
//imprimi O inteiro eh 8 e o real eh 10.4
printf(\n Ola,eu estou vivo!);
// ser impresso no Konsole Ola,eu estou vivo!
No lugar do %d ser impresso o valor armazenado na varivel b (valor inteiro) e no lugar do %f
ser impresso o valor armazenado na varivel a (valor real). O \n significa nova linha e o \t
significa tabulao no terminal, sendo assim antes de imprimir a mensagem pularia uma linha e
daria uma tabulao para a mensagem ser impressa.
Para escrever um caracter deve-se utilizar o cdigo %c. Mas se for preciso imprimir uma string
deve-se usar o cdigo %s.
3.3. scanf()
Responsvel pela entrada de dados via Konsole, sua forma geral :
scanf(string_de_controle,lista_de_argumentos);

11

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados

Usando a funo scanf( ) podemos ler dados digitados pelo usurio. Para cada cdigo de
controle na string_de_controle deve haver uma varivel na lista_de_argumentos, estes dois
so combinados na ordem da esquerda para a direita.. Deve-se colocar o & antes de cada
argumento da lista_de_argumentos. Os cdigos de controle na string_de_controle so os
mesmos da funo printf( ) => ( %d, %f, %c, %s). A funo scanf( ) termina a leitura de um
nmero quando um caractere diferente de nmeros for pressionado.
Para a leitura de uma string devemos utilizar o cdigo %s, no qual acabar a leitura da string
quando for encontrado um caractere de espao em branco, porm, se for necessrio controlar
a leitura de caracteres de uma string, coloca-se o nmero de caracteres mximo a ser lido pelo
scanf( ) para determinada cadeia de caracteres.
Exemplo:
scanf(%20s,str);
scanf(%d %f,&b,&a);

scanf(%c,&smbolo);

// ir ler apenas os 20 primeiros caracteres digitados


// b recebe um nmero inteiro digitado
// a recebe um nmero real digitado
// smbolo recebe um caractere

Exerccios: Desenvolva programas em C para as seguintes questes.


1) Ler dois valores inteiros e imprimi-los.
2) Ler trs valores reais e imprimir o somatrio deles.
3) Armazenar o valor 10 na varivel a, o valor 5 na varivel b e trocar seus contedos
apresentando a resposta.
4) Supondo um valor real referente largura e um outro referente ao comprimento de
uma sala, escreva um programa que leia esses 2 valores e calcule a rea dessa
sala, imprimindo a resposta.
5) Desenvolva um programa que receba o raio e efetue o clculo do permetro de uma
circunferncia, apresentando a medida calculada.
6) Escreva um programa que leia uma temperatura em graus Fahrenheit e converta-a
para graus Celsius. Para isso voc deve utilizar a frmula C = ( F 32 ) * ( 5 / 9 ).
7) Ler o raio e a altura de um cone, calcular o valor de seu volume e apresentar o
2
resultado, utilizando a seguinte formula: VOLUME = (.R .ALTURA)/3.
8) Escreva um programa que faa a leitura de um valor inteiro de segundos, e imprima
o equivalente em minutos e horas.
9) Faa um programa em C que leia uma medida em metros e a converta para
polegadas, centmetros e ps, apresentando os resultados ao final. Lembre-se que:
1.0 metro = 100.0 cm
1.0 metro = 10000.0/254.0 (~ 39.3700787402) polegadas
1.0 metro = 1.0/0.3048 (~ 3.28083989501) ps

12

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados


4. Comandos de Seleo

Em C encontramos dois comandos de desvio condicional, esse desvio depende do teste de


uma expresso, resultando em um valor verdadeiro ou falso, porm, no encontramos esses
resultados em C, mas sim valores iguais ou diferentes de zero. Para qualquer valor diferente de
zero consideramos que a resposta verdadeira, j um valor falso representado pelo valor 0.
4.1. Decises com if
A estrutura bsica do comando if :
if(condio)
{
comando ou bloco de comandos;
}
ou
if(condio)
{
bloco de comandos do if;
}
else {
bloco de comandos do else;
}
Na primeira estrutura se a expresso produzir um valor diferente de 0 (verdadeiro), o bloco de
comandos ser executado, caso contrrio a execuo do programa continua a partir do fecha
chaves }. Na segunda estrutura temos duas opes, se o teste for diferente de 0 (verdadeiro)
o bloco de comandos do if que est delimitado pelas chaves ser executado, caso contrrio (se
a expresso resultar no valor 0), somente o bloco de comandos do else ser executado.
Os blocos de comando devem ser delimitados por uma chave aberta e uma chave fechada,
porm, se o desvio possuir apenas uma instruo (um comando), no se torna obrigatrio o
uso de chaves. A indentao (recuo de linha) dos comandos fundamental para uma maior
clareza do cdigo.
Na instruo if-else, ou ser executado o bloco de comandos do if, ou ser executado o bloco
de comandos referente ao else. Leia assim, se isto, ento isso, se no aquilo.... Em C, um
comando else sempre se refere ao comando if mais prximo.
/*Recebe 2 valores e acha o maior*/
Exemplo:
#include<stdio.h>
int main()
{
int n1, n2;
// variveis do tipo inteiro
printf(\n Entre com 2 valores inteiro\n);
scanf(%d %d, &n1, &n2);
//armazena 1 dado lido em cada varivel
if (n1 > n2)
printf(\n Este valor eh o maior %d \n,n1);
else
printf(\n Este valor eh o maior %d \n,n2);
}
O uso de comandos if aninhados (em cascata) vlido e muito usado. Conforme veremos no
exemplo:
if (expresso)
{
if (expresso)
comando;
if (expresso)
comando;
else
comando;

13

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados

Com a utilizao do comando if podemos construir a chamada escada if-else-if, a qual consiste
em um novo teste condicional caso o teste anterior tenha retornado 0 (falso), at que encontre
o ltimo else ou satisfaa algum dos testes anteriores, conforme mostra o exemplo:
if (expresso)
comando;
else if (expresso)
commando;
else if (expresso)
commando;
...
else
commando;
4.2. Decises com switch
O comando switch uma estrutura de controle condicional. Permite que grupos particulares de
instrues sejam escolhidas entre grupos possveis. A escolha baseada no valor
correspondente de uma varivel ou expresso.
O comando switch prprio para se testar uma varivel em relao a diversos valores prestabelecidos, tanto para constantes inteiras quanto para caracteres.
Sua forma geral :
switch(varivel ou expresso) {
case constante1:
comando1;
break;
case constante2:
comando2;
break;
.... ....
.... ....
case constanteN:
comandoN;
break;
default:
comando_default;
break;
}
O switch testa a varivel (ou expresso) contra os valores especificados nos comandos case e
executa o comando (ou bloco de comandos) cujo case coincidiu com o valor da varivel ou
expresso, esses comandos sero executados at que seja encontrado o comando break ou o
fim do comando switch. A declarao default opcional e ser executada apenas se a
varivel (ou expresso) que est sendo testada no for igual a nenhuma das constantes prestabelecidas nos case. O case no pode existir fora do comando switch.
O break um comando de desvio em C, faz com que o switch seja interrompido passando a
execuo do programa a partir da prxima linha de comando aps o fecha chaves do switch.
O comando break muito utilizado em laos.
Duas constantes case no mesmo switch no podem possuir o mesmo valor, exceo de um
switch dentro de outro. No caso de constantes caracteres, estas devem estar entre aspas
simples, e elas so automaticamente convertidas para seus valores correspondentes inteiro de
acordo com a tabela ASCII.
possvel ter instrues case sem nenhum comando associado, porm, quando isto acontece
a execuo do programa cai no prximo case. importante deixar claro que todo o comando
switch forma um bloco de comandos e os comandos associados a cada case so uma

14

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados

seqncia de comandos, ou seja, variveis locais so declaradas no incio de blocos de


comandos e no podem ser declaradas dentro dos comandos associados aos cases.
/*Entre com o dia da semana e ser impresso o nome*/
Exemplo:
#include<stdio.h>
int main()
{
int num;
printf(\n Digite um numero entre 1 e 7 \n);
scanf(%d,&num);
// armazena valor inteiro em num
switch(num)
{
// testa num
case 1:
printf(\n Domingo\n);
break;
case 2:
printf(\n Segunda-feira\n);
break;
case 3:
printf(\n Terca-feira\n);
break;
case 4:
printf(\n Quarta-feira\n);
break;
case 5:
printf(\n Quinta-feira\n);
break;
case 6:
printf(\n Sexta-feira\n);
break;
case 7:
printf(\n 15onte\n);
break;
default:
//se valor for != dos case entra aqui no default
printf(\n Valor digitado invalido\n);
break;
}
}
4.3. Comandos de Desvio Incondicional
O C disponibiliza quatro comandos de desvio incondicional, dois deles voc utiliza em
comandos de loopings e os outros dois em qualquer parte do programa.
4.3.1. Comando return
Comando utilizado para retornar de uma funo, retorna a execuo do programa a partir do
ponto em que foi chamado na outra funo. Sempre que for encontrado o primeiro return, a
funo ser finalizada, assim como se for encontrado o smbolo } da funo. Este comando
pode simplesmente retornar de uma funo, como retornar um valor para a funo que o
chamou. Se nenhum valor for especificado, ser retornado zero. A forma geral deste comando
:
return expresso;
importante enfatizar que em funes do tipo void no poder ser utilizado o comando return.
4.3.2. Comando goto
Comando de desvio incondicional, normalmente no utilizado em C devido a ilegibilidade do
cdigo fonte. Utilizando este comando voc define um rtulo, este rtulo voc coloca em outra
parte do programa seguido de dois pontos :, definindo ali o ponto de salto (destino) do
programa. Sua forma geral a seguinte:

15

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados

goto rtulo;
...
...
rtulo:
4.3.3. Comando break
Conforme estudado no comando switch, o comando break utilizado para interromper a
execuo dos comandos dentro de um case, assim como interromper a continuidade de
execuo de um lao.
4.3.4. Funo exit()
Utilizando a funo exit() voc sai imediatamente de um programa. Sua forma geral :
exit(cdigo_de_retorno);
Onde cdigo_de_retorno contm um valor inteiro retornado para o S.O., se este valor for 0
(zero) significa que o programa teve uma terminao normal, j outros valores normalmente
indicam algum tipo de erro.
Exerccios:
1) Escreva um programa que faa a leitura de dois valores inteiros e descubra qual o
maior, imprimindo a resposta.
2) Escreva um programa que faa a leitura de dois valores reais e faa a diviso entre
eles se o denominador no for zero. Ao final deve ser impresso o resultado ou uma
mensagem de erro..
3) Ler um valor numrico inteiro e descobrir se ele maior ou igual a 10 e menor ou
igual a 20 (utilize operadores lgicos). Se ele satisfizer essas condies dever
aparecer no vdeo VERDADE, caso contrrio dever aparecer MENTIRA.
4) Escreva um programa que descubra se trs valores recebidos esto ou no em
ordem crescente.
5) Ler 3 valores numricos inteiros (variveis a, b e c) e descobrir se este tringulo
Equiltero, Issceles ou Escaleno. Lembrando que o tringulo ser eqiltero
quando todas as arestas (lados) dele forem do mesmo tamanho. Issceles quando
apenas duas arestas forem iguais ou ser escaleno quando todas as medidas das
arestas forem diferentes. No final dever apresentar a resposta: EQUILTERO,
ESCALENO ou ISSCELES.
6) Escreva um programa que mostre na tela o conceito conforme a nota obtida, de
acordo com a tabela seguinte:
De 9,0 a 10,0
A
De 7,5 a 9,0
B
De 6,0 a 7,5
C
De 4,0 a 6,0
D
De 0,0 a 4,0
E
7) Escreva um programa que leia um valor inteiro e descubra se o mesmo par ou
mpar, apresentando a resposta.
8) Escreva um programa que faa a leitura da idade de 2 homens e 2 mulheres
(supondo que as idades do mesmo sexo sero diferentes). O programa deve fazer o
somatrio da idade do homem mais velho com a idade da mulher mais nova e o

16

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados

produto da idade do homem mais novo pela idade da mulher mais velha. Ao final
imprimir os resultados.
9) Faa um programa que simule uma calculadora padro, com as operaes + soma,
- subtrao, * multiplicao e / diviso. Inicialmente o programa deve pedir a
operao ao usurio, aps o usurio deve entrar com os 2 operandos. Ao final, o
programa deve imprimir a resposta.
10) Crie um programa que leia 3 valores inteiros e imprima-os em ordem crescente.
11) Faca um programa que receba hora e minuto inicial e final de uma partida de tnis, a
durao do jogo no pode ultrapassar 60 minutos. O programa deve calcular a
durao do jogo, considere que o jogo pode comear em um dia e acabar somente
no outro.

17

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados


5. Comandos de Repetio

Algoritmos com laos (loopings) definem conjuntos de instrues que devem ser executadas
repetidas vezes, ou seja, uma ao deve ser realizada um numero preciso e conhecido de
vezes em um ou mais comandos.
5.1. Comando de Repetio while
O while um comando de lao, isto , que permite que as instrues que se encontram dentro
do lao sejam repetidas.
Sua forma geral :
while (condio)
comando;

// ou bloco de comandos entre chaves

Ele faz com que o lao (comando ou bloco de comandos) sejam executados enquanto a
condio for verdadeira, onde a condio verdadeira ser sempre que for um valor diferente de
zero. Quando a condio for falsa, a execuo do programa passa para o prximo comando
aps o bloco de comandos do lao while.
O lao while seria equivalente a:
if(condio)
{
comando;
volte para o comando if
}
O while tem a mesma caracterstica que o lao for referente a verificao condicional, que
sempre feita no inicio do lao.
Exemplo:
#include<stdio.h>
// imprime o numero de i de 0 ate 99
int main( ) {
int i=0;
while(i<100)
{
printf( %d ,i);
i++; }
}
5.2. Comando de Repetio for
O lao de repetio for um comando muito utilizado para repetir linha(s) de comando(s).
Utiliza uma varivel contadora para definir o ponto de incio e fim do looping. As execues das
instrues acontecem at que um valor limite para a varivel contador seja ultrapassado.
Sua forma geral :
for(inicializao; condio; atualizao)
comando;
Onde a inicializao normalmente um comando de atribuio que inseri um valor inicial na
varivel de controle (contador). A condio carrega uma expresso relacional, pode ser lgica
tambm, a qual determina at quando o lao ser executado. Por fim, a atualizao
caracterizado pela operao que executada em cima da varivel contadora todas as vezes
que o lao se repetir. No momento que a condio se tornar falsa, o lao no mais executado
e o programa da continuidade aps o final do bloco de comandos do for.
Exemplo1:
#include<stdio.h>
int main( ) {

18

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados

int contador;
for(contador=1;contador<=100;contador++)
printf(\n No devo conversar em aula);
No exemplo 1, o contador inicializado com 1, a operao em cima do contador de
incremento de uma unidade e a condio que o contador seja menor ou igual a 100, assim
que o contador se tornar maior que 100 ser interrompida a execuo do lao. A mensagem
No devo conversar em aula ser impressa cem vezes e aps ser finalizado o programa.
O melhor modo de entender o lao for ver de que maneira ele funciona. O lao for
equivalente a:
inicializao
if (condio)
{
//se condio V, ento entra no lao
comando
// ou bloco de comandos
atualizao
//atualiza contador
volte para o comando if
}
Podemos ver que o for executa a inicializao incondicionalmente e ento testa a condio. Se
ela for falsa, no faz mais nada, se ela for verdadeira, ele executa o comando (ou bloco de
comandos), realiza o incremento e volta a testar a condio. Ele fica repetindo estas operaes
at que a condio seja falsa.
Exemplo2:
for (i=100; i>0; i=i-1)
printf(\n %d , i);
No exemplo 2 ser impresso todos os valores inteiros entre os nmeros 100 e 1, na ordem
decrescente de unidade em unidade, at que o valor 0 seja atingido no contador (i) e
interrompa a execuo do looping.
Exemplo3:
for (i=0; i>0; i=i+5)
printf(\n Oi );
Neste exemplo 3 no ser impresso nenhuma vez a mensagem Oi, pois o lao inicializado
com 0 e a condio exige que este valor seja maior que zero..
Exemplo4:
for (i=0; i!=666; )
scanf(%d, &i);
Conforme demonstrado no exemplo 4, partes da definio do lao for no precisam existir. O
programa inicializa a varivel i com 0 e testa se ela diferente de 666, enquanto o usurio no
digitar este ltimo valor o lao continuar em execuo, sem que seja feito nenhuma operao
de incremento na repetio do lao.
Exemplo5:
for ( ; ; )
printf( Looping Infinito);
O exemplo 5 sinaliza a construo de um lao infinito, ou seja, os comandos associados ao for
sero eternamente executados at que o computador estrague, falte energia ou at o fim do
mundo.
5.3. Comando de Repetio do-while
Em C podemos ver outro comando para a construo de laos, cujo teste avaliado somente
no final do lao. O comando do-while garante que pelo menos uma vez ser executado o
comando ou bloco de comandos.

19

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados

do {
comando ou bloco de comandos;
}while(condio);
Este lao repete o comando ou bloco de comandos at que a condio seja falsa, ou seja, at
que o valor condicional resultante seja zero. Para esta instruo, procure sempre utilizar as
chaves, mesmo que tenha apenas um comando, a fim de evitar confuses futuras.
Exemplo:
do {
scanf(%d, &valor);
} while( (valor >= 1) && (valor <= 100) )
O exemplo acima demonstra um cdigo que ler do teclado um valor, enquanto este valor
estiver compreendido entre 1 e 100, ele continuar lendo novos valores, quando for digitado
um valor maior que 100 ou menor que 1 o lao interrompe a execuo.
Exerccios:
1) Crie um programa que imprima todos os nmeros mpares compreendidos entre 10 e
140.
2) Escreva um programa que apresente o quadrado dos nmeros inteiros de 1 a 100.
3) Repita 10 vezes os seguintes passos: leitura de um valor real, multiplicao pelo
nmero 7 e apresentao da resposta.
4) Apresentar os resultados de uma tabuada de um nmero inteiro qualquer. Por exemplo,
foi digitado o nmero 3, ento o programa dever imprimir assim:
3x1=3
3x2=6
(...)
3 x 10 = 30
5) Escreva um programa que apresente o total da soma dos nmeros inteiros entre 50 e
80, inclusive 50 e 80.
6) Escreva um programa que faa a leitura de um valor inteiro n e calcule o somatrio dos
n primeiros nmeros naturais, apresentando o resultado.
7) Escreva um programa que leia um nmero inteiro para n e calcule a soma da srie 1/1,
1/2, 1/3, ..., 1/n e imprima o resultado ao final.
8) Faa um programa que continue em execuo enquanto no receber um valor mltiplo
de 7, assim que for digitado um valor correto o programa dever encerrar sua execuo.
9) Escreva um programa que receba dois valores inteiros e imprima o somatrio de todos
os valores inteiros compreendidos entre eles (inclusive eles). Nota: o intervalo pode
comear em um valor maior e acabar em um valor menor.
10) Escreva um programa que imprima somente os nmeros mpares compreendidos entre
dois nmeros inteiros recebidos do teclado. Nota: o intervalo pode comear em um valor
maior e acabar em um valor menor.
11) Faa um programa que receba um valor n inteiro e calcule seu fatorial. O programa
deve imprimir a resposta.
12) Escreva um programa que receba um nmero inteiro e descubra se o mesmo ou no
um nmero primo.

20

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados

13) Dado um n lido do teclado, calcule a soma da srie: 1/2 + 2/2 + 3/2 + ... + n/2 .
x

14) Crie um programa que calcule o valor de e . O valor de x deve ser lido do teclado. O
resultado deve ter uma preciso de no mnimo 0.0001 do resultado obtido atravs da
funo exp. Ao final deve ser apresentado o valor de x, o valor calculado atravs da
srie e o valor obtido pela funo exp. Utilize a seguinte srie:
x

e = x + x /1! + x /2! + x /3! + x /4! + ...


15) Escreva um programa que encontre os N primeiros nmeros perfeitos, onde N um
valor lido do teclado. Um nmero perfeito aquele cuja soma de seus divisores, exceto
ele prprio, igual ao nmero. Ex.: 6 = 1 + 2 + 3.
16) Dado um nmero N lido do teclado, escreva um programa que imprima os primeiros N
nmeros primos.

21

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados


6. Vetores e Matrizes

Vetores e matrizes so conjuntos de variveis que so referenciados pelo mesmo nome, e


trabalham com o mesmo tipo de dados. Para ter o acesso a essas diferentes variveis
necessrio utilizar ndices. Esses ndices atuam como deslocamentos na memria a partir de
um endereo inicial. Vetores e matrizes em C utilizam uma parte contgua da memria, onde o
primeiro ndice corresponde ao endereo mais inferior e o ultimo ndice corresponde ao
endereo superior da memria.
6.1. Vetores
A forma geral para declarar um vetor em C a seguinte:
tipo_de_dado nome_da_variavel[tamanho];
Assim como as variveis, vetores tambm devem ser declarados. Esta declarao reserva um
espao na memria suficientemente grande para armazenar o nmero de clulas especificadas
por tamanho, onde est especificado quantos elementos o vetor poder guardar. No campo
tipo_de_dado ser escolhido um dos tipos de dados da linguagem C (inteiro, real, caracter). O
nome_da_variavel o identificador do vetor. Na linguagem C, a numerao dos ndices de um
vetor ou matriz inicia sempre em zero, ou seja, o primeiro elemento sempre ser referenciado
pelo ndice 0. Isto significa que, no exemplo abaixo, os dados sero indexados de 0 a 29.
Exemplo1:
int num[30];
valores
num[0]= 10;
num[1]= 2;
...
num[29]= num[1];

// declara vetor do tipo inteiro que poder armazenar at 30

// armazena 10 na primeira posio do vetor num


// armazena 2 na segunda posio do vetor num
// atribui contedo da segunda p/ ltima posio da varivel

num
Nada impede de escrever:
num[30];
num[103];
Em C no verificado se o ndice usado est dentro dos limites vlidos. Este um cuidado que
o programador deve tomar, caso contrrio h risco de haver variveis sobre-escritas ou de
escrever no prprio cdigo do programa.
/*preenchimento de um vetor de tamanho 10*/
Exemplo2:
#include<stdio.h>
int main() {
int vet[10],i;
printf(\n Digite um valor inteiro e pressione ENTER \n);
for(i=0;i<10;i++)
// ler 10 valores digitados no teclado
scanf(%d,&vet[i]);
}
/* l dado a dado e armazena na varivel com ndice i */
Vetores e matrizes podem ser passados como parmetros para funes, porm, no todo o
vetor que ser passado, mas sim um ponteiro para o primeiro elemento do vetor. Para isso
voc deve passar como parmetro apenas o nome do vetor, sem colocar o ndice e os
colchetes.
Exemplo3:
// chamando a funo soma e passando como parmetro o 1 elemento de nota
int nota[5];
soma(nota);

22

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados

A funo que est sendo chamada, que ir receber o ponteiro para o primeiro elemento do
vetor nota, deve estar preparada para isso. A varivel que vai receber este parmetro poder
ser declarada de trs formas distintas, conforme o exemplo a seguir:
// referente ao exemplo3, parte da funo que receber o parmetro
Exemplo4:
void soma(int aux[5])
{
//declarando um vetor de mesmo tamanho
...
}
ou
void soma(int aux[])
...
}

//declarando um vetor sem tamanho

ou
void soma(int *pt)
...
}

//declarando um ponteiro

6.2. Vetores Bidimensionais Matrizes


Em C podemos criar vetores multidimensionais, mas normalmente utilizado bidimensionais.
Por exemplo, para declararmos uma matriz de valores reais com 4 linhas e 3 colunas, fazemos:
float mat[4][3];
Esta declarao reserva um espao de memria necessrio para armazenar os 12 elementos (
4 x 3 ) da matriz, que so armazenados de maneira contgua, organizados linha a linha.
Os elementos da matriz so acessados com indexao dupla. No exemplo acima o primeiro
ndice 4, este significa que a matriz apresenta 4 linhas. O segundo ndice 3, este significa
que a matriz apresenta 3 colunas. Como em C a indexao comea em zero, o elemento da
primeira linha e primeira coluna ser acessado pelos ndices mat[0][0].
Para declarar uma matriz em C, utilizamos a seguinte forma geral:
tipo_da_variavel nome_da_variavel[linha][coluna];
As matrizes tambm podem ser inicializadas na declarao:
float mat[4][3] = {1,2,3,4,5,6,7,8,9,10,11,12};
Exemplo1:
/*exemplo de preenchimento de matriz 4x3*/
for(i=0; i<4; i++)
//controle das linhas da matriz
for(j=0; j<3; j++)
//controle das colunas da matriz
scanf(%f,&mat[i][j]);
//matriz recebe valor
No exemplo acima, a cada vez que for executado o primeiro comando for, ser executado
todas as vezes possveis o segundo lao for. Ser executado esse conjunto de laos at que a
condio do primeiro lao for seja falsa.
Exemplo2:
/* impresso do contedo de uma matriz 4x3 */
for(i=0; i<4; i++)
// controle das linhas da matriz
for(j=0; j<3; j++)
// controle das colunas da matriz
printf (mat[%d][%d] = %f\n,i,j,mat[i][j]);
Exerccios:
1) Preencher um vetor de 10 elementos, aps, copiar este vetor para outro, apresentado
os elementos deste segundo vetor.

23

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados

2) Preencher um vetor de 15 elementos, aps fazer o somatrio destes elementos e


apresentar a resposta.
3) Crie um programa que leia 5 valores de ponto flutuante e calcule a mdia destes. O
programa deve apresentar a mdia calculada, assim como o nmero de valores iguais
ou superiores mdia.
4) Preencher um vetor de 5 elementos e imprimir os elementos em ordem decrescente de
ndices.
5) Preencher 2 vetores de 5 elementos cada. Aps fazer a multiplicao entre os mesmos
elementos de cada vetor e armazenar a resposta em um terceiro, imprimindo os
resultados.
6) Faa um programa que leia um vetor de 10 nmeros inteiros e informe qual o maior e
qual o menor valor digitado.
7) Preencher um vetor de 5 elementos. Calcular o fatorial de cada elemento e armazenar
em um segundo vetor, apresentando o resultado somente no final.
8) Preencher um vetor de 6 elementos e ordena-los em ordem crescente, apresentando
os resultados.
9) Faa um programa que solicite a digitao de um vetor de 10 nmeros inteiros e em
seguida informe se h nmeros repetidos.
10) Ler uma matriz de 4 linhas por 6 colunas do teclado e fazer sua cpia para uma outra
matriz. Ao final, deve ser apresentado os elementos da segunda matriz.
11) Ler duas matrizes de 4 linhas por 3 colunas do teclado e armazenar sua soma em uma
terceira matriz. Ao final, deve ser apresentada a matriz soma.
12) Faa um programa que solicite a digitao de 3 notas de cada aluno de uma turma de
5 alunos. Em seguida, o programa deve imprimir a mdia de cada aluno.
13) Ler 20 valores para uma matriz e coloc-los em ordem crescente, apresentando seus
elementos.
14) Ler duas matrizes de 16 elementos inteiros cada e contar quantos elementos so
comuns as duas matrizes apresentando o resultado.
15) Preencha e imprima o contedo de uma matriz identidade de 4 linhas e 4 colunas.

24

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados


7. Cadeia de Caracteres

7.1. Caracteres
Os caracteres so representados por cdigos numricos. A correspondncia entre os
caracteres e seus cdigos numricos feita por uma tabela de cdigos. Em geral, usa-se a
tabela ASCII, mas diferentes mquinas podem usar diferentes cdigos.
Para a utilizao de funes especificas de caracteres, devemos incluir a seguinte biblioteca
padro, a qual possui o prottipo das funes de manipulao de caracteres:
#include<ctype.h>
Em C, a diferena entre caracteres e inteiros feita apenas atravs da maneira pela qual so
tratados. Por exemplo, podemos imprimir o mesmo valor de duas formas diferentes usando
formatos diferentes. Um constante caractere escrito envolvendo o caractere com aspas
simples. Assim, a expresso a representa um constante caractere e resulta no valor numrico
associado ao caractere a.
char c = a;
printf(%d %c\n, c, c);
Para capturarmos o valor de um caractere simples fornecido pelo usurio via teclado, usamos a
funo scanf, com o especificador de formato %c.
char a;
scanf(%c, &a);

Exemplo:
/* imprime todos os caracteres e valores da tabela ASCII */
#include<stdio.h>
int main() {
char tmp;
printf(\n\t *** Impresso da tabela ASCII ***\n\n);

25

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados

for(tmp=32;tmp<127;tmp++)
printf(Caractere: %c\t Valor: %d\n,tmp,tmp);
}
7.2. Cadeia de caracteres - Strings
Em C uma string de caracteres definida como um vetor ou uma matriz de caracteres. Esse
vetor deve terminar com o caractere \0 (tambm denominado de caracter nulo). Por essa
razo uma string deve conter uma posio a mais do que o nmero de caracteres que se
deseja. Portanto se desejamos guardar uma string de n caracteres, devemos definir um vetor
com tamanho n + 1.
Para a utilizao de funes especificas de strings, devemos incluir a seguinte biblioteca
padro, a qual possui o prottipo das funes de manipulao de strings:
#include<string.h>
A inicializao de cadeias de caracteres to comum em cdigos C que a linguagem permite
que elas sejam inicializadas escrevendo-se os caracteres entre aspas duplas. Sempre que for
utilizada uma constante string, o compilador automaticamente fornece o terminador nulo.
Formas de inicializar uma cadeia de caracteres:
(1)

char str[10]=um texto;

(2)

char str[10]={u,m, ,t,e,x,t,o,\0};

(3)

strcpy(str,um texto);

(4)

char str[4];
str[0] = O;
str[1] = l;
str[2] = a;
str[3] = \0;
printf(%s \n,str);

//precisa do caracter nulo

Para ilustrar a declarao e inicializao de cadeias de caracteres, consideremos as


declaraes abaixo:
7.3. Sada de dados com strings
O especificador de formato %s da funo printf() permite imprimir uma cadeia de caracteres. A
funo printf ento recebe um vetor de char e imprime elemento por elemento, at encontrar o
caractere nulo. Tambm se pode usar a funo puts para este fim:
puts(<var_string>);
Esta funo escreve o seu argumento no dispositivo padro de sada (vdeo), colocando um \n
(um salto de linha) no final.
7.4. Entrada de dados com strings
A funo scanf s l strings de uma palavra com o formato %s. No primeiro espao em
branco a funo encerrada. Para contornar este problema, podemos seguir dois caminhos:
Caminho 1: substituir o cdigo de controle %s por %[^\n] no campo da funo scanf(), esta
nova sintaxe faz com que seja lido qualquer caractere digitado diferente do nova linha \n,
quando este digitado a funo scanf() encerrada.
Caminho 2: utilizar a funo gets() para leitura de strings, sua forma geral :
gets(<var_string>);

26

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados

Esta funo utilizada para leitura de uma string atravs do dispositivo padro, at que a tecla
ENTER seja pressionada. A funo gets() no testa limites do vetor em que chamada.
/* funcionalidades do gets e puts */
Exemplo1:
main() {
char str[80];
printf(Entre com um string:\n);
gets(str);
printf(O string lido foi:\n);
puts(str);
printf(Entre com uma palavra:\n);
scanf(%s,str);
printf(A palavra lida foi: %s,str);
}
/* impresso caracter a caracter */
Exemplo2:
int i;
for(i=0;str[i]!=\0;i++)
printf(%c,str[i]);
printf(\n);
O exemplo acima tem a mesma funcionalidade da linha de comando abaixo:
printf(%s\n,s);
Exemplo3:
/*descobre o comprimento da cadeia de caracteres*/
int i;
int n=0;
/* contador */
for(i=0;s[i]!=\0;i++)
n++;
Para contar o nmero de caracteres da cadeia, basta contarmos o nmero de caracteres at
que o caractere nulo (que indica o fim da cadeia) seja encontrado. O caractere nulo em si no
deve ser contado.
/*copia uma cadeia de caracteres p/ um vetor de caracteres*/
Exemplo4:
int i;
for(i=0;orig[i]!=\0;i++)
dest[i]=orig[i];
dest[i]=\0;
/*fecha a cadeia copiada*/
Assumimos que a cadeia que receber a cpia tem espao suficiente para que a operao seja
realizada. Salientamos a necessidade de fechar a cadeia copiada aps a cpia dos
caracteres no nulos. Quando o lao for terminar, a varivel i ter o ndice de onde est
armazenado o caractere nulo na cadeia original. A cpia tambm deve conter o \0 nesta
posio.
Exemplo5:
/*concatenar um string no final de outra string*/
/*acha o final da cadeia destino*/
i=0;
//str1 recebe a segunda string
while(str1[i]!=\0)
i++;
/*copia elementos da segunda string para a str1*/
for(j=0;str2[j]!=\0;j++) {
str1[i]=str2[j];
i++;
}
str1[i]=\0;
/*fecha cadeia destino*/

27

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados

Concatenar colocar os caracteres de uma cadeia de caracteres no final de outra cadeia.


Assim, se uma cadeia representa inicialmente a cadeia Ola e concatenarmos a ela a cadeia
Turma, teremos como resultado a cadeia OlaTurma.
Funes anlogas s funes comprimento, copia, compara e concatena so disponibilizadas
pela biblioteca padro de C. As funes da biblioteca padro so, respectivamente, strlen,
strcpy, strcmp e strcat, que fazem parte da biblioteca de cadeias de caracteres (strings),
string.h. Existem diversas outras funes que manipulam cadeias de caracteres nessa
biblioteca.
7.5. Funes de Strings
A biblioteca string.h fornece algumas rotinas para a manipulao de strings em C. Existem
rotinas para copiar, concatenar e comparar strings, assim como muitas outras. A seguir sero
apresentadas as principais rotinas de manipulao de strings. Entretanto, importante
ressaltar que esta no uma lista completa das rotinas de manipulao de strings. Alm
destas funes, h outras que podem ser consultadas no manual de referncia da linguagem
C.
7.5.1. Funo strcpy
Serve para copiar o contedo de uma string para outro. Ela recebe o endereo de duas strings
e copia o contedo da segunda string (<fonte>) para dentro da primeira string (<destino>). O
contedo original da primeira string sobrescrito pelo contedo da segunda string. A segunda
string no sofre alteraes. A primeira string deve possuir espao livre suficiente para a cpia.
strcpy(<destino>,<fonte>);
7.5.2. Funo strlen
Serve para contar quantos caracteres existem numa string. Ela recebe o endereo de uma
string e retorna o tamanho desta. Esta funo no conta o caracter \0 do fim da string.
int strlen(<string>);
7.5.3. Funo strcat
Serve para concatenar o contedo de uma string no fim de outra string. Ela recebe o endereo
de duas strings e copia o contedo da segunda string (<fonte>) no fim da primeira string
(<destino>). A segunda string no sofre alteraes. A primeira string deve possuir espao livre
suficiente para a concatenao, j que vai possuir todos os caracteres dela assim como os
caracteres que estavam na segunda string.
strcat(<destino>,<fonte>);
7.5.4. Funo strcmp
Serve para comparar duas strings. Ela recebe o endereo de duas strings e compara o
contedo de uma string contra a outra. Esta funo ir retornar um valor numrico negativo,
zero ou positivo dependendo do resultado da comparao, de acordo com as seguintes regras:
Retorna um nmero negativo se o <string1> for menor que o <string2>
Retorna zero se o <string1> for igual ao <string2>
Retorna um nmero positivo se o <string1> for maior que o <string2>
int strcmp(<string1>,<string2>);
Observaes:
Letras maisculas so consideradas diferentes de minsculas;
O valor de retorno corresponde diferena em ASCII entre os primeiros dois
caracteres diferentes.

28

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados

7.5.5. Funo strstr


A funo strstr() devolve um ponteiro para a primeira ocorrncia da string (<palavra>) na string
(<string1>). Ela devolve um ponteiro nulo se no for encontrada nenhuma coincidncia em
string1.
char *strstr(<string1>,<palavra>);
Exemplo6:
//manipulao de strings
main() {
char str1[100],str2[100],str3[100];
//inicializa um string com uma constante
strcpy(str1,uma constante string);
//copia o contedo de um string para outro vetor
strcpy(str2,str1);
//concatena um texto ao fim de str1
strcat(str2,que foi concatenada com outra);
//inicializa o string str3
strcpy(str3,uma constante string);
//compara os tamanhos de strings
if(strlen(str1)==strlen(str3))
printf(str1 tem o mesmo tamanho de str3\n);
else
printf(str1 no tem o mesmo tamanho que str3\n);
//compara os strings str1 e str2
if(strcmp(str1,str2)==0)
printf(str1 e str2 sao iguais\n);
else if(strcmp(str1,str2)<0)
printf(str1 eh menor que str2\n)
else
printf(str1 eh maior que str2\n)
}
7.6. Funes de Caracteres
A biblioteca ctype.h fornece algumas rotinas para a manipulao de caracteres em C. Sero
apresentadas algumas rotinas para tratamento de caracteres.
Poderemos constatar que os argumentos para essas rotinas so compostos geralmente por
dados inteiros, as funes de caracteres convertem automaticamente o argumento em
unsigned char utilizando apenas o byte menos significativo, mas, nada impede que voc chame
essas funes com argumento do tipo caractere.
7.6.1. Funo isalnum (Letras e nmeros)
Responsvel pela verificao de um caractere, retornando um valor diferente de zero se o
caractere for alfanumrico, uma letra ou um digito. Se o caractere no for alfanumrico, a
funo devolver o valor zero.
int isalnum(char ch);
7.6.2. Funo isalpha (Letras)
Esta funo verifica se o caractere corresponde a uma letra do alfabeto, retornando um valor
diferente de zero se for uma letra minscula ou maiscula de A a Z. Caso contrrio, esta
funo retornar o valor zero.
int isalpha(char ch);

29

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados

7.6.3. Funo isdigit (Nmeros)


Esta funo verifica se o caractere corresponde a um digito de 0 a 9, retornando um valor
diferente de zero se for, caso contrrio, esta funo retornar o valor zero.
int isdigit(char ch);
7.6.4. Funo islower (Letras minsculas)
Esta funo verifica se o caractere corresponde a uma letra minscula, retornando um valor
diferente de zero se for, caso contrrio, esta funo retornar o valor zero.
int islower(char ch);
7.6.5. Funo isupper (Letras maisculas)
Esta funo verifica se o caractere corresponde a uma letra maiscula, retornando um valor
diferente de zero se for, caso contrrio, esta funo retornar o valor zero.
int isupper(char ch);
7.6.6. Funo isprint (Caracteres impressos)
Esta funo verifica se ch corresponde a um caractere que pode ser impresso, incluindo o
espao, retornando um valor diferente de zero se for, caso contrrio, esta funo retornar o
valor zero. Geralmente os caracteres que podem ser impressos esto na faixa de 0x20 a 0x7E.
int isprint(char ch);
7.6.7. Funo ispunct (Caracteres de pontuao)
Esta funo verifica se ch corresponde a um caractere de pontuao, retornando um valor
diferente de zero se for, caso contrrio, esta funo retornar o valor zero. Os caracteres de
pontuao, como definido pela funo, inclui todos os caracteres que podem ser impressos e
no sejam alfanumricos ou espao.
int ispunct(char ch);
7.6.8. Funo toupper
A funo toupper() devolve o equivalente maisculo de ch se a mesma for uma letra; caso
contrrio, devolvido ch sem alterao.
char toupper(char ch);
7.6.9. Funo tolower
A funo tolower() devolve o equivalente minsculo de ch se a mesma for uma letra; caso
contrrio, devolvido ch sem alterao.
char tolower(char ch);
Exerccios:
1) Escreva um programa que receba uma string e imprima a mesma (resolver de duas
formas, com printf() e scanf(), com puts() e gets()).
2) Escreva um programa que receba uma string e descubra quantos caracteres foram
armazenados, apresentando o resultado (sem a utilizao da funo strlen()).

30

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados

3) Escreva um programa que receba uma string e faa uma cpia dela em outro vetor
de caracteres, apresentando o contedo dos dois vetores (sem a utilizao da
funo strcpy()).
4) Escreva um programa que receba duas strings e concatene a segunda na primeira
string, apresentando a string concatenada no final (sem a utilizao da funo
strcat()).
5) Escreva um programa que receba duas strings e compare elas, descobrindo se elas
SO ou NO SO iguais (sem a utilizao da funo strcmp()).
6) Escreva um programa que receba uma string e descubra quantos caracteres
(espao) foram digitados, apresentando o resultado no final.
7) Escreva um programa que receba uma string e descubra quantas vogais foram
digitadas, apresentando o resultado no final.
8) Escreva um programa que receba uma string e substitua todos os caracteres
(espao) pelo caractere \n (nova linha), apresentando a string modificada.
9) Escreva um programa que simule um bloco de notas (limite de 10000 caracteres), o
programa s deve ser encerrado quando for digitado os caracteres :, q, \n
respectivamente.
10) Escreva um programa que receba uma string e substitua todas as vogais minsculas
por vogais maisculas, apresentando a string modificada no final.
11) Escreva um programa que receba o nome de 5 pessoas e imprima os mesmos em
ordem alfabtica.
12) Escreva um programa que leia uma string de no mximo 100 caracteres e copie as
consoantes para um vetor e as vogais para outro vetor. Ao final deve ser impresso a
string original, aps o vetor com as consoantes e por final o vetor com as vogais.
13) Escreva um programa que receba uma string de no mximo 500 caracteres. Aps o
usurio ir digitar uma palavra. O programa deve descobrir quantas vezes esta
palavra ocorre na string digitada.
14) Crie um programa que efetue a leitura dos nomes de 10 alunos e tambm de 2 notas
de cada aluno. O programa deve calcular a mdia de cada aluno para ver se ele est
Aprovado ou Reprovado, utilize mdia igual ou maior a 7. Ao final, o programa
dever apresentar somente o nome dos alunos aprovados e sua respectiva nota
final.

31

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados


8. Funes

Uma funo um miniprograma dentro de outro. A utilizao de funes caracterstica de


uma programao estruturada, pois de qualquer lugar do cdigo fonte pode ser feita a
chamada de funo.
8.1. Declarao de Funes
Em C, cada funo contm um bloco de comandos que executado separadamente s outras
funes. As variveis declaradas dentro de uma funo no so vistas por outras funes.
Uma funo jamais dever estar contida no bloco de comandos de outra funo, apenas a
chamada a ela deve estar ali. Como exemplo, podemos citar a funo main(), ela sempre ser
a primeira funo a ser executada no cdigo, pois a funo principal. A forma geral de
utilizao de funes :
tipo_de_dado nome_da_funo(lista_de_parametros)
corpo da funo ou bloco de comandos;
}

O campo tipo_de_dado especifica o tipo de dado que ser retornado pela funo, atravs do
comando return. Se o tipo de dado for void, significa que a funo no retornar nenhum valor.
Se no for especificado nenhum tipo de dado de retorno, o compilador assumir que ser
retornado dado do tipo inteiro. O campo nome_da_funcao segue as mesmas regras para
identificadores de variveis. A lista_de_parmetros conter declarao de variveis separadas
por vrgula, essas variveis sero utilizadas para receber os argumentos passados no
momento que feito a chamada de funo. Uma funo que no for receber nenhum
parmetro, no precisar ter variveis na lista_de_parametros, mas obrigatoriamente dever
aparecer o abre e fecha parnteses (). No caso de declarar variveis na lista_de_parmetros
devemos tomar uma ateno especial, pois qualquer varivel dever ser precedida pelo seu
tipo, conforme o exemplo a seguir:
Exemplo:
void funcao(int a, int b, int c, float aux, char letra)
()
}

Exemplo 1:
/*Primeiramente executada a funo main(), a qual faz uma chamada a
funo imprime(), ento a execuo do programa passa para a funo imprime(), que mostra
no terminal a mensagem e volta para a funo principal, que encerra o programa */
#include<stdio.h>
void imprime()
{
//declarando a funo imprime
printf("Sou a funcao e estou viva!\n");
}
//fechando funo imprime
main()
imprime();
}

{
//chama a funo imprime

8.2. Prottipo de Funes


Tambm conhecido como cabealho de funo, seu objetivo listar as funes que existem no
cdigo fonte, possui o seguinte formato:
tipo_de_dado nome_da_funo(lista_de_parametros);
Podemos observar que praticamente igual a declarao da funo, exceto pelo corpo da
funo que neste caso NO deve aparecer. Este prottipo de funo deve ser encerrado com o
caractere ponto e vrgula ; aps a lista_de_parmetros.

32

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens


Exemplo:
void imprime();

de Programao I e Estruturas de Dados

//prottipo da funo acima

8.3. Variveis Locais e Globais


As variveis locais so declaradas dentro de uma funo (ou na lista_de_parmetros da
funo), somente esta funo tem acesso direto a elas, as variveis locais deixam de existir
quando a funo finaliza sua execuo. As variveis locais devem ser declaradas sempre que
inicia-se um bloco de comandos, antes de qualquer instruo do programa.
As variveis globais normalmente so definidas no inicio do cdigo fonte, devendo estar fora
de qualquer funo. Podem ser acessadas diretamente por qualquer funo subseqente,
existem permanentemente e guardam seus valores enquanto o programa existir.
8.4. Argumentos de funes
Se for necessrio passar argumentos a uma funo, ela dever conter variveis declaradas
para receber estes argumentos. Essas variveis possuem as mesmas caractersticas de
variveis locais, e devem ser declaradas logo aps o nome da funo e entre parnteses, no
caso de declarar variveis na lista_de_parmetros devemos tomar uma ateno especial, pois
qualquer varivel dever ser precedida pelo tipo de dado que ser manipulado por ela.
A passsagem de parmetros para uma funo se d de duas formas:

passagem por valor, onde passado o contedo de uma varivel de uma funo para
outra, isto , o valor original da varivel no alterado, pois passado apenas uma
cpia da varivel;
e passagem por referncia, onde passado o endereo de uma varivel, isto ,
qualquer alterao no contedo desta varivel ser realmente modificado, pois
estamos manipulando diretamente o endereo da varivel atravs de um ponteiro.

Quando um vetor ou uma matriz passada como argumento para uma funo, apenas um
ponteiro para o endereo inicial da matriz passado, e no todo seu contedo.
8.5. Comando return
Utilizado para devolver um valor para o programa (ou funo) que o chamou. Tambm utilizada
para sair imediatamente de uma funo. Uma funo ser finalizada quando for encontrado o
comando return ou quando for encontrado o fecha chaves da funo }.
Exemplos:
return 10;
return aux;

//retorna valor 10 para funo que fez a chamada


//retorna contedo de aux para funo que fez a chamada

Exerccios:
1) Escreva um programa que imprima 100 vezes a mensagem Ola, estou vivo!, utilize
uma funo (exemplo, imprime()) para imprimir a mensagem.
2) Escreva um programa que faa a soma de 3 valores inteiros e imprima o resultado, isto
deve ser feito em uma funo (exemplo, soma(int n1, int n2, int n3)).
3) Referente ao exerccio 2, faa a leitura dos 3 valores inteiros e o somatrio em outra
funo (exemplo, soma()), mas o resultado deve ser impresso na funo main().
4) Ainda referente ao exerccio 2, faa a leitura dos 3 valores inteiros na funo main(), a
soma em outra funo e o resultado deve ser impresso na funo principal.
5) Escrever um programa que utilize a funo somaintervalo (int n1, int n2) que retorna a
soma dos nmeros inteiros que existem entre n1 e n2 (inclusive ambos). A funo deve
funcionar inclusive se o valor de n2 for menor que n1.

33

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados

n = somaintervalo(3, 6);
n = somaintervalo(5,5);
n = somaintervalo(4, 0);

/* n recebe 18 (3 + 4 + 5 + 6) */
/* n recebe 10 (5 + 5) */
/* n recebe 10 (4 + 3 + 2 + 1 + 0) */

6) Escrever um programa que utilize a funo ampm(int hora, int minutos) que exibe a
hora passada por parmetro no formato americano, isto , ao meio-dia, as horas
voltam a serem contadas a partir de 00:00, seguida de AM, se for antes de meio-dia, ou
PM, se for meio-dia ou depois.
ampm(1,30);
/* 01:30 AM */
ampm(12,5);
/* 00:05 PM */
ampm(17,00);
/* 05:00 PM */
7) Fazer um programa em C, que ordena 5 nmeros :
a) Em ordem crescente, utilizando a funo crescente().
b) Em ordem decrescente, utilizando a funo decrescente().
8) Escrever uma funo somavet(int *vetor, int tamanho), que recebe por parmetro o
endereo (ponteiro) de um vetor de inteiros e o seu tamanho e retorna a soma de seus
elementos.
9) Escrever uma funo espaco(), que retorna o nmero de espaos em branco contidos
em uma string passada como parmetro, mximo de 60 caracteres.
10) Implementar uma calculadora padro utilizando funes. Primeiramente o programa
recebe a operao desejada:
+
soma
subtrao
*
multiplicao
/
diviso
e, logo aps, chama a funo correspondente a operao escolhida, o qual calcula e
retorna o resultado para a funo principal.

34

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados


9. Ponteiros (apontadores)

Ponteiros so como uma varivel qualquer, ou seja, possuem um nome e guardam um valor
dentro deles, porm seus valores tm um significado diferente do que foi visto anteriormente.
Estas variveis apontadoras armazenam um endereo, sendo que este endereo aponta para
uma outra posio da memria, onde estar armazenado o dado que ser manipulado.
9.1. Declarao de Ponteiros
Para declarar variveis ponteiros o programador deve colocar o * (asterisco) antes do nome
da varivel, conforme a seguir:
tipo_de_valor_apontado *nome;
Onde tipo_de_valor_apontado qualquer tipo de dado vlido em C e define que tipo de dado a
varivel ponteiro ir apontar e o nome o identificador da varivel.
Exemplo:
int *px;
float *py;
char *pstr;

//apontador para inteiros


//apontador para ponto flutuante
//apontador para caracter ou string

Um ponteiro referencia um endereo de memria e ao mesmo tempo seu contedo. As


principais funes de ponteiros consistem em referenciar rapidamente elementos de uma
matriz, permitem modificar seus valores entre funes e suportam estruturas dinmicas de
dados.
9.2. Operadores de Ponteiros & e *
Normalmente a inicializao de um apontador deve-se a atribuio de um endereo de
memria (uma referncia). O operador unrio & devolve o endereo de memria de
determinada varivel (unrio porque necessita de apenas um operando).
Exemplo:
int i;
float soma;
char sexo;
/* inicializando ponteiros na declarao */
int *px = &i;;
//px aponta para endereo da varivel i
float *py =&soma;
//py aponta para endereo da varivel soma
/* declarando ponteiros, e somente depois inicializando */
char *pstr;
//declarao de apontador para caracter ou string
pstr = &sexo;
//pstr aponta para endereo da varivel sexo
O segundo operador unrio *, referencia o contedo da varivel localizada no endereo
apontado pelo apontador, como se trabalhasse-mos com uma varivel normal. Para o
exemplo a seguir, considere que a varivel i esta localizada no endereo 65000 e possui o
valor 7.
Exemplo:
px = &i;
num = *px;
*px = 9;

// px recebe o endereo da varivel i (65000)


// num recebe o valor apontado pelo endereo de px (7)
// endereo 65000 recebe o valor 9

Tambm podemos modificar a memria apenas manipulando ponteiros. Ao incrementar ou


decrementar um ponteiro, ele passa a apontar para a prxima posio de memria, onde est
o prximo dado de determinado tipo.

35

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados

Exemplo:
/* preenchimento da string str com oi utilizando ponteiros */
ps = str;
//ponteiro recebe endereo inicial da string
*ps = o;
// letra o ser o primeiro elemento da string
ps++;
//ponteiro aponta para prxima posio da memria
*ps = i;
//atribui caracter i ao endereo apontado por ps
ps++;
//ponteiro aponta para prxima posio da memria
*ps = \0;
//caracter nulo ser o terceiro elemento da string
9.3. Ponteiros para Vetores
Voc pode criar um ponteiro para um vetor ou matriz apenas atribuindo ao ponteiro o nome da
varivel sem o ndice e os colchetes, assim ser armazenado no apontador o endereo inicial
do vetor, pois o nome de uma matriz sem o ndice e os colchetes um ponteiro para o primeiro
elemento da matriz.
A seguir dado o cdigo fonte de um programa que trabalha com ponteiro para manipular um
vetor de inteiros. Copie o cdigo fonte, compile e execute para analisar as sadas deste
programa.
/* manipulao com ponteiros */
Exemplo1:
#include<stdio.h>
main()
{
int vet[5], *pt, i;
for(i=0;i<5;i++)
vet[i] = i+10;
pt = &vet[0];
printf("Endereco em pt = %d\n",pt);
printf("Conteudo em pt = %d\n",*pt);
pt = vet;
// igual ao que foi feito acima
printf("Endereco em pt = %d\n",pt);
printf("Conteudo em pt = %d\n",*pt);
for(i=0;i<5;i++)
{
printf("Endereco em pt[%d] = %d\n",i,&(pt[i]));
printf("Conteudo em pt[%d] = %d\n",i,pt[i]);
}
*(pt+4) = 4;
printf("Endereco em pt[4] = %d\n",&(pt[4]));
printf("Conteudo em pt[4] = %d\n",pt[4]);
}
Neste exemplo, possvel perceber que aplicando indexao em um ponteiro, como se
estivssemos manipulando diretamente um vetor de dados, ou seja, qualquer ponteiro em C
pode ser indexado como um vetor, usando os colchetes [ ].
9.4. Vetores de Ponteiros
Assim como variveis, tambm podem ser declarados vetores de ponteiros. Se em algum
momento for necessrio passar o vetor de ponteiros como parmetro para uma funo, faz-se
o mesmo processo que com vetores e matrizes, simplesmente coloca-se o nome sem nenhum
ndice.
int *pt[10];

// declara um vetor de ponteiros para inteiros

Um ponteiro assim que declarado, no aponta para um local de memria vlido, ento por
conveno, a maioria dos programadores atribui a ele o valor nulo (zero). Assim, qualquer
ponteiro que tiver o valor nulo, significar que ele no aponta para nada.

36

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados

9.5. Cuidados com Ponteiros


Entre os erros mais difceis de serem encontrados em C, est na utilizao incorreta dos
ponteiros. Analise o exemplo a seguir:
Exemplo1:
/* programa incorreto */
main()
{
int x=10, *pt;
*pt=x;
// endereo apontado por pt recebe 10
}
A pergunta : mas qual endereo recebe o valor 10?. Estamos colocando um valor em
alguma posio da memria, sendo que no temos nem certeza se est posio ou no
vlida, o ponteiro pt no foi inicializado, ou seja, ele possui lixo. Portanto, sempre antes de
comear a utilizar um ponteiro procure inicializ-lo, de forma que garanta que este ponteiro
nunca ir sobrescrever o prprio cdigo do programa, ou a rea de dados ou o sistema
operacional.
A utilizao de ponteiros em C deve-se a dois itens:

Primeiramente em sua utilizao como argumento de funes;


A segunda razo consiste em podermos alocar memria dinamicamente, ou seja,
criarmos variveis em tempo de execuo.

9.6. Ponteiros como passagem de parmetros


Quando for necessrio passar como parmetro o endereo para uma funo ou um apontador
para uma varivel, fazemos o uso de ponteiros.
Ento, para passarmos um parmetro por referncia, no momento da chamada a funo
devemos usar o operador & na frente da varivel para se obter o apontador da varivel a qual
se quer usar. Alm disso, devemos declarar uma varivel apontadora na lista_de_parmetros
da funo que esta sendo chamada.
//passando endereo das variveis a e b para a funo
Exemplo1:
void troca(int *pa, int *pb);
(...)
main() {
int a, b;
troca(&a,&b);
Exemplo2:
//convertendo um ponteiro para acesso bidimensional
void tabela(int nota[5][3]);
(...)
main() {
int *pt;
(...)
tabela(pt);
9.7. Funes de Alocao Dinmica em C
A alocao dinmica uma forma de reservar espao em memria enquanto o programa est
em execuo. Muitas vezes nos deparamos com programas usando variveis de tamanho ou
muito grande ou muito pequeno, pois no sabemos qual a real necessidade do usurio,
causando alto desperdcio de memria ou sua prpria carncia, o que no acontece quando
trabalhamos com alocao dinmica. Com as funes de alocao dinmica, essas variveis
vo sendo dimensionadas de acordo com a necessidade do usurio.
H basicamente trs formas de alocarmos espao em memria, a primeira com o uso de
variveis globais (estticas), essas variveis existem enquanto o programa estiver em

37

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados

execuo e qualquer funo tem acesso a elas. A segunda forma atravs de variveis locais
(estticas), essas existem enquanto a funo que a criou estiver sendo executada e, somente
esta funo tem acesso a ela. A terceira maneira de requisitar memria ao sistema , utilizando
alocao dinmica, a qual feita em tempo de execuo, este espao permanece reservado
at que seja liberado explicitamente, sendo desta forma acessvel por qualquer funo do
programa. Se o espao reservado no for liberado explicitamente, ao final da execuo do
programa ele ser liberado automaticamente.
As principais funes de alocao dinmica de C so malloc() e free(). A funo malloc() aloca
memria e free() a libera. Para utilizar essas funes de alocao dinmica, devemos inserir a
biblioteca stdlib.h.
#include<stdlib.h>
A forma geral da funo malloc :
void* malloc(numero_de_bytes*sizeof(tipo_de_dado));
A funo malloc recebe como parmetro o nmero de bytes que se deseja alocar e retorna um
ponteiro para o endereo inicial do espao reservado em memria. A funo malloc retorna um
ponteiro genrico, de acordo com o tipo de dado requisitado, por isso void*, na atribuio, este
tipo convertido automaticamente pela linguagem. O campo numero_de_bytes representa a
quantidade de bytes que queremos reservar na memria e o campo sizeof(tipo_de_dado)
retorna a quantidade de bytes utilizada por determinado tipo de dado, ficando independente do
compilador e da arquitetura da mquina, alocando desta forma o espao correto e garantindo
portabilidade de cdigo.
Exemplo:
char *pt;
pt = malloc(1000);
//aloca 1000 bytes na memria e retorna um apontador para o 1 byte
int *pt;
pt = malloc(25*sizeof(int));
//aloca espao p/ 25 inteiros, 100 bytes, 4 para cada inteiro
Visto que a linguagem faz a converso automaticamente do tipo de ponteiro a ser retornado,
comum encontrarmos um operador cast fazendo esta converso explicitamente, conforme
apresentado no exemplo a seguir:
pt =(int *) malloc(25*sizeof(int));
Aps a alocao dinmica, devemos testar o valor retornado pela funo malloc, se houver
falha na alocao, ser retornado o valor NULL, caso contrrio retornado o ponteiro para a
primeira posio da memria reservada. Isto necessrio para no usarmos ponteiros nulos, o
que provavelmente provocaria um travamento na mquina.
A funo free o oposto da malloc, ela desaloca espao reservado da memria, devolvendo
aquele espao ao sistema para posteriores requisies de memria novamente.
A forma geral da funo free :
void free(void *pt);
Esta funo recebe como parmetro o ponteiro para o espao reservado em memria e libera
este espao.
Exemplo:
free(pt);
Podemos alocar memria dinamicamente e manipular os dados como se fossem um vetor, pois
qualquer ponteiro pode ser indexado como se fosse um vetor unidimensional.

38

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados

Exerccios:
1) Escreva um programa que leia um nmero digitado do teclado. Aps isto, um ponteiro
deve apontar para esta varivel que guardou o valor e imprimi-lo na tela, atravs do
ponteiro.
2) Escreva um programa que leia dois valores inteiros. Aps, com a utilizao de 2
ponteiros, deve ser trocado os valores dessas 2 variveis e impresso na tela.
3) Crie um vetor de 5 elementos reais e preencha-o com a utilizao de ponteiros. Ao
final, imprima os valores digitados novamente com a utilizao de ponteiros.
4) Preencha um vetor de 7 elementos reais. Aps o programa deve chamar uma funo
passando como parmetro o endereo inicial do vetor. Na funo chamada deve ter um
ponteiro para receber este endereo inicial, aps deve ser alterado cada valor do vetor
pelo seu quadrado. Voltando a funo main(), imprima os elementos do vetor.
5) Escreva um programa que faa a leitura de duas strings de no mximo 100 caracteres.
Aps deve ser chamada uma funo que concatene o contedo da segunda string na
primeira string (utilize concatena(char *s1, char *s2)). Ao final deve ser impressa a
string concatena na funo main().

39

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados


10. Estruturas (structs)

Uma estrutura uma coleo de variveis de tipos de dados distintos, referenciados por um
mesmo nome. As variveis contidas em uma estrutura so denominadas de campos da
estrutura. As variveis dentro da struct ocupam endereos contguos da memria.
10.1. Declarao de Estruturas
Quando criamos uma estrutura ela fica como se fosse um esqueleto, um molde, para ser
utilizada futuramente. As estruturas so declaradas entre as bibliotecas e as funes do cdigo
fonte. Sua forma geral :
struct nome_da_estrutura
{
tipo_de_dado nome_da_varivel;
tipo_de_dado nome_da_varivel;
(...)
};
Onde struct a palavra chave para definir um dado do tipo estrutura, acompanhado do
nome_da_estrutura, o qual caracteriza a struct. Entre as chaves encontramos os campos, que
consistem nos tipos de dados e nomes de variveis. Como estamos definindo um molde, esta
estrutura deve ser finalizada pelo caractere ';'.
/* declarando um molde de estrutura */
Exemplo:
struct cliente
{
char nome[50];
int idade;
char sexo;
};
Neste exemplo, declaramos um formato de estrutura com os seguintes campos: um vetor de
caracteres para armazenar o nome do cliente, uma varivel inteira para armazenar a idade e
uma varivel caractere para armazenar o sexo (M ou F) do cliente. Repare que apenas
definimos um molde, mas ainda no existe nenhuma varivel utilizando essa estrutura. Para
declarar uma varivel que utilize esse molde, devemos fazer o seguinte, por exemplo:
struct cliente c1,c2;
As variveis c1 e c2 iro utilizar o molde da estrutura cliente. Agora podemos utilizar os
campos nome, idade e sexo da estrutura atravs de c1 e c2. Tambm possvel declarar as
variveis no momento que definimos o molde da estrutura, conforme mostrado a seguir:
/* declarando um molde e variveis da estrutura */
Exemplo:
struct cliente
{
char nome[50];
int idade;
char sexo;
} c1,c2;
10.2. Operadores Ponto (.) e Seta (->)
Estes operadores referenciam elementos de estruturas, nos quais so tipos de dados
compostos referenciados por um nome. O operador . (ponto) deve ser utilizado quando
quisermos ler ou modificar algum campo da estrutura. Sua forma geral :
nome_da_varivel.nome_do_campo

40

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados

O operador -> (seta p/ direita) utilizado quando trabalhamos com apontadores para
estruturas, para declarar um apontador para estrutura fazemos o seguinte:
struct nome_da_estrutura *nome_do_apontador;
Assim como apontadores para variveis simples, ponteiros para estruturas devem ser
precedidos do operador *, para referenciar o dado apontado pelo apontador, ou, podemos
abrir mo do operador * para utilizar o operador ->, o qual deixa o cdigo mais legvel.
Devemos tomar cuidado para no utilizar o apontador para a estrutura sem antes inicializ-lo.
/*cadastro de 2 clientes */
Exemplo:
#include<stdio.h>
struct cliente
{
char nome[50];
int idade;
char sexo;
};
main()

{
struct cliente c1,c2;
struct cliente *pc2 = &c2;

// inicializando o apontador para a

estrutura
// inicializando a variavel c1 do tipo
struct
strcpy(c1.nome,"Joao");
c1.idade = 21;
c1.sexo = 'M';
// inicializando a varivel c2 por referncia (apontador)
strcpy(pc2->nome,"Maria");
pc2->idade = 18;
pc2->sexo = 'F';
// imprimindo o contedo
printf("Cliente 1:\n");
printf("\tNome: %s\n",c1.nome);
printf("\tIdade: %d\n",c1.idade);
printf("\tSexo: %c\n",c1.sexo);
printf("\n\nCliente 2:\n");
printf("\tNome: %s\n",pc2->nome);
printf("\tIdade: %d\n",pc2->idade);
printf("\tSexo: %c\n",pc2->sexo);
}
Exerccios:
1) Crie um programa que cadastre dois funcionrios. As informaes que cada funcionrio
deve possuir so: cdigo, nome, idade, profisso, sexo (M ou F) e telefone. Ao final
deve ser impresso os dados dos dois funcionrios.
2) Faa o mesmo que pedido no exerccio 1, mas agora somente com a utilizao de
apontadores para a estrutura.
3) Crie um programa que cadastre 10 produtos de um mercado. Onde cada produto
possui um cdigo seqencial, nome de identificao, quantidade em estoque e valor. O
programa deve permitir as seguintes operaes:
Apagar um produto, atravs do cdigo do produto;
Listar os produtos cadastrados, mostrando o cdigo e o nome do produto;
Alterar o estoque dos produtos;

41

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados

Alterar o valor dos produtos.


Antes de um produto ser apagado, o programa deve imprimir o nome do produto e
aguardar uma confirmao do usurio para deletar o mesmo.

42

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados


11. Arquivos

Neste captulo ser apresentado outra forma de entrada e sada de dados, arquivos em disco.
Veremos, tambm, alguns conceitos bsicos e detalhes para a manipulao de arquivos,
podendo ler, escrever, apagar, criar e salvar arquivos em disco. Assim como entrada e sada
de dados pode ser via teclado e vdeo, podemos manipular arquivos para os mesmos fins.
Um arquivo em disco representa um elemento de informao do dispositivo secundrio de
memria. Os arquivos acessados na memria secundria so carregados para a memria
principal, onde ficam armazenados em um buffer, este buffer uma rea de transferncia entre
o disco e a memria, o qual mantm parte ou todo o arquivo para acessos posteriores. Cada
arquivo identificado por seu nome e pelo diretrio onde encontra-se armazenado. Geralmente
os nomes dos arquivos so compostos por um nome e uma extenso, esta extenso pode ser
usada para identificar a natureza da informao armazenada no arquivo ou para identificar o
programa que gerou o arquivo.
Os arquivos podem ser tratados de duas maneiras pelos sistemas operacionais: em modo
texto, onde o arquivo composto de uma seqncia de caracteres, ou em modo binrio,
onde o arquivo composto por uma seqncia de bytes.
A linguagem C disponibiliza um conjunto de funes para manipular arquivos, os principais
servios de manipulao so:

Abertura de arquivo: passado o nome e o caminho, o sistema operacional encontra o


arquivo e prepara o buffer na memria.
Leitura do arquivo: o sistema operacional obtm o contedo do arquivo solicitado. Uma
parte ou toda a informao solicitada pode vir do buffer.
Escrita no arquivo: aps aberto o arquivo, o sistema operacional acrescenta ou altera o
contedo dele. A alterao no contedo do arquivo feita inicialmente no buffer para
depois ser transferida para o disco.
Fechamento de arquivo: a informao contida no buffer transferida para o disco e a
rea utilizada na memria pelo buffer liberada.

Para o tratamento destes arquivos necessrio que o sistema operacional mantenha um


ponteiro de arquivo (file pointer), o qual ir conter o endereo inicial para o arquivo. Para o
processo de leitura de arquivo, este apontador percorre o arquivo do incio at o fim, conforme
os dados vo sendo lidos para a memria. Para o processo de escrita em um arquivo,
normalmente os dados so acrescentados quando o apontador se encontra no fim do arquivo.
11.1. Funes para abrir e fechar arquivos
Todas as funes de C que manipulam arquivos encontram-se na biblioteca padro de entrada
e sada, stdio.h.
Visto que para a abertura de um arquivo necessrio ter um ponteiro de arquivo, o primeiro
passo para a manipulao de arquivos a declarao de um ponteiro, conforme apresentado
a seguir:
FILE* nome_do_ponteiro;
Exemplo:
FILE* fp;
Agora sim podemos abrir um arquivo usando a funo fopen, sua forma geral :
FILE* fopen(nome_do_arquivo,modo);
A funo fopen(), responsvel pela abertura do arquivo, tem como valor de retorno um ponteiro
para o tipo FILE, onde todas as operaes subseqentes devero utilizar o ponteiro. Se ocorrer
algum erro na abertura do arquivo, a funo retornar o valor NULL. Geralmente quando

43

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados

abrimos um arquivo, testamos se o arquivo foi aberto com sucesso antes de continuar a
execuo do programa. O campo nome_do_arquivo uma cadeia de caracteres, a qual ser
passada o nome do arquivo a ser aberto, podendo ser relativo ou absoluto:

Nome do arquivo relativo: contm apenas o nome do arquivo, sem o caminho de


diretrios para chegar at ele, o sistema ir procurar o arquivo a partir do diretrio
corrente, no diretrio que possui o cdigo objeto executado.; ou
Nome do arquivo absoluto: contm o nome do arquivo, incluindo os diretrios, desde o
diretrio raiz, exemplo: /home/aluno/Desktop/meu_arquivo.txt.

O campo modo tambm uma cadeia de caracteres, onde especificado de qual forma
queremos tratar o arquivo. Existem diferentes modos de manipulao de arquivos, podemos
abrir um arquivo para leitura ou para escrita, o arquivo pode ser aberto em modo texto ou em
modo binrio. Os caracteres interpretados no modo so:
Modo
r
w
a
t
b
r+
w+
a+

read-only
write
append
text
binary

Significado
Abre arquivo para leitura, o arquivo no pode ser alterado.
Abre arquivo para escrita, o arquivo no pode ser lido.
Abre arquivo para escrita ao final do contedo original.
Abre arquivo em modo texto, tratado caracter a caracter.
Abre arquivo em modo binrio, arquivo tratado byte a byte.
Abre arquivo texto para leitura/escrita.
Cria arquivo texto para leitura/escrita.
Abre arquivo texto para leitura/escrita ao final.

Em casos de abertura de um arquivo em modo de escrita, modo w, se o arquivo j existe, ele


apagado e criado um novo arquivo com mesmo nome, mas vazio. Quando for solicitada a
abertura em modo a, o contedo do arquivo preservado e os dados so adicionados ao
final do contedo. Com ambos os modos, se o arquivo no existe, um novo criado. Os modos
b e t podem ser combinados com os demais.
Todos arquivos que forem abertos, devem ser fechados antes do fim da execuo do
programa. A funo utilizada para fechar um arquivo fclose, que recebe como parmetro o
ponteiro do arquivo que se deseja fechar. O prottipo da funo :
int fclose(FILE* nome_do_ponteiro);
Esta funo retorna um valor inteiro, retornando zero se o arquivo for fechado com sucesso, ou
retornando a constante EOF (definida pela biblioteca) em caso de erro.
Exemplo:
fp = fopen(teste.txt,rt);
//abre o arquivo em modo leitura e
texto
if(fp == NULL)
{
//testa se houve erro na abertura do
arquivo
printf(Erro na abertura do arquivo\n);
exit(1);
//aborta o programa
}
fclose(fp);
//fecha o arquivo apontado por fp
11.2. Arquivos em modo texto
Veremos as principais funes para manipular arquivos em modo texto:

Leitura de dados: fscanf(), fgetc() e fgets();


Escrita de dados: fprintf(), fputc() e fputs()..

Algumas vezes, aps uma leitura ou escrita tanto de arquivos quanto do teclado/vdeo, ser
necessrio limpar o buffer para que no haja falha nas operaes subseqentes de leitura ou
escrita. A linguagem C trabalha basicamente com 3 streams (arquivos), o stdin que o arquivo

44

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados

padro de entrada de dados via teclado e o stdout e stderr que so os arquivos padres de
sada de dados no vdeo, esses buffers de dados eventualmente precisam ser esvaziados
tambm. Para esses procedimentos temos as seguintes funes:

__fpurge(parmetro): esta funo esvazia o arquivo passado como parmetro, esta


funo deve ser utilizada somente no linux;
fflush(parmetro): tambm responsvel pelo esvaziamento do arquivo passado como
parmetro, deve ser utilizada somente no Devc++.

Exemplo:
fflush(fp);
__fpurge(stdin);

//esvazia arquivo apontado por fp


//esvazia buffer de entrada de dados

11.2.1. Funes para leitura de dados em arquivos


Assim como utilizamos a funo scanf() para leitura de dados da entrada padro, o teclado,
para leitura de dados em arquivos em modo texto, geralmente utilizada a funo fscanf,
responsvel pela captura de dados de um arquivo previamente aberto para leitura. A cada
leitura o ponteiro varre todo o arquivo e os dados correspondentes so transferidos para a
memria. O prottipo da funo fscanf :
fscanf(FILE* nome_do_ponteiro,formato,nome_da_varivel);
O primeiro campo da funo deve ser o ponteiro para o arquivo que queremos efetuar a leitura.
O campo formato corresponde a maneira a qual queremos fazer a leitura (%d, %f, %c, %s),
geralmente utilizamos %s para ler o contedo do arquivo, porm, este l somente uma palavra.
O ltimo campo corresponde a varivel que ir receber o contedo lido do arquivo. A funo
fscanf() possui como valor de retorno o numero de dados lidos com sucesso.
Exemplo:
fscanf(fp,"%s",str);
printf(%s,str);

//l contedo do arquivo e armazena em str


//imprime contedo lido do arquivo

Exemplo1:

/* Abertura do seguinte arquivo em modo leitura */


Escola
3
1.99
Solon
50
2.99
Tavares
35
3.99
#include<stdio.h>
main()
{
int idade;
float preco;
char nome[101];
FILE *fp;
if((fp = fopen("leitura","r")) == NULL)
{
printf("Falha na abertura do arquivo\n");
exit(1);
}
while((fscanf(fp,"%s %d %f",nome,&idade,&preco)) != EOF)
printf("Nome:%s\nIdade:%d\nPreco:%f\n",nome,idade,preco);
printf("Leitura finalizada\n");
fclose(fp);
}
Outra funo de leitura em modo texto bastante utilizada a funo fgetc, atravs do ponteiro
ela captura o prximo caractere do arquivo e, o ponteiro passa a apontar para o prximo dado
do arquivo. Esta funo retorna um valor inteiro, que corresponde ao caracter lido, se o fim do
arquivo for alcanado, a constante EOF (end of file) retornada, essa constante corresponde
ao valor 1. O prottipo da funo fgetc :

45

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados

int fgetc(FILE* nome_do_ponteiro);


Exemplo:
char c;
c = fgetc(fp);

//c recebe o caracter lido ou EOF

Exemplo2: /* abertura do arquivo anterior em modo leitura por char */


#include<stdio.h>
main()
{
int i;
char dados[101];
FILE *fp;
if((fp = fopen("leitura","r")) == NULL)
{
printf("Falha na abertura do arquivo\n");
exit(1);
}
for(i=0;i<100;i++)
{
dados[i] = fgetc(fp);
if(dados[i] == EOF)
{
dados[i] = '\0';
break;
}
}
printf("Dados do arquivo.\n%s\n",dados);
fclose(fp);
}
Uma outra funo muito utilizada para ler linhas de um arquivo a funo fgets. Essa funo
recebe trs parmetros: a cadeia de caracteres que armazenar o contedo lido do arquivo, o
nmero mximo de caracteres que deve ser lido e o ponteiro do arquivo. A funo l do arquivo
uma seqncia de caracteres at que seja encontrado o caractere nova linha (\n) ou que o
nmero mximo de caracteres especificado seja alcanado ou ainda que o final do arquivo seja
alcanado (EOF), se o caracter nova linha for lido ele ser escrito no vetor de caracteres.
Geralmente o nmero mximo de caracteres indica o tamanho mximo do vetor de caracteres,
evitando dessa forma a invaso de memria. Vale lembrar, que deve ser contado o caracter
finalizador de string \0 para o limite de caracteres lidos. O valor de retorno dessa funo o
ponteiro da prpria cadeia de caracteres passada como parmetro ou NULL no caso de ocorrer
erro de leitura (por exemplo, quando alcanar o final do arquivo). O prottipo da funo :
char* fgets (char* s, int n, FILE* fp);
Exemplo:
char str[30];
fgets(str,30,fp);

//str recebe o contedo lido do arquivo

Exemplo3: /*abertura do arquivo anterior em modo leitura por linhas*/


#include<stdio.h>
#include<string.h>
main()
{
char dados[201] ,tmp[51];
FILE *fp;
if((fp = fopen("leitura","r")) == NULL)
{
printf("Falha na abertura do arquivo\n");
exit(1);
}

46

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados

while(fgets(tmp,50,fp) != NULL)
{
strcat(dados,tmp);
}
printf("Dados do arquivo.\n%s\n",dados);
fclose(fp);
}
11.2.2. Funes para escrita de dados em arquivos
Assim como utilizamos a funo printf() para escrita de dados na sada padro, o vdeo, para
escrita de dados em arquivos em modo texto, geralmente utilizada a funo fprintf,
responsvel pela escrita de dados em um arquivo previamente aberto para escrita.
fprintf(FILE* nome_do_ponteiro,formato,nome_da_varivel);
Esta funo tambm apresenta 3 campos, o primeiro campo da funo deve ser o ponteiro
para o arquivo, o campo formato corresponde a maneira que queremos fazer a leitura (%d, %f,
%c, %s), geralmente utilizado %s para escrever dados em modo texto e o ltimo campo
corresponde a varivel que possui os dados a serem copiados para o arquivo. A funo fprintf()
possui como valor de retorno o numero de dados escritos com sucesso.
Exemplo:
scanf("%[^\n]",str);
fprintf(fp,"%s",str);

//l o contedo a ser gravado no arquivo


//escreve contedo de str no arquivo

Outra funo de escrita em modo texto o fputc, anloga funo fgetc, ela escreve somente
um caracter por vez no arquivo e atualiza o ponteiro para a prxima posio do arquivo. A
funo fputc() recebe dois parmetros, o primeiro deve ser a varivel caractere que possui o
contedo a ser escrito e o segundo deve ser o ponteiro para o arquivo. Esta funo retorna um
valor inteiro, que corresponde ao caracter escrito ou EOF se houver erro de escrita. O prottipo
da funo fputc :
int fputc (char c, FILE* fp);
Exemplo:
char c;
fputc(c,fp);

//escreve o caracter no arquivo apontado por fp

Outra funo de escrita em modo texto o fputs, anloga funo puts, ela escreve uma
linha no arquivo e atualiza o ponteiro para a prxima posio do arquivo, no escrito o
caracter de nova linha no final da string escrita. A funo fputs() recebe dois parmetros, o
primeiro deve ser um ponteiro para o endereo inicial de um vetor de caracteres que possui o
contedo a ser escrito e o segundo deve ser o ponteiro para o arquivo. Esta funo retorna a
quantidade de caracteres escritos no arquivo ou NULL em caso de erro, sua forma geral :
int fputs (char* c, FILE* fp);
11.3. Arquivos em modo binrio
Arquivos so tratados binariamente quando h necessidade de salvarmos o contedo da
memria principal diretamente no disco. Desta forma, o arquivo escrito copiando-se cada
byte da memria.
11.3.1. Funo de leitura de arquivos binrios
A funo para ler (recuperar) dados de arquivos binrios fread. Est funo faz uma cpia do
contedo do arquivo (disco) e escreve na memria, a partir de um endereo passado como
parmetro. Sua forma geral :
int fread (char* p, int tam, int tam_total, FILE* fp);

47

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados

O primeiro parmetro passado um ponteiro para um endereo de memria onde o arquivo


comeara a ser escrito, o qual deve ser alocado dinamicamente, de acordo com o tamanho do
arquivo a ser copiado. O segundo parmetro 1, indicando que o tamanho de cada elemento
um byte. O terceiro parmetro o tamanho total do arquivo, em bytes. Por fim, o ltimo
parmetro deve ser o ponteiro para o arquivo.
11.3.2. Funo de escrita em arquivos binrios
Para salvarmos ou escrevermos dados em arquivos binrios, utiliza-se a funo fwrite. A forma
geral dessa funo :
int fwrite (void* p, int tam, int tam_total, FILE* fp);
O primeiro parmetro dessa funo representa um apontador para o contedo que desejamos
salvar no arquivo, inicialmente este contedo est na memria principal. O parmetro tam
indica o tamanho em bytes de cada elemento, que 1. O parmetro tam_total indica o nmero
de elementos, ou seja, o tamanho total do arquivo. Por fim, passa-se o ponteiro do arquivo
binrio para o qual o contedo da memria ser copiado.
Exemplo:
/*Faz a cpia de um arquivo */
#include <stdio.h>
#include <unistd.h>
#include <string.h>
main()
{
char *buff;
FILE *fp;
long tamanho;
char nome_arq[20];
printf("Digite o nome do arquivo a ser copiado: ");
scanf("%s",nome_arq);
//Abre o arquivo
if((fp = fopen(nome_arq,"rb")) == NULL)
{
printf("Falha na abertura do arquivo de leitura\n");
exit(1);
}
// Descobre o tamanho do arquivo
fseek(fp,0,SEEK_END);
//percorre o arquivo do incio ao fim
tamanho = ftell(fp);
rewind(fp);
printf("tamanho:%d\n",tamanho);
// Aloca um buffer na memoria
buff = (char*) malloc (sizeof(char)*tamanho);
if(buff == NULL) {
printf("Falha na alocacao de memoria\n");
exit(1);
}
// Copia conteudo do arquivo para a memoria
// buff recebe, 1 byte, tamanho total e ponteiro de arquivo
fread(buff,1,tamanho,fp);
fclose(fp);
printf("Digite o nome do arquivo a ser salvo: ");
scanf("%s",nome_arq);
if((fp = fopen (nome_arq,"wb")) == NULL) {
printf("Falha na abertura do arquivo de escrita\n");
exit(1);
}
else
fwrite(buff,1,tamanho,fp);
fclose(fp);
}

48

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados

Exerccios:
1) Escreva um programa que abra um arquivo entrada.txt em modo texto e de escrita
w. Aps, deve ser feita a leitura de uma string do teclado de no mximo 200
caracteres e, copiada para dentro do arquivo, utilize a funo fprintf().
2) Faa o mesmo que foi pedido no exerccio 1, s que escreva no arquivo caracter por
caracter, utilize a funo fputc().
3) Crie um programa que efetue a leitura do arquivo criado no exerccio 1, apresentando
na tela o contedo do arquivo, utilize a funo fscanf().
4) Faa o mesmo que foi pedido no exerccio 3, porm, desta vez faa a leitura do arquivo
caracter a caracter, apresentando o contedo na tela, utilize a funo fgetc().
5) Novamente faa o mesmo que foi pedido no exerccio 3, no entanto, faa a leitura linha
a linha, apresentando o contedo na tela, utilize a funo fgets().
6) Crie um programa que leia o contedo de um arquivo e crie outro com o mesmo
contedo, mas com todas as letras maisculas. Os nomes dos arquivos sero
fornecidos pelo usurio.
7) Crie um programa que efetue uma pesquisa em determinado arquivo. A palavra a ser
buscada deve ser digitada pelo usurio. O programa deve apresentar o nmero da
linha da primeira ocorrncia da palavra.
8) Teste o exemplo de tratamento de arquivos binrios, onde feita a cpia de um
arquivo.
9) Escreva um programa que faa a inscrio de trs pessoas em algum dos cursos
oferecidos pela escola. Os dados a serem passados so:
 Nome: mximo de 30 caracteres;
 N RG;
 N CPF;
 Curso: mximo de 30 caracteres;
 Turno: mximo de 10 caracteres.
Esses dados de inscrio devem ser salvos em um arquivo. Entre cada
inscrio deve ser deixado 20 caracteres asterisco '*'.

49

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados


12. Listas Encadeadas

Para representar um grupo de dados, podemos utilizar vetores, pois so uma forma primitiva
de representar elementos em conjunto. Quando declaramos um vetor de tamanho n, um
espao contguo na memria alocado. Como j vimos, o nome de um vetor (sem o ndice)
um ponteiro para o primeiro elemento de um conjunto de elementos, sendo apenas necessrio
incrementar este ponteiro, indexar o ponteiro (ex. vet [i]) para acessar os elementos seguintes.
Baseado na indexao do vetor, podemos acessar qualquer elemento do mesmo
aleatoriamente.
O problema de trabalhar com vetores quando precisamos armazenar mais elementos no
vetor do que a dimenso a qual ele foi criado, pois nas declaraes de vetores precisamos
estipular um tamanho MXIMO de elementos a serem armazenados. Assim como podemos
dimensionar um vetor com tamanho grande, e na hora de utilizar o mesmo, necessitar de uma
pequena parte desse vetor, o que seria um desperdcio de memria.
Para solucionar esses problemas, precisamos utilizar estruturas de dados dinmicas, ou
seja, que possam ser modificadas em tempo de execuo de acordo com a necessidade do
usurio, se o usurio precisar armazenar elementos ela cresce, se o usurio precisar retirar
elementos ela diminui, essas estruturas armazenam os valores por alocao dinmica.
12.1. Lista Encadeada
Uma lista encadeada pode acessar seus dados de forma randmica, porque cada elemento de
informao carrega consigo um ponteiro para o prximo item de dados da corrente. Para cada
novo elemento inserido na lista, alocamos um espao de memria para armazen-lo. Como os
elementos provavelmente no ocuparo um espao contguo de memria, no possumos
acesso direto aos elementos desta lista. A maneira de percorrermos os elementos da lista
guardando o encadeamento entre seus elementos, ou seja, junto da informao de cada
elemento teremos tambm um ponteiro para o prximo elemento da lista.

Cada elemento da lista conhecido como n, esta estrutura de ns consiste de uma seqncia
encadeada de elementos. A lista representada por um ponteiro para o primeiro n. No
primeiro n encontramos um ponteiro para o segundo n, e assim sucessivamente at
encontrar o ltimo elemento, que ser aquele que ir apontar para NULL, indicando que no
existe um prximo elemento.
12.2. Funes de Manipulao
Vamos considerar como exemplo de implementao de uma lista encadeada, o
armazenamento de valores inteiros na mesma. O n da lista ser representado pela seguinte
estrutura:
struct lista
{
int info;
struct lista *prox;
};
typedef struct lista Lista;
dado

// Lista representa nossa estrutura de lista, um tipo de

Dentro dessa estrutura temos dois campos, o primeiro campo simplesmente armazena o
nmero inteiro, a informao, j o segundo campo um ponteiro para uma prxima estrutura
do mesmo tipo, ou seja, uma estrutura auto-referenciada.O tipo Lista um mnemnico com o
sinnimo de struct lista, esse tipo Lista representa um n da lista e essa estrutura de lista
encadeada referenciada pelo ponteiro para seu primeiro elemento (tipo *Lista).

50

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados

As principais funes de listas encadeadas so: inicializao, insero, imprimir, verificar,


busca, retirada e liberao da lista. Veremos uma a uma a seguir.
Funo de inicializao
A funo de inicializao deve criar uma lista sem nenhum elemento, uma lista vazia. Esta lista
deve ser representada pelo ponteiro NULL, pois no existem elementos na lista, e visto que a
lista representada por um ponteiro para o primeiro elemento, logo, aponta para NULL. A
implementao dessa funo ficaria da seguinte forma:
/* inicializa uma lista e retorna ela vazia
Lista *inicializa()
{
return NULL;
}
Funo de insero
Uma vez criada a lista vazia (inicializada), possvel adicionar elementos nela. Para cada
elemento que for inserido na lista, devemos antes alocar dinamicamente um espao da
memria para essa estrutura e encade-la na lista existente. Esta funo de insero insere
um novo elemento no incio da lista e retorna o ponteiro para o primeiro n da lista.
/* insere elemento no incio e retorna ponteiro para primeiro n da lista */
Lista *insere(Lista *li, int valor)
{
Lista *novo = (Lista *)malloc(sizeof(Lista));
novo->info = valor;
novo->prox = li;
return novo;
}
Como os novos elementos so inseridos no incio da lista, devemos atualizar o valor do
ponteiro que representa a lista, pois este ponteiro deve referenciar o novo primeiro elemento.
Os parmetros de entrada dessa funo so: a lista, onde ser inserido o novo elemento, e a
informao do novo elemento, retornando a nova lista, que esta sendo representada pelo
ponteiro para o novo elemento.
O espao de memria alocado dinamicamente para armazenar o novo n da lista, guardando
a informao neste n e fazendo-o apontar para o prximo elemento da lista (que agora o
segundo elemento da lista). Esta funo sempre ir retornar o ponteiro para o novo primeiro
elemento da lista.

Funo que imprime os elementos da lista


Esta funo percorre todos os elementos da lista imprimindo os dados armazenados nela, se a
lista estiver vazia a prpria funo imprime() avisa. Esta funo poderia ser utilizada conforme
implementao a seguir:
/* varre todos os ns da lista imprimindo suas informaes */
void imprime(Lista *li)
{
if(li == NULL)
printf("Lista esta vazia\n");

51

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados

while(li != NULL)
{
printf("\n Valor = %d\n",li->info);
li = li->prox;
}
}

Funo que verifica se a lista est vazia


Esta funo poder ser chamada quando for preciso testar se a lista est vazia ou no. Esta
funo recebe como parmetro a lista e imprime a resposta se est ou no vazia. A lista estar
vazia se tiver o valor NULL. A implementao dessa funo a seguinte:
/*verifica se lista esta vazia */
void vazia(Lista *li)
{
if(li == NULL)
printf(\n A lista esta vazia\n);
else
printf(\n A lista nao esta vazia\n);
}
Funo de busca
Esta funo busca um dado ou elemento na lista, verificando se h ou no a existncia do
mesmo. A funo recebe como parmetro a lista e o dado que queremos buscar e imprime a
resposta se o valor est na lista ou no. A seguir demonstrada a implementao desta
funo:
/* busca dado na lista e imprime resposta */
void busca(Lista *li, int valor)
{
for(li;li != NULL;li = li->prox)
if(li->info == valor)
{
printf("Valor %d encontrado na lista.\n",li->info);
return;
}
printf("Valor %d nao encontrado na lista.\n",valor);
}
Funo que retira um elemento da lista
Serve para excluir um n da lista. Recebe como parmetros de entrada a lista e o valor do
elemento que desejamos retirar, retornando o valor atualizado da lista.
Esta funo a que exige maior cuidado do programador, pois se o elemento a ser retirado da
lista for o primeiro, devemos fazer com que o novo valor da lista passe a ser o ponteiro para o
segundo elemento da lista, e somente depois deste processo que podemos liberar o n da
lista. Se o elemento a ser removido estiver no meio da lista, devemos fazer com que o
elemento anterior a ele aponte para o elemento posterior a ele, e somente depois poderemos
liberar este n da lista. Por fim, se o elemento a ser removido for o ltimo da lista, devemos
primeiramente fazer com que o elemento anterior a ele aponte para NULL para somente depois
removermos o elemento.
Antes de removermos um elemento da lista devemos ter certeza de que este elemento existe
na lista, utilizando a funo busca() para verificar sua existncia.

52

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados

Remoo no incio da lista encadeada.

Remoo no meio da lista encadeada.


O primeiro passo a ser seguido para retirar um elemento da lista encadeada buscar esse
elemento e guardar uma referncia para o elemento anterior. A seguir mostrado a
implementao da funo:

/* retira elemento (n) da lista */


Lista *retira(Lista *li, int valor)
{
Lista *ant = NULL;
Lista *tmp = li;

//ponteiro para n anterior


//aponta para primeiro n da lista

/* quando um deles for igual fecha


while((tmp->info != valor) && (tmp
ant = tmp;
tmp = tmp->prox;
}
if(tmp == NULL)
return li;

o looping */
!= NULL))
{
//anterior atualizado
//tmp atualizado para prximo n

else if(ant == NULL)


li = tmp->prox;

//remove primeiro elemento


//segundo n vira primeiro n

else

//remove elemento do meio ou fim da

//elemento no encontrado
//retorna lista original

lista
ant->prox = tmp->prox;

//atualiza ponteiro do n anterior

free(tmp);
return li;
}
Funo para liberar a lista
Esta funo responsvel por liberar todos os ns da lista, deixando-a vazia. A funo libera
elemento por elemento, enquanto vai a percorrendo. Assim que todos os ns da lista forem
liberados, a funo retorna NULL, indicando que a lista esta vazia. Vale ressaltar que antes de
liberar um n da lista devemos guardar a posio do prximo n. A implementao da funo
demonstrada a seguir:
Lista *libera(Lista *li)
{
Lista *tmp = li;
while(tmp != NULL)
li = tmp->prox;
free(tmp);
tmp = li;

53

{
// li aponta para prximo n
// libera memria apontada por tmp
// faz tmp apontar para prximo n

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados


}

return NULL;
}
Agora apresentamos a funo principal para ilustrar essa lista.
Exemplo:
main()
{
int num;
Lista *l;
l = inicializa();
l = insere(l,18);
l = insere(l,21);
l = insere(l,666);
l = insere(l,123);
imprime(l);
l = retira(l,666);
imprime(l);
l = retira(l,18);
vazia(l);
imprime(l);
busca(l,19);
busca(l,21);
l = libera(l);
vazia(l);

//declara uma varivel para struct lista


//inicializa lista vazia
//insere elemento 18 no novo n
//insere elemento 21 no novo n
//insere elemento 666 no novo n
//insere elemento 123 no novo n
//imprime: 123 666 21 18
//imprime: 123 21 18
//testa se a lista esta vazia
//imprime: 123 21
//imprime que valor 19 nao foi encontrado
//imprime que valor 21 foi encontrado
//esvazia a lista e retorna NULL

}
12.3. Listas Circulares
Poderemos encontrar aplicaes onde ser necessrio representar conjuntos cclicos. O
funcionamento de uma lista circular bem semelhante a uma lista encadeada, a diferena est
no ltimo n da lista, que ao invs de apontar para NULL, aponta para o primeiro n da lista.
Mas, como falamos de listas circulares, na verdade no temos um primeiro n e um ltimo n,
mas sim um n inicial na lista, ou seja, a lista representada por um ponteiro para um
elemento inicial qualquer da lista, conforme mostra a figura a seguir.

Para percorrer os elementos de uma lista circular, percorremos todos os ns a partir de um n


inicial at que seja encontrado novamente este mesmo n. Relembrando que uma lista vazia
aponta para NULL, uma funo que percorra uma lista circular que armazene valores inteiros
ficaria da seguinte forma:
void imprime_circular(Lista *li)
{
Lista *pt = li;
//pt aponta para n inicial
if(li == NULL)
//testa se lista esta vazia
printf("Lista esta vazia\n");
do
{
printf("\n Valor = %d\n",pt->info);
//imprime valor do n
pt = pt->prox;
//atualiza apontador para prximo n
} while(li != pt);
}

54

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados

12.4. Listas duplamente encadeadas


As listas duplamente encadeadas, so diferentes da lista que foi vista anteriormente, pois os
ns da lista possuem um apontador para o prximo n da lista e para o n anterior da lista. Isso
nos possibilita percorrermos a lista tanto em um sentido quanto em outro sentido, pois cada n
possui duas referncias. Portanto, o ltimo elemento desta lista tem como prximo n o NULL
e uma referncia para o n anterior, j o primeiro n da lista possui uma referncia para o
prximo n da lista e o ponteiro para o n anterior NULL.

Conforme comentado anteriormente, listas duplamente encadeadas possuem algumas


diferenas em relao s listas encadeadas. A primeira diferena comea na estrutura que
representa a informao, seguindo os exemplos anteriores de valores inteiros na lista, a
estrutura ficaria da seguinte forma:
struct lista_dupla
{
int info;
struct lista_dupla *ant;
struct lista_dupla *prox;
};
typedef struct lista_dupla ListaDupla;
A seguir ser mostrado algumas funes de manipulao de listas duplamente encadeadas,
funes as quais j foram vistas, mas com algumas peculiaridades.
Funo de inicializao
A funo de inicializao deve criar uma lista sem nenhum elemento, uma lista vazia. Esta lista
deve ser representada pelo ponteiro NULL, pois no existem elementos na lista, e visto que a
lista representada por um ponteiro para o primeiro elemento, logo, aponta para NULL. A
implementao dessa funo ficaria da seguinte forma:
/* inicializa uma lista e retorna ela vazia
ListaDupla *inicializa()
{
return NULL;
}
Funo de insero
Uma vez criada a lista vazia (inicializada), possvel adicionar elementos nela. Para cada
elemento que for inserido na lista, devemos antes alocar dinamicamente um espao da
memria para essa estrutura e fazer o duplo encadeamento na lista existente. Esta possvel
implementao da funo de insero insere um novo elemento no incio da lista e retorna o
ponteiro para o primeiro n da lista.
/* insere elemento no incio e retorna ponteiro para primeiro n da lista */
ListaDupla *insere(ListaDupla *li, int valor)
{
ListaDupla *novo = (ListaDupla *)malloc(sizeof(ListaDupla));
novo->info = valor;
novo->ant = NULL;
//atualiza ponteiro de ant para NULL
novo->prox = li;
//aponta para segundo n da lista
if(li != NULL)
//verifica se lista no esta vazia
li->ant = novo;
//faz com que o 2 n aponte para o 1 n

55

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens


return novo;

de Programao I e Estruturas de Dados

//retorna novo primeiro n da lista

}
Como os novos elementos so inseridos no incio da lista, o apontador para o n anterior a
este que est sendo inserido deve apontar para NULL e o apontador para o prximo n deve
apontar para o antigo primeiro n. Os parmetros de entrada dessa funo so: a lista, onde
ser inserido o novo elemento, e a informao do novo elemento, retornando a nova lista, que
esta sendo representada pelo ponteiro para o novo elemento, o primeiro elemento da lista.
Funo de busca
Esta funo busca um dado ou elemento na lista, verificando se h ou no a existncia do
mesmo. A funo recebe como parmetro a lista e o dado que queremos buscar e tem como
valor de retorno o ponteiro para o elemento, ou, caso no seja encontrado o valor a funo
retorna NULL. Segue uma possvel implementao desta funo.
/* busca dado na lista e imprime resposta */
ListaDupla *busca(ListaDupla *li, int valor)
{
for(li;li != NULL;li = li->prox)
if(li->info == valor)
return li;
//retorna ponteiro para o elemento
return NULL;
//no encontrou, retorna NULL
}
Funo que retira um elemento da lista
Serve para excluir um n da lista. Recebe como parmetros de entrada a lista e o valor do
elemento que desejamos retirar, retornando o valor atualizado da lista. A melhor utilizao
desta funo seria associ-la a funo busca(), a qual ir retornar um ponteiro para o elemento
a ser removido.
Visto que estamos trabalhando com listas duplamente encadeadas, antes de removermos um
n devemos atualizar o duplo encadeamento da lista. Supondo que pt representa o ponteiro
para o elemento que queremos remover, o encadeamento deve ficar da seguinte forma:
/* operaes referente ao n a ser retirado */
pt->ant->prox = pt->prox;
//n 1 prox recebe ponteiro para n 3
pt->prox->ant = pt->ant;
//n 3 ant recebe ponteiro para n 1

In fo 1

In fo 2

In fo 3

Os dois passos acima servem para qualquer n que esteja no meio da lista. Porm, se for um
dos ns extremos, devemos fazer um tratamento especial com eles. Se for preciso remover o
primeiro n da lista no podemos fazer pt->ant->prox, pois ant aponta para NULL. Assim
como se for o ltimo elemento da lista, novamente no podemos fazer pt->prox->ant, pois
prox aponta para NULL. Alm disso, se o elemento a ser removido for o primeiro, devemos
atualizar o ponteiro para a lista.
Uma possvel implementao desta funo representada a seguir:
/* retira elemento (n) da lista */
ListaDupla *retira(ListaDupla *li, int valor)
{
ListaDupla *pt = busca(li,valor);
//busca elemento na lista
if(pt == NULL)
//se valor no encontrado

56

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados

return li;
//retorna lista original
if(li == pt)
//retira primeiro elemento da lista
li = pt->prox;
//atualiza ponteiro da lista para o segundo n
else
//n anterior recebe ponteiro para prximo n
pt->ant->prox = pt->prox;
if(pt->prox != NULL)
//significa que no o ltimo n
pt->prox->ant = pt->ant;
free(pt);
return li;

//libera n
//retorna nova lista

}
Exerccios:
1) Implemente uma funo que verifique se duas listas encadeadas so iguais. As listas
sero consideradas iguais se possurem a mesma seqncia de elementos. Utilize o
seguinte prottipo de funo:
int iguais(Lista *l1, Lista *l2);
2) Implemente uma funo que crie uma cpia de uma lista encadeada. Utilize o seguinte
prottipo de funo:
Lista *copia(Lista *li);
3) Implemente as funes para inserir e retirar um elemento de uma lista circular. Utilize
os seguintes prottipos de funo:
Lista *insere(Lista *li, int valor);
Lista *retira(Lista *li, int valor);
4) Implemente as funes para imprimir os elementos e para verificar se uma lista
duplamente encadeada est vazia. Utilize os seguintes prottipos:
void vazia(ListaDupla *li);
void imprime(ListaDupla *li);

57

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados


13. Pilhas

A idia fundamental da pilha que todos o acesso a seus elementos feito atravs do topo.
Desta forma, quando um novo elemento adicionado na pilha, ele passa a ser o topo da pilha.
Da mesma forma que, para retirarmos um elemento da pilha, devemos retirar primeiramente o
elemento do topo, sempre. Isso faz com que os elementos da pilha sejam retirados na ordem
inversa ordem em que foram introduzidos: o primeiro que sai o ltimo que entrou (sigla
LIFO Last in, First out).
Para manipulao de pilhas h duas operaes bsicas que devem ser implementadas: a
operao para empilhar um novo elemento, inserindo-o no topo e a operao para desempilhar
um elemento, removendo o elemento do topo. Essas duas operaes so normalmente
conhecidas como push (empilhar) e pop (desempilhar). A figura a seguir ilustra o
funcionamento de uma pilha.

As pilhas podem ser implementadas com vetores ou lista encadeada. Essas duas maneira
sero tratadas a seguir. Para as duas implementaes iremos utilizar uma pilha que armazene
valores reais e com cinco funes de manipulao de pilhas:

Criar uma estrutura de pilha;


Inserir um elemento no topo (push);
Remover um elemento do topo (pop);
Verificar se a pilha est vazia;
Liberar a estrutura de pilha.

13.1. Implementao de pilha com vetor


Em aplicaes onde definida uma quantidade mxima de elementos que podem ser
armazenados na pilha, ou seja, quando temos um limite conhecido do tamanho da pilha,
podemos fazer a implementao utilizando vetores, o que torna sua implementao mais
simples. Desta forma, declaramos um vetor, onde os ndices mais baixos iro referenciar a
parte mais inferior da pilha e os ndices mais altos representam a parte superior da pilha (topo).
Logo, a estrutura do tipo pilha ser composta pelo vetor e por uma varivel inteira que indicar
a quantidade de elementos armazenados na pilha.
struct pilha
{
int n;
float vet[100];
};
typedef struct pilha Pilha;

// Pilha representa nossa struct pilha

Funo para criar a pilha


Esta funo responsvel por alocar dinamicamente a estrutura da pilha e inicializar a pilha
como sendo vazia, ou seja, com nmero de elementos igual a zero.
Pilha *cria()
{
Pilha *pt = (Pilha *)malloc(sizeof(Pilha));
//aloca a pilha na memria

58

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens


pt->n = 0;
return pt;

de Programao I e Estruturas de Dados


//armazena 0 em n
//retorno ponteiro para a pilha criada

Funo para inserir um elemento


Para inserir um elemento novo no topo da pilha, devemos antes verificar se o tamanho da pilha
no est esgotado. Este elemento armazenado no vetor de ndice n, onde aps a insero do
novo dado deve ser incrementado, indicando o topo da pilha. Uma possvel implementao
demonstrada a seguir:
void push(Pilha *pt, float valor)
{
if(pt->n == 100)
//verifica se o tamanho da pilha no estourou
{
printf(Pilha esgotada\n);
return;
}
else
//existe espao na pilha, adiciona elemento no topo da pilha
{
pt->vet[pt->n] = valor;
pt->n++;
}
}
Funo para retirar um elemento
Para removermos um elemento do topo da pilha, devemos antes verificar se a pilha no est
vazia. Visto que um elemento da pilha sempre retirado do topo, passado como parmetro
para esta funo somente o ponteiro para a pilha e a funo retorna o valor que foi removido
da pilha. Uma possvel implementao demonstrada a seguir:
float pop(Pilha *pt)
{
float valor;
if(pt->n == 0)
{
printf(A pilha esta vazia\n);
return;
}
else
//h elementos na pilha, remove elemento do topo da pilha
{
pt->n--;
valor = pt->vet[pt->n];
return valor;
}
}
Funo que verifica se a pilha est vazia
Esta funo muito simples, basta receber o ponteiro para a pilha e verificar se a varivel n
possui o valor 0, conforme demonstra a implementao a seguir:
void vazia(Pilha *pt)
{
if(pt->n == 0)
printf(A pilha esta vazia\n);
else
printf(A pilha nao esta vazia\n);
}

59

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados

Funo para liberar a pilha


Esta funo apenas libera a pilha da memria e no precisa retornar nada, conforme
demonstrado a seguir:
void libera(Pilha *pt)
{
free(pt);
}
13.2. Implementao de pilha com lista encadeada
Outra forma de trabalharmos com pilhas, normalmente utilizamos listas para este fim quando
no fornecido um nmero preciso de elementos a serem armazenados na mesma. Desta
forma, como as listas encadeadas so estruturas alocadas dinamicamente, se encaixa
perfeitamente neste processo. Os elementos so armazenados na lista e a pilha pode ser
representada por um ponteiro para o primeiro n da lista. A estrutura que ir representar a pilha
composta por uma estrutura que representa os ns da lista, conforme a seguir:
struct no
{
float info;
struct no *prox;
};
typedef struct no No;

//struct que representa os ns da lista encadeda

struct pilha
n
{
No *prim;
};
typedef struct pilha Pilha;

//struct que representa a pilha, composta por um ponteiro p/ um

// No representa cada n da pilha

// Pilha representa nossa struct pilha

Funo para criar a pilha


Esta funo responsvel por alocar dinamicamente a estrutura da pilha e inicializar a lista
como sendo vazia, ou seja, apontando para NULL.
Pilha *cria()
{
Pilha *pt = (Pilha *)malloc(sizeof(Pilha));
memria
pt->prim = NULL;
//armazena 0 em n
return pt;
}
//retorno ponteiro para a pilha criada

//aloca

pilha

na

Funo para inserir um elemento


Conforme estudado em listas encadeadas, um novo elemento sempre inserido no inicio da
lista, portanto o incio da lista ser o topo da pilha. A funo para inserir um novo elemento no
topo da pilha, deve chamar uma outra funo que ser responsvel por inserir um novo n no
incio da lista. Uma possvel implementao demonstrada a seguir:
void push(Pilha *pt, float valor)
{
pt->prim = insere(pt->prim,valor);
}
No *insere(No *li, float valor)
pilha

60

//insere um elemento no inicio da lista, topo da

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados

{
No *pt = (No *)malloc(sizeof(No));
//aloca um n na memria
pt->info = valor;
//armazena o valor na pilha
pt->prox = li;
// este n aponta para o resto da pilha
return pt;
//retorna ponteiro para este n, que o 1 n
}
Funo para retirar um elemento
Para removermos um elemento do topo da pilha, basta removermos o primeiro n da lista. Se a
pilha estiver vazia, simplesmente sai da funo. Novamente a funo pop() que responsvel
por remover um elemento do topo da pilha, precisa chamar uma outra funo para remover o
n do incio da lista. Uma possvel implementao demonstrada a seguir:
void pop(Pilha *pt)
{
float valor;
if(pt->prim == NULL)
//verifica se a pilha esta vazia
{
printf(A pilha esta vazia\n);
}
else
//h elementos na pilha, remove elemento do topo da pilha
{
valor = pt->prim->info;
//atribui elemento a ser removido p/
valor
pt->prim = retira(pt->prim); //chama funo para remover o n do
incio
printf(Valor removido eh %f\n,valor);
}
}
No *retira(No *li)
{
No *pt = li->prox;
free(li);
return pt;
}
Funo que verifica se a pilha est vazia
Esta funo muito simples, basta receber o ponteiro para a pilha e verificar se a varivel prim
aponta para NULL, conforme demonstra a implementao a seguir:
void vazia(Pilha *pt)
{
if(pt->prim == NULL)
printf(A pilha esta vazia\n);
else
printf(A pilha nao esta vazia\n);
}
Funo para liberar a pilha
Por fim a funo que libera a pilha da memria. Esta funo deve liberar n por n da lista e
por final armazenar NULL no ponteiro da pilha, indicando que a pilha est vazia, pois aponta
para NULL, conforme demonstrado a seguir:
void libera(Pilha *pt)
{
No *tmp = pt->prim;

61

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados

No *li;
while(tmp != NULL)
{
li = tmp->prox;
free(tmp);
tmp = li;
}
pt->prim = NULL;
}
Exerccios:
1) Implemente a funo que percorre a pilha e imprima os elementos, deve comear pelo
topo (implemente para pilhas com vetores e com listas encadeadas).
2) Implemente a funo que busque um valor na pilha e imprima a resposta (implemente
para pilhas com vetores e com listas encadeadas).

62

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados


Anexo A
Funes Matemticas

O padro C ANSI define 22 funes matemticas, divididas em trigonomtricas, hiperblicas,


exponenciais, logartmicas e miscelneas. Referente s funes trigonomtricas, todos os
ngulos so expressos em radianos.
Todas as funes matemticas que veremos a seguir, exigem o arquivo de cabealho math.h.
No estudaremos todas as funes definidas na biblioteca, se o leitor quiser se aprofundar nas
funes da biblioteca math.h deve consultar a documentao. Incluindo a biblioteca
matemtica no programa:
#include<math.h>
Sempre que estivermos trabalhando com esta biblioteca, devemos fazer uma ligao do nosso
programa com a biblioteca, para isso, a linha de compilao deve ser:
gcc -lm programa.c o programa

//ou gcc programa.c -lm

Funes trigonomtricas
A funo sin devolve o seno de val. O valor de val deve estar em radianos. Sua forma geral :
double sin(double val);
Semelhante a funo sin, temos tambm as funes cos e tan, que devolvem o coseno e a
tangente de val, respectivamente. A forma geral dessas duas so semelhantes a sin.
A funo acos() devolve o arco-coseno de val. O valor de val deve estar na faixa de -1 a 1,
caso contrrio, ocorrer um erro de domnio. Sua forma geral :
double acos(double val);
Semelhante a funo acos, temos tambm as funes asen e atan, que devolvem o arco-seno
e arco-tangente, respectivamente. A forma geral dessas duas so semelhantes acos.
Exemplo:
/*imprimi os senos dos valores de -1 a 1, passo de 0.1 */
#include<stdio.h>
#include<math.h>
main()
{
double res, val = -1.0;
while(val<=1.0)
{
res = sin(val);
printf(Sin(%.2f) = %f\n,val,res);
val = val + 0.1;
}
}
Funes exponenciais e logartmicas
A funo log10 devolve o logaritmo de base 10 de val. Se o valor de val for zero, ocorrer um
erro de escala e se o valor for negativo, um erro de domnio. Sua forma geral :
double log10(double val);
A funo log devolve o logaritmo natural de val. Se o valor de val for zero, ocorrer um erro de
escala e se o valor for negativo, um erro de domnio. Sua forma geral :
double log(double val);

63

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados

A funo exp devolve o valor de e elevado potncia val, onde o valor arredondado de e
2.718282. Sua forma geral :
double exp(double val);
Exemplo:
/* Escreve os logaritmos naturais dos nmeros de 1 a 10 */
#include<stdio.h>
#include<math.h>
main()
{
double res, val = 1.0;
while(val<=10.0) {
res = log(val);
printf(Log(%.2f) = %f\n,val,res);
val++;
}
}
Funes de Raiz e Potncia
exp

A funo pow devolve base elevada potncia exp (base ). Se a base for 0 e exp for menor
ou igual a 0 ocorrer erro de domnio, assim como se base for negativa e exp for fracionrio.
Sua forma geral :
double pow(double base,doubl exp);
A funo sqrt devolve a raiz quadrada de val. Se val for um nmero negativo, ocorrer erro de
domnio. Sua forma geral :
double sqrt(doubl val);
Exemplo:
/* imprime as 8 primeiras potncias de 2 */
#include<stdio.h>
#include<math.h>
main()
{
double res, exp = 0;
while(val < 8.0) {
res = pow(2,exp);
printf(2 elevado %.1f = %f\n,exp,res);
exp++;
}
}
Miscelneas
A funo fabs devolve o valor absoluto de val, ou seja, o valor sem sinal. Sua forma geral :
double fabs(double val);
Exerccios:
1) Escreva um programa que imprima a raiz quadrada dos valores inteiros entre 0 e 10.
2) Escreva um programa que imprima o cubo de todos inteiros entre 0 e 10.
3) A relao entre os lados (a,b) de um tringulo retngulo e a hipotenusa dada pela
formula (Teorema de Pitgoras):
h = (a + b)
Escreva um programa que leia os valores dos lados a e b, aps deve ser impresso o valor
da hipotenusa.

64

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados

4) A rea A de um tringulo cujos lados so a, b e c pode ser calculada pela frmula:


onde p = (a+b+c)/2. Escreva um programa em linguagem C que leia os valores dos 3 lados
do tringulo e imprima a rea correspondente.
5) Escreva um programa que encontre as razes de uma equao do segundo grau. A
equao do 2 grau representado por:
ax + bx + c = 0
Onde a,b e c sero lidos do teclado. Ao final, o programa deve apresentar a equao
tratada, conforme os valores lidos, assim como apresentar as razes da equao.

65

Copyright 2006,07 Alan Malta Rodrigues

Escola Solon Tavares Linguagens

de Programao I e Estruturas de Dados

Referncias bibliogrficas
SCHILDT, Herbert. C Completo e Total [3 edio]. So Paulo: Makron Books, 1996.
CELES, Waldemar; RANGEL, Jos Lucas. Apostila de Estruturas de Dados. PUC-RIO, 2002.
GLUZ, Joo Carlos. Apostila de Algoritmos de Dados. Guaba: UERGS, 2003.

66

Copyright 2006,07 Alan Malta Rodrigues

Você também pode gostar