You are on page 1of 62

CENTRO UNIVERSITRIO LASALLE

CINCIA DA COMPUTAO
LINGUAGEM DE PROGRAMAO II

PROGRAMAO EM C

Professores:
Mozart Lemos de Siqueira
Tasso Gomes de Faria

SUMRIO

1 A LINGUAGEM C - PRIMEIROS PASSOS . .


1.1
Introduo ao Linux . . . . . . . . . . . . . .
1.1.1
O Linux igual ao Unix? . . . . . . . . . . .
1.1.2
Comandos Bsicos . . . . . . . . . . . . . .
1.1.3
Estrutura de diretrios do Linux . . . . . . .
1.1.4
Como acessar um disquete (floppy) no Linux?
1.1.5
Compilando um programa . . . . . . . . . .
1.1.6
Exerccios . . . . . . . . . . . . . . . . . . .
1.2
Introduo Linguagem C . . . . . . . . . .
1.2.1
Caractersticas Bsicas . . . . . . . . . . . .
1.2.2
Estruturas dos programas em C . . . . . . . .
1.2.3
Primeiro exemplo . . . . . . . . . . . . . . .
1.2.4
Identao de programas . . . . . . . . . . . .
1.2.5
Reviso de termos . . . . . . . . . . . . . . .
1.2.6
Exerccios . . . . . . . . . . . . . . . . . . .

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

. . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .

5
5
5
5
5
5
7
7
8
8
8
9
11
11
11

2 INTRODUO AO TRATAMENTO DE VARIVEIS


2.1
Identificadores . . . . . . . . . . . . . . . . . . . .
2.2
Variveis . . . . . . . . . . . . . . . . . . . . . . .
2.3
Tipos de dados . . . . . . . . . . . . . . . . . . . .
2.4
Operador de Atribuio . . . . . . . . . . . . . . .
2.5
Variveis Locais x Variveis Globais . . . . . . . .
2.5.1
Variveis Locais . . . . . . . . . . . . . . . . . . .
2.5.2
Variveis Globais . . . . . . . . . . . . . . . . . .
2.6
Constantes . . . . . . . . . . . . . . . . . . . . . .
2.7
Operadores Aritmticos . . . . . . . . . . . . . . .
2.8
Operadores Relacionais e Lgicos . . . . . . . . . .
2.9
Operadores Bit a Bit . . . . . . . . . . . . . . . . .
2.10 Prioridade das Operaes . . . . . . . . . . . . . .
2.11 Operaes de entrada e sada . . . . . . . . . . . .
2.11.1 printf . . . . . . . . . . . . . . . . . . . . . . . . .
2.11.2 scanf . . . . . . . . . . . . . . . . . . . . . . . . .
2.11.3 sprintf e sscanf . . . . . . . . . . . . . . . . . . .
2.12 Exerccios . . . . . . . . . . . . . . . . . . . . . . .

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

. . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .

12
12
12
13
14
14
14
14
15
15
16
17
18
19
19
20
21
21

3 COMANDOS DE CONTROLE E REPETIO


3.1
if/else . . . . . . . . . . . . . . . . . . . . . . .
3.2
while . . . . . . . . . . . . . . . . . . . . . . .
3.3
for . . . . . . . . . . . . . . . . . . . . . . . .
3.4
do/while . . . . . . . . . . . . . . . . . . . . .
3.5
Break e Continue . . . . . . . . . . . . . . . .
3.6
switch/case . . . . . . . . . . . . . . . . . . .
3.7
Expresses Condicionais . . . . . . . . . . . .
3.8
Exerccios: . . . . . . . . . . . . . . . . . . .

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

. . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .

23
23
25
25
26
26
26
27
27

4 MATRIZES . . . . . . . . . . .
4.1
Strings . . . . . . . . . . . . .
4.2
Matrizes Bidimensionais . . .
4.3
Matrizes de Strings . . . . . .
4.4
Matrizes Multidimensionais .
4.5
Inicializao de Matrizes . . .
4.6
Exerccios: . . . . . . . . . .

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

. . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .

29
30
32
33
33
34
34

5 ESTRUTURAS DEFINIDAS PELO USURIO


5.1
Estruturas . . . . . . . . . . . . . . . . . . . .
5.1.1
Exerccios . . . . . . . . . . . . . . . . . . .
5.2
Unies . . . . . . . . . . . . . . . . . . . . . .
5.3
Enumeraes . . . . . . . . . . . . . . . . . .

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

. . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .

36
36
38
38
40

6 FUNES . . . . . . . . . . . . . . . . .
6.1
Modularidade . . . . . . . . . . . . . . .
6.2
Forma de uma Funo . . . . . . . . . .
6.3
Regras de Escopo . . . . . . . . . . . . .
6.4
Argumentos de Funes . . . . . . . . .
6.5
O Comando return . . . . . . . . . . . .
6.6
Funes do Tipo void . . . . . . . . . . .
6.7
Passagem por Parmetros . . . . . . . .
6.7.1
Chamada por Valor . . . . . . . . . . .
6.7.2
Chamada por Referncia . . . . . . . .
6.7.3
Matrizes como Argumentos de Funes
6.8
Prottipos de Funes . . . . . . . . . .
6.9
Exerccios . . . . . . . . . . . . . . . . .

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

. . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .

41
41
41
42
42
43
43
44
44
45
46
46
47

7 APONTADORES . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7.1
Apontadores: passagem de parmetros por referncia . . . . . . . . . .
7.2
Alocao Dinmica de ponteiros . . . . . . . . . . . . . . . . . . . . . .
7.3
Exerccios: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

48
50
52
54

8 ARQUIVOS . . . . . . . . . .
8.1
Introduo . . . . . . . . . .
8.2
Arquivos . . . . . . . . . . . .
8.3
Funes . . . . . . . . . . . .
8.3.1
Ponteiro de Arquivo . . . . .
8.3.2
Abrindo um arquivo (fopen) .

55
55
55
55
55
55

.
.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

. . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .

8.3.3
Fechando um arquivo (fclose) . . . . . . . . . . . . .
8.3.4
Escrevendo e Lendo um caractere . . . . . . . . . . .
8.3.5
Lidando com Strings (fputs e fgets) . . . . . . . . . .
8.3.6
Lidando com blocos de dados binrios(fread e fwrite)
8.3.7
Realizando Procuras (fseek) . . . . . . . . . . . . . .
8.4
Exerccios . . . . . . . . . . . . . . . . . . . . . . . .
9

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

BIBLIOGRAFIA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

.
.
.
.
.
.

57
57
58
59
60
61
62

1 A LINGUAGEM C - PRIMEIROS PASSOS

Esse captulo apresenta uma breve introduco ao Sistema Operacional Linux, suas caractersticas bsicas e seus principais comandos. O objetivo dar suporte para o aluno
desenvolver seus programas no ambiente Linux, utilizando o compilador gcc. Uma introduo a Linguagem de Programao C tambm apresentada, atravs do histrico da
linguagem e da descrio da estrutura bsica de um programa escrito com ela.

1.1 Introduo ao Linux


Linux um Sistema Operacional que foi inicialmente criado por um estudante, Linus
Torvalds, na Universidade de Helsinki na Finlndia. Linus era interessado pelo Minix,
um pequeno sistema UNIX, e decidiu desenvolver um sistema que excedesse os padres
Minix.
Ele iniciou seu trabalho em 1991 e sua verso 1.0 surgiu em 1994. O kernel, o corao
dos sistemas Linux, desenvolvido sob o GNU General Public License e seu cdigo fonte
disponvel para todos, gratuitamente.
1.1.1 O Linux igual ao Unix?
O Linux foi escrito desde o inicio pelo Linus Torvalds e no contm nenhuma linha de
cdigo do UNIX. Mas o Linux foi escrito para ser conforme o padro POSIX, que deve
ser o padro da API (Application Programming Interface) Unix.
1.1.2 Comandos Bsicos
Na Tabela 1.1 esto relacionados os principais comandos do Linux:
1.1.3 Estrutura de diretrios do Linux
Na Tabela 1.2 esto relacionados os principais diretrios do Linux. Essa estrutura ser
encontrada na maioria das distribuies disponveis.
1.1.4 Como acessar um disquete (floppy) no Linux?

 
  
  


 
Para desmontar:   
Para montar:

Obs.: Para acessar o contedo do disquete, copiar, deletar, mover ou qualquer outra
tarefa relativa aos arquivos, use os comandos do Linux no diretrio /mnt/floppy,
esse diretrio o disquete!

Comando
man <comando>
ls
ls -la
cd <nome-dir>
mkdir <nome-dir>
touch <nome-arquivo>
rmdir <nome-dir>
cp <origem> <destino>
mv <origem><destino>
mv <nome1> <nome2>
rm file
ps
kill -9 nro
pwd
cat f
more f
free
passwd

Funo
Manual de usurio Linux para os comandos
Lista arquivos do diretrio
Lista arquivos no diretrio com detalhes
Muda para o diretrio
Cria o novo diretrio
Cria ou atualiza data, se o arquivo j existe
Deleta diretrio (deve estar vazio)
Copia arquivo
Move dado da origem para o destino
Renomeia diretrio ou arquivo 1 para 2
Remove arquivo (cuidado!)
Imprime o numero dos processos ativos
Mata processo nro
Imprime diretrio corrente
Mostra contedo do arquivo f
Mostra contedo do arquivo f tela a tela
Exibe memria livre
Altera senha do usurio

Tabela 1.1: Comandos bsicos do Linux

Diretrio
/
bin
boot
dev
etc
home
lib
mnt
root
sbin
tmp
usr

Contedo
Diretrio raiz do sistema
Arquivos executveis(binrios)
Arquivos estticos de boot de inicializao(boot-loader)
Arquivos de dispositivos de entrada/sada
Configurao do sistema da mquina local
Diretrio local (home) dos usurios
Arquivos das bibliotecas compartilhadas usados freqentemente
Ponto de montagem de partio temporrios (floppy, cdrom, etc)
Diretrio local do superusurio (root)
Arquivos de sistema essenciais
Arquivos temporrios gerados por alguns utilitrios
Todos os arqs dos diversos aplicativos devem estar aqui
Tabela 1.2: Principais diretrios do Linux

1.1.5 Compilando um programa


Para compilar um programa e transform-lo em executvel, atravs de linha de comando digite:

    
  
onde gcc o comando que dispara o compilador,   o argumento, no obrigatrio,
para entrar com o nome do executvel. Caso seja omitido   , o compilador retornar

um nome padro para o executvel igual a 
 . Dvidas sobre o comando podem ser
resolvidas digitando  
  .

Obs.: Para executar o programa digite antes do nome do executvel. Isso neces

  



 

srio porque o executvel no est no Path do Sistema Operacional.


1.1.6 Exerccios
1. Logue-se no Linux
2. Abra um Terminal
3. Crie um diretrio aluno
4. Entre neste diretrio aluno
5. Crie, dentro do diretrio aluno, outro diretrio chamado teste e entre nele
6. Crie um arquivo chamado linux.arq
7. Faa uma cpia deste arquivo para linux2.arq
8. Liste os arquivos do diretrio com detalhes
9. Mova estes dois arquivos para o diretrio aluno
10. Volte para o diretrio aluno
11. Apague o diretrio teste

1.2 Introduo Linguagem C


A linguagem "C"foi criada nos laboratrios Bell por Brian W. Kernighan e Dennis Ritchie em 1972. Esta linguagem, teve suas idias iniciais originadas da linguagem BCPL
(Basic Combined Programming Language), desenvolvida por Martin Richards. Esta influncia do BCPL se deu atravs de outra linguagem, chamada "B"e criada por Thompson
em 1970 para o primeiro sistema operacional UNIX no PDP-11.
A partir de sua criao a linguagem "C" sofreu uma longa evoluo sendo que uma de
suas primeiras utilizaes foi a de reescrever o sistema operacional UNIX (1973) que estava escrito em linguagem assembly do PDP-11. Por este motivo que se tem associado a
linguagem ao S.O. UNIX, visto que o UNIX composto, quase na sua totalidade, de programas escritos em "C" (Sistema Operacional, utilitrios, compiladores, ...). Entretanto
isto no implica que o "C" seja uma linguagem "amarrada"a um sistema operacional ou
mquina.
Devido evoluo do "C" que seguia apenas o padro descrito por Kernighan e Ritchie, tornou-se necessria uma padronizao mais rgida para a linguagem, permitindo a
portabilidade dos softwares escritos nesta linguagem. Isto foi feito pelo ANSI (American
National Standard Institute), criando assim o padro C ANSI.
1.2.1 Caractersticas Bsicas
O "C" uma linguagem de propsitos gerais e que tem como caractersticas principais:
Controle de fluxo e estrutura de dados adotando conceitos modernos de linguagens
de programao;
Poderoso conjunto de operadores e tipos de dados;
Permite a gerao de um cdigo bem otimizado e compacto (quase to otimizado
quanto o assembly);
Grande portabilidade de programas (a maioria dos computadores suportam "C");
uma linguagem de nvel "relativamente baixo", mas com recursos de alto nvel;
Apresenta facilidade de manipulao direta do hardware da mquina;
Uso de bibliotecas de funes, expandindo as potencialidades da linguagem;
Grande "liberdade"para o programador.
1.2.2 Estruturas dos programas em C
Todo programa C deve ter ao menos uma funo, denominada main(), a qual a
primeira funo a ser chamada quando o programa executado. Geralmente, a funo
main() contm um esboo do que o programa faz, ou a estrutura geral de controle do
programa. Embora main no seja uma palavra reservada da linguagem, no se pode usala para outros fins que no seja o nome da funo principal do programa.

/*No incio do programa, declara-se as bibliotecas usadas*/


#include <stdio.h>
/* Declaraes globais */
/* Declarao de funes do programador, se for o caso */
/* Declarao da funo principal. Sempre necessria */
tipo_devolvido main (lista de parmetros)
{
/* variaveis locais ao main, se existirem */
// Isto tambm comentrio at o final da linha
/* seqncia de comandos... */
}

A linguagem C formada por pouco mais de 30 palavras-chave, por isso, normalmente necessria a declarao das bibliotecas que contem funes no nativas na linguagem. Como exemplo podemos citar as funes de entrada e sada de dados presentes
na biblioteca padro.
Em C, maisculas e minsculas so diferentes por isso preste ateno na hora de
digitar o programa fonte. Essa caracterstica chamada de case sensitive. Os smbolos /*
(inicio de comentrio) e */ (final do comentrio) indicam comentrios de cdigo e podem
abranger uma ou mais linhas do programa. Para comentar somente uma linha, pode-se
utilizar //.
Todo programa em C consiste em uma ou mais funes. A nica funo que necessariamente precisa estar presente a denominada main(), que a primeira funo a ser
chamada quando a execuo do programa comea. Embora main() no seja tecnicamente
parte da linguagem C, tratada como se fosse. No pode ser usada como nome de varivel, porque pode confundir o compilador.
1.2.3 Primeiro exemplo
O nico caminho para aprender uma nova linguagem de programao escrever programas nesta linguagem, Normalmente os autores utilizam um exemplo clssico no primeiro programa, o famoso - Oi Mundo!
Esse ser o seu primeiro programa, para cria-lo, utilize algum editor de textos para
digitar os fontes e um compilador para gerar o executvel.

#include<stdio.h>
main()
{
printf(Oi mundo! n");
}

 Obs.: Editar esse programa, salv-lo como oi.c,


compil-lo (gcc oi.c) e executlo (./a.out).
Exerccio: Edite este programa, experimente deixar fora do fonte partes como ; por
exemplo, para verificar as mensagens de erro.

10

Um programa C, independentemente de seu tamanho, consiste de uma ou mais "funes que especificam as operaes computacionais que devem ser feita. Funes C so
similares aos procedimentos em Pascal. No nosso exemplo main() uma funo. Normalmente voc pode escolher o nome que quiser, menos para main.
Um mtodo de comunicao de dados entre funes por argumentos. Os parnteses
seguindo o nome da funo envolvem a lista de argumentos, sendo que nesse exemplo,
main uma funo sem argumentos. As chaves envolvem os comandos que formam
a funo, elas so anlogas ao BEGIN-END do Pascal. Uma funo ativada por seu
nome, seguido de uma lista de argumentos entre parnteses. Os parnteses devem estar
presentes mesmo quando no h argumentos.
A linha:
printf (Oi mundo! n);
uma chamada de funo, que chama a funo printf, com o argumento Oi mundo! n.
printf uma funo de biblioteca que imprime no terminal (a menos que outro destino
seja especificado). Nesse caso ela imprime a cadeia de caracteres que compem seu argumento.
Uma seqncia de qualquer nmero de caracteres entre aspas ... chamada cadeia
de caracteres. A seqncia n na cadeia a notao C para o caractere nova linha, que,
quando impresso provoca o avano do cursor do terminal para o inicio da prxima linha.
Se voc omitir o n, voc encontrar sua sada no terminada por uma alimentao de
linha.
printf nunca fornece uma nova linha automaticamente, de forma que mltiplas ativaes pode ser usadas para construir uma linha de sada passo a passo. Nosso primeiro
programa poderia ter sido escrito como:
#include<stdio.h>
main()
{
printf(Oi");
printf(mundo!");
printf( n");
}
O cdigo acima produziria uma sada idntica ao anterior.
O n, apresentado no cdigo anterior, representa um nico caractere. Uma seqncia
de escape tal como n prov um mecanismo geral e extensvel para a representao de
caracteres difceis de obter ou invisveis. Entre outros que C prove, esto:
n para quebra de linha,
t para tabulao,
b para retrocesso,
" para a aspa,

 para a contra-barra propriamente dita,


0 Nulo,
a Alerta (beep).

11

1.2.4 Identao de programas


Os comandos de "C"devem ser escritos em minsculas e devem ser seguidos de um
";", podendo haver mais de um comando na mesma linha, desde que separados por ponto
e vrgula (no abuse disto pois torna o cdigo difcil de compreender). A identao do
programa no obrigatria, mas aconselhada para deixar cdigo-fonte legvel para outros
programadores ou mesmo para o prprio criador.
Os blocos so definidos de uma { at a outra } e equivalem aos blocos de Pascal
definidos pelo "BEGIN"e "END". Dentro de cada bloco pode-se definir um conjunto
de comandos como se fossem um s, sendo que no C pode-se declarar novas variveis
(variveis locais ao bloco) independentemente da posio deste bloco no programa.

{ /* inicio de bloco */

  



 


    
 
 

<Comandos>
} /* fim de bloco */



1.2.5 Reviso de termos


Os termos a seguir sero usados freqentemente nessa apostila.
Cdigo-Fonte: o texto um programa que um usurio pode ler; normalmente interpretado como o programa. O cdigo-fonte a entrada para o compilador C.
Compilador: programa que l o cdigo-fonte de uma determinada linguagem de programao e converte-o em cdigo objeto.
Cdigo-Objeto: traduo do cdigo fonte de um programa em cdigo de mquina que
o computador pode ler e executar diretamente. O cdigo objeto a entrada para o
linkeditor.
Linkeditor: um programa que une funes compiladas separadamente em um programa.
Ele combina as funes da biblioteca C padro com o cdigo que voc escreveu. A
sada do linkeditor um programa executvel.
Biblioteca: o arquivo contendo as funes padro que seu programa pode usar. Essas
funes incluem todas as operaes de E/S como tambm outras rotinas teis.
1.2.6 Exerccios
a. Crie um cdigo fonte, que imprime seu nome, idade, endereo e telefone em linhas
separadas na tela.
Compile e Execute
b. Altere o cdigo anterior para deixar uma linha em branco entre as linhas e colocar um
tab a frente das palavras:
Compile e Execute
c. Crie um cdigo fonte para imprimir :
"exemplo de utilizao de aspas"dia 02 03 2004
Compile e execute

12

2 INTRODUO AO TRATAMENTO DE VARIVEIS

Nesta aula o aluno receber noes do tratamento de variveis em C. Essas noes


iniciam pela descrio dos tipos de dados disponiveis em C, variveis locais, globais e
constantes.

2.1 Identificadores
Os nomes das variveis, funes, rtulos e outros objetos definidos pelo usurio, so
chamados de identificadores. Algumas observaes sobre os identificadores so importantes, como:
O primeiro caractere deve ser uma letra ou um sublinhado. Os caracteres subseqentes devem ser letras, nmeros ou sublinhados. Por exemplo: count, total23 e
peso.
Podem ter qualquer tamanho, mas os seis primeiros caracteres devem ser significativos.
Em C, letras minsculas e maisculas so tratadas diferentemente, portanto "Aula"
diferente de "aula". Case sensitive
Um identificador no pode ser igual a uma palavra chave do C.

2.2 Variveis
Uma varivel uma possio de memria que pode ser identificada atravs de um
nome. Estas podem ter seu contedo alterado por um comando de atribuio e aps a
atribuio mudam de valor.
Toda varivel tem:
um nome (identificador)
um tipo de dado
um valor

13

//...
int a,b,c;
a = 3; // a recebe o valor 3
b = a * 2; // b recebe o dobro do valor de a
c = a + b + 2; // c recebe 11
//...

2.3 Tipos de dados


O C tem 5 tipos bsicos - char, int, float, void e double:
char serve para se guardar caracteres;
int serve para se guardar valores inteiros;
float serve para se guardar valores reais de baixa preciso;
double o ponto flutuante duplo com muito mais preciso;
void o tipo vazio, ou um "tipo sem tipo".
Para cada um dos tipos de variveis existem os modificadores de tipo, que so quatro:
signed, unsigned, long e short. Ao float no se pode aplicar nenhum e ao double pode-se
aplicar apenas o long. Os quatro modificadores podem ser aplicados a inteiros. A inteno
que short e long devam prover tamanhos diferentes de inteiros onde isto for prtico.
int normalmente ter o tamanho natural para uma determinada mquina. Assim, numa
mquina de 16 bits, int provavelmente ter 16 bits. Numa mquina de 32, int dever ter
32 bits. Na verdade, cada compilador livre para escolher tamanhos adequados para o
seu prprio hardware, com a nica restrio de que tipos short int e int devem ocupar pelo
menos 16 bits, tipos long int pelo menos 32 bits, e short int no pode ser maior que int,
que no pode ser maior que long int.
O modificador unsigned serve para especificar variveis sem sinal. Um unsigned int
ser um inteiro que assumir apenas valores positivos. A seguir so relacionados os tipos
de dados permitidos e seus valores mximos e mnimos em um compilador tpico para
um hardware de 16 bits. Tambm nesta tabela est especificado o formato (mscara) que
deve ser utilizado para leitura e impresso dos tipos de dados.

Tipo
hline char
int
unsigned int
long int
unsigned long int
float
double
long double

mascara para e/s Tamanho aproximado(bits)


%c
8
%d ou %i
16
%u
16
%ld
32
%ld
32
%f
32
%lf
64
%lf
128

O tipo long double o tipo de ponto flutuante com maior preciso.

faixa mnima
-127 a 127
-32.767 a 32.767
0 a 65.535
-2.147.483.647 a 2.147.483.647
0 a 4.294.967.295
Seis dgitos de preciso
Dez dgitos de preciso
Dez dgitos de preciso

14

2.4 Operador de Atribuio


Em C, voc pode utilizar o operador de atribuio dentro de qualquer expresso vlida
de C. O simbolo utilizado para atribuio o =. A forma geral do operador de atribuio
:
nome_da_varivel = expresso;

2.5 Variveis Locais x Variveis Globais


Todas as variveis devem ser declaradas. Estas podem ser declaradas em trs lugares
bsicos: dentro de funes, na definio dos parmetros das funes e fora de todas as
funes. Estas so chamadas de variveis locais, parmetros ou variveis globais, respectivamente.
2.5.1 Variveis Locais
As variveis locais devem ser declaradas dentro das funes nas quais sero utilizadas, ou seja, estas no so acessveis a outras funes do programa. Portanto, s podem
ser referenciadas por comandos que esto dentro do bloco no qual as variveis foram
declaradas.

func1(void)
{
int x;
x = 10;
}

func2(void)
{
int x;
x = -199;
}

No exemplo, pode-se verificar que existem duas funes (fun1 e func2). Estas possuem variveis locais com o mesmo nome, x. Dentro da func1, o valor acessvel de x
ser 10. Em func2, o valor ser -199. Ou seja, nenhuma funo tem acesso ao valor das
variveis locais de outras funes.
Ressalva-se que todas as variveis devem ser declaradas no incio das funes, e se
forem declaradas no meio do programa/funo, ocorrer um erro no processo de compilao. Outro fator importante que as variveis locais s "existem"ou esto disponveis
quando a funo est sendo executada, aps a finalizao da execuo da funo, esta rea
de memria liberada e o valor se perde.
2.5.2 Variveis Globais
As variveis globais so reconhecidas por todo o programa, e podem ser utilizadas em
qualquer trecho de cdigo. O valor destas permanece disponvel por toda a execuo do
programa.

15

#include<stdio.h>
int total;
void contas()
{
total = total + 3;
}
main()
{
int i;
total = 0;
for(i=0;i<10;i++)
contas();
printf(Total = %d n",total);
}

Pode-se verificar no cdigo exemplo que a varivel total foi declarada no incio do
programa e esta ser acessvel a todo o programa. Tanto que o seu valor inicializado
com zero na funo principal e que seu valor tambm pode ser alterado pela funo contas.
No final o programa imprimir na tela: "Total: 27".

2.6 Constantes
Constantes so valores declarados que no podem ser alterados durante a execuo do
programa. Portanto, em C as constantes referem-se a valores fixos que o programa no
pode alterar. Esta podem aparecer dentro das expresses ou podem ser declaradas, como
por exemplo:
const valor = 10;
const taxa = 1.5;
const letra = S;
Define
A diretiva define atribui a um identifcador uma string que o substituir toda a vez que
for encontrador no arquivo-fonte. Esta associa um identificador a um valor. O padro C
ANSI refere-se ao identificador como um nome de macro e ao processo de substituio
como substituio de macro (geralmente declarado com letra maiscula, sempre aps a
declarao das bibliotecas). O formato utilizado :
#define nome_da_macro valor.
Veja os exemplos:
#define VERDADEIRO 1
#define FALSO 0
#define MSG "Digite S para Sair"

2.7 Operadores Aritmticos


A lista dos operadores aritmticos de C esto relacionados na tabela abaixo, visto que
estes operadores trabalham da mesma forma que na maioria das outras linguagens.

16

Operador Aritmtico
+
*
/
%
-++

Ao
Subtrao
Adio
Multiplicao
Diviso
Mdulo da diviso (resto)
Decremento
Inremento

A sequir, apresentado um cdigo fonte comentado, com operaes aritmticas.

#include<stdio.h>
main()
{
int x,y;
x = 5;
y = 2;
printf(%d n",x/y);
printf(%d n",x%y);
x ++;
printf(%d n",x);
}

//mostra 2 (truncado)
// mostra 1, o resto da diviso
// x foi incrementado em 1
// mostra 6, pois x foi incrementado

2.8 Operadores Relacionais e Lgicos


No termo operador relacional, relacional refere-se as relaes que os valores podem
ter uns com os outros. Os operadores relacionais retornam verdadeiro (1) ou falso (0).
Para verificar o funcionamento dos operadores relacionais, execute o programa abaixo:

Operador relacional Ao
==
Igual
!=
Diferente
<=
Menor ou igual
>=
Maior ou igual
<
Menor
>
Maior

/* O prximo programa ilustra o funcionamento dos operadores relacionais. */

17

#include<stdio.h>
main()
{
int i,j;
printf( nEntre com 2 nros inteiros:);
scanf(%d %d, &i, &j);
printf( n%d == %d e %d n", i, j, i==j);
printf( n%d != %d e %d n", i, j, i!=j);
printf( n%d <= %d e %d n", i, j, i<=j);
printf( n%d >= %d e %d n", i, j, i>=j);
printf( n%d < %d e %d n", i, j, i < j);
printf( n%d > %d e %d n", i, j, i > j);
}

Para fazer operaes com valores lgicos (verdadeiro e falso) temos os operadores
lgicos:
Operador lgico
&&
|| (pipes)
! (exclamao)

Ao
AND
OR
NOT

O programa a seguir ilustra o funcionamento dos operadores lgicos. Compile-o e


faa testes com vrios valores para i e j:

#include<stdio.h>
main()
{
int i,j;
printf( nEntre com 2 nros inteiros (0 ou 1):);
scanf(%d %d, &i, &j);
printf( n%d AND %d %d n", i, j, i && j);
printf( n%d OR %d %d n", i, j, i || j);
printf( n NOT %d %d n", i,!i);
}

2.9 Operadores Bit a Bit


C suporta um conjunto de operaes bit a bit. Operaes bit a bit refere-se a testar,
atribuir ou deslocar os bits efetivos em um byte ou uma palavra, que correspondem aos
tipos de dados char, int e variantes do padro C. Estas operaes so aplicadas bit a bit.
Abaixo esto relacionados estas operaes.

18

Operador binrio Ao
!(exclamao)
NOT
&
AND
| (pipe)
OR

XOR

Complemento de 1

Desloca p/direita

Desloca pra esquerda


Imagine um nmero inteiro de 16 bits, a varivel i, armazenando o valor 2. A representao binria de i, ser: 0000000000000010 (quinze zeros e um nico 1 na segunda
posio da direita para a esquerda). Pode-se fazer operaes em cada um dos bits deste
nmero. Por exemplo, se fizermos a negao do nmero (operao binria NOT, ou operador binrio ! em C), isto , i, o nmero se transformar em 1111111111111101. As
operaes binrias ajudam programadores que queiram trabalhar com o computador em
baixo nvel.
O uso de operaes de deslocamento de bits podem ser teis quando se decodifica
a entrada de um dispositivo externo. Estes podem realizar operaes de multiplicao e
diviso rapidamente. Um deslocamento direita efetivamente multiplica um nmero por
dois e um esqueda multiplica. Observe o exemplo de funcionamento na Tabela abaixo:
unsigned char x;
x = 7;
x = x 1;
x = x 3;
x = x 2;
x = x 1;
x=x2

x a cada execuo da sentena


00000111
00001110
01110000
11000000
01100000
00011000

Valor de x
7
14
112
192
96
24

2.10 Prioridade das Operaes


As operaes demonstradas possuem prioridades de execuo quando so agrupadas.
Abaixo segue a ordem de prioridade das operaes (iniciam pelas maiores prioridades).
() []
! ++ ++ (tipo) * &
*/%
+
< <= > >=
== !=
&

!
&&
!!
= += -= *= /=

19

2.11 Operaes de entrada e sada


printf
scanf
sprintf e sscanf
As funes que resumem todas as funes de entrada e sada formatada no C so as
funes printf() e scanf(). Um domnio destas funes fundamental ao programador.
2.11.1 printf
Prottipo:
int printf (char *str,...);
As reticncias no prottipo da funo indicam que esta funo tem um nmero de
argumentos varivel. Este nmero est diretamente relacionado com a string de controle
str, que deve ser fornecida como primeiro argumento. A string de controle tem dois
componentes. O primeiro so caracteres a serem impressos na tela. O segundo so os
comandos de formato. Como j vimos, os ltimos determinam uma exibio de variveis
na sada. Os comandos de formato so precedidos de %. A cada comando de formato
deve corresponder um argumento na funo printf(). Se isto no ocorrer podem acontecer
erros imprevisveis no programa. Abaixo apresentamos a tabela de cdigos de formato:
Cdigo
%c
%d e %i
%e
%E
%f
%g
%G
%o
%s
%u
%x
%X
%%
%p

Formato
Um caracter (char)
Um nmero inteiro decimal (int)
Nmero em notao cientfica com o "e"minsculo
Nmero em notao cientfica com o "e"maisculo
Ponto flutuante decimal
Escolhe automaticamente o melhor entre %f e %e
Escolhe automaticamente o melhor entre %f e %E
Nmero octal
String
Decimal "unsigned"(sem sinal)
Hexadecimal com letras minsculas
Hexadecimal com letras maisculas
Imprime um %
Ponteiro

Exemplo:
Cdigo
printf ("Um %%%c %s",c,"char");
printf ("%X %f %e",107,49.67,49.67);
printf ("%d %o",10,10);

Imprime
Um %c char
6B 49.67 4.967e1
10 12

possvel tambm indicar o tamanho do campo, justificao e o nmero de casas


decimais. Para isto usa-se cdigos colocados entre o % e a letra que indica o tipo de
formato.
Um inteiro indica o tamanho mnimo, em caracteres, que deve ser reservado para a
sada. Se colocarmos ento %5d estamos indicando que o campo ter cinco caracteres de
comprimento no mnimo. Se o inteiro precisar de mais de cinco caracteres para ser exibido

20

ento o campo ter o comprimento necessrio para exibi-lo. Se o comprimento do inteiro


for menor que cinco ento o campo ter cinco de comprimento e ser preenchido com
espaos em branco. Se se quiser um preenchimento com zeros pode-se colocar um zero
antes do nmero. Temos ento que %05d reservar cinco casas para o nmero e se este
for menor ento se far o preenchimento com zeros.
O alinhamento padro direita. Para se alinhar um nmero esquerda usa-se um
sinal - antes do nmero de casas. Ento %-5d ser o nosso inteiro com o nmero mnimo
de cinco casas, s que justificado a esquerda.
Pode-se indicar o nmero de casas decimais de um nmero de ponto flutuante. Por
exemplo, a notao %10.4f indica um ponto flutuante de comprimento total dez e com 4
casas decimais. Entretanto, esta mesma notao, quando aplicada a tipos como inteiros
e strings indica o nmero mnimo e mximo de casas. Ento %5.8d um inteiro com
comprimento mnimo de cinco e mximo de oito.
Exemplo:
Cdigo
printf("%-5.2f",456.671);
printf ("%5.2f",2.671);
printf ("%-10s","Ola");

Imprime
|456.67 |
| 2.67|
|Ola
|

Obs.: O "pipe"( | ) indica o incio e o fim


do campo mas no sero escritos na tela.
2.11.2 scanf
Prottipo:
int scanf (char *str,...);
A string de controle str determina, assim como com a funo printf(), quantos parmetros a funo vai necessitar. Devemos sempre nos lembrar que a funo scanf() deve
receber ponteiros como parmetros. Isto significa que as variveis que no sejam por
natureza ponteiros devem ser passadas precedidas do operador &. Os especificadores de
formato de entrada so muito parecidos com os de printf(). Os caracteres de converso
d, i, u e x podem ser precedidos por h para indicarem que um apontador para short ao
invs de int aparece na lista de argumento, ou pela letra l (letra ele) para indicar que que
um apontador para long aparece na lista de argumento. Semelhantemente, os caracteres
de converso e, f e g podem ser precedidos por l para indicarem que um apontador para
double ao invs de float est na lista de argumento.
Cdigo
%c
%d e %i
%hi
%li
%e
%f
%lf
%s
%h
%x
%p

Formato
Um caracter (char)
Um nmero inteiro decimal (int)
Um short it
Um long int
Nmero em notao cientfica
Ponto flutuante decimal
Um double
String
Inteiro curto
Hexadecimal com letras minsculas
Ponteiro

21

2.11.3 sprintf e sscanf


sprintf e sscanf so semelhantes a printf e scanf. Porm, ao invs de escreverem na
sada padro ou lerem da entrada padro, escrevem ou leem em uma string. Os prottipos
so:
int sprintf (char *destino, char *controle, ...);
int sscanf (char *destino, char *controle, ...);
Estas funes so muito utilizadas para fazer a converso entre dados na forma numrica e sua representao na forma de strings. No programa abaixo, por exemplo, a varivel
i "impressa"em string1. Alm da representao de i como uma string, string1 tambm
conter "Valor de i=".

#include<stdio.h>
main()
{
int i;
char string1[20];
printf( nEntre com 1 nros inteiros:);
scanf(%d, &i);
sprintf(string1, Valor de i = %d", i);
puts(string1);
}

J no programa abaixo, foi utilizada a funo sscanf para converter a informao armazenada em string1 em seu valor numrico:

#include<stdio.h>
main()
{
int i,j,k;
char string1[]=10 20 30;
sscanf(string1,"%d %d %d", &i, &j, &k);
printf("Valores lidos: %d, %d, %d", i, j, k);
}

2.12 Exerccios
1. Faa um programa que receba dois valores do tipo inteiro e efetue as quatro operaes
bsicas, mostrando o resultado no final das quatro.
2. Faa um programa que receba o nome do usurio, quatro notas e calcule a mdia do
aluno. A frmula da mdia final : (nota1+2*nota2+3*nota3+4*nota4)/10.
3. Faa um programa que solicite o tamanho do lado de um quadrado e calcule a rea do
mesmo, mostrando o resultado.

22

4. Programa para calcular a rea de um tringulo. Receber a informao da base e da


altura em centmetros. Ao final do programa alm de mostrar o resultado da rea
calculada, listar tambm o calculo para 5 figuras maiores cujas dimenses so o
dobro da anterior e 5 figuras menores cujas dimenses so a metade da anterior,
partindo da base e altura informadas.
5. Faa um programa que solicite a data atual e a data de nascimento do usurio e calcule a sua idade em dias. Obs.: Para saber se um ano bissexto (366 dias),
 
use a segunte formula:

_




 
 




 

  
  
   


6. Programa para converso de moedas. Inicialmente ler o valor da cotao de 1 dolar


para Real. A seguir pedir o valor em dolar e responder o valor convertido para Real.

23

3 COMANDOS DE CONTROLE E REPETIO

3.1 if/else
Execuo condicional de comandos. A instruo if causa a execuo de uma ou de
um conjunto de instrues, dependendo do valor resultante de uma expresso avaliada.
Sintaxe:
if (expresso)
comando1;
[else]
[comando2; ]
Se a expresso for verdadeira, executa o comando1, caso contrrio executa o comando2. Se comando1 ou comando2 tiverem mais de uma instruo deve-se criar blocos
usando e .
Exemplo:
if (n != 0)
x = a*b/n;
else {
n = x*x;
x = a*b/n;
}

As instrues de execuo condicional dependem da avaliao de uma expresso condicional. Esta expresso composta por vrias operaes, que so efetuadas atravs dos
operadores lgicos e relacionais (ou mesmo atribuies e operaes matemticas), devolvendo um valor booleano TRUE ou FALSE. O C no possui o tipo boolean e no atribui
conceito abstrato para VERDADEIRO e FALSO. Para o C V ou F representado por um
valor inteiro, com o seguinte significado:
0 - FALSO (FALSE),
No Zero - VERDADEIRO (TRUE).
Ou seja, para o C, o valor 0 considerado FALSO, enquanto que todos os demais valores (-1, 1, 2, 1000, -1000, etc) so considerados VERDADEIROS. Quando o C precisa
CALCULAR uma expresso, atribuindo o conceito de V ou F, ele usar SEMPRE o valor
1 para Verdadeiro e o valor 0 para FALSO. Assim fica fcil entender o que ocorre nestes
exemplos:

24

main()
{
int x, y, r;
x = 20;
y = 10;
r = x > y; /* Sim, o x maior que y. Ento esta sentena
considerada como VERDADEIRA. O C ir avaliar ela como
tendo resultado 1 (VERDADEIRO). r recebe 1, portanto */
if (x)
{ // x vale 20. 20 para o C conceito de VERDADEIRO.
r = 0;
}
r = y + ((x>y) && (y > 0));
/* complicou, no? Temos uma sentena AND que ser
calculada como sendo VERDADEIRA (1) ou FALSA (0).
Como x maior que y (V, 1) e y maior que 0 (V),
a sentena (x>y) && (y > 0) VERDADEIRA,
valendo 1. y + 1 = 11. r receber 11.*/
}

Devido clausula else ser opcional, pode existir uma ambigidade no uso de ifelse
aninhado. O compilador resolve isto associando o else ao ltimo if sem else. Por exemplo:
if (n>0)
if (a>b)
z=a;
else
z=b;

Se a>b, ento z=a, quando n>0. Se a<=b, ento z=b, quando n>0. Se n<=0, o valor de
z no ser alterado nesta poro de cdigo.
Entretanto se tivermos:
if (n>0)
{
if (a>b)
z=a;
}
else
z=b;

Se a>b, ento z=a, quando n>0. Se n<=0, ento z=b. Se n>0 e a<=b, o valor de z no
ser alterado nesta poro de cdigo.

25

3.2 while
Enquanto a condio descrita pela expresso for satisfeita (ou seja, verdadeira), o
comando ser repetido. O comando somente ser executado se a expresso condicional
for verdadeira. A avaliao da expresso realizada da mesma forma que no comando
if. O comando while o nico e o principal comando de repetio realmente necessrio,
sendo que pode substituir qualquer outra construo do tipo: for, repeat/until, do/while,
goto ...).
Sintaxe:
while (expresso)
comando1;
Exemplo: contagem de bits setados na varivel n.
bits = 0;
while (n != 0)
{
if (n & 1)
bits++;
n = 1;

Exemplo: imprimir os nmeros impares de 3 at 21 (inclusive).


i = 3;
while ( i <= 21 )
{
printf(%d n, i);
i = i + 2;
}

3.3 for
O comando for serve para a execuo de um nmero fixo de vezes (ou no), enquanto
uma varivel percorre uma determinada faixa de valores. Esta varivel chamada de
varivel de ndice.
Sintaxe:
for (inicio; condio; modific)
comando;
Onde temos "incio"como sendo uma expresso que ir gerar o valor inicial da varivel de ndice utilizada pelo comando. A "condio"ir indicar uma condio para o
prosseguimento do lao (enquanto tal condio for verdadeira ir repetir o lao). E finalmente "modific"ser o comando dado a cada execuo do lao, sendo este realizado ao
final de um lao do for, modificando o valor da varivel de ndice, antes de um novo teste
da condio. Cada um destes elementos (incio, condio e comando) pode ainda estar
dividido em sries de comandos, como nas expresses do if.
Exemplo: nmeros mpares de 3 a 21, com for:
for (i = 3; i <= 21; i = i+2)
printf("%d n", i);

26

Para criarmos um lao infinito (sem fim) podemos fazer um comando da seguinte
forma: for(;;) - comando sem expresses de controle. O comando for equivalente a
seguinte estrutura:
while (condio)
{
comando;
modific;
}

3.4 do/while
O comando do/while o inverso do comando while, ou seja, o teste executado ao
final deste ao invs de ser no incio. Este comando tambm equivalente ao comando
repeat/until (Pascal) s que a expresso avaliada em um estaria negada em relao ao
outro.
Sintaxe:
do
comando; } while (expresso);
O comando ser executado e depois ser testada a condio dada pela expresso, e
caso esta seja verdadeira (TRUE) ser novamente executado o comando.

3.5 Break e Continue


Break causa a sada no meio de um lao (para comandos: for, while, do/while, switch).
Provoca a antecipao do fim do lao. muito usado com o comando case como ser visto
mais adiante. Continue serve para a re-execuo do lao, a partir do teste. Ir causar a
reinicializao do lao (no funciona com o switch). Um exemplo prtico do seu uso pode
ser visto no exemplo a seguir:
while ( x <= valmax)
{
printf ("Entre com um valor:");
scanf ("%d",&val);
if (val < 0)
continue;
}

3.6 switch/case
Faz uma associao de valores com comandos a executar. Conforme o valor dado,
executa um certo nmero de instrues. Serve como uma estrutura mais sofisticada que
os ifs encadeados.
Sintaxe:
switch (varivel)
{
case <valor1> : <comando1>;
case <valor2> : <comando2>;

27

<comando3>;
...
[ default : comando4; ]
}
No comando switch no possvel definir intervalos para os quais o comando ser
executado, temos que definir os valores textualmente, um a um. Os valores utilizados no
case devem ser do tipo inteiro ou char.
O uso do comando break muito importante quando associado ao switch, pois caso
este no seja usado a cada case, ser feita a execuo de todos os comandos at encontrar
o fim do switch, sendo executado inclusive o default, se houver. Por isso a estrutura
comumente usada em um comando case :
case A:
x++;
break;
case b:
case B:
y++;
break;
...

3.7 Expresses Condicionais


As expresses condicionais se apresentam da seguinte forma:
expr1 ? expr2 : expr3
Esta expresso equivalente a:
se expr1 // Onde: expr1 -> Condio de teste
expr2 // expr2/expr3 -> Valor
retornado seno expr3
Portanto expr2 ser o valor calculado se expr1 for verdadeiro e expr3 ser o valor
calculado se expr1 for falso.
Exemplo:
b = ((x == y)?x:y);

3.8 Exerccios:
1. Escrever um programa que solicite dois numeros ao usurio. O programa deve comparar os valores e imprimir na tela os dois nmeros digitados, a soma deles, o maior e
o menor deles.
2. Escrever um programa que recebe trs numeros inteiros (a, b e cod) e imprima na tela:
a+b, se cod >= 0;
a-b, se cod < 0.
3. Fazer uma funo que receba um nmero (do teclado) e retorne o fatorial deste nmero
(exemplo 5!= 5*4*3*2*1;), usando comandos de repetio (Lembre que os fatoriais
de 0 e de 1 so iguais a 1). Deve pedir para o usurio repetir a entrada se o nmero
que ele digitou for negativo. Deve ser capaz de calcular fatoriais maiores que 65535,
limite para um inteiro.

28

4. Faa um programa completo que leia do teclado 10 nmeros inteiros e depois imprima:
a) A soma de todos os elementos
b) O maior e o menor elemento
5. Escrever um trecho de cdigo, usando atribuio condicional, que teste o contedo de
duas variveis e atribua o maior valor a uma terceira varivel.
6. Faa um programa para calcular o valor de , dado por:

       
    
    
   

onde n fornecido pelo usurio;


7. Escreva um programa que l um valor
escreve o valor de , dado por:

 

inteiro e positivo, logo em seguida, calcule e

              

8. O valor aproximado de

pode ser calculado usando a srie:

  
  

 

 
   


 !
#"$  , implemente um programa que calcule o valor de 

Sendo
, baseado
nos n primeiros elementos dessa srie. O n deve ser informado pelo usurio, quanto
maior esse numero, mais preciso ser o valor de .

9. Escreva um programa que apresente a srie de Fibonacci at o n-simo elemento, esse


limite deve ser informado pelo usurio. A srie de Fibonacci formada pela sequncia: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...
10. O que faz o trecho de cdigo a seguir?
int a,b,c;
...
c = (a>=0)?(b>=0):(b<0);

29

4 MATRIZES

Uma matriz uma coleo de variveis do mesmo tipo, e esta referenciada por um
nome comum. Cada elemento de uma matriz acessado atravs de um ndice. O ndice
0 corresponde ao primeiro elemento de uma matriz, e o ndice mais alto, representa o
ltimo elemento de uma matriz.
Basicamente existem alguns tipos de matrizes:
Matrizes Unidimensionais: So matrizes de apenas uma dimenso, e so geralmente chamadas de vetores ou listas (estticas).
Matrizes Bidimensionais: So matrizes de duas dimenses.
Matrizes Multidimensionais: So matrizes de n dimenses.
A forma geral de se declarar uma matriz unidimensional :
tipo nomevar [tamanho];
Por exemplo, se quisermos declarar um vetor (matriz unidimensional) com o nome
teste que armazena 10 nmero inteiros, teramos que definir o tipo (int) e o tamanho do
vetor (10). Ressalva-se que o primeiro ndice de um vetor em C sempre ser o 0. Ou seja,
os ndices deste vetor iriam de 0 a 9, onde tm-se 10 posies. A declarao do vetor
ficaria assim: int teste[10];
Criando um vetor de 3 posies do tipo double, pode-se analisar como fazer o acesso
a cada ndice. Vejamos:
Exemplo 1:
main()
{
double vetor[3];
vetor[0]=3.9;
vetor[1]=4.9;
vetor[2]=0.7;
printf("O valor do primeiro elemento eh:%lf n",vetor[0]); /*Sera impresso 3.9*/
printf("O valor do ultimo elemento eh:%lf n",vetor[2]); /*Sera impresso 0.7*/
}

Quando o C v uma declarao como esta ele reserva um espao na memria suficientemente grande para armazenar o nmero de clulas especificadas em tamanho. Por
exemplo, se declararmos:

30

float exemplo [20];


O compilador C reservar 4x20=80 bytes. Estes bytes so reservados de maneira
contgua. Alm disso, C no verifica se o ndice que voc usou est dentro dos limites
vlidos. Este um cuidado que voc deve tomar.
Se o programador no tiver ateno com os limites de validade para os ndices ele
corre o risco de ter variveis sobrescritas ou de ver o computador travar. Logo, o programa
ir compilar e executar se voc programou algo, como: exemplo[400]=32;.
Para verificarmos a funcionalidade dos vetores, vamos analisar mais um exemplo.
Exemplo 2:
#include <stdio.h>
main ()
{
int num[100]; /* Declara um vetor de inteiros de 100 posicoes */
int count=0;
int totalnums;
do
{
printf (" nEntre com um numero (-999 p/ terminar):");
scanf ("%d",&num[count]);
count++;
} while (num[count-1]!=-999);
totalnums=count-1;
printf (" n Os nmeros que voc digitou foram: n");
for (count=0;count<totalnums;count++)
printf ("%d n",num[count]);
}
No exemplo acima, o inteiro count inicializado em 0. O programa pede pela entrada
de nmeros at que o usurio entre com o Flag -999. Os nmeros so armazenados no
vetor num. A cada nmero armazenado, o contador do vetor incrementado para na
prxima iterao escrever na prxima posio do vetor. Quando o usurio digita o flag,
o programa abandona o primeiro loop e armazena o total de nmeros gravados. Por fim,
todos os nmeros so impressos. bom lembrar aqui que nenhuma restrio feita
quanto a quantidade de nmeros digitados. Se o usurio digitar mais de 100 nmeros,
o programa tentar ler normalmente, mas o programa os escrever em uma parte no
alocada de memria, pois o espao alocado foi para somente 100 inteiros. Isto pode
resultar nos mais variados erros no instante da execuo do programa.

4.1 Strings
Strings so vetores de caracteres, chars. As strings so o uso mais comum para os
vetores. As strings tm o seu ltimo elemento como um 0. A declarao geral para
uma string : char nome-da-string [tamanho];

Uma constante string uma lista de caracteres entre aspas. Por exemplo: Oi Mundo.
Neste caso, no necessrio adicionar o nulo no final das constantes strings manualmente

31

(o compilador faz isso para voc).


possvel solicitar ao usurio uma determinada string e sua leitura pode ser feita de
duas formas: utilizando a funo scanf ou utilizando a funo gets. Porm, a funo scanf
tem alguma dificuldade em lidar com os espaos no meio de uma string, por isso vamos
utilizar a funo gets. Abaixo segue um exemplo para entrada de strings.
Exemplo 3:
#include <stdio.h>
main ()
{
char string1[100], string2[100];
printf (" n Digite o seu nome: ");
gets (string1);
printf (" n Digite o seu sobrenome: ");
gets (string2);
printf (" n Seu nome completo eh: %s %s n",string1,string2);
}

Existem diversas funes para trabalharmos com strings, estas necessitam que no cabealho seja declarada a biblioteca <string.h>.
A tabela 4.1 apresenta as principais funes de manipulao e tratamento de strings:
Nome
strcpy(s1,s2)
strcat(s1,s2)
strlen(s1)
strcmp(s1,s2)
strchr(s1,ch)
strstr(s1,s2)

Funo
Copia s2 em s1.
Concatena s2 ao final de s1.
Retorna o tamanho de s1.
Retorna 0 se s1=s2; menor que 0 se s1<s2; maior que 0 se s1>s2.
Retorna um ponteiro para a primeira ocorrncia de ch em s1.
Retorna um ponteiro para a primeira ocorrncia de s2 em s1.
Tabela 4.1: Manipulao de Strings

Abaixo segue um exemplo de utilizao de algumas funes, as quais utilizam a biblioteca string.h. Cabe ressaltar que existem ainda diversas funes j desenvolvidas as
quais fazem parte da biblioteca. No exemplo, o contedo da string s1 lido do usurio,
e o contedo de s2 atribudo atravs da funo strcpy. A funo strlen ir imprimir o
tamanho de cada string, e a funo strcmp ir comparar se os contedos de s1 e s2 esto
iguais.

32

Exemplo 4:
#include<stdio.h>
#include<string.h>
main()
{
char s1[80],s2[80];
printf (" n Digite uma string qualquer: ");
gets(s1);
strcpy(s2,"Programa Exemplo");
printf(s2);
printf(" n Tamanho: %d %d",strlen(s1),strlen(s2));
if (!strcmp(s1,s2))
printf(" n As strings so iguais n");
else printf (" n As strings so diferentes! n");
}

4.2 Matrizes Bidimensionais


Quando trabalha-se com C sabe-se que este suporta matrizes multidimensionais. As
matrizes bidimensionais so a forma mais simples das matrizes multidimensionais.
A forma geral de se declarar uma matriz unidimensional :
tipo nomevar [linha][coluna];
muito importante ressaltar que, nesta estrutura, o ndice da esquerda indexa as linhas
e o da direita indexa as colunas.
Quando vamos preencher ou ler uma matriz no C o ndice mais direita varia mais
rapidamente que o ndice esquerda.
Mais uma vez bom lembrar que, na linguagem C, os ndices variam de zero ao valor
declarado, menos um; mas o C no vai verificar isto para o usurio. Manter os ndices na
faixa permitida tarefa do programador.
Se declararmos int num[4][3], e inicializarmos toda a matriz com o contedo zero e
apenas a posio 1,2 recebesse um valor diferente (num[1][2]=9;), a matriz poderia ser
mostrada assim:
0
0
0
0

0
0
0
0

0
9
0
0

Abaixo damos um exemplo do uso de uma matriz, onde a matriz mtrx preenchida,
seqencialmente por linhas, com os nmeros de 1 a 200.

33

Exemplo 5:
#include <stdio.h>
main ()
{
int mtrx [20][10];
int i,j,count;
count=1;
for (i=0;i<20;i++)
for (j=0;j<10;j++)
{
mtrx[i][j]=count;
count++;
printf(" n Linha:%d Col:%d INT:%d n",i,j,mtrx[i][j]);
}
}

4.3 Matrizes de Strings


Matrizes de strings so matrizes bidimensionais. Se fizermos um vetor de strings
estaremos fazendo uma lista de vetores.
Esta estrutura uma matriz bidimensional de chars. Podemos ver a forma geral de
uma matriz de strings como sendo:
char nome [nrodestrings][compr-das-strings];
Para acessar cada string basta usar apenas o primeiro ndice. Ento, para acessar uma
determinada string faa:
nome [ndice]
Aqui est um exemplo de um programa que l 5 strings e as exibe na tela:
Exemplo 6:
#include <stdio.h>
main ()
{
char strings [5][100];
int count;
for (count=0;count<5;count++)
{
printf (" n Digite uma string: ");
gets (strings[count]);
}
printf (" n As strings que voce digitou foram: n");
for (count=0;count<5;count++)
printf ("%s n",strings[count]);
}

4.4 Matrizes Multidimensionais


O uso de matrizes multidimensionais na linguagem C simples. Sua forma geral :

34

tipo nome [tam1][tam2] ... [tamN];


Uma matriz N-dimensional funciona basicamente como outros tipos de matrizes. Basta
lembrar que o ndice que varia mais rapidamente o ndice mais direita.

4.5 Inicializao de Matrizes


Podemos inicializar matrizes, assim como podemos inicializar variveis. A forma
geral de uma matriz como inicializao :
tipo nome [tam1][tam2] ... [tamN] = {lista-de-valores};
A lista de valores composta por valores (do mesmo tipo da varivel) separados por
vrgula. Os valores devem ser dados na ordem em que sero colocados na matriz. Abaixo
vemos alguns exemplos de inicializaes de matrizes:
int matrx [3][4] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
char str [10] = { J, o, a, o, 0};
char strvect [3][10] = { "Joao", "Maria", "Jose"};

4.6 Exerccios:
1. A avaliao em um colgio feita atravs de 3 notas. Como a turma pequena, existem
apenas 4 alunos inscritos. Faa um programa que receba as notas dos 4 alunos e
indique a mdia de cada um deles, mostrando as suas notas individualmente. Depois
disso, o programa ainda deve indicar a maior mdia.
2. Faa um programa que tenha um vetor de 20 posies de inteiros positivos. Este deve
receber do usurio os valores, valid-los e armazen-los. O programa deve apenas
imprimir na tela os nmeros inseridos em posies de ndices mpares do vetor.
3. Faa um programa que recebe 8 nmeros e o armazene em um vetor (entrada). Aps
a leitura dos nmeros, deve ser armazenado em outro vetor a raiz quadrada de cada
nmero do vetor de entrada. Imprima as raizes na tela.
4. Fazer o programa que leia o nome do usurio e diga quantas letras este nome tem.
5. Fazer um programa que recebe duas palavras e diz se estas strings so iguais.
6. Fazer um programa que recebe quatro nomes e diz quantos deles comeam com a letra
L e quantos com a letra T.
7. Fazer um programa que recebe separadamente o primeiro nome, o segundo nome e o
ltimo nome de uma pessoa. O programa deve concatenar estes nomes e imprimi-lo
no final.
8. Fazer o programa que leia uma matriz 4x4 e imprima a mdia dos elementos.
9. Fazer o programa que leia uma matriz 6x6 e imprima a mdia dos elementos da diagonal principal (linha=coluna) e tambm a mdia dos elementos da diagonal secundria (linha + coluna == nro_de_linha ).
10. Fazer um programa que recebe uma matriz A 2x2 e uma matriz B 2x2, e crie uma
terceira matriz C 2x2, a qual composta pelos elementos multiplicados de AB.

35

11. Fazer uma programa que gere (sem o usurio digit-la) e imprima na tela a seguinte
matriz:
1
1
1
1
1
1

1
2
2
2
2
1

1
2
3
3
2
1

1
2
3
3
2
1

1
2
2
2
2
1

1
1
1
1
1
1

36

5 ESTRUTURAS DEFINIDAS PELO USURIO

5.1 Estruturas
Matrizes so estruturas de dados homogneos, isto , podem conter colees de dados
do mesmo tipo (todos int, todos float, todos char). Na vida real encontramos muitas
situaes onde temos colees de dados que so de tipos diferentes. Como exemplo
temos uma ficha de cadastro de funcionrio, uma cdula de identidade, uma inscrio em
uma concurso, uma cadastro de usurio em um site, etc.
Num cadastro de usurio temos dados como nome, endereo, telefone, e-mail, data
de nascimento, entre outros. Pode-se notar que esses dados so de tipos diferentes. Para
agrupar esses dados no nos serve uma matriz. H necessidade de uma estrutura de dados
heterogneos, definida pelo usurio.
As estruturas (struct) so agrupamentos de dados, que definem um novo tipo de dado
mais complexo, formado por tipos de dados mais simples.
struct nome_do_tipo_da_estrutura {
tipo-var nome-var;
tipo-var nome-var2;
...}variveis_estrutura;

O nome_do_tipo_da_estrutura o nome para a estrutura. As variveis_estrutura so


OPCIONAIS e seriam nomes de variveis que o usurio j estaria declarando e que seriam
do tipo nome_do_tipo_da_estrutura.
Exemplo:
struct data {
int dia;
int mes;
int ano;
int dia_ano;
char nome-mes[10];
};
struct data hoje;

A utilizao de estruturas no C semelhante ao record do pascal.


Referncia a um elemento da estrutura:

37

nome_estrut.elemento > hoje.dia = 23;


Exemplo 2:
#include <stdio.h>
#include <string.h>

 _____estrutura de endereo:
struct tipo_endereco {
char rua [50];
int numero;
char bairro [20];
char cidade [30];
char sigla_estado [3];
long int CEP;
};
*Estrutura ficha_pessoal
para adicionar os dados pessoais de algum:*
struct ficha_pessoal {
char nome [50];
long int telefone;
struct tipo_endereco endereco;
};

 _____Programa Principal____
void main (void){
struct ficha_pessoal ficha;
strcpy(ficha.nome,"Luiz Osvaldo Silva");
ficha.telefone=33332234;
strcpy(ficha.endereco.rua,"Rua dos Flores");
ficha.endereco.numero=10;
strcpy(ficha.endereco.bairro,"Menino Deus");
strcpy(ficha.endereco.cidade,"Porto Alegre");
strcpy(ficha.endereco.sigla_estado,"RS");
ficha.endereco.CEP=90000000;
}
Esse programa declara uma varivel ficha do tipo ficha_pessoal e preenche os seus dados. O exemplo mostra como podemos acessar um elemento de uma estrutura: basta usar
o ponto (.). Assim, para acessar o campo telefone de ficha, escrevemos: ficha.telefone
= 33332234; Como a struct ficha pessoal possui um campo, endereo, que tambm
uma struct, podemos fazer acesso aos campos desta struct interna da seguinte maneira:
ficha.endereco.numero = 10; ficha.endereco.CEP=90000000; Desta forma, estamos acessando, primeiramente, o campo endereco da struct ficha e, dentro deste campo, estamos
acessando o campo numero e o campo CEP.
Caractersticas das estruturas:

38

No podem ser inicializadas na declarao ou copiadas atravs de atribuio;


Podem ser acessadas com o auxlio de pointers. Permitem a criao de listas encadeadas.
Tambm podem ser declarados matrizes de estruturas, da mesma forma que uma matriz de inteiros ou caracteres. A forma de acesso semelhante:
struct data st[10]; /*um vetor da estrutura de 10 elementos */
st[0].dia=2;
sprintf(st[0].nome_ms, "Janeiro");
...

5.1.1 Exerccios
a) Faa um programa que define um tipo para alunos com os seguintes campos: nome
(20 caracteres), cdigo (10 caracteres), notas de 3 provas e mdia final. O programa
dever ler da entrada padro os dados de 4 alunos, calcular a mdia individual de
cada aluno e a mdia geral dos alunos.
b) Modifique o exerccio anterior, mas permita que o usurio fornea antes o nmero
total de alunos que deseja digitar.
c) Considere uma bilhete de passagem de nibbus, conforme mostrado na tabela 5.1. Primeiro - Defina uma estrutura de dados de nome Passagem. Segundo - Considerando
uma onibus de 48 lugares, defina um vetor de Passagens.

VIAO MONTENEGRO S/A


Nmero:______
Origem:___________________
Data: __ __ ____
Assento:______
Valor da Passagem: R$____________

Nome da Empresa:___________
Destino:___________________
Horrio:____:____
Distncia: ____km

Tabela 5.1: Bilhete de passagem

5.2 Unies
Uma declarao union determina uma nica localizao de memria onde podem
estar armazenadas vrias variveis diferentes. A declarao de uma union semelhante
declarao de uma estrutura:

39

union nome_do_tipo_da_union {
tipo_1 nome_1;
tipo_2 nome_2;
...
tipo_n nome_n;
} variaveis_union;

Como exemplo, vamos considerar a seguinte unio:


union angulo {
float graus;
float radianos;
};

Nela, temos duas variveis (graus e radianos) que, apesar de terem nomes diferentes,
ocupam o MESMO local da memria. Isto quer dizer que s gastamos o espao equivalente a um nico float. Unies podem ser feitas tambm com variveis de diferentes tipos.
Neste caso, a memria alocada corresponde ao tamanho da maior varivel no union. Veja
o exemplo:
#include <stdio.h>
#define GRAUS G
#define RAD R
union angulo {
int graus;
float radianos;
};
main()
{
union angulo ang;
char op;
printf(" n Numeros em graus ou radianos? (G/R):");
scanf("%c",&op);
if (op == GRAUS) {
ang.graus = 180;
printf(" nAngulo: %d n",ang.graus);
}
else if (op == RAD){
ang.radianos = 3.1415;
printf(" nAngulo: %f n",ang.radianos);
}
else printf(" nEntrada invalida!! n");
}

40

5.3 Enumeraes
Numa enumerao podemos dizer ao compilador quais os valores que uma determinada varivel pode assumir. Sua forma geral :
enum nome_do_tipo_da_enumerao
{
lista_de_valores
} lista_de_variveis

Exemplo:
#include <stdio.h>
enum dias_da_semana {
segunda,
terca,
quarta,
quinta,
sexta,
sabado,
domingo};
main()
{
enum dias_da_semana d1,d2;
d1=segunda;
d2=sexta;
if (d1==d2)
printf (O dia o mesmo);
else printf (So dias diferentes);
}

Voc deve estar se perguntando como que a enumerao funciona. Simples, o compilador pega a lista que voc fez de valores e associa, a cada um, um nmero inteiro.
Ento, ao primeiro da lista, associado zero, ao segundo 1 e assim por diante. As variveis declaradas so ento variveis inteiras.

41

6 FUNES

6.1 Modularidade
Modularidade a tcnica de programar, desenvolvendo um programa a partir de pequenas partes ou mdulos. Em C, construir um mdulo significa construir uma funo.
Inicialmente, modularizar um programa parece dificultar a programao. Mas o que
acontece no desenvolver de qualquer programa o contrrio. As vantagens de se modularizar so: economia de tempo de criao do programa, economia de tempo de manuteno
do programa, reutilizao de mdulos, organizao do cdigo e construo de bibliotecas.

6.2 Forma de uma Funo


Funes so blocos de construo de C e o local onde toda atividade ou tarefa do
programa se realiza. A forma geral de uma funo :

especificador_do_tipo nome_da_funo (lista de parmetros)


{
corpo da funo
}

O especificador_de_tipo especifica o tipo de valor que o comando return da funo


ir devolver. Se nenhum tipo especificado, o compilador assume que a funo devolve
um inteiro. A lista de parmetros indica o nome das variveis e seus tipos associados.
Estas so separadas por vrgula e e indicam os argumentos da funo. A declarao de
parmetros uma lista com a seguinte forma geral:

tipo nome1, tipo nome2, ... , tipo nomeN

No corpo da funo as entradas so processadas, sadas so geradas, ou seja, toda a


tarefa corresponde desta funo.
Abaixo segue um exemplo de criao de uma funo em C. Neste exemplo, a funo
recebe um nmero x e imprime a raiz quadrada do mesmo.

42

#include<stdio.h>
#include<math.h>
void raiz(double x)
{
printf("%lf",sqrt(x));
}
main()
{
double nro;
printf("Digite um numero");
scanf("%lf",&nro);
raiz(nro);
}

6.3 Regras de Escopo


As regras de escopo de uma linguagem so as regras que governam se uma poro de
cdigo conhece ou tem acesso a outra poro de cdigo ou dados. Ou seja, o escopo o
conjunto de regras que determinam o uso e a validade de variveis nas diversas partes do
programa.
Para trabalharmos corretamente com as regras de escopo, cabe lembrar o conceito de
variveis locais e variveis globais. Variveis locais so aquelas tm validade dentro do
bloco no qual so declaradas, ou seja, s existem enquanto o bloco est sendo executado.
No caso de criarmos uma variveil dentro de uma funo, esta s ser acessvel dentro
desta funo e poderemos chamar ela de varivel local a funo. J as variveis globais
so aquelas declaradas fora das funes do programa, e so acessveis atravs de todos os
mdulos do programa. Estas so alocadas no incio do programa, e s so desalocadas no
trmino do mesmo.

6.4 Argumentos de Funes


Se uma funo utiliza argumentos, necessrio declarar as variveis que aceitem os
valores dos argumentos. Estas variveis so chamadas de parmetros formais da funo,
se comportando como variveis locais dentro da mesma. Estas so alocadas no incio de
uma funo, e desalocadas na sua sada.
importante salientar que os parmentros devem ser passados na ordem respectiva
e compatibilidade. Foi implementado um exemplo simples, para verificarmos a importncia da passagem de parmetros. Temos uma funo que calcula a diferenca entre dois
nmeros, e imprime na tela. Vejamos o exemplo:

43

#include<stdio.h>
void diferenca(int x, int y)
{
printf("%d",x-y);
}
main()
{
diferenca(10,0); /*Imprimir 10 na Tela*/
diferenca(0,10); /* Imprimir -10 na Tela*/
}

6.5 O Comando return


O comando return utilizado dentro das funes visando devolver um determinado
valor para a outra funo que chamou a funo corrente. Quando se chega a uma declarao return a funo encerrada imediatamente e, se o valor de retorno informado, a
funo retorna este valor.
importante lembrar que o valor de retorno fornecido tem que ser compatvel com o
tipo de retorno declarado para a funo. Uma funo pode ter mais de uma declarao
return. Isto se torna claro quando pensamos que a funo terminada quando o programa
chega primeira declarao return. Abaixo est um exemplo de uso do return:

#include <stdio.h>
int Square (int a)
{
return (a*a);
}
main ()
{
int num;
printf ("Entre com um numero: ");
scanf ("%d",&num);
num=Square(num);
printf ("O seu quadrado vale: %d",num);
}

6.6 Funes do Tipo void


Um dos usos de void declarar explicitamente funes que no devolvem valores.
Podemos analisar a funcionalidade do void observando o programa abaixo:

44

#include <stdio.h>
void Mensagem (void)
{
printf ("Ola! Eu estou vivo.");
}
int main ()
{
Mensagem();
printf ("Diga de novo:");
Mensagem();
return 0;
}
No exemplo acima, chama-se duas vezes a funo Mensagem. Esta declarada para
retornar um tipo void, ou seja, no retornar valor nenhum, apenas imprimir uma mensagem. Alm disso, dentro da lista de parmetros passamos ainda o tipo void, que siginifica
que nenhum valor ser passado por parmetro tambm.

6.7 Passagem por Parmetros


Sabemos que as funes em C recebem variveis por parmetros. Existem basicamente duas maneiras de passarmos estes argumentos para as sub-rotinas.
6.7.1 Chamada por Valor
Portanto, quando chamamos uma funo os parmetros formais da funo copiam os
valores dos parmetros que so passados para a funo. Estes viram variveis locais,
assim quaisquer alteraes feitas nestas variveis no tm nenhum efeito nas variveis
usadas para cham-la. Isto ocorre porque so passados para a funo apenas os valores
dos parmetros e no os prprios parmetros. Vamos analisar o exemplo abaixo:
#include <stdio.h>
float sqr (float num)
{
num=num*num;
return num;
}
void main ()
{
float num,sq;
printf ("Entre com um numero: ");
scanf ("%f",&num);
sq=sqr(num);
printf ("O numero original e: %f",num);
printf ("O seu quadrado vale: %f",sq);
}
Neste exemplo, a funo sqr eleva ao quadrado o float num passado por parmetro. A
funo utiliza o prprio num (parmetro) para realizar o clculo. Como a passagem por

45

parmetro foi feita por valor, o valor de num no ser alterado quando voltar a funo
main. Logo, este parmetro funciona como uma varivel local dentro da funo, pois o
valor num da funo principal foi copiado para a varivel num da funo sqr.
6.7.2 Chamada por Referncia
Neste tipo de chamado os parmetros podem ser alterados dentro da funo, mantendo
este valor para a funo que o chamou. Este nome vem do fato de que, neste tipo de
chamada, no se passa para a funo os valores das variveis, mas sim suas referncias (a
funo usa as referncias para alterar os valores das variveis fora da funo).
O C s faz chamadas por valor. Isto bom quando queremos usar os parmetros formais vontade dentro da funo, sem termos que nos preocupar em estar alterando os
valores dos parmetros que foram passados para a funo. Mas isto tambm pode ser
ruim s vezes, porque podemos querer mudar os valores dos parmetros fora da funo
tambm. O C++ tem um recurso que permite ao programador fazer chamadas por referncia (deve-se utilizar o compilador g++ para isto). H entretanto, no C, um recurso de
programao que podemos usar para simular uma chamada por referncia.
Quando queremos alterar as variveis que so passadas para uma funo, ns podemos declarar seus parmetros formais como sendo ponteiros. Os ponteiros so a "referncia"que precisamos para poder alterar a varivel fora da funo. O nico inconveniente
que, quando usarmos a funo, teremos de lembrar de colocar um & na frente das variveis que estivermos passando para a funo.
O que so ponteiros? "Ponteiro uma varivel que contm um endereo de memria.
Esse endereo normalmente a posio de uma outra varivel na memria. Se uma
varivel contm o endereo de memria da outra, ento a primeira varivel dita apontar
para a segunda. "
Veja um exemplo:
#include <stdio.h>
void Swap (int *a,int *b)
{
int temp;
temp=*a;
*a=*b;
*b=temp;
}
void main (void)
{
int num1,num2;
num1=100;
num2=200;
Swap (&num1,&num2);
printf ("Eles agora valem %d %d",num1,num2);
}

O que est acontecendo que passamos para a funo Swap o endereo das variveis
num1 e num2. Estes endereos so copiados nos ponteiros a e b. Atravs do operador
* estamos acessando o contedo apontado pelos ponteiros e modificando-o. O contedo

46

nada mais do que os valores armazenados em num1 e num2, que, portanto, esto sendo
modificados!
6.7.3 Matrizes como Argumentos de Funes
Se declaramos uma matriz de 50 posies, existem basicamente trs maneiras de passarmos ela por parmetro para uma funo, so elas:
void func (int matrx[50]);
void func (int matrx[]);
void func (int *matrx);
Nos trs casos, teremos dentro de func() um int* chamado matrx. Ao passarmos um
vetor para uma funo, na realidade estamos passando um ponteiro. Neste ponteiro
armazenado o endereo do primeiro elemento do vetor. Isto significa que no feita
uma cpia, elemento a elemento do vetor. Isto faz com que possamos alterar o valor dos
elementos do vetor dentro da funo.
Para chamarmos a funo func passando a matriz mt2 de 50 posies, podemos seguir
o seguinte exemplo:
func(mt2);
Muito embora o parmetro mt2 seja declarado como uma matriz de inteiros, o compilador C converte-o para um ponteiro de inteiros. Portanto, seu endereo passado para
a funo. Neste caso, o cdigo dentro da funo estar operando com, e potencialmente
alterando, o contedo real da matriz usada para chamar a funo.

6.8 Prottipos de Funes


Os prottipos permitem indicar ao compilador indicar a existncia de funes durante
o cdigo, e quais os tipos dos argumentos que devem se passados. At agora, nossas
funes sempre foram declaradas antes do main , no necessitando a indicao do seu
prottipo. A sintaxe de um prottipo de funo :
tipo_de_retorno nome_da_funo (declarao_de_parmetros);
Vejamos o seguinte exemplo:
#include <stdio.h>
float Square (float a);
int main ()
{
float num;
printf ("Entre com um numero: ");
scanf ("%f",&num);
num=Square(num);
printf ("O seu quadrado vale: %f",num);
return 0;
}
float Square (float a)
{
return (a*a);
}

47

6.9 Exerccios
1. Desenvolva uma funo, que receba trs notas e devolva a sua mdia.
2. Desenvolva uma funo que receba trs notas (p1, p2 e p3) e devolva a mdia no
argumento p3.
3. Construa uma funo C que recebe, por parmetro, um valor n, inteiro e positivo, e
escreve os seus divisores.
4. Contrua uma funo que recebe um vetor de x elementos preenchidos, e ordene o
vetor.
5. Desenvolva uma funo em C que recebe o gabarito da LOTO e uma aposta (no
mximo 10 dezenas) e devolve o nmero de pontos da aposta.
6. Desenvolver um algoritmo com uma funo que recebe um vetor e sua dimensio
e devolve o percentual de valores do vetor que so menores do que a mdia dos
valores deste vetor.
7. Dado a funo abaixo, responda:
int func(int n)
{
if (n)
return n*func(n-1);
else return 1;
}

O que esta funo faz?


O que recursividade?

48

7 APONTADORES

Antes de vermos o que so apontadores e como podem ser utilizados no C, vamos


fazer uma rpida reviso sobre o conceito de variveis. Uma varivel mostrada nas
disciplinas de algoritmos como se fosse uma caixa com um nome e esta caixa possui um
valor qualquer.
Teste cont
texto
209
34 "exemplo"
Bem, esta uma analogia fcil de entender quando lidamos com algoritmos, mas
agora devemos entender como as varveis so realmente implementadas pelas linguagens.
Uma varivel nada mais que um nome (label) que referencia (aponta) uma posio
de memria. A memria pode ser considerada como um array de bytes, sendo que cada
palavra tem um endereo nico. Considerando que teste seja do tipo int, cont do tipo
char e texto uma string de 10 posies, podemos admitir que os mesmos poderiam estar
dispostos da seguinte forma em um trecho de memria hipottico que comea no endereo
200:
Endereo
200
201
202
203
204
205
206
207
208
209
210
211
212
213

Valor Nome
209
teste
000
34
cont
e
texto
x
e
m
p
l
o
0
?
?
...
xx

Temos, ento, que um label, ou seja, um nome de varivel que aponta para o incio de
uma rea de memria reservada para si, cujo tamanho depende do tipo. Ou seja, para o
tipo int, so reservados 2 bytes (em algumas arquiteturas so 4 ou mesmo 8 bytes), para
o tipo char apenas um e para a string texto, so reservados tantos bytes quantos forem

49

necessrios para satisfazer o tamanho requerido. No momento o texto de exemplo no


utiliza todos os 10 bytes, sendo que a prxima varivel declarada (xx) ocupar a posio
de memria 213 mesmo assim. No desenho tambm est representado o uso do 0 como
terminador de uma cadeia de caracteres no C.
Anteriormente, no Captulo 6, falamos dos operadores "&"e "*"para manipulao de
endereos. Agora podemos entender melhor seu funcionamento. Quando referenciamos a
varivel pelo nome, o que nos retornado ser simplesmente o valor contido na memria
referenciada pela varivel, ou seja, ao referenciarmos a varivel teste, nos ser retornado
o valor 209, ao referenciarmos a varivel cont, nos ser retornado o valor 34. Quando,
entretanto, referenciarmos a varivel teste com a seguinte sintaxe:
&teste
Estamos agora pedindo o endereo ocupado pela varivel, ou seja, receberemos o
valor 200 (posio da memria onde a mesma comea). De forma anloga, se usarmos a
notao:
teste
ser retornado o valor contido na memria cujo endereo est na posio de memria
apontada por teste! Complicado? Vejamos no exemplo:
A posio de memria apontada pela varivel teste contem o valor 209. Quando
usamos *teste, queremos o valor da posio 209, ou seja, nos ser retornado o!! Este o
conceito de apontadores: variveis cujo valor o endereo de uma outra varivel ou uma
rea de memria reservada para tal. Estes exemplos so hipotticos, pois o C no permite
usar o operador "*"para variveis que no sejam do tipo pointer.
Os apontadores ou pointers so tipos de dados que tem por funo "apontar"(referenciar)
variveis atravs de seus endereos fsicos (posio da varivel na memria), permitindo
uma maior flexibilidade em nossos programas como: acesso indireto por ponteiros, simulao de passagem de parmetros por referncia, alocao dinmica de memria, criao
de listas encadeadas e outras estruturas de dados mais complexas. So declarados da
seguinte forma:
int x,y;
// Declarao de dois inteiros
int *px;
// Declarao de um ponteiro para inteiros
double vard, *pd; // um double e um ponteiro para double
Os ponteiros so definidos em funo do tipo de varivel ao qual ele ser ligado, so
do tipo "aponta para um determinado tipo de dado". Como se usa um apontador:
pt = &x;
y = *pt;

 pt = 12;

// pt recebe o endereo de x, aponta para x


//y recebe o valor apontado por pt
//O endereo dado por pt recebe o valor 12
//Se pt = &x ento *pt = 12 igual a x = 12

impossvel apontar para registradores e constantes definidas atravs do comando


#define do processador de macros. Um uso muito prtico de ponteiros com os arrays,
pois este tipo de dado tem caractersticas que se comportam de maneira muito parecida
a eles. Na realidade, um array pode ser visto, na maioria das vezes, como sendo um
apontador para uma posio onde se encontram alocados os dados. Por isso temos:

50

char car,a[10],*ptr;
ptr = a;
//ptr aponta para o endereo de a[0]
ptr = &(a[0]);
//igual ao exemplo anterior a = &a[0]
car = *(ptr);
//car recebe o contedo de a[0]
int var[5],*pint;
pint = var;
pint = (var+2);

//pint aponta para var[0]


//pint aponta para var[2]

Como j pode ser visto, a indexao dos arrays feita na mesma maneira em que se
trata com ponteiros. Ento, incrementar um ponteiro significa somar ao endereo atual
tantas unidades quanto for o tamanho do tipo de dado apontado, assim como o endereo
de um elemento de um array pode ser obtido apenas somando-se tantas unidades quanto
for o tamanho do elemento do array.
Portanto podemos fazer somas e incrementos com ponteiros operando-os como se
fossem meros endereos. Sendo que no caso de incrementos, o acrscimo ser feito de
acordo com tipo de dado ao qual o ponteiro atua (soma tantos bytes quanto for o tamanho
do tipo).
Como foi visto, apontadores acessam diretamente a memria do micro, por isso constituem uma ferramenta poderosa mas ao mesmo tempo perigosa, pois um descuido qualquer pode causar srios danos. Sempre que formos usar um ponteiro ele j dever ter sido
inicializado, ou seja, j deve ter sido atribudo algum endereo a ele.
Arrays, algumas informaes extras ...
A diferena entre um array e um ponteiro que quando definimos um array, uma
rea de memria reservada para ele e quando definimos um apontador, no h
alocao de memria. Exemplo:
char *string
-> reserva rea somente para o pointer (2/4 bytes)
char string[10] -> reserva rea para 10 caracteres (10 bytes)
Arrays so passados como parmetros para funes como sendo um ponteiro para
o incio do array.
Como conseqncia do modo de alocao de arrays de mais de uma dimenso,
quando for passado como parmetro o array, temos que indicar as outras dimenses,
exceto a principal. Isto se d pelo fato de que passado apenas o endereo inicial
do array, que tratado como um vetor linear. Sem a indicao das outras dimenses
no conseguimos distinguir os elementos de uma ou de outra dimenso. Exemplo:
funo (a)
int a[ ][10];

 o primeiro valor opcional


 o segundo valor obrigatrio

7.1 Apontadores: passagem de parmetros por referncia


Como visto anteriormente, o C s possui passagem de parmetros por valor, atravs
da pilha do sistema e no possui passagem por referncia. Esta regra continua sendo
verdadeira, mas pode-se simular a passagem por referncia atravs de ponteiros.

51

int quadrado ( int *a)


{
a=( a) ( a);
return(1);
}

  

main ()
{
int a=8;
quadrado(&a);
printf("A resposta foi %d n", a);
}

Observe que a passagem continua sendo por valor porque o que foi passado no o
valor inteiro, mas sim o seu endereo, e este endereo no pode ser mudado dentro da
funo. Veja pelo exemplo a seguir:

int x=34;
int quadrado (int a)
{
a=( a) ( a);
a=&x;
printf("A tem o valor %d n", a);
return(1);
}

//varivel global

  

main ()
{
int a=8;
quadrado(&a);
printf("A resposta foi %d n", a);
}

No exemplo acima, o endereo da varivel "a", passada por parmetro, trocado e a


impresso dentro da funo gerar o valor 34 (valor de x), mas quando a funo retornar,
o valor do endereo de a (passado por parmetro) restaurado, portanto continua sendo
por valor, mas o valor absoluto de "a"foi alterado.
Outra observao importante que a manipulao de valores dentro de uma funo
dever ser feita sempre com o operador "*". Outro exemplo:

52

int x=34; //varivel global


int quadrado ( int a)
{
a=( a) ( a);
a=&x;
printf("A tem o valor %d n", a);
return(1);
}

  

main ()
{
int a=8, b;
b=&a;
quadrado(b);
printf("A resposta foi %d n", a);
printf("A resposta foi %d n", b);
}

No exemplo acima, criou-se uma varivel do tipo apontador para inteiros e fez-se com
que ela recebesse o endereo de a. A varivel b j contem o endereo de uma rea de
memria e portando a passagem de parmetro feita simplesmente pelo seu nome. Por
fim, imprimir o valor de a ou o valor da posio apontada por b resultar no mesmo valor,
pois b aponta para a.
Portanto, sempre que desejar passar algum valor por referncia, deve-se passar o endereo deste valor, se desejar-se passar o prprio endereo por referncia, deve-se passar
o endereo do endereo. Mais adiante sero vistos outras utilidades para ponteiros.

7.2 Alocao Dinmica de ponteiros


Um apontador pode referenciar uma rea de memria j alocada, como por exemplo,
um inteiro, char ou mesmo um vetor declarado de forma esttica. Entretanto, pode-se
reservar uma nova rea de memria e faz-lo apontar para l. Considere um exemplo
em que tenhamos que guardar os inteiros digitados pelo usurio para depois imprimi-los
todos. Precisamos de um vetor de inteiros para isso, certo? De quantos elementos?
Talvez soubssemos de antemo que o usurio ir digitar apenas 20 nmeros, ento,
podemos fazer a seguinte declarao:
int vetor[20];
Mas se o usurio quiser digitar mais que 20, no ser possvel ao passo que se ele
digitar, digamos, apenas cinco, estamos desperdiando espao (15). E se tivermos uma
forma de alocar espao quando tivermos certeza qual o tamanho dele? possvel com o
uso de apontadores.

53

#include <stdio.h>
main()
{
int *vet;
int tamanho,i;
printf("Quantos elementos vc vai digitar? n ");
scanf("%d", &tamanho);
vet = (int *)malloc (tamanho * sizeof(int));
if (!vet) {  se vetor vazio (not vetor)...
printf("Erro na reserva de memria n");
return(0);
}
/* usa-se vet como vet[0], vet[1], ... vet[tamanho-1] */
}
Vetores estticos e dinmicos, como j dito, so praticamente o mesmo para o C,
e podem ser manipulados de forma semelhante. Vamos analisar por partes o exemplo
acima.
Ao criarmos o apontador vet, ele ter algum endereo de memria e podera-mos uslo. Mas, este espao em memria pode estar sendo usado por outro, pois no o reservamos
para nosso uso exclusivo (que o que fazemos com int vet[20]). Poderia ser desastrosa a
utilizao nestes termos.
Reservar um espao em memria de uso exclusivo nosso o que tenta fazer o comando
malloc. Digo tenta, porque ele pode no conseguir, por exemplo, caso no haja memria
suficiente. O malloc s reserva espao em bytes e retorna um apontador para este endereo
do tipo void. Por isso que para o compilador aceitar, devemos usar um cast no incio para
o tipo que estamos usando (no caso, int). Como a reserva em bytes, devemos reservar a
quantidade de bytes que reflita a nossa necessidade. No exemplo, temos uma necessidade
de tamanho elementos, sendo que cada elemento do tipo int, o espao que precisamos
de tamanho sizeof(int).
O malloc retorna o endereo reservado se conseguiu ou 0, (NULL) se falhou.
extremamente recomendvel testar seu retorno antes de usar.
No correto afirmar que o malloc cria variveis dinmicas, pois ele apenas reserva
espao deixando sobre a inteira responsabilidade do programador o gerenciamento desta
rea Logo, se o programador fizer mal uso, azar o dele!!! Podemos considerar um pssimo
uso o exemplo a seguir:

#include <stdio.h>
main()
{
int *vet;
int tamanho=20,i;
vet = (int *)malloc (tamanho * sizeof(int));
if (!vet) {
printf("Erro na reserva de memria n");
return(0);
}
vet = &i;
}

54

Na linha em destaque, vet recebe o endereo da varivel i. Ento, o que aconteceu


com a rea anteriormente reservada? Continua reservada para ns, mas j no temos
como us-la pois no sabemos onde est.
Para liberar-mos um espao anteriormente alocado, usamos o comando free():
free(vet);
No precisamos, neste caso, indicar o tamanho de memria liberada, pois isso o C
controla.

7.3 Exerccios:
1) Implemente a funo my_strcmp(), semelhante a strcmp() mas apenas retornando 0 se
forem iguais e diferente de zero se no.
2) Faa uma funo para somar dois vetores. A funo deve receber 3 vetores (os 2
vetores a serem somados e o vetor que receber a soma) e o tamanho dos vetores e
deve retornar a mdia dos valores somados (int).
3) Faa uma funo que copie X caracteres para uma outra cadeia de caracteres. A funo
dever retornar o nmero de caracteres efetivamente copiados (pode ser <que x que
a string origem terminar antes). Chamada:
char a[50], b[50], tam;
/* atribua um texto qualquer a a */
tam=copia(b,a,10);
/* copia no maximo 10 caracteres de a para b.
Se a string de a tiver s 5, copia apenas os cinco */
4) Faa um programa que crie dois vetores dinmicos de mesmo tamanho. O tamanho
deve ser passado por parmetro na execuo do programa. O usurio, ao executar
o programa, deve digitar todos os elementos de um dos vetores. Depois que todos
os elementos foram digitados, os elementos do segundo vetor deve ser calculado
da seguinte forma vet2[0]=tamanho-vet1[0], vet2[n]=tamanho-vet1[n]. Finalmente
imprima ambos os vetores.

55

8 ARQUIVOS

8.1 Introduo
O padro C ANSI define um conjunto completo de funes de E/S que pode ser utilizado para ler e escrever qualque tipo de dado.
O sistema de arquivos em C projetado para trabalhar com diversos tipos de dispositivos. O sistema de arquivo com buffer transforma-se em um dispositivo lgico chamado
de stream. Existem dois tipos de streams: texto e binria. Uma stream de texto uma
sequncia de caracteres. J uma stream binria uma sequncia de bytes com alguma
correspondncia.

8.2 Arquivos
Deve-se associar uma stream com um arquivo especfico e para isso tambm precisamos realizar uma operao de abertura. Depois do arquivo aberto, troca-se informaes
entre ele e o programa. Cada stream associada a um arquivo tem uma estrutura de controle do tipo FILE (stdio.h). Alm disso, cada vez que o arquivo aberto, tambm
inicializado o indicador de posio no arquivo. Quando um caractere lido ou escrito no
arquivo, o indicador de posio incrementado.

8.3 Funes
O sistema de arquivos C ANSI composto de diversas funes inter-relacionadas. As
mais comuns so mostradas na Tabela 8.1:
8.3.1 Ponteiro de Arquivo
O ponteiro de arquivo um ponteiro para informaes que definem coisas sobre o
arquivo (nome, status e posio atual do arquivo). Este indentifica um arquivo especfico
em disco e usado pela stream associada para direcionar as operaes de E/S. Para obter
uma varivel ponteiro de arquivo, a sintaxe a seguinte:
FILE *fp;
8.3.2 Abrindo um arquivo (fopen)
A funo fopen( ) abre uma stream para uso e associa um arquivo a ela, retornando
um ponteiro associada ao arquivo. A sintaxe da funo :
FILE *fopen(const char* nomearq, const char* modo);
Em modo devemos indicar como o arquivo dever ser aberto. Um arquivo pode ser

56

Nome
fopen( )
fclose( )
putc( )
fputc( )
getc( )
fgetc( )
fseek( )
fprintf( )
fscanf( )
feof( )
ferror( )
rewind( )
remove( )
fflush( )

Funo
Abre um arquivo
Fecha um arquivo
Escrever um caractere em um arquivo
O mesmo que putc( )
L um caractere de um arquivo
O mesmo que getc( )
Posiciona o arquivo em um byte especfico
para um arquivo o que um printf( )
para um arquivo o que o scanf( ) para o console
Devolve verdadeiro se o fim de arquivo for atingido
Devolve verdadeiro se ocorreu um erro
Recoloca o indicador de posio de arquivo no incio do arquivo
Apaga um arquivo
Descarrega um arquivo
Tabela 8.1: Funes para Arquivos

aberto em modo texto ou binrio. A tabela 8.2 mostra os modos os quais podemos abrir
os arquivos.
Modo
r
w
a
rb
wb
ab
r+
w+
a+
r+b
w+b
a+b

Significado
Abre um arquivo-texto para leitura
Cria um arquivo-texto para escrita
Anexa a um arquivo-texto
Abre um arquivo binrio para leitura
Cria um arquivo binrio para escrita
Anexa a um arquivo binrio
Abre um arquivo-texto para leitura/escrita
Cria um arquivo-texto para leitura/escrita
Anexa/cria um arquivo texto para leitura/escrita
Abre um arquivo binrio para leitura/escrita
Cria um arquivo binrio para leitura/escrita
Anexa a um arquivo binrio para leitura/escrita

Tabela 8.2: Modos de Abertura para Arquivos


Para abrir um arquivo chamado prog4all, pode-se desenvolver o seguinte trecho de
cdigo:
...
FILE *fp;
fp = fopen("prog4all","w");
...
Se quiseres sempre testar se a operao foi realizada com sucesso, mais comum se
programa como:

57

...
FILE *fp;
if((fp=fopen("prog4all","w"))==NULL) {
printf("O arquivo no pode ser criado n");
exit(1);
}
...

8.3.3 Fechando um arquivo (fclose)

A funo fclose( ) fecha uma stream que foi aberta por meio de uma chamada fopen( ).
Portanto, lembre-se sempre que um arquivo for aberto, voc deve fech-lo antes do final
do programa. A sintaxe do fclose ( ) :

int fclose(FILE *fp);

8.3.4 Escrevendo e Lendo um caractere

O padro C ANSI define duas funes para escrever caracteres: putc( ) e fputc( ). A
funo putc( ) escreve caracteres em um arquivo que foi aberto, tendo o seguinte prottipo:

int putc(int ch, FILE *fp);

Onde ch o caracter e o fp o ponteiro para o arquivo. Para ler caracteres de um


determinado arquivo podemos usar as funes getc( ) e fgetc( ). A funo getc( ) l caracteres de um arquivo aberto no modo leitura e seu prottipo :

int getc(FILE *fp);

A funo getc( ) ir retornar EOF quando o final do arquivo for alcanado. Para
entendermos melhor o funcionamento destas funes, vamos analisar o seguinte exemplo:

58

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main()
{
FILE *p;
char c, str[30], frase[80] = "Este e um arquivo chamado: ";
int i;
/* Le um nome para o arquivo a ser aberto: */
printf("Entre com um nome para o arquivo: n");
gets(str);
if (!(p = fopen(str,"w"))) /* Caso ocorra algum erro na abertura do arquivo..*/
{
printf("Erro! Impossivel abrir o arquivo! n");
exit(1); /* o programa aborta automaticamente */
}
/* Se nao houve erro, imprime no arquivo e o fecha ...*/
strcat(frase, str);
for (i=0; frase[i]; i++)
putc(frase[i],p);
fclose(p);
/* Abre novamente para leitura */
p = fopen(str,"r");
c = getc(p); /* Le o primeiro caracter */
while (!feof(p)) /* Enquanto no se chegar no final do arquivo */
{
printf("%c n",c); /* Imprime o caracter na tela */
c = getc(p); /* Le um novo caracter no arquivo */
}
fclose(p); /* Fecha o arquivo */
}
No exemplo, primeiro o arquivo aberto para a escrita, e imprime-se algo nele. Em
seguida, o arquivo fechado e novamente aberto para a leitura.
8.3.5 Lidando com Strings (fputs e fgets)
C suporta funes fputs( ) e fgets( ) que efetuam operaes de leitura e gravao de
strings de caracteres para um arquivo em disco. Abaixo esto os prottipos destas funes:
int fputs(const char *str, FILE *fp);
char *fgets(char *str, int length, FILE *fp);
Estas duas funes esto na biblioteca stdio.h. A funo fgets( ) l uma string da
stream especificada at que um caractere de nova linha seja lido ou que lenght-1 caracteres
tenham sido lidos. Pode-se observar um exemplo que ir inserindo strings num arquivo
at a tecla ENTER ser digitada:

59

#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *pf;
char string[100];
if((pf = fopen("arquivo.txt","w")) ==NULL)
{
printf("Nao consigo abrir o arquivo ! n");
exit(1);
}
do
{
printf("Digite uma nova string. Para terminar, digite <enter>: n ");
gets(string);
fputs(string, pf);
putc( n, pf);
}while (strlen(string) > 0);
fclose(pf);
}

8.3.6 Lidando com blocos de dados binrios(fread e fwrite)


Podemos escrever e ler blocos de dados. Para tanto, temos as funes fread() e
fwrite(). O prottipo de fread() :
unsigned fread (void *buffer, int numerodebytes, int count, FILE *fp);
O buffer a regio de memria na qual sero armazenados os dados lidos. O nmero
de bytes o tamanho da unidade a ser lida. Count indica quantas unidades devem ser
lidas. Isto significa que o nmero total de bytes lidos : numerodebytes*count.
A funo retorna o nmero de unidades efetivamente lidas. Este nmero pode ser
menor que count quando o fim do arquivo for encontrado ou ocorrer algum erro. Quando
o arquivo for aberto para dados binrios, fread pode ler qualquer tipo de dados.
A funo fwrite() funciona como a sua companheira fread(), porm escrevendo no
arquivo. Seu prottipo :
unsigned fwrite(void *buffer, int numerodebytes, int count, FILE *fp);
A funo retorna o nmero de itens escritos. Este valor ser igual a count a menos
que ocorra algum erro. O exemplo abaixo ilustra o uso de fwrite e fread para gravar e
posteriormente ler uma varivel float em um arquivo binrio.

60

#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *pf;
float pi = 3.1415;
float pilido;
if((pf = fopen("arquivo.bin", "wb")) == NULL)
/* Abre arquivo binrio para escrita */
{
printf("Erro na abertura do arquivo n");
exit(1);
}
if(fwrite(&pi, sizeof(float), 1,pf) != 1) /* Escreve a varivel pi */
printf("Erro na escrita do arquivo n");
fclose(pf); /* Fecha o arquivo */
if((pf = fopen("arquivo.bin", "rb")) == NULL)
/* Abre o arquivo novamente para leitura */
{
printf("Erro na abertura do arquivo n");
exit(1);
}
if(fread(&pilido, sizeof(float), 1,pf) != 1)
/* Le em pilido o valor da varivel armazenada anteriormente */
printf("Erro na leitura do arquivo n");
printf("O valor de PI, lido do arquivo e: %f n", pilido);
fclose(pf);
return(0);
}

Note-se o uso do operador sizeof, que retorna o tamanho em bytes da varivel ou do


tipo de dados.
8.3.7 Realizando Procuras (fseek)
Para se fazer procuras e acessos randmicos em arquivos usa-se a funo fseek(). Esta
move a posio corrente de leitura ou escrita no arquivo de um valor especificado, a partir
de um ponto especificado. Seu prottipo :
int fseek (FILE *fp, long numbytes, int origem);
O parmetro origem determina a partir de onde os numbytes de movimentao sero contados. Os valores possveis so definidos por macros em stdio.h. Estes esto apresentados
na Tabela 8.3.
Tendo-se definido a partir de onde ir se contar, numbytes determina quantos bytes de
deslocamento sero dados na posio atual.

61

Nome
SEEK_SET
SEEK_CUR
SEEK_END

Valor
0
1
2

Significado
Incio do arquivo
Ponto corrente no arquivo
Fim do arquivo

Tabela 8.3: Valores do fseek

8.4 Exerccios
1) Fazer um programa que leia do usurio um determinado nmero de caracteres e armazeneos em um arquivo, chamado de "teste.txt". O programa deve parar de ler quando o
usurio digitar a letra A.
2) Fazer um programa que simule uma lista telefnica. O usurio poder incluir novos
registros (nome + telefone) ou apenas consult-los. importante ressaltar que ao
reiniciar o programa, o usurio deve poder visualizar telefones pr-cadastrados.
3) Fazer um programa que solicite ao usurio o nome de um arquivo de entrada. Aps
abrir este arquivo o programa deve criar outro arquivo que uma cpia do arquivo
de origem. O arquivo destino deve ser uma cpia, com algumas alteraes, so elas:
letras a so substitudas por G, letras c so substitudas por H e letras e so
substitudas pela palavra lp.
4) Faa uma rotina que recebe uma matriz A(4,4) de inteiros e retorna um vetor apenas
com os elementos cuja soma dos ndices par. Faa uma rotina que recebe o vetor
gerado na rotina anterior e armazena o vetor em um arquivo binrio. Faa uma
rotina para ler o arquivo binrio gravado e imprima as informaes na tela.
5) Faa um programa que permita inserir e visualizar o cadastro dos alunos de uma academia. As informaes a serem armazenada so: nome, idade e peso. As informaes
devem ser armazenadas em um arquivo binrio.

62

9 BIBLIOGRAFIA

KRNIGHAN, B.; RITCHIE, D. A Linguagem de Programao C. Campus, Porto


Alegre, 1986.
SCHILDT, E. C Completo e Total. Makron Books, So Paulo, 1990;
http://linux.org
http://tlm.conectiva.com.br/
http://www.indiana.edu/ uitspubs/b017/
http://www.labbas.eng.uerj.br/linux/linuxman.html
http://www.inf.ufrgs.br/ elgios/
http://www.inf.pucrs.br/ pinho
http://www.inf.pucrs.br/ silvia/lapro
http://www.inf.unilasalle.edu.br/ barreto/
http://www.cp.cefetpr.br/pessoal/mauricio