Vous êtes sur la page 1sur 143

Trabalho de Formatura:

Curso de Linguagem C

Autor: Jair Gustavo de Mello Torres


Orientador: Carlos Antnio Alves

Ilha Solteira - Junho de 2006

Sumrio
Pgina

Mdulo 1 Apresentao do Histrico e das Caractersticas Bsicas da


Linguagem C
1.1 Histria da Linguagem C
1.2 Compiladores e Interpretadores
1.3 Caractersticas da Linguagem C
1.4 Aplicaes Escritas em C
1.5 A Linguagem C Comparada Outras Linguagens
1.6 Estrutura de um Programa em Linguagem C
1.6.1 Comentrios
1.6.2 Diretiva #include
1.6.3 Uso do ponto-e-vrgula
1.7 Compreendendo os Tipos de Arquivo
Mdulo 2 Caractersticas e Definies Gerais da Linguagem C
2.1 Palavras Reservadas em Linguagem C
2.2 Nomes e Identificadores Usados na Linguagem C
2.3 Tipos e Dados
2.3.1 Modificadores de Tipos
2.4 Definio de Variveis
2.5 Definio de Constantes
2.5.1 Constantes Hexadecimais e Octais
2.5.2 Constantes Strings
2.5.3 Cdigos de Barra Invertida
2.6 Operadores
2.6.1 Operador de atribuio
2.6.2 Operadores Aritmticos
2.6.3 Operadores Relacionais
2.6.4 Operadores Lgicos
2.6.5 Manipulao de bits
2.6.6 Operadores de assinalamento
2.6.7 Operadores de Pr e Ps-Incremento
2.6.8 Operadores de Endereo
2.7 Tabela de Operadores da Linguagem C
2.8 Expresses
2.8.1 Converses de Tipos em Expresses
2.8.2 Modeladores (CASTS)
2.8.3 Espaamento e Parnteses
Mdulo 3 Funes na Linguagem C
3.1 Funes

01
01
02
02
03
05
05
05
06
06
08
08
08
09
09
10
10
11
11
11
12
12
12
12
13
13
13
14
14
14
15
15
16
17
20
20

3.2 Variveis dentro das Funes


3.3 Main como uma Funo
3.4 Introduo aos Parmetros
3.5 Parmetros Mltiplos
3.6 Retornando um Valor de uma Funo
3.7 Comando Return
3.8 Prottipos de Funo
3.9 Biblioteca de Execuo
3.10 Funes que no Retornam Int
3.11 Variveis Locais
3.12 Sobrecarga da Funo
3.13 Declarando Variveis Globais
3.14 Solucionando os Conflitos de Nomes de Variveis Locais e Globais
3.15 Chamada por Valor
3.16 Chamada por Referncia
3.17 Obtendo um Endereo
3.18 Usando um Endereo de Memria
3.19 Alterando o Valor de um Parmetro
3.20 Alterando Somente Parmetros Especficos
3.21 Funes Recursivas
Mdulo 4 - Funes PRINTF() e SCANF()
4.1 Funo PRINTF()
4.1.1 Exibindo Valores do Tipo int Usando Printf()
4.1.2 Exibindo um Valor Inteiro Octal ou Hexadecimal
4.1.3 Exibindo Valores do Tipo Unsigned Int
4.1.4 Exibindo Valores do Tipo Long Int
4.1.5 Exibindo Valores do Tipo Float
4.1.6 Exibindo Valores do Tipo Char
4.1.7 Exibindo Valores de Ponto Flutuante em um Formato Exponencial
4.1.8 Exibindo Valores em Ponto Flutuante
4.1.9 Exibindo uma String de Caracteres
4.1.10 Exibindo um Endereo de Ponteiro
4.1.11 Precedendo um Valor com um Sinal de Adio ou de Subtrao
4.1.12 Formatando um Valor Inteiro
4.1.13 Sada de Inteiros Preenchida com Zeros
4.1.14 Exibindo um Prefixo Antes dos Valores Octais ou Decimais
4.1.15 Formatando um Valor em Ponto Flutuante
4.1.16 Formatando a Sada Exponencial
4.1.17 Justificando Esquerda a Sada de Printf()
4.1.18 Combinando os Especificadores de Formato de Printf()
4.1.19 Trabalhando com os Caracteres Escape de Printf()
4.1.20 Determinando o Nmero de Caracteres que Printf() Exibiu
4.1.21 Usando o Valor de Retorno de Printf()
4.2 Funo SCANF():
4.2.1 Usando Caracteres em Scanf() que Sero Descartados

21
21
22
23
23
24
25
26
26
27
27
28
29
29
30
31
31
32
33
33
37
37
37
38
38
38
39
39
39
39
40
40
40
41
41
41
42
42
42
42
43
43
43
43
44

4.2.2 Lendo Valores em Variveis


4.2.3 Lendo String de Caracteres
4.2.4 Formatando a Entrada de Scanf()
4.2.5 Determinando o Nmero Mximo de Caracteres a ser Lido
4.2.6 Lendo Somente Caracteres Pr-Determinados
Mdulo 5 - Estruturas de Fluxo de Controle
5.1 A Declarao If
5.1.1 Usando a Declarao Else
5.1.2 O Encadeamento If-Else-If
5.1.3 A Expresso Condicional
5.1.4 Ifs Aninhados
5.2 A Declarao For
5.2.1 Partes do Comando For so Opcionais
5.2.2 Lao Null
5.2.3 Lao Infinito
5.2.4 Usando o operador vrgula da Linguagem C dentro de um lao for
5.3 A Declarao While
5.3.1 Partes de um Lao While
5.4 A Declarao Do-While
5.5 Comando Continue
5.6 Finalizando um Lao Usando o Comando Break
5.7 Desvios com o comando goto
5.8 A Declarao Switch
5.8.1 As Declaraes Switch Aninhadas
5.9 Laos Aninhados
Mdulo 6 Matrizes
6.1 Compreendendo as Matrizes
6.2 Declarando uma Matriz
6.3 Requisitos de Armazenamento de uma Matriz
6.4 Inicializando uma Matriz
6.5 Acessando Elementos da Matriz
6.6 Percorrendo em um Lao Elementos da Matriz
6.7 Usando Constantes Para Definir as Matrizes
6.8 Passando uma Matriz a uma Funo
6.9 Revisitando as Matrizes Como Funes
6.10 Como as Matrizes de String Diferem
6.11 Quantos Elementos Uma Matriz Pode Armazenar
6.12 Matrizes Multidimensionais
6.13 Inicializando Elementos em Uma Matriz Bidimensional
6.14 Percorrendo em Um Lao Uma Matriz Bidimensional
6.15 Percorrendo Uma Matriz Tridimensional
6.16 Passando uma Matriz Bidimensional Para uma Funo
6.17 Tratando as Matrizes Multidimensionais Como Uma Dimenso

45
45
45
45
46
50
50
51
51
52
53
53
54
55
55
56
56
57
58
59
60
61
61
63
64
68
68
68
68
69
69
70
70
71
71
72
72
72
73
73
73
74
74

Mdulo 7 Ponteiros
7.1 Ponteiros como Endereos
7.2 Determinando o Endereo de uma Varivel
7.3 Como a Linguagem C trata Matrizes como Ponteiros
7.4 Aplicando o Operador de Endereo (&) a uma Matriz
7.5 Declarando Variveis Ponteiros
7.6 Desreferenciando um Ponteiro
7.7 Usando Valores de Ponteiro
7.8 Ponteiros com Parmetros de Funo
7.9 A Aritmtica de Ponteiros
7.10 Incrementando e Decrementando um Ponteiro
7.11 Percorrendo uma String usando um Ponteiro
7.12 Funes que retornam Ponteiros
7.13 Criando uma Funo que retorna um Ponteiro
7.14 Uma Matriz de Ponteiros
7.15 Percorrendo em um Lao uma Matriz de Strings de Caracteres
7.16 Usando um Ponteiro para um Ponteiro para String de Caracteres
7.17 Declarando uma Constante String usando um Ponteiro
7.18 O Ponteiro do tipo Void
7.19 Ponteiros para as Funes
7.20 Ponteiro para uma Funo
7.21 Usando um Ponteiro para um Ponteiro para um Ponteiro

77
77
77
77
78
78
79
79
79
80
80
81
81
81
82
82
82
83
83
83
84
84

Mdulo 8 - Sistema de Arquivos

87

8.1 Introduo
8.2 O Ponteiro de Arquivo
8.3 Abrindo um Arquivo Usando FOPEN
8.4 A Estrutura FILE
8.5 Fechando um Arquivo Aberto
8.6 Lendo e Gravando Informaes no Arquivo um Caracter de Cada Vez
8.7 O Ponteiro de Posio do Ponteiro de Arquivo
8.8 Determinando a Posio Atual no Arquivo
8.9 O Significado de Canais de Arquivo
8.10 Lendo Linhas de Textos
8.11 Gravando Linhas de Texto
8.12 Exemplo do Uso das Funes Fgets e Fputs
8.13 As Funes Fread( ) E Fwrite( )
8.14 As Funes Fprintf( ) e Fscanf( )
8.15 Testando o Final do Arquivo
8.16 Posicionamento do Ponteiro de Arquivo com Base em sua Posio
Atual
8.17 Excluindo um Arquivo

87
87
87
89
89
90
90
91
91
92
92
92
93
95
96
97

Mdulo 9 Funes Grficas na Linguagem C

100

9.1 A Tela Grfica

97

100

9.2 Detectando o Adaptador Grfico


9.3 Inicializando a Parte Grfica
9.4 Obtendo as Dimenses da Tela
9.5 Desenhando uma Reta na Tela
9.6 Desenhando um Retngulo na Tela
9.7 Desenhando um Ponto na Tela
9.8 Desenhando um Crculo na Tela
9.9 Desenhando um Arco Circular na Tela
9.10 Limpando a Tela Grfica
9.11 Mudando as Cores do um Desenho
9.12 Mudando a Cor de Fundo e o Preenchimento do um Desenho
Mdulo 10 Estruturas, Unies, Enumeraes e Typedef
10.1 Estruturas
10.1.1 Referenciando os Campos da Estrutura
10.1.2 Matrizes de Estruturas
10.1.3 Atribuindo Estruturas
10.1.4 Passando Estruturas para Funes
10.1.5 Ponteiros para Estruturas
10.1.6 Matrizes e Estruturas dentro de Estruturas
10.2 Unies
10.3 Enumeraes
10.4 A Palavra Reservada Typedef

101
102
102
103
103
104
104
105
105
106
106
109
109
110
110
110
111
112
114
115
116
118

Mdulo 11 Funes de Entrada/Sada (I/O) e Programa Analisador


Espectral
11.1 Introduo
11.2 As Funes inport e outport
11.3 Placas de Aquisio de Sinais Analgicos
11.3.1 - Conversor A/D
11.3.2 - Conversor D/A
11. 4 Fatores de Escala para o Modo Grfico
11.4.1 Fator de Escala Eixo X
11.4.2 - Fator de Escala Eixo Y
11.4.3. Programa: Anlise Espectral

121

Referncias Bibliogrficas

134

121
121
122
123
123
124
124
125
126

Mdulo 1 Apresentao do Histrico e das


Caractersticas Bsicas da Linguagem C

1.1 Histria da Linguagem C


A Linguagem C uma linguagem de programao que tem sua origem em outras
duas linguagens anteriores: a Linguagem BCPL e a Linguagem B. A Linguagem BCPL foi
desenvolvida por Martin Richards. Esta linguagem influenciou a linguagem inventada por
Ken Thompson, chamado B. Logo em seguida, Dennis Ritchie desenvolveu a Linguagem C
que foi implementada em um DEC PDP-11, usando o sistema operacional UNIX.
A Linguagem C, dada a sua simplicidade e flexibilidade, tornou-se ao longo do
tempo uma das linguagens de programao mais usadas, sendo utilizada na criao e
desenvolvimento de softwares e sistemas operacionais que se tornaram famosos em todo
mundo, como por exemplo o Sistema Operacional Windows. Entretanto, a Linguagem C
atinge seus limites a partir do ponto em que os programas escritos na linguagem atingem
um certo tamanho, entre 25.000 e 100.000 linhas, devido problemas de gerenciamento do
cdigo. Para resolver este problema, em 1980, enquanto trabalhava nos laboratrios da
Bell, em Murray Bill, New Jersey, Bjarne Stroustrup acrescentou vrias extenses
linguagem C e chamou inicialmente esta nova linguagem de C com classes.
Em 1983, o nome adotado para esta nova linguagem foi C++. Muitas modificaes
foram feitas na Linguagem C++ para que ela pudesse suportar a programao orientada a
objetos (POO).

1.2 Compiladores e Interpretadores


Compiladores e Interpretadores so simplesmente programas sofisticados que agem
sobre o cdigo-fonte do seu programa, ou seja, depois que o cdigo-fonte de um
determinado programa escrito ele submetido um Compilador ou um Interpretador que
far com que seja possvel sua execuo em uma determinada mquina.
O Compilador l o programa inteiro e converte-o em um cdigo executvel. Uma
vez o programa compilado, uma linha de cdigo-fonte est significativamente distante do
cdigo executvel. O compilador no necessrio para executar o programa, desde que ele
j esteja compilado, ou seja, neste caso no ser necessrio que se tenha um programa
instalado na mquina que reconhea o cdigo em questo.
O Interpretador l o cdigo-fonte do seu programa uma linha por vez e executa
uma instruo especfica contida naquela linha. O interpretador dever estar presente toda
vez que o programa estiver sendo executado, ou seja, necessrio que um interpretador
especfico da linguagem utilizada esteja instalado na mquina.
Existem dois termos freqentes: tempo de compilao e tempo de execuo. O
termo tempo de compilao refere-se aos eventos que acontecem durante o processo de
compilao e tempo de execuo, aos eventos que ocorrem enquanto o programa est sendo
executado. Infelizmente, constantemente esses termos esto relacionados a mensagens de
erros, como em erros de tempo de compilao e erros de tempo de execuo.

1.3 Caractersticas da Linguagem C


Portabilidade entre mquinas e sistemas operacionais, ou seja, um cdigo
escrito em linguagem C poder ser executado em diferentes mquinas independentemente
da sua configurao fsica (hardware) e do sistema operacional residente.
A linguagem C estruturada, com isso desencoraja a utilizao dos goto's
desvios incondicionais -, que geram os chamados cdigos "macarronada". O "goto"
substitudo por diversos tipos de laos e desvios, tais como: while, do-while, for; if-thenelse, switch, que permitem ao programador exercer um controle lgico mais eficaz sobre os
cdigos fontes de seus programas.
A linguagem C/C++ possui sub-rotinas com variveis locais, isto , funes
cujas variveis so visveis apenas dentro desta funo e somente no momento em que estas
funes estejam sendo usadas. Assim as variveis com mesmo nome, que pertenam a
funes distintas, so protegidas dos efeitos colaterais (proteo de variveis), isto , uma
modificao em nvel funcional no acarretar mudana na varivel em nvel global. Desta
forma, mudanas de valores de variveis no corpo do programa principal no afetam as
variveis de funes e vice-versa, a no ser que o programador assim o queira.
Cdigo compacto e rpido, quando comparado ao cdigo de outras linguagem
de complexidade anloga.
A linguagem C Case-Sensitive. importante saber que as letras maisculas e
minsculas so tratadas como caracteres distintos. Por exemplo, em algumas linguagens, os
nomes de variveis count, Count e COUNT so trs maneiras de se especificar a mesma
varivel. Entretanto na linguagem C, sero trs variveis diferentes. Ento, quando voc
digitar programas em C seja cuidadoso na utilizao correta das letras.

1.4 Aplicaes Escritas em C


Atualmente, nos Estados Unidos, C a linguagem mais utilizada pelos
programadores, por permitir, dadas suas caractersticas, a escrita de programas tpicos do
Assembler, BASIC, COBOL e Clipper, sempre com maior eficincia e portabilidade, como
podemos constatar pelos exemplos abaixo relacionados:
Sistema Operacional: UNIX (Sistema Operacional executvel em micro computadores e em
mainframes).
Montadores: Clipper (O utilitrio de banco de dados mais usado no Brasil).
Planilhas: 1,2,3 e Excel (A planilha eletrnica com maior volume de vendas mundial).
Banco de Dados: dBase III, IV e Access (o gerenciador de base de dados mais utilizado no
mundo).
InfoStar: O Editor de Texto mais utilizado nos USA no Sistema Operacional UNIX.
Utilitrios: FormTool (Editor de formulrio mais vendido no mundo).
Aplicaes Grficas: Efeitos Especiais de filmes com Star Trek e Star War.
Linguagens como o Power Builder e o Visual Basic, respectivamente as linguagens mais
utilizadas nos EUA e no Brasil.

No Brasil utilizada por empresas especializadas na elaborao de vinhetas e outros


efeitos especiais.

1.5 A Linguagem C Comparada Outras Linguagens


Deve-se entender Nvel Alto como sendo a capacidade da linguagem em
compreender instrues escritas em dialetos prximos do ingls (Ada e Pascal, por
exemplo) e Nvel Baixo para aquelas linguagens que se aproximam do Assembly, que a
linguagem prpria da mquina, compostas por instrues binrias e outras
incompreensveis para o ser humano no treinado para este propsito. Infelizmente, quanto
mais clara uma linguagem for para o humano (simplicidade >) mais obscura o ser para a
mquina (velocidade <).
A Linguagem C freqentemente referenciada como uma linguagem de nvel
mdio, posicionando-se entre o Assembly (baixo nvel) e o Pascal (alto nvel). Uma das
razes da inveno da Linguagem C foi dar ao programador uma linguagem de alto nvel
que poderia ser utilizada como uma substituta para a linguagem Assembly. Entretanto,
ainda que a Linguagem C possua estruturas de controle de alto nvel, como encontrado na
Pascal, ela tambm permite que o programador manipule bits, bytes e endereos de uma
maneira mais proximamente ligada mquina, ao contrrio da abstrao apresentadas por
outras linguagens de alto nvel. Por esse motivo, a Linguagem C tem sido ocasionalmente
chamada de cdigo Assembly de alto nvel. Por sua natureza dupla, a Linguagem C
permite que sejam criados programas rpidos e eficientes sem a necessidade de se recorrer
a linguagem Assembly.
A filosofia que existe por trs da Linguagem C que o programador sabe realmente
o que est fazendo. Por esse motivo, a Linguagem C quase nunca coloca-se no caminho
do programador, deixando-o livre para usar (ou abusar) dela de qualquer forma que queira.
O motivo para essa liberdade na programao permitir ao compilador C criar cdigos
muito rpidos e eficientes, j que ele deixa a responsabilidade da verificao de erros para o
programador.
Observemos o esquema a seguir:
Nvel Baixo

Nvel Mdio

VELOCIDADE
Assembler

Macro Assembler
Forth

Nvel Alto
CLAREZA

Fortran

Basic
COBOL

Pascal

Ada
MODULA-2

Antes da Linguagem C tornar-se um padro de fato (meados de 1.988, nos USA),


tnhamos, aproximadamente, o seguinte perfil de mercado:
- Aplicaes de Banco de Dados

- Mainframe: COBOL e gerenciadores


- Micros: dBase, Clipper e BASIC e gerenciadores como Btrieve.
- Aplicaes Grficas: Pascal.
- Aplicaes Cientficas: FORTRAN e Pascal.
- Utilitrios, Sistemas Operacionais e Compiladores: Assembler.
A chegada de poderosos compiladores C (Borland, Microsoft e Zortech-Symantec),
revolucionou totalmente estes conceitos pois passou a permitir a construo de
praticamente qualquer tipo de aplicao na Linguagem C, normalmente mais rpidas do
que na linguagem original e portvel entre os diversos ambientes (roda em DOS, UNIX,
etc. com poucas mudanas).
Devemos entender no entanto, que apenas temos uma relativa portabilidade, pois a
verdadeira portabilidade depende necessariamente da implementao do sistema
operacional, necessariamente aberto, o que no existe fora do mundo Unix.
Quadro de caractersticas de linguagens:
Linguagens /
Caractersticas Ideais
Executveis Curtos
Executveis Rpidos
Portveis
Manipulao de Bits

Assembler

timo
timo
pssimo
timo

BASIC
Pascal

fraco
Bom
Bom
razovel

Clipper

COBOL

pssimo
razovel
timo
pssimo

fraco
fraco
timo
fraco

timo
bom
bom
timo

O quadro anterior, deixa claro o porqu da revoluo causada pela Linguagem C,


dados os inmeros pontos fortes da linguagem e a inexistncia de pontos fracos da mesma.
No deve-se concluir apressadamente que poderemos desenvolver tudo em C e
abandonarmos todas as outras linguagens, pelos seguintes motivos:
- Alta base de programas escritos em Assembler, COBOL, BASIC, Pascal.
- Conhecimento amplo de linguagens concorrentes como COBOL, Clipper e BASIC.
- Melhor adaptao de alguma linguagem para tarefa especfica como Grficos (Pascal),
Inteligncia Artificial (Prolog, LISP), matemticas (Pascal e FORTRAN), aplicaes
comerciais (COBOL, Clipper e BASIC).
As verses atuais das linguagens BASIC, C, Clipper, Pascal e COBOL, esto muito
mais semelhantes do que o eram ao tempo em que este quadro foi elaborado, portanto na
prtica muitas vezes este quadro, meramente terico, pode tornar-se inaplicvel.
mdio prazo, pode-se afirmar que a Linguagem C dever ir desalojando as outras
linguagens podendo at mesmo tornar-se um padro de direito, porm devemos lembrar
que algumas linguagens foram propostas para isto (Algol, PL/1) e no s no conseguiram
atingir seus objetivos como praticamente desapareceram.

1.6 Estrutura de um Programa em Linguagem C

Um programa em Linguagem C formado por uma ou mais funes. Cada funo


possui um nome exclusivo e corresponde um bloco de cdigo, delimitado por um par de
chaves {}, contendo um conjunto de declaraes, expresses, comandos de controle e
chamadas outras funes. Uma funo denominada main obrigatria em todos os
programas, pois o seu ponto de entrada, isto , o programa comea a ser executado no
incio da funo main e termina ao final desta funo. Normalmente a declarao desta
funo possui a seguinte forma: int main(void), mas adiante ser estudada outra forma de
declarao para esta funo. Ao concluir a funo main, com o comando return, a
execuo do programa finalizada, sendo que pelo padro ANSI, esta funo deve retornar
0 (zero) se o programa foi finalizado com sucesso, ou um valor maior que zero caso ele
tenha sido finalizado por uma situao anormal. Alm da funo main, o programa pode
possuir outras funes, sendo que estas devem ser, direta ou indiretamente, chamadas pela
funo main.
Abaixo, um programa escrito em linguagem C, muito simples que voc pode rodar
no seu compilador:
/* Seu primeiro programa em linguagem C*/
#include <stdio.h>
void main ()
{
printf ("Bem vindo ao mundo da programao em C!!!\n");
getchar(); /* Aguarda pressionar Enter */
}

1.6.1 Comentrios
Os comentrios servem principalmente para documentao do programa e so
ignorados pelo compilador, portanto no iro afetar o programa executvel gerado. Os
comentrio iniciam com o smbolo /* e se estendem at aparecer o smbolo */. Um
comentrio pode aparecer em qualquer lugar no programa onde possa aparecer um espao
em branco e pode se estender por mais de uma linha.

1.6.2 Diretiva #include


Toda a diretiva, em C, comea com o smbolo # no incio da linha. A diretiva
#include inclui o contedo de um outro arquivo dentro do programa atual, ou seja, a linha
que contm a diretiva substituda pelo contedo do arquivo especificado. Sintaxe:
#include <nome do arquivo>
ou
#include nome do arquivo

O primeiro caso o mais utilizado. Ele serve para incluir alguns arquivos que
contm declarao das funes da biblioteca padro, entre outras coisas. Estes arquivos,
normalmente, possuem a extenso .h e se encontram em algum diretrio pr-definido pelo
compilador. Sempre que o programa utilizar alguma funo da biblioteca-padro deve ser
includo o arquivo correspondente. A tabela a seguir apresenta alguns dos principais .h da
linguagem C: Descrio
stdio.h - Funes de entrada e sada (I/O)
string.h - Funes de tratamento de strings

math.h - Funes matemticas


ctype.h - Funes de teste e tratamento de caracteres
stdlib.h - Funes de uso genrico
A segunda forma, onde o nome do arquivo aparece entre aspas duplas, serve
normalmente para incluir algum arquivo que tenha sido criado pelo prprio programador ou
por terceiros e que se encontre no diretrio atual, ou seja, no mesmo diretrio do programa
que est sendo compilado.

1.6.3 Uso do Ponto-e-Vrgula


Voc pode no ter percebido, mas no cdigo em C apresentado no item 1.6 usamos
duas vezes o ponto-e-vrgula, quando terminamos a declarao dos comandos printf() e
getchar(). Ele usado para separar diferentes comandos dentro do seu cdigo em C.
Durante o processo de compilao executado pelo compilador, o ponto-e-vrgula mostra ao
compilador quando uma linha de comando termina e quando outra linha de comando se
inicia. Ou seja, se voc esquecer do ponto-e-vrgula seu compilador ir acusar um erro pois
ele no ir saber quando termina ou comea um determinado comando dentro do cdigo
que voc digitou.

1.7 Compreendendo os Tipos de Arquivo


Ao criar um programa em linguagem C, voc coloca seus comando em um arquivofonte, que tem a extenso .c . Se o seu programa for compilado com sucesso, o compilador
ir criar um programa executvel com a extenso .exe . Durante a compilao, o
compilador cria em seu diretrio outros arquivos com extenso .obj . Estes arquivos contm
as instrues em forma binria, ou seja 1s e 0s, que o computador compreende. Vale
ressaltar que os cdigos estudados neste material foram testados no compilador Turbo C
2.0.

1.8 Sntese do Mdulo


apresentado seguir, uma sntese do que foi tratado em cada item deste mdulo.
Com esta sntese voc poder relembrar conceitos vistos durante nosso estudo ou mesmo
direcionar seu estudo, caso voc j tenha conhecimentos na Linguagem C.
1 1.1 Histria da Linguagem C: apresenta um breve relato sobre o
desenvolvimento da Linguagem de Programao C. Nele mostrado que a Linguagem C
foi desenvolvida por Dennis Ritchie e que ela na verdade uma linguagem derivada de
outras duas linguagens de programao anteriores, a BCPL e a Linguagem B. Mesmo
sendo uma linguagem flexvel e poderosa, a Linguagem C chegou a seus limites, e com
isso, o desenvolvimento de uma nova linguagem tornou-se inevitvel, sendo desenvolvida a
Linguagem C++, que na verdade era a Linguagem C com novas caractersticas que
superaram seus limites. Foram feitas vrias modificaes e melhorias na Linguagem C++
para que ela pudesse suportar a programao orientada a objeto (POO).

2 1.2 Compiladores e Interpretadores: neste item, foi mostrada a diferena


entre compilador e interpretador. Compiladores e Interpretadores so programas que
traduzem um cdigo-fonte de um programa para a linguagem que a mquina entende. No
caso do Interpretador, ele faz isso linha por linha do cdigo-fonte, toda vez que o programa
em questo executado. Ou seja, necessrio que exista na mquina um interpretador
especfico instalado para a linguagem de programao em que o programa em questo foi
escrito. No caso do Compilador gerado um programa executvel, ou seja, o Compilador
cria um arquivo que pode ser lido pelo sistema operacional da mquina, eliminando assim a
necessidade de um interpretador instalado. Foi visto tambm que o termo tempo de
compilao refere-se aos eventos que acontecem durante o processo de compilao e tempo
de execuo, aos eventos que ocorrem enquanto o programa est sendo executado.
3 1.3 Caractersticas da Linguagem C: neste item, apresentou-se as
principais caractersticas da Linguagem C, entre elas: que a Linguagem C portvel; a
Linguagem C estruturada; a linguagem C/C++ possui sub-rotinas com variveis locais;
seu cdigo compacto e rpido; a linguagem case-sensitive.
4 1.4 Aplicaes Escritas em C: devido sua compatibilidade com outras
linguagens de programao, como por exemplo, Assembly, Cobol, Clipper, Basic, a
Linguagem C largamente utilizada no desenvolvimento de programas, sistemas
operacionais e at em efeitos especiais em filmes.
5 1.5 A Linguagem C Comparada Outras Linguagens: neste item foi
feita uma comparao entre a Linguagem C e outras linguagens de programao. Mostrouse que a Linguagem C se classifica como uma linguagem de nvel mdio, pois mesmo
possuindo estruturas de controle de alto nvel, ela permite a manipulao de bits, bytes e
endereos de uma maneira bem prxima mquina. Alm do mais, a Linguagem C veloz
e tem uma alta portabilidade. Mas mostra-se que no possvel pensar em abandonar as
outras linguagens e usar-se somente a Linguagem C.
6 1.6 Estrutura de um Programa em Linguagem C: foi estudado neste item
que um programa em Linguagem C formado por uma ou mais funes. Cada funo
possui um nome exclusivo e corresponde um bloco de cdigo, delimitado por um par de
chaves {}, contendo um conjunto de declaraes, expresses, comandos de controle e
chamadas outras funes. Uma funo denominada main obrigatria em todos os
programas, pois o seu ponto de entrada, isto , o programa comea a ser executado no
incio da funo main e termina ao final desta funo.
7 1.6.1 Comentrios: comentrios servem principalmente para documentao
do programa e so ignorados pelo compilador, portanto no iro afetar o programa
executvel gerado. Os comentrio iniciam com o smbolo /* e se estendem at aparecer o
smbolo */.
8 1.6.2 Diretiva #include: neste subitem foi estudada a diretiva #include
inclui o contedo de um outro arquivo dentro do programa atual, ou seja, a linha que
contm a diretiva substituda pelo contedo do arquivo especificado. Ela serve para
incluir alguns arquivos que contm declarao das funes da biblioteca padro, entre
outras coisas.
9 1.6.3 Uso do ponto-e-vrgula: foi visto que o ponto-e-vrgula usado para
separar diferentes comandos dentro do seu cdigo em C. Durante o processo de compilao

executado pelo compilador, o ponto-e-vrgula mostra ao compilador quando uma linha de


comando termina e quando outra linha de comando se inicia.
10 1.7 Compreendendo os Tipos de Arquivo: foi explicado detalhadamente
os tipos de arquivos usados na programao em Linguagem C, como por exemplo, os
arquivos com extenso .c, .exe e .obj .

Mdulo 2 Caractersticas e Definies Gerais da


Linguagem C
2.1 Palavras Reservadas na Linguagem C

Na Linguagem C existem palavras que so de uso reservado, ou seja, no pode-se


us-las para escrever programas, por exemplo, usando o nome de uma palavra reservada
para referenciar uma varivel. Uma palavra reservada essencialmente um comando e, na
maioria das vezes, as palavras reservadas de uma linguagem definem o que pode ser feito e
como pode ser feito.
O conjunto de palavras reservadas em Linguagem C especificado pelo padro ANSI
C so as relacionadas abaixo:
auto
break
case
char
const
continue
default
do

double
else
enum
extern
float
for
goto
if

int
long
register
return
short
signed
sizeof
static

struct
switch
typedef
union
unsigned
void
volatile
while

Como j foi dito no Mdulo 1, a Linguagem C diferencia letras maisculas e


minsculas, ou seja, char uma palavra reservada da Linguagem C mas CHAR ou ChAr
no . Reforando o que j foi mencionado, as palavras reservadas s iro executar os
comandos que lhes foram designados.

2.2 Nomes e Identificadores Usados na Linguagem C


A Linguagem C chama o que usado para referenciar variveis, funes, rtulos e
vrios outros objetos definidos pelo usurio de identificadores. Quanto aos nomes ou
identificadores usados na declarao de variveis, deve-se considerar as seguintes regras:
('_');

nomes de variveis comeam com uma letra ('A'..'Z', 'a'..'z') ou pelo underscore

aps podem ser seguidos dgitos, letras e underscores;

3 evitar o uso do '_' no primeiro caractere do identificador de uma varivel, pois


este tipo de identificadores de uso do sistema;

4 normalmente ao declarar-se uma varivel esta ser inicializada com zero. No se


deve, no entanto, contar que isto sempre seja verdadeiro, portanto inicializa-se sempre as
variveis.
Aqui esto alguns exemplos de nomes de identificadores corretos e incorretos:

Correto
count
test23
high_balance

Incorreto
1count
Ol! Aqui
high..balance

Em C os primeiros 32 caracteres de um nome de identificador so significantes. Isso


quer dizer que duas variveis com os 32 primeiros caracteres em comum, diferindo somente
no 33 , so consideradas iguais. Como voc deve lembrar, em C, letras maisculas e
minsculas so tratadas como diferentes e distintas umas das outras. Por isso, count, Count
e COUNT so trs identificadores distintos.
Um identificador no pode ser o mesmo que uma palavra reservada e no devem ter
o mesmo nome de uma funo tanto uma funo que voc tenha escrito como uma funo
de biblioteca da linguagem C.

2.3 Tipos e Dados


Quando um programa escrito em qualquer linguagem de programao necessrio
a definio de algumas variveis. Variveis so instncias em que sero armazenados
valores utilizados durante a execuo de programas. Estas variveis podem ser modificadas
para suportar diferentes tipos de dados. Na tabela abaixo constam os tipos bsicos de dados
da Linguagem C:
Tipo
Char
Int
Float
double
void

Tamanho (em bits)


8
16
32
64
0

Intervalo
-128 a 127
-32768 a 32767
3,4E-38 a 3,4E+38
1,7E-308 a 1,7E+308
sem valor

2.3.1 Modificadores de Tipos


Possuindo os tipos bsicos de dados, pode-se ainda format-los para atender melhor
as necessidades de cada situao. Com exceo do tipo void, todos os outros tipos bsicos
podem ter modificadores precedendo-os. Voc pode ter como modificadores signed,
unsigned, long e short. Os modificadores signed, unsigned, long e short podem ser
aplicados aos tipos de base caractere e inteira. Entretanto, long, tambm pode ser aplicado
ao tipo double. A tabela a seguir mostra todas as combinaes permitidas dos tipos bsicos
e dos modificadores de tipo.

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

Tamanho (em bits)


8
8
8
16
16
16
16
16
16
32
32
32
32
64
80

Intervalo
-128 a 127
0 a 255
-128 a 127
-32768 a 32767
0 a 65535
-32768 a 32767
-32768 a 32767
0 a 65535
-32768 a 32767
-2147483648 a 2147483647
-2147483648 a 2147483647
0 a 4294967295
3,4E-38 a 3,4E+38
1,7E-308 a 1,7E+308
3,4E-4932 a 1,1E+4932

A linguagem C permite uma notao simplificada para declarao de inteiro


unsigned, short ou long. Voc pode simplesmente usar a palavra unsigned, short ou long
sem o int. O int est implcito. Por exemplo:
unsigned x;
unsigned int x;

declaram igualmente variveis inteiras sem sinal.


Variveis do tipo char podem ser usadas para armazenar valores outros que so
simplesmente o conjunto de caracteres ASCII. Uma varivel char pode ser usada tambm
como um pequeno inteiro com intervalo de 128 a 127, e no lugar de um inteiro quando a
situao no requer nmeros grandes.

2.4 Definio de Variveis


Variveis so instncias onde o programa em execuo coloca os dados que esto
sendo processados durante sua execuo. As variveis devem ser declaradas, ou seja,
devem ser definidos nome, tipo e algumas vezes seu valor inicial. As variveis so
classificadas em variveis locais e globais.
Variveis globais so aquelas declaradas fora do escopo das funes.
Variveis locais so aquelas declaradas no incio de um bloco e seus escopos esto
restritos aos blocos em que foram declaradas. A declarao de variveis locais deve
obrigatoriamente ser a primeira parte de um bloco, ou seja, deve vir logo aps um caractere
de abre chaves, '{'; e no deve ser intercalada com instrues ou comandos. Veja a
sintaxe para se declarar uma varivel:
<tipo> <nome>

Exemplos:

int mul = 100;


char a, b, c;
float valor;

2.5 Definio de Constantes


O conceito de constantes em linguagens de programao atribuir um certo valor
constante a um nome, e quando este nome for referenciado dentro do cdigo do programa,
ser utilizado nas operaes o valor atribudo a este nome. Ou seja, se for definida a
constante PI com o valor 3,1415926536, quando for encontrado no cdigo o nome PI,
ser utilizado em seu lugar o valor 3,1415926536. Na Linguagem C, constantes podem
ser definidas da seguinte maneira :
#define <nome_da_constante> valor

Exemplos:
#define PI 3,1415926536
#define SINAL "aberto"
#define MULT A*B

Observe que na definio de uma constante no h o ; no final. Se for colocado,


este far parte do valor associado constante.

2.5.1 Constantes Hexadecimais e Octais


Em programao algumas vezes comum usar um sistema de numerao baseado
em 8 ou 16 em vez de 10. O sistema numrico baseado em 8 chamado octal e usa os
dgitos de 0 a 7. Em octal, o nmero 10 o mesmo que 8 em decimal. O sistema numrico
de base 16 chamado hexadecimal e usa os dgitos de 0 a 9 mais as letras de A at F, que
equivalem a 10, 11, 12, 13, 14 e 15. Por exemplo, o nmero hexadecimal 10 16 em
decimal. Por causa da freqncia com que estes dois sistemas numricos so usados, a
linguagem C permite que se especifique constantes inteiro em hexadecimal ou octal em vez
de decimal, se preferir. Uma constante hexadecimal deve comear com 0x (um zero
seguido de um x), seguido pela constante em formato hexadecimal. Uma constante octal
comea com um zero. Aqui esto alguns exemplos:
hex = 0xFF; /* 255 em decimal */
oct = 011; /* 9 em decimal */

2.5.2 Constantes Strings


Outro tipo de constante suportada pela Linguagem C o tipo string. Uma string
um conjunto de caracteres entre aspas. Por exemplo, voc um vencedor uma string.
No confunda strings com caractere. Uma constante caractere simples fica entre
dois apstrofos, por exemplo a. Entretanto a uma string que contm somente uma
letra.

2.5.3 Cdigos de Barra Invertida


Colocar todas as constantes caractere entre aspas funciona para muitos caracteres,
mas alguns, como o retorno de carro, so impossveis de serem inseridos em uma string a
partir do teclado. Por isso, a linguagem C fornece constantes caractere mais barra invertida
especiais. Estes cdigos so mostrados na tabela a seguir:
Cdigo

\b
\n
\t
\
\\
\a
\xN

Significado
Retrocesso
Nova linha
Tabulao horizontal
Apstrofo
Barra invertida
Sinal sonoro
Constante hexadecimal

Cdigo
\f
\r
\
\0
\v
\N

Significado
Alimentao de formulrio
Retorno de carro
Aspas
Nulo
Tabulao vertical
Constante octal

Usa-se um cdigo de barra invertida exatamente da mesma maneira como usa


qualquer outro caractere. Por exemplo:
ch = \t;
printf (este um teste\n);

Esse fragmento de cdigo primeiro atribui uma tabulao a ch e, ento, imprime


este um teste na tela, seguido de uma nova linha.

2.6 Operadores
A linguagem C muito rica em operadores internos. Um operador um smbolo
que diz ao compilador para realizar manipulaes matemticas e lgicas especficas. A
linguagem C possui trs classes gerais de operadores: aritmticos, relacionais e lgicos e
bit-a-bit.

2.6.1 Operador de atribuio


O operador = atribui um valor ou resultado de uma expresso contida a sua direita
para a varivel especificada a sua esquerda. Exemplos:
a = 10;
b = c * valor + getval(x);
a = b = c = 1; /*Aceita associao sucessiva de valores*/

2.6.2 Operadores Aritmticos


So aqueles que operam sobre nmeros e expresses, resultando valores numricos.
So eles:
Operador

+
*

Soma
subtrao
multiplicao

Ao

/
%
-

diviso
mdulo da diviso (resto da diviso inteira)
sinal negativo (operador unrio)

2.6.3 Operadores Relacionais


Operam sobre expresses, resultando valores lgicos de TRUE (verdadeiro) ou
FALSE (falso). so eles:
Operador

Ao

>
>=
<
<=
==
!=

Maior
maior ou igual
Menor
menor ou igual
Igual
no igual (diferente)

Ateno!
No existem os operadores relacionais: =<, => e <>.
No confunda a atribuio (=) com a comparao (==).

2.6.4 Operadores Lgicos


Operam sobre expresses, resultando valores lgicos de TRUE (verdadeiro) ou
FALSE (falso). Possuem a caracterstica de short circuit, ou seja, sua execuo curta e
s executada at o ponto necessrio. So eles:
Operador

Ao

&&
||
!

operao AND
operao OR
operador de negao NOT (operador
unrio)

Exemplos de short circuit:


(a == b) && (b == c)
(a == b) || (b == c)

/*
/*

Se a != b no avalia o resto da expresso */


Se a == b no avalia o resto da expresso */

2.6.5 Manipulao de bits


A manipulao feita em todos os bits da varivel a qual no pode ser do tipo float
ou double. Os operadores que manipulam bits esto relacionados abaixo:
Operador

&
|
^

Ao

bit and
bit or
bit xor - exclusive or

<<
>>
~

Rotao a esquerda
Rotao a direita
bit not (complemento)

Observao: x << n ir rotacionar n vezes a varivel x esquerda.

2.6.6 Operadores de assinalamento


expresso da seguinte forma: (operadores combinados)
var = var op expr

var op = expr

->

Onde tempos op como um dos seguintes operadores:


Operador

Ao

+
*
/
%
>>
<<
&
^
|

Soma
Subtrao
Multiplicao
Diviso
mdulo (resto da diviso)
Rotao a direita
Rotao a esquerda
And
xor - exclusive or
Or

Exemplo de aplicao:
i+= 2; /* equivalente a: i = i + 2 */
j-= 3; /* equivalente a: j = j 3 */
k >>= 3; /* equivalente a: k = k >> 3;*/
z &= flag; /* equivalente a: z = z & flag;*/

2.6.7 Operadores de Pr e Ps-Incremento


Operadores de pr e ps-incremento so aqueles usados quando necessrio
incrementar ou decrementar um determinado valor.
As operaes abaixo podem ser representadas assim:
i = i + 1;
i = i 1;
z = a; a = a + 1;
z = a; a = a 1;
a = a + 1; z = a;
a = a - 1; z = a;

i = ++i;
i = --i;
z = a++;
z = a--;
z = ++a;
z = --a;

2.6.8 - Operadores de Endereo

++i;
--i;

So operadores usados com ponteiros, para acesso a endereos de memria.


Operador

&
*

Significado

endereo de uma varivel


contedo do endereo especificado

Exemplos:
int var, *x;
x = &var;
var = *x;

2.7 Tabela de Operadores da Linguagem C


+
!
~
&
*
sizeof
++
-*
/
/
%
+
>>
<<
>
>=
<
<=
==
!=
&
|
^
&&
||
=
OP=

Operador

Funo
menos unrio
mais unrio
negao lgica
bitwise not
endereo de
referncia a ptr
tamanho de var
incremento
decremento
multiplicao
diviso inteira
diviso real
resto da diviso
soma
subtrao
shift right
shift left
maior que
maior ou igual a
menor que
menor ou igual a
igual a
diferente de
bitwise AND
bitwise OR
bitwise XOR
logical AND
logical OR
assinalamento
assinalamento

Exemplo C
a = -b;
a = +b ;
! flag
a = ~b ;
a = &b ;
a = *ptr ;
a = sizeof(b) ;
++a; ou a++;
--a; ou a--;
a = b * c;
a = b / c;
a = b / c;
a = b % c;
a = b + c;
a = b c;
a = b >> n;
a = b << n;
a>b
a >= b
a<b
a <= b
a == b
a != b
a = b & c;
a = b | c;
a = b ^ c;
flag1 && flag2
flag1 || flag2
a = b;
a OP= b;

2.8 Expresses
Operadores, constantes e variveis constituem expresses. Uma expresso em C
qualquer combinao vlida dessas partes. Uma vez que muitas expresses tendem a seguir
as regras gerais da lgebra, estas regras so freqentemente consideradas. Entretanto,
existem alguns aspectos das expresses que esto especificamente relacionadas com a
linguagem C e sero discutidas agora.

2.8.1 Converses de Tipos em Expresses


Quando constantes e variveis de tipos diferentes so misturadas em uma expresso,
elas so convertidas para o mesmo tipo. O compilador C converter todos os operandos
para o tipo do operando maior. Isso feito na base de operao a operao, como descrito
nestas regras de converso de tipos:
Todos os chars e shor ints so convertidos para ints.
Todos os floats so convertidos para doubles;
Para todos os pares de operandos, se um deles um long double, o outro operando
convertido para uma long double. Se um dos operandos double, o outro convertido
para double. Se um long, o outro convertido para long. Se um unsigned, o outro
convertido para unsigned.
Uma vez que essas regras de converso tenham sido aplicadas, cada par de
operandos ser do mesmo tipo e o resultado de cada operao ter o mesmo tipo dos dois
operandos. Note que a regra 2 tem muitas condies que devem ser aplicada em seqncia.
Por exemplo, considere a converso de tipos que ocorre na expresso a seguir:

Primeiro, o caractere ch convertido para um inteiro e float f convertido para


double. Ento, o resultado de ch/i convertido para um double, j que f * d um double.

O resultado final um double, tendo em vista que, neste caso, os dois operandos so
double.

2.8.2 - Modeladores (CASTS)


possvel forar uma expresso a ser de um tipo especfico usando-se uma
construo chamada de modelador. A forma geral de um modelador :
(tipo) expresso
(float) x / 2;

Onde tipo um dos tipos dado-padro da linguagem C. Por exemplo, se x um


inteiro e voc quer certificar-se de que a expresso x/2 resulta em um tipo float, garantindo
um componente fracionrio, pode escrever:
Aqui, o modelador (float) associado com o x, o que faz com que o 2 seja elevado
ao tipo float e o resultado seja um float. Entretanto, tome cuidado: se voc escrever a
expresso acima como segue, o componente fracionrio no ser considerado:
(float) (x / 2);

float.

Neste caso, uma diviso de inteiros levada a cabo e o resultado transformado em

Modeladores so freqentemente considerados como operadores. Como um


operador, um modelador unrio e tem a mesma precedncia de qualquer outro operador
unrio.

2.8.3 Espaamento e Parnteses


Pode-se colocar espaos numa expresso para torn-la mais legvel. O uso de
parnteses redundantes ou adicionais no causar erros ou diminuir a velocidade de
execuo da expresso. estimulado o uso de parnteses para tornar clara e exata a ordem
de avaliao, tanto para voc como para outros que precisarem entender o seu programa
mais tarde. Por exemplo, as duas expresses seguintes so as mesmas:
x=645/(num_entry)-y*(3217/balance);
x = 645 / (num_entry) y * (3127 / balance);

Qual das duas expresses seguintes mais fcil de ler?


x=y/3-24*temp-127;
x = (y/3) (34*temp) 127;

2.9 Sntese do Mdulo


apresentada, a seguir, uma sntese do que foi tratado em cada item deste mdulo.
Com esta sntese voc poder relembrar conceitos vistos durante nosso estudo ou mesmo
direcionar seu estudo, caso voc j tenha conhecimentos na Linguagem C.
1 2.1 Palavras Reservadas em Linguagem C: foi visto neste item, que na
Linguagem C existem palavras que so de uso reservado, ou seja, referenciam comandos ou
aes e, portanto, no podem ser usadas pelo programador para referenciar por exemplo
uma varivel em um determinado programa. Foi apresentado uma tabela relacionando as
palavras reservadas da Linguagem C.
2 2.2 Nomes e Identificadores Usados na Linguagem C: a Linguagem C
chama o que usado para referenciar variveis, funes, rtulos e vrios outros objetos
definidos pelo usurio de identificadores. Em C os primeiros 32 caracteres de um nome de
identificador so significantes. Um identificador no pode ser o mesmo que uma palavra
reservada e no devem ter o mesmo nome de uma funo.
3 2.3 Tipos e Dados: variveis so instncias em que sero armazenados
valores utilizados durante a execuo de programas. Estas variveis podem ser modificadas
para suportar diferentes tipos de dados. Foi visto que os tipos bsicos de dados da
Linguagem C so: char, int, float, doubl, void.
4 2.3.1 Modificadores de Tipos: possuindo os tipos bsicos de dados, pode-se
ainda format-los para atender melhor as necessidades de cada situao. Com exceo do
tipo void, todos os outros tipos bsicos podem ter modificadores precedendo-os. Foi
apresentado uma tabela mostrando todas as combinaes permitidas dos tipos bsicos e
dos modificadores de tipo.
5 2.4 Definio de Variveis: foi visto que variveis so instncias onde o
programa em execuo coloca os dados que esto sendo processados durante sua execuo.
As variveis devem ser declaradas, ou seja, devem ser definidos nome, tipo e algumas
vezes seu valor inicial. As variveis so classificadas em variveis locais e globais.
6 2.5 Definio de Constantes: definimos uma constante quando atribumos
um certo valor constante um nome. Quando este nome referenciado dentro de um
programa, ser utilizado nas operaes o valor atribudo a este nome.
7 2.5.1 Constantes Hexadecimais e Octais: em programao algumas vezes
comum usar um sistema de numerao baseado em 8 ou 16 em vez de 10. Por causa da
freqncia com que estes dois sistemas numricos so usados, a linguagem C permite que
se especifique constantes inteiro em hexadecimal ou octal em vez de decimal, se preferir.
8 2.5.2 Constantes Strings: Outro tipo de constante suportada pela Linguagem
C o tipo string. Uma string um conjunto de caracteres entre aspas. Por exemplo, voc
um vencedor uma string.
9 2.5.3 Cdigos de Barra Invertida: colocar todas as constantes caractere entre
aspas funciona para muitos caracteres, mas alguns, como o retorno de carro, so
impossveis de serem inseridos em uma string a partir do teclado. Por isso, a linguagem C
fornece constantes caractere mais barra invertida especiais. Estes cdigos foram mostrados
em uma tabela.

10 2.6 Operadores: Um operador um smbolo que diz ao compilador para


realizar manipulaes matemticas e lgicas especficas. A linguagem C possui trs classes
gerais de operadores: aritmticos, relacionais e lgicos e bit-a-bit.
11 2.6.1 Operador de atribuio: o operador = atribui um valor ou resultado
de uma expresso contida a sua direita para a varivel especificada a sua esquerda.
12 2.6.2 Operadores Aritmticos: so aqueles que operam sobre nmeros e
expresses, resultando valores numricos.
13 2.6.3 Operadores Relacionais: operam sobre expresses, resultando valores
lgicos de TRUE (verdadeiro) ou FALSE (falso).
14 2.6.4 Operadores Lgicos: operam sobre expresses, resultando valores
lgicos de TRUE (verdadeiro) ou FALSE (falso). Possuem a caracterstica de short
circuit, ou seja, sua execuo curta e s executada at o ponto necessrio.
15 2.6.5 Manipulao de bits: a manipulao feita em todos os bits da varivel
a qual no pode ser do tipo float ou double. Os operadores que manipulam bits foram
relacionados em uma tabela.
16 2.6.6 Operadores de assinalamento: assinalam o uso de uma operao,
combinando operadores de tal forma a diminuir o cdigo e facilitar sua posterior
compreenso.
17 2.6.7 Operadores de Pr e Ps-Incremento: operadores de pr e psincremento so aqueles usados quando necessrio incrementar ou decrementar um
determinado valor.
18 2.6.8 Operadores de Endereo: so operadores usados com ponteiros, para
acesso a endereos de memria.
19 2.7 Tabela de Operadores da Linguagem C: foi apresentada uma tabela
com os operadores disponveis na Linguagem C.
20 2.8 Expresses: operadores, constantes e variveis constituem expresses.
Uma expresso em C qualquer combinao vlida dessas partes.
21 2.8.1 Converses de Tipos em Expresses: quando constantes e variveis de
tipos diferentes so misturadas em uma expresso, elas so convertidas para o mesmo tipo.
O compilador C converter todos os operandos para o tipo do operando maior.
22 2.8.2 Modeladores (CASTS): possvel forar uma expresso a ser de um
tipo especfico usando-se uma construo chamada de modelador. Modeladores so
freqentemente considerados como operadores. Como um operador, um modelador
unrio e tem a mesma precedncia de qualquer outro operador unrio.
2.8.3 Espaamento e Parnteses: pode-se colocar espaos numa expresso para torn-la
mais legvel. O uso de parnteses redundantes ou adicionais no causar erros ou diminuir

Mdulo 3 Funes na

a velocidade de execuo da expresso.

Linguagem C

3.1 Funes
A maioria dos programas apresentam a funo main. Quando os programas tornamse maiores e mais complexos, pode-se melhorar a clareza e compreenso do trabalho
dividindo-o em partes menores, chamadas funes. Vamos citar o exemplo de um
determinado programa, suponha um programa de contabilidade. Poderia haver no programa
uma funo que efetuasse as operaes normais de um contador, uma funo diferentes
para contas a pagar, uma terceira para contas a receber e uma quarta para gerar um balano.
Se fossem colocados todos os comandos do programa dentro da funo main, o programa
ficaria muito grande, e seria difcil de compreende-lo. medida que o tamanho e a
complexidade do programa aumentam, aumenta tambm a possibilidade de erros. Se o
programa for dividido em blocos menores e mais facilmente gerenciveis, poder evitar
erros. Uma funo uma coleo nomeada de comandos que efetuam uma tarefa
especfica. Por exemplo, a funo ola_mundo, usa a funo printf para exibir uma
mensagem:
void ola_mundo (void)
{
printf(Ol mundo!\n);
}

A palavra chave void diz a Linguagem C que a funo no retorna um valor. Em


muitos casos, as funes usaro return para retornar o valor de um clculo para a funo
chamadora. Se a funo no usa return para retornar um resultado, deve-se preceder o
nome da funo com void. O void que aparece nos parmetros diz que a funo no usa
parmetros. Um parmetro a informao que o programa passa para a funo. Por
exemplo, quando os programas chamam printf, as informaes que se especifica dentro dos
parnteses so parmetros. Quando uma funo no usa parmetros, deve-se colocar void
dentro dos parnteses. Para usar uma funo, especifica-se o nome da funo seguido de
parnteses. Os programadores referenciam o uso de uma funo como uma chamada da
funo. O programa a seguir, usa a funo oi_pessoal:
#include <stdio.h>
void ola_pessoal(void)
{
printf("Ola pessoal!\n");
}
void main(void)
{
ola_pessoal();
}

Ao executar esse programa, a funo main executada primeiro. Como se pode ver,
o nico comando em main a chamada da funo oi_pessoal. Quando C encontra a
chamada da funo, imediatamente transfere a execuo do programa para a funo,
iniciando a execuo do programa com o primeiro comando da funo. Depois que o
ltimo comando da funo termina, a Linguagem C transfere a execuo para o comando
que segue imediatamente a chamada da funo.

Para compreender melhor esse processo, mude a funo main dentro do programa
anterior como mostrado aqui:
void main(void)
{
printf(Prestes chamar a funo\n);
oi_pessoal();
printf(Voltei da chamada da funo\n);
}

3.2 Variveis dentro das Funes


medida que as funes vo se tornando mais teis nos programas, muitas delas
requerem que as variveis gerem resultados valiosos. Para usar uma varivel dentro de uma
funo, precisa-se primeiro declarar a varivel, exatamente como feito em main.
Por exemplo, o programa a seguir chama a funo trs_olas, que usa a varivel
contador em um lao for para exibir uma mensagem 3 vezes:
#include <stdio.h>
void tres_olas(void)
{
int contador; /* Variavel */
for (contador = 1; contador <= 3; contador++)
printf("Oi pessoal!\n");
}
void main(void)
{
tres_olas();
}

Quando se declara variveis dentro de uma funo, os nomes usados para essas
variveis so exclusivos para a funo.
Portanto, se o programa usa dez funes diferentes e cada funo usa uma varivel
chamada contador, a Linguagem C considera a varivel de cada funo como distinta. Se
uma funo requer muitas variveis, elas devero ser declaradas no incio da funo,
exatamente como se faria dentro de main.

3.3 Main como uma Funo


Quando um programa criado, usa-se o nome da funo main para determinar o
primeiro comando que o programa executar. Na verdade, main uma funo, de modo
que, caso tenha perguntas sobre os tipos de operaes que podem ser executadas dentro das
funes, a regra bem simples: tudo o que se pode fazer em main, pode-se fazer em uma
funo. Exatamente como pode declarar variveis em main, tambm pode declarar
variveis nas funes. Tambm possvel utilizar construes tais como if, while, e for em
suas funes. Finalmente, uma funo pode chamar (usar) outra. Por exemplo, o programa
a seguir usa duas funes. Quando o programa inicia, main chama a funo tres_olas, que,

por sua vez, chama a funo oi_pessoal trs vezes para exibir mensagens na tela, como
mostrado aqui:
#include <stdio.h>
void ola_pessoal(void)
{
printf("Ola, pessoal!\n");
}
void tres_olas(void)
{
int contador;
for (contador = 1; contador <= 3; contador++)
ola_pessoal();
}
void main(void)
{
tres_olas();
}

3.4 Introduo aos Parmetros


Um parmetro um valor passado a uma funo. A maioria dos programas
apresentados passou parmetros para a funo printf. medida que o uso de funes for
maior, poder passar parmetros para as funes de modo a torn-las mais teis. Por
exemplo, considere a seguinte construo da funo tres_olas, que chama a funo
oi_pessoal trs vezes:
void tres_olas(void)
{
int contador;
for (contador = 1; contador <= 3; contador++)
ola_pessoal();
}

Uma funo mais til permite especificar, como um parmetro, o nmero de vezes
que quer que o programa exiba a mensagem. Para usar um parmetro, a funo precisa
especificar o nome e o tipo do parmetro, como mostrado aqui:
void ola_conta(int msg_conta)

Neste caso, a funo ola_conta suporta um parmetro do tipo int chamado


msg_conta. Quando outra funo, tal como main, quiser usar ola_conta, a funo precisa
especificar o valor que a Linguagem C atribui para o parmetro msg_conta:
ola_conta(2);
ola_conta(100);
ola_conta(1);

/*Exibe a mensagem 2 vezes*/


/*Exibe a mensagem 100 vezes*/
/*Exibe a mensagem uma vez*/

O programa a seguir ilustra como pode usar uma funo com um parmetro:

#include <stdio.h>
void oi_pessoal(void)
{
printf("Ola, pessoal!\n");
}
void ola_conta(int msg_conta)
{
int contador;
for (contador = 1; contador <= msg_conta; contador++)
oi_pessoal();
}
void main(void)
{
printf("Exibe a msg duas vezes\n");
ola_conta(2);
printf("Exibe a msg cinco vezes\n");
ola_conta(5);
}

3.5 Parmetros Mltiplos


Em geral, pode-se passar um nmero irrestrito de parmetros para uma funo. No
entanto, as pesquisas mostram que, quando o nmero de parmetros excede sete, a funo
mostra-se mais difcil de se compreender e usar corretamente, ficando, portanto, mais
susceptvel a erros. Quando a funo usa mais de um parmetro, precisa especificar o tipo e
o nome de cada parmetro e separar os parmetros por vrgulas, como mostrado aqui:
void uma_funcao(int idade, float sal, int num_cargo)
{
/*Comandos da funo*/
}

Quando o programa chamar a funo, ser necessrio especificar valores para cada
parmetro, como mostrado aqui:
uma_funcao(33, 40000.00, 534);

3.6 Retornando um Valor de uma Funo

Funes mais complexas normalmente realizam clculos e retornam resultados. Pra


fornecer um resultado ao chamador, uma funo precisar usar o comando return que ser
implementado como segue:
return (resultado);

O tipo de valor que a funo retorna (int, float, char, etc.) determina o tipo da
funo. Por exemplo, se uma funo retorna um valor do tipo int, necessrio preceder o
nome da funo com o nome do tipo, como mostrado aqui:

int uma_funo(int valor)


{
/*Comandos da funo*/
}

A funo a seguir, retorna o cubo do valor inteiro que o programa especifica como
seu parmetro. Por exemplo, se o chamador passar o valor 5 para a funo, a funo
retornar o valor 5*5*5, ou 125:
int i_cubo(int valor)
{
return (valor *valor *valor);
}

Como visto, a funo usa o comando return para retornar o resultado do clculo ao
chamador. O cdigo dentro da funo de chamada pode atribuir o resultado da funo
chamada (tambm conhecido como valor de retorno) a uma varivel, ou o cdigo pode usar
o valor de retorno dentro de uma terceira funo, tal como printf, como mostrado aqui:
result = i_cubo(5);
printf(O cubo de 5 %d\n, I_cubo(5));

O programa a seguir usa a funo i_cubo para determinar vrios valores diferentes
ao cubo:
#include <stdio.h>
int i_cubo(int valor)
{
return(valor * valor * valor);
}
void main(void)
{
printf("O cubo de 3 %d\n", i_cubo(3));
printf("O cubo de 5 %d\n", i_cubo(5));
printf("O cubo de 7 %d\n", i_cubo(7));
}

Os valores que so passados para uma funo precisam corresponder aos tipos de
parmetros contidos dentro da declarao dessa funo. Por exemplo, se quiser determinar
o cubo de um valor em ponto flutuante, crie uma segunda funo chamada f_cubo, como
mostrado a seguir (observe que o valor de retorno tambm do tipo float):

float f_cubo(float valor)


{
return (valor *valor *valor);
}

3.7 Comando Return


Quando a Linguagem C encontra um comando return em uma funo, ela finaliza
imediatamente a execuo da funo e retorna o valor especificado para o chamador. O
programa no executa quaisquer outros comandos dentro da funo aps o comando
return. Em vez disso, ele continua a execuo da funo chamadora.
Outros programas possuem funes que contm mltiplos comandos return, cada
um dos quais retornando um valor para uma condio especfica. Por exemplo, considere a
funo compara_valores, mostrada a seguir:
int compara_valores(int primeiro, int segundo)
{
if (primeiro == segundo)
return (0);
else if (primeiro > segundo)
return (1);
else if (primeiro < segundo)
return (2);
}

A funo compara_valores examina dois valores listados na tabela abaixo:


Resultado
0
1
2

Significado
Os valores so iguais
O primeiro valor maior que o segundo
O segundo valor maior que o primeiro

Como regra, deve-se tentar limitar as funes a usar somente um comando return.
medida que as funes se tornarem maiores e mais complexas, ter muitos comandos
return normalmente tornar as funes mais difceis de compreender. Na maioria dos
casos, pode-se reescrever a funo para que ela use somente um comando return, como
mostrado aqui:
int compara_valores(int primeiro, int segundo)
{
int result;
if (primeiro == segundo)
return = 0;
else if (primeiro > segundo)
return = 1;
else if (primeiro < segundo)
return = 2;
return(result);
}

Neste caso, como a funo simples, pode-se ter dificuldades em compreender qual
a vantagem de usar um nico comando de return. No entanto, medida que as funes se
tornarem mais complexas, a vantagem ficar mais clara. Pode-se observar que, algumas

vezes, usar mais de um comando return produz um cdigo mais legvel do que a alternativa
de um nico return. Deve-se escrever o cdigo mais legvel e facilmente modificvel
quanto possvel; se usar mltiplos return atingir os objetivos pr-estabelecidos, ento utilize
quantos comandos return forem necessrios.

3.8 Prottipos de Funo


A maioria dos novos compiladores C precisa conhecer os tipos de retorno e de
parmetro de uma funo antes do programa chamar a funo.Colocando as funes antes
dos seus chamadores dentro do cdigo do seu programa, permitir que o compilador C
conhea as informaes que ele dever ter antes de encontrar a chamada da funo. No
entanto, medida que os programas ficam mais complexos, pode se tornar impossvel
colocar as funes sempre na ordem correta. Portanto, a Linguagem C permite colocar
prottipos de funo no seu programa, para descrever os tipos de parmetro e de retorno de
uma funo. Por exemplo, considere um programa que use as funes i_cubo e f_cubo.
Antes que a funo seja usada pela primeira vez, o programa pode incluir um prottipo
semelhante ao seguinte:
int i_cubo(int);
float f_cubo(float);

/*Retorna um parmetro int*/


/* Retorna um parmetro float*/

Como pode-se ver, o prottipo da funo especifica os tipos de parmetro e de


retorno da funo. O programa a seguir usa dois prottipos de funo para eliminar a
necessidade de ordem da funo:
#include <stdio.h>
int i_cubo(int);
float f_cubo(float);
void main(void)
{
printf("O cubo de 3 %d\n", i_cubo(3));
printf("O cubo de 3.7 %f\n", f_cubo(3.7));
}
int i_cubo(int valor)
{
return(valor * valor * valor);
}
float f_cubo(float valor)
{
return(valor * valor * valor);
}

3.9 Biblioteca de Execuo


Muitas vezes, uma funo criada para um determinado programa atende as
necessidades de um segundo programa. A capacidade de reutilizar as funes em mais de
um programa pode poupar um tempo considervel de programao e teste. Para isto s
copiar a funo de um para outro programa.

Antes de gastar um tempo enorme desenvolvendo uma ampla variedade de funes


de propsito geral, no deixe de examinar as funes que seu compilador fornece. Muitos
compiladores referenciam essas funes internas como biblioteca de execuo. A maioria
dos compiladores fornece centenas de funes de biblioteca de execuo com propsito que
vo de abertura e trabalho com arquivos para acessar informaes do disco ou de diretrio
para determinar o tamanho de uma string de caracteres. As duas ou trs horas que sero
gastas para ler a documentao da biblioteca de execuo pouparo muitas horas de
programao.

3.10 Funes que no retornam Int


Muitas funes retornam valores do tipo int. Quando uma determinada funo no
retorna um valor do tipo int (em vez disso ela pode retornar float, double, char, etc.)
precisa-se informar ao compilador o tipo de retorno da funo. O programa a seguir usa a
funo valor_medio para determinar a mdia de trs valores do tipo int. A funo retorna a
mdia usando um valor do tipo float (repare que o cabealho da funo especifica o tipo de
retorno da funo):
#include <stdio.h>
float valor_medio(int a, int b, int c)
{
return ((a + b + c) / 3.0);
}
void main(void)
{
printf("A mdia de 100, 133 e 155 %f\n",
valor_medio(100, 133, 155));
}

3.11 Variveis Locais


A Linguagem C permite declarar variveis dentro de suas funes. Essas variveis
so chamadas de variveis locais, pois seus nomes e valores somente tm significado dentro
da funo que contm a declarao da varivel. O programa a seguir ilustra o conceito de
uma varivel local. A funo valores_locais declara 3 variveis a, b e c, e atribui s
variveis os valores 1, 2 e 3, respectivamente. A funo main tenta imprimir o valor de
cada varivel. No entanto, como os nomes dos valores so locais funo, o compilador
gera erros, dizendo que os smbolos a, b, e c esto indefinidos.
#include <stdio.h>
void valores_locais(void)
{
int a=1, b=2, c=3;
printf("a contm %d b contm %d c contm %d\n", a,b,c);
}
void main(void)

{
printf("a contm %d b contm %d c contm %d\n", a,b,c);
}

3.12 - Sobrecarga da Funo


Quando um programa usa uma funo, a Linguagem C armazena o endereo de
retorno, os parmetros e as variveis locais na pilha. Quando a funo termina, a
Linguagem C descarta o espao da pilha que continha as variveis locais e parmetros, e,
depois, usa o valor de retorno para retornar a execuo do programa para a posio correta.
Embora o uso da pilha seja poderoso porque permite que o programa chame e passe
as informaes para as funes, tambm consome tempo de processamento. Os
programadores chamam a quantidade de tempo que o computador requer para colocar e
retirar informaes da pilha de sobrecarga da funo. Para compreender melhor o impacto
da sobrecarga da funo no desempenho do seu programa, considere o programa a seguir.
Primeiro o programa usa um lao para somar os valores de 1 a 100.000. Em seguida, repete
um lao novamente, mas usa uma funo para somar os valores, como mostrado aqui:

#include <stdio.h>
#include <time.h>
float soma(long int a, float b)
{
float result;
result = a + b;
return(result);
}
void main(void)
{
long int i;
float result = 0;
time_t hora_inicio, hora_parada;
printf("Trabalhando...\n");
time(&hora_inicio);
for (i = 1; i <= 100000L; i++)
result += i;
time(&hora_parada);
printf("Usando lao %d segundos\n", hora_parada - hora_inicio);
printf("Trabalhando...\n");
time(&hora_inicio);
for (i = 1; i <= 100000L; i++)
result = soma(i, result);

time(&hora_parada);
printf("Usando funo %d segundos \n", hora_parada hora_inicio);
}

Na maioria dos sistemas, os clculos baseados em funes podem requerer quase o


dobro do tempo de processamento. Portanto, quando usar funes dentro dos programas,
necessrio considerar os benefcios que elas oferecem versus a sobrecarga no desempenho
que introduzem.

3.13 Declarando Variveis Globais


Alm das variveis locais, a Linguagem C permite que os programas usem variveis
globais, cujos nomes, valores e existncia so conhecidos em todo o programa. Em outras
palavras, todos os programas em Linguagem C podem usar variveis globais. O programa a
seguir ilustra o uso de trs variveis globais a, b e c:

#include <stdio.h>
int a = 1, b = 2, c = 3;

/* Variaveis globais */

void valores_globais(void)
{
printf("a contm %d b contm %d c contm %d\n", a, b, c);
}
void main(void)
{
valores_globais();
printf("a contm %d b contm %d c contm %d\n", a, b, c);
}

Quando este programa compilado e executado, as funes variaveis_globais e


main exibem os valores da varivel global. Observe que as variveis globais so declaradas
fora de todas as funes. Declarando variveis globais deste modo, todas as funes do
programa podem usar e alterar os valores da varivel global simplesmente referenciando o
nome da varivel global. Embora as variveis globais possam parecer convenientes, o uso
incorreto delas podem causar erros que so difceis de depurar.

3.14 Solucionando os Conflitos de Nomes de Variveis Locais e


Globais

Se um programa usa variveis globais, algumas vezes o nome de uma varivel


global o mesmo que aquele de uma varivel local que seu programa declara dentro de
uma funo. Por exemplo, o programa a seguir usa as variveis globais a, b e c. A funo
conflito_a usa uma varivel local chamada a e as variveis globais b e c:
#include <stdio.h>
int a=1, b=2, c=3;

/* Variveis globais */

void conflito_a(void)
{
int a=100;
printf("a contm %d b contm %d c contm %d\n", a, b, c);
}
void main(void)
{
conflito_a();
printf("a contm %d b contm %d c contm %d\n", a, b, c);
}

Quando nomes de variveis globais e locais estiverem em conflito, a Linguagem C


usar sempre a varivel local. Como voc pode ver, as alteraes que a funo conflito_a
fez na varivel a somente aparecem dentro da funo.

3.15 Chamada por Valor


Os programas passam informaes para funes usando parmetros. Quando um
parmetro passado a uma funo, a Linguagem C usa uma tcnica conhecida como
chamada por valor para fornecer funo uma cpia dos valores dos parmetros. Usando a
chamada por valor, quaisquer modificaes que a funo fizer nos parmetros existem
apenas dentro da prpria funo. Quando a funo termina, o valor das variveis que a
funo chamadora passou para a funo no modificada dentro da funo chamadora. Por
exemplo, o programa a seguir passa trs parmetros (as variveis a, b e c) para a funo
exibe_e_altera. A funo, por sua vez, exibir os valores, somar 100 aos valores e depois
exibir o resultado. Quando a funo terminar, o programa exibir os valores das variveis.
Como a Linguagem C usa chamada por valor, a funo no altera os valores das variveis
dentro do chamador, como mostrado a seguir:
#include <stdio.h>
void exibe_e_altera(int primeiro, int segundo, int terceiro)
{
printf("Valores originais da funo %d %d %d\n",
primeiro, segundo, terceiro);
primeiro += 100;
segundo += 100;
terceiro += 100;
printf("Valores finais da funo %d %d %d\n", primeiro,
segundo, terceiro);
}

void main(void)
{
int a = 1, b = 2, c = 3;
exibe_e_altera(a, b, c);
printf("Valores finais em main %d %d %d\n", a,b,c);
}

Como pode ser visto, as alteraes que a funo faz nas variveis somente so
visveis dentro da prpria funo. Quando a funo termina, as variveis dentro de main
esto inalteradas.

3.16 - Chamada por Referncia


Usando a chamada por valor, as funes no podem modificar o valor de uma
varivel passada para uma funo. No entanto, na maioria dos programas, as funes
modificaro as variveis de um modo ou de outro. Por exemplo, uma funo que l
informaes de um arquivo precisa colocar as informaes em uma matriz de string de
caracteres. Da mesma forma, uma funo tal como strupr precisa converter as letras em
uma string de caractere para maisculas. Quando as funes alteram o valor de um
parmetro, os programas precisam passar o parmetro para a funo usando chamada por
referncia. A diferena entre chamada por valor e chamada por referncia que, usando a
chamada por valor, as funes recebem uma cpia do valor de um parmetro. Por outro
lado, com a chamada por referncia, as funes recebem o endereo de memria da
varivel. Portanto, as funes podem alterar o valor armazenado na posio de memria
especfica (em outras palavras, o valor da varivel); alteraes essas que permanecem aps
a funo terminar. Para usar a chamada por referncia, seu programa precisar usar
Ponteiros. O Mdulo sobre Ponteiros, mais adiante, discute os Ponteiros em detalhes. No
entanto, por ora, pense em um Ponteiro simplesmente como um endereo de memria. Para
atribuir o endereo de uma varivel a um ponteiro, necessrio usar o operador de
endereo "&". Para acessar posteriormente o valor na posio de memria para o qual o
Ponteiro aponta, use o operador de direo "*".

3.17 Obtendo um Endereo


Uma varivel essencialmente um nome atribudo a uma ou mais posies de
memria. Quando um programa roda, cada varivel reside em um seu prprio endereo de
memria. O programa localiza as variveis na memria usando o endereo de memria da
varivel. Para determinar o endereo de uma varivel, usa-se o operador de endereo "&".
Por exemplo, o programa a seguir usa o operador de endereo para exibir o endereo (em
hexadecimal) das variveis a., b e c:
#include <stdio.h>
void main(void)
{
int a=1, b=2, c=3;

printf("O endereo de a %x o valor de a %d\n", &a, a);


printf("O endereo de b %x o valor de b %d\n", &b, b);
printf("O endereo de c %x o valor de c %d\n", &c, c);
}

Para os programas passarem parmetros para funes cujos valores a funo precisa
alterar, os programas passaro as variveis por referncia (endereo de memria), usando o
operador de endereo, como mostrado a seguir:
alguma_funcao(&a, &b, &c);

3.18 Usando um Endereo de Memria


Quando se passa um endereo para uma funo, precisa-se informar ao compilador
que a funo estar usando um ponteiro (o endereo de memria) de uma varivel, e no o
valor de uma varivel. Para fazer isto, necessrio declarar uma varivel ponteiro. Declarar
uma varivel ponteiro muito similar declarao de uma varivel padro, em que se
especifica um tipo e o nome da varivel. A diferena, no entanto, que um asterisco (*)
precede os nomes das variveis ponteiro. As declaraes a seguir criam variveis ponteiro
do tipo int, float e char:
int *i_ponteiro;
float *f_ponteiro;
char *c_ponteiro

Aps declarar uma varivel ponteiro, precisa atribuir um endereo de memria


ela. Por exemplo, o comando a seguir, atribui o endereo da varivel inteira a varivel
ponteiro i_ponteiro:
i_ponteiro = &a;

Em seguida, para usar o valor apontado para a varivel ponteiro, os programas


precisam usar o operador de redireo da Linguagem C - o asterisco (*). Por exemplo, o
comando a seguir atribui o valor 5 varivel a (cujo endereo est contido na varivel
i_ponteiro):
i_ponteiro = 5;

De um modo similar, o comando a seguir atribui varivel b o valor ao qual a


varivel i_ponteiro aponta atualmente:
b = *i_ponteiro;

Quando quiser usar o valor apontado por uma varivel ponteiro, usa-se o operador
de redireo (*). Quando quiser atribuir o endereo de uma varivel uma varivel
ponteiro, usa-se o operador de endereo (&). O programa a seguir ilustra o uso de uma
varivel ponteiro. Ele atribui varivel ponteiro i_ponteiro o endereo da varivel O
programa ento usa a varivel ponteiro para alterar, exibir e atribuir o valor da varivel:
#include <stdio.h>
void main(void)
{
int a = 1, b = 2;

int *i_ponteiro;
i_ponteiro = &a;
*i_ponteiro = 5;
para 5 */

/* Atribui um endereo*/
/* Altera o valor apontado por i_ponteiro

printf("O valor apontado por i_ponteiro %d a variavel a


%d\n",*i_ponteiro, a);
/* Exibe o valor */
b = *i_ponteiro;
/* Atribui o valor */
printf("O valor de b %d\n", b);
printf("Valor de i_ponteiro %x\n", i_ponteiro);
}

3.19 Alterando o Valor de um Parmetro

Como foi visto anteriormente, para alterar o valor de um parmetro dentro de uma
funo, os programas precisam usar a chamada por referncia, passando o endereo da
varivel. Dentro da funo, precisa-se usar ponteiros. O programa a seguir usa ponteiros e
endereos (chamada por referncia) para exibir e, depois, alterar os parmetros que o
programa passa para a funo exibe_e_altera:

#include <stdio.h>
void exibe_e_altera(int *primeiro, int *segundo, int *terceiro)
{
printf("Valores originais da funo %d %d %d\n",*primeiro,
*segundo, *terceiro);
*primeiro += 100;
*segundo += 100;
*terceiro += 100;
printf("Valores finais da funo %d %d %d\n",*primeiro,
*segundo, *terceiro);
}
void main(void)
{
int a=1, b=2, c=3;
exibe_e_altera(&a, &b, &c);
printf("Valores finais em main %d %d %d\n", a, b ,c);
}

3.20 Alterando Somente Parmetros Especficos


Como foi visto, as funes podem modificar o valor de um parmetro usando a
chamada por referncia. Por exemplo, o item anterior, apresentou a funo exibe_e_altera,
que usou chamada por referncia para alterar o valor de cada um de seus parmetros. No
entanto, em muitos casos, suas funes podem alterar o valor de um parmetro e ao mesmo
tempo deixar o valor de um segundo parmetro inalterado. Por exemplo, o programa a
seguir usa a funo muda_primeiro para atribuir ao parmetro primeiro o valor do
parmetro segundo:
#include <stdio.h>

void muda_primeiro(int *primeiro, int segundo)


{
*primeiro = segundo;
/* Atribui o valor de segundo a primeiro */
}
void main(void)
{
int a = 0, b = 5;
muda_primeiro(&a, b);
printf("Valor de a %d

valor de b %d\n", a, b);

Como pode ser visto, a funo muda_primeiro usa a chamada por referncia para
alterar o valor do parmetro primeiro, e chamada por valor para o parmetro segundo.
Quando os programas usam ambas as tcnicas, precisa ter-se em mente quando usar
ponteiros e quando referenciar diretamente a varivel. Como regra, os parmetros cujos
valores sero alterados iro requerer chamada por referncia. Para compreender melhor o
impacto da chamada por referncia versus chamada por valor, modifique a funo
muda_primeiro, como mostrado aqui:
void muda_primeiro(int *primeiro, int segundo)
{
*primeiro = segundo; /*Atribui o valor de segundo a primeiro*/
segundo = 100;
}

Quando este programa for compilado e executado, ver que o valor de primeiro foi
alterado, mas o valor de segundo no foi. Como o parmetro segundo foi passado usando
chamada por valor, a alterao do parmetro visvel fora da funo.

3.21 Funes Recursivas


Em C, as funes podem chamar a si prprias. Uma funo recursiva se um
comando no corpo da funo chama ela mesma. Algumas vezes chamada de definio
circular, a recursividade o processo de definio de algo em termos de si mesmo.
Exemplos de recursividade existem em grande nmero. Uma maneira de definir um
nmero inteiro sem sinal por meio de recursividade utilizando-se os dgitos 0, 1, 2, 3, 4, 5,
6, 7, 8, 9 mais ou menos outro nmero inteiro. Por exemplo, o nmero 15 o nmero 7
mais o nmero 8; 21 9 mais 12 e 12 9 mais 3.
Para uma linguagem ser recursiva, uma funo deve estar apta a chamar a si prpria.
O exemplo clssico de recursividade mostrado na funo fatorial_recursivo(), que calcula
o fatorial de um nmero inteiro. O fatorial de um nmero N o produto de todos os
nmeros inteiros entre 1 e N. Por exemplo, o fatorial de 3 1 x 2 x 3, ou 6. Tanto a funo
fatorial_recursivo( ) como sua equivalente interativa so mostradas aqui:
#include <stdlib.h>
#include <stdio.h>
unsigned long int fatorial_recursivo (int n){
unsigned long int resposta;

if ((n == 1) || (n == 0))return(1);
resposta = n * fatorial_recursivo(n 1);
return(resposta);
void main()
{
unsigned long f;
int n;
printf(Digite um nmero: );
scanf(%d,&n);
f = fatorial_recursivo(n);
printf(O fatorial de %d %ld\n, n, f);
}

#include <stdlib.h>
#include <stdio.h>
unsigned long int fatorial (int n){
unsigned long int t, resposta;
resposta = 1;
for (t = 1; t < n; t++) resposta = resposta * t;
return(resposta);
void main()
{
unsigned long f;
int n;
printf(Digite um nmero: );
scanf(%d,&n);
f = fatorial(n);
printf(O fatorial de %d %ld\n, n, f);
}

Quando uma funo chama a si prpria, as novas variveis locais e os argumentos


so alocados na pilha, e o cdigo da funo executado com esses novos valores a partir do
incio. Uma chamada recursiva no faz uma nova cpia da funo. Somente os argumentos
e as variveis so novos. Quando cada chamada recursiva retorna, as antigas variveis
locais e os parmetros so removidos da pilha e a execuo recomea no ponto de chamada
da funo dentro da funo.
Tendo em vista que o local para os argumentos de funes e para as variveis locais
a pilha e que a cada nova chamada criado uma cpia destas variveis na pilha,
possvel ocorrer overflow da pilha (stack overflow) e o programa terminar com um erro.

3.22 Sntese do Mdulo


apresentado seguir, uma sntese do que foi tratado em cada item deste mdulo.
Com esta sntese voc poder relembrar conceitos vistos durante nosso estudo ou mesmo
direcionar seu estudo, caso voc j tenha conhecimentos na Linguagem C.
24 3.1 Funes: dada uma explicao detalhada sobre as caractersticas gerais
de funes na Linguagem C.

25 3.2 Variveis dentro das Funes: foi visto que possvel e muito valioso o
uso de variveis dentro das funes. Foi mostrado que as variveis declaradas dentro de
uma funo, so vlidas apenas para aquela funo.
26 3.3 Main como uma Funo: foi visto que quando um programa criado,
usa-se o nome da funo main para determinar o primeiro comando que o programa
executar. A funo main a principal funo em um programa.
27 3.4 Introduo aos Parmetros: foi visto que um parmetro uma valor
passado a uma funo. Com eles a funo se torna mais til ao programa e facilita vria
operaes.
28 3.5 Parmetros Mltiplos: foi mostrado que em geral, pode-se passar um
nmero irrestrito de parmetros para uma funo. Quando a funo usa mais de um
parmetro, precisa especificar o tipo e o nome de cada parmetro e separar os parmetros
por vrgulas.
29 3.6 Retornando um Valor de uma Funo: foi visto que funes usam o
comando return para retornar o resultado do clculo ao chamador. O tipo de valor que a
funo retorna (int, float, char, etc.) determina o tipo da funo. Os valores que so
passados para uma funo precisam corresponder aos tipos de parmetros contidos dentro
da declarao dessa funo.
30 3.7 Comando Return: foi visto que quando a Linguagem C encontra um
comando return em uma funo, ela finaliza imediatamente a execuo da funo e retorna
o valor especificado para o chamador. O programa no executa quaisquer outros comandos
dentro da funo aps o comando return. Em vez disso, ele continua a execuo da funo
chamadora.
31 3.8 Prottipos de Funo: foi explicado que o prottipo de uma funo
especifica os tipos de parmetro e de retorno da funo.
32 3.9 Biblioteca de Execuo: foi explicado que a maioria dos compiladores
fornece centenas de funes de biblioteca de execuo com propsito que vo de abertura e
trabalho com arquivos para acessar informaes do disco ou de diretrio para determinar o
tamanho de uma string de caracteres, poupando horas de trabalho de programao.
33 3.10 Funes que no Retornam Int: foi visto que quando uma determinada
funo no retorna um valor do tipo int (em vez disso ela pode retornar float, double, char,
etc.) precisa-se informar ao compilador o tipo de retorno da funo.
34 3.11 Variveis Locais: foi explicado que variveis so locais, quando seus
nomes e valores somente tm significado dentro da funo que contm a declarao da
varivel.
35 3.12 Sobrecarga da Funo: foi visto que a quantidade de tempo que o
computador requer para colocar e retirar informaes da pilha de sobrecarga da funo.
Este tempo tem um papel fundamental no desempenho dos programas em execuo.
36 3.13 Declarando Variveis Globais: foi visto que variveis globais so
aquelas cujos nomes, valores e existncia so conhecidos em todo o seu programa. Foi visto
tambm como declar-las.

37 3.14 Solucionando os Conflitos de Nomes de Variveis Locais e Globais:


foi visto que quando nomes de variveis globais e locais estiverem em conflito, a
Linguagem C usar sempre a varivel local.
38 3.15 Chamada por Valor: foi explicado que na chamada por valor, quaisquer
modificaes que a funo fizer nos parmetros existem apenas dentro da prpria funo.
Quando a funo termina, o valor das variveis que a funo chamadora passou para a
funo no modificada dentro da funo chamadora.
39 3.16 Chamada por Referncia: foi visto que quando as funes alteram o
valor de um parmetro, os programas precisam passar o parmetro para a funo usando
chamada por referncia.
40 3.17 Obtendo um Endereo: foi visto que para determinar o endereo de
uma varivel, usa-se o operador de endereo "&".
41 3.18 Usando um Endereo de Memria: foi visto que quando se passa um
endereo para uma funo, precisa-se informar ao compilador que a funo estar usando
um ponteiro (o endereo de memria) de uma varivel, e no o valor de uma varivel. Para
fazer isto, necessrio declarar uma varivel ponteiro.
42 3.19 Alterando o Valor de um Parmetro: foi mostrado um programa que
usa ponteiros e endereos (chamada por referncia) para exibir e, depois, alterar os
parmetros que o programa passa para uma funo.
43 3.20 Alterando Somente Parmetros Especficos: foi mostrado como fazer
para que as funes alterem o valor de um parmetro e ao mesmo tempo deixe o valor de
um segundo parmetro inalterado.
44 3.21 Funes Recursivas: foi explicado que uma funo recursiva se um
comando no corpo da funo chama ela mesma. Alm disso, foi dada uma viso geral sobre
funes recursivas.

Mdulo 4 Funes PRINTF() e SCANF()


4.1 Funo PRINTF()

Quando necessrio imprimir na tela um dado, um valor, uma string ou mesmo um


endereo de memria, usa-se a funo printf(). Quando o programa usa a funo printf(), as
informaes que instrui printf() a imprimir so chamadas parmetros ou argumentos de
printf(). A estrutura bsica da funo printf() dada a seguir:
printf ("string de controle", lista de argumentos);

A string de controle contm tanto caracteres para serem impressos na tela como
cdigos de formato que especificam como apresentar o restante dos argumentos. Quando os
programas trabalharem com variveis, ser possvel usar printf() para exibir os valores de
cada varivel. A funo printf() suporta mais de um parmetro. O primeiro parmetro
precisa ser sempre uma string de caracteres. Pode-se fazer os parmetros que seguem a
primeira string de caracteres serem nmeros, expresses, variveis, ou at outras strings de
caracteres. Quando for necessrio que printf() exiba um valor ou uma varivel, preciso
fornecer informaes sobre o tipo da varivel dentro do primeiro parmetro. Alm de

especificar caracteres dentro do primeiro parmetro, pode-se incluir especificadores de


formato, que instruem printf() como imprimir os outros parmetros. Esses especificadores
de formato tm a forma de um sinal de porcentagem (%) seguido por uma letra. Por
exemplo, para exibir um valor inteiro, usa-se o %d. Da mesma forma para exibir um valor
em ponto flutuante, pode-se usar %f. A seguir, uma tabela com os especificadores de
formato:
Cdigo
%c
%d
%i
%e
%E
%f
%g
%G
%o
%s
%u
%x
%X
%%
%p

Significado

Exibe um caractere
Exibe um inteiro em formato decimal
Exibe um inteiro
Exibe um nmero em notao cientfica (com e minsculo)
Exibe um nmero em notao cientfica (com E maisculo)
Exibe um ponto flutuante em formato decimal
Usa %e ou %f, o que for menor
O mesmo que %g, s que um E maisculo usado se o formato %e
for escolhido
Exibe um nmero em notao octal
Exibe uma string
Exibe um decimal sem sinal
Exibe um nmero em hexadecimal com letras minsculas
Exibe um nmero em hexadecimal com letras maisculas
Exibe um sinal de %
Exibe um ponteiro

4.1.1 Exibindo Valores do Tipo int Usando Printf()


Para exibir valores do tipo int com printf(), usa-se o especificador de formato %d. O
programa a seguir usa o especificador de formato %d para exibir valores e variveis do tipo
int:
#include <stdio.h>
void main(void)
{
int idade = 41;
int altura = 182;
int peso = 80;
printf("Idade do usuario: %d peso: %d altura: %d\n", idade, peso,
altura);
printf("%d mais %d igual a %d\n", 1, 2, 1 + 2);
}

Uma observao importante que muitos compiladores C tratam o especificador de


formato %i como idntico a %d. No entanto, para criar-se novos programas , use o
especificador %d, pois %i um legado do passado, e os compiladores futuros talvez
deixem de aceit-lo.

4.1.2 Exibindo um Valor Inteiro Octal ou Hexadecimal

Muitas vezes nos programas preciso exibir um valor inteiro em seu formato octal
(base 8) ou hexadecimal (base 16). O especificador de formato %o (letra "o", no zero)
instrui printf() a exibir uma valor em octal. Da mesma forma, %x e %X instruem printf() a
exibir uma valor em hexadecimal, sendo que no primeiro caso em minsculo e no segundo
imprime os valores em maisculo.
Veja a seguir um exemplo que utiliza estes especificadores de formato:
#include <stdio.h>
void main(void)
{
int valor = 255;
printf("O valor decimal %d em octal %o\n", valor, valor);
printf("O valor decimal %d em hexadecimal %x\n", valor, valor);
printf("O valor decimal %d em hexadecimal %X\n", valor, valor);
}

4.1.3 Exibindo Valores do Tipo Unsigned Int


Para exibir valores do tipo unsigned int com a funo printf(), deve-se usar o
especificador de formato %u. Se usar %d em lugar de %u, printf() tratar o valor
especificado como tipo int, provavelmente exibindo o valor incorreto. O exemplo a seguir
ilustra o uso dos dois especificadores, %d e %u.
#include <stdio.h>
void main(void)
{
unsigned int valor = 42000;
printf("Exibindo 42000 como unsigned %u\n", valor);
printf("Exibindo 42000 como int %d\n", valor);
}

4.1.4 Exibindo Valores do Tipo Long Int


Para exibir valores do tipo long int com a funo printf(), deve-se usar o
especificador de formato %ld. Se usar %d em lugar de %ld, printf() tratar o valor
especificado como tipo int, provavelmente exibindo o valor incorreto.
O exemplo a seguir ilustra o uso dos dois especificadores, %d e %ld:

#include <stdio.h>
void main(void)
{
long int um_milhao = 1000000;
printf ("Um milho %ld\n", um_milhao);
printf ("Um milho %d\n", um_milhao);
}

4.1.5 Exibindo Valores do Tipo Float


Para exibir valores do tipo float com a funo printf(), deve-se usar o especificador
de formato %f. A seguir um exemplo que usa %f para exibir valores em ponto flutuante.

#include <stdio.h>
void main(void)
{
float preco = 525.75;
float imposto_vendas = 0.06;
printf("O custo do item %f\n", preco);
printf("O imposto sobre a venda do item %f\n", preco *
imposto_vendas);
}

4.1.6 Exibindo Valores do Tipo Char


Para exibir valores do tipo char com a funo printf(), deve-se usar o especificador
de formato %c. A seguir um exemplo que usa %c para exibir a letra A em sua tela.
#include <stdio.h>
void main(void)
{
printf("A letra %c\n", 'A');
printf("A letra %c\n", 65);
}

4.1.7 Exibindo Valores de Ponto Flutuante em um Formato Exponencial


Para exibir um valor em ponto flutuante em um formato exponencial com a funo
printf(), deve-se usar o especificador de formato %e ou %E. A diferena entre os dois
que %E instrui printf() a usar uma letra E maiscula na sada.
#include <stdio.h>
void main(void)
{
float pi = 3.14159;
float raio = 2.0031;
printf("A rea do crculo %e\n", 2 * pi * raio);
printf("A rea do crculo %E\n", 2 * pi * raio);
}

4.1.8 Exibindo Valores em Ponto Flutuante


A funo printf() tambm suporta os especificadores %g e %G para imprimir
valores em ponto flutuante. Quando usa-se esses especificadores de formato, printf()
decide se deve usar o formato %f ou %e, dependendo da tcnica que exibir a sada no
formato mais significativo para o usurio.
Veja o exemplo que ilustra o uso do especificador %g:
#include <stdio.h>
void main(void)
{
printf("Exibir 0.1234 resulta em %g\n", 0.1234);
printf("Exibir 0.00001234 resulta em %g\n", 0.00001234);
}

4.1.9 Exibindo uma String de Caracteres


Para exibir uma string de caracteres com a funo printf(), deve-se usar o
especificador de formato %s.
A seguir um exemplo que usa %s para exibir uma string de caracteres:
#include <stdio.h>
void main(void)
{
char faculdade[255] = "Universidade Estadual Paulista";
printf("O nome da minha universidade %s\n", faculdade);
}

4.1.10 Exibindo um Endereo de Ponteiro


Para exibir um endereo de ponteiro com a funo printf(), deve-se usar o
especificador de formato %p.
A seguir um exemplo que usa %p para exibir um endereo de memria.
#include <stdio.h>
void main(void)
{
int valor;
printf("O endereo da varivel valor %p\n", &valor);
}

4.1.11 - Precedendo um Valor com um Sinal de Adio ou de Subtrao


Em muitos programas necessrio que printf() exiba o sinal para os valores
positivos e negativos. Para instruir printf() a exibir um sinal de um valor, simplesmente
inclua um sinal de adio imediatamente aps o % no especificador de formato. O exemplo
a seguir ilustra o uso do sinal de adio dentro do especificador de formato.
#include <stdio.h>
void main(void)
{
int neg_int = -5;
int pos_int = 5;
float neg_flt = -100.23;
float pos_flt = 100.23;
printf("Os valores inteiros so %+d and %+d\n",neg_int, pos_int);
printf("Os valores em ponto flutuante so %+f %+f\n", neg_flt,
pos_flt);
}

4.1.12 Formatando um Valor Inteiro


Usando o especificador de formato %d, ser possvel instruir printf() a exibir um
nmero mnimo de caracteres. O dgito que for colocado aps o % especifica o nmero
mnimo de caracteres que printf() usar para exibir um valor inteiro. Por exemplo, caso seja
especificado %5d e o valor a ser exibido for 10, printf() predecer o valor com trs espaos.
Observe que o valor especifica o nmero mnimo de caracteres que a sada consumir. Se o
valor a ser exibido requer mais caracteres do que o especificado, printf() usar o nmero de

caracteres que printf() requer para exibir o valor corretamente. Veja um exemplo que ilustra
este caso logo a seguir:
#include <stdio.h>
void main(void)
{
int valor = 5;
printf ("%1d\n",
printf ("%2d\n",
printf ("%3d\n",
printf ("%4d\n",
}

valor);
valor);
valor);
valor);

4.1.13 - Sada de Inteiros Preenchida com Zeros


No item anterior, foi visto como formatar uma sada instruindo printf() a exibir um
determinado nmero de dgitos. No caso anterior, printf() colocava espaos antes do valor a
ser exibido, mas possvel configur-lo de tal maneira que ele exiba zeros antes do valor
ou caracter que necessrio exibir. Esses zeros so chamados de zeros de preenchimento.
Para instruir printf() a preencher um valor com zeros, coloca-se um 0 (zero) imediatamente
aps o % no especificador de formato, antes do nmero desejado de dgitos. O exemplo
abaixo ilustra o uso desta propriedade.
#include <stdio.h>
void main(void)
{
int valor = 5;
printf ("%01d\n",
printf ("%02d\n",
printf ("%03d\n",
printf ("%04d\n",
}

valor);
valor);
valor);
valor);

4.1.14 Exibindo um Prefixo Antes dos Valores Octais ou Decimais


Em muitos programas que apresentam valores octais ou hexadecimais, em muitos
casos necessrio que se preceda os valores em octal com um zero (0777, por exemplo), e
os hexadecimais com 0x (oxFF, por exemplo). Para instruir printf() a preceder um valor
octal ou hexadecimal com o prefixo apropriado, coloca-se um sinal # imediatamente aps o
% no especificador de formato. Veja o exemplo abaixo que ilustra o uso do sinal #.
#include <stdio.h>
void main(void)
{
int valor = 255;
printf("O valor decimal %d em octal %#o\n", valor, valor);
printf("O valor decimal %d em hexadecimal %#x\n", valor, valor);
printf("O valor decimal %d em hexadecimal %#X\n", valor, valor);
}

4.1.15 Formatando um Valor em Ponto Flutuante


No item 3.1.11 foi visto como formatar um valor inteiro colocando o nmero
desejado de dgitos imediatamente aps o % no especificador de formato %d. Usando uma
tcnica similar, printf() permite formatar a sada em ponto flutuante. Quando formata-se um
valor em ponto flutuante especifica dois valores. O primeiro valor diz a printf() o nmero

mnimo de caracteres a serem exibidos. O segundo valor diz a printf() o nmero de dgitos
a serem exibidos direita do ponto decimal. O exemplo abaixo ilustra esta tcnica.
#include <stdio.h>
void main(void)
{
float valor = 1.23456;
printf ("%8.1f\n", valor);
printf ("%8.3f\n", valor);
printf ("%8.5f\n", valor);
}

4.1.16 Formatando a Sada Exponencial


No item anterior foi visto como usar o especificador de formato %f para formatar
valores em ponto flutuante. Usando tcnicas de formatao similares, pode-se instruir
pintf() a exibir a sada em ponto flutuante em um formato exponencial. Veja o exemplo a
seguir que ilustra este caso.
#include <stdio.h>
void main(void)
{
float valor = 1.23456;
printf ("%12.1e\n", valor);
printf ("%12.3e\n", valor);
printf ("%12.5e\n", valor);
}

4.1.17 Justificando Esquerda a Sada de Printf()


Por padro, quando for exibido o texto usando os caracteres de formatao, printf()
exibir o texto justificado direita. Dependendo do programa, algumas vezes necessrio
que printf() justifique o texto esquerda. Para justificar o texto esquerda, coloque um
sinal de subtrao (-) imediatamente aps o % no especificador de formato. O exemplo a
seguir ilustra o uso desta tcnica de formatao.
#include <stdio.h>
void main(void)
{
int int_valor = 5;
float flt_valor = 3.33;
printf("Justificado direita %5d valor\n", int_valor);
printf("Justificado esquerda %-5d valor\n", int_valor);
printf("Justificado direita %7.2f valor\n", flt_valor);
printf("Justificado esquerda %-7.2f valor\n", flt_valor);
}

4.1.18 Combinando os Especificadores de Formato de Printf()


Muitas vezes por rapidez e para que o cdigo torne-se mais enxuto pode-se
aproveitar dois ou mais especificadores de formato de printf(). Em tais casos, simplesmente
coloque cada um dos especificadores logo aps o %. Veja um exemplo.

#include <stdio.h>
void main(void)
{
int int_valor = 5;
printf("Justificado esquerda com sinal %-+3d\n", int_valor);
}

4.1.19 Trabalhando com os Caracteres Escape de Printf()


Quando trabalha-se com string de caracteres, pode-se usar caracteres especiais, tais
como tabulao, retorno do carro, ou alimentao de linha. A Linguagem C define vrios
caracteres de escape (referenciados no Mdulo 2 item 2.4.3) para facilitar para voc a
incluso de caracteres especiais dentro de uma string. Um exemplo o uso do caracter de
nova linha (\n) para avanar a sada para o incio da prxima linha.
printf("Linha 1\nLinha2\nLinha 3\n");

4.1.20 Determinando o Nmero de Caracteres que Printf() Exibiu


Quando usa-se o especificador de formato %n, printf() atribuir uma varivel
(passada por ponteiro) um contador do nmero de caracteres que printf() exibiu.
#include <stdio.h>
void main(void)
{
int primeiro_conta;
int segundo_conta;
printf("Universidade%n Estadual Paulista%n\n",&primeiro_conta,
&segundo_conta);
printf("Primeiro conta %d Segundo conta %d\n", primeiro_conta,
segundo_conta);
}

4.1.21 Usando o Valor de Retorno de Printf()


Usar o especificador de formato %n um modo de garantir que printf() teve sucesso
ao exibir sua sada. Alm disso, quando printf() termina, ele retorna o nmero total de
caracteres que escreveu. Se printf() encontrar um erro, retornar a constante EOF (que
como ser visto no mdulo sobre sistema de arquivo, indica o fim de um arquivo). O
exemplo a seguir, usa o valor de retorno de printf() para garantir que printf() foi bem
sucedido.
#include <stdio.h>
void main(void)
{
int result;
result =
printf("Universidade Estadual Paulista\n");
if (result == EOF)
fprintf(stderr, "Erro dentro de printf\n");
}

4.2 Funo SCANF()

A funo scanf( ) uma das funes de entrada de dados da Linguagem C, que


pode ser usada para ler virtualmente qualquer tipo de dado inserido por meio do teclado,
freqentemente ela usada para a entrada de nmeros inteiros ou de ponto flutuante. A
forma geral da funo scanf( ) :
scanf (string de controle, lista de argumentos);

Os especificadores de formato de entrada so precedidos por um sinal % e dizem


funo scanf( ) qual tipo de dado deve ser lido em seguida. Esses cdigos so listados na
tabela a seguir.
Cdigo
%c
%d
%i
%u
%e
%f
%g
%o
%s
%x
%p

Significado

L um nico caractere
L um decimal inteiro
L um decimal inteiro (no pode ser octal ou hexadecimal)
L um decimal sem sinal
L um nmero em ponto flutuante com sinal opcional
L um nmero em ponto flutuante com ponto opcional
L um nmero em ponto flutuante com expoente opcional (double)
L um nmero em base octal
L uma string
L um nmero em base hexadecimal
L um ponteiro

Os caracteres de converso d, i, o, u e x podem ser precedidos por h para indicarem


que um apontador para short ao invs de int aparece na lista de argumentos, ou por l (letra
ele) para indicar que um apontador para long aparece na lista de argumentos.
Semelhantemente, os caracteres de converso e, f e g podem ser precedidos por l (letra ele)
para indicarem que um apontador para double ao invs de float est na lista de argumentos.
A cadeia de formato geralmente contm especificaes de converso, que so
usadas para controlar a converso da entrada. A cadeia de formato pode conter:
espaos, tabulaes e novas linhas, que sero ignorados;
caracteres comuns (no %), que devem combinar com o prximo caractere
no espao do fluxo de entrada;
especificaes de converso, consistindo no caractere %, um caractere *
opcional de supresso de atribuio, um nmero opcional especificando um tamanho
mximo do campo, um h ou l opcional indicando o tamanho do destino, e um caractere de
converso.

4.2.1 Usando Caracteres em Scanf() que Sero Descartados


Um caractere que no seja um espao em branco faz com que a funo scanf( ) leia
e descarte o caractere correspondente. Por exemplo, %d,%d faz com que a funo scanf()
leia um inteiro, ento, leia uma vrgula (que ser descartada) e, finalmente, leia outro
inteiro. Se o caractere especificado no encontrado, a funo scanf( ) terminar. Pode-se
usar esta tcnica para separa os especificadores de formato, tornando o cdigo mais legvel.

#include <stdio.h>
void main(void)
{
int a,b;
scanf("%d,%d", &a, &b);
}

4.2.2 - Lendo Valores em Variveis


Todas as variveis usadas para receber valores por meio da funo scanf() devero
ser passadas pelos seus endereos. Por exemplo, para ler um inteiro em uma varivel count,
poderia usar a seguinte chamada funo scanf():
#include <stdio.h>
void main(void)
{
int count;
scanf("%d ", &count);
}

4.2.3 Lendo String de Caracteres


As strings sero lidas em vetores (cadeias de caracteres) e o nome do vetor o
endereo do primeiro elemento do vetor. Ento, para ler uma string no vetor de caracteres
nome, deve-se usar o seguinte comando:
#include <stdio.h>
void main(void)
{
char nome[40];
scanf("%s", nome);
}

Nesse caso, nome j um endereo e no precisa ser precedido pelo operador &.

4.2.4 Formatando a Entrada de Scanf()


Os itens de dados de entrada devem ser separados por espaos, tabulaes ou novas
linhas. Pontuaes como vrgula, ponto-e-vrgula e semelhantes no contam como
operadores. Isso significa que scanf(%d%d, &r, &c); aceitar uma entrada dos nmeros
10 20, mas falhar com 10,20. Como na funo printf( ), os cdigos de formato da funo
scanf( ) devem ser correspondidos na ordem com as variveis que esto recebendo a
entrada na lista de argumento.
Um * colocado depois do % e antes do cdigo de formato ler um dado de um tipo
especificado, mas suprimir a sua atribuio. Assim, scanf(%d%*c%d, &x, &y); dandose a entrada 10/20, colocar o valor 10 em x descartando o sinal de diviso, e dar a y o
valor 20.
Ainda que espaos, tabulaes e novas linhas sejam usados como separadores de
campos, quando da leitura de um nico caractere, esses ltimos so lidos como qualquer

outro caractere. Por exemplo, com uma entrada de x y; scanf(%c%c%c, &a, &b, &c);
retornar com o caractere x em a, um espao em b e o caractere y em c.

4.2.5 Determinando o Nmero Mximo de Caracteres a ser Lido


Os comandos de formato podem especificar um campo modificador de
comprimento mximo. Esse modificador um nmero inteiro colocado entre o sinal % e o
cdigo de comando de formato, que limita o nmero de caracteres lidos para qualquer
campo. Por exemplo, para ler no mais que 20 caracteres em str, voc pode escrever:
#include <stdio.h>
void main(void)
{
char str[40];
scanf("%20s", str);
}

Se o apontador de entrada maior do que 20 caracteres, uma chamada subseqente


para entrada comear onde ela pra. Por exemplo, se for digitado
ABCDEFGHIJKLMNOPQRSTUVWXYZ em resposta chamada scanf( ), nesse
exemplo, somente os 20 primeiros caracteres, at o T, sero colocados em str por causa
do especificador de tamanho mximo. Isso significa que os caracteres restantes
UVWXYZ no so usados. Se uma outra chamada funo scanf( ) feita, tal como
scanf(%s, str); ento UVWXYZ colocado em str. A entrada para o campo pode ser
terminada, antes que o campo de comprimento mximo seja alcanado, se um caractere de
espao em branco encontrado. Nesse caso, a funo scanf( ) move-se para o prximo
campo.

4.2.6 - Lendo Somente Caracteres Pr-Determinados


A funo scanf( ) inclui tambm uma caracterstica muito poderosa chamada
scanset. Um scanset define uma lista de caracteres que sero correspondidos por scanf(). A
funo scanf( ) continuar a ler caracteres enquanto eles estiverem no scanset. Assim que
um caractere entrado no corresponder a qualquer um do scanset, a funo scanf( ) segue
para o prximo especificador de formato (se existir). Um scanset definido colocando-se
uma lista de caracteres que quer-se que seja examinada entre chaves. A chave inicial deve
ser prefixada por um sinal de porcentagem. Por exemplo, este scanset diz funo scanf( )
para ler somente os dgitos de 0 a 9: %[1234567890].
O argumento correspondente a scanset deve ser uma varivel string.
Aps retornar de funo scanf( ), a varivel conter uma string terminada com um
nulo com os caracteres lidos. Para ver como isso funciona, considere este programa:
#include <stdio.h>
#include <conio.h>
void main()
{
char s1[80], s2[80];

scanf (%[1234567890]%s, s1, s2);


printf (\n%s| |%s, s1, s2);
getch();
}

Pode-se testar esse programa usando a entrada 123456789abcdefg987654 seguida


por um retorno de carro. O programa exibir, ento: 123456789| |abcdefg987654. Uma vez
que a no faz parte do scanset, a funo scanf( ) pra de ler os caracteres em s1 quando
ele encontrado e os caracteres restantes so colocados em s2.
Voc pode especificar um intervalo dentro de um scanset usando um hfen. Por
exemplo, isto diz funo scanf( ) para aceitar os caracteres de A a Z:
%[A-Z]
Pode-se especificar mais de um intervalo dentro de um scanset. Por exemplo, este
programa l dgitos e letras. Ele tambm ilustra que pode-se usar o especificador de campo
mximo como um scanset.
#include <stdio.h>
#include <conio.h>
void main()
{
char str[80];
printf (Informe dgitos e letras: );
scanf (%78[a-z0-9], str);
printf (\n%s, str);
getch();
}

Pode-se especificar um conjunto invertido se o primeiro caractere um ^. Quando


est presente, o ^ instrui a funo scanf( ) a aceitar quaisquer caracteres que no esto
definidos no scanset.
Um ponto importante a lembrar que o scanset difere letras minsculas de
maisculas. Portanto, se quiser examinar tanto letras maisculas como minsculas, deve
especific-las individualmente.

4.3 - Sntese do Mdulo


apresentado seguir, uma sntese do que foi tratado em cada item deste mdulo.
Com esta sntese voc poder relembrar conceitos vistos durante nosso estudo ou mesmo
direcionar seu estudo, caso voc j tenha conhecimentos na Linguagem C.
1 4.1 Funo PRINTF(): neste item foi apresentada uma introduo da funo
printf(), listando suas caractersticas e propriedades bem como sua estrutura.
2 4.1.1 Exibindo Valores do Tipo int Usando Printf(): neste item foi mostrado
como possvel exibir uma sada printf() para valores inteiros, usando-se o especificador de
formato %d.

3 4.1.2 Exibindo um Valor Inteiro Octal ou Hexadecimal: foi visto que


possvel exibir um valor inteiro em seu formato octal (base 8) ou hexadecimal (base 16)
atravs dos especificadores de formato %o, %x e %X.
4 4.1.3 Exibindo Valores do Tipo Unsigned Int: neste item foi apresentado
como exibir valores do tipo unsigned int com a funo printf(), usando o especificador de
formato %u.
5 4.1.4 Exibindo Valores do Tipo Long Int: foi visto que para exibir valores
do tipo long int com a funo printf(), deve-se usar o especificador de formato %ld.
6 4.1.5 Exibindo Valores do Tipo Float: foi visto que para exibir valores do
tipo float com a funo printf(), deve-se usar o especificador de formato %f.
7 4.1.6 Exibindo Valores do Tipo Char: foi visto que para exibir valores do
tipo char com a funo printf(), deve-se usar o especificador de formato %c.
8 4.1.7 Exibindo Valores de Ponto Flutuante em um Formato Exponencial:
foi visto que para exibir um valor em ponto flutuante em um formato exponencial com a
funo printf(), deve-se usar o especificador de formato %e ou %E.
9 4.1.8 Exibindo Valores em Ponto Flutuante: foi visto que a funo printf()
tambm suporta os especificadores %g e %G para imprimir valores em ponto flutuante.
10 4.1.9 Exibindo uma String de Caracteres: foi visto que para exibir uma
string de caracteres com a funo printf(), deve-se usar o especificador de formato %s.
11 4.1.10 Exibindo um Endereo de Ponteiro: foi visto que para exibir um
endereo de ponteiro com a funo printf(), deve-se usar o especificador de formato %p.
12 4.1.11 Precedendo um Valor com um Sinal de Adio ou de Subtrao: foi
visto que para instruir printf() a exibir um sinal de um valor, deve-se incluir um sinal de
adio imediatamente aps o % no especificador de formato.
13 4.1.12 Formatando um Valor Inteiro: neste item foi visto como configurar
printf() de tal forma que sua valores a serem exibidos tenha seu formato de sada na tela
especificado pelo programador.
14 4.1.13 Sada de Inteiros Preenchida com Zeros: foi visto neste item que
possvel configurar printf() de tal maneira que ele exiba zeros antes do valor ou caracter
que necessrio exibir.
15 4.1.14 Exibindo um Prefixo Antes dos Valores Octais ou Decimais: foi
visto como preceder os valores em octal com um zero, e os hexadecimais com 0x .
16 4.1.15 Formatando um Valor em Ponto Flutuante: foi visto que quando
formata-se um valor em ponto flutuante especifica dois valores. O primeiro valor diz a
printf() o nmero mnimo de caracteres a serem exibidos. O segundo valor diz a printf() o
nmero de dgitos a serem exibidos direita do ponto decimal. Com isto foi apresentada
uma tcnica de formatao de printf().
17 4.1.16 Formatando a Sada Exponencial: foi visto como configurar printf()
de tal forma a exibir a sada em ponto flutuante em um formato exponencial.

18 4.1.17 Justificando Esquerda a Sada de Printf(): foi apresentado que para


justificar o texto esquerda, coloca-se um sinal de subtrao (-) imediatamente aps o % no
especificador de formato.
19 4.1.18 Combinando os Especificadores de Formato de Printf():
apresentado neste item a possibilidade de aproveitar dois ou mais especificadores de
formato de printf() com intuito de deixar o cdigo mais enxuto.
20 4.1.19 Trabalhando com os Caracteres Escape de Printf():. Foi visto que a
Linguagem C define vrios caracteres de escape (referenciados no Mdulo 2 item 2.4.3)
para facilitar para voc a incluso de caracteres especiais dentro de uma string.
21 4.1.20 Determinando o Nmero de Caracteres que Printf() Exibiu: Foi
visto que quando usa-se o especificador de formato %n, printf() atribuir uma varivel
(passada por ponteiro) um contador do nmero de caracteres que printf() exibiu.
22 4.1.21 Usando o Valor de Retorno de Printf(): foi mostrado que possvel
utilizar o valor que printf() retorna quando ele finaliza suas tarefas. Este valor retornado
pode ser utilizado de vrias formas, variando o uso de acordo com as caractersticas do
programa.
23 4.2 Funo SCANF(): foi feita neste item uma introduo funo scanf().
Foi mostado que a funo scanf( ) uma das funes de entrada de dados da Linguagem C,
que pode ser usada para ler virtualmente qualquer tipo de dado inserido por meio do
teclado. Alm da introduo funo foi apresentada sua estrutura e caractersticas.
24 4.2.1 Usando Caracteres em Scanf() que Sero Descartados: foi mostrado
que possvel inserir dentro da funo scanf() caracteres que no sero lidos. Estes
caracteres servem apenas na tornar o cdigo mais legvel e de fcil entendimento.
25 4.2.2 Lendo Valores em Variveis: foi visto que possvel utilizar a funo
scanf() para obter valores para determinadas variveis.
26 4.2.3 Lendo String de Caracteres: foi mostrado como usar a funo scanf()
para ler string de caracteres que sero armazenadas em vetores.
27 4.2.4 Formatando a Entrada de Scanf(): neste item mostrado como
formatar scanf()de tal forma a atender as especificaes de cada programa para entrada de
dados.
28 4.2.5 Determinando o Nmero Mximo de Caracteres a ser Lido: foi
mostrado que possvel especificar o nmero de caracteres lidos por scanf(), de tal forma a
desprezar caracteres que forem digitados a mais, por exemplo.
29 4.2.6 Lendo Somente Caracteres Pr-Determinados: foi visto que pode-se
previamente especificar os caracteres que sero lidos por scanf(), sendo que o caracter que
no estiver dentro destes especificados ser ignorado.

Mdulo 5 - Estruturas de Fluxo de Controle

5.1 A Declarao If
A declarao if usada quando necessrio testar em um programa duas ou mais
condies. Isto permite ao programador o desenvolvimento de programas complexos. A
forma geral da declarao if :
if (condio)
{
comandos;
}
else
{
comandos;
}

A clusula else opcional. Se condio for verdadeira (qualquer coisa diferente de


0), o bloco que forma o destino de if ser executado; caso contrrio o bloco que forma o
destino de else ser executado (desde que exista else).
Lembre-se que somente o cdigo associado a if ou o cdigo associado a else ser
executado, nunca os dois. O destino dos dois, if e else, pode ser um comando simples ou
um bloco de comandos.
O comando if ser demonstrado atravs de um programa simples que converte bases
numricas. Este programa ser capaz de apresentar as seguintes converses:
1 Decimal para Hexadecimal;
2 Hexadecimal para Decimal.
O programa permitir que primeiro seja selecionado o tipo de converso a partir de
um menu e, ento, solicitar o nmero a ser convertido.
#include <stdio.h>
void main()
{
int opcao;
int valor;
printf (Converter: \n);
printf (1: decimal para hexadecimal\n);
printf (2: hexadecimal para decimal\n);
printf (\nInforme sua opo: );
scanf (%d, &opcao);
if (opcao == 1)
{
printf (\nInforme o valor em decimal: );
scanf (%d, &valor);
printf (%d em hexadecimal e: %x, valor, valor);
}
if (opcao == 2)
{
printf (\nInforme o valor em hexadecimal: );
scanf (%x, &valor);
printf (%x em decimal e: %d, valor, valor);
}
}

5.1.1 - Usando a Declarao Else


possvel associar um else com qualquer if. Com esta declarao podemos
acrescentar ao teste condicional vrias opes de escolha. Se a expresso condicional
associada a if verdadeira, a instruo ou bloco de instrues associada ser executada. Se
for falsa, ento a instruo ou bloco de instrues do else ser executada. O programa
seguinte demonstra este princpio fundamental:
#include <stdio.h>
void main()
{
int i;
printf (Informe um nmero: );
scanf (%d, &i);
if (i < 0) printf (O nmero negativo);
else printf (O nmero positivo ou nulo);
}

5.1.2 O Encadeamento If-Else-If


Uma construo comum em programao o encadeamento if-else-if. O seguinte
exemplo ilustra esta construo:
if (condio)
{
comandos;
}
else if (condio)
{
comandos;
}
else if (condio)
{
comandos;
}
else
{
comandos;
}

As expresses condicionais sero avaliadas de cima para baixo. Assim que uma
condio verdadeira encontrada, o bloco associado a ela ser executado, e o resto do
encadeamento ignorado. Se nenhuma das condies for verdadeira, ento o else final ser
executado.
Se o else final no estiver presente e todas as outras condies forem falsas, ento
nenhuma ao ser realizada.
Pode-se usar o encadeamento if-else-if para implementar o programa de converso
de base numrica desenvolvido anteriormente. Na verso original, cada declarao if era
avaliada sucessivamente, mesmo se uma das declaraes anteriores tivesse xito. Ainda que
no haja grande significado neste caso, a avaliao redundante de todos os ifs no muito
eficiente ou elegante. O seguinte programa resolve este problema. Nessa verso de

encadeamento if-else-if, to logo uma declarao if satisfeita, o resto das declaraes


ignorado.

/* Programa de converso de base numrica if-else-if


decimal ---> hexadecimal
hexadecimal ---> decimal
*/
#include <stdio.h>
void main()
{
int opcao;
int valor;
printf (Converter: \n);
printf (1: decimal para hexadecimal\n);
printf (2: hexadecimal para decimal\n);
printf (\nInforme sua opo: );
scanf (%d, &opcao);
if (opcao == 1)
{
printf (\nInforme o valor em decimal: );
scanf (%d, &valor);
printf (%d em hexadecimal e: %x, valor, valor);
}
else if (opcao == 2)
{
printf (\nInforme o valor em hexadecimal: );
scanf (%x, &valor);
printf (%x em decimal e: %d, valor, valor);
}
else
{
printf (\nA opo escolhida invlida.)
}
}

5.1.3 A Expresso Condicional


Algumas vezes, iniciantes na linguagem C confundem-se pelo fato de que qualquer
expresso vlida na linguagem C pode ser usada para controlar a declarao if. Isto , o tipo
de expresso no precisa se restringir quelas envolvendo operadores relacionais e lgicos.
S requerido que a expresso resulte em um valor zero ou no zero. Por exemplo, este
programa l dois inteiros do teclado e mostra o quociente. Para evitar um erro de diviso
por zero, uma declarao if usada para controlar o segundo nmero.
#include <stdio.h>
void main()
{
int a, b;
printf (Informe dois nmeros: );

scanf (%d%d, &a, &b);


if (b) printf (%d\n, a/b);
else printf (No posso dividir por zero\n);
}

Essa abordagem funciona porque, se b for zero, a condio controlando o if falsa e


a instruo else executada. Caso contrrio, a expresso verdadeira (no zero) e a diviso
realizada. No necessrio escrever uma declarao if como esta
if (b != 0) printf (%d\n, a/b);

porque redundante.

5.1.4 Ifs Aninhados


Um dos muitos aspectos que causam confuso na declarao if, em qualquer
linguagem de programao, so os ifs aninhados. Um if aninhado uma declarao if que
objeto de um if ou um else. Os ifs aninhados so incmodos por poderem dificultar saber
qual else est associado a qual if.
Considere este exemplo:
if (x)
if (y) printf (1);
else printf (2);

Em C, o else ligado ao if mais prximo dentro do mesmo bloco de cdigo que j


no tenha uma declarao else associada a ele. Neste caso o else associado declarao
if(y).
Para fazer com que else seja associado declarao if(x), deve-se usar chaves para
sobrepor a sua associao normal, como mostrado aqui:
if (x)
{
if (y) printf (1);
}
else printf (2);

if(y).

O else agora est associado ao if(x), j que ele no parte do bloco de cdigo do

5.2 A Declarao For


Uma operao que vrios programas executaro comumente repetir um conjunto
de comandos um nmero especfico de vezes. Por exemplo, pode-se querer calcular as
notas dos exames de 30 alunos ou soar trs vezes o alto-falante interno do computador. Para
auxiliar programas a repetir um ou mais comandos um certo nmero de vezes, a Linguagem
C fornece o comando for.
for(valor_inicial; condio_final; valor_incremento)
comando;

Quando um programa repetir comandos um nmero especfico de vezes,


normalmente usar uma varivel de controle, que contar o nmero de vezes que for

executado os comandos. O comando for contm quatro sees. A seo valor_inicial


atribui varivel de controle o valor inicial da varivel, que , na maioria das vezes, 0 ou 1.
A seo condio_final normalmente testa o valor da varivel de controle para determinar
se o programa executou os comandos um nmero desejado de vezes. A seo
valor_incremento normalmente adiciona o valor 1 para a varivel de controle toda a vez
que os comandos so executados. Finalmente a quarta seo do comando for o comando
ou comandos especificados. O comando for geralmente chamado de lao for. Considere o
seguinte lao for, ele exibir os nmeros de 1 a 10 na sua tela:
for(contador=1; contador <= 10; contador++)
printf("%d\n", contador);

Para compreender melhor o processamento do lao for execute em seu compilador o


seguinte programa:
#include <stdio.h>
void main(void)
{
int contador;
for (contador = 1; contador <= 5; contador++)
printf("%d ", contador);
printf("\nIniciando o segundo laco\n");
for (contador = 1; contador <= 10; contador++)
printf("%d ", contador);
printf("\nIniciando o terceiro laco\n");
for (contador = 100; contador <= 5; contador++)
printf("%d ", contador);
}

Como pode-se verificar, o primeiro lao for exibe os nmeros de 1 at 5. O segundo


lao exibe os valores de 1 at 10. O terceiro lao no exibe nenhum valor. Se for
examinado com ateno, ser visto que o programa inicialmente atribui varivel de
controle do lao o valor 100. Quando o comando for testa o valor, o lao for atende
imediatamente condio final, de modo que o lao no executado.

5.2.1 Partes do Comando For so Opcionais


Como foi visto no item anterior, o lao for usa trs sees dentro do comando for:
uma inicializao, um teste e um incremento:
for(inicializao; teste; incremento)

Dependendo do programa, algumas vezes pode no ser necessrio o uso de cada


uma das sees do comando for. Por exemplo, se j foi atribuido o valor 0 varivel conta,
pode-se pular a seo de inicializao do lao. Depois, para exibir os nmeros de 0 at 999,
o lao conter o seguinte:
for(; conta <1000; conta++)

printf("%d", conta);

No entanto, se for omitido uma das sees do lao for, precisa-se incluir o ponto-evrgula correspondente. Por exemplo, o lao for a seguir omite as sees de inicializao e
de incremento:
for(; conta < 1000; )
printf("%d", conta++);

Da mesma forma, o comando for seguir ficar em execuo perpetuamente. Este


o chamado lao infinito:
for (; ; ; )
/*comando*/

5.2.2 Lao Null


No passado, quando os programadores queriam que seus programas fizessem uma
breve pausa, talvez para exibir alguma mensagem, eles colocavam um lao nulo ou "no
faz nada" em seus programas. Por exemplo, o seguinte lao for no faz nada 100 vezes:
for(contador=1; contador <= 100; contador++)
;
/* no faz nada */

Quando se coloca um lao nulo nos programas, a Linguagem C efetuar a


inicializao do lao, e, depois, repetidamente, testar e incrementar a varivel de controle
at que a varivel de controle atenda a condio final. O teste repetido do lao consome
tempo do processador, o que faz o programa retardar. Se o programa precisar de um retardo
maior, voc poder aumentar a condio final:
for(contador=1; contador <= 10000; contador++)
;
/* no faz nada */

Usar as tcnicas de retardo, tais como o lao nulo, poder causar problemas.
Primeiro, se o programa estiver rodando em um computador 286, 386 ou 486, a durao do
retardo diferir simplesmente devido diferena de velocidade entre os diferentes
microprocessadores. Segundo, se o programa estiver rodando em um ambiente multitarefa,
tal como o Windows, OS/2 ou Unix, os laos "no fazem nada" consomem tempo que o
processador poderia estar gastando fazendo trabalho importante em outro programa.

5.2.3 Lao Infinito


Quando so usados laos for, precisa-se garantir que o lao atender sua condio
final. Caso contrrio, o lao continuar sua execuo para sempre. Esses laos
interminveis so chamados laos infinitos. Na maioria dos casos, os laos infinitos
ocorrem como resultado de erro na programao. Por exemplo, considere o seguinte lao:
for(i = 0; i <100; i++)
{
printf("%d", i);

resultado = valor * --i;

/*causa do erro*/

Como pode-se verificar, o segundo comando do lao decrementa o valor da varivel


de controle i. Especificamente, o lao decrementa o valor para -1, e, depois, incrementa o
valor para 0. Como resultado, o valor nunca atinge 100, de modo que o lao no termina.
Quando o programa entra em um lao infinito, pode-se pressionar Ctrl+C para finalizar o
programa.
O programa a seguir ilustra um lao infinito:
#include <stdio.h>
void main(void)
{
int i;
int result = 0;
int valor = 1;
for (i = 0; i < 100; i++)
{
printf("%d ", i);
result = valor * --i;
}
printf("Resultado %d\n", result);
}

5.2.4 Usando o operador vrgula da Linguagem C dentro de um lao for


A Linguagem C permite a declarao de mltiplas variveis do mesmo tipo
separando os nomes das variveis com vrgulas:
int idade, altura, peso;

De um modo similar, a Linguagem C permite inicializar e incrementar mltiplas


variveis em um lao for separando as operaes com vrgula. Considere o lao a seguir,
que trabalha com as variveis i e j:
for (i=0, j=100; i <= 100; i++, j++)
printf("i = %d j = %d\n", i, j);

Alguns programas iro trabalhar com mltiplas variveis em um lao for em


programas que trabalham com matrizes. O programa a seguir ilustra o uso do operador
vrgula em um lao for:
#include <stdio.h>
void main(void)
{
int i, j;
for (i = 0, j = 100; i <= 100; i++, j++)
printf("i = %d j = %d\n", i, j);
}

5.3 A Declarao While


Em muitos casos, os programas precisam repetir um ou mais comandos
at que o lao atenda a uma condio especfica que no envolva necessariamente uma

contagem. Por exemplo, para um programa que exiba o contedo de um arquivo na tela,
ser necessrio que o programa exiba cada linha do arquivo. Na maioria dos casos, no
sabe-se quantas linhas o arquivo contm. Portanto, no se pode usar um lao for para exibir,
por exemplo, 100 linhas. O arquivo poderia conter mais ou menos linhas. Em vez disso,
ser necessrio que o programa leia e exiba linhas at chegar ao final do arquivo. Para fazer
isso, os programas podem usar o lao while, como segue:
while (condio)
comando;

Ao encontrar um lao while no programa, a Linguagem C testa a condio


especificada. Se a condio for verdadeira, efetuar os comandos contidos no lao. Se o
comando for falso, continuar a execuo do programa ao primeiro comando que segue.
Um lao while pode repetir um nico comando ou um comando composto delimitado por
abre e fecha chaves, como segue:
while (condio)
{
/*comandos*/
}

O programa a seguir, usa o lao while para repetir um lao at que seja pressionado
a tecla S ou N em resposta a uma pergunta:
#include <stdio.h>
#include <ctype.h>
#include <conio.h>
void main(void)
{
char letra;

/* Letra digitada pelo usurio */

printf("Quer continuar? (S/N): ");


letra = getch();
/* L a letra */
letra = toupper(letra); /* Converte letra para maiscula */
while ((letra != 'S') && (letra != 'N'))
{
putch(7);
/* Soa o alto-falante */
letra = getch();
/* L a letra */
letra = toupper(letra);
/* Converte a letra para maiscula */
}
printf("\nSua resposta foi %c\n", letra);
}

Primeiro, o programa exibir a mensagem que o primeiro comando printf contm.


Segundo, o programa usa getch para ler a tecla pressionada. Para simplificar o teste do lao,
o programa converte a letra para maiscula, de modo que o lao somente precisa testar as
letras S ou N. Terceiro, o lao while testar a letra que o usurio digitou. Se a letra for um S
ou N, a condio falhar, e os comandos do lao no sero executados. Se a letra
pressionada no for S ou N, a condio do lao ser verdadeira e seus comandos sero

executados. No lao, o comando soar o alto-falante interno do computador para indicar um


caractere invlido. Em seguida, o programa ler a nova tecla e converter a letra para
maiscula. O lao depois repetir o seu teste para determinar se o usurio digitou um S ou
um N. se no, os comando do lao sero repetidos. Caso contrrio, a execuo do programa
continuar no primeiro comando que segue o lao.

5.3.1 Partes de um Lao While


Foi visto anteriormente que um lao for realmente contm quatro sees: uma
inicializao, um teste, um comando de execuo e um incremento. Por outro lado, um lao
while contm somente um teste e os comandos que quer-se repetir, como visto no item
anterior.
Foi visto tambm, que um lao infinito aquele cuja condio final nunca
atendida, e portanto o lao continua a execuo para sempre. Ao escrever programas que
usa laos while, pode-se reduzir a possibilidade de um lao infinito garantindo que seus
laos while efetuem os mesmos passos executados por um lao for. Veja a seguir os quatro
passos relacionados na tabela:

Ao
Inicializa
Testa
Executa
Modifica

Descrio
Inicializa a varivel de controle do lao
Testa a varivel de controle ou a condio do lao
Executa os comando desejados no lao
Modifica o valor da varivel de controle ou efetua uma operao que
afetar a condio que voc est testando

Ao contrrio do lao for, que permite explicitamente inicializar e incrementar uma


varivel de controle, um lao while requer que sejam inclusos comandos no programa que
efetuem esses passos. O programa a seguir, ilustra como o programa efetua esses quatro
passos. Ao contrrio dos programas escritos anteriormente, este usa um lao while para
exibir os nmeros de 1 a 100:
#include <stdio.h>
void main(void)
{
int contador = 1;

/* Inicializa a varivel de controle */

while (contador <= 100) /* Testa a varivel de controle */


{
printf("%d ", contador); /* Executa os comandos */
contador++;

/* Modifica a varivel de controle */

}
}

5.4 A Declarao Do-While

Ao contrrio dos laos for e while, que testam a condio do lao no incio, o lao
do-while verifica sua condio no final do lao. Isso significa que um lao do-while ser
executado pelo menos uma vez. A forma geral do lao do-while :
do{
comandos;
}while(condio);

Ainda que as chaves no sejam necessrias quando somente um comando ser


executado no lao, elas so usadas para aumentar a legibilidade do cdigo do programa.
Este programa usa um lao do-while para ler nmeros do teclado at que um deles seja
menos que 100.
#include <stdio.h>
void main()
{
int num;
do
{
scanf (%d, &num);
}
while(num > 100);
}

Talvez o uso mais comum do lao do-while seja em uma rotina de seleo em
menu. J que sempre ser preciso de uma rotina de seleo em menu para ser executada no
mnimo uma vez, o lao do-while uma opo bvia. O seguinte fragmento mostra como
adicionar um lao do-while no menu do programa de converso numrica.
/* Assegura que o usurio especificou uma opo vlida */
do
{
printf (Converte:\n);
printf ( 1: decimal para hexadecimal\n);
printf ( 2: hexadecimal para decimal\n);
printf (informe sua opo: );
scanf (%d, &opcao);
}while(opcao < 1 || opcao > 2);

Depois que a opo tiver sido apresentada, o programa se repetir at que uma
opo vlida seja selecionada.

5.5 Comando Continue


Dependendo do propsito do programa, algumas vezes, com base em uma segunda
condio especfica, poder ser necessrio que o programa pule a iterao atual. O
comando continue da Linguagem C lhe permite fazer exatamente isso. Se a Linguagem C
encontrar um comando continue em um lao for, a Linguagem C automaticamente
executar a poro de incremento do lao, e, depois, efetuar o teste da condio final. Se a
Linguagem C encontrar um comando continue em um lao while ou do, ento a Linguagem
C imediatamente efetuar o teste da condio final. Para compreender melhor o comando

continue, considere o seguinte programa, que usa continue em um lao for e um lao while
para exibir os nmeros pares e mpares entre 1 e 100:
#include <stdio.h>
void main(void)
{
int contador;
printf("\nValores pares\n");
for (contador = 1; contador <= 100; contador++)
{
if (contador % 2) /* mpar */
continue;
printf("%d ", contador);
}
printf("\nValores mpares\n");
contador = 0;
while (contador <= 100)
{
contador++;
if (! (contador % 2)) /* Par */
continue;
printf("%d ", contador);
}
}

importante observar que normalmente pode-se eliminar a necessidade de usar um


comando continue reprojetando o uso dos comandos if e else em seu programa. Por
exemplo, o programa a seguir tambm exibe valores pares e mpares sem usar continue:
#include <stdio.h>
void main(void)
{
int contador;
printf("\nValores pares\n");
for (contador = 1; contador <= 100; contador++)
{
if (!(contador % 2)) /* Par */
printf("%d ", contador);
}
printf("\nValores mpares\n");
contador = 0;
while (contador <= 100)
{
contador++;
if (contador % 2) /* mpar */
printf("%d ", contador);
}

5.6 Finalizando um Lao Usando o Comando Break


Dependendo do propsito do programa, algumas vezes, com base em uma segunda
condio especfica, poder querer que o lao termine automaticamente, com seu programa
continuando seu processamento no comando que segue o lao. O comando break lhe
permite fazer exatamente isso. Quando a Linguagem C encontra um break em um lao, a
execuo do lao terminar de imediato. O prximo comando que o programa executa o
comando que segue imediatamente o lao. No caso de um comando for, a Linguagem C
no efetuar a seo de incremento do lao, ao invs disso, o lao termina imediatamente.
O programa a seguir ilustra o uso do comando break. O programa percorre os nmeros de 1
a 100, e, depois, de 100 a 1. Toda vez que o lao chega ao valor 50, o comando break
termina imediatamente o lao:
#include <stdio.h>
void main(void)
{
int contador;
for (contador = 1; contador <= 100; contador++)
{
if (contador == 50)
break;
printf("%d ", contador);
}
printf("\nPrximo lao\n");
for (contador = 100; contador >= 1; contador--)
{
if (contador == 50)
break;
printf("%d ", contador);
}
}

5.7 Desvios com o comando goto


Como a maioria das linguagens de programao, a Linguagem C fornece um comando
goto, que permite que a execuo do programa desvie-se para uma localizao especfica,
chamada rtulo. O formato do comando goto como segue:
goto rotulo;
rotulo:

O programa a seguir usa o comando goto para exibir os nmeros de 1 a 100:


#include <stdio.h>
void main(void)
{
int conta = 1;

rotulo:
printf("%d ", conta++);
if (conta <= 100)
goto rotulo;
}

Quando usa-se o comando goto, o rtulo precisa residir na funo atual. Em outras
palavras, no pode-se usar goto para desviar-se de main para um rtulo que aparece em
outra funo e vice - versa.

5.8 A Declarao Switch


Ainda que o encadeamento if-else-if possa realizar testes de mltipla escolha, ele
quase nunca elegante. O cdigo pode ser muito difcil de acompanhar e pode confundir
at mesmo o seu autor. Por esse motivo, a linguagem C tem internamente uma declarao
de deciso de mltipla escolha chamada de switch. Na declarao switch, a varivel
sucessivamente testada contra uma lista de inteiros ou constantes caractere. Quando uma
associao encontrada, o conjunto de comandos associado com a constante executado.
As constantes no precisam sequer estar em qualquer ordem especial. A forma geral
da declarao switch :
switch (varivel)
{
case constante1:
commandos;
break;
case constante2:
commandos;
break;
case constante3:
commandos;
break;
M
default
commandos;
}

Onde a declarao default executada se nenhuma correspondncia for encontrada.


O default opcional e, se ele no estiver presente, nenhuma ao ser realizada se todas as
correspondncias falharem. Quando uma correspondncia encontrada, os comandos
associados a case so executados at que o break seja encontrado ou at que se encontre o
final do switch.
H trs coisas importantes a saber sobre a declarao switch:
1) Ele difere do if, j que o switch pode testar somente igualdades, enquanto a
expresso condicional if pode ser de qualquer tipo;

2) Nunca duas constantes case no mesmo switch podem ter valores iguais.
Obviamente, uma declarao switch dentro de outra declarao switch pode ter as mesmas
constantes case;
3) Uma declarao switch mais eficiente que um encadeamento if-else-if.
possvel especificar comandos no switch que sero executados caso nenhuma
correspondncia seja encontrada. Basta adicionar uma declarao default. A declarao
default uma boa maneira de direcionar qualquer final livre que possa ficar pendente na
declarao switch. Por exemplo, no programa de converso de base numrica, pode-se usar
uma declarao default para informar ao usurio que uma resposta invlida foi dada e para
tentar outra vez.
Usa-se freqentemente o switch para desviar uma seleo de menu para a rotina
apropriada. Seguindo essa linha, pode-se us-la para fazer um melhoramento adicional ao
programa de converso de base numrica. A verso mostrada aqui elimina as sries
anteriores de ifs e substitui-as por uma clara declarao switch.
/* Programa de converso de base numrica switch
decimal ---> hexadecimal
hexadecimal ---> decimal*/
#include <stdio.h>
void main()
{
int opcao;
int valor;
printf (Converter: \n);
printf (1: decimal para hexadecimal\n);
printf (2: hexadecimal para decimal\n);
printf (\nInforme sua opo: );
scanf (%d, &opcao);
switch(opcao)
{
case 1:
printf (\nInforme o valor em decimal: );
scanf (%d, &valor);
printf (%d em hexadecimal e: %x, valor, valor);
break;
case 2:
printf (\nInforme o valor em hexadecimal: );
scanf (%x, &valor);
printf (%x em decimal e: %d, valor, valor);
break;
default:
printf (\nOpo invlida. Tente outra vez.)
}
}

5.8.1 As Declaraes Switch Aninhadas


possvel ter um switch como parte da seqncia de declarao de um switch
externo. Mesmo que as constantes case do switch interno e externo contenham valores

comuns, nenhum conflito surgir. Por exemplo, o seguinte fragmento de cdigo


perfeitamente aceitvel.
switch(x){
case 1:

switch(y){

case 0:
printf (erro de diviso por zero);
break;
case 1:
process (x, y);

}
break;
case 2:
.
.
.

Como outro exemplo, um programa de banco de dados bastante simples mostrado a


seguir ilustra como se pode usar uma declarao switch aninhada. Este programa solicita ao
usurio a regio e a letra inicial do nome do vendedor e, ento, mostra o demonstrativo de
vendas do mesmo. Switchs aninhados so requeridos uma vez que muitos vendedores tm a
mesma letra inicial. Note que uma nova funo, toupper( ), introduzida. Ela retorna a
letra maiscula correspondente do seu argumento caractere. Ela usada neste programa
para permitir que o usurio insira informaes tanto em letra maiscula como em letra
minscula. A funo complementar de toupper( ) tolower( ), que converte caracteres
maisculos em minsculos. Ambas as funes esto contidas na biblioteca ctype.h.
/* Um banco de dados simples de vendedores por regio */
#include <stdio.h>
#include <ctype.h>
void main()
{
char regiao, vendedor;
printf (As regies so: Leste, Oeste e Norte\n);
printf (Informe a primeira letra da regio: );
regiao = getche();
regiao = toupper(regiao); /*converte para maisculas*/
printf (\n);
switch (regiao)
{
case L:
printf (Vendedores so: Rafael, Joo e Maria \n);
printf (Informe a primeira letra do vendedor: );
vendedor = toupper(getche());
printf (\n);
switch (vendedor)
{
case R:
printf (Vendas: R$%d\n, 10000);
break;
case J:
printf (Vendas: R$%d\n, 12000);
break;

case M:
printf (Vendas: R$%d\n, 14000);
}
break;
case O:
printf (Vendedores so: Ronaldo, Lisa e Hilton\n);
printf (Informe a primeira letra do vendedor: );
vendedor = toupper(getche());
printf (\n);
switch (vendedor)
{
case R:
printf (Vendas: R$%d\n, 10000);
break;
case L:
printf (Vendas: R$%d\n, 9500);
break;
case H:
printf (Vendas: R$%d\n, 13000);
}
break;
case N:
printf (Vendedores so: Toms, Joo e Raquel\n);
printf (Informe a primeira letra do vendedor: );
vendedor = toupper(getche());
printf (\n);
switch (vendedor)
{
case R:
printf (Vendas: R$%d\n, 5000);
break;
case J:
printf (Vendas: R$%d\n, 9000);
break;
case T:
printf (Vendas: R$%d\n, 14000);
}
break;
}
}

Para ver como o programa funciona, seleciona-se a regio Oeste, digitando O. Isso
indica que case O selecionado pela declarao switch externa. Para ver o total de vendas
de Hilton, digite H. Isso faz com que o valor 13000 seja apresentado.
Note que a declarao break em um switch aninhado no tem efeito no switch
externo.

5.9 Laos Aninhados


Quando um lao est dentro de outro, diz-se que o lao mais interno aninhado.
Laos aninhados propiciam o meio de resolver alguns problemas interessantes de
programao. Por exemplo, este pequeno programa exibe as quatro primeiras potncias dos
nmeros de 1 a 9.

/* Exibe uma tabela das 4 primeiras potencies de 1 a 9 */


#include <stdio.h>
void main()
{
int i, j, k, temp;
printf( i i^2 i^3 i^4\n);
for (i = 1; i < 10; i++)
{ /* lao externo */
for (j = 1; j < 5; j++)
{ /* primeiro aninhamento */
temp = 1;
for (k = 0; k < j; k++) /* segundo aninhamento */
temp = temp * i;
printf (%9d, temp);
}
printf (\n);
}
}

Algumas vezes, importante determinar quantas interaes o lao interno executa.


Este nmero conseguido multiplicando-se o nmero de vezes que o lao externo intera
pelo nmero de vezes que o lao interno repetido cada vez que executado. No exemplo
do programa de potncia, o lao externo repetido nove vezes e o segundo lao, quatro
vezes; assim, o segundo lao interagir 36 vezes. O lao interno executado, em mdia,
duas vezes; dessa forma, o nmero total de interaes 72.
Como no ltimo exemplo, um melhoramento final para o programa de converso de
base numrica usando-se laos aninhados mostrado aqui. O lao externo faz com que o
programa seja executado at que o usurio diga para parar. O lao interno assegura que o
usurio informar uma seleo vlida do menu. Agora, em vez de simplesmente converter
um nmero toda vez que for executado, o programa repete at que o usurio queira parar.
/* Programa de converso de base numrica verso final
decimal ---> hexadecimal
hexadecimal ---> decimal*/
#include <stdio.h>
void main()
{
int opcao;
int valor;
/*repete at que o usurio diga para terminar*/
do
{
/*assegura que o usurio especificou uma opo vlida*/
do
{
printf (Converter: \n);
printf (1: decimal para hexadecimal\n);
printf (2: hexadecimal para decimal\n);
printf (3: fim\n);

printf (\nInforme sua opo: );


scanf (%d, &opcao);
}
while(opcao < 1 || opcao > 3);
switch(opcao)
{
case 1:
printf (\nInforme o valor em decimal: )
scanf (%d, &valor);
printf (%d em hexadecimal e: %x, valor, valor);
break;
case 2:
printf (\nInforme o valor em hexadecimal: )
scanf (%x, &valor);
printf (%x em decimal e: %d, valor, valor);
break;
case 3:
default:
printf (\nOpo invlida. Tente outra vez.)
}
printf (\n);
}
while(opcao != 5);
}

5.10 Sntese do Mdulo


apresentado seguir, uma sntese do que foi tratado em cada item deste mdulo.
Com esta sntese voc poder relembrar conceitos vistos durante nosso estudo ou mesmo
direcionar seu estudo, caso voc j tenha conhecimentos na Linguagem C.
45 5.1 A Declarao If: neste item foi apresentada uma introduo da declarao
if, listando suas caractersticas e propriedades bem como sua estrutura. Foi apresentado um
exemplo com o uso da declarao if para facilitar o entendimento e compreenso.
46 5.1.1 Usando a Declarao Else: foi apresentada a declarao else, que tem
como funo dar seqncia s opes apresentadas pela declarao if.
47 5.1.2 O Encadeamento If-Else-If: foi mostrado o encadeamento de ifs e elses
que permite inserir dentro das alternativas um primeiro if novos teste condicionais.
48 5.1.3 A Expresso Condicional: foi visto que qualquer expresso vlida na
linguagem C pode ser usada para controla a declarao if. Isto , o tipo de expresso no
precisa se restringir quelas envolvendo operadores relacionais e lgicos. S requerido
que a expresso resulte em um valor zero ou no zero.
49 5.1.4 Ifs Aninhados: foi visto que um if aninhado uma declarao if que
objeto de um if ou um else, ou seja, uma declarao if dentro da outra.
50 5.2 A Declarao For: neste item foi apresentada uma introduo da
declarao for, listando suas caractersticas e propriedades bem como sua estrutura. Foi
apresentado que a declarao for usada para repetir um ou mais comandos um certo
nmero de vezes.

51 5.2.1 Partes do Comando For so Opcionais: foi visto que muitas partes
constituintes da declarao for so opcionais.
52 5.2.2 Compreendendo um Lao Null: foi visto que este um recurso para
obter um retardo ou uma breve pausa durante a execuo de um programa.
53 5.2.3 Lao Infinito: foi visto que muitas vezes, devido erros de
programao, alguns laos for nunca atingem sua condio final, sendo executados
infinitamente.
54 5.2.4 Usando o operador vrgula da Linguagem C dentro de um lao for:
foi mostrado que a Linguagem C permite inicializar e incrementar mltiplas variveis em
um lao for separando as operaes com vrgula.
55 5.3 A Declarao While: foi visto que ao encontrar um lao while no
programa, a Linguagem C testa a condio especificada. Se a condio for verdadeira,
efetuar os comandos contidos no lao. Se o comando for falso, continuar a execuo de
seu programa ao primeiro comando que segue.
56 5.3.1 Partes de um Lao While: foi estudado as partes componentes do lao
while, de tal forma a conhece-las evitando laos infinitos e erros de programao.
57 5.4 A Declarao Do-While: neste item foi mostrado que o lao do-while
verifica sua condio no final do lao. Isso significa que um lao do-while ser executado
pelo menos uma vez.
58 5.5 Comando Continue: foi visto neste item que o comando continue em um
programa utilizado quando quer-se pular a iterao atual.
59 5.6 Finalizando um Lao Usando o Comando Break: o comando Break
utilizado para terminar imediatamente a execuo de um lao e a partir da continuar
executando a prxima linha de cdigo aps o lao.
60 5.7 Desvios com o comando goto: o comando goto permite que a execuo
do programa desvie-se para uma localizao especfica, chamada rtulo.
61 5.8 A Declarao Switch: na declarao switch, a varivel sucessivamente
testada contra uma lista de inteiros ou constantes caractere. Quando uma associao
encontrada, o conjunto de comandos associado com a constante executado.
62 5.8.1 As Declaraes Switch Aninhadas: da mesma forma vista para a
declarao for, a declarao switch pode ser posta no cdigo de programao da forma
aninhada.
63 5.9 Laos Aninhados: Quando um lao est dentro de outro, diz-se que o
lao mais interno aninhado. Laos aninhados propiciam o meio de resolver alguns
problemas interessantes de programao.

Mdulo 6 Matrizes

6.1 Compreendendo as Matrizes


Muitas vezes em programas, necessrio que uma varivel contenha muitos
valores. Por exemplo, a varivel nota pode controlar as notas obtidas por 100 alunos em um
exame. Da mesma maneira, a varivel salrios poderia controlar os salrios de cada
funcionrio em uma companhia. Uma matriz uma estrutura de dados que pode armazenar
mltiplos valores do mesmo tipo. Por exemplo, pode-se criar uma matriz que possa conter
100 valores do tipo int e uma segunda matriz com 25 valores do tipo float.
Todo valor que se atribui a uma matriz precisa ser do mesmo tipo que o tipo da
matriz. Neste mdulo ser mostrado como criar e trabalhar com matrizes em programas.
Com o tempo, aps o uso de matrizes, ficar claro como simples o uso de matrizes.

6.2 Declarando uma Matriz


Para declarar uma matriz, precisa-se especificar o tipo desejado (tal como int, float
ou double), bem como o tamanho da matriz. Para especificar o tamanho de uma matriz,
coloca-se o nmero de valores que a matriz pode armazenar dentro de colchetes aps o
nome da matriz. Por exemplo, a declarao seguir cria uma matriz chamada notas, que
pode armazenar 100 notas de exame do tipo int:
int notas [100];

De forma similar, a seguinte declarao cria uma matriz do tipo float, que contm
50 salrios:
float salarios [50];

Quando uma matriz declarada, a Linguagem C aloca memria suficiente para


conter todos os elementos. O primeiro item est na posio 0. Por exemplo, nas matrizes
notas e salarios, os comandos a seguir atribuem os valores 80 e 35000 aos primeiros
elementos da matriz:
notas[0] = 80;
salarios[0] = 35000;

Como o primeiro elemento da matriz inicia no deslocamento 0, o ltimo elemento


da matriz ocorre uma posio antes do tamanho da matriz. Dadas as matrizes anteriores, os
comandos a seguir atribuem valores ao ltimo elemento de cada matriz:
notas[99] = 65;
salarios[49] = 250000;

6.3 Requisitos de Armazenamento de uma Matriz


Ao declarar uma matriz, o compilador aloca memria suficiente para conter o
nmero de valores especificado. A quantidade real de memria que o compilador aloca
depende do tipo da matriz. Por exemplo, uma matriz de 100 elementos do tipo int
normalmente ir requerer 100*2 ou 200 bytes de memria. Por outro lado, uma matriz de
100 elementos do tipo float ir requerer 100*4 bytes ou 400 bytes. O programa abaixo, usa
o operador sizeof para exibir a quantidade de memria que os diferentes tipos de matrizes
requerem:

#include <stdio.h>
void main(void)
{
int notas[100];
float salar[100];
char string[100];
printf("Memoria para conter int notas[100] %d bytes\n",
sizeof(notas));
printf("Memoria para conter float salar[100] %d bytes\n",
sizeof(salar));
printf("Memoria para conter char string[100] %d bytes\n",
sizeof(string));
}

6.4 - Inicializando uma Matriz


segue:

Muitos programas em Linguagem C inicializam as strings de caracteres como

char titulo[] = "UNESP - Ilha Solteira";


char secao[64] = "Matrizes";

No primeiro caso, o compilador alocar 22 bytes para armazenar a string. No


segundo, o compilador alocar uma matriz de 64 bytes, inicializando os primeiro 8
caracteres com as letras "Matrizes" e o caracter NULL. A maioria dos compiladores
tambm inicializar as posies de bytes restantes com NULL. Quando declara-se matrizes
de outros tipos, pode inicializar matrizes da mesma forma. Por exemplo, o comando a
seguir inicializa a matriz de inteiros notas com os valores 80, 70, 90, 85 e 80:
int notas[5] = {80, 70, 90, 85, 80};

Quando atribui-se valores iniciais a uma matriz, necessrio delimitar os valores


por abre e fecha chaves ( {} ). No caso anterior, o tamanho da matriz igual ao nmero de
valores atribudos. O comando a seguir, no entanto, atribui quatro valores de ponto
flutuante a uma matriz que pode armazenar 64 valores:
float salar[64] = {25000.0, 32000.0; 44000.0, 23000.0};

Dependendo do compilador, ele pode atribuir 0 aos elementos aos quais o programa
no atribui valores explcitos. No entanto, como regra, no se deve assumir que o
compilador inicializar os outros elementos. Alm disso, se no for especificado um
tamanho de matriz, o compilador alocar memria suficiente para conter somente os
valores que voc especificar. Por exemplo, a seguinte declarao de matriz cria uma matriz
grande o suficiente para conter trs valores do tipo long:
long planetas[] = {1234567L, 654321L, 1221311L};

6.5 Acessando Elementos da Matriz


Os valores armazenados em uma matriz so chamados elementos de matriz. Para
acessar um elemento da matriz, voc especifica o nome da matriz e o elemento que deseja.

O programa a seguir, inicializa a matriz notas e depois usa printf para exibir os valores dos
elementos:
#include <stdio.h>
void main(void)
{
int notas[5] = {80, 70, 90, 85, 80};
printf("Valores da Matriz\n");
printf("notas[0] %d\n", notas[0]);
printf("notas[1] %d\n", notas[1]);
printf("notas[2] %d\n", notas[2]);
printf("notas[3] %d\n", notas[3]);
printf("notas[4] %d\n", notas[4]);
}

6.6 Percorrendo em um Lao Elementos da Matriz


Quando se referencia muitos elementos de uma matriz, especificar nmeros para
cada elemento da matriz individualmente pode ser demorado e tedioso. Como uma
alternativa, os programas podem usar uma varivel para referenciar os elementos da matriz.
Por exemplo, assumindo que a varivel i contenha o valor 2, o comando a seguir atribuiria
o valor 80 a matriz[2]:
i = 2;
matriz[i] = 80;

notas:

O cdigo a seguir usa a varivel i e um lao for para exibir os elementos da matriz

#include <stdio.h>
void main(void)
{
int notas[5] = {80, 70, 90, 85, 80};
int i;
printf("Valores da Matriz\n");
for (i = 0; i < 5; i++)
printf("notas[%d] %d\n", i, notas[i]);
}

6.7 Usando Constantes Para Definir as Matrizes


Como visto, quando os programas trabalham com matrizes, necessrio especificar
o tamanho da matriz. Por exemplo, o programa a seguir declara uma matriz de cinco
valores e depois usa um lao for para exibir os valores da matriz:
#include <stdio.h>
void main(void)
{
int valores[5] = {80, 70, 90, 85, 80};
int i;

for (i = 0; i < 5; i++)


printf("valores[%d] %d\n", i, valores[i]);
}

Por exemplo, suponha que seja necessrio alterar o cdigo anterior de tal forma que
ele suporte 10 valores. Precisar alterar no somente a declarao da matriz, mas tambm o
lao for. Quanto mais alteraes forem feitas em um programa, maiores as chances de errar.
O programa a seguir declara uma matriz com base na constante TAM_MATRIZ. Como se
v, o programa no somente usa a constante para declarar a matriz, mas tambm usa a
constante como a condio final para o lao for:
#include <stdio.h>
#define TAM_MATRIZ 5
void main(void)
{
int valores[TAM_MATRIZ] = {80, 70, 90, 85, 80};
int i;
for (i = 0; i < TAM_MATRIZ; i++)
printf("valores[%d] %d\n", i, valores[i]);
}

Se mais tarde for necessrio alterar o tamanho da matriz, poder alterar o valor
atribudo constante TAM_MATRIZ para que o programa automaticamente atualize os
laos que controlam a matriz como o tamanho da matriz.

6.8 Passando uma Matriz a uma Funo


Quando declara-se uma funo que trabalha com um parmetro matriz, precisa
informar o compilador. Por exemplo, o seguinte programa usa a funo exibe_matriz para
exibir os valores em uma matriz. Como pode-se ver, o programa passa para a funo tanto a
matriz como o nmero de elementos que a matriz contm, como mostrado a seguir:
#include <stdio.h>
void exibe_matriz(int valores[], int num_de_elementos)
{
int i;
for (i = 0; i < num_de_elementos; i++)
printf("%d\n", valores[i]);
}
void main(void)
{
int notas[5] = {70, 80, 90, 100, 90};
exibe_matriz(notas, 5);
}

Quando uma funo recebe uma matriz como parmetro, o programa no precisa
especificar o tamanho da matriz na declarao do parmetro. No caso da funo
exibe_valores, os colchetes aps o nome da varivel valor informam o compilador de que o
parmetro uma matriz. Sabendo que o parmetro uma matriz, o compilador no se
preocupa com o tamanho da matriz que o programa passa para a funo.

6.9 Revisitando as Matrizes Como Funes

No item anterior, foi visto que ao declarar o parmetro formal para uma matriz, no
necessrio declarar o tamanho da matriz. Em vez disso, pode-se especificar somente o
abre e fecha colchetes. O programa a seguir passa trs matrizes diferentes (de diferentes
tamanhos) para a funo exibe_valores:

#include <stdio.h>
void exibe_matriz(int valores[], int num_de_elementos)
{
int i;
printf("Prestes a exibir %d valores\n",num_de_elementos);
for (i = 0; i < num_de_elementos; i++)
printf("%d\n", valores[i]);
}
void main(void)
{
int notas[5] = {70, 80, 90, 100, 90};
int conta[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int pequeno[2] = {-33, -44};
exibe_matriz(notas, 5);
exibe_matriz(conta, 10);
exibe_matriz(pequeno, 2);
}

6.10 Como as Matrizes de String Diferem


Muitos programas passam string para funes. Em muitos casos, as funes no
especificaram o tamanho da string. Por exemplo, o comando a seguir usa a funo strupr
para converter uma string para maisculas:
char titulo[64] = "Unesp Ilha Solteira";
strupr(titulo);

Como foi visto, na Linguagem C o caracter NULL representa o final de uma string
de caracteres. Portanto, as funes podem procurar o caracter NULL nos elementos da
matriz para determinar onde a matriz termina. No entanto, as matrizes de outros tipos, tais
como int, float ou long, no tem um caracter finalizador equivalente. Portanto, voc
normalmente precisa passar para as funes que trabalham com matrizes o nmero de
elementos que a matriz contm.

6.11 Quantos Elementos Uma Matriz Pode Armazenar


J foi visto anteriormente que, dependendo do tipo de uma matriz, a quantidade real
de memria que uma matriz pode consumir diferir. Se o ambiente de trabalho for o DOS, a
quantidade de memria que as matrizes podem consumir depender do modelo de memria

atual. Em geral, uma matriz no pode consumir mais do que 64Kb de espao. O programa a
seguir pode no passar na compilao porque as matrizes consomem muita memria:
void main(void)
{
char string[66000L];
int values[33000L];
float numbers[17000];
}

/* 66,000 bytes */
/* 33,000 * 2 = 66,000 bytes */
/* 17,000 * 4 = 68,000 bytes */

6.12 Matrizes Multidimensionais


Como foi visto, uma matriz uma varivel que pode armazenar mltiplos valores
do mesmo tipo. Em todos os exemplos apresentados at o momento, as matrizes
consistiram de uma fileira de dados. No entanto, a Linguagem C permite matrizes bi, tri e
multidimensionais. O melhor modo de visualizar uma matriz bidimensional com uma
tabela com linhas e colunas. Se uma matriz contm trs dimenses, visualize-a como vrias
pginas, cada uma das quais contendo uma tabela bidimensional.
Por exemplo, ao declarar-se uma matriz bidimensional, o primeiro valor que for
especificado informar o nmero de linhas, e o segundo valor, o nmero de colunas:
int tabela [2] [3];

6.13 - Inicializando Elementos em Uma Matriz Bidimensional


No item 5.4 foi visto que, para inicializar elementos de matriz, voc pode colocar os
valores do elemento dentro de abre e fecha colchetes aps a declarao da matriz. O
comando a seguir usa a mesma tcnica para inicializar uma matriz bidimensional. No
entanto, neste caso, o comando especifica os valores para cada linha da matriz dentro de
chaves:
int tabela [2] [3] = {{1,2,3}, {4,5,6}};

O compilador inicializar os elementos da matriz como mostrado a seguir:


1

6.14 Percorrendo em Um Lao Uma Matriz Bidimensional


Quando os programas trabalham com matrizes bidimensionais, normalmente usa-se
duas variveis para acessar elementos da matriz. O programa a seguir usa as variveis linha
e coluna para exibir os valores contidos dentro da matriz tabela:
#include <stdio.h>
void main(void)
{
int linha, coluna;
float tabela[3][5] = {{1.0, 2.0, 3.0, 4.0, 5.0},

{6.0, 7.0, 8.0, 9.0, 10.0},


{11.0, 12.0, 13.0, 14.0, 15.0}};
for (linha = 0; linha < 3; linha++)
for (coluna = 0; coluna < 5; coluna++)
printf("tabela[%d][%d] = %f\n", linha, coluna,
tabela[linha][coluna]);
}

Colocando laos for um dentro do outro, como mostrado, o programa exibir os


elementos contidos na primeira linha da matriz (1.0 at 5.0). Em seguida, o programa ir se
mover para a prxima linha, e, depois, para a terceira linha, exibindo os elementos dentro
de cada linha.

6.15 Percorrendo Uma Matriz Tridimensional


No item anterior foi visto como percorrer uma matriz bidimensional usando duas
variveis chamadas linha e coluna. O programa a seguir usa as variveis linha, coluna e
tabela para percorrer uma matriz tridimensional:
#include <stdio.h>
void main(void)
{
int linha, coluna, tabela;
float valores[2][3][5] = {
{{1.0, 2.0, 3.0, 4.0, 5.0},
{6.0, 7.0, 8.0, 9.0, 10.0},
{11.0, 12.0, 13.0, 14.0, 15.0}},
{{16.0, 17.0, 18.0, 19.0, 20.0},
{21.0, 22.0, 23.0, 24.0, 25.0},
{26.0, 27.0, 28.0, 29.0, 30.0}}
};
for (linha = 0; linha < 2; linha++)
for (coluna = 0; coluna < 3; coluna++)
for (tabela = 0; tabela < 5; tabela++)
printf("valores[%d][%d][%d] = %f\n", linha,
coluna, tabela,
valores[linha][coluna][tabela]);
}

6.16 Passando uma Matriz Bidimensional Para uma Funo


No item 5.8, foi visto que, ao passar matrizes para uma funo, no ser necessrio
especificar o nmero de elementos na matriz. Em matrizes bidimensionais, no ser
necessrio especificar o nmero de linha na matriz, mas, sim, especificar o nmero de
colunas. O programa a seguir usa a funo exibe_2d_matriz para exibir o contedo de
variveis matrizes bidimensionais:
#include <stdio.h>
void exibe_2d_matriz(int matriz[][10], int linhas)
{
int i, j;

for (i = 0; i < linhas; i++)


for (j = 0; j < 10; j++)
printf("matriz[%d][%d] = %d\n", i, j, matriz[i][j]);
}
void main(void)
{
int a[1][10] = {{1, 2, 3, 4, 5,
int b[2][10] = {{1, 2, 3, 4, 5,
{11, 12, 13, 14,
int c[3][10] = {{1, 2, 3, 4, 5,
{11, 12, 13, 14,
{21, 22, 23, 24,
exibe_2d_matriz(a, 1);
exibe_2d_matriz(b, 2);
exibe_2d_matriz(c, 3);
}

6, 7, 8, 9,
6, 7, 8, 9,
15, 16, 17,
6, 7, 8, 9,
15, 16, 17,
25, 26, 27,

10}};
10},
18, 19,20}};
10},
18, 19, 20},
28, 29, 30}};

6.17 Tratando as Matrizes Multidimensionais Como Uma


Dimenso
Quando for necessrio trabalhar com os elementos de uma matriz multidimensional,
mas sem precisar acessar os elementos em suas posies de linha ou coluna, as funes
podero tratar a matriz multidimensional como se ela tivesse uma dimenso. O programa a
seguir retorna a soma dos valores em uma matriz bidimensional:
#include <stdio.h>
long soma_matriz(int matriz[], int elementos)
{
long soma = 0;
int i;
for (i = 0; i < elementos; i++)
soma += matriz[i];
return(soma);
}
void main(void)
{
int a[10] =
{1,
int b[2][10]={{1,
{11,
int c[3][10]={{1,
{11,
{21,
printf("Soma dos
soma_matriz(a,
printf("Soma dos
soma_matriz(b,
printf("Soma dos
soma_matriz(c,

2, 3, 4, 5,
2, 3, 4, 5,
12, 13, 14,
2, 3, 4, 5,
12, 13, 14,
22, 23, 24,

6, 7, 8, 9,
6, 7, 8, 9,
15, 16, 17,
6, 7, 8, 9,
15, 16, 17,
25, 26, 27,

10};
10},
18, 19,20}};
10},
18, 19, 20},
28, 29,30}};

elementos da primeira matriz %d\n",


10));
elementos da segunda matriz %d\n",
20));
elementos da terceira matriz %d\n",
30));

6.18 Sntese do Mdulo

apresentado seguir, uma sntese do que foi tratado em cada item deste mdulo.
Com esta sntese voc poder relembrar conceitos vistos durante nosso estudo ou mesmo
direcionar seu estudo, caso voc j tenha conhecimentos na Linguagem C.
64 6.1 Compreendendo as Matrizes: dada uma explicao que uma matriz
uma estrutura de dados que pode armazenar mltiplos valores do mesmo tipo.
65 6.2 Declarando uma Matriz: neste item visto como declarar uma matriz,
precisando-se especificar o tipo desejado (tal como int, float ou double), bem como o
tamanho da matriz.
66 6.3 Requisitos de Armazenamento de uma Matriz: foi visto que ao
declarar uma matriz, o compilador aloca memria suficiente para conter o nmero de
valores especificado. A quantidade real de memria que o compilador aloca depende do
tipo da matriz.
67 6.4 Inicializando uma Matriz: neste item explicada de maneira clara
como inicializar diferentes tipos de matrizes.
68 6.5 Acessando Elementos da Matriz: foi visto que para acessar um
elemento da matriz, voc especifica o nome da matriz e o elemento que deseja.
69 6.6 Percorrendo em um Lao Elementos da Matriz: foi mostrado que
quando se referencia muitos elementos de uma matriz, especificar nmeros para cada
elemento da matriz individualmente pode ser demorado e tedioso. Como uma alternativa,
os programas podem usar uma varivel para referenciar os elementos da matriz.
70 6.7 Usando Constantes Para Definir as Matrizes: mostra como os
programas usam constantes para definir matrizes.
71 6.8 Passando uma Matriz a uma Funo: visto que programas passam
para a funo tanto a matriz como o nmero de elementos que a matriz contm.
72 6.9 Revisitando as Matrizes Como Funes: . foi visto um programa que
passa trs matrizes diferentes (de diferentes tamanhos) para a funo exibe_valores.
73 6.10 Como as Matrizes de String Diferem: explica as principais diferenas
das matrizes de string.
74 6.11 Quantos Elementos Uma Matriz Pode Armazenar: foi visto que se o
ambiente de trabalho for o DOS, a quantidade de memria que as matrizes podem consumir
depender do modelo de memria atual. Em geral, uma matriz no pode consumir mais do
que 64Kb de espao.
75 6.12 Matrizes Multidimensionais: foi visto que a Linguagem C permite
matrizes bi, tri e multidimensionais.
76 6.13 Inicializando Elementos em Uma Matriz Bidimensional: foi
mostrado como inicializar uma matriz bidimensional.
77 6.14 Percorrendo em Um Lao Uma Matriz Bidimensional: foi mostrado
um programa que usa as variveis linha e coluna para exibir os valores contidos dentro da
matriz tabela.

78 6.15 Percorrendo Uma Matriz Tridimensional: foi mostrado um


programa que usa as variveis linha, coluna e tabela para percorrer uma matriz
tridimensional.
79 6.16 Passando uma Matriz Bidimensional Para uma Funo: foi visto
que para passar matrizes bidimensionais para uma funo, no ser necessrio especificar o
nmero de linha na matriz, mas, sim, especificar o nmero de colunas.
80 6.17 Tratando as Matrizes Multidimensionais Como Uma Dimenso: foi
visto que quando for necessrio trabalhar com os elementos de uma matriz
multidimensional, mas sem precisar acessar os elementos em suas posies de linha ou
coluna, as funes podero tratar a matriz multidimensional como se ela tivesse uma
dimenso.

Mdulo 7 Ponteiros
7.1 Ponteiros como Endereos
Como j foi visto, uma varivel o nome de uma posio na memria que pode
armazenar um valor de um determinado tipo. Os programas referenciam cada posio na
memria usando um endereo exclusivo. Um ponteiro uma varivel ou um valor que
contem um endereo. A Linguagem C utiliza muito os ponteiros. Quando se passa matrizes
ou string para as funes, o compilador C passa um ponteiro. Da mesma forma, quando
uma funo precisa alterar o valor de um parmetro, o programa deve passar para a funo
um ponteiro para o endereo de memria da varivel.

7.2 Determinando o Endereo de uma Varivel


Um ponteiro um endereo de uma posio na memria. Quando os programas
trabalham com matrizes (e strings), o programa trabalha com um ponteiro para o primeiro
elemento da matriz. Quando os programas precisarem determinar o endereo de uma
varivel, devero usar o operador de endereo da Linguagem C &.
Por exemplo, o programa a seguir usa o operador de endereo para exibir o
endereo de vrias variveis diferentes:
#include <stdio.h>
void main(void)
{
int conta = 1;
float salario = 40000.0;
long distancia = 1234567L;
printf("O endereo de conta %x\n", &conta);
printf("O endereo de salario %x\n", &salario);
printf("O endereo de distancia %x\n", &distancia);
}

7.3 Como a Linguagem C trata Matrizes como Ponteiros


J foi visto anteriormente que um compilador C trata as matrizes como ponteiros.
Por exemplo, quando um programa passa uma matriz para uma funo, o compilador passa
o endereo inicial da matriz.
O programa a seguir exibe o endereo inicial de vrias matrizes diferentes:
#include <stdio.h>
void main(void)
{
int conta[10];
float salarios[5];
long distancia[10];
printf("O endereo da matriz conta %x\n", conta);
printf("O endereo da matriz salarios %x\n", salarios);
printf("O endereo da matriz distancia %x\n", distancia);
}

7.4 Aplicando o Operador de Endereo (&) a uma Matriz


Se o operador de endereo for aplicado a uma matriz, a Linguagem C retornar o
endereo inicial da matriz. Portanto, aplicar o operador de endereo a uma matriz
redundante. O programa a seguir exibe o endereo inicial de uma matriz, seguido pelo
ponteiro que o operador de endereo retorna:
#include <stdio.h>
void main(void)
{
int conta[10];
float salarios[5];
long distancias[10];
printf("O endereo da matriz conta %x &conta %x\n",
conta, &conta);
printf("O endereo da matriz salarios %x &conta %x\n",
salarios, &salarios);
printf("O endereo da matriz distancias %x &distancias
%x\n", distancias, &distancias);
}

7.5 Declarando Variveis Ponteiros


medida que os programas tornarem-se mais complexos, ponteiros so usados com
muita freqncia. Para armazenar ponteiros, os programas precisam declarar variveis
ponteiros. Para declarar um ponteiro, precisa-se especificar o tipo do valor ao qual o
ponteiro aponta (tal como int, float, char, etc.) e um asterisco (*) antes do nome da
varivel. Por exemplo, o comando a seguir declara um ponteiro para um valor do tipo int:
int *iptr;

Como qualquer varivel, precisa-se atribuir um valor a uma varivel ponteiro antes
de poder usar o ponteiro dentro do programa. Quando atribui-se um valor a um ponteiro,
realmente atribui um endereo. Assumindo que anteriormente tenha-se declarado int conta,
o comando a seguir atribui o endereo da varivel conta ao ponteiro iptr:
iptr = &conta;

/* Atribui o endereo de conta a iptr */

O programa a seguir declara a varivel ponteiro iptr e atribui ao ponteiro o endereo


da varivel conta. O programa ento exibe o valor da varivel ponteiro, juntamente com o
endereo de conta:
#include <stdio.h>
void main(void)
{
int *iptr;
int conta = 1;

/* Declara variavel ponteiro */

iptr = &conta;
printf("Valor de iptr %x Valor de conta %d Endereo de conta
%x\n", iptr, conta, &conta);
}

7.6 Desreferenciando um Ponteiro


Desreferenciar um ponteiro o processo de acessar o valor de uma posio de
memria especfica. Para desreferenciar o valor de um ponteiro, usa-se o operador asterisco
de indireo (*). Por exemplo, o comando printf a seguir exibe o valor apontado pelo
ponteiro inteiro iptr:
printf(O valor apontado po iptr %d\n, *iptr);

Da mesma forma, o comando a seguir atribui o valor apontado pela varivel iptr
para a varivel conta:
conta = *iptr;

Finalmente, o comando a seguir atribui o valor 7 posio de memria apontada


por iptr:
*iptr = 7;

7.7 Usando Valores de Ponteiro


O programa a seguir atribui ao ponteiro int iptr o endereo da varivel conta. O
programa depois exibe o valor do ponteiro e o valor armazenado na posio apontada pelo
ponteiro (o valor contador).
O programa ento modifica o valor apontado pelo ponteiro, como mostrado aqui:
#include <stdio.h>
void main(void)

{
int contador = 10;
int *iptr;

/* Declara valor do ponteiro */

iptr = &contador;
/* Atribui o endereo */
printf("Endereo em iptr %x Valor em *iptr %d\n", iptr, *iptr);
*iptr = 25;

/* Altera o valor na memria */

printf("Valor de contador %d\n", contador);


}

7.8 Ponteiros com Parmetros de Funo


O Mdulo de Funes examina em detalhes o processo de passar parmetros para as
funes. Quando for necessrio alterar o valor de um parmetro, dever passar para a
funo um ponteiro para um parmetro. O programa a seguir usa os ponteiros para dois
parmetros do tipo int para permutar os valores das variveis, como mostrado a seguir:
#include <stdio.h>
void troca_valores(int *a, int *b)
{
int temp;
temp = *a; /* Armazena temporariamente o valor */
/* apontado por a */
*a = *b;
/* Atribui o valor de b a a */
*b = temp; /* Atribui o valor de a a b */
}
void main(void)
{
int um = 1, dois = 2;
troca_valores(&um, &dois);
printf("um contm %d dois contm %d\n", um, dois);
}

Como pode ser visto, dentro da funo, os comandos desreferenciam os ponteiros


usando o operador de indireo (*). O programa passa o endereo de cada varivel para a
funo usando o operador de endereo (&).

7.9 A Aritmtica de Ponteiros


Um ponteiro um endereo que aponta para um valor de um determinado tipo na
memria. Nos termos mais simples possveis, um ponteiro um valor que aponta para uma
posio de memria especfica. Se somar-se o valor 1 a um ponteiro, o ponteiro apontar
para a prxima posio de memria. Se somar-se 5 ao valor de um ponteiro, o ponteiro
apontar para a posio de memria de cinco posies adiante do endereo atual. No
entanto, a aritmtica de ponteiro no to simples quanto parece. Por exemplo, assuma que
um ponteiro contenha o endereo 1000. Se fosse somado 1 ao ponteiro, poderia se esperar
que o resultado fosse 1001. No entanto, o endereo resultante depende do tipo de ponteiro.
Por exemplo, se fosse somado 1 a um ponteiro do tipo char (que contm 1000), o endereo

resultante ser 1001. Se fosse somado 1 a um ponteiro do tipo int (que requer dois bytes na
memria), o endereo resultante ser 1002. Quando for efetuada a aritmtica de ponteiro
necessrio ter em mente o tipo de ponteiro. Alm de somar valores aos ponteiros, os
programas podero subtrair valores ou somar e subtrair dois ponteiros.

7.10 Incrementando e Decrementando um Ponteiro


Uma das operaes mais comuns com ponteiros o incremento e o decremento do
valor de um ponteiro para apontar para a prxima posio ou para a posio anterior na
memria. O programa a seguir atribui o endereo inicial de uma matriz de valores inteiros
ao ponteiro iptr. O programa depois incrementa o valor do ponteiro para exibir os cinco
elementos que a matriz contm:
#include <stdio.h>
void main(void)
{
int valores[5] = {1, 2, 3, 4, 5};
int contador;
int *iptr;
iptr = valores;
for (contador = 0; contador < 5; contador++)
{
printf("%d\n", *iptr);
iptr++;
}
}

7.11 - Percorrendo uma String usando um Ponteiro


Uma string uma matriz de caracteres terminada p NULL. O programa a seguir
usa a funo exibe_string para exibir uma string de caracteres usando um ponteiro:
#include <stdio.h>
void exibe_string(char *string)
{
while (*string)
putchar(*string++);
}
void main(void)
{
exibe_string("Unesp Ilha Solteira");
}

Como pode ser visto, a funo exibe_string declara a varivel string como um
ponteiro. Usando o ponteiro, a funo simplesmente percorre os caracteres da string at
encontrar o caractere NULL. Para exibir o caractere, a funo exibe_string primeiro
desreferencia o endereo do ponteiro (obtendo o caractere). Em seguida, a funo
incrementa o ponteiro para apontar para o prximo caractere na string.

7.12 - Funes que retornam Ponteiros

O valor que uma funo retorna sempre do tipo declarado no prottipo ou


cabealho da funo. Alm de retornar esses tipos bsicos, as funes podem declarar
ponteiros para os valores. Por exemplo, a funo fopen, que a maioria das funes da
Linguagem C usam para abrir um canal de arquivo, retorna um ponteiro para uma estrutura
do tipo FILE, como mostrado aqui:
FILE *fopen(const char *nomecaminho, const char *modo);

7.13 Criando uma Funo que retorna um Ponteiro


O programa a seguir cria uma funo chamada string_maiusc que converte todos os
caracteres de uma string para maisculas e depois retorna um ponteiro para uma string:
#include <stdio.h>
#include <ctype.h>
char *string_maiusc(char *string)
{
char *ender_inicial, *temp;
ender_inicial = temp = string;
while (*string)
*(temp++) = toupper(*string++);
return(ender_inicial);
}
void main(void)
{
char *titulo = "UNESP Ilha Solteira";
char *string;
string = string_maiusc(titulo);
printf("%s\n", string);
printf("%s\n", string_maiusc("Matrizes e Ponteiros"));
}

7.14 - Uma Matriz de Ponteiros


Assim como pode-se criar funes que retornam ponteiros, tambm pode-se criar
matrizes de ponteiros. Mais comumente sero usadas matrizes para conter strings de
caracteres.
Como exemplo, a declarao a seguir cria uma matriz chamada dias que contm
ponteiros para string de caracteres:
char *dias[7]= {Domingo,
Sexta, Sbado};

Segunda,

Tera,

Quarta,

Quinta,

Se for examinado o tipo da matriz da direita para a esquerda, ser visto que a matriz
contm sete elementos. O asterisco antes do nome da varivel especifica um ponteiro. Se
combinar o nome do tipo char que precede o nome da varivel, a declarao se tornar
uma matriz de ponteiros para strings de caractere.

7.15 - Percorrendo em um Lao uma Matriz de Strings de


Caracteres
Ao criar uma matriz de string de caracteres, a Linguagem C armazena os ponteiros
para cada string dentro dos elementos da matriz.

O programa a seguir percorre em um lao a matriz dias, que contm ponteiros para
strings que contm os nomes dos dias da semana, como mostrado aqui:
#include <stdio.h>
void main(void)
{
char *dias[7] = {"Domingo", "Segunda", "Tera",
"Quarta", "Quinta", "Sexta", "S bado"};
int i;
for (i = 0; i < 7; i++)
printf("dias[%d] contm %s\n", i, dias[i]);
}

7.16 Usando um Ponteiro para um Ponteiro para String de


Caracteres
A declarao a seguir cria um ponteiro para uma string de caracteres:
char **dia_til_ptr;

O programa a seguir usa um ponteiro para um ponteiro para string de caracteres


para exibir o contedo da matriz diasuteis:
#include <stdio.h>
void main(void)
{
char *diasuteis[] = {"Segunda", "Tera", "Quarta",
"Quinta", "Sexta", "" };
char **dia_util;
dia_util = diasuteis;
while (*dia_util)
printf("%s\n", *dia_util++);
}

Quando o programa inicia, ele atribui ao ponteiro dia_til o endereo inicial da


matriz diasuteis (o endereo da string Segunda). O programa repete ento um lao at
encontrar o ponteiro para a string NULL (a condio final).

7.17 Declarando uma Constante String usando um Ponteiro


Muitas vezes strings de caracteres so inicializadas como segue:
char titulo[] = Unesp Ilha Solteira;

Quando se declara uma matriz com colchetes vazios, o compilador C aloca memria
suficiente para armazenar os caracteres especificados (e o terminador NULL), atribuindo
varivel titulo um ponteiro para o primeiro caractere. Como o compilador C
automaticamente aloca a memria necessria e depois trabalha com um ponteiro para a
memria, os programas podem usar um ponteiro de string de caracteres, em vez de uma
matriz, como mostrado a seguir:
char *titulo = Unesp Ilha Solteira;

7.18 O Ponteiro do tipo Void


Ao declarar uma varivel ponteiro, preciso especificar o tipo do valor para o qual
o ponteiro aponta. Quanto se faz isso, o compilador pode, mais tarde, efetuar aritmtica de
ponteiros corretamente e adicionar os valores de deslocamentos corretos quando
incrementar ou decrementar o ponteiro. Em alguns casos, no entanto, os programas no
manipularo o valor de um ponteiro de qualquer maneira. Em vez disso, os programas
somente iro obter um ponteiro para uma posio de memria com a qual o programa
determinar o uso do ponteiro.
Nesses casos, os programas podero criar um ponteiro para o tipo void, como
mostrado aqui:
void *ponteiro_memoria;

7.19 Ponteiros para as Funes


A Linguagem C permite criar ponteiros para todos os tipos de dados. Alm disso,
ela permite que os programas criem e usem ponteiros para as funes. O uso mais comum
dos ponteiros para funes permitir que os programas passem uma funo como um
parmetro para outra funo. As seguintes declaraes criam ponteiros para funes:
int (*min)();
int (*max)();
float (*media)();

Observe o uso dos parnteses entre os nomes das variveis. Se os parnteses fossem
removidos, as declaraes serviriam como prottipos de funo para as funes que
retornam ponteiros para um tipo especfico, como mostrado aqui:
int *min();
int *max();
float *media();

Ao ler uma declarao de varivel, deve-se comear com a declarao mais interna
que aparece dentro dos parnteses, e, depois, trabalha-se da direita para a esquerda:
int (*min)();

7.20 Ponteiro para uma Funo


O uso mais comum de um ponteiro para uma funo passar essa funo como um
parmetro para outra funo. O programa a seguir passa a funo min ou max para a
funo pega_result. Dependendo da funo que o programa passa, o valor que pega_result
retorna ser diferente:
#include <stdio.h>
int pega_result(int a, int b, int (*compare)())
{
return(compare(a, b)); // Chama a funo passada
}
int max(int a, int b)
{
printf("Em max\n");

return((a > b) ? a: b);


}
int min(int a, int b)
{
printf("Em min\n");
return((a < b) ? a: b);
}
void main(void)
{
int result;
result = pega_result(1, 2, &max);
printf("O maximo entre 1 e 2 %d\n", result);
result = pega_result(1, 2, &min);
printf("O minimo de 1 e 2 %d\n", result);
}

7.21 Usando um Ponteiro para um Ponteiro para um Ponteiro


A Linguagem C permite criar variveis que so ponteiros para outros ponteiros. Em
geral, no h limite no nmero de indirees (ponteiros para ponteiros) que os programas
podem usar. No entanto, para a maioria dos programadores, usar mais do que um ponteiro
para um ponteiro resultar em confuso considervel, e tornar seus programas muito
difceis de compreender. Por exemplo, o programa a seguir usa trs nveis de ponteiros para
um valor do tipo int. Separe um tempo para experimentar este programa e desenhe os nveis
de indireo em um pedao de papel at compreender o processamento que ele executa:
#include <stdio.h>
int qual_e_o_valor(int ***ptr)
{
return(***ptr);
}
void main(void)
{
int *nivel_1, **nivel_2, ***nivel_3, valor = 1001;
nivel_1 = &valor;
nivel_2 = &nivel_1;
nivel_3 = &nivel_2;
printf("O valor %d\n", qual_e_o_valor(nivel_3));
}

7.22 Sntese do Mdulo


apresentado seguir, uma sntese do que foi tratado em cada item deste mdulo.
Com esta sntese voc poder relembrar conceitos vistos durante nosso estudo ou mesmo
direcionar seu estudo, caso voc j tenha conhecimentos na Linguagem C.
81 7.1 Ponteiros como Endereos: visto que um ponteiro uma varivel ou
um valor que contem um endereo.
82 7.2 Determinando o Endereo de uma Varivel: foi visto como obter um
endereo de uma varivel e quando os programas precisarem determinar o endereo de
uma varivel, devero usar o operador de endereo da Linguagem C &.
83 7.3 Como a Linguagem C trata Matrizes como Ponteiros: mostrado o
cdigo de um programa que exibe o endereo inicial de vrias matrizes diferentes.

84 7.4 Aplicando o Operador de Endereo (&) a uma Matriz: foi visto que se
o operador de endereo for aplicado a uma matriz, a Linguagem C retornar o endereo
inicial da matriz.
85 7.5 Declarando Variveis Ponteiros: foi visto que para declarar um ponteiro,
precisa-se especificar o tipo do valor ao qual o ponteiro aponta (tal como int, float, char,
etc.) e um asterisco (*) antes do nome da varivel.
86 7.6 Desreferenciando um Ponteiro: foi explicado que desreferenciar um
ponteiro o processo de acessar o valor de uma posio de memria especfica. Para
desreferenciar o valor de um ponteiro, usa-se o operador asterisco de indireo (*).
87 7.7 Usando Valores de Ponteiro: foi apresentado o cdigo de um programa
em que o valor de um ponteiro usado para receber o endereo de uma varivel de depois o
ponteiro usado para indicar o valor armazenado na posio de memria que ele indica.
88 7.8 Ponteiros com Parmetros de Funo: foi visto que quando for
necessrio alterar o valor de um parmetro, dever passar para a funo um ponteiro para
um parmetro. Foi apresentado um programa que usa os ponteiros para dois parmetros do
tipo int para permutar os valores das variveis.
89 7.9 A Aritmtica de Ponteiros: foi explicada de manira clara a aritmtica de
ponteiros, que trata os ponteiros como valores que podem ser somados ou subtrados.
90 7.10 Incrementando e Decrementando um Ponteiro: foram vistas as
operaes de incremento e o decremento do valor de um ponteiro, que servem para apontar
para a prxima posio ou para a posio anterior na memria.
91 7.11 Percorrendo uma String usando um Ponteiro: foi visto um programa
que usa uma funo para exibir uma string de caracteres usando um ponteiro.
92 7.12 Funes que retornam Ponteiros: foi explicado que o valor que uma
funo retorna sempre do tipo declarado no prottipo ou cabealho da funo. Alm de
retornar esses tipos bsicos, as funes podem declarar ponteiros para os valores.
93 7.13 Criando uma Funo que retorna um Ponteiro: foi visto um
programa que cria uma funo que converte todos os caracteres de uma string para
maisculas e depois retorna um ponteiro para uma string.
94 7.14 Uma Matriz de Ponteiros: foi explicado que assim como pode-se criar
funes que retornam ponteiros, tambm pode-se criar matrizes de ponteiros. Mais
comumente sero usadas matrizes para conter strings de caracteres.
95 7.15 Percorrendo em um Lao uma Matriz de Strings de Caracteres: foi
visto um programa que percorre em um lao uma matriz , que contm ponteiros para strings
que contm os nomes dos dias da semana.
96 7.16 Usando um Ponteiro para um Ponteiro para String de Caracteres:
foi visto um programa que usa um ponteiro para um ponteiro para string de caracteres para
exibir o contedo de uma matriz.
97 7.17 Declarando uma Constante String usando um Ponteiro: foi visto
como declarar uma constante string usando um ponteiro.

98 7.18 O Ponteiro do tipo Void: foi dada uma explicao geral sobre o
ponteiro do tipo void.

99 7.19 Ponteiros para as Funes: foi visto que a Linguagem C permite que os

programas criem e usem ponteiros para as funes.

1007.20 Ponteiro para uma Funo: foi visto que o uso mais comum de um
ponteiro para uma funo passar essa funo como um parmetro para outra funo.
1017.21 Usando um Ponteiro para um Ponteiro para um Ponteiro: foi visto
que a Linguagem C permite criar variveis que so ponteiros para outros ponteiros. Em
geral, no h limite no nmero de indirees (ponteiros para ponteiros) que os programas
podem usar.

Mdulo 8 - Sistema de Arquivos


8.1 Introduo
Na Linguagem C, um arquivo um conceito lgico que pode ser aplicado a tudo,
desde arquivos em disco at terminais. Um fluxo associado a um arquivo especfico pela
realizao de uma operao de abertura. Uma vez que um arquivo esteja aberto,
informaes podem ser intercambiadas entre o arquivo e o seu programa.
Nem todos os arquivos tm as mesmas capacidades. Por exemplo, um arquivo em
disco pode suportar acesso randmico enquanto um acionador de fita no pode. Isso ilustra
um ponto importante sobre o sistema de E/S da linguagem C: todos os fluxos so os
mesmos, mas nem todos os arquivos os so.
Se pode suportar acesso randmico, ento uma abertura de um arquivo tambm
inicializa um indicador de posio do arquivo no comeo do arquivo. medida que cada
caractere lido ou escrito para o arquivo, o indicador de posio incrementado,
assegurando, assim, a progresso atravs do arquivo.
Um arquivo desassociado de um fluxo especfico por meio de uma operao de
fechamento. Em fluxos abertos para sada, o fechamento do fluxo faz com que o contedo,
se houver, da rea intermediria (buffer) seja descarregado para o dispositivo externo. Esse
processo geralmente referenciado como uma limpeza/descarga de apontador e garante
que nenhuma informao ser acidentalmente esquecida na rea intermediria do disco.
Todos os arquivos so fechados automaticamente quando o programa termina
normalmente.

8.2 O Ponteiro de Arquivo


A linha comum que une o sistema de E/S de disco aos programas escritos em C o
ponteiro de arquivo. Um ponteiro de arquivo um ponteiro para uma rea na memria
(buffer) onde esto contidos vrios dados sobre o arquivo a ler ou escrever, tais como o
nome do arquivo, estado e posio corrente. O buffer apontado pelo ponteiro de arquivo a
rea intermediria entre o arquivo no disco e o programa.

Este buffer intermedirio entre arquivo e programa chamado fluxo, e no jargo


dos programadores comum falar em funes que operam fluxos em vez de arquivos. Isto
se deve ao fato de que um fluxo uma entidade lgica genrica, que pode estar associada a
uma unidade de fita magntica, um disco, uma porta serial, etc. Adotaremos esta
nomenclatura aqui.
Um ponteiro de arquivo uma varivel ponteiro do tipo FILE que definida em
stdio.h. Para ler ou escrever em um arquivo de disco, o programa deve declarar uma (ou
mais de uma se formos trabalhar com mais de um arquivo simultaneamente) varivel
ponteiro de arquivo. Para obter uma varivel ponteiro de arquivo, usa-se uma declarao
semelhante a esta:
FILE *fp;

onde fp o nome que escolhemos para a varivel (podia ser qualquer outro).

8.3 Abrindo um Arquivo Usando FOPEN


Muitos programas em Linguagem C armazenam e lem informaes de um arquivo.
Antes que os programas possam ler ou gravar informaes em um arquivo, ser preciso
abrir o arquivo. A funo fopen permite que seus programas abram um arquivo. O formato
de fopen como segue:
#include <stdio.h>
FILE *fopen(const char *nomearq, const char *modo);

O parmetro nomearq uma string de caracteres que contm o nome do arquivo


desejado, tal como "c:\arqdados.dat". O parmetro modo especifica como quer-se usar o
arquivo - para ler, gravar ou anexar. A tabela abaixo descreve os valores de modo que
fopen suporta:
Modo
"r"
"w"
"a"
"rb"
"wb"
"ab"
"r+"
"w+"
"a+"
"r+b"
"w+b"
"a+b"
"rt"
"wt"
"at"
"r+t"
"w+t"

Abre um arquivo para leitura

Significado

Cria um arquivo para escrita


Acrescenta dados para um arquivo existente
Abre um arquivo binrio para leitura
Cria um arquivo binrio para escrita
Acrescenta dados a um arquivo binrio existente
Abre um arquivo para leitura/escrita
Cria um arquivo para leitura/escrita
Acrescenta dados ou cria um arquivo para leitura/escrita
Abre um arquivo binrio para leitura/escrita
Cria um arquivo binrio para leitura/escrita
Acrescenta ou cria um arquivo binrio para leitura/escrita
Abre um arquivo texto para leitura
Cria um arquivo texto para escrita
Acrescenta dados a um arquivo texto
Abre um arquivo-texto para leitura/escrita
Cria um arquivo texto para leitura/escrita

"a+t"

Acrescenta dados ou cria um arquivo texto para leitura/escrita

A funo fopen retorna um ponteiro (chamado ponteiro de arquivo) para uma


estrutura do tipo FILE que o arquivo de cabealho stdio.h define. Seus programas usaro o
ponteiro de arquivo para suas operaes de entrada e sada. Se a funo fopen no puder
abrir o arquivo especificado, ela retornar o valor NULL. Seus programas sempre devem
testar o valor de retorno de fopen para garantir que abriu o arquivo com sucesso, como
mostrado aqui:
if ((pa = fopen("NOMEARQ.EXT", "r")) != NULL)
{
/*Arquivo aberto com sucesso*/
}
else
{
/*Erro ao abrir o arquivo*/
}

Dentro do programa, preciso declarar a varivel ponteiro de arquivo como segue:


void main()
{
FILE *pa /*Ponteiro para uma estrutura do tipo FILE*/

Muitos programas abrem um arquivo para entrada e outro para sada. Em tais casos,
voc poderia declarar dois ponteiros de arquivo, como mostrado aqui:
FILE *entrada, *saida;

8.4 A Estrutura FILE


Como voc aprendeu, quando os programas efetuam operaes de entrada e sada,
elas normalmente declaram ponteiros de arquivos usando a estrutura FILE, como visto no
final do item 3.3.
Se voc examinar o arquivo de cabealho stdio.h, encontrar a definio da
estrutura FILE. Esta definio foi tomada do Turbo C++ Lite:
typedef struct
{
short level;
/*Nivel do buffer cheio/vazio*/
unsigned flags;
/* Sinalizadores de status*/
char fd;
/* Descritor de arquivo*/
unsigned char hold;
/*Caracter ungetc se no existir um buffer*/
short bsize;
/*Tamanho do buffer*/
unsigned char *buffer; /*Buffer de transferncia*/
unsigned char *curp;
/*Ponteiro ativo atual*/
unsigned stemp;
/*Indicador de arquivo temporrio*/
short token;
/*Usado para verificao de validade*/
} FILE
/*Esse o objeto FILE */

A estrutura FILE contm o descritor de arquivo de baixo nvel que o sistema


operacional usa para acessar o arquivo, o tamanho do buffer do arquivo e a localizao, o
buffer de caracteres que unget usa, um sinalizador que indica se o arquivo um arquivo
temporrio, e outras variveis sinalizadoras. Alm disso, a estrutura FILE armazena o
ponteiro de arquivo que controla sua localizao atual dentro do arquivo.

Se estiver trabalhando no ambiente do DOS, a maioria dos compiladores definir


uma matriz de tamanho fixo (normalmente 20) dos ponteiros de arquivo que contm as
informaes para cada arquivo que seu programa abrir. Se o programa precisa abrir mais
de 20 arquivos, consulte a documentao do compilador para conhecer os passos que
precisar seguir para modificar o tamanho da matriz de ponteiros de arquivo.

8.5 Fechando um Arquivo Aberto


Fechar um arquivo instrui o sistema operacional a esvaziar todos os buffers de disco
associados com o arquivo e a liberar os recursos do sistema que o arquivo consumiu, tais
como os dados de ponteiros de arquivo. A funo fclose fecha o arquivo associado com o
ponteiro de arquivo especificado, como mostrado aqui:
#include <stdio.h>
int fclose (FILE *pont_arquivo);

Se fclose for bem sucedida, retornar o valor 0. Se ocorrer um erro, fclose retornar
a constante EOF, como mostrado aqui:
if (fclose(pa) == EOF)
printf ("Erro ao fechar o arquivo de dados\n");

medida que for examinando programas em Linguagem C, ser visto que a maioria
deles no testa o valor de retorno de fopen, como mostrado aqui:
fclose(pa);

Na maioria das vezes, se uma operao fechar arquivo apresentar erro, o programa
poder fazer muito pouco para corrigir a situao. No entanto, se estiver trabalhando com
arquivos de dados crticos, dever exibir uma mensagem de erro para o usurio para que ele
possa examinar o contedo do arquivo.
Se no chamar a funo fclose, C fechar os arquivos abertos quando o programa
terminar.

8.6 Lendo e Gravando Informaes no Arquivo um Caracter


de Cada Vez
Quando os programas efetuam operaes de entrada e sada em arquivos, podem ler
e gravar dados um caracter de cada vez ou uma linha de cada vez. Para as operaes de
entrada e sada de caractere, os programas podem usar as funes fgetc e fputc, cujos
formatos so mostrados aqui:
#include <stdio.h>
int fgetc (FILE *pont_entrada);
int fputc (int caractere, FILE *pont_saida);

A funo fgetc l o caracter atual do arquivo de entrada especificado. Se o ponteiro


de arquivo tiver chegado ao final do arquivo, fgetc retornar a constante EOF. A funo
fputc gravar um caractere na posio do ponteiro de arquivo atual dentro do arquivo de
sada especificado. Se um erro ocorrer, fputc retornar a constante EOF. O programa a

seguir, usa fgetc e fputc para copiar o contedo do arquivo do diretrio raiz config.sys para
um arquivo chamado config.tst:
#include <stdio.h>
void main(void)
{
FILE *entrada, *saida;
int letra;
if ((entrada = fopen("\\CONFIG.SYS", "r"))==NULL)
printf("Erro ao abrir \\CONFIG.SYS\n");
else if ((saida = fopen("\\CONFIG.TST", "w"))==NULL)
printf("Erro ao abrir \\CONFIG.TST\n");
else
{
/* L e grava cada caractere no arquivo*/
while ((letra = fgetc(entrada)) != EOF)
fputc(letra, saida);
fclose(entrada);
/* Fecha o arquivo entrada */
fclose(saida);
/* Fecha o arquivo saida */
}
}

8.7 O Ponteiro de Posio do Ponteiro de Arquivo


O item 8.4 apresentou a estrutura FILE. Como foi visto, um dos campos da estrutura
armazena um ponteiro da posio para localizao atual dentro do arquivo. Quando abre-se
um arquivo para operaes de leitura ou gravao, o sistema operacional define o ponteiro
da posio no incio do arquivo. Toda vez que ler ou gravar um caractere, o ponteiro da
posio avanar um caractere. Se ler uma linha de texto do arquivo, o ponteiro da posio
avanar para o incio da prxima linha. Usando o ponteiro da posio, a funes de
entrada e sada de arquivo sempre podem controlar a localizao atual dentro do arquivo.
Quando abre-se um arquivo no modo de anexao, o sistema operacional define o ponteiro
da posio no final do arquivo. A tabela a seguir especifica a localizao na qual fopen
coloca o ponteiro da posio quando abre-se o arquivo nos modos de leitura, gravao e
anexao.
Modo de Abertura

a
r
w

Posio do Ponteiro do Arquivo

Imediatamente aps o ltimo caractere do arquivo


No incio do arquivo
No final do arquivo

8.8 Determinando a Posio Atual no Arquivo


No item anterior foi visto como a Linguagem C controla a posio atual em
arquivos abertos para as operaes de entrada e sada. Dependendo do programa, algumas
vezes ser necessrio determinar o valor do ponteiro de posio.
Em tais casos usa-se a funo ftell, como segue:
#include <stdio.h>
long int ftell (FILE *pont_arquivo);

A funo ftell retorna um valor inteiro longo que especifica o byte de deslocamento
partir da posio atual no arquivo especificado. O programa a seguir usa ftell para exibir
informaes do ponteiro de posio. O programa comea abrindo o arquivo do diretrio
raiz config.sys no modo de leitura. O programa ento usa ftell para exibir a posio atual.
Em seguida, o programa l e exibe o contedo do arquivo. A ps encontrar o final do
arquivo, o programa novamente usar ftell para exibir a posio atual, como segue:
#include <stdio.h>
void main(void)
{
FILE *entrada;
int letra;
if ((entrada = fopen("\\CONFIG.SYS", "r")) == NULL)
printf("Erro ao abrir \\CONFIG.SYS\n");
else
{
printf("A posio atual o byte %d\n\n",
ftell(entrada));
/* L e grava cada caractere no arquivo*/
while ((letra = fgetc(entrada)) != EOF)
fputc(letra, stdout);
printf("\nA posio atual o byte %d\n",
ftell(entrada));
fclose(entrada);
/* Fecha o arquivo entrada */
}
}

8.9 - O Significado de Canais de Arquivo


Muitos livros e revistas referem-se aos ponteiros de arquivos da Linguagem C como
ponteiros stream (ou de canais) de arquivos. Ao contrrio de outras linguagens de
programao, a Linguagem C no assume que os arquivos contm informaes em um
formato especfico. Em vez disso, a Linguagem C considera todos os arquivos como nada
mais que uma coleo de bytes. medida que se l um arquivo, l um byte aps o outro,
em outras palavras, uma seqncia de bytes. Seus programas e funes precisam interpretar
os bytes. Por exemplo, a funo fgets considera o caractere de alimentao de linha como o
final de uma linha e o incio de outra.
Logo, quando se escrevem funes ou programas que manipulem arquivos, pensa-se
nos arquivos como uma coleo de bytes.

8.10 Lendo Linhas de Textos


Quando os programas lem arquivos de texto, normalmente fazem isso uma linha de
cada vez. Para ler uma linha de um arquivo, os programas podem usar a funo fgets, cujo
formato mostrado a seguir:
#include <stdio.h>
char *fgets(char string, int limite, FILE *canal);

O parmetro string o buffer de caracteres no qual fgets l os dados do arquivo.


Normalmente os programas iro declarar uma matriz de 128 ou 256 bytes para conter os

dados. O parmetro limite especifica o nmero de caracteres que o buffer pode conter.
Quando fgets l caracteres do arquivo, fgets ler at limite - 1 (limite menos um) ou at o
primeiro caractere de nova linha (\n), o que vier primeiro. A funo ento colocar um
caractere NULL no buffer para indicar o final da string.
Muitos programas usam a funo sizeof para especificar o tamanho do buffer, tal
como sizeof(string). Finalmente o parmetro canal especifica o arquivo a partir do qual
fgets precisa ler a string. Precisa-se ter aberto previamente o canal usando fopen. Se fgets
ler informaes com sucesso do arquivo, fgets retornar um ponteiro para a string. Se
ocorrer um erro ou se chegar ao final do arquivo, fgets retornar NULL.

8.11 Gravando Linhas de Texto


No item anterior, vimos que os arquivos lero uma linha de cada vez de um arquivo.
Ao gravar em um arquivo, seus programas gravaro uma linha de cada vez. Para gravar
uma string em um arquivo, seus programas podem usar a funo fputs, como segue:
#include <stdio.h>
int fputs(const char *string, FILE *canal);

A funo fputs grava os caracteres em uma string especificada at o caractere


NULL de finalizao. Se fputs grava a string com sucesso, ela retornar um valor positivo
para a funo chamadora. Se ocorrer um erro, fputs retornar uma constante EOF.

8.12 Exemplo do Uso das Funes Fgets e Fputs


Nos dois itens anteriores foi mostrada a sintaxe das funes fgets e fputs,
respectivamente. Agora ser visto como us-las atravs do programa abaixo que usa as
funes fgets e fputs para copiar o contedo do primeiro arquivo especificado na linha de
comando para o segundo arquivo:

#include <stdio.h>
void main(int argc, char **argv)
{
FILE *entrada, *saida;
char string[256];
if ((entrada = fopen(argv[1], "r")) == NULL)
printf("Erro ao abrir %s\n", argv[1]);
else if ((saida=fopen(argv[2], "w")) == NULL)
{
printf("Erro ao abrir %s\n", argv[2]);
fclose(entrada);
}
else
{
while (fgets(string, sizeof(string), entrada))
fputs(string, saida);

fclose(entrada);
fclose(saida);
}
}

8.13 As Funes Fread( ) E Fwrite( ):


so:

Esta funes permitem a leitura e a escrita de blocos de dados. Os seus prottipos

unsigned fread(void *buffer, int num_bytes, int count, FILE *fp);


unsigned fwrite(void *buffer, int num_bytes, int count, FILE *fp);

No caso da funo fread( ), buffer um ponteiro para uma regio de memria que
receber os dados lidos do arquivo.
No caso de fwrite( ), buffer um ponteiro para uma regio de memria onde se
encontram os dados a serem escritos no arquivo. O buffer usualmente um ponteiro para
uma matriz ou uma estrutura.
O nmero de bytes a ser lido ou escrito especificado por num_bytes.O argumento
count determina quantos itens (cada um tendo num_bytes de tamanho) sero lidos ou
escritos. Finalmente, fp um ponteiro para um arquivo de um fluxo previamente aberto por
fopen( ).
A funo fread( ) retorna o nmero de itens lidos, que pode ser menor que count
caso o final de arquivo seja encontrado ou ocorra um erro.
A funo fwrite( ) retorna o nmero de itens escritos, que ser igual a count a
menos que ocorra um erro.
Quando o arquivo for aberto para dados binrios, fread( ) e fwrite( ) podem ler e
escrever qualquer tipo de informao. O programa a seguir escreve um float em um arquivo
de disco chamado teste.dat.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
void main()
{
FILE *fp;
float f = 3.141592654;
if ((fp = fopen(teste.dat, wb)) == NULL)
{
puts (No posso abrir arquivo!);
exit(1);
}
if (fwrite(&f, sizeof(float), 1, fp)!=1)
{
puts(Erro escrevendo no arquivo!);
}
fclose(fp);
}

Como o programa anterior ilustra, a rea intermediria de armazenamento pode ser,


e freqentemente , simplesmente uma varivel.

Uma das aplicaes mais teis de fread( ) e fwrite( ) envolve leitura e escrita em
matrizes e estruturas. Por exemplo, este fragmento de programa escreve o contedo da
matriz em ponto flutuante exemplo no arquivo exemplo.dat usando uma simples
declarao fwrite( ).
#include <stdio.h>
#include <stdlib.h>
void main()
{
FILE *fp;
float exemplo[10][10];
int i, j;
if ((fp = fopen(exemplo.dat, wb)) == NULL)
{
puts(No posso abrir arquivo!);
exit(1);
}
for (i = 0; i < 10; i++)
{
for (j = 0; j < 10; j++)
{
exemplo[i][j] = (float) i+j;
}
}
/*O cdigo a seguir grava a matriz inteira num nico passo*/
if (fwrite(exemplo, sizeof(exemplo), 1, fp) != 1)
{
puts(Erro ao escrever arquivo!);
exit(1);
}
fclose(fp);
}

Note como sizeof usado para determinar o tamanho da matriz exemplo. O prximo
exemplo usa a funo fread( ) para ler a informao escrita pelo programa anterior. Ele
exibe os nmeros na tela para verificao.
#include <stdio.h>
#include <stdlib.h>
void main()
{
FILE *fp;
float exemplo[10][10];
int i,j;
if ((fp = fopen(exemplo.dat, rb)) == NULL)
{
puts(No posso abrir arquivo!);
exit(1);
}
/*O cdigo a seguir l a matriz inteira num nico passo*/
if (fread(exemplo, sizeof(exemplo), 1, fp) != 1)
{
puts(Erro ao ler arquivo!);
exit(1);
}
for (i = 0; i < 10; i++)
{

for (j = 0; j < 10; j++)


{
printf (%3.1f , exemplo[i][j]);
printf(\n);
}
}
fclose(fp);
}

8.14 As Funes Fprintf( ) e Fscanf( )


Estas funes comportam-se como printf( ) e scanf( ) s que escrevem e lem de
arquivos em disco. Todos os cdigos de formato e modificadores so os mesmos. Os
prottipos destas funes so:
int fprintf(FILE *fp, char *string_controle, lista_de_argumentos);
int fscanf(FILE *fp, char *string_controle, lista_de_argumentos);

Embora fprintf( ) e fscanf( ) sejam a maneira mais fcil de ler e escrever tipos de
dados nos mais diversos formatos, elas no so as mais eficientes em termos de tamanho de
cdigo resultante e velocidade. Assim, se a velocidade e tamanho so uma preocupao,
deve-se dar preferncia as funes fread( ) e fwrite( ).
Para ilustrar o quo til essas funes podem ser, o seguinte programa mantm uma
lista de telefones em um arquivo em disco. Pode-se inserir nomes e nmeros ou verificar
um nmero dado um nome.
#include
#include
#include
#include
#include

<stdio.h>
<string.h>
<stdlib.h>
<ctype.h>
biblioteca.c /*biblioteca com funes de tela*/

void add_num (void); /*prottipos de funes*/


void consulta(void);
int menu(void);
void main()
{
char opcao;
do
{
opcao = menu();
switch (opcao)
{
case A: add_num();
break;
case C: consulta();
break;
}
}while (opcao != T)
}
int menu(void)
{
char ch;

do
{
printf ((A)diciona, (C)onsulta, (T)ermina: );
ch = toupper(getche());
printf(\n);
}while (ch != T && ch != A && ch != C);
return(ch);
}
void add_num(void)
{
FILE *fp;
char nome[80];
int prefixo, num;
if (fp = fopen(fones.db, a)) == NULL)
{
printf (O arquivo da lista no pode ser aberto!\n);
exit(1);
}
printf (Informe o nome e o nmero: );
fscanf (stdin, %s%d%d, nome, &prefixo, &num);
fscanf (stdin, %*c); //remove o CR do buffer do teclado
fprintf (fp, %s %d %d, nome, prefixo, num);
fclose (fp);
}
void consulta(void)
{
FILE *fp;
char nome[80], nome2[80];
int prefixo, num;
if (fp = fopen(fones.db, r)) == NULL)
{
printf (O arquivo da lista no pode ser aberto!\n);
exit(1);
}
printf (Nome? );
gets (nome);
/*consulta um nmero*/
while (!feof(fp))
{
fscanf (fp, %s%d%d, nome2, &prefixo, &num);
if (!strcmp(nome, nome2))
{
printf (%s: %d-%d\n, nome, prefixo, num);
break;
}
}
fclose(fp);
}

8.15 - Testando o Final do Arquivo


Como foi visto, quando a funo fgets encontra o final de um arquivo, ela retorna
NULL. Da mesma forma, quando fgetc atinge o final de um arquivo, ela retorna EOF.
Algumas vezes os programas precisam determinar se o ponteiro de um arquivo est no final

do arquivo antes de efetuar uma operao especfica. Nesses casos, os programas podem
chamar a funo feof, como segue:
#include <stdio.h>
int feof(FILE *canal);

Se o ponteiro de arquivo especificado estiver no final do arquivo, feof retornar um


valor diferente de zero (verdadeiro). Se ainda no tiver atingido o final de arquivo, feof
retornar 0 (falso). O lao a seguir l e exibe os caracteres do arquivo que correspondem ao
ponteiro do arquivo entrada:
while (! feof(entrada))
fputc (fgetc(entrada), stdout);

8.16 Posicionamento do Ponteiro de Arquivo com Base em sua


Posio Atual
Foi visto que o ponteiro de arquivo contm um ponteiro de posio para controlar
sua posio atual dentro do arquivo. Quando se conhece o formato do arquivo, algumas
vezes quer avanar o ponteiro de posio para um local especfico antes de comear a ler o
arquivo. Por exemplo, os primeiros 256 bytes podem conter informaes de cabealho que
voc no quer ler. Nesses casos, os programas podem usar a funo fseek para posicionar o
ponteiro de arquivo, como segue:
#include <stdio.h>
int fseek (FILE *canal, long desloc, int relativo_a);

O parmetro canal especifica o ponteiro de arquivo que se quer posicionar. Os


parmetros desloc e relativo_a combinam para especificar a posio desejada. O desloc
contm o byte de deslocamento no arquivo. O parmetro relativo_a especifica a posio no
arquivo a partir do qual fseek deve aplicar o deslocamento. A tabela abaixo especifica os
valores que se pode usar para o parmetro relativo_a:
Constante
SEEK_CUR
SEEK_SET
SEEK_END

Significado
Da posio atual no arquivo
Do incio do arquivo
Do final do arquivo

Para posicionar o ponteiro de arquivo imediatamente aps os primeiros 256 bytes de


informaes de cabealho em um arquivo, poderia usar fseek, como segue:
fseek(pa, 256, SEEK_SET); /*o deslocamento 0 o incio*/

Se tiver sucesso, fseek retornar o valor 0. Se ocorrer um erro, a funo retornar


um valor diferente de zero.

8.17 Excluindo um Arquivo


Quando os programas trabalham com arquivos, algumas vezes precisa-se excluir um
ou mais arquivos. Em tais casos, os programas podem usar a funo remove, que tem o
seguinte formato:

#include <stdio.h>
int remove (const char *nomearq);

Se a funo remover o arquivo com sucesso, ela retornar o valor 0. Se um erro


ocorrer, remove retornar o valor -1, e atribuir varivel global erro um dos valores
listados na tabela abaixo:
Valor

EACES
ENOENT

Significado

Acesso negado
Arquivo no encontrado

O programa a seguir, usa a funo remove para apagar todos os arquivos


especificados na linha de comando:
#include <stdio.h>
void main(int argc, char *argv[])
{
while (*++argv)
if (remove(*argv))
printf("Erro ao remover %s\n", *argv);
}

Alm da funo remove, a maioria dos compiladores C suporta a funo unlink, que
tambm exclui um arquivo:
#include <stdio.h>
int unlink(const char *nomearq);

Se unlink excluir com sucesso um arquivo, ela retornar um valor 0. Se ocorrer um


erro, a funo retornar o status de erro -1, atribuindo varivel global erro as constantes
de status de erro j listadas na tabela anterior. O programa a seguir usa a funo unlink para
excluir os arquivos especificados na linha de comandos do programa:
#include <stdio.h>
void main(int argc, char *argv[])
{
while (*++argv)
if (unlink(*argv))
printf("Erro ao remover %s\n", *argv);
}

8.18 Sntese do Mdulo


apresentado seguir, uma sntese do que foi tratado em cada item deste mdulo.
Com esta sntese voc poder relembrar conceitos vistos durante nosso estudo ou mesmo
direcionar seu estudo, caso voc j tenha conhecimentos na Linguagem C.
1028.1 Introduo: neste item mostrado que na linguagem C, um arquivo
um conceito lgico que pode ser aplicado a tudo, desde arquivos em disco at terminais.
Um fluxo associado a um arquivo especfico pela realizao de uma operao de abertura.
Uma vez que um arquivo esteja aberto, informaes podem ser intercambiadas entre o
arquivo e o seu programa.

1038.2 O Ponteiro de Arquivo: foi visto que um ponteiro de arquivo um


ponteiro para uma rea na memria (buffer) onde esto contidos vrios dados sobre o
arquivo a ler ou escrever, tais como o nome do arquivo, estado e posio corrente. O buffer
apontado pelo ponteiro de arquivo a rea intermediria entre o arquivo no disco e o
programa.
1048.3 Abrindo um Arquivo Usando FOPEN: foi visto que a funo fopen
utilizada para abrir um arquivo. Alm disso foi vista a estrutura de fopen e que a funo
fopen retorna um ponteiro (chamado ponteiro de arquivo) para uma estrutura do tipo FILE
que o arquivo de cabealho stdio.h define.
1058.4 A Estrutura FILE: neste item mostrado o contedo da definio da
estrutura FILE.
1068.5 Fechando um Arquivo Aberto: fechar um arquivo instrui o sistema
operacional a esvaziar todos os buffers de disco associados com o arquivo e a liberar os
recursos do sistema que o arquivo consumiu, tais como os dados de ponteiros de arquivo. A
funo fclose faz exatamente o processo descrito anteriormente.
1078.6 Lendo e Gravando Informaes no Arquivo um Caracter de Cada
Vez: foi visto que usando as funes fgetc e fputc, pode-se ler e gravar dados um caracter
de cada vez ou uma linha de cada vez.
1088.7 O Ponteiro de Posio do Ponteiro de Arquivo: foi visto que o
ponteiro de posio utilizado para controlar a posio atual dentro de um arquivo e
atravs dele que as funes se localizam dentro de um arquivo.
1098.8 Determinando a Posio Atual no Arquivo: usa-se a funo ftell
determinar o valor do ponteiro de posio e assim determina-se a posio atual do arquivo.
1108.9 O Significado de Canais de Arquivo: explica o significado de canais de
arquivo.
1118.10 Lendo Linhas de Textos: foi visto os programas podem usar a funo
fgets para ler uma linha de um arquivo.
1128.11 Gravando Linhas de Texto: foi visto que para gravar uma linha em
um arquivo necessrio utilizar a funo fputs.
1138.12 Exemplo do Uso das Funes Fgets e Fputs: foi visto como usar as
funes fgets e fputs para copiar o contedo do primeiro arquivo especificado na linha de
comando para o segundo arquivo.
1148.13 As Funes Fread( ) E Fwrite( ): funes que permitem a leitura e a
escrita de blocos de dados. Neste item foi apresentada a sintaxe e a funo de cada
parmetro.
1158.14 As Funes Fprintf( ) e Fscanf( ): foi apresentado que estas funes
comportam-se como printf( ) e scanf( ) s que escrevem e lem de arquivos em disco.
Embora sejam a maneira mais fcil de ler e escrever tipos de dados nos mais diversos
formatos, foi visto que elas no so as mais eficientes em termos de tamanho de cdigo
resultante e velocidade.
1168.15 Testando o Final do Arquivo: algumas vezes os programas precisam
determinar se o ponteiro de um arquivo est no final do arquivo antes de efetuar uma
operao especfica. Nesses casos, os programas podem chamar a funo feof. Se o
ponteiro de arquivo especificado estiver no final do arquivo, feof retornar um valor
diferente de zero (verdadeiro). Se ainda no tiver atingido o final de arquivo, feof retornar
0 (falso).

1178.16 Posicionamento do Ponteiro de Arquivo com Base em sua Posio


Atual: quando se conhece o formato do arquivo, algumas vezes quer avanar o ponteiro de
posio para um local especfico antes de comear a ler o arquivo. Nesses casos, os
programas podem usar a funo fseek para posicionar o ponteiro de arquivo.
1188.17 Excluindo um Arquivo: Quando os programas trabalham com
arquivos, algumas vezes precisa-se excluir um ou mais arquivos. Em tais casos, os
programas podem usar a funo remove.

Mdulo 9 Funes Grficas na Linguagem C


9.1 A Tela Grfica

No modo grfico, a tela do monitor de vdeo dividida numa fina malha de pontos
individuais, chamados de elementos de imagem, ou pixel. Qualquer pixel pode ser apagado
ou iluminado, o que vem a ser o princpio bsico para a criao de imagens grficas. A
resoluo da tela descrita em termos do nmero de pixeis por linha ou por coluna. Uma
tela VGA (Adaptador Grfico Colorido) tem 640 linhas por 480 colunas, como est
mostrado na Figura (a). importante notar que o sistema de numerao inicia no canto
superior esquerdo da tela no ponto (x,y) = (0,0).
(0,479
)

EIXO X

EIXO Y

(0,0)

(639,0)

(639,479)

(a)

(b)

(a) Eixos de coordenadas no modo VGA


(b) Eixos de coordenada no modo carteziano
Segundo as figuras (a) e (b) acima, vemos que o eixo y na tela do PC est invertido
em relao ao eixo yc do plano cartesiano. Por isto, para mostrar na tela do PC no grfico
como se fosse no plano cartesiano deve-se fazer a seguinte equivalncia:
yv = ymax/2 - yc

onde: yv = eixo y da tela de vdeo


yc = eixo y do plano cartesiano
ymax = n. total de linhas do vdeo
abaixo:

Ento a tela do vdeo ter o sistema de eixos conforme dado na figura

(0,320)

yc

(479,0)
(0,0)

xc

(0,-319)

(c)Eixos cartesianos no monitor CGA

9.2

Detectando

o Adaptador Grfico

Provavelmente em seu programa seja necessrio detectar qual o adaptar grfico est
em uso. Para isso usamos a funo detectgraph. Esta funo detecta qual adaptador (CGA,
VGA, EGA, Hercules etc.) est conectado e informa o modo de resoluo mais alto do
driver daquele adaptador. A sintaxe da funo :
detectgraph(&gdriver,&gmode);

Os valores que os parmetros gdriver e gmode podero assumir so:


Gdriver
1 - CGA

3 - EGA

Placa Grfica
CGAC0 CGAC1 CGAC2
CGAC3 CGAHI
MCGAC0 MCGAC1
MCGAC2 MCGAC3
MCGAMED MCGAHI
EGALO EGAHI

01

4 - EGA64

EGA64LO EGA64HI

01

5 - EGA-MONO
6 - IBM8514

EGAMONOHI
IBM8514HI IBM8514LO

3
01

7 - HERCULES
8 - ATT400

HERCMONOHI
ATT400C0 ATT400C1
ATT400C2 ATT400C3
ATT400MED ATT400HI
VGALO VGAMED
VGAHI
PC3270HI

0
012345

2 - MCGA

9 - VGA
10 - PC3270

Gmode
01234
012345

012
0

N LinhasxColunas
320x200 320x200 320x200 320x200
640x200 - 2 color
320x200 320x200 320x200 320x200
640x200 - 2 color 640x480 - 2 color
640x200 - 16 colors 640x350 - 16
colors
640x200 - 16 colors 640x350 - 4
colors
640x350 - 2 colors
640x480 - 256 colors 1024x768 256 colors
720X348 - 2 color
320x200 320x200 320x200 320x200
640x200 - 2 colors 640x400 - 2
colors
640x200 - 16 colors 640x350 - 16
colors 640x480 - 16 colors
720x350 - 2 colors

A seguir temos um exemplo de um programa que detecta o adaptador imformando o


mesmo:

#include <stdio.h>
#include <graphics.h>
main()
{
int adaptador_grafico,i,j;
int modo_grafico;
clrscr();
detectgraph(&adaptador_grafico,&modo_grafico);
printf("\n O adaptador detectado %d ",adaptador_grafico);
printf("\n O modo de alta resolucao %d",modo_grafico);
getch();
}

No programa anterior, por exemplo, se o monitor de vdeo for CGA aparecer:


O adaptador detectado 9
O modo de alta resolucao 2

Indicando que o adaptador 9 (VGA) e as dimenses da tela so as do modo 2 (640


linhas x 480 colunas).

9.3 Inicializando a Parte Grfica


Quando os programas que voc escrever usarem os recursos grficos da Linguagem
C, voc ter de preparar o sistema para isto. A funo initgraph() inicializa o sistema para a
placa e o modo grfico detectados pela funo detectgraph(), tirando a tela do modo texto e
colocando-a no modo grfico. A funo closegraph() cancela o modo grfico estabelecido
por initgraph() liberando a memria utilizada para grficos. A seguir um exemplo que
ilustra a sintaxe e o uso destas duas funes initgraph() e closegraph():
#include <stdio.h>
#include <graphics.h>
main()
{
int adaptador_grafico;
int modo_grafico;
detectgraph(&adaptador_grafico,&modo_grafico);
initgraph(&adaptador_grafico,&modo_grafico,"c:\\tc");
getch();
closegraph();
}

O programa anterior detecta a resoluo grfica da tela, inicia a tela no modo


grfico e depois sai do modo grfico.

9.4 Obtendo as Dimenses da Tela


Trabalhando com funes grficas, seus programas precisaro conhecer as
dimenses da tela grfica, visto que sem estas informaes as manipulaes grficas
incorrero em erros. As funes getmaxx() e getmaxy() retornam com valores inteiros os
valores mximos das coordenadas x e y da tela. Com estas funes determinam-se as
dimenses mximas da tela, com isto, o programa est habilitado a utilizar toda tela sendo

ela CGA, VGA, EGA, etc. A seguir, o programa ilustra o uso destas duas funes grficas:

#include <stdio.h>
#include <graphics.h>
main()
{
int adapt, mod, xmax, ymax;
detectgraph(&adapt,&mod);
initgraph(&adapt,&mod,"c:\\tc");
xmax=getmaxx();
ymax=getmaxy();
outtextxy(100,100,Estamos no modo grfico!
tecla.);
getch();
closegraph();
printf("\n O eixo x da tela vai de 0 a %d", xmax);
printf("\n O eixo y da tela vai de 0 a %d", ymax);
getch();
}

Aperte

uma

Este programa informa quais so as dimenses mximas x e y da tela grfica. Se a


tela em questo for VGA o resultado ser:
O eixo x da tela vai de 0 a 639
O eixo y da tela vai de 0 a 479

9.5 Desenhando uma Reta na Tela


Muitas so as aplicaes grficas em que necessrio desenhar-se uma reta na tela,
para separar textos ou para outras funes especficas. Para este propsito, a Linguagem C
tem a funo line() que tem a seguinte sintaxe:
line(xi,yi,xf,yf);

Os parmetros entre parnteses indica para o seu programa que ele desenhe uma
linha ligando o ponto xi,yi ao ponto xf,yf.
A seguir, o uso da funo line(), com um programa exemplo:
#include <graphics.h>
main()
{
int adapt, mod ;
detectgraph(&adapt,&mod);
initgraph(&adapt,&mod,"c:\\tc");
line(0, 0, getmaxx(), getmaxy());
getch();
closegraph();
}

9.6 Desenhando um Retngulo na Tela


Muitas so as aplicaes grficas em que necessrio desenhar-se um retngulo na
tela. Para este propsito, a Linguagem C tem a funo rectangle() que tem a seguinte

sintaxe:
rectangle(xsup, ysup, xinf, yinf);

Os parmetros entre parnteses indica para o seu programa que ele desenhe um
retngulo na tela com o canto superior esquerdo no ponto (xsup, ysup) e o canto inferior
direito no ponto (xinf, yinf).
A seguir, ilustramos o uso da funo rectangle(), com um programa exemplo:
#include <graphics.h>
main()
{
int adapt, mod ;
detectgraph(&adapt,&mod);
initgraph(&adapt,&mod,"c:\\tc");
rectangle(5, 10, 300, 100);
getch();
closegraph();
}

9.7 Desenhando um Ponto na Tela


Muitas so as aplicaes grficas em que necessrio desenhar-se um ponto na tela,
ou seja, ela acende um nico pixel na tela. Para este propsito, a Linguagem C tem a funo
putpixel() que tem a seguinte sintaxe:
putpixel(x, y, cor);

Os parmetros entre parnteses indicam para o seu programa que ele imprima um
pixel (ponto) no ponto (x, y),usando a cor especificada por cor.
A seguir, ilustramos o uso da funo putpixel(), com um programa exemplo:
#include <graphics.h>
main()
{
int adapt, mod ;
detectgraph(&adapt,&mod);
initgraph(&adapt,&mod,"c:\\tc");
putpixel(50,100,15);
outtextxy(55,110," aqui 1" );
putpixel(300,100,15); outtextxy(303, 102," aqui 2");
getch();
closegraph();
}

9.8 Desenhando um Crculo na Tela


Muitas so as aplicaes grficas em que necessrio desenhar-se um crculo na
tela. Para este propsito, a Linguagem C tem a funo circle() que tem a seguinte sintaxe:
circle(xcentro, ycentro, raio);

Os parmetros entre parnteses indicam para o seu programa que ele desenhe um
crculo partir das coordenadas (xcentro, ycentro),de raio raio.

A seguir, ilustramos o uso da funo circle (), com um programa exemplo:


#include <graphics.h>
main()
{
int adapt, mod ;
detectgraph(&adapt,&mod);
initgraph(&adapt,&mod,"c:\\tc");
circle(300,100,50);
getch();
closegraph();
}

O exemplo a seguir um programa que desenha uma reta, um retngulo, um crculo


e dois pontos:
#include <graphics.h>
main()
{
int adapt, mod ;
detectgraph(&adapt,&mod);
initgraph(&adapt,&mod,"c:\\tc");
line(5, 10, 300, 100);
rectangle(5, 10, 300, 100);
putpixel(100, 50, 1);
putpixel(200, 50, 1);
circle(300, 100, 50);
getch();
closegraph();
}

9.9 Desenhando um Arco Circular na Tela


Muitas so as aplicaes grficas em que necessrio desenhar-se um arco crcular
na tela. Para este propsito, a Linguagem C tem a funo arc() que tem a seguinte sintaxe:
arc(xcentro, ycentro, angulo_inicial, angulo_final, raio);

O centro dado pelas coordenadas (xcentro, ycentro) e o raio por raio. Os


parmetros angulo_inicial e angulo_final especificam os ngulos inicial e final em graus,
onde o 0 est na posio horizontal apontando para a direita e 90 na posio vertical
apontando para cima.
A seguir, ilustramos o uso da funo arc (), com um programa exemplo:
#include <graphics.h>
main()
{
int adapt, mod ;
detectgraph(&adapt,&mod);
initgraph(&adapt,&mod,"c:\\tc");
arc(300, 100, 0, 90, 100);
getch();
closegraph();
}

9.10 Limpando a Tela Grfica


Em muitas ocasies, seus programas iro desenhar vrias formas geomtricas e logo
em seguida ser necessrio apag-las. Para este propsito, a Linguagem C tem a funo
cleardevice(), que tem uma sintaxe bastante simples, que ser ilustrada atravs do programa
exemplo abaixo:
#include <graphics.h>
main()
{
int adapt, mod,i ;
detectgraph(&adapt,&mod);
initgraph(&adapt,&mod,"c:\\tc");
for (i=0; i<200;i++)
{
line(i+5,i+10,i+300,i+100);
rectangle(i+5, i+10,i+300,i+ 100);
putpixel(100, 50, 15);
putpixel(200, 50, 15);
circle(300+i, 100+i, 50+i);
delay(1000);
cleardevice();
}
getch();
closegraph();
}

9.11 Mudando as Cores do um Desenho


Em muitos casos ser necessrio alterar a cor das linhas que delimitam os desenhos
que so feitos pelos seus programas. Para este propsito, a Linguagem C tem a funo
setcolor() que tem a seguinte sintaxe:
setcolor(cor);

seguir:

Os valores que se pode atribuir ao parmetro cor para a tela VGA so dados a

COR
PRETO
VERDE
VERMELHO
MARROM
CINZA ESCURO
VERDE CLARO
VERMELHO CLARO
AMARELO

0
2
4
6
8
10
12
14

VALOR

COR
AZUL
CIANO
MAGENTA
CINZA CLARO
AZUL CLARO
CIANO CLARO
MAGENTA CLARO
BRANCO

1
3
5
7
9
11
13
15

VALOR

9.12 Mudando a Cor de Fundo e o Preenchimento do um


Desenho
Em muitos casos ser necessrio alterar a cor de fundo e o padro de preenchimento
dos desenhos que so feitos pelos seus programas. Para este propsito, a Linguagem C tem
a funo setfillstyle() e floodfill() que tem a seguinte sintaxe:

setfillstyle(padrao,cor);
floodfill(x, y, borda);

A funo floodfill(x, y, borda) preenche uma rea na tela grfica ao redor do ponto
dado por (x, y) com a cor e o padro atuais de preenchimento, setados pela instruo
setfillstyle(), at encontrar a cor especificada por borda.
A funo setfillstyle() ajusta o padro e a cor de preenchimento grfico atuais, sendo
que o parmetro padrao assume um dos valores abaixo:
0
2
4
6
8
10

Nmero

Padro
Cor de fundo
Linhas horizontais
Linhas inclinadas grossas ///
linhas inclinadas grossas \\\
cruzes grossas agrupadas
pontos esparsos

1
3
5
7
9
11

Nmero

Padro
Cor slida
Linhas inclinadas finas ///
Linhas inclinadas finas \\\
cruzes finas agrupadas
linhas intercaladas
pontos densos

A seguir, ilustramos o uso das funes setfillstyle() e floodfill() com um programa


exemplo:
#include <graphics.h>
main()
{
int adapt, mod, xm,ym ;
detectgraph(&adapt,&mod);
initgraph(&adapt,&mod,"c:\\tc");
xm = getmaxx()/2;
ym = getmaxy()/2;
setcolor(LIGHTGREEN);
circle(xm,ym,100);
circle(xm,ym,150);
circle(xm,ym,250);
setfillstyle(2,1);
floodfill(xm,ym+10,10);
setfillstyle(7,1);
floodfill(xm,ym+160,10);
setfillstyle(3,1);
floodfill(xm,ym+260,10);
setfillstyle(7,1);
floodfill(xm*2,ym*2,10);
getch();
closegraph();
}

9.13 Sntese do Mdulo


apresentado seguir, uma sntese do que foi tratado em cada item deste mdulo.
Com esta sntese voc poder relembrar conceitos vistos durante nosso estudo ou mesmo
direcionar seu estudo, caso voc j tenha conhecimentos na Linguagem C.
1199.1 A Tela Grfica: dada uma explicao detalhada de como funciona
a tela grfica na Linguagem C.

1209.2 Detectando o Adaptador Grfico: explicita o uso da funo


detectgraph que identifica o adaptador grfico em uso.
1219.3 Inicializando a Parte Grfica: explica em detalhes que a funo
initgraph() inicializa o sistema para a placa e o modo grfico detectados pela funo
detectgraph(), tirando a tela do modo texto e colocando-a no modo grfico.
1229.4 Obtendo as Dimenses da Tela: explica que com as funes
getmaxx() e getmaxy() determinam-se as dimenses mximas da tela, conhecendo-se as
dimenses da tela.
1239.5 Desenhando uma Reta na Tela: fala sobre a funo line() que
desenha uma reta na tela.
1249.6 Desenhando um Retngulo na Tela: fala sobre a funo rectangle()
que desenha um retngulo na tela.
1259.7 Desenhando um Ponto na Tela: fala sobre a funo putpixel() que
desenha um ponto na tela.
1269.8 Desenhando um Crculo na Tela: fala sobre a funo circle() que
desenha um ponto na tela.
1279.9 Desenhando um Arco Circular na Tela: fala sobre a funo arc()
que desenha um arco circular na tela.
limpa a tela.

1289.10 Limpando a Tela Grfica: fala sobre a funo cleardevice() que

1299.11 Mudando as Cores do um Desenho: fala sobre a funo setcolor()


que muda as cores do desenho.
1309.12 Mudando a Cor de Fundo e o Preenchimento do um Desenho:
fala sobre as funes setfillstyle() e floodfill() que muda as cores de fundo e o
preenchimento de um desenho.

Mdulo 10 Estruturas, Unies, Enumeraes e


Typedef
A Linguagem C permite criar diversos tipos diferentes de dados particulares.
Podemos citar a estrutura, a unio, o tipo enumerado e o typedef. A estrutura um
agrupamento de variveis sobre um nome, que algumas vezes chamado de conglomerado
ou agregado de tipos de dados. A unio habilita um mesmo pedao de memria a ser
definido como dois ou mais tipos de dados diferentes. O tipo enumerado uma lista de
smbolos. O typedef cria um novo nome para um tipo existente.

10.1 Estruturas
Na Linguagem C, uma estrutura uma coleo de variveis referenciadas sobre um
nome, provendo um meio conveniente de manter informaes relacionadas juntas. Uma
declarao de estrutura forma uma fonte que pode ser usada para criar variveis de
estruturas. As variveis que compreendem a estrutura so chamadas de campos.

Em geral, todos os campos na estrutura estaro logicamente relacionados uns aos


outros. Por exemplo, a informao sobre o nome e o endereo em uma lista de endereos
deve ser normalmente representada em uma estrutura.
O seguinte fragmento de cdigo declara uma estrutura-fonte que define os campos
nome e endereo de tal estrutura. A palavra reservada struct diz ao compilador que uma
estrutura est sendo definida:
struct endereo{
char nome[30];
char rua[40];
char cidade[20];
char estado[3];
unsigned long int cep;
};

Observa-se que a declarao termina com um ponto-e-vrgula. por isso que uma
estrutura uma declarao. Temos ainda que, a etiqueta endereo, identifica essa estrutura
de dados particular e o seu especificador de tipo.
Neste ponto do cdigo, nenhuma varivel foi declarada. Somente a forma dos dados
foi definida. Para declarar uma varivel com essa estrutura, deve-se escrever:
struct endereo info_adr;

Esta expresso declarar uma varivel estrutura do tipo endereo chamada


info_adr. Quando declara-se uma estrutura, define-se um tipo de varivel complexa
composto por campos. At que se declare uma varivel desse tipo, ela no existe.
Pode-se tambm declarar uma ou mais variveis enquanto declara uma estrutura.
Veja a seguir um exemplo:
struct endereo{
char nome[30];
char rua[40];
char cidade[20];
char estado[3];
unsigned long int cep;
} info_adr, binfo, cinfo;

Isso definir um tipo de estrutura chamada endereo e declarar as variveis


info_adr, binfo e cinfo como desse tipo.

10.1.1 Referenciando os Campos da Estrutura


Campos da estrutura so referenciados pelo uso do operador de seleo de campo: o
ponto. Por exemplo, o seguinte cdigo atribuir o cep 12345777 ao campo cep da varivel
estrutura info_adr declarada anteriormente:
info_adr.cep = 12345777;

O nome da varivel estrutura seguido por um ponto e o nome do campo


referenciaro um campo individual da estrutura. Todos os campos da estrutura so
acessados da mesma maneira. A forma geral :
nome_da_varivel_estrutura.nome_do_campo

Portanto, para imprimir o cep na tela, pode-se escrever:

printf (%lu, info_adr.cep);

Isso imprimir o cep contido no campo cep da varivel estrutura info_adr.


Da mesma maneira, a matriz de caracteres info_adr.nome pode ser usada em uma
chamada funo gets( ), como mostrada aqui:
gets (info_adr.nome);

Isso passar um ponteiro para caractere para o comeo do campo nome. Se fosse
necessrio acessar os elementos individuais de info_adr.nome, poderia indexar nome. Por
exemplo, pode-se imprimir o contedo da info_adr.nome, um caractere por vez, usando
este cdigo:
int t;
for (t = 0; info_adr.nome[t]; ++t) putchar (info_adr.nome[t]);

10.1.2 Matrizes de Estruturas


O uso de matrizes de estruturas o mais comum das estruturas. Para declarar uma
matriz de estruturas, deve-se primeiro definir uma estrutura e, ento, declarar uma varivel
matriz daquele tipo. Por exemplo, para declarar uma matriz de 100 elementos de estrutura
do tipo endereo (definida anteriormente), deve-se escrever:
struct endereo info_adr[100];

Isso cria 100 conjuntos de variveis que so organizados como definido na estrutura
endereo. Para acessar uma estrutura especfica, o nome da estrutura indexado.
Por exemplo, para imprimir o cdigo cep na estrutura 3, deve-se escrever:
printf (%lu, info_adr[2].cep);

Como todas as variveis matrizes, as matrizes de estruturas comeam sua indexao


em zero.

10.1.3 Atribuindo Estruturas


Se duas variveis so do mesmo tipo, pode-se atribuir uma a outra. Nesse caso,
todos os elementos da estrutura no lado esquerdo da atribuio recebero os valores dos
elementos correspondentes da estrutura do lado direito.
Por exemplo, este programa atribui o valor da estrutura um para a estrutura dois e
exibe o resultado 10 98.6.
#include <stdio.h>
void main()
{
struct exemplo
{
int i;
double d;
} um, dois;
um.i = 10;
um.d = 98.6;
dois = um; /*atribui uma estrutura a outra*/
printf (%d %lf, dois.i, dois.d);
}

10.1.4 Passando Estruturas para Funes


At aqui, todas as estruturas e matrizes de estruturas dos exemplos so assumidas
como globais ou definidas dentro da funo que as usa.
Nesta seo, ser dada ateno especial passagem das estruturas e seus elementos
para funes.
Passando Campos de uma Estrutura para Funes: Quando um campo de uma
varivel estrutura passado para uma funo, est passando o valor daquele elemento para
a funo. Portanto, voc est passando uma simples varivel. Por exemplo, considere esta
estrutura:
/*observe que neste exemplo a estrutura no possui nome.*/
struct{ /*isso permitido quanto declaramos apenas uma*/
char x; /*varivel com o formato da estrutura definida.*/
int y;
float z;
char s[10];
} exemplo;

Aqui esto exemplos de cada campo sendo passado para uma funo:
func1
func2
func3
func4
func5

(exemplo.x); //passa o valor do


(exemplo.y); //passa o valor do
(exemplo.z); //passa o valor do
(exemplo.s); //passa o endereo
(exemplo.s[2]); //passa o valor

caractere em x
inteiro em y
float em x
da string em s
do caractere em s[2]

Contudo, se for necessrio passar o endereo de um campo individual da estrutura,


criando uma passagem de parmetro por referncia, deve-se colocar o operador & antes do
nome da varivel. Por exemplo, para passar o endereo dos campos na varivel estrutura
exemplo, voc deve escrever isto:
func1
func2
func3
func4
func5

(&exemplo.x); /*passa o endereo do caractere em x*/


(&exemplo.y); /*passa o endereo do inteiro em y*/
(&exemplo.z); /*passa o endereo do float em x*/
(exemplo.s); /*passa o endereo da string em s*/
(&exemplo.s[2]); /*passa o endereo do caractere em s[2]*/

Note que o operador & precede o nome da varivel estrutura, no o nome do campo
individual. Note tambm que o elemento string s j significa o endereo, assim, o operador
& no requerido.
Passando Estruturas Inteiras para Funes: Quando uma estrutura usada como
argumento para uma funo, a estrutura inteira passada usando-se o mtodo padro de
chamada por valor (passagem de parmetro por cpia). Isso, obviamente, significa que
qualquer mudana feita no contedo de uma estrutura dentro da funo para qual ela
passada no afeta a estrutura usada como argumento.
A considerao mais importante para se ter em mente quando se usa uma estrutura
como parmetro que o tipo do argumento deve corresponder ao tipo do parmetro. Por
exemplo, este programa declara o argumento arg e o parmetro parm para serem do mesmo
tipo de estrutura:
#include <stdio.h>
/*define um tipo de estrutura*/

struct exemplo{
int a, b;
char ch;
};
void fl(struct exemplo parm)
{
printf (%d, parm.a);
}
void main()
{
struct exemplo arg;
arg.a = 1000;
fl(arg);
}

Esse programa, como fcil de se ver, imprimir o nmero 1000 na tela. Como
mostrado, melhor definir um tipo estrutura globalmente e, ento, usar o seu nome para
declarar variveis estrutura e parmetros, quando necessrio. Isso ajuda a assegurar a
correspondncia entre os argumentos e os parmetros. Tambm, mostram para outras
pessoas que estiverem lendo o programa que parm e arg so do mesmo tipo.

10.1.5 Ponteiros para Estruturas


A Linguagem C permite ponteiros para estruturas da mesma maneira que aceita
ponteiros para qualquer outro tipo de varivel. Contudo, existem alguns aspectos especiais
dos ponteiros para estruturas que devem ser vistos.
Declarando um Ponteiro para Estrutura: Ponteiros para estruturas so declarados
colocando-se o * na frente do nome da varivel. Por exemplo, assumindo-se a estrutura
endereo definida previamente, a linha abaixo declara ponteiro_endereo para ser um
ponteiro para dados daquele tipo:
struct endereo *ponteiro_endereo;

Usando Ponteiros para Estruturas: Existem muitos usos para ponteiros para
estruturas. Um deles na obteno de uma chamada por referncia para uma funo. Outro
na criao de estruturas dinmicas (listas, filas, pilhas, rvores, etc.).
Existe uma desvantagem maior em passar tudo, at a mais simples estrutura, para
funes: o esforo necessrio para levar (e trazer) todos os campos da estrutura para a pilha.
Em estruturas simples, com poucos campos, esse esforo no to importante, mas, se
muitos campos so usados e se algum deles matriz, a performance de tempo de execuo
pode se tornar inaceitvel. A soluo para esse problema passar somente um ponteiro para
estrutura.
Quando um ponteiro para estrutura passado para uma funo, somente o endereo
da estrutura empurrado (e puxado) para a pilha. Isso significa que uma chamada de
funo extremamente rpida pode ser executada. Tambm, como estar referenciando a
estrutura em si e no uma cpia, a funo ter condies de modificar o contedo dos
campos da estrutura usada na chamada.
Para encontrar o endereo de uma varivel estrutura, o operador & colocado antes
do nome da varivel estrutura. Por exemplo, este fragmento coloca o endereo de cliente no
ponteiro p.:
struct sal{

float saldo;
char nome[80];
} cliente;
struct sal *p; /* declarao de um ponteiro para estrutura*/

Para acessar o campo saldo, pode-se escrever:


(*p).saldo

Raramente ser visto referncias feitas a um campo de uma estrutura com uso
explcito do operador *, como mostrado no exemplo anterior. Uma vez que o acesso a um
campo de uma estrutura por meio de um ponteiro para a dada estrutura to comum, um
operador especial definido pela Linguagem C realiza esta tarefa. Ele o ->, chamada de
operador seta. Ele formado utilizando-se o sinal de menos seguido por um sinal de maior
que. A seta usada no lugar do operador ponto, quando se acessa um campo da estrutura
utilizando-se um ponteiro para a varivel estrutura. Por exemplo, a declarao anterior
usualmente escrita assim:
p->saldo

Para ver como um ponteiro para uma estrutura pode ser usado, examine este
programa simples que imprime horas, minutos e segundos na sua tela, usando uma rotina
de espera cronometrada:
#include <stdio.h>
#include <conio.h>
struct estrut_horas{
int horas;
int minutos;
int segundos;
};
void espera()
{
long int t;
for (t = 1; t < 128000; ++t);
}
void atualiza (struct estrut_horas *t)
{
t->segundos++;
if (t->segundos == 60)
{
t->segundos = 0;
t->minutos++;
}
if (t->minutos == 60)
{
t->minutos = 0;
t->horas++;
}
if (t->horas == 24) t->horas = 0;
espera();

}
void exibe(struct estrut_horas *t)
{
printf (%d:, t->horas);
printf (%d:, t->minutos);

printf (%d\n, t->segundos);


}
void main()
{
struct estrut_horas tempo;
tempo.horas = 0;
tempo.minutos = 0;
tempo.segundos = 0;
for ( ; !kbhit(); )
{
atualiza (&tempo);
exibe (&tempo);
}
}

A cronometragem desse programa ajustada variando-se o contador do lao na


funo espera( ). Como pode-se observar, a estrutura global, chamada estrut_hora,
definida, mas nenhuma varivel declarada. Dentro da funo main( ), a estrutura tempo
declarada e inicializada como 00:00:00. Isso significa que tempo conhecida diretamente
apenas na funo main( ).
s duas funes atualiza( ), que atualiza a hora, e exibe( ), que imprime a hora
passado o endereo de tempo. Nas duas funes, o argumento declarado para ser da
estrutura estrut_hora. Isso necessrio para que o compilador saiba como referenciar os
campos da estrutura.
A referncia a cada campo da estrutura feita pelo uso de um ponteiro. Por
exemplo, se fosse necessrio retornar as horas para zero quando chegasse 24:00, poderia-se
escrever:
if (t->horas == 24) t->horas = 0

Essa linha de cdigo diz ao compilador para pegar o endereo da varivel t (que o
tempo na funo main( )) e atribuir zero ao seu campo chamado horas.

10.1.6 Matrizes e Estruturas dentro de Estruturas


Campos de estruturas podem ser de qualquer tipo de dado vlido na Linguagem C,
incluindo-se matrizes e estruturas. J foi visto um exemplo de um campo matriz: a matriz
de caracteres usada em info_adr.
Um exemplo de estrutura que uma matriz, tratado como nos exemplos
anteriores. Por exemplo, seja a estrutura:

struct x{
int a[10][10]; /*matriz 10x10 de inteiros*/
float b;
} y;

Para referenciar o inteiro em [3][7] na varivel a da estrutura y, deve-se escrever:


y.a[3][7]

Quando uma estrutura um campo de outra estrutura, ela chamada de estrutura


aninhada. Por exemplo, o elemento da varivel estrutura info_adr do tipo endereo est
aninhado em emp neste exemplo:
struct emp{
struct endereo info_adr;
float salrio;
} funcionrio;

Aqui endereo a estrutura definida anteriormente e emp foi definida como tendo
dois elementos. O primeiro elemento a estrutura do tipo endereo, que conter um
endereo de um empregado. O segundo salrio, que armazena o salrio do empregado. O
seguinte fragmento de cdigo atribui o cep 98765777 para o campo cep do endereo do
funcionrio:
funcionrio.endereo.cep = 98765777;

Como pode-se verificar, os elementos de cada estrutura so referenciados da


esquerda para a direita do mais externo para o mais interno.

10.2 Unies
Na Linguagem C, uma union uma localizao de memria usado por muitos tipos
de variveis diferentes. A declarao de uma union similar ao de uma estrutura, como
mostrado neste exemplo:
union u_tipo{
int i;
char ch;
};

Assim como com estruturas, essa declarao no declara qualquer varivel. Pode-se
declarar uma varivel tanto colocando-se o nome dela no fim da declarao como pelo uso
de uma declarao em separado. Para declarar uma varivel union, chamada cnvt, do tipo
u_tipo, usando a declarao dada anteriormente, pode-se escrever:
union u_tipo cnvt;

Em cnvt, o inteiro i e o caractere ch compartilham a mesma localizao de


memria.
Quando uma varivel union declarada, o compilador cria automaticamente uma
varivel grande o bastante para armazenar o tipo da varivel de maior tamanho na union.
Para acessar um elemento union deve-se usar a mesma sintaxe das estruturas: os
operadores ponto e seta. Quando se opera diretamente na union, usa-se o operador ponto.
Se a varivel union acessada por meio de um ponteiro, usa-se o operador seta. Por
exemplo, para atribuir o inteiro 10 ao elemento i de cnvt, deve-se escrever:
cnvt.i = 10;

Unies so usadas freqentemente quando so necessrias converses de tipos, uma


vez que elas permitem que se considere uma regio de memria de mais de uma maneira.

10.3 Enumeraes

Uma enumerao um conjunto de constantes inteiras que especifica todos os


valores legais que uma varivel de um tipo especfico pode ter. As enumeraes no so
incomuns no dia-a-dia. Por exemplo, uma enumerao das moedas usadas nos Estados
Unidos :
penny, nickel, dime, quarter, half_dollar, dollar

As enumeraes so definidas muito semelhantemente s estruturas com a palavra


reservada enum usada para indicar o incio de um tipo enumerado. A forma geral
mostrada aqui:
enum nome_do_tipo_enumerado {lista_de_enumerao} lista de variveis;

A lista de enumerao uma lista de nomes separados por vrgulas que representam
os valores que uma varivel da enumerao pode ter. Tanto o nome do tipo enumerado
como a lista de variveis so opcionais. Assim como com estruturas, o nome do tipo
enumerado usado para declarar variveis do seu tipo. O fragmento seguintes define uma
enumerao chamada moeda e declara dinheiro para ser desse tipo:
enum moeda {penny, nickel, dime, quarter,
half_dollar, dollar};
enum moeda dinheiro;

Dadas essas declaraes, as seguintes utilizaes so perfeitamente vlidas:


dinheiro = dime;
if (dinheiro == quarter) printf ( um quarter\n);

O ponto-chave para entender as enumeraes que cada um dos smbolos


representado por um valor inteiro. Assim sendo, eles podem ser usados em qualquer
expresso vlida com inteiros. A menos que seja inicializado de outra maneira, o valor do
primeiro smbolo da enumerao zero, o valor do segundo smbolo 1, e assim por
diante. Portanto, a declarao a seguir exibe 0 2 na tela:
printf (%d %d, penny, dime);

possvel especificar o valor de um ou mais smbolos usando-se um inicializador.


Isso feito seguindo-se o smbolo com um sinal de igual e um valor inteiro. Sempre que
um inicializador usado, aos smbolos que aparecem depois dele so associados valores
maiores que o valor de inicializao anterior. Por exemplo, o cdigo a seguir atribui o valor
100 para quarter:
enum moeda {penny, nickel, dime, quarter = 100,
half_dollar, dollar};

Uma suposio comum, mas errnea, feita a respeito das enumeraes que os
smbolos podem ser atribudos e exibidos diretamente. Esse no o caso. Por exemplo, o
seguinte fragmento de cdigo no proceder como desejado:
/*isto no funciona*/
dinheiro = dollar;
printf (%s, dinheiro);
/*este cdigo est incorreto*/

gets(s);
strcpy (dinheiro, s);

Isto , uma string que contm o nome de um smbolo no convertida


automaticamente naquele smbolo.
Criar um cdigo para entrada e sada de smbolos enumerados bastante montono
(a menos que se esteja disposto a tornar claro os seus valores inteiros). Por exemplo, o
cdigo seguinte necessrio para exibir, em palavras, o tipo de moeda que dinheiro
contm:
switch (dinheiro){

case penny: printf (penny);


break;
case nickel: printf (nickel);
break;
case dime: printf (dime);
break;
case quarter: printf (quarter);
break;
case half_dollar: printf (half_dollar);
break;
case dollar: printf (dollar);
break;

Algumas vezes, possvel declarar uma matriz de strings e usar o valor de uma
enumerao como ndice na transformao de uma valor enumerado na sua string
correspondente. Por exemplo, este cdigo tambm produzir a string apropriada:
char nome[][20] = {
penny,
nickel,
dime,
quarter,
half_dollar,
dollar
};
.
.
.
printf (%s, nome[dinheiro]);

Esse cdigo funcionar se nenhuma inicializao de smbolos for usada, uma vez
que a matriz de strings deve ser indexada comeando em zero. Por exemplo, este programa
imprime os nomes das moedas:

#include <stdio.h>
enum moeda {penny, nickel, dime, quarter,
half_dollar, dollar};
char nome[][20] =
{
penny,
nickel,
dime,

quarter,
half_dollar,
dollar

};
void main()
{
enum moeda dinheiro;
for (dinheiro = penny; dinheiro <= dollar; dinheiro++)
{
printf (%s, nome[dinheiro]);
}
}

Como os valores enumerados devem ser convertidos manualmente nos valores


correspondentes em portugus para E/S no console, eles encontram grande uso em rotinas
que no fazem tais converses. comum ver uma enumerao ser usada para definir uma
tabela de smbolos de um compilador, por exemplo, que no requer interaes com
usurios.

10.4 A Palavra Reservada Typedef


A Linguagem C permite definir explicitamente novos nomes de tipos de dados
usando-se a palavra reservada typedef. No se cria um novo tipo de dado, mas, ao contrrio,
define-se um novo nome para um tipo existente. Este processo pode auxiliar programas
dependentes de mquinas a serem portveis; somente a declarao typedef tem de ser
modificada. Ele tambm auxilia na documentao do seu cdigo por permitir nomes
descritivos para tipos de dados padres. A forma geral da declarao typedef da a seguir:
typedef tipo_nome;

Nela, temos que tipo qualquer tipo de dado permitido e nome o novo nome para
esse tipo.
O novo nome definido uma adio, no uma substituio, ao nome existente. Por
exemplo, pode-se criar um novo nome para o tipo float usando-se a seguinte declarao:
typedef float flutuante;

Essa declarao diz ao compilador para reconhecer flutuante como um outros nome
para float. A seguir, pode-se criar uma varivel float usando-se flutuante:
flutuante atraso;

Aqui, atraso uma varivel de ponto flutuante do tipo flutuante, que um


sinnimo para float.
Pode-se usar typedef para criar nomes para tipos mais complexos tambm. Por
exemplo:
typedef struct cliente_tipo{
float divida;
int atraso;
char nome[40];
} cliente;
cliente clist[NUM_CLIENTES]; /*define uma matriz de estruturas*/
/*do tipo cliente*/

Nesse exemplo, cliente no uma varivel do tipo cliente_tipo mas, ao contrrio,


um outro nome para struct cliente_tipo. A utilizao de typedef pode ajudas a tornar
cdigos mais fceis de serem lidos e portados para outro computador. Mas, lembre-se: no
est sendo criado qualquer tipo de dado novo.

10.5 Sntese do Mdulo


apresentado seguir, uma sntese do que foi tratado em cada item deste mdulo.
Com esta sntese voc poder relembrar conceitos vistos durante nosso estudo ou mesmo
direcionar seu estudo, caso voc j tenha conhecimentos na Linguagem C.
13110.1 Estruturas: foi visto que uma estrutura uma coleo de variveis
referenciadas sobre um nome, provendo um meio conveniente de manter informaes
relacionadas juntas. Uma declarao de estrutura forma uma fonte que pode ser usada para
criar variveis de estruturas.
13210.1.1 Referenciando os Campos da Estrutura: foi visto que os campos da
estrutura so referenciados pelo uso do operador de seleo de campo: o ponto. O nome da
varivel estrutura seguido por um ponto e o nome do campo referenciaro um campo
individual da estrutura. Todos os campos da estrutura so acessados da mesma maneira.
13310.1.2 Matrizes de Estruturas: foi visto que o uso de matrizes de estruturas
o mais comum das estruturas. Para declarar uma matriz de estruturas, deve-se primeiro
definir uma estrutura e, ento, declarar uma varivel matriz daquele tipo.
13410.1.3 Atribuindo Estruturas: foi visto que se duas variveis so do mesmo
tipo, pode-se atribuir uma a outra. Nesse caso, todos os elementos da estrutura no lado
esquerdo da atribuio recebero os valores dos elementos correspondentes da estrutura do
lado direito.
13510.1.4 Passando Estruturas para Funes: foi visto neste item como passar
campos de uma estrutura para funes e como passar estruturas inteiras para funes.
13610.1.5 Ponteiros para Estruturas: foi visto que Linguagem C permite
ponteiros para estruturas da mesma maneira que aceita ponteiros para qualquer outro tipo
de varivel. Foi visto como declarar e usar ponteiros em estruturas.
13710.1.6 Matrizes e Estruturas dentro de Estruturas: foi visto que campos de
estruturas podem ser de qualquer tipo de dado vlido na Linguagem C, incluindo-se
matrizes e estruturas. Quando uma estrutura um campo de outra estrutura, ela chamada
de estrutura aninhada. Os elementos de cada estrutura so referenciados da esquerda para a
direita do mais externo para o mais interno.
13810.2 Unies: foi visto que na Linguagem C, uma union uma localizao de
memria usado por muitos tipos de variveis diferentes. Para acessar um elemento union
deve-se usar a mesma sintaxe das estruturas: os operadores ponto e seta.
13910.3 Enumeraes: foi visto que uma enumerao um conjunto de
constantes inteiras que especifica todos os valores legais que uma varivel de um tipo
especfico pode ter.
14010.4 A Palavra Reservada Typedef: foi visto que a Linguagem C permite
definir explicitamente novos nomes de tipos de dados usando-se a palavra reservada

typedef. No se cria um novo tipo de dado, mas, ao contrrio, define-se um novo nome para
um tipo existente. Este processo pode auxiliar programas dependentes de mquinas a serem
portveis.

Mdulo 11 Funes de Entrada/Sada (I/O) e


Programa Analisador Espectral
11.1 Introduo
As funes de entrada/sada (I/O input/output) da linguagem C so as equivalentes
das instrues in e out da linguagem Assembly. Elas permitem acesso direto ao hardware
do microcomputador e, portanto, os endereos e modo de programao dos dispositivos de
I/O a serem manipulados tem que conhecidos adequadamente para evitar algum travamento
do sistema por uso inadequado dessas funes.
O mapa de endereos de I/O do PC padro, apresentado na tabela a seguir, deixam
livre os endereos 220H a 22FH e 300H a 30FH. Portanto, todo tipo de placa que no
tenham grande demanda de endereos, como placas de prottipo ou de aquisio de sinais
podem ser alocadas nesses endereos sem risco de causar conflito com outros dispositivos
de I/O. A placa a ser inserida no slot ou barramento de expanso deve ser previamente
configurada num desses endereos e conectada com o computador desligado. No caso de
placas de aquisio de sinais, os sinais analgicos a serem convertidos s devem ser
conectados com o computador ligado. Tambm estes sinais devem ser desconetados antes
de se desligar o computador.

Tabela 11.1 Mapa de Endereos de I/O do PC

11.2 As Funes inport e outport


As funes inport() e outrport() permitem acesso direto a endereos de dispositivos
de I/O, em 8 ou 16 bits. O arquivo header dessas funes dos.h. Seus formatos so
apresentados a seguir:

int inport( int port_id);


Le um valor inteiro de 16 bits do endereo port_id especificado;

int inportb( int port_id);


Le um valor inteiro de 8 bits do endereo port_id especificado;

void outport(int port_id, int value)


Envia o contedo da varivel value, de 16 bits, para o endereo port_id
especificado;

void outportb(int port_id, unsigned char value)


Envia o contedo da varivel value, de 8 bits para o endereo port_id especificado;

11.3 Placas de Aquisio de Sinais Analgicos


A placa de aquisio de sinais CIO-DAS-AO-08H uma placa de baixo custo para
barramento ISA, com as seguintes caractersticas:

Entradas analgicas: 8 canais diferenciais multiplexados, 12 bits de resoluo do


tipo aproximaes sucessivas, tempo de converso de 25 microssegundos;
Sada analgica: dois canais de 12 bits, com faixa de tenso de sada selecionvel
por programao;
A tabela de endereamento dessa placa mostrada a seguir:

Tabela 11.2 Tabela de Endereamento da Placa CIO-DAS08-AOH


A placa tem um endereo-base setado por meio de chave de configurao. Os
valores normalmente utilizados so 220H ou 300H, em hexadecimal.

11.3.1 - Conversor A/D


A converso A/D iniciada com uma escrita no endereo BASE para operao
em 8 bits ou escrita no endereo (BASE +1) para operao em 12 bits.
O final de converso sinalizado atravs da leitura do bit mais significativo do
endereo (BASE+2), que zerado quando a converso termina, conforme esquema:
Endereo BASE+2 - Leitura
7
6
5
EOC
IP3
IP2

4
IP1

3
IRQ

2
MUX2

1
MUX1

0
MUX0

O resultado final da converso pode ento ser lido nos endereos BASE e
BASE+1 com a seguinte configurao:
Endereo BASE - Leitura
7
6
5
AD9
AD10
AD11
Endereo BASE+1 - Leitura

4
AD12 (LSB)

3
0

2
0

1
0

0
0

7
AD1 (MSB)

6
AD2

5
AD3

4
AD4

3
AD5

2
AD6

1
AD7

0
AD8

Observa-se acima que o LSB lido no endereo (BASE), com apenas 4 bits
menos significativos. No endereo (BASE+1) esto os 8 bits mais significativos. Para
ordenao nos 12 bits, deve, portanto, realizar a leitura nos respectivos endereos,
rotacionar o byte menos significativo 4 casas a direita e somar com o byte superior
rotacionado 4 casas a esquerda.
O seguinte trecho de programa em linguagem C realiza a converso de um valor
analgico em digital, em 12 bits, j provendo a ordenao dos bits.
outportb(BASE+1,0);
/* Partida no conversor A/D, 12 bits */
a=0x80;
while(a==0x80)
a=inportb(BASE+2)&0x80; /*espera por EOC = 0, fim converso */
BS=(inportb(BASE)&0xF0)>>4; /* leitura Byte inferior e correo */
Bi=inportb(BASE+1);
/* leitura byte superior */
vec = 16 * BS + Bi ;
/* rearranjo valor digital em 12 bits */

11.3.2 - Conversor D/A


A converso realizada diretamente, enviando o valor digital de 12 bits para os
respectivos endereos no seguinte formato (Canal D/A 0):
Endereo BASE+8 - Escrita
7
6
5
DA7
DA6
DA5
Endereo BASE+9 - Escrita
7
6
5
X
X
X

4
DA4
4
X

3
DA3

3
DA11 (MSb)

2
DA2
2
DA10

1
DA1

0
DA0 (LSb)

1
DA9

0
DA8

O canal D/A 1 tem a mesma configurao dos bits, porm os endereos so


(BASE+10) e (BASE+11) respectivamente.
A seguir mostrado um trecho de programa em linguagem C que faz o envio de um
valor de 12 bits para o conversor D/A. O formato o mesmo apresentado na aquisio do
sinal, em 12 bits, j conveniente ordenados.
BDAI = vec & 0xFF;
/* mascara os 4 bits mais significativos */
BDAS =( vec & 0xF00 ) >> 8; /* mascara 8 bits menos significativo
e faz rotao de 8 bits a direita */
outportb(BASE+8,BDAI);
/* envia LSB
*/
outportb(BASE+9,BDAS);
/* envia 4 bits do MSB */

11. 4 Fatores de Escala para o Modo Grfico


Os fatores de escala nos eixos x e y so usados para que um conjunto qualquer de
dados possam ser exibidos numa regio da tela pr-determinada.
Para a deduo das expresses, considere as seguintes definies:

NP nmero de pontos, valor constante;

vec vetor de dados com NP pontos;

vec[i] i-simo elemento do vetor de dados vec, 0

vecmin valor mnimo do vetor vec;

vecmax valor mximo do vetor vec;

i ndice do elemento no vetor vec;

k coordenada do eixo x correspondente ao i-simo elemento;

xmin coordenada mnima do eixo x da janela especificada;

xmax coordenada mxima do eixo x da janela especificada;

i < NP;

10 ymin - coordenada mnima do eixoy da janela especificada;


11 ymax - coordenada mxima do eixo y da janela especificada;
12 y coordenada do eixo y correspondente ao elemento vec[i];

11.4.1 Fator de Escala Eixo X


Este fator de escala permite que um vetor com qualquer nmero de pontos possa ser
plotado no eixo x da tela. O vetor de dados comea no elemento 0 e vai at o ndice (NP-1).
0

NP-1

xmin

xmax

x max x min
NP 1

x min

i*

k x min
i

x max x min
NP 1

[11.1]

x max x min
NP 1

k i * x x min
11.4.2 - Fator de Escala Eixo Y
Nesse caso so envolvidos os valores mximo e mnimo do vetor, devendo ser
desenvolvida uma rotina para tal objetivo.
ymin

vecmax

[11.2]
[11.3]

vec[i]

ymax

vecmin

y max y min
vec min vec max
y y min

vec[i] vecmax *

y y min
vec[i] vec max

y max
vec min

y max y min
vecmin vecmax

y min
vec max

vec[i] vec max * y y min

[11.4]

[11.5]
[11.6]

Como exemplo, considere uma janela com coordenadas de 10 a 90 % da tela no


eixo x e de 5 a 45 % do eixo y. Os respectivos fatores de escala poderiam ser obtidos como:
float deltax, deltay;
detectgraph(&graf,&gmode);
initgraph(&graf,&gmode,"c:\\tc");
max_min();

xmax =
ymax =
deltax
deltay

getmaxx();
getmaxy();
= (0.9*xmax-0.1*xmax)/(NP-1));
/* [11.2] */
= ((0.45*ymax-0.05*ymax)/(vec_min-vec_max)); /* [11.5]*/

for (i=1;i<NP ;i++)


{ ki = ((i-1)*deltax)+0.08*xmax ;
/* [11.3] */
yi = ((1.0*(vec[i-1]-vec_max))*deltay)+0.1*ymax; /* [11.6] */
kf = (i*deltax)+0.08*xmax;
yf = ((1.0*(vec[i]-vec_max))*deltay)+0.1*ymax;
line(ki,yi,kf,yf);
}
.
.
.
max_min()
{ int i;
vec_max = vec_min = vec[0];
for ( i = 1; i < NP ; i++ )
{
if( vec[i] > vec_max)
if( vec[i] < vec_min)
}

vec_max = vec[i];
vec_min = vec[i];

11.4.3 Programa: Anlise Espectral


Como exemplo de aplicao, apresenta-se a seguir um programa em linguagem C
que realiza a anlise espectral (decomposio de fourier) de um sinal, armazenado no vetor
vec[i]. As fontes de sinais so:
[A] - arquivo de dados com 512 pontos: datan.c;
[G] gerador de sinais, composto de duas senides com amplitudes aleatrias;
[P] placa de aquisio de sinais, modelo CIO-DAS-AO.
O sinal e seu espectro so exibidos em duas janelas, sendo o sinal no domnio do
tempo mostrado na janela superior e o sinal no domnio da freqncia, como metade dos
pontos do vetor, na janela inferior.
#define PI
3.1415926
#define NP
512
#define BASE 0x300
#include
#include
#include
#include
#include
#include
#include
#include

<stdio.h>
<graphics.h>
<math.h>
<stdlib.h>
<ctype.h>
<conio.h>
<dos.h>
<stdarg.h>

float vec[NP+1],vec_max,vec_min,xmax,ymax;
float A=1,R=1,K=200,deltax,deltay,ki,kf,yi,yf;
float K2,B;
int BS[NP+1],Bi[NP+1];
int BDAS[NP+1],BDAI[NP+1];
double magr[NP+1], magi[NP+1];
int y1,x1,k,vetor[NP+1];
void main(void)
{
char L;
int graf,gmode;
detectgraph(&graf,&gmode);
initgraph(&graf,&gmode,"c:\\tc");
xmax = getmaxx();
ymax = getmaxy();
L = 'G';
while(L!='S')
{
cleardevice();
switch(L)
{ case 'A': datan(); superior(); fft();
inferior(); break;
case 'G': seno();
superior(); fft();
inferior(); break;
case 'P': convad(); superior(); fft();
inferior(); convda();
break;
}
L=toupper(getch());
}
closegraph();
}
datan()
{
int i;
FILE *infile;
if((infile = fopen("datan.c","rb")) == NULL)
{ perror("Desculpe mas nao encontrei o datan.c");
exit(1);
}
for(i=0;i< NP; i++ )
fscanf(infile,"%f ", &vec[i]);
fclose(infile);
}
superior()
{
int i;
tela();
max_min();
deltax = (0.92*xmax/(NP-1));
deltay = (0.35*ymax/(vec_min-vec_max));
settextstyle(0,0,1); setcolor(YELLOW);

x1=0.008*xmax; y1=0.44*ymax;
gprintf(&x1,&y1,"%3.1f",vec_min);
x1=0.008*xmax; y1=0.1*ymax;
gprintf(&x1,&y1,"%3.1f",vec_max);
setcolor(RED); setlinestyle(1,0,0);
if(vec_min<0)
{
k=(-vec_max)*deltay+0.1*ymax;
line(0.08*xmax,k,xmax,k);
x1=0.03567*xmax;
gprintf(&x1,&k,"0.0");
}
setlinestyle(0,0,0);
setcolor(BLACK);
for (i=1;i<NP ;i++)
{ ki = ((i-1)*deltax)+0.08*xmax ;
yi = ((1.0*(vec[i-1]-vec_max))*deltay)+0.1*ymax;
kf = (i*deltax)+0.08*xmax;
yf = ((1.0*(vec[i]-vec_max))*deltay)+0.1*ymax;
line(ki,yi,kf,yf);
}
}
max_min()
{ int i;
vec_max = vec_min = vec[0];
for ( i = 1; i < NP ; i++ )
{
if( vec[i] > vec_max)
if( vec[i] < vec_min)
}
}

vec_max = vec[i];
vec_min = vec[i];

tela()
{

int cor_quadro = WHITE;


setfillstyle(1,BLACK);
floodfill(0.05*xmax,0.01*ymax,WHITE);
setcolor(WHITE);
rectangle(0.08*xmax,0.1*ymax,xmax,0.45*ymax);
setfillstyle(1,cor_quadro);
floodfill(0.2*xmax,0.2*ymax,WHITE);
rectangle(0.08*xmax,0.55*ymax,xmax,0.9*ymax);
setfillstyle(1,cor_quadro);
floodfill(0.2*xmax,0.8*ymax,WHITE);
rectangle(0,0,xmax,ymax);
line(0,0.95*ymax,xmax,0.95*ymax);
setfillstyle(1,8);
floodfill(0.2*xmax,0.96*ymax,WHITE);
setfillstyle(1,YELLOW);
floodfill(0.95*xmax,0.98*ymax,WHITE);
nome();
}

nome()
{

setcolor(LIGHTRED); settextstyle(0,0,1);

outtextxy(0.05*xmax,0.03*ymax,"DEMO");
outtextxy(0.02*xmax,0.04*ymax,"");
outtextxy(0.84*xmax,0.02*ymax,"MICRO - 2");
outtextxy(0.85*xmax,0.05*ymax,"06/2006");
setcolor(WHITE); rectangle(.2*xmax,0,0.80*xmax,.08*ymax);
setcolor(GREEN); settextstyle(0,0,2);
outtextxy(0.26*xmax,0.03*ymax,"ANALISADOR ESPECTRAL");
setcolor(MAGENTA); settextstyle(5,0,2);
outtextxy(0.47*xmax,0.48*ymax,"Tempo");
outtextxy(0.45*xmax,0.92*ymax,"Frequencia");
setcolor(BLACK);
outtextxy(0.25*xmax,0.97*ymax,"[A]rquivo [G]erador [P]laca [S]air");
setcolor(MAGENTA); settextstyle(0,1,1);
outtextxy(0.025*xmax,0.24*ymax,"Tensao");
outtextxy(0.025*xmax,0.67*ymax,"Tensao");
}
seno()
{

int i;
float xi,yi;
double teta,B,K2;
B=random(50)+1.0;
K2=random(250)+1.0;
A=random(100)+1.0;
for(i=0;i<NP;i++)
{ teta=360.*i*PI/(180.*NP);
vec[i]=A*sin(100.0*teta)+ B*sin(K2*teta)+
10.0*random(100)/101.0;
}
}
inferior()
{
int i;
max_min();
setcolor(YELLOW);
settextstyle(0,0,1);
x1=0.02*xmax;
y1=0.89*ymax;
gprintf(&x1,&y1,"%3.1f",vec_min);
settextstyle(0,0,1);
x1=0.01*xmax;
y1=0.55*ymax;
gprintf(&x1,&y1,"%3.1f",vec_max);
setcolor(BLACK);
deltax = (2*0.92*xmax/(NP-1));
deltay = (0.35*ymax/(vec_min-vec_max));
for (i=1;i<NP/2;i++)
{
ki = (i-1)*deltax+0.08*xmax ;
yi = ((1.0*(vec[i-1]-vec_max))*deltay)+0.55*ymax;
kf = (i)*deltax+0.08*xmax;
yf = ((1.0*(vec[i]-vec_max))*deltay)+0.55*ymax;
line(ki,yi,kf,yf);
}
}

convad()
{ int i,a;
for(i=0;i<NP;i++)
{
outportb(BASE+1,0);
a=0x80;
while(a==0x80)
a=inportb(BASE+2)&0x80;
BS[i]=(inportb(BASE)&0xF0)>>4;
Bi[i]=inportb(BASE+1);
vec[i]=16*BS[i]+Bi[i];
vetor[i]=vec[i];
}
}
convda()
{ int i;
for(i=0;i<=NP;i++)
{
BDAI[i]=vetor[i]&0xFF;
BDAS[i]=(vetor[i]&0xF00)>>8;
}
while(!kbhit())
{ for(i=0;i<=NP;i++)
{ outportb(BASE+8,BDAI[i]);
outportb(BASE+9,BDAS[i]);
}
}
}

/*

SUBROTINA FFT - CALCULA A FFT DE NP PONTOS DO VETOR VEC,


RETORNANDO OS VETOR VEC
*/

fft()
{

int ii,jj,n,mudado,ni,m,l,k;
int N,gm,gd;
double ur,ui,wr,wi,tr,ti,tur;
float ji;
for(ii=0;ii<=NP;ii++) magr[ii]=magi[ii]=0.0;
n = log10(NP)/log10(2);
/ ******** bit reverso *************/
for(jj = 0; jj < NP; jj++)
{
mudado=0;
ni = 1;
for(ii=1;ii<=n; ii++)
{ if((ni&jj)!= 0)
mudado|=(1<<(n+1-ii));
ni<<=1;
}
magr[(mudado>>1)+1]=vec[jj]/NP;
}
for(m=1;m<=n;m++)
{ ur = 1; ui =0;
jj = 1;
k = 1<<(m-1);
wr = cos(PI/k); wi = -sin(PI/k);

for(jj=1;jj<=k;jj++)
{ for(l=jj;l<=NP;l+= (1<<m))
{ tr = magr[l+k]*ur-magi[l+k]*ui;
ti = magr[l+k]*ui+magi[l+k]*ur;
magr[l+k] = magr[l] - tr;
magi[l+k] = magi[l] - ti;
magr[l] = magr[l] + tr;
magi[l] = magi[l] + ti;
}
tur = ur*wr-ui*wi;
ui = ur*wi+ui*wr;
ur = tur;
}
}
for(ii=0;ii<NP;ii++)
{ magr[ii] = magr[ii+1];
magi[ii] = magi[ii+1];
vec[ii]=2*sqrt(pow(magi[ii],2.)+ pow(magr[ii],2.));
}
vec[0]=0;
/* faz o valor medio do vetor igual a zero */
}
int gprintf( int *xloc, int *yloc, char *fmt, ... )
{
va_list argptr;
/* Argument list pointer
*/
char str[140];
/* Buffer to build sting into */
int cnt;
/* Result of SPRINTF for return */
va_start( argptr, format ); /* Initialize va_ functions */
cnt = vsprintf(str,fmt,argptr); /*prints string to buffer*/
outtextxy(*xloc,*yloc,str); /* Send string in graphics mode */
*yloc += textheight("H")+2; /* Advance to next line
*/
va_end( argptr );
/* Close va_ functions
*/
return( cnt );

/* Return the conversion count

*/

A seguir so apresentados alguns resultados da simulao desse programa, para as


opes Arquivo e Gerador.

Figura 11.1 Analisador Espectral Duas senides

Figura 11.2 Analisador Espectral Duas senides prximas

11.3 Analisador Espectral Arquivos datan.c

Figura

11.5 - Sntese do Mdulo


apresentado seguir, uma sntese do que foi tratado em cada item deste mdulo.
Com esta sntese voc poder relembrar conceitos vistos durante nosso estudo ou mesmo
direcionar seu estudo, caso voc j tenha conhecimentos na Linguagem C.
11.1 Introduo: feita uma breve introduo sobre as funes de entrada/sada
(I/O input/output) da linguagem C. Nele visto que elas permitem acesso direto ao
hardware do microcomputador.
11.2 As Funes inport e outport: visto que as funes inport() e outrport()
permitem acesso direto a endereos de dispositivos de I/O, em 8 ou 16 bits.
11.3 Placas de Aquisio de Sinais Analgicos: foi visto que a placa de
aquisio de sinais CIO-DAS-AO-08H uma placa de baixo custo para barramento ISA.
Tambm foi mostrado suas caractersticas de entrada e sada.
11.3.1 - Conversor A/D: detalhado como ocorre o processo de converso
analgico para digital.

11.3.2 - Conversor D/A: detalhado como ocorre o processo de converso digital


para analgico.
11. 4 Fatores de Escala para o Modo Grfico: foi visto que os fatores de escala
nos eixos x e y so usados para que um conjunto qualquer de dados possam ser exibidos
numa regio da tela pr-determinada.
11.4.1 Fator de Escala Eixo X: explicado que o fator de escala do eixo X
permite que um vetor com qualquer nmero de pontos possa ser plotado no eixo x da tela.
O vetor de dados comea no elemento 0 e vai at o ndice (NP-1).
11.4.2 - Fator de Escala Eixo Y: no caso do fator de escala do eixo Y so
envolvidos os valores mximo e mnimo do vetor, devendo ser desenvolvida uma rotina
para tal objetivo.
11.4.3. Programa: Anlise Espectral: foi apresentado um programa em linguagem C que

Referncias

realiza a anlise espectral (decomposio de fourier) de um sinal.

Bibliogrficas

[1] UNIPAM Unio Pan-Americana de Ensino. Linguagem C/C++. Cascavel: Faculdade


de Cincias Aplicadas de Cascavel FACIAP. Curso de Cincia da Computao. 2004.
[2] JAMSA, Kris Ph.D., KLANDER, Lars. Programando em C/C++. A Bblia .O melhor
guia para programao em C/C++. So Paulo: Makron Books.1999.
[3] KERNIGHAN, Brian W., and RITCHIE, Dennis M.. The C Programming Language.
Englewood Cliffs, N. J.: Prentice-Hall Inc, 1978.
[4] MIZRAHI, Victorine Viviane. Treinamento em Linguagem C++. So Paulo: Makron
Books, 1995.
[5] HOLZNER, Steven. Borland C++ Programao for Windows. So Paulo: Makron
Books, 1995.

Vous aimerez peut-être aussi