Você está na página 1de 160

Introdução à Lógica

e
Técnicas de Programação

agosto de 13
2

Sumário
1. Teoria dos Conjuntos ................................................................................................................................................ 5
1.1 Conjunto .............................................................................................................................................................. 5
1.2 Determinação de um conjunto ............................................................................................................................ 5
1.2.1 Por Extensão ................................................................................................................................................ 5
1.2.2 Por Compreensão ........................................................................................................................................ 5
1.3 Conjunto Unitário e Conjunto Vazio .................................................................................................................... 5
1.4 Conjuntos Finitos e Infinitos ................................................................................................................................ 6
1.5 Subconjuntos ...................................................................................................................................................... 6
1.6 Igualdade de Conjuntos ...................................................................................................................................... 6
1.7 Conjunto Universo ............................................................................................................................................... 7
1.8 Conjuntos Numéricos Importantes ...................................................................................................................... 7
1.9 Operações com Conjuntos ................................................................................................................................. 7
1.9.1 União de Conjuntos ( ). ............................................................................................................................. 7
1.9.2 Interseção de Conjuntos ( ). ..................................................................................................................... 7
1.9.3 Diferença de Conjuntos ( )......................................................................................................................... 8
1.9.4 Complementar de A em Relação ao Universo ............................................................................................. 8
1.9.5 Complementar de A em relação a B ........................................................................................................... 8
1.9.6 Diferença Simétrica ...................................................................................................................................... 8
1.10 Propriedades das Operações com Conjuntos .................................................................................................. 8
1.10.1 Comutativas ................................................................................................................................................ 9
1.10.2 Associativas ................................................................................................................................................ 9
1.10.3 Distributivas ................................................................................................................................................ 9
1.10.4 Leis de “DE MORGAN” ............................................................................................................................. 9
1.11 Número de Elementos de um Conjunto ............................................................................................................ 9
1.12 Conjunto das partes de um conjunto A ............................................................................................................. 9
1.13 Exercícios de Conjuntos ................................................................................................................................. 10
2. Lógica ..................................................................................................................................................................... 13
2.1 O que é Lógica .................................................................................................................................................. 13
2.2 Estudo da Lógica Matemática ........................................................................................................................... 13
2.2.1 Noções de Lógica Matemática ................................................................................................................... 13
2.2.2 Proposições ................................................................................................................................................ 13
2.2.2.1 Valores Lógicos das Proposições ........................................................................................................ 13
2.2.2.2 Proposições Simples x Proposições Compostas ................................................................................ 13
2.2.2.3 Conectivos ........................................................................................................................................... 14
2.2.3 Operações Lógicas Sobre Proposições ..................................................................................................... 16
2.3 Exercícios e Teste de Raciocínio Lógico .......................................................................................................... 16
3. Algoritmos ............................................................................................................................................................... 18
3.1 Definição ........................................................................................................................................................... 18
3.2 Algoritmos Estruturados .................................................................................................................................... 18
3.3 Programas ......................................................................................................................................................... 19
3.4 Técnicas Usadas para Desenvolver os Algoritmos: ......................................................................................... 19
3.5 Tipos de Dados ................................................................................................................................................. 19
3.5.1 Dados Numéricos ....................................................................................................................................... 19
3.5.2 Dados Literais ............................................................................................................................................. 19
3.5.3 Dados Lógicos ............................................................................................................................................ 19
3.6 Constantes ........................................................................................................................................................ 20
3.7 Variáveis............................................................................................................................................................ 20
3.8 Identificadores ................................................................................................................................................... 20
3.9 Declaração de Variáveis ................................................................................................................................... 20
3.10 Operadores ..................................................................................................................................................... 21
3.10.1 Operadores Aritméticos ............................................................................................................................ 21
3.10.2 Operadores Relacionais ........................................................................................................................... 22
3.10.3 Operadores Lógicos ................................................................................................................................. 22
3.11 Expressões Matemáticas ................................................................................................................................ 22
3.11.1 Expressões Aritméticas ............................................................................................................................ 22
3.11.2 Expressões Lógicas e Relacionais ........................................................................................................... 22
3.11.3 Expressões Literais .................................................................................................................................. 23
3.12 Funções Matemáticas ..................................................................................................................................... 23
3.13 Comandos de atribuição ................................................................................................................................. 23
3.14 Comandos de Entrada e Saída de Dados ...................................................................................................... 23
3.15 Documentação ................................................................................................................................................ 24

Introdução á Lógica e Técnicas de Programação José Gracioli


3

3.16 Estruturas Básicas de Controles ..................................................................................................................... 24


3.16.1 Sequência ................................................................................................................................................. 24
3.16.2 Seleção ..................................................................................................................................................... 24
3.16.2.1 Seleção Simples ................................................................................................................................ 24
3.16.2.2 Seleção Composta............................................................................................................................. 25
3.16.3 Repetição ................................................................................................................................................. 27
3.16.4 Repetição com uma variável de Controle................................................................................................. 30
3.16.5 Seleção dentre Múltiplas Alternativas....................................................................................................... 31
4. Estrutura de Dados Agregados Homogêneos: Vetores e Matrizes ...................................................................... 32
4.1 Vetores .............................................................................................................................................................. 32
4.2 Matrizes ............................................................................................................................................................. 33
4.2.1 Definição ..................................................................................................................................................... 33
4.2.2 Representação Algébrica ........................................................................................................................... 33
4.2.3 Matriz Quadrada ......................................................................................................................................... 34
4.2.4 Matriz Unidade ou Identidade ..................................................................................................................... 34
4.2.5 Matriz Transposta ....................................................................................................................................... 35
4.2.6 Operação com Matrizes ............................................................................................................................. 35
4.2.6.1 Adição e Subtração .............................................................................................................................. 35
4.2.6.2 Multiplicação ........................................................................................................................................ 35
4.2.7 Matriz Oposta ............................................................................................................................................. 36
4.2.8 Matriz Simétrica .......................................................................................................................................... 36
4.2.9 Matriz Anti-Simétrica .................................................................................................................................. 36
4.2.9 Propriedades .............................................................................................................................................. 36
4.2.10 Matriz Inversa ........................................................................................................................................... 36
4.2.11 Determinantes .......................................................................................................................................... 37
4.2.11.1 Determinante de uma matriz quadrada de 2ª Ordem ........................................................................ 37
4.2.11.2 Determinante de uma matriz quadrada de 3ª Ordem ........................................................................ 37
4.2.12 Declaração de uma Matriz no Algoritmo .................................................................................................. 38
5. Modularização de Algoritmos/Programas ............................................................................................................... 38
5.1 Variável Global e Local ..................................................................................................................................... 38
5.2 Sub-Rotinas....................................................................................................................................................... 40
5.2.1 Procedimento sem Passagem de Parâmetros. .......................................................................................... 40
5.2.2 Procedimento com Passagem de Parâmetros ........................................................................................... 41
5.2.2.1 Por Valor .............................................................................................................................................. 42
5.2.2.2 Por Referência ..................................................................................................................................... 42
5.2.3 Funções – Function .................................................................................................................................... 43
5.2.3.1 Function sem Passagem de Parâmetros. ........................................................................................... 43
5.2.3.2 Function com Passagem de Parâmetros. ........................................................................................... 44
6. Registro e Arquivos................................................................................................................................................. 44
6.1 Registros ou Agregados Heterogêneos ............................................................................................................ 44
6.1.1 Declaração de Registros ............................................................................................................................ 45
6.1.2 Para Acessar um Campo do Registro: ....................................................................................................... 45
6.1.3 Exemplo Prático da Utilização de Registros ............................................................................................... 45
6.1.4 Exercícios ................................................................................................................................................... 46
6.2 Arquivos ............................................................................................................................................................ 46
6.2.1 Arquivos do Tipo File .................................................................................................................................. 47
6.2.2 Arquivos do Tipo Text................................................................................................................................. 47
6.2.3 Declaração de Arquivos ............................................................................................................................. 47
6.2.4 Comandos de Arquivos em Pascal ............................................................................................................ 47
7. Linguagem Pascal .................................................................................................................................................. 52
7.1 Tipos de Dados ................................................................................................................................................. 52
7.2 Palavras Reservadas ........................................................................................................................................ 52
7.3. Constantes ....................................................................................................................................................... 52
7.4 Declaração de Variáveis ................................................................................................................................... 53
7.5 Operadores Aritméticos .................................................................................................................................... 53
7.6 Operadores Relacionais .................................................................................................................................... 53
7.7 Operadores Lógicos .......................................................................................................................................... 53
7.8 Funções Matemáticas ....................................................................................................................................... 53
7.9 Comando de Atribuição(:=) ............................................................................................................................... 54
7.10 Comando de Entrada e Saída ......................................................................................................................... 54
7.11 Comentários .................................................................................................................................................... 54
7.12 Formatação de Números Reais ...................................................................................................................... 54
7.13 Funções de Tratamento de Caracteres .......................................................................................................... 54
7.14 Declaração de Registros ................................................................................................................................. 56
Introdução á Lógica e Técnicas de Programação José Gracioli
4

Introdução á Lógica e Técnicas de Programação José Gracioli


5

1. Teoria dos Conjuntos


A teoria dos conjuntos foi estabelecida por Georg Ferdinand Ludwig Philip Cantor
(1845–1918), nascido na Rússia, onde estudou física e matemática e doutorou-se na
Alemanha em 1867, sobre a Teoria dos Números.

1.1 Conjunto
Intuitivamente um conjunto é uma coleção de objetos(não repetidos). Os objetos são os
elementos do conjunto e podem ser expressos sob a forma de números, cores, pessoas etc.
Em geral, os conjuntos são expressos por letras maiúsculas do alfabeto(A, B, C...) e os
elementos de um conjunto são representados por letras minúsculas(a, b, c,...)

Exemplos
1) Conjunto das vogais Elementos: a, e, i, o, u
2) Conjunto dos pares compreendidos entre 9 e 17. Elementos: 10, 12, 14, 16

Para indicarmos se um certo elemento pertence ou não pertence a um determinado


conjunto, utilizamos, respectivamente, os símbolos e .

Importante: Os símbolos e relacionam elementos com conjuntos.

1.2 Determinação de um conjunto


Um conjunto está bem determinado quando conhecemos todos os seus elementos, ou
quando conhecemos a regra que determina a composição de seus elementos. Um conjunto
pode ser representado de dois modos:

1.2.1 Por Extensão


Quando é possível escrever todos os seus elementos.
Exemplos
Conjunto das vogais do alfabeto A = {a, e, i, o, u}
Conjunto dos pares maiores que 3 P = {4, 6, 8,...}

1.2.2 Por Compreensão


Quando conhecemos uma propriedade característica comum a todos os elementos do
conjunto.
Exemplos
Conjunto das vogais do alfabeto A = {x | x é vogal}
Conjunto dos pares P = {x | x é par}

Se todos os elementos de A satisfazem a propriedade p,


podemos escrever A = {x | x tem a propriedade p}

1.3 Conjunto Unitário e Conjunto Vazio

Conjunto Unitário é o que tem um único elemento.


Exemplo
B = { x | x é um inteiro e 3x = 6} B={2}

Conjunto Vazio é aquele que não possui elemento.

Exemplos
Introdução á Lógica e Técnicas de Programação José Gracioli
6

C={x|x+1=x+2}
D = { x | x é par compreendido entre 3 e 3,56 }

Notação de Conjunto Vazio: { } ou

1.4 Conjuntos Finitos e Infinitos


Intuitivamente um conjunto é finito se contém um número específico (contável) de
elementos. Caso contrário, é infinito.
Exemplos
1) Conjunto Finito
E = Múltiplos de 5 entre 10 e 25 E = {15 , 20 }
G = Vogais de nosso alfabeto G = {a, e, i, o, u}

2) Conjunto Infinito
H = Múltiplos de 5 H = {5, 10, 15, 20, .... }
L = Números Impares L = { 1, 3, 5, 7,... }

1.5 Subconjuntos
Um Conjunto C qualquer é subconjunto de J se e somente se todo elemento de C for
também elemento de J.
Exemplos
Seja A = { a, b, c, d } ; B = { a, c } e C = { a, c, d }. É fácil verificar que B é
subconjunto de C e C é subconjunto de A.

Notação:
B A B é subconjunto de A ou B está contido em A.
C B C não é subconjunto de B ou C não está contido em B.
B A B não contém A.
A B A contém B.

Obs: Os símbolos , , e relacionam Conjunto com Conjunto.

Observações Importantes:
A, qualquer que seja A.
A A, qualquer que seja A.

1.6 Igualdade de Conjuntos


Diz-se que os Conjuntos A e B são iguais quando ambos têm os mesmos elementos,
isto é, qualquer elemento de A é elemento de B e qualquer elemento de B é também elemento
de A.
Exemplos
Se A = {a, b, c, d} e B = { a, c, d, b } então A=B a ordem dos elementos não importa
para a igualdade.
Se X = {a, b, c} e Y = {a, a, b, c, c} então X=Y a repetição de elementos não importa
para a igualdade.

Importante

SE A=B A B e B A

Introdução á Lógica e Técnicas de Programação José Gracioli


7

1.7 Conjunto Universo


No estudo e nas aplicações da Teoria dos Conjuntos, admite-se que todos os conjuntos
devem ser pensados como subconjuntos de um conjunto previamente fixado e ao qual
denomina-se CONJUNTO UNIVERSO que é representado por U ou .

Diagrama de Euler -Venn


É possível pensar nos elementos do
Conjunto Universo representados pelos
pontos interiores de um retângulo e os
A elementos de qualquer de seus
subconjuntos pelos pontos interiores de
U um círculo.

1.8 Conjuntos Numéricos Importantes


Alguns conjuntos numéricos são muito importantes e de enorme utilização no estudo da
Matemática. Os principais deles são:

a) N = Conjunto dos números naturais = { 0, 1, 2, 3, 4, 5,.... }


b) N* = Conjunto dos Naturais exclusive o zero = { 1, 2, 3,...}
c) Z = Conjunto dos números inteiros = { ...,-2, -1, 0, 1, 2,... }
d) Z + = Conjunto dos Inteiros não Negativos = { 0, 1, 2, 3,...}
e) Z - = Conjunto dos Inteiros não Positivos = {...,-2, -1, 0 }
f) Z+* = Conjunto dos números Inteiros Positivos = {1, 2, 3,..}
g) Z-* = Conjunto dos números Inteiros Negativos = {...,-2, -1}
h) Z* = Conjunto dos inteiros não zero = {...,-2, -1, 1, 2,...}
i) Q = Conjunto dos números Racionais = { a / b | a Z e b Z * }
j) Q’ = Conjunto dos números Irracionais.
k) R = Conjunto dos números Reais = Q U Q’

1.9 Operações com Conjuntos

1.9.1 União de Conjuntos ( ).


A U B={x U|x A ou x B}

A B A B A B

U U U

1.9.2 Interseção de Conjuntos ( ).


A B={x U|x A e x B}

A B A
A B B

U U U

Introdução á Lógica e Técnicas de Programação José Gracioli


8

1.9.3 Diferença de Conjuntos ( ).

A – B={x U|x A e x B}

A B
A B A

B
U U U

1.9.4 Complementar de A em Relação ao Universo

A
C U
= A' ={x U|x A}

1.9.5 Complementar de A em relação a B

Sejam A e B dois subconjuntos do Universo U tais


que A B. A diferença B - A é denominada
A “Complementar de A em relação a B” e é indicada
A
B por CB .
A
U C B
=B – A = {x U|x Bex A}

1.9.6 Diferença Simétrica

( ):A B = (A - B) U (B - A)

A B A
A B B

U U U

1.10 Propriedades das Operações com Conjuntos

a) A A = A h) A A=A
b) A = A i) A =
Introdução á Lógica e Técnicas de Programação José Gracioli
9

c) A B A B=B j) A B A B=A
d) A - A = k) A - = A
e) - A= l) (A')' = A
f) '= U m) U' =
g) A' A=U n) A A' =

1.10.1 Comutativas

A B=B A
A B=B A

1.10.2 Associativas

(A B) C=A (B C)
(A B) C=A (B C)

1.10.3 Distributivas

A (B C) = (A B) (A C)
A (B C) = (A B) (A C)

1.10.4 Leis de “DE MORGAN”

(A B)’ = A’ B’
(A B)’ = A’ B’

1.11 Número de Elementos de um Conjunto


n (A B) = n (A) + n (B) – n (A B)
B
+ + + n (A - B) = n (A) – n (A B)
A
+ + + +
+ + + n (A’) = n (U) – n (A)
+
U Observe que: n (A) = 6; n (B) = 7, mas n (A B) = 11
Diferente, portanto de n (A) + n (B) = 13

Se fosse a união de 3 conjuntos seria:


n (A B C) = n (A) + n (B) + n (C) – n (A B) – n (A C) – n (B C) + n (A B C)

1.12 Conjunto das partes de um conjunto A


É o conjunto cujos elementos são todos os subconjuntos de A.

Notação: P(A) = { x | x A }
Exemplo
A = {a , b} P(A) = { {a} , {b} , {a,b} , }

Se A têm n elementos então P(A) terá 2n elementos

Introdução á Lógica e Técnicas de Programação José Gracioli


10

1.13 Exercícios de Conjuntos


1) Assinale no Diagrama o conjunto indicado:
a) (A B)’ c) (A U B) C

A B
A B C

U U

b) (A - B) d) (A B) C

A B
A B C

U U

2) Dados os Conjuntos A = { 0, 1, 2 } e B = { 1, 2, 3, 4 } , determine o Conjunto X tal que


A X={0, 1}, B X={1, 4} e A B X ={0, 1, 2, 3, 4, 5, 6}.

3) Dados os conjuntos A = {1,2,3,4,5} ; B = {2,4,5,6,7} e C = {0,2,3,4,5}


Determinar:
a) (A B) c) (C - B)
b) (A B) (A C) d) (A C) (B C)

4) Assinalar no diagrama o Conjunto indicado:


a) B A’ b) (B A)’

A B A B
U U

c) (A – B) B’ d) (A – B)’ (B C)’

A B A B C

U U

5) Uma pesquisa foi realizada em uma empresa com 500 funcionários, todos ouvidos. Os
resultados obtidos foram os seguintes: a) 120 funcionários lêem o jornal A; b) 98 funcionários
lêem o jornal B; e c) 15 funcionários lêem os dois jornais. Nessas condições, pergunta-se:
Introdução á Lógica e Técnicas de Programação José Gracioli
11

a) Quantas pessoas lêem apenas o jornal A?


b) Quantas pessoas lêem apenas o jornal B?
c) Quantas pessoas lêem apenas um dos jornais?
d) Quantas pessoas não lêem nenhum dos jornais?

6) Numa sala de 630 alunos, 350 deles estudam Português, 210 estudam espanhol e 90
estudam as duas matérias (português e espanhol). Pergunta-se:
a) Quantos alunos estudam apenas português?
b) Quantos alunos estudam apenas espanhol?
c) Quantos alunos estudam português ou espanhol?
d) Quantos alunos não estudam nenhuma das duas matérias?

7) Considere o diagrama e escreva os seguintes conjuntos:

E F
3 7 1
4 9 11
5 8

2 6
G
U 10

a) E, F e G
b) E F
c) F–G
d) (E G) – F
e) (E G)’
f) (E G)’ – (F E)
g) (F – G)’ (E G)’

8) Dado o conjunto A 0, 1, 2, 3 , diga se as proposições a seguir são verdadeiras ou falsa:


( )0 A ( ) {0, 1} A ( ) {{3}} A
( )1 A ( ) {0, 1} A ( ) {3} A
( )1 A ( ) A ( ) {3} A
( ) A ( )3 A ( ) {{3}} A

9) Numa prova constituída de dois problemas, 300 alunos acertaram somente um dos
problemas, 260 acertaram o segundo, 100 alunos acertaram os dois e 210 erraram o primeiro.
Quantos alunos fizeram a prova?

10) Marque no diagrama abaixo os seguintes conjuntos:


a) (( A B ) C )| b) ( A B) (C D )|
c) ( A B) (C D )| d ) (C B) ( B D| )
e) ( A B) (C D) f ) (( A C ) D )|

Introdução á Lógica e Técnicas de Programação José Gracioli


12

A B

C D

11) Numa pesquisa com jovens, foram feitas as seguintes perguntas para que respondessem
sim ou não: Gosta de música? Gosta de esportes? Responderam sim à primeira pergunta 90
jovens; 70 responderam sim à segunda; 25 responderam sim a ambas; e 40 não a ambas.
Quantos jovens foram entrevistados?

Introdução á Lógica e Técnicas de Programação José Gracioli


13

2. Lógica

2.1 O que é Lógica


É essencialmente o estudo da natureza do raciocínio e as formas de incrementar sua
utilização. Poderíamos dizer que é a arte ou a técnica que nos ensina a usar corretamente o
pensamento, isto é, ordenar nossa razão; é o conhecimento das formas gerais e regras do
pensamento correto e verdadeiro, independentemente dos conteúdos pensados; regras para a
demonstração científica verdadeira; regras para os pensamentos não-científicos; regras sobre
o modo de expor o conhecimento; regras para verificação da verdade ou falsidade de um
pensamento.
Exemplo

1. Todo Homem é mamífero.Todo mamífero é animal. Portanto, todo homem é animal.

2. Todo homem é mortal. Sócrates é um homem. Portanto Sócrates é mortal

2.2 Estudo da Lógica Matemática

2.2.1 Noções de Lógica Matemática


A Lógica Matemática é uma ciência exata que só admite margem de erro zero.
Exemplos
Sequência de Fibonacci: 0, 1, 1, 2, 3, 5, ...
Série das potências de 2: 1, 2, 4, 16, 256, 512, 1024, ..

2.2.2 Proposições
É todo conjunto de palavras ou símbolos que exprimem de forma completa um
pensamento de sentido complexo.

Exemplos
A Lua é satélite da Terra.
> 5
1=2

A Lógica Matemática é baseada em dois princípios básicos ou axiomas:

i) Princípio da Não-Contradição: Uma proposição não pode ser verdadeira ou falsa ao


mesmo tempo.

ii) Princípio do Terceiro Excluído: Uma proposição só pode ser verdadeira ou falsa. Por este
motivo a Lógica Matemática também é denominada lógica bivalente.
Exemplos:
Vasco da Gama descobriu o Brasil.
é número racional.

2.2.2.1 Valores Lógicos das Proposições


O valor lógico de uma proposição é verdade se a proposição é verdadeira e falsidade se
a proposição é falsa.

2.2.2.2 Proposições Simples x Proposições Compostas

Introdução á Lógica e Técnicas de Programação José Gracioli


14

Uma proposição é dita simples quando não têm nenhuma outra proposição como parte
integrante de si mesma. Por esse motivo as proposições simples são também denominadas
proposições atômicas. As proposições simples são em geral representadas por letras
minúsculas.
Exemplos
p: Carlos é careca.
q: Pedro é estudante.

Uma proposição é dita composta quando é formada por duas ou mais proposições
simples. Por esse motivo as proposições compostas são também denominadas proposições
moleculares. As proposições compostas são em geral representadas por letras maiúsculas.
Exemplos:
P: Carlos é careca e Pedro é estudante.
Q: Carlos é careca ou Pedro é estudante.

Note nos exemplos acima que as proposições compostas são formadas por duas ou
mais proposições simples cada uma, que por sua vez são relacionadas através de conectivos.
No caso da proposição composta P o conectivo utilizado é da conjunção (equivale ao operador
lógico e), já na proposição composta Q o conectivo utilizado é o conectivo disjunção
(equivalente ao operador lógico ou).

2.2.2.3 Conectivos
São palavras que se usam para formar novas proposições a partir de outras. São
exemplos de conectivos: negação, conjunção, disjunção, disjunção exclusiva, condicional e bi-
condicional.
A seguir serão estudadas as tabelas-verdade dos conectivos básicos da lógica
matemática:

1 - Negação ( )
Dada a proposição simples p, a tabela-verdade da negação é dada por:
p ~p V(~p) = ~V(p)
V F
F V
O conectivo negação é equivalente a palavra não em língua portuguesa.

2 - Conjunção ( )
Dada as proposições simples p e q, a tabela-verdade da conjunção é dada por:
p q p q V(p q) = V(p) V(q)
V V V
V F F
F V F
F F F
O conectivo conjunção é equivalente a letra “e” em língua portuguesa.

3 - Disjunção ( )
Dada as proposições simples p e q, a tabela-verdade da disjunção é dada por:

Introdução á Lógica e Técnicas de Programação José Gracioli


15

p q p q V(p q) = V(p) V(q)


V V V
V F V
F V V
F F F
O conectivo disjunção é equivalente a palavra “ou” em língua portuguesa. Note que o
sentido da palavra ou nesse tipo de disjunção é inclusivo, pois não exclui a possibilidade de
uma ou outra proposição simples ocorrer. Por esse motivo essa disjunção pode também ser
denominada disjunção inclusiva.

4 - Disjunção Exclusiva ( )
Dada as proposições simples p e q, a tabela-verdade da disjunção exclusiva é dada por:
p q p q V(p q) = V(p) V(q)
V V F
V F V
F V V
F F F
O conectivo disjunção é equivalente a palavra ou em língua portuguesa. Note que o
sentido da palavra ou nesse tipo de disjunção é exclusivo.

5 - Condicional ( )
Dada as proposições simples p e q, a tabela-verdade do condicional é dada por:
p q p q V(p q) = V(p) V(q)
V V V
V F F
F V V
F F V
Note que a o fato da primeira proposição p ser verdadeira não implica que a segunda
proposição q tenha que ser também verdadeira. Isso equivale a dizer que o fato da primeira
proposição p ser verdadeira é condição necessária mas não suficiente para que a segunda
proposição q seja verdadeira.

6 - Bi-condicional ( )

Dada as proposições simples p e q, a tabela-verdade do bi-condicional é dada por:


p q p q V(p q) = V(p) V(q)
V V V
V F F
F V F
F F V
Note que a o fato da primeira proposição p ser verdadeira implica que a segunda
proposição q tenha que ser também verdadeira. Isso equivale a dizer que o fato da primeira
Introdução á Lógica e Técnicas de Programação José Gracioli
16

proposição p ser verdadeira é condição necessária e suficiente para que a segunda


proposição q seja verdadeira.

2.2.3 Operações Lógicas Sobre Proposições


Denomina-se cálculo proposicional os resultados e conclusões que podem ser obtidos
através da resolução da tabela-verdade de uma proposição composta. A construção da tabela
verdade será assim feita:
São montadas n colunas, onde n é o número de proposições simples que compõem a
proposição composta que se quer resolver, explorando todas as possibilidades possíveis. Em
n
uma proposição composta de n proposições simples, existem 2 combinações possíveis de
n i
resultados de proposições simples. A coluna i ( onde i ≤ n ) é formada por 2 / 2 valores
verdadeiros e falsos alternados.
Atenção:
- A prioridade entre os operadores lógicos é : 1º Não, 2º E , 3º OU
- Quando houver parênteses resolve-o primeiro
- Da esquerda para direita.
Exemplo
Construir a tabela-verdade da proposição composta P (p,q) = ~ ( p ~q )
p q ~q p ~q ~ ( p ~q )
V V F F V
V F V V F
F V F F V
F F V F V

2.3 Exercícios e Teste de Raciocínio Lógico

I - Nos exercícios de 1 até 10 marque qual a sequência que vem logo após.

1- 1322543210, 1344543210, 1366543210, .....

A) 1388543211 B) 1366543211 C)1388543210 D) 1300543210

2- 1234567890, 6789012345, 1234567890, .....

A) 6789012345 B) 1234567890 C) 2345678901 D) 7890123456

3- 1234678125, 1236784125, 1237846125, .....

A) 1234678126 B) 1234678125 C) 1238467125 D) 1234678251

4- 2938204185, 3938204184, 4938204183, .....

A) 1938204182 B) 5938204182 C) 5938204183 D) 5938204186

5- 5494859485, 5496959406, 5498059427, .....

A) 5494859448 B) 5490159427 C) 5490159448 D) 5494859485

6- 4356787874, 4361787879, 4366787884, .....

Introdução á Lógica e Técnicas de Programação José Gracioli


17

A) 4361787889 B) 4351787889 C) 4377787889 D) 4371787889

7- 4135646789, 2115444769, 6155848709, .....

A) 4135646789 B) 8175040729 C) 0195242749 D) 2115444769

8- 4564310041, 4575533341, 4586756641, .....

A) 4597867741 B) 4597979941 C) 4597978841 D) 4597869941

9- 4594594854, 9594594859, 9894594889, .....

A) 4894594854 B) 4894594884 C) 9874594789 D) 9594594859

10- 3429857414, 3021827314, 3122837415, .....

A) 3220817315 B) 3323847315 C) 3428807315 D) 3223847516

Respostas:
1=C 2=A 3=C 4=B 5=C 6=D 7=A 8=B 9=B 10=D

II – Resolva as seguintes proposições lógicas

A B (A B) C (A B) C (A B ) (B C) A B
A B C

F F F
F F V
F V F
F V V
V F F
V F V
V V F
V V V

Introdução á Lógica e Técnicas de Programação José Gracioli


18

3. Algoritmos

3.1 Definição
É uma sequência finita de ações que descrevem como um problema deve ser resolvido;
É uma sequência ordenada, sem ambiguidade de passos que levam à solução de um dado
problema; É a descrição de um padrão de comportamento, expressado em termos de um
repertório bem definido e finito de ações “primitivas”, das quais damos por certo que elas
podem ser executadas.

Exemplos de Algoritmos do nosso dia a dia:


Receitas culinárias
Instruções de Montagem de um brinquedo.

3.2 Algoritmos Estruturados


Quando queremos resolver um problema utilizando um computador, a sequência de
passos que conduzem à solução é detalhada até que se chegue a um conjunto de ações
primitivas que chamamos de comandos ou instruções, que podem ser entendidas e
executadas pela máquina. Este algoritmo no maior nível de detalhamento possível, quando
“traduzido” para uma linguagem de programação, constituirá um programa. Uma das
vantagens de se programar utilizando um algoritmo é que a partir dele o programador pode
implementá-lo em qualquer linguagem de programação que conheça.
A programação estruturada ou o desenvolvimento de algoritmos estruturados consiste
na utilização de técnicas que permitem a sistematização do desenvolvimento, que simplificam
bastante a solução de problemas grandes e complexos, mas que podem também ser utilizados
para algoritmos mais simples. Objetivos dessas técnicas são:
Facilitar o desenvolvimento e representação de algoritmos;
Facilitar a leitura e o entendimento dos algoritmos pelas pessoas;
Antecipar a comprovação de sua correção;
Facilitar a manutenção (correções e modificações) dos programas e algoritmos;
Permitir que o desenvolvimento de algoritmos pudesse ser empreendido
simultaneamente por uma equipe de pessoas.

Para isso os algoritmos estruturados são desenvolvidos levando-se em conta três premissas
básicas.

1) Desenvolver algoritmos do geral para o particular, por refinamentos sucessivos


(desenvolvimento “top-down”).
2) Decompor os algoritmos em módulos funcionais, organizados de preferência em um sistema
hierárquico. Esses módulos trazem vantagens adicionais: para o desenvolvimento, pois
cada módulo poderá ser desenvolvido por um programador/analista diferente; para teste,
pois testa-se um módulo de cada vez independentemente.
3) Dentro de cada módulo utilizar alguns poucos e bem definidos comandos e estruturas de
controle.

Exemplo: Uma consulta num caixa Eletrônico.


Inicio
Execute Apresentação
Execute Pesquisa
Execute Finalização
Fim

Introdução á Lógica e Técnicas de Programação José Gracioli


19

Apresentação Pesquisa
Inicio Inicio
Execute Tela Inicial Execute Operação desejada
Execute Senha Execute Outro Serviço
Execute Menu Fim
Fim

Finalização
Inicio
Execute Impressão/Dinheiro
Fim

3.3 Programas
É um conjunto de instruções ordenadas logicamente escritos em uma linguagem de
programação a serem interpretadas e executadas pelo computador. Essas instruções são
representadas por um conjunto de símbolos armazenados na memória do computador.

3.4 Técnicas Usadas para Desenvolver os Algoritmos:


Os algoritmos podem ser representados de diversas formas gráficas, a saber:
Fluxogramas (Hoje em dia em desuso)
Diagramas de Nassi-Shneiderman
Pseudo-Código: Aqui não tem os inconvenientes da ambiguidade de uma língua e nem os
rigores da sintaxe de uma linguagem de programação, e, por isso, é também bastante
recomendada.

3.5 Tipos de Dados


Tudo em informática é baseado na manipulação de Informações, que podem ser
classificadas em vários tipos de dados:

3.5.1 Dados Numéricos


Os dados numéricos são representados pelos números Inteiros e Reais:
Inteiro: qualquer número inteiro positivo ou negativo: (...,-1, 0, -1....).
Real: qualquer número real: (-5, 30.9, 0, 23, -345.62).

3.5.2 Dados Literais


É constituído por uma sequência de caracteres contendo letras, dígitos e/ou símbolos
especiais. Esses dados são conhecidos como String, alfanuméricos ou cadeia de caracteres.
São representados entre aspas ( “” ).
Exemplos
“Engenharia de Produção” Literal de comprimento 22
“ Página” Literal de comprimento 8
“” Literal de comprimento 1
“123” Literal de comprimento 3

3.5.3 Dados Lógicos


Esses dados são muitas vezes chamados de Booleanos, Só poderá assumir dois
valores: V (Verdadeiro) e F (Falso).

Exercícios
Marque nos parênteses com as respectivas letras: Se for I tipo de dado Inteiro, R tipo de
dado Real, L tipos de dados literais e B tipos de dados Booleanos e X com os tipos de dados
que não podemos classificar.
Introdução á Lógica e Técnicas de Programação José Gracioli
20

( ) 123 ( ) V ( ) reti” ( ) Casa


( ) “.F.” ( ) “ m12” ( ) .V. ( ) .F
( ) “Mar” ( ) -0.0 ( ) “......” ( ) “.F>>>”
( ) “-0.0” ( ) -1.000 ( ) -12 ( ) 23.98

3.6 Constantes
É um identificador que armazena um valor fixo e imutável, durante toda a execução do
algoritmo. As constantes dos tipos caracteres serão colocadas entre aspas ( “” ).

Ex: PI = 3,14
NOME = “Maria Catarina”

3.7 Variáveis
Como o próprio nome diz essa informação poderá ser alterada em um dado instante.
Exemplo: Índice da Bolsa de Valores, Cotação do Ouro etc.

3.8 Identificadores
É um conjunto de caracteres (letras, números ou símbolos). Devem-se observar alguns
pontos na construção desses identificadores:
1º Devem começar por caracteres alfabéticos;
2º Podem ser seguidos por mais caracteres alfabéticos e/ou numéricos;
3º Não é permitido o uso de caracteres especiais;
4º Os caracteres alfabéticos deverão ser escritos em maiúsculos ou minúsculos, mas deve ser
mantida uma padronização.

Ex: SOMA - identifica a soma de determinados números


MEDIA - identifica a média de um conjunto de números ( idades, pesos, etc.).

Exercícios
Marque com V os identificadores válidos e com F os identificadores inválidos.
( ) OMEGA ( ) 3D/P
( ) VB67 ( ) 3P
( ) R]F ( ) MEMO
( ) R/F ( ) DIOGO@
( ) E908R ( ) FAVO

3.9 Declaração de Variáveis


Sempre no início do algoritmo deverão ser declaradas todas as variáveis que forem ser
utilizadas no algoritmo para que quando codificarmos em uma linguagem, o compilador possa
reservar um espaço na memória para as mesmas. Será feita da seguinte forma:

VAR
<nome da variável> : <tipo da variável>
Onde o nome da variável poderá ser uma lista de variáveis caso elas sejam do mesmo tipo.

Atenção
1- A palavra VAR deverá ser utilizada sempre e uma única vez.
2- Quando for definida uma ou mais variáveis do mesmo tipo serão separadas por vírgulas.
3- Tipos diferentes de variáveis serão declaradas em linhas diferentes.

Introdução á Lógica e Técnicas de Programação José Gracioli


21

Exemplo VAR
NOME : Literal[30]
IDADE : Inteiro
PROFISSAO : Literal[15]
SALARIO : Real

3.10 Operadores
São elementos funcionais que atuam sobre determinados operandos produzindo
determinados resultados. Eles classificam-se em:

3.10.1 Operadores Aritméticos


É um conjunto de símbolos que representam as operações matemáticas. São eles:
+ soma
- subtração
* multiplicação
/ divisão
** exponenciação ( Em pascal : 23 Exp(3*Ln(2)) )

OBS: Também usaremos os operadores: MOD e DIV


m mod i (resto): Fornece o resto da divisão inteira de m por i.
m div n (quociente): Fornece o quociente inteiro da divisão de m por n.
Ex: 2 + 2 = 4
3 ** 2 = 9
15 mod 6 = 3
15 div 6 = 2
Exemplo Mod/Div
Program Exemplo_Mod_Div;
Var
num:integer;
Resto,Divi:Integer;
Begin
Write('Digite um número : ');
Readln(Num);
Resto:=Num mod 3;
Divi:=Num div 3;
Writeln(Resto,' ', Divi);
Readkey;
End.
Saída:
Digite um número : 7 Digite um número : 2 Digite um número : -7
1 2 2 0 -1 -2

Digite um número : -2 Digite um número : -5


-2 0 -2 -1

Obs: Imagine que a divisão fosse por -3 isto é: resto:=Num mod -3 e Divi:=Num div -3
Saída:
Digite um número : 7 Digite um número : 2 Digite um número : -2
1 -2 2 0 -2 0
Digite um número : -14 Digite um número : -7 Digite um número : -3
-2 4 -1 2 0 1

Introdução á Lógica e Técnicas de Programação José Gracioli


22

Prioridades

Parênteses mais internos


Pot, raiz
* / div mod
+ -

3.10.2 Operadores Relacionais


São operadores usados para fazer a comparação entre variáveis de mesma natureza,
ou seja, do mesmo tipo de dado. O resultado sempre será um valor lógico Booleano ( V ou F ).
São eles:

Operador Função
= Igualdade
<> Diferente
> Maior
>= Maior igual
< Menor
<= Menor igual

Exemplo
Seja A=45 e B= 35
A>=B Verdadeiro
A> B Verdadeiro
B>A Falso
B<>A Verdadeiro

3.10.3 Operadores Lógicos


São operadores usados em expressões lógicas cujo resultado da avaliação será V (
verdadeiro) ou F ( falso). São eles: AND, OR XOR e NOT .

3.11 Expressões Matemáticas

3.11.1 Expressões Aritméticas


São expressões cujo resultado é um valor inteiro ou real.
Exemplo
Sejam A, B valores Inteiros e C, D valores Reais, então:
A + B = terá como resultado um valor Inteiro
A + B * D = terá como resultado um valor Real
A / C = terá como resultado um valor Real.
Atenção: A prioridade na execução será:
1º Parênteses mais internos
2º Funções matemáticas
3º Prioridade da esquerda para a direita
4º Inversão do sinal ( - para + )
5º Exponenciação ( ** )
6º Multiplicação e Divisão ( * e / )
7º Adição e Subtração ( + e - )

3.11.2 Expressões Lógicas e Relacionais


São expressões cujos operadores são relacionais e/ou lógicos e cujos operandos são
relações e/ou variáveis e/ou constantes do tipo lógico.
Atenção: A prioridade na execução será:
Introdução á Lógica e Técnicas de Programação José Gracioli
23

1º Parênteses mais internos


2º Funções matemáticas
3º Operadores aritméticos
4º Operadores relacionais
5º Operadores lógicos

3.11.3 Expressões Literais


São aquelas cujo resultado da avaliação é um valor literal.
Exemplo
A concatenação de Dados Literais (Strings).

Se, A = “Casa” B=“” C = “Velha” então:

A + B + C = “Casa Velha”

3.12 Funções Matemáticas


As funções matemáticas quando usadas nos algoritmos podem ser representadas
como:
Log( x ) : logaritmo de um numero na base 10.
Raiz( x ) : Calcula a raiz quadrada de um número.
Int ( x ) : a parte inteira de um número fracionário.
Frac( x ) : a parte fracionária de x.
Abs ( x ) : Valor absoluto de x.

Exercícios:
1 - Marque V ou F se os identificadores são ou não válidos:
( ) $ret ( ) UH! ( ) JOSÉ
( ) B567 ( ) RET1 ( ) TEMA&1
( ) P[oi] ( ) 12ROP ( ) TEMA2
( ) O2O ( ) XPTO ( ) AL PO

2 - Seja A = 6 , B = 2 C = 1,6 , D = “Meta” , E = “Info” coloque V ou F nas expressões abaixo.

( ) A >= C+B ( ) A**B >= B**A ( ) (B *2 <> 0) E ( A<>B)


( ) D+E = “MetaInfo” ( ) C+ B <= B**5 ( ) Não( C+5 > B**4)
( ) C <> B*4,5 ( ) (B div 3 <> 0) OU ( A<>C) ( ) Raiz( B**4) <> 4
( ) Raiz(A**2) = B ( ) Não( A<B*4) ( ) Não( A>B**4)
( ) A mod B = 3 ( ) E+D = “Infometa” ( ) C+ B = B**2
( ) A div B = 3 ( ) Raiz( B**4) = 4 ( ) abs (A/B) = 3
( ) (A*B) div 3 = 4 ( ) A mod 8 = 0 ( ) 4 + B <> 6
( ) frac ( C ) = 0,6 ( ) (B div 2 <> 0) OU ( A<>B) ( ) E+D = “InfoMeta ”
( ) Int ( C ) = 1 ( ) abs (A/B) = -3 ( ) C*6 >= C + 67
( ) E+D = “ InfoMeta” ( ) (abs (A/B) = -3) E (A+2= 8) ( ) A/2 <= B/2

3.13 Comandos de atribuição


Serve para atribuir um valor a uma variável, usaremos o símbolo ou =

3.14 Comandos de Entrada e Saída de Dados

Entrada: Ler (variável) ; Ler(arq, registroalu) quando for lido de um arquivo.


Saída: Escreva (variável), Escreva (Registroalu, Nome, Idade) quando for impresso
o conteúdo de um registro.

Introdução á Lógica e Técnicas de Programação José Gracioli


24

Exemplo:
Inicio
Ler(NOME)
Ler(IDADE)
Escreva(“ O Nome é = ”, NOME)
Escreva(“A Idade é = ”, IDADE)
Fim
3.15 Documentação
A documentação é uma etapa muito importante e deve ser feita desde o inicio até o final
do desenvolvimento do projeto. Devemos ter em mente alguns princípios básicos:
1º Ao criar constantes e variáveis devemos utilizar nomes significativos e comentá-las
2º Usar a indentação, para mostrar a estrutura e sequência dos comandos.
3º Documentar as rotinas e fazer um dicionário de dados que especifique o conteúdo de
cada variável ou constante.

Exemplo
Será colocado entre chaves( { } ) ou da seguinte forma :(*.....*)
(* somatot é a soma das idades dos alunos *}
{ num - representa o código de cada produto }

3.16 Estruturas Básicas de Controles

3.16.1 Sequência
É um grupo de comandos executados um após o outro.

Fluxograma Pseudo-Código NS
Inicio
Comando 1 Comando 1
comando 1
comando 2 Comando 2
Comando
. 2 .
comando n .
Comando Fim
Comando n
n
Exemplo
Inicio
x=1
y = 127
d=x* y
Escreva ( x, y, d )
Fim

3.16.2 Seleção
Também chamada de estrutura de decisão ou de processamento condicional. A
estrutura de seleção é utilizada quando a execução de um comando ou uma sequência de
comandos depende de um teste anterior (uma ou mais comparações). A seleção pode ser
simples ou composta.

3.16.2.1 Seleção Simples


Quando a execução de um ou vários comandos depender de uma condição verdadeira,
e não há comandos a executar se a condução for falsa.

Introdução á Lógica e Técnicas de Programação José Gracioli


25

Fluxograma Pseudo Código NS


Inicio Condição
Condição SE Condição Então V
Comando 1
Comando 1
V Comando 2 .
Comando 1 : .
Fim-SE Comando n
Comando n Fim

Exemplo
Faça um algoritmo que leia dois números inteiros e escreva ambos os números, se o 1º
for divisível pelo 2º:

Programa Exemplo
var
Num1, Num2: Inteiro
Inicio
Leia (Num1)
Leia (Num2)
SE Num1 mod Num2 = 0 Então
Escreva (Num1)
Escreva (Num2)
Fim-SE
Fim

3.16.2.2 Seleção Composta


Se a condição for Verdadeira executa um ou mais comandos e se for falso também
executará um ou mais comandos.

Fluxograma Pseudo-Código NS

V F Inicio Condição
Condição V F
SE Condição Então
Comando 1 Com 1 Com 1
Comando 2 . .
Senão . .
Comando 1 Comando 1 Comando 1 Com n Com n
Comando 2
Comando n Comando n Fim-SE
Fim

Exemplo
Faça um algoritmo que leia dois números inteiros e escreva o maior deles. Assumir que não
podemos entrar com números iguais.

Introdução á Lógica e Técnicas de Programação José Gracioli


26

Programa exemplo
Var
Num1, Num2: Inteiro.
Inicio
Leia (Num1)
Leia (Num2)
SE Num1 > Num2 Então
Escreva (“O maior nº é:”, Num1)
Senão
Escreva (“O maior nº é: ”, Num2)
{ Escreverá o Num2 se forem iguais}
Fim-SE
Fim

Exercícios

1 - Fazer um algoritmo que leia um nº inteiro e escreva-o se for diferente de zero.

2 - Fazer um algoritmo que leia dois números inteiros. Escreva a soma dos números se o 1º for
maior que o 2º, escreva o produto se o 2º for maior que o 1º, e escreva um deles se os
números forem iguais.

3 - Fazer um algoritmo que leia 3 números inteiros e escreva a soma deles.

4 - Fazer um algoritmo para calcular e escrever a área (S) de um triângulo de base b (real) e
altura h(real). (S = b * h / 2).

5 - Fazer um algoritmo para calcular e escrever a área (S) de um quadrado de lado l(real),
onde a área é dada por S = l2 .

6 - Fazer um algoritmo para calcular e escrever a raiz da equação do 1º grau, do tipo:


A * X + B = 0.

7 - Fazer um algoritmo que leia dois valores inteiros e escreva qual dos dois é o maior deles.
Se os números forem iguais deve ser dada uma mensagem: ”Iguais”

8 - Fazer um algoritmo que leia três valores inteiros e escreva o maior deles. Considere que
não poderá ter números iguais. Deverá ser usado o encadeamento de “SE”

9 - Fazer um algoritmo que determine se o número inteiro lido é divisível por 23.

10 - Fazer um algoritmo que leia um número inteiro e escreva-o se ele for par ou se ele for
ímpar.

11 - Fazer um algoritmo que leia um nº inteiro e escreva se ele é par e maior do que 50 ou se
ele é ímpar menor que 39.

12 - Fazer um algoritmo que leia A, B, e C os três coeficientes de uma equação do 2º grau.


Pede-se: Calcule o determinante e escreva se a equação possui 2 raízes reais e iguais, ou 2
raízes reais e diferentes ou não existe raízes. Logo após deverá ser calculada e exibida as
raízes da equação quando existir.

Introdução á Lógica e Técnicas de Programação José Gracioli


27

13 - Fazer um algoritmo que leia 3 números quaisquer. Pede-se Calcular o produto e a Soma
destes números e imprimir qual dos dois resultados é maior. Se a Soma for igual ao produto
deverá ser impressa a mensagem: “Soma e Produto são iguais”.

14 – Fazer um algoritmo que leia o nome e três notas de um determinado aluno e ao final
imprimir se ele está aprovado ou reprovado. O critério para aprovação é média maior ou igual a
7,0.

15 – Fazer um algoritmo que leia o nome, o Salário bruto, e a quantidade de filhos de um


determinado funcionário. Pede-se: Escrever o Nome, o Desconto do INSS, o Salário Família e
o Salário Liquido. O desconto do INSS será de 8% se o funcionário ganhar um salário bruto de
até R$ 800,00(inclusive), de 12% se ganhar entre R$ 800,00 e R$ 2000,00(inclusive) e de 20%
se for acima de R$ 2000,00. O Salário família será acrescido pelo número de dependente (R$
12,00 por dependente).

16 – Fazer um algoritmo que leia as três medidas de um triângulo, escreva se o mesmo é


escaleno (todos os lados diferentes), isósceles (dois lados iguais) ou equilátero (todos os lados
iguais). Considere que as medidas são válidas para formar um triangulo.

17 – Fazer um algoritmo para calcular o preço pago por uma conta telefônica, para isso você
terá que ler o número de minutos gastos com ligações comuns e também com ligações para
celulares. O cálculo será feito da seguinte forma: até 200 minutos o usuário pagará R$ 45,00
de tarifa básica; até 240 minutos o usuário pagará a tarifa básica mais R$ 0,10 por minuto
excedente; até 540 minutos o usuário pagará a tarifa básica, mais R$ 0,15 por minuto
excedente e mais uma alíquota de 10% somente sobre os minutos excedentes. Acima de 540
minutos, o usuário pagará a tarifa básica, mais R$0,20 por minuto excedente e mais 15% de
alíquota sobre os minutos excedentes. Para ligações de celulares o preço será de R$ 0,95 por
minuto mais uma alíquota de 22% sobre o total de minutos gastos. Você deverá imprimir
discriminadamente o total gasto com ligações simples, o total com ligações de celulares e um
total da conta.

3.16.3 Repetição
Quando um conjunto de ações é executado repetidamente enquanto uma determinada
condição (expressão lógica) permanece verdadeira. Dependendo do resultado do teste da
condição, o conjunto de comandos poderá não ser executado nem uma vez (se for falsa no 1º
teste), ou várias vezes (Enquanto for Verdadeira). Chama-se isso de laço (LOOP).

Fluxograma Pseudo-Código NS

F Inicio
CONDIÇÃO CONDIÇÃO
Enquanto Condição Faça
V Comando 1 Comando 1
Comando 1
Comando 2
: Comando 2
.
:
. Comando n :
Comando n Fim-Enquanto :
Fim
Comando n

Exemplo

Introdução á Lógica e Técnicas de Programação José Gracioli


28

Faça um algoritmo que leia n números e ao final escreva a soma deles. Para finalizar
basta que digite o número zero.
Programa Exemplo
Var
Soma:Inteiro
Num: Inteiro
Inicio
Leia (Num)
Soma = 0 (* Variável que soma de todos os número lidos *)
Enquanto Num <> 0 Faça
Soma = Soma + Num
Leia (Num)
Fim-Enquanto
Escreva (“A soma dos valores é :”, Soma)
Fim

Exercícios

1 - Fazer um algoritmo que leia 10 números inteiros e ao final escreva a soma, a média
aritmética e a média geométrica dos números.

2 - Fazer um algoritmo para escrever na tela os números de 1 até 20.

3 - Fazer um algoritmo para imprimir na tela o quadrado dos números de 1 até 20.

4 - Fazer um algoritmo para imprimir na tela o quadrado dos números ímpares compreendidos
entre(compreende os limites) 1 e 100.

5 - Fazer um algoritmo que leia 30 registros contendo cada um: Nome, Idade, Sexo e duas
notas(P1 e P2). Deverá ser escrito uma lista contendo o Nome, sexo e a média do aluno. Ao
final escreva: A média das idades, o total de pessoas do sexo masculino e o total de pessoas
do sexo feminino.

6 - Fazer um algoritmo para imprimir os 50 primeiros números pares.

7 - Fazer um algoritmo que leia 20 números inteiros e escreva o menor deles.

8 - Fazer um programa para gerar e imprimir a série 1, 5, 9, 13, 17,.....n. Imprimir a soma deles
até o 50º termo(inclusive).

9 - Fazer um algoritmo que leia 30 temperaturas de uma determinada cidade, isto é, cada dia é
fornecida a temperatura média daquele dia. Pede-se imprimir a menor e a maior temperatura
ocorrida naquele mês.

10 - Faça o exercício 14 da lista anterior, supondo que existe uma turma de 45 alunos. Deverá
ser calculada a média da turma, além do que agora deverá ser lido também o sexo do aluno
(M – Masculino e F – Feminino) deverá ser impresso, ao final, o nome e o sexo do aluno de
maior média e também quantos alunos foram reprovados e quantas alunas foram aprovadas.

11 - Fazer um algoritmo que leia 20 números inteiros e escreva o menor e o maior deles.

Introdução á Lógica e Técnicas de Programação José Gracioli


29

1 1 1 1
12 - Fazer um algoritmo que imprima a série , , , ,..... até o 56º elemento.
2 4 16 256

1 3 5
13 - Fazer um algoritmo que escreva a soma da série , , ,..... até o 45º elemento.
2 4 6

14 - Fazer um programa que calcule e imprima a soma da série até o 20º elemento.
1 3 1 5 0 1 2 3 4
1, , , , ,.... . Dica Denominador 4 , 4 , 4 , 4 , 4 ,....E numerador números sequenciais.
2 16 16 256

15 - Calcule o fatorial de um nº lido até 12. Deverá ser verificado se o número lido não está
acima de 12. Ex.: 5! = 5.4.3.2.1= 120.

16 - Uma coleção de 30 bolas numeradas de 1 a 30 e coloridas (azul, verde, vermelha e preta)


estão dentro de uma urna. Vamos retirando uma a uma e contabilizando. Pede-se:
Total de bolas vermelhas
Total de bolas azuis e Pares
Total de bolas verdes ou ímpares.
Total de bolas retiradas.
O algoritmo termina quando for retirada uma bola preta. As bolas pretas não têm numeração e
não são contabilizadas.

17 - Fazer um programa que calcule e imprima a soma da série até o 10º elemento.
10 3 4 1
0, 1, , , , ,.... .
25 25 125 125

18 - O setor imobiliário é um segmento do mercado responsável por um grande volume de


transações e por um importante significado social. A imobiliária XYZ contratou você para
desenvolver um algoritmo que controla os imóveis de sua carteira. Cada imóvel quando
registrado na imobiliária consta dos seguintes itens: Código do imóvel (um número inteiro
sequencial de 1 a 50), Tipo do imóvel (C – Casa, A – Apartamento), metragem, número de
quartos, número de banheiros, existência de garagem(S – sim ou N – não), a condição do
imóvel (1 – efetivamente alugado, 2 – para ser alugado, 3 – efetivamente vendido 4 – a ser
vendido) e o preço. O programa termina quando for digitado zero no código do imóvel.No final
do mês o dono da imobiliária precisa saber:

a) Total de imóveis para serem alugados


b) Total de casas que estão efetivamente alugadas
c) Total de apartamentos que estão efetivamente alugados
d) Total de imóveis que estão à venda;
e) Quantos apartamentos tem garagem?
f) Quantidade de faturamento bruto de aluguel do mês
g) Quanto que a imobiliária retirou com a comissão de vendas(5% sobre o preço do
imóvel).
h) Total de casas com 2 ou mais banheiros

19 - O padrão de comportamento de uma sequência de números é: A partir do terceiro termo


(inclusive) cada termo é obtido somando-se os dois termos antecedentes. A sequência será:
1, 1, 2, 3, 5, 8, 13, 21, ... . Lembrando que o total de termo é lido através da variável N . Pede-
se: Imprimir a série e a soma dos elementos.

Introdução á Lógica e Técnicas de Programação José Gracioli


30

OBS: Num algoritmo muitas vezes precisamos usar um artifício para sabermos quando termina
um arquivo, nesse caso iremos usar um sinalizador chamado FLAG, ele geralmente sinalizará
que é fim de arquivo e sairá do LOOP.

3.16.4 Repetição com uma variável de Controle


É uma estrutura semelhante a repetição, a diferença é que aqui é necessário saber a
priori o número de vezes que será executado o LOOP. A vantagem desse sobre o anterior é
que dispensa a inicialização e modificações de variáveis de controle do LOOP, isso será feito
automaticamente, além do valor do incremento do índice ser definido pelo programador.
Formato:
Variando CONT de LI a LF [Passo P], Faça
comando1
comando2
:
Fim Variando

Obs: As representações do Fluxograma e NS são o inverso da representação de Repetição


CONT : é a variável de controle do laço, isto é, o número de vezes que o laço está sendo
executado;
LI : é o limite inferior da variável de controle; o inicio da contagem;
LF: é o limite superior da variável de controle; o fim da contagem;
P: é o passo entre dois valores de CONT; podendo ser positivo(1, 2,...) ou negativo ( -1, -2,..)
e também é opcional.

Exemplo:

Faça um algoritmo que escreva todos os números ímpares entre 1 e 60.


Programa exemplo
Var
I : Inteiro
Inicio
Variando I de 1 a 60 passo 2 Faça

Escreva ( I )
Fim Variando
Fim

Exercícios

1 - Faça um algoritmo que escreva 30 vezes o nome e a sua idade.

2 - Faça um algoritmo que escreva os números de uma P.A., sabendo que o 1º termo é 1 e o
último termo é 31 e sua razão é 3. Ao final escreva a quantidade de números da P.A .

3 - Faça um algoritmo para imprimir os 50 primeiros números naturais inteiros em ordem


decrescente.

4 - Faça um algoritmo que escreva os 30 primeiros números impares.

5 - Faça um algoritmo que escreva todos os múltiplos de 3 ou de 7 entre 20 e 100.

Introdução á Lógica e Técnicas de Programação José Gracioli


31

6 - Faça um algoritmo que escreva todos os anos em ordem decrescente até o ano de seu
nascimento.

7 - Faça um algoritmo que escreva todas as potências (de 2) dos números pares de 1 até 100
(inclusive).

8 - Faça um algoritmo que escreva a raiz quadrada de todos os números ímpares de 1 até 167.

9 - Faça um algoritmo para escrever os 30 primeiros números primos

10 - Faça um algoritmo que escreva os números pares maiores que 50 e menores que 349.

11 – Faça um algoritmo que escreva as letras do alfabeto de forma decrescente

3.16.5 Seleção dentre Múltiplas Alternativas


Quando uma variável puder assumir vários valores pré-definidos.

Fluxograma Pseudo-Código NS

Inicio Id = 1 expressão
Condição
Conforme Id = 2
Caso ident = 1 Senão
Senão comando 1 Id = n
Caso ident = 2
C1 C2 Cn comando 2
:
Senão com 1 com2 com n com n+1
comando n
Fim Conforme
Fim

OBS.: É muito útil esse comando quando estamos trabalhando com subrotinas dentro de um
algoritmo

Exemplo:
Imagine um arquivo contendo Nome, Salário, Classe. Caso o funcionário seja da classe
A seu desconto será de 10% para o INSS, se for classe B seu desconto será de 8%, se for
classe C será 6% de outra classe o desconto será Nulo.

Inicio
Leia ( arqfun, Nome, Salario, Classe)
Conforme
Caso Classe =”A” desconto = Salario * 10%
Caso Classe = “B” desconto = Salario * 8%
Caso Classe = “C” desconto = Salario * 6%
senão desconto = 0
Fim Conforme
Escreva ( “O desconto é : ”, desconto )
Fim

Exercícios

Introdução á Lógica e Técnicas de Programação José Gracioli


32

1 - Faça um algoritmo que leia de 100 números. Ao final escreva a soma dos números pares, a
soma dos números ímpares e maior soma dentre elas. Deverá ser impresso cada número par
lido. Usar o comando CASE.

2 - Escreva um algoritmo que leia um arquivo de uma turma contendo 5 registros, onde cada
um contém:
Nome
Altura
Sexo ( M, F )
Pede-se:
- Escreva a menor altura das meninas e seu nome;
- Escreva a maior altura entre os meninos e seu nome;
- Escreva a média de altura da turma.

3 - O movimento do mês de uma empresa foi registrado em 30 operações onde cada uma
contém:
Valor
Data da transação
Tipo (D - débito, C - Crédito).
Pede-se:
Escreva o Valor e o tipo de transação
Escreva o Total de débitos da empresa no mês
Escreva o total de Créditos da empresa no mês
Escreva o Resultado final: Se a empresa teve ou não lucro e de quanto foi

4. Estrutura de Dados Agregados Homogêneos: Vetores e Matrizes

4.1 Vetores

Um vetor ou agregado homogêneo, ou ainda uma variável composta homogênea, é uma


estrutura de dados que contém elementos do mesmo tipo, que podem ser referenciados como
um todo. Da mesma forma que os registros, ao declararmos um valor, estamos reservando na
memória principal do computador uma série de células para uso da variável desse tipo. O
nome do vetor aponta para a base das células e o seu índice dá a posição relativa do elemento
referenciado ao primeiro.
Exemplo
NUM(I)

32 87 5 34 4 5 123 23 58 94 13 0
onde,
NUM = é o nome do vetor
I = é o índice do vetor que varia de 1 até 12

NUM(4) = 34, NUM (7) = 123 e assim por diante.

Obs.: O índice do vetor poderá começar com o valor zero(0)

Declaração de Vetores:

Tipo
Num = vetor[1..12] de Inteiros
Var
Introdução á Lógica e Técnicas de Programação José Gracioli
33

Vetnum : Num

Exercícios
1 - Fazer um algoritmo que leia um vetor com 50 posições inteiras e escreva a soma de seu
conteúdo.

2 - Fazer um algoritmo que a partir de um vetor de 100 posições inteiras positivas, escreva o
conteúdo das posições pares e ao final escreva a soma das posições ímpares.

3 – Faça um algoritmo que leia um vetor de 30 posições de caracteres e ao final imprima:


Quantas vezes a palavra “LUA” aparece nesse vetor.
O Total de vogais de vogais desse vetor.

4 - Faça um algoritmo que leia um vetor de 50 posições de números inteiros positivos. O


algoritmo consiste em ordenar o vetor de forma crescente. Deverá ser usada somente uma
estrutura de vetor.

4.2 Matrizes
São estruturas de dados similares ao vetor (agregados homogêneos), com a diferença
que podem ter várias dimensões. Cada célula da matriz será indicada pelo nome e tantos
índices quantas forem as dimensões da matriz. No nosso curso trabalharemos só com duas
dimensões, mas nada impede de ter mais.

4.2.1 Definição
Exemplo
2 5 7 4 8
Ai x j = 9 3 7 8 2
3 5 3 7 2
6 6 4 1 0 4 x5

A representação anteriormente é uma matriz e cada número dentro da matriz é


chamado de elemento da matriz. A matriz pode ser representada entre parênteses ou entre
colchetes. No exemplo a matriz A é do tipo 4 x 5 ( quatro por cinco), isto é, 4 linhas por 5
colunas
Onde, i = Linha da matriz
j = Coluna da Matriz

Para indicarmos a ordem da matriz, dizemos primeiro o número de linhas e, em seguida,


o número de colunas.
Exemplo
2 4 1
matriz de ordem 2 x 3 ( 2 Linhas e 3 colunas)
4 7 3

1 9 4 matriz de ordem 1 x 3 ( 1 Linha e 3 colunas)

4.2.2 Representação Algébrica


Utilizamos letras minúsculas para indicar matrizes genéricas e letras maiúsculas
correspondentes aos elementos. Algebricamente a matriz pode ser representada por:

Introdução á Lógica e Técnicas de Programação José Gracioli


34

a11 a12 a13  a1n


a21 a22 a23  a2 n
A a31 a32 a33  a3n
    
am1 am 2 am 3  amn mxn

com m e n *
. Como o A é bastante extenso podemos representar por A (aij ) m x n
a11 ( Lê-se a um um ) elemento localizado na 1ª Linha e 1ª Coluna
a12 ( Lê-se a um dois ) elemento localizado na 1ª Linha e 2ª Coluna

4.2.3 Matriz Quadrada


Se o número de linhas de uma matriz for igual ao número de colunas, a matriz é dita
Quadrada.

1 4
Ex.: A é uma matriz de ordem 2
3 4
1 3 7
B 3 6 7 é uma matriz de ordem 3
4 5 2

Observações:
Quando uma matriz tem todos os seus elementos iguais a zero, dizemos que é uma matriz
nula.
Os elementos aij onde i = j, formam a diagonal principal.

a11 a12 a13  a1n


a21 a22 a23  a2 n
A a31 a32 a33  a3n
    
am1 am 2 am 3  amn mxn

Diagonal Secundária Diagonal Principal

4.2.4 Matriz Unidade ou Identidade

A matriz quadrada de ordem n, em que todos as elementos da diagonal principal são


iguais a 1 (um) e os demais elementos iguais a 0 (zero) é denominada matriz identidade.
Representação: In

1 0 0
In 0 1 0
0 0 1

Introdução á Lógica e Técnicas de Programação José Gracioli


35

4.2.5 Matriz Transposta


Se A é uma matriz de ordem m x n , denominamos transposta de A a matriz de ordem n
x m obtida pela troca ordenada das linhas pelas colunas.

Representação : At
Exemplo

1 3 9 1 3 6
A 3 5 4 então a transposta será A t
3 5 5
6 5 0 9 4 0

4.2.6 Operação com Matrizes

4.2.6.1 Adição e Subtração


A adição ou a subtração de duas matrizes A e B, efetuada somando-se ou subtraindo-
se os seus elementos correspondentes e deverá ter a mesma dimensão.
Exemplo
1 8 2 2
Seja A e B então
4 5 3 4

1 8 2 2 3 10
A B
4 5 3 4 1 9

1 8 2 2 1 6
A B
4 5 3 4 7 1

4.2.6.2 Multiplicação
Na multiplicação de duas matrizes A e B, o número de colunas de A tem que ser igual
ao número de linhas de B ; O produto AB terá o mesmo número de linhas de A e o mesmo
número de colunas de B.
Amxn Bnxp ( A B) mxp

Sejam as matrizes A e B, então a multiplicação das matrizes é:


a11 a12 a13 b11 b12
A a 21 a 22 a 23 e B b21 b22
a 31 a 32 a 33 3 x3
b31 b32 3x2

a11 b11 a12 b21 a13 b31 a11 b12 a12 b22 a13 b32
A B a 21 b11 a 22 b21 a 23 b31 a 21 b12 a 22 b22 a 23 b32
a 31 b11 a 32 b21 a 33 b31 a 31 b12 a 32 b22 a 33 b32

Obs.: A multiplicação de um número real K qualquer por uma matriz é feita multiplicando cada
um dos elementos da matriz pelo número real K.
Exemplo:
Seja K = 3

Introdução á Lógica e Técnicas de Programação José Gracioli


36

2 0 6 0
Se a matriz A k A
4 5 12 15
4.2.7 Matriz Oposta
Denominamos de matriz oposta a matriz cujos elementos são simétricos dos elementos
correspondentes.
Exemplo
2 7 2 7
A A
1 9 1 9

4.2.8 Matriz Simétrica


Denominamos de matriz simétrica a matriz cujos elementos fora da diagonal principal
são iguais( Ai j Aj i ).
Exemplo
1 2 7
A 2 4 5
7 5 6

4.2.9 Matriz Anti-Simétrica


Denominamos de matriz anti-simétrica a matriz cujos elementos fora da diagonal
principal são iguais( Ai j Aj i ).
Exemplo
1 2 17
A 2 6 3
17 3 2

4.2.9 Propriedades

Adição
1. A + B = B + A (Comutativa)
2. (A + B) + C = A + (B + C) (Associativa)
3. A + 0 = A (Elemento Neutro)
4. A + (-A) = 0 (Elemento Oposto)

Multiplicação
1. A . (BC) = (AB) . C (Associativa)
2. A . (B + C) = AB + AC (Distributiva à Direita)
3. (B + C) . A = BA + CA (Distributiva à Esquerda)

Obs.: A multiplicação de matrizes não é comutativa, mas se ocorrer AB = BA, dizemos que as
matrizes A e B comutam.

4.2.10 Matriz Inversa


Seja A uma matriz quadrada, se existir uma matriz B tal que A.B = B.A = I, dizemos que
a matriz B é uma matriz inversa de A e a indicaremos por A -1. Vale lembrar que I é a matriz
identidade. Caso exista a inversa dizemos que a matriz A é inversível e, em caso contrário, não
inversível ou singular. Se a matriz quadrada A é inversível, a sua inversa é única.

1 1
A A A A In
Introdução á Lógica e Técnicas de Programação José Gracioli
37

Exemplo:
1 2
Determinar a inversa da matriz A .
3 2
a b 1
Fazendo A 1
e sabendo que A A I n então teremos :
c d
1 2 a b 1 0 a 2c b 2d 1 0
3 2 c d 0 1 3a 2c 3b 2d 0 1
a 2c 1
1 3
3a 2c 0 a e c
2 4
b 2d 0 1 1
b e d
3b 2d 1 2 4
1 1
Logo a matriz inversa é: 1 2 2
A
3 1
4 4

4.2.11 Determinantes
É um número real associado a matriz quadrada.

4.2.11.1 Determinante de uma matriz quadrada de 2ª Ordem


O determinante de uma matriz quadrada de 2ª ordem é obtido pela diferença entre o
produto dos elementos da diagonal principal e o produto dos elementos da diagonal
secundária.
a11 a12
det A A a11 a22 a12 a21
a21 a22
Exemplo
4 5
Achar o valor do determinante 4 7 5 ( 1) 28 ( 5) 33
1 7
4.2.11.2 Determinante de uma matriz quadrada de 3ª Ordem

Para calcular o determinante de uma matriz quadrada de 3ª ordem utilizaremos uma


regra muita prática denominada regra de Sarrus.

1 2 3
Seja a matriz A 0 3 2 . Para Calcularmos o determinante vamos repetir a 1ª e a
4 5 1
2ª colunas à direita da matriz, conforme o esquema abaixo:

1 2 3 1 2
0 3 2 0 3
4 5 1 4 5

- - - + + +
det A = | A | = (1)(3)(-1) + (2)(2)(4) + (3)(0)(-5) – (2)(0)(-1) – (1)(2)(-5) – (3)(3)(4)
det A = | A | = -3 + 16 – 0 + 0 + 10 – 36 = -13
Introdução á Lógica e Técnicas de Programação José Gracioli
38

4.2.12 Declaração de uma Matriz no Algoritmo

Tipo
TPMATRIZ = Vetor[1..4,1..5] de Inteiros

Var
MAT = TPMATRIZ

Obs.: A melhor estrutura de Controle para se trabalhar com Vetores e/ou Matrizes é a
REPETIÇÃO com uma variável de controle

Exercícios

1 - Fazer um algoritmo que escreva a soma da diagonal principal de uma matriz 5x5.

2 - Fazer um algoritmo que calcule a soma dos valores marcados na matriz abaixo, imprimir
também a multiplicação dos valores restantes:

12 4 36 7 9
Mat = 12 83 2 -4 -3
34 -67 -5 1 35
56 4 17 21 -24
2 3 -8 -12 77
3 - Faça um algoritmo que leia um arquivo de notas dos 30 alunos de uma classe. Cada aluno
possui 4 notas. Deverá ser armazenado em uma matriz de 4 X 30. Calcule a média de cada
aluno e também a média geral da turma.Use um vetor para armazenar os nomes.

4 – Faça um algoritmo que leia uma matriz 5 x 5 de valores inteiros e gere e imprima um vetor
com todos os valores das colunas ímpares dessa matriz e também um vetor com todos os
números pares dessa matriz.

5. Modularização de Algoritmos/Programas
A modularização traz algumas vantagens para o entendimento, construção, codificação,
teste e reutilização dos mesmos. A grande maioria das linguagens de programação tem essa
facilidade. Seja como subrotinas, procedimentos, funções, subprogramas etc. Sempre é
possível subdividir um programa de modo a facilitar o entendimento, permitir a reutilização,
evitando-se a repetição de blocos. No pseudo-código definiremos dois tipos de módulos: os
procedimentos (“procedure”) e as funções (“functions”).
Os procedimentos e funções são normalmente definidos antes de serem utilizados pelo
programa principal. Nos nossos algoritmos poderemos defini-los em qualquer parte do
algoritmo, seguindo os formatos e as normas de documentação.

5.1 Variável Global e Local


Uma variável Global será declarada no inicio do programa, e poderá ser utilizada por
qualquer sub-rotina ou procedimento dentro do programa. Dizemos que é visível em todo o
programa.
A variável Local é declarada dentro de uma sub-rotina ou procedimento e somente será
válida dentro da sub-rotina que foi declarada.

Introdução á Lógica e Técnicas de Programação José Gracioli


Exemplos:
Program Um; Program Dois;
Var Var
A:integer; A:integer;
B:Integer; B:Integer;
X:integer; Procedure Troca;
Begin(*Inicio do prog. Principal*) Var
Writeln('Digite um número '); X:integer;
Readln(A); Begin
Writeln('Digite número dois'); X:=A;
Readln(B); A:=B;
X:=A; B:=X;
A:=B; End;
B:=X; Begin(*Inicio do prog. Principal*)
Writeln(A); Writeln('Digite um número ');
Writeln(B); Readln(A);
End. Writeln('Digite número dois');
Readln(B);
Troca;
Writeln(A);
Writeln(B);
End.

Apesar de o programa dois ser um pouco maior que o primeiro em número de linhas, no
segundo há uma economia de memória, uma vez que quando não está sendo utilizada a rotina
TROCA, a variável X será liberada, ficando somente os espaços reservados para variáveis
Globais. Caso déssemos um comando de impressão da variável X dentro do programa dois(na
parte principal) teríamos como resposta uma mensagem de erro: “Variável fora do Escopo”,
pois se trata de uma variável local.
Uma observação importante quanto a declaração de variáveis: Estas só serão globais
referentes as sub-rotinas e procedimentos que forem colocadas após a declaração. Por isso se
quiser que as variáveis sejam globais a todas as rotinas, deverão ser declaradas em primeiro
lugar no programa. Se declarada antes, esta será global a todas as sub-rotinas existentes após
a sua declaração, porém, se forem declaradas após uma sequência de sub-rotinas, esta será
global do ponto que está para baixo e local com relação às sub-rotinas definidas acima dela(e
que devem estar declaradas dentro das rotinas anteriores, pois senão teremos um erro de
escopo!!!!). Veja o programa a seguir:
Program Tres;
Procedure Troca;
Var
X:integer;
A:integer;
B:integer;
Begin
A:=9;
X:=A;
A:=B;
B:=X;
Writeln(A);
Writeln(B);
Writeln(X);
End;
Var
A:integer;
40

B:Integer;
Begin(*Inicio do prog. Principal*)
Writeln('Digite um número: ');Readln(A);
Writeln('Digite um número: ');Readln(B);
Troca;
Writeln(A);
Writeln(B);
End.

Sua saída seria:


Digite um número: 12
Digite um número: 8
0
9
9
12
8

Exercícios
a) Faça um programa que crie uma calculadora com as quatro operações básicas. Deverá ser
usado um sub-rotina para cada operação com suas variáveis locais e um menu(Utilizando o
comando “Case”) no programa principal que chamará essas subrotinas quando solicitadas.
Deverá também ter pelo menos uma variável Global. Deverá ser usado o comando gotoxy que
define a posição do cursor do teclado na tela.
Sintaxe
gotoxy ( Coluna: integer ; Linha: integer ) ;

Program Exemplo;
{ Programa que move o cursor do teclado para a Coluna 10, Linha 20, e imprime
"Programação" na tela. As linhas são de 1 á 25 e as colunas de 1 à 80}
Begin
gotoxy(10,20);
write('Programação');
End.

5.2 Sub-Rotinas
A modularização dos programas pode ser feitos por meio de procedures
(procedimentos) com ou sem passagem de parâmetros, funções(functions) e Units(unidades).

5.2.1 Procedimento sem Passagem de Parâmetros.


Exemplo
Program Primo_Proced;
Var
N:integer;{Número a ser gerado para verificar se é primo}
Primo:integer;{Conta os números primos}
Divi:Integer;{assume os divisores 2,3,4,5,6,7....}
Achou:Boolean;{ Quando encontra um primo ele avisa}
Procedure Procura_Primo;
Begin
Achou:=False;
IF N >2 Then
For Divi:=2 to N-1 Do
If N mod Divi =0 Then
Introdução á Lógica e Técnicas de Programação José Gracioli
41

Achou:=True;
End;
Procedure Imprima_Primo;
Begin
If Not achou Then
Begin
Writeln(N, ' É Primo');
primo:=primo+1;
End;
End;
Begin (*Inicio do pgm principal*)
Primo:=0;
N:=1;
While primo< 30 Do
Begin
Procura_Primo;
Imprima_Primo;
N:=N+1;
End;
End.(*Fim do programa principal*)

5.2.2 Procedimento com Passagem de Parâmetros


Esses parâmetros podem ser Formais ou Reais. Serão formais quando forem
declarados através de variáveis juntamente com a identificação do nome da sub-rotina, os
quais serão tratados exatamente da mesma forma que são tratadas as variáveis globais ou
locais. Os parâmetros Reais são aqueles que estão presentes na chamada da rotina.
Exemplo:
Program Soma_Raiz;
Var
{Programa que lê dois valores e chama uma rotina que
calcula as suas raízes e soma os valores}
X:integer;{Número a ser Lido- Parâmetro Real}
Y:Integer;{Número a ser Lido- Parâmetro Real}
Procedure Calc_Soma_Raiz(A,B:Integer);
(* A e B são os parâmetros Formais*)
Var
Z: Real;
Begin
Z:=SQRT(A)+SQRT(B);
Writeln(Z:8:3, ' É a soma das raízes quadradas de : ', A, ' e ',B);
End;
Begin (*Inicio do pgm principal*)
Write('Digite o valor de um número positivo inteiro: ');Readln(X);
Write('Digite o valor de um número positivo inteiro: ');Readln(Y);
Calc_Soma_Raiz(X,Y);(*X e Y parâmetros reais*)
Calc_Soma_Raiz(49,81); (*49 e 81 parâmetros reais*)

End.(*Fim do programa principal*)

Essa passagem de parâmetros poderá ser feita de duas formas: Por Valor e Por
Referência.

Introdução á Lógica e Técnicas de Programação José Gracioli


42

5.2.2.1 Por Valor


Esta modalidade caracteriza-se pela não alteração do valor do parâmetro real quando o
parâmetro formal é manipulado dentro da sub-rotina. Somente uma cópia do parâmetro real é
passada para o parâmetro formal e qualquer modificação feita, dentro da rotina, só afetará a
variável local da sub-rotina e não o parâmetro real.
Exemplo
Program Fatorial_Valor;
Uses
Crt;
Procedure Fatorial(N:Integer);
Var
I, Fat:Integer;
Begin
Fat:=1;
For I:=1 to N do
Fat:=Fat*I;
Writeln('O fatorial de ', N, ' equivale a : ', Fat);
N:=N-1;(*Para mostrar que não vai alterar o parâmetro fora do
procedimento*)
Writeln(N);
End;
Var
Lim:Integer;
Resp:Char;
Begin
Clrscr;
Writeln('Deseja calcular um fatorial ? S/N');Readln(Resp);
While Resp='s' do
Begin
Write('Informe um valor inteiro : ');
Readln(Lim);
Fatorial(Lim);
Writeln;
Writeln('Deseja Continuar ? S/N');Readln(Resp);
End;
End.

5.2.2.2 Por Referência


Esta modalidade caracteriza-se pela ocorrência da alteração do valor do parâmetro real
quando o parâmetro formal é manipulado dentro da sub-rotina. A alteração efetuada é
devolvida para a rotina chamadora
Exemplo:
Program Fatorial_Referencia;
Uses
Crt;
Procedure Fatorial(N:Integer; var Fat:integer);
Var
I:Integer;
Begin
Fat:=1;
For I:=1 to N do
Fat:=Fat*I;
End;
Introdução á Lógica e Técnicas de Programação José Gracioli
43

Var
Limite:Integer;
Retorno:Integer;
Resp:Char;
Begin
Clrscr;
Writeln('Programa Fatorial ');
Writeln('Deseja calcular um fatorial ? s/n');Readln(Resp);
While Resp='s' do
Begin
Write('Informe um valor inteiro : ');
Readln(Limite);
Fatorial(Limite, Retorno);
Writeln('O Fatorial de ',Limite,' equivale a : ',Retorno);
Writeln;
Writeln('Deseja Continuar ? s/n');Readln(Resp);
End;
End.
Obs.: Neste exemplo a variável “N” continua sendo do tipo: “Passagem de parâmetro por
valor”, pois ela apenas receberá o valor da variável “Limite” através da chamada da sub-rotina
“Fatorial”; A variável “Fat” é do tipo “passagem de parâmetro por referência” (pois aparece
através da instrução “var” na declaração do nome da sub-rotina), a “Fat” será alterada dentro
da sub-rotina e passará o cálculo do fatorial para a variável “Retorno” dentro do programa
principal.

5.2.3 Funções – Function


Uma function tem o mesmo objetivo de uma procedure, isto é, desviar a execução do
programa principal para a realização de uma tarefa específica com uma única diferença: O
Valor de uma função é retornado no próprio nome da função e quando mencionamos “Valor”
devem ser levados em conta os valores numéricos, lógicos ou literais(String ou Char). Somente
não poderão ser retornados tipos ARRAY e RECORD, justamente por serem tipos que definem
variáveis que armazenam mais de um valor. Ela poderá usar variáveis Locais e/ou Globais. A
Function pode ser com ou sem passagem de parâmetros.
Sintaxe :

Function <nome da Função>[parâmetros:Tipo dos dados]: <Tipo do dado do valor


retornado>;
Var
(* declaração das variáveis Locais*)
Begin
Comando 1
Comando 2
.....
End;
Exemplo:

5.2.3.1 Function sem Passagem de Parâmetros.


Program Funcao_sem_passagem;
Uses
Crt;
Var
Elevado:Real;(* Recebe o valor da função no programa principal*)
X:Real;(*base a ser elevado a um expoente 2*)
Introdução á Lógica e Técnicas de Programação José Gracioli
44

Function POT:Real;
(*Função que calcula o valor de um número intero elevado a potencia 2*)
Begin
POT:=EXP(2*Ln(abs(X)));
{POT:=SQR(X);}
End;
Begin
Clrscr;
WriteLn('Programa Potência de 2 ');
Writeln('Digite um valor ');Readln(X);
Elevado:=POT;
Writeln('O Valor de ', X:5:2, ' Elevado a 2 é :',Elevado:5:2);
End.

5.2.3.2 Function com Passagem de Parâmetros.


Program Funcao_com_passagem;
Uses
Crt;
Var
Elevado:Integer;(* Recebe o valor da função no programa principal*)
I:Integer;(*Valor da base Limite a ser elevado a um expoente 2*)
J:Integer;(*Controle do For para gerar a base *)
Function POT(Num:Integer):Integer;
(*Função que calcula o valor de um número real elevado a potencia 2*)
Begin
POT:=SQR(Num);
End;
Begin
Clrscr;
WriteLn('Programa Potencia de 2 ');
Writeln('Digite um valor inteiro maior que zero e menor que 1000');Readln(I);
If I<= 0 then
Writeln('Valor Inválido ')
else
For J:=1 to I do
Begin
Elevado:=POT(J);
Writeln('O Valor de ', J, ' Elevado a 2 é :',Elevado);
End;
End.

Obs: O valor J(que irá variar de 1 até o número que foi digitado – o valor máximo para ser
calculada a potência de 2) será passado para dentro da Função pela variável “Num” onde será
calculada a potência de Num e então retorna o valor pelo nome da Função(POT).

6. Registro e Arquivos

6.1 Registros ou Agregados Heterogêneos


São conjuntos de informações relacionadas entre si, que podem ser referenciadas como
uma unidade e que, normalmente são compostas de informações(campos) de tipos diferentes.
Eles são conhecidos como variáveis compostas heterogêneas.

Introdução á Lógica e Técnicas de Programação José Gracioli


45

6.1.1 Declaração de Registros


Declaramos os registros em nossos algoritmos como TIPO definido pelo programador.
Assim cada registro poderá ter tantos campos quanto o programador deseje. O ideal do
tamanho de um registro é de 10 campos. Quando forem necessário estruturas de dados
maiores poderemos utilizar registros previamente definidos dentro de outros registros

Exemplo(Em algoritmo):
Tipo
Regaluno = Record
Nome : Texto
Sexo : Caracter
Media : Real
Fim -Record
Var
Reg1,Reg2 : Regaluno

Exemplo(Em Pascal):
Type
Regaluno = Record
Nome : String[30];
Sexo : Char;
Media : Real;
End;
Var
Registro : Regaluno;
Vet: array [1..30] of Regaluno;(* Aqui está declarado um vetor com 30 posições
sendo que cada uma conterá o nome, o sexo e a média de cada aluno*)

6.1.2 Para Acessar um Campo do Registro:


Alguns exemplos:
Vet[25].Nome:=’Maria’
Read(Vet[I].Nome)
Writeln(Vet[I].Sexo)
Regaluno.Media=7.4

6.1.3 Exemplo Prático da Utilização de Registros


Fazer um programa que leia 4 notas bimestrais de 5 alunos e apresente no final os
dados dos alunos classificados de forma crescente por nome com as suas respectivas médias.
Program Exemplo_7;
Type
Bim=array[1..4] of real;
Cadalu=record
Nome:string;
Nota:bim;
end;
Var
Aluno:array[1..5] of Cadalu;
I,J,Fim:integer;
Aux:Cadalu;
Soma,Media:Real;
Begin
(*Rotina de Entrada*)
Introdução á Lógica e Técnicas de Programação José Gracioli
46

Writeln('Cadastro de Aluno');
Writeln;
For J:=1 to 5 do
begin
writeln('Informe o nome do ',J:2,' aluno....: ');
Readln(Aluno[j].nome);
For I:=1 to 4 do
begin
Write('Informe a ', I:2, ' Nota....: ');
Readln(Aluno[J].Nota[I]);
end;
end;
(*Rotina de Ordenação*)
For Fim:=5 downto 2 do
For I:=1 to Fim -1 do
If Aluno[I].Nome > Aluno[I+1].Nome then
Begin
Aux:=Aluno[I+1];
Aluno[I+1]:=Aluno[I];
Aluno[I]:=Aux;
end;
(*Rotina de Saída*)
Writeln;
For J:=1 to 5 do
begin
Soma:=0;
Writeln(Aluno[J].Nome);
For I:= 1 To 4 do
Soma:=Soma+Aluno[J].Nota[I];
Media:=Soma/4;
Writeln('A Média é = ',Media:5:2)
End;
End.

6.1.4 Exercícios

1) Criar um registro de Funcionários onde cada registro contém: Nome, Endereço (Rua,
Número, Complemento, Bairro, Cidade, Estado e Cep) Tel(Resid,Comercial e Celular) e
Salário.
2) Fazer um programa que leia um vetor contendo 15 registros de funcionários contendo cada
um (Nome, sexo, idade, salário). Você deverá fazer um programa que escreva o nome do
funcionário e o seu salário acrescido de uma bonificação de 10% sobre o salário, calcule e
escreva a média das idades desses funcionários, bem como escrever o nome daquele que
possui o maior salário. Para isso deverá usar um vetor e uma estrutura de registro.

6.2 Arquivos
É um conjunto de dados ou informações de tamanho limitado que é identificado por um
nome (identificador do arquivo), e que está localizado na memória secundária.
Um arquivo é uma coleção de registros, em que cada registro é formado por campos,
um desses campos é chamado de chave(Identificador do registro) e que irá ser único dentro do
arquivo para distinguir dos demais.
Um Banco de Dados é um conjunto de vários arquivos e nos quais poderemos fazer
algumas operações como: Inclusão, alteração, exclusão(físicas ou Lógicas), consulta etc.
Introdução á Lógica e Técnicas de Programação José Gracioli
47

O PASCAL possui dois tipos de arquivos: FILE e TEXT

6.2.1 Arquivos do Tipo File


Um arquivo do tipo FILE tem acesso aleatório. É o mais importante e também o mais
utilizado. Um arquivo randômico é caracterizado pelo fato de ser possível buscar uma
determinada informação em qualquer posição que a mesma se encontre, sem haver a
necessidade de se percorrer todo o arquivo. O acesso a informação é direto.

6.2.2 Arquivos do Tipo Text


É um conhecido como sequencial, é um tipo especial de arquivo que, ao contrário do
arquivo FILE, pode ser editado normalmente através de um editor de textos qualquer. Ele é
sequencial porque a leitura tem que ser feita sequencialmente do início ao fim do arquivo, não
podendo desta forma, como é feito no arquivo FILE através do comando SEEK, posicionar de
forma direta em um registro em particular. Todas as informações armazenadas são texto,
mesmo assim, é possível armazenar no arquivo informações de qualquer tipo de dado simples
(integer, real, byte etc) as quais, ao serem fisicamente armazenadas no arquivo, serão
automaticamente convertidas do seu tipo original para o tipo STRING. A leitura se processa de
forma inversa, ou seja, quando é lida uma informação em um arquivo TEXT, a mesma será
automaticamente convertida para o tipo da variável que irá armazenar a informação, isto é, do
tipo STRING para o tipo da variável receptora da informação lida.

6.2.3 Declaração de Arquivos


Tipo(* Tipo File*)
<Nome do arquivo> = File of < nome do registro>;
Var
Arqfun : <Nome do arquivo>;
ArqTexto : TEXT;

Obs: No nosso curso vamos trabalhar só com arquivo do tipo File que são os mais utilizados e
os mais rápidos.

Exemplo: Imagine armazenar os nomes alunos de uma determinada turma. Onde cada registro
contém: Matricula, Nome, Idade, Sexo.
Type registro=Record
Matricula:Integer;
Nome:String;
Idade:Integer;
Sexo:Char;
End;
Arquivo = File of registro;
Var
Alunos:Arquivo;
Regalu:registro;

6.2.4 Comandos de Arquivos em Pascal

1) Assign : Associa nomes dos arquivos físicos a variáveis locais, isto é, a variáveis do tipo
arquivo com o arquivo do dispositivo da memória secundária(disco)
Sintaxe:
Assign(<nome do arquivo no programa>, ‘ caminho do arquivo no disco:\nome do
arquivo no disco’)
Exemplo:
Assing(Alunos,’Alunos.Dat’)
Introdução á Lógica e Técnicas de Programação José Gracioli
48

2) Rewrite: É utilizado para abrir novos arquivos apagando todo seu conteúdo.
Exemplo:
Rewrite(Alunos)

3) Reset : É utilizado para abrir arquivos e posicionar o ponteiro no registro de nº zero sem
destruir os dados existentes.
Exemplo:
Reset(Alunos)

4) Close : Serve para fechar arquivos que foram abertos pelo Rewrite ou Reset.
Exemplo
Close(Alunos)

5) Read: Ler dados que estão nos registros de um arquivo.


Exemplo
Read(Alunos, Regalu)

6) Write: Grava os dados que estão nos registros de um arquivo.


Exemplo
Write(Alunos, Regalu)

7) Seek: Serve para posicionar o ponteiro no registro desejado. O primeiro registro é o de


número zero.
Exemplo:
Seek(Alunos,3)

8) Filespos: Retorna o numero do registro onde o ponteiro está localizado.


Exemplo:
Filepos(Aluno)

9) Filesize: Informa o número do registros presentes em um arquivo


Exemplo:
Filesize(Aluno)

10) NOT EOF: Verificar se é o final do arquivo


Exemplo:
While Not EOF Do
Begin
Comando 1
Comando 2
¨¨¨¨¨
End;

Exemplo: Fazer um programa que simule um controle dos alunos matriculados em uma
determina escola. Este programa deverá ser capaz de cadastrar, alterar e excluir os nomes
dos alunos. O Arquivo será composto de vários registros, onde cada registro contém:
Matricula(Inteiro),Nome, Idade e Sexo. Vamos usar o arquivo do tipo TEXT.

Program Arquivo_Texto;(*programa arquivotexto salvo na pasta Pascal*)


Uses
Crt;
var
Introdução á Lógica e Técnicas de Programação José Gracioli
49

opcao:char;
Arqalunos:text;
Matricula:integer;
Nome:String[30];
Idade:Integer;
Sexo:Char;
Tecla:char;
(* Rotinas de Visualização *)

Procedure Linha;
Var
I:integer;
Begin
For I:= 1 to 80 do
Write(#205);
End;
Procedure Center(Msg:String);
Var
tam:integer;
Begin
Tam:=40+length(Msg) div 2;
Writeln(Msg:tam);
End;
Procedure Writexy(X, Y:integer; Msg:String);
Begin
Gotoxy(X,Y);
Write(Msg);
End;

(* Rotinas de Manipulação *)
Procedure Arquivo;
Begin
Clrscr;
Linha;
center('Criação de Arquivo');
Linha;
Rewrite(Arqalunos);
gotoxy(1,12); Center('Arquivo foi Criado');
writexy(25,24,' Tecle algo para voltar ao menu');
Tecla:=Readkey;
Close(Arqalunos);
end;
Procedure Cadastra;
Begin
Clrscr;
Linha;
Center(' Cadastramento de Registro');
Linha;
Append(Arqalunos);
writexy(10,5,' Entre com a Matricula...');Readln(Matricula);
writexy(10,6,' Entre com o Nome........');Readln(Nome);
writexy(10,7,' Entre com a Idade......');Readln(Idade);
writexy(10,8,' Entre com o Sexo.......');Readln(Sexo);
Introdução á Lógica e Técnicas de Programação José Gracioli
50

Writeln(Arqalunos,Matricula);
Writeln(Arqalunos,Nome);
Writeln(Arqalunos,Idade);
Writeln(Arqalunos,Sexo);
Writexy(25,24,' Tecle algo para voltar ao menu');
Close(Arqalunos);
End;
Procedure Exibir;
Var
Lin:integer;
Begin
Clrscr;
Linha;
Center(' Apresentação de Registros');
Linha;
Lin:=5;
Reset(Arqalunos);
While not EOF(Arqalunos) do
begin
Readln(Arqalunos,Matricula);
Readln(Arqalunos,Nome);
Readln(Arqalunos,Idade);
Readln(Arqalunos,Sexo);
gotoxy(5,Lin);Write(Matricula);
gotoxy(20,Lin);Write(Nome);
gotoxy(35,Lin);Write(Idade);
gotoxy(45,Lin);write(Sexo);
Lin:=Lin+1;
end;
Writexy(25,24,' Tecle algo para voltar ao menu');
Tecla:=Readkey;
Close(Arqalunos);
End;

(********************Programa Principal*****************)

Begin
Opcao:='0';
assign(Arqalunos,'C:\Pascalzim\alunos.txt');
While(opcao<>'4') do
Begin
Clrscr;
Linha;
Center('Menu principal');
Linha;
Gotoxy(28,6);Write('1........Criar um arquivo');
Gotoxy(28,8);Write('2...............Cadastrar');
Gotoxy(28,10);Write('3.......Exibir Registros');
Gotoxy(28,12);write('4........Fim do Programa');
Gotoxy(28,16);Write('Escolha uma opção....: ');
Readln(opcao);
If opcao<> '4' then
case opcao of
Introdução á Lógica e Técnicas de Programação José Gracioli
51

'1':Arquivo;
'2':Cadastra;
'3':Exibir;
else
Begin
gotoxy(27,24);Writeln(' opção Inválida - Tecle algo ');
opcao:=Readkey;
end;
End;
End;
End.

OBS: A tabela ASCII muito usada para fazermos formatação de tela pode ser vista através
desse programa.
// -------------------------------------------------------------
// Este programa imprime o conteúdo da tabela ASCII
// -------------------------------------------------------------

Program PASCII ;
Var
I: integer;
Begin
for I:= 1 to 255 do
write( I, chr(I), ' ' );
End.

No programa do arquivo foi usado o caractere de nº 205(=)

Introdução á Lógica e Técnicas de Programação José Gracioli


52

7. Linguagem Pascal
O Programa em Pascal ficaria da seguinte forma:

Program <Nome do programa>;


Const
Type
Var
Procedures
Functions
Begin
<Comandos>;
End.

7.1 Tipos de Dados

Pascal Descrição
a) integer Números entre -32768 até +32767. ocupa 2 bytes na memória.
b) real Representa os números entre 2.9 x 10 -39 até 1.7 x 1038 . Ocupa 6 bytes na
memória.
c) char Um caracter da tabela ASCII. Ocupa 1 byte na memória.
d) string Conjunto de caracteres. Ocupa de 1 a 255 bytes na memória.
e) boolean Valor lógico. Assuma somente dois valores: TRUE(Verdade) ou
FALSE(Falso). ocupa 1 byte na memória.
f) word Números inteiros de 0 até 65535. Ocupa 2 bytes na memória.
g) byte Números inteiros de 0 até 255. Ocupa 1 byte na memória.
h) shorint Números entre -128 até 127 . Ocupa 1 bytes na memória.
i) longint Números entre - 2.147.483.648 até 2.147.483.647 . Ocupa 4 bytes na
memória.
j) single Números reais entre 1.5 x 10 -45 até 3.4 x 1038 . Ocupa 4 bytes na memória.
k) double Números reais entre 5 x 10 -324 até 1.7 x 10308 . Ocupa 8 bytes na memória.

7.2 Palavras Reservadas


As palavras reservadas fazem parte da estrutura da linguagem e têm significados pré-
determinados. Elas não podem ser usadas como identificadores de variáveis, procedures,
functions etc. Algumas das palavras reservadas são:

absolute and array begin


case const div do
destructor downto else end
file for function goto
if in inline interface
label mod nil not
of or packed procedure
program record repeat set
shl shr string(*) then
to type until unit
uses var while xor

7.3. Constantes

Podemos definir tantas constantes quantas quisermos.


Introdução á Lógica e Técnicas de Programação José Gracioli
53

Const
Nome = 'Maria';
Idade= 25;
Toda vez que nos referirmos às constantes acima, o pascal substituí-las-á pelos seus
respectivos valores.

7.4 Declaração de Variáveis


Program Declara;
Var
Idade:shortint;
Num_Filhos:Integer;
Nome:String[30] (* A variável Nome só poderá ter até 30 caracteres*);
Altura, Peso: Real;
Achou:Boolean;
Sexo:Char
Begin
<comandos>;
End.

7.5 Operadores Aritméticos


Adição +
Subtração -
Multiplicação *
Divisão /
Quociente Inteiro DIV
Resto Inteiro Mod

7.6 Operadores Relacionais


Igual =
Diferente <>
Menor igual <=
Maior igual >=
Menor <
Maior >

7.7 Operadores Lógicos


E AND
OU OR
NÃO NOT
OU Exclusivo XOR

7.8 Funções Matemáticas


|X| Abs(x)
ex Exp(x)
Ln x Ln(x)
Parte inteira de um número Trunc(x)
Parte Fracionária de um número Frac(x)
Arredondar um número Round(x)
Raiz Quadrada Sqrt(x)
x2 Sqr(x)
Sen x Sin(x)
Cos x Cos(x)
Arctg x Arctan(x)
Introdução á Lógica e Técnicas de Programação José Gracioli
54

Obs.:
Se quiséssemos resolver a operação 45 exp 5 ln( 4)
1
1
Se quiséssemos resolver a operação 3
6 6 3
exp ln( 6)
3
7.9 Comando de Atribuição(:=)

Exemplo
Program Teste;
Var
Num: Integer;
Begin
Num: =48;
Num:= Num + 5;
End.

7.10 Comando de Entrada e Saída

Read( < variável>)


Write (<variável>)

Exemplo
Program Ler;
Var
Nome: string;
Idade: Integer;
Begin
Write(´ Digite seu nome : ´); Readln(Nome);
Write(´ Digite sua Idade : ´); Readln(Idade);
Writeln;
Writeln(´ Seu Nome é = ´, Nome)
Writeln(´ Sua idade é = ´, Idade);
End.

Em Pascal, quando usamos os comandos READ e WRITE, o cursor continuará


posicionado na mesma linha. Para passar para nova linha devemos acrescentar as letras
LN ( de LINE NEW) no final dos comandos READ e WRITE.

7.11 Comentários
Poderá ser feito em qualquer parte do programa, basta usar (*.....*) ou {....comentar...}

7.12 Formatação de Números Reais


Para formatar números reais usaremos a seguinte sintaxe:
X:7:2 significa que das 7 casas, 2 será para a parte decimal, 1 para o ponto e 4 para
parte inteira.

7.13 Funções de Tratamento de Caracteres


Copy(cadeia, posição, número) → Copia da cadeia, a partir da posição dada, o número
de caracteres estipulados
Length(cadeia)→Informa o tamanho da cadeia de caracteres
Pos(cadeia1, cadeia2) →Mostra, a partir de que posição, a cadeia1 aparece dentro da
cadeia2
Introdução á Lógica e Técnicas de Programação José Gracioli
55

Delete(Cadeia, posição, número) →Apaga da cadeia, a partir da posição dada, o


número de caracteres estipulados
Insert(cadeia1, cadeia2, posição) →Insere a cadeia1 na cadeia2 a partir da posição
dada
Concat(cadeia1, cadeia2) ou Cadeia1 + Cadeia2→ Soma duas cadeias de caracteres
Exemplos:
1) Faça um programa que receba uma frase e imprima a quantidade de palavras na frase

Program exemplo;
Uses crt;(* Para usar algumas funções definidas como reakey, clrscr e gotoxy*)
Var
frase,letra: string;
qtde, tam, i : integer;
begin
clrscr;
qtde:=0;
writeln('Digite uma frase');
readln(frase);
tam := length(frase); {tamanho da frase}
For i := 1 to tam do {vai percorrer cada caractere da frase}
Begin
letra := copy(frase,i,1); {coloca cada caract. da frase na variável letra}
If letra = ' ' Then {compara o caractere com espaço em branco}
qtde := qtde + 1;
end;
qtde := qtde + 1; {depois da última palavra não tem espaço}
writeln('Quantidade de palavras da frase = ',qtde);
readln;
end.
2) Faça um programa que leia uma frase e uma palavra. Caso a palavra contenha “Produção”,
substitua pela palavra digitada.

Program exemplo;
Uses
crt;
Var
frase, palavra_digitada, palavra_frase: string;
tam, i: integer;
Begin
clrscr;
writeln('Digite uma frase :');
readln(frase);
writeln('Digite a palavra para substituição :');
readln(palavra_digitada);
tam := length(frase);
i:=1;
while i<= tam do
begin
palavra_frase := COPY(frase,i,8);
if palavra_frase = 'Produção' then
begin
delete(frase,i,8);
insert(palavra_digitada, frase,i);
Introdução á Lógica e Técnicas de Programação José Gracioli
56

end;
tam := length(frase);
i:= i + 1;
end;
writeln(frase);
Readkey;
End.

7.14 Declaração de Registros


Formato:
TYPE Reg=Record
Matricula:integer;
Nome:string[30]
Idade: byte;
Var
Reg_Aluno:Reg
Ou
Var
Reg_Aluno:array[1..30] of reg(* Aqui as informações de cada um dos 30 alunos
serão colocadas em cada posição do vetor*)

Para Ler ou Imprimir os campos dos registros faremos:


Readln(Reg_Aluno.Matricula)
Readln(Reg_Aluno.Nome)
Readln(Reg_Aluno.Idade)

ou
For i=1 to 30 do
Begin
Readln(Reg_Aluno[i].Matricula);
Readln(Reg_Aluno[i].Nome);
Readln(Reg_Aluno[i].Idade);
End;

Introdução á Lógica e Técnicas de Programação José Gracioli


Centro Tecnológico de Mecatrônica

Fundamentos de
Linguagem C
ou

“Tudo que você precisa saber sobre C para não passar vergonha!”

Caxias do Sul, novembro de 1997


Conselho Regional do SENAI - RS

Presidente
Dagoberto Lima Godoy

Conselheiros

Titulares Suplentes

Deomedes Roque Talini Valayr Hélio Wosiack


Enio Lúcio Scheln Valdomiro Bochese da Cunha
Astor Milton Schmitt José Carlos Cerveri

Diretoria SENAI - SR
Diretor Regional
José Zortéa

Diretor Técnico
Paulo Fernando Presser

Diretor Administrativo e Financeiro


Adalberto Luiz Lenhard

5
Apresentação

O texto que segue é um resumo dos tópicos fundamentais sobre a linguagem C.

C é uma linguagem poderosa, robusta, flexível e madura. Conhecer todos os seus detalhes,
truques e armadilhas requer um estudo criterioso e profundo. Mas o C é uma linguagem de sintaxe
simples e elegante que permite rápido entendimento pelo programador iniciante. Desde sua criação, o C
tornou-se uma linguagem popular tanto entre programadores profissionais quanto iniciantes.

Neste contexto, procuramos abordar os tópicos essenciais da linguagem que nos permite escrever
um programa completo e útil.

Esperamos ter alcançado os objetivos propostos, e em próximas edições, aprimora-las.

Adalberto A. Dornelles F.

6
1. Fundamentos da Linguagem C

Neste capitulo serão vistos os fundamentos da linguagem C. O conceito de linguagem de


programação, linguagens de alto e baixo nível, linguagens genéricas e especificas. Será visto um pouco
do histórico da criação da linguagem e a descrição das características mais importantes da linguagem C.
Finalmente, será visto o aspecto geral de um código fonte escrito em C.

1.1 Linguagens de Programação

Um programa de computador é um conjunto instruções que representam um algoritmo para a


resolução de algum problema. Estas instruções são escritas através de um conjunto de códigos (símbolos
e palavras). Este conjunto de códigos possui regras de estruturação lógica e sintática própria. Dizemos
que este conjunto de símbolos e regras formam uma linguagem de programação.

1.1.1 Exemplos de códigos.

Existem muitas linguagens de programação. Podemos escrever um algoritmo para resolução de


um problema por intermédio de qualquer linguagem. A seguir mostramos alguns exemplos de trechos de
códigos escritos em algumas linguagens de programação.
Exemplo: trecho de um algoritmo escrito em Pseudo-linguagem que recebe um número num e
escreve a tabuada de 1 a 10 para este valor:
leia num
para n de 1 até 10 passo 1 faça
tab ← num * n
imprime tab
fim faça
Exemplo: trecho do mesmo programa escrito em linguagem C:
scanf(&num);
for(n = 1; n <= 10; n++){
tab = num * n;
printf(”\n %d”, tab);
};

Exemplo: trecho do mesmo programa escrito em linguagem Basic:

7
10 input num
20 for n = 1 to 10 step 1
30 let tab = num * n
40 print chr$ (tab)
50 next n

Exemplo: trecho do mesmo programa escrito em linguagem Fortran:


read (num);
do 1 n = 1:10
tab = num * n
write(tab)
10 continue

Exemplo: trecho do mesmo programa escrito em linguagem Assembly para INTEL 8088:
MOV CX,0
IN AX,PORTA
MOV DX,AX
LABEL:
INC CX
MOV AX,DX
MUL CX
OUT AX, PORTA
CMP CX,10
JNE LABEL

1.1.2 Linguagens de baixo e alto nível.

Podemos dividir, genericamente, as linguagens de programação em dois grandes grupos: as


linguagens de baixo nível e as de alto nível:

Linguagens de baixo nível: São linguagens voltadas para a máquina, isto é, são escritas usando
as instruções do microprocessador do computador. São genericamente chamadas de linguagens Assembly.
Vantagens: Programas são executados com maior velocidade de processamento. Os programas
ocupam menos espaço na memória.
Desvantagens: Em geral, programas em Assembly tem pouca portabilidade, isto é, um código
gerado para um tipo de processador não serve para outro. Códigos Assembly não são estruturados,
tornando a programação mais difícil.

8
Linguagens de alto nível: São linguagens voltadas para o ser humano. Em geral utilizam sintaxe
estruturada tornando seu código mais legível. Necessitam de compiladores ou interpretadores para gerar
instruções do microprocessador. Interpretadores fazem a interpretação de cada instrução do programa
fonte executando-a dentro de um ambiente de programação, Basic e AutoLISP por exemplo.
Compiladores fazem a tradução de todas as instruções do programa fonte gerando um programa
executável. Estes programas executáveis (*.exe) podem ser executados fora dos ambientes de
programação, C e Pascal por exemplo. As linguagens de alto nível podem se distinguir quanto a sua
aplicação em genéricas como C, Pascal e Basic ou específicas como Fortran (cálculo matemático),
GPSS (simulação), LISP (inteligência artificial) ou CLIPPER (banco de dados).

Vantagens: Por serem compiladas ou interpretadas, tem maior portabilidade podendo ser
executados em varias plataformas com pouquíssimas modificações. Em geral, a programação torna-se
mais fácil por causa do maior ou menor grau de estruturação de suas linguagens.
Desvantagens: Em geral, as rotinas geradas (em linguagem de maquina) são mais genéricas e
portanto mais complexas e por isso são mais lentas e ocupam mais memória.

1.2 Linguagem C

A linguagem C é uma linguagem de alto nível, genérica. Foi desenvolvida por programadores
para programadores tendo como meta características de flexibilidade e portabilidade. O C é uma
linguagem que nasceu juntamente com o advento da teoria de linguagem estruturada e do computador
pessoal. Assim tornou-se rapidamente uma linguagem “popular” entre os programadores. O C foi usado
para desenvolver o sistema operacional UNIX, e hoje esta sendo usada para desenvolver novas
linguagens, entre elas a linguagem C++ e Java.

1.2.1 Características do C

Entre as principais características do C, podemos citar:

• O C é uma linguagem de alto nível com uma sintaxe bastante estruturada e flexível tornando sua
programação bastante simplificada.
• Programas em C são compilados, gerando programas executáveis.
• O C compartilha recursos tanto de alto quanto de baixo nível, pois permite acesso e programação
direta do microprocessador. Com isto, rotinas cuja dependência do tempo é crítica, podem ser
facilmente implementadas usando instruções em Assembly. Por esta razão o C é a linguagem
preferida dos programadores de aplicativos.

9
• O C é uma linguagem estruturalmente simples e de grande portabilidade. O compilador C gera códigos
mais enxutos e velozes do que muitas outras linguagens.
• Embora estruturalmente simples (poucas funções intrínsecas) o C não perde funcionalidade pois
permite a inclusão de uma farta quantidade de rotinas do usuário. Os fabricantes de compiladores
fornecem uma ampla variedade de rotinas pré-compiladas em bibliotecas.

1.2.2 Histórico

1970: Denis Ritchie desenha uma linguagem a partir do BCPL nos laboratórios da Bell Telephones, Inc.
Chama a linguagem de B.
1978: Brian Kerningham junta-se a Ritchie para aprimorar a linguagem. A nova versão chama-se C.
Pelas suas características de portabilidade e estruturação já se torna popular entre os
programadores.
~1980: A linguagem é padronizada pelo American National Standard Institute: surge o ANSI C.
~1990: A Borland International Co, fabricante de compiladores profissionais escolhe o C e o Pascal
como linguagens de trabalho para o seu Integrated Development Enviroment (Ambiente Integrado
de Desenvolvimento): surge o Turbo C.
~1992: O C se torna ponto de concordância entre teóricos do desenvolvimento da teoria de Object
Oriented Programming (programação orientada a objetos): surge o C++.

1.3 Estrutura de um programa em C


Um programa em C é constituído de:
• um cabeçalho contendo as diretivas de compilador onde se definem o valor de constantes simbólicas,
declaração de variáveis, inclusão de bibliotecas, declaração de rotinas, etc.
• um bloco de instruções principal e outros blocos de rotinas.
• documentação do programa: comentários.
Programa Exemplo: O arquivo e0101.cpp contém um programa para calcular a raiz
quadrada de um número real positivo:

1.3.1 Conjunto de caracteres


Um programa fonte em C é um texto não formatado escrito em um editor de textos usando um o
conjunto padrão de caracteres ASCII. A seguir estão os caracteres utilizados em C:

Caracteres válidos:
a b c d e f g h i j k l m n o p q r s t u v w x y z
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
1 2 3 4 5 6 7 8 9 0

10
+ - * / \ = | & ! ? # % ( ) { } [ ] _ ‘ “ . , : < >

Caracteres não válidos:


@ $ ¨ á é õ ç

Os caracteres acima são válidos apenas em strings. Veja seção 2.1.4.

1.3.2 Comentários

Em C, comentários podem ser escritos em qualquer lugar do texto para facilitar a interpretação do
algoritmo. Para que o comentário seja identificado como tal, ele deve ter um /* antes e um */ depois.
Observe que no exemplo e0101.cpp todo o cabeçalho esta dentro de um comentário.
Exemplo:
/* esta e´ uma linha de comentário em C */

Observação: O C++ permite que comentários sejam escritos de outra forma: colocando um //
em uma linha, o compilador entenderá que tudo que estiver a direita do símbolo é um comentário.
Observe no programa exemplo e0101.cpp as linhas de comentários colocadas a direita dos comandos.

Exemplo:
// este e´ um comentário valido apenas em C++

1.3.3 Diretivas de Compilação

Em C, existem comandos que são processados durante a compilação do programa. Estes


comandos são genericamente chamados de diretivas de compilação. Estes comandos informam ao
compilador do C basicamente quais são as constantes simbólicas usadas no programa e quais bibliotecas
devem ser anexadas ao programa executável. A diretiva #include diz ao compilador para incluir na
compilação do programa outros arquivos. Geralmente estes arquivos contem bibliotecas de funções ou
rotinas do usuário. Voltaremos a trabalhas esta diretiva com mais detalhe no capítulo 5. A diretiva
#define diz ao compilador quais são as constantes simbólicas usadas no programa. Veremos sobre esta
diretiva no capitulo 2.
1.3.4 Declaração de variáveis
Em C, como na maioria das linguagens, as variáveis devem ser declaradas no inicio do programa.
Estas variáveis podem ser de vários tipos: int (inteiro), float (real de simples precisão) e outras que
serão vistas no capitulo 2. No exemplo acima num, raiz, inf e sup são declaradas como variáveis
reais, enquanto i é declarada como uma variável inteira.
11
1.3.5 Entrada e saída de dados
Em C existem varias maneiras de fazer a leitura e escrita de informações. Estas operações são
chamadas de operações de entrada e sadia. Veremos no capitulo 3 algumas funções de entrada e sadia de
informações via teclado e tela. Outras funções de leitura e escrita em arquivos, sadia gráfica, funções de
manipulação de mouse, entrada e sadia de informações via portas serial e paralela serão vistas em
capítulos posteriores. No exemplo acima printf é uma função de escrita na tela, scanf é uma função
de leitura de teclado.

1.3.6 Estruturas de controle


A linguagem C permite uma ampla variedade de estruturas de controle de fluxo de
processamento. Estas estruturas serão vistas em detalhes nos capítulos 4 e 5. Duas estruturas das
estruturas básicas (decisão e repetição) são muito semelhantes as estruturas usadas nas Pseudo-linguagem
algorítmicas:
Estrutura de Decisão: Permite direcionar o fluxo lógico para dois blocos distintos de instruções
conforme uma condição de controle.

Pseudo-linguagem Linguagem C

se condição if(condição){
então bloco 1 bloco 1;
senão bloco 2 }else{
fim se bloco 2;
};
Estrutura de Repetição: Permite executar repetidamente um bloco de instruções ate que uma
condição de controle seja satisfeita.

Pseudo-linguagem Linguagem C

faça do{
bloco bloco;
até condição }while(condição);

2. Constantes e Variáveis

12
Neste capitulo veremos como os dados constantes e variáveis são manipulados pela linguagem C.
O que são constantes inteiras, reais, caracteres e strings. Quais são as regras de atribuição de nomes a
variáveis e quais são os tipos de dados que O C pode manipular. Veremos também como são declaradas
as variáveis e as constantes simbólicas usadas em um programa.

2.1 Constantes
O C possui quatro tipos básicos de constantes: inteiras, de ponto flutuante, caracteres e strings.
Constantes inteiras e de ponto flutuante representam números de um modo geral. Caracteres e strings
representam letras e agrupamentos de letras (palavras).

2.1.1 Constantes inteiras

Uma constante inteira é um número de valor inteiro. De uma forma geral, constantes inteiras são
seqüências de dígitos que representam números inteiros. Números inteiros podem ser escritos no formato
decimal (base 10), hexadecimal (base 16) ou octal (base 8).

Uma constante inteira decimal é formada por uma seqüência de dígitos decimais: 0, 1, 2,
3, 4, 5, 6, 7, 8, 9. Se a constante tiver dois ou mais dígitos, o primeiro não pode ser 0. Na
verdade, pode ser 0 mas o compilador considerará esta constante como octal e não decimal.

Exemplo: A seguir são mostradas algumas constantes inteiras decimais válidas.


0 3 -45 26338 -7575 1010

Exemplo: Algumas constantes inteiras decimais inválidas.


1. (ponto)
1,2 (vírgula)
045 (primeiro dígito é 0: não é constante decimal)
212-22-33 (caracter ilegal: -)
Uma constante inteira hexadecimal é formada por uma seqüência de dígitos decimais: 0, 1,
2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F (ou a, b, c, d, e). Uma constante
hexadecimal deve começar por 0x. Neste caso, os dígitos hexadecimais podem ser minúsculos ou
maiúsculos.

Exemplo: A seguir são mostrados algumas constantes inteiras hexadecimais válidas.


0x0 0x3 0x4f5a 0x2FFE OxABCD 0xAaFf

Exemplo: Algumas constantes inteiras hexadecimais inválidas.

13
0x3. (ponto)
0x1,e (vírgula)
0x ff (espaço)
FFEE (não começa com 0x: não é constante hexadecimal)
0Xfg34 (caracter ilegal: g)

Uma constante inteira octal é formada por uma seqüência de dígitos octais: 0, 1, 2, 3, 4,
5, 6, 7. A constante octal deve ter o primeiro digito 0 para que o compilador a identifique como tal
Exemplo: A seguir são mostrados algumas constantes octais válidas.
00 -03 045 02633 07575 -0101

Exemplo: Algumas constantes inteiras octais inválidas.


010. (ponto)
01,2 (vírgula)
0 4 (espaço)
45 (primeiro digito não é 0: não é constante octal)
01784 (caracter ilegal: 8)

2.1.2 Constantes de ponto flutuante


Números reais (não inteiros) são representados em base 10, por números com um ponto decimal e
(opcionalmente) um expoente. Um número ponto flutuante deve ter um ponto decimal que não pode ser
substituído por uma vírgula. Um número de ponto flutuante pode ser escrito em notação científica. Neste
caso o x10 é substituído por e ou E. O número 1.23e4 representa 1.23 x 104 ou 12300.
Exemplo: Números de ponto flutuante válidos.
0.234 125.65 .93 1.23e-9 -1.e2 10.6e18 -.853E+67

A forma de representação de um número real em C é bastante flexível.

Exemplo: O número 314 pode ser representado por qualquer uma das seguintes formas:
314. 3.14e2 +3.14e+2 31.4e1 .314E+3 314e0
2.1.3 Constantes caracteres
Uma constante caracter é uma letra ou símbolo colocado entre aspas simples.
Exemplo: Abaixo estão representados algumas constantes caracteres.
’a’ ’b’ ’X’ ’&’ ’{’ ’ ’

Embora sejam visualizados como letras e símbolos as constantes caracteres são armazenadas
internamente pelo computador como um número inteiro entre 0 e 255. O caracter ’A’ por exemplo, tem

14
valor 65. Os valores numéricos dos caracteres estão padronizados em uma tabela chamada de American
Standard Code for Information Interchange Table ou simplesmente tabela ASCII. Veja apêndice B.
Certos codigos de controle da tabela ASCII (como o line feed) ou caracteres especiaiss (como ')
possuem representação especial no C. Esta representacao chama-se seqüência de escape representada por
uma barra invertida (\) e um caracter. Sequencias de escape são interpretadas como caracteres simples.
Abaixo segue uma lista das principais sequencias de escape usadas no C.
Controle/Caracter Sequencia de escape Valor ASCII
nulo (null) \0 00
campainha (bell) \a 07
retrocesso (backspace) \b 08
tabulacao horizontal \t 09
nova linha (new line) \n 10
tabulacao vertical \v 11
alimentacao de folha (form feed) \f 12
retorno de carro (carriage return) \r 13
aspas (") \" 34
apostrofo (') \' 39
interrogacao (?) \? 63
barra invertida (\) \\ 92

2.1.4 Constantes strings


Uma constante string consiste de um conjunto de caracteres colocados entre aspas duplas.
Embora as instruções do C usem apenas os caracteres do conjunto padrão ASCII, as constantes caracter e
string podem conter caracteres do conjunto estendido ASCII: é, ã, ç, ü, ...
Exemplo: Abaixo seguem algumas constantes strings válidas.
”Oba!”
”Caxias do Sul”
”A resposta é: ”
”João Carlos da Silveira”
”a”
”isto é uma string”

2.2 Identificadores
Identificadores são os nomes das variáveis e funções usadas no programa. Por exemplo raiz e
MAX são nomes de variáveis utilizadas no programa e0101.cpp.
2.2.1 Regras de sintaxe
Os identificadores devem seguir as seguintes regras de construção:
• Os identificadores devem começar por uma letra (a - z , A - Z) ou um underscore ( _ ).

15
• O resto do identificador deve conter apenas letras, underscores ou dígitos (0 - 9). Não pode
conter outros caracteres. Em C, os identificadores podem ter até 32 caracteres.
• Em C, letras maiúsculas são diferentes de letras minúsculas: Por exemplo: MAX, max, Max
são nomes diferentes para o compilador. Esta propriedade é chamada de case sensibility.

Exemplo: os nomes abaixo são válidos:


abc, y24, VetorPontosMovimentoRobo, nota_1, TAM_MAX.

Exemplo: os nomes abaixo não são válidos:


3dia, vetor-1, pao&leite, iteração.

2.2.2 Palavras reservadas


Existem certos nomes que não podem ser usados como identificadores. São chamadas as
palavras reservadas e são de uso restrito da linguagem C (comandos, estruturas, declarações, etc.). O
conjunto de palavras reservadas usadas em C é o seguinte:
asm auto break case cdecl char
class const continue _cs default delete
do double _ds else enum _es
extern _export far _fastcall float for
friend goto huge if inline int
interrupt _loadds long near new operator
pascal private protected public register return
_saveregs _seg short signed sizeof _ss
static struct switch template this typedef
union unsigned virtual void volatile while

Exemplo: Não é possível declarar estes conjunto de variáveis:


do, re, mi, fa, sol, la, si
old, new

Dos conjuntos acima, do e new são palavras reservadas.

2.3 Tipos de dados

Em C, como na maioria das linguagens, os dados são divididos tipos: inteiro, real, caracter, etc.
Esta divisão se deve basicamente ao número de bytes reservados para cada dado. Cada tipo de dado
possui um intervalo de valores permitidos.

2.3.1 Tipos básicos

16
Abaixo segue uma lista dos tipos básicos de dados permitidos em C. Os tipos char e int são
inteiros e os tipos float e double são de ponto flutuante.
Tipo Tamanho Intervalo Uso
char 1 byte -128 a 127 número muito pequeno e caracter ASCII
int 2 bytes -32768 a 32767 contador, controle de laço
float 4 bytes 3.4e-38 a 3.4e38 real (precisão de 7 dígitos)
double 8 bytes 1.7e-308 a 1.7e308 científico (precisão de 15 dígitos)

2.3.2 Declaração de variáveis


Para que se possa usar uma variável em um programa, é necessário fazer uma declaração de
variável antes. A declaração de variáveis simplesmente informa ao processador quais são os nomes
utilizados para armazenar dados variáveis e quais são os tipos usados. Deste modo o processador pode
alocar (reservar) o espaço necessário na memória para a manipulação destas variáveis. É possível declarar
mais de uma variável ao mesmo tempo, basta separá-las por vírgulas (,).

Sintaxe: A sintaxe para declaração de variáveis é a seguinte:


tipo variavel_1 [, variavel_2, ...] ;

Onde tipo é o tipo de dado e variavel_1 é o nome da variável a ser declarada. Se houver
mais de uma variável, seus nomes são separados por vírgulas.

Exemplo: Declaração das variáveis:


int i;
int x,y,z;
char letra;
float nota_1,nota_2,media;
double num;

No exemplo acima, i, x, y e z foram declaradas variáveis inteiras. Assim elas podem armazenar
valores inteiros de -32768 até 32767. Do mesmo modo letra foi declarada como variável caracter
podendo receber valores de -128 até 127 ou caracteres do conjunto padrão ASCII. As variáveis nota_1,
nota_2 e media foram declaradas como ponto flutuante tipo float e num como ponto flutuante tipo
double.

A declaração de variáveis é feita, em geral, dentro de uma rotina. Por exemplo, a rotina principal
main(). Deste modo se diz que está se fazendo uma declaração de variáveis locais. Variáveis locais
podem ser referenciadas apenas dentro da rotina dentro da qual foi declarada, neste caso a rotina
main().
17
Exemplo: Observe o uso da declaração de variáveis no trecho de programa abaixo:
void main(){
float raio, area; // declaracao de variaveis
raio = 2.5;
área = 3.14 * raio * raio;
}

No exemplo acima, as variáveis area e raio foram declaradas como variáveis locais tipo
float. Assim o processador faz a alocação de dois espaços (endereços) de 4 bytes cada para armazenar
as informações, um para cada variável. Na terceira linha, o processador coloca no endereço alocado para
raio o valor 2.5. Depois, na quarta linha, o processador coloca o resultado da conta (19.625) no
endereço de área.

É possível fazer a declaração de variáveis fora de uma rotina. Neste caso diz-se que se fez a
declaração de variáveis globais. O uso de variáveis globais é explicado na sessão ?.?.

2.3.3 Tipos modificados

Além dos tipos de dados citados acima existem outros tipos de dados ditos modificados. Em C
existem dois modificadores: o modificador long e o modificador unsigned. Tipicamente o
modificador long aumenta o número de bytes usados para o registro do número. Por conseqüência o
intervalo de validade do número fica aumentado significativamente. O modificador unsigned, usado
somente em inteiros, permite que um bit usado para guardar o sinal do número seja usado para guardar o
valor do número. Em conseqüência disto o intervalo do número fica dobrado, porém somente permite o
uso de números positivos.

Tipo Tamanho (bytes) Intervalo


unsigned char 1 0 a 255
unsigned int 2 0 a 65 535
long int 4 -2 147 483 648 a 2 147 483 647
unsigned long int 4 0 a 4 294 967 295
long double 10 3.4e-4932 a 1.1e4932

2.3.4 Strings.
Uma string é um conjunto ordenado de caracteres que pode ser armazenado sob forma de um
vetor um ponteiro. Estas estruturas de dados serão vistas em detalhe nos capitulo ? e ?. Por enquanto, nos
basta saber como declarar e armazenar um conjunto caracter em uma variável.

18
Sintaxe: Para declararmos uma variável para receber um conjunto caracter devemos escrever:
char* var;

Exemplo: No exemplo seguinte a variável nome foi declarada como conjunto caracter e em
seguida recebe uma constante string.
char* nome;
nome = "João Carlos de Oliveira Andrade";

2.3.5 Inicialização de variáveis.


Quando se faz a declaração de uma variável está se determinando que tipo de dado ela vai
receber. É possível, em C, declarar uma variável e já armazenar nela um valor inicial. Chamamos este
procedimento de inicialização de uma variável.

Sintaxe: A sintaxe para a inicialização de variáveis é:


tipo var_1 = valor_1 [, var_2 = valor_2, ...] ;

Onde tipo é o tipo de dado, var_1 é o nome da variável a ser inicializada e valor_1 é o
valor inicial da variável.

Exemplo: Inicialização de variáveis:


int i = 0, j = 100;
float num = 13.5;
char* titulo = " Programa Teste ";
No exemplo acima, i e j foram declaradas variáveis tipo int. O valor inicial de i é 0 e o de j
é 100. Do mesmo modo num foi declarada como variável float com valor inicial de 13.5. Tambem a
variavel titulo foi declarada como um conjunto caracter e recebeu como conteudo inicial a string "
Programa Teste ".

2.3.6 Conversão de tipo (Casting)

Algumas vezes queremos, momentaneamente, modificar o tipo de dado representado por uma
variável, isto é, queremos que o dado seja apresentado em um tipo diferente do qual a variável foi
inicialmente declarada. Por exemplo: declaramos uma variável como int e queremos,
momentaneamente, que seu conteúdo seja apresentado como float. Este procedimento é chamado de
conversão de tipo ou casting (moldagem, em inglês).
Sintaxe: A sintaxe da instrução de conversão de tipo é:
(tipo) variável
19
onde tipo é o nome do tipo ao qual queremos converter o dado armazenado em variável.

Exemplo: observe a conversão de tipo feita no exemplo abaixo:


int num;
float valor = 13.0;
num = (int)valor % 2;
No exemplo acima a variável valor foi declarada inicialmente como sendo do tipo float
recebendo o valor inicial 13.0. Logo em seguida o conteúdo de valor é convertido para o tipo int para
realizar a operação módulo (%) com o inteiro 2. Aqui a conversão é necessária pois a operação módulo
somente pode ser feita com inteiros. É importante salientar que a conversão de tipo é feita com o dado
armazenado em uma variável mas a variável continua tendo o seu tipo original. No exemplo acima a
variável valor e os dados nela armazenados continuam sendo do tipo float após a conversão.
Veremos na seção 3.1 uma explicação mais detalhada do uso da conversão de tipos.

2.4 Constantes Simbólicas


Muitas vezes identificamos uma constante numérica por um símbolo: Pi = 3,14159 por exemplo.
Podemos definir um nome simbólico para esta constante, isto é, podemos definir uma constante
simbólica que represente valor.

2.4.1 Constantes definidas pelo programador

O programador pode definir constantes simbólicas em qualquer programa.

Sintaxe: A sintaxe da instrução de definição de uma constante simbólica é:


#define nome valor

Onde #define é uma diretiva de compilação que diz ao compilador para trocar as ocorrências
do texto nome por valor. Observe que não há ; no final da instrução pois trata-se de um comando para
o compilador e não para o processador. A instrução #define deve ser escrita antes da instrução de
declaração da rotina principal.
Exemplo: a seguir definimos algumas constantes simbólicas.
#define PI 3.14159
#define ON 1
#define OFF 0
#define ENDERECO 0x378

20
void main(){
...

No exemplo acima, definimos PI como 3.14159. Isto significa que todas as ocorrências do
texto PI será trocado por 3.14159. Assim se escrevemos uma instrução:

área = PI * raio * raio;


o compilador vai interpretar esta instrução como se fosse escrita assim:
área = 3.14159 * raio * raio;
Poderíamos escrever estas instruções assim:
float pi = 3.14159;
área = pi * área * área;

porém este tipo de instrução tem duas desvantagens: Primeiro, reserva 4 bytes de memória
desnecessariamente. Segundo, esta instrução é executada mais lentamente pois o processador precisa
acessar a memória para verificar qual é o valor de pi.

Observe também que no exemplo definimos os nomes simbólicos com letras maiúsculas. Isto não
é necessário, podemos perfeitamente definir nomes simbólicos usando letras minúsculas, porém faz parte
do jargão dos programadores C usar letras maiúsculas para definir constantes simbólicas.

O uso da diretiva #define não se restringe apenas ao apresentado acima, podemos usá-la para
definir macro instruções. Não veremos o uso de macros neste texto, procure mais detalhes na
bibliografia recomendada.

2.4.2 Constantes pré-definidas


Em alguns compiladores C, algumas constantes simbólicas já estão pré-definidas. Estas
constantes em geral definam alguns valores matemáticos (π, π/2, e, etc.), limites de tipos etc. A seguir
segue uma tabela contendo algumas (existem muitas outras) constantes simbólicas pré-definidas no
compilador Turbo C++ da Borland.
Biblioteca Constante Valor Significado
math.h M_PI 3.14159... π
math.h M_PI_2 1.57079... π/2
math.h M_PI_4 0,78539... π/4
math.h M_1_PI 0,31830... 1/π
math.h M_SQRT2 1,41421... √2
conio.h BLACK 0 valor da cor (preto)
conio.h BLUE 1 valor da cor (azul)
21
conio.h GREEN 2 valor da cor (verde)
conio.h CYAN 3 valor da cor (cyan)
conio.h RED 4 valor da cor (vermelho)
conio.h MAGENTA 5 valor da cor (magenta)
limits.h INT_MAX 32767 limite superior do tipo int
limits.h INT_MIN -32768 limite inferior do tipo int
Cada uma das constantes acima esta definida em uma biblioteca. Uma biblioteca, em C, é um
arquivo pré-compilado chamado arquivo header (cabeçalho, em inglês). Em cada biblioteca estão
agrupadas constantes e funções semelhantes (veja seção 3.7.2). Por exemplo, constantes e funções
matemáticas estão guardadas na biblioteca math.h (mathematical functions), constantes e funções de
manipulação teclado e monitor estão guardadas na biblioteca conio.h (console input and output). Para
que se possa usar a constante simbólica em um programa é preciso incluir a biblioteca na compilação do
programa.
Sintaxe: A sintaxe de inclusão de bibliotecas é a seguinte:
#include <nome_bib>

onde nome_bib é o nome da biblioteca que se deseja incluir. Esta instrução deve ser escrita
antes do programa principal.

Exemplo: O programa abaixo usa a constante predefinida M_PI para calcular a área de um disco
circular.
#include <math.h>
void main(){
float area, raio = 5.0;
área = M_PI * raio * raio;
}

22
3. Operadores, Expressões e Funções

Um programa tem como característica fundamental a capacidade de processar dados. Processar


dados significa realizar operações com estes dados. As operações a serem realizadas com os dados podem
ser determinadas por operadores ou funções. Os operadores podem ser de atribuição, aritméticos, de
atribuição aritmética, incrementais, relacionais, lógicos e condicionais.

Exemplo: o símbolo + é um operador que representa a operação aritmética de adição. O


identificador sqrt() é uma função que representa a operação de extrair a raiz quadrada de um número.

Uma expressão é um arranjo de operadores e operandos. A cada expressão válida é atribuído um


valor numérico.

Exemplo: 4 + 6 é uma expressão cujo valor é 10. A expressão sqrt(9.0) tem valor 3.0.

3.1 Operador de Atribuição

A operação de atribuição é a operação mais simples do C. Consiste de atribuir valor de uma


expressão a uma variável.

Sintaxe: A sintaxe da operação de atribuição é a seguinte:

identificador = expressão;
onde identificador é o nome de uma variável e expressão é uma expressão válida (ou
outro identificador).

Exemplo: A seguir são mostradas algumas atribuições válidas:


a = 1;
delta = b * b - 4. * a * c;
i = j;

Observe que o símbolo de atribuição ( = ) não tem o mesmo significado que o usual da
matemática que representa a igualdade de valores. Este símbolo, em C, representa a atribuição do valor
calculado em expressão a variável identificador. Em pseudo-linguagem o operador de
23
atribuição é representado como ←. Também não se pode confundir o operador de atribuição ( = ) com
o operador relacional de igualdade ( == ) que será visto na seção 3.5.1.

Observe-se também que o operando esquerdo deve ser um identificador de variável, isto é, não
pode ser uma constante ou expressão.

Exemplo: A seguir são mostradas algumas atribuições inválidas:


1 = a; // constante!
b + 1 = a; // expressão!

3.1.1 Conversão de tipo.

Se os dois operandos de uma atribuição não são do mesmo tipo, o valor da expressão ou operador
da direita será convertido para o tipo do identificador da esquerda.

Exemplo: Algumas atribuições com conversão de tipo:


int i;
float r;
i = 5; // valor de i: 5
r = i ; // valor de r: 5.0

A variável i foi inicializada com o valor 5. Ao final da terceira instrução, r recebe o valor
5.0.

Nestas conversões podem ocorrer alterações dos valores convertidos se o operando da esquerda
for de um tipo que utilize menor numero de bytes que o operando da direita.

Exemplo: Algumas atribuições com conversão de tipo e perda de informação:


int i;
float r = 654.321;
i = r; // truncamento!

Após a execução deste trecho de programa o valor da variável i será 654 pois seu valor foi
truncado durante a conversão.

Pode-se dizer que as conversões potencialmente perigosas (onde há possibilidade de perda de


informação) são:

24
char ← int ← float ← double

Observe que o compilador C ao encontrar esta operação não gera nenhum aviso de atenção para
o programador. Assim este detalhe pode gerar um erro de programação (bug) que passe desapercebido ao
programador inexperiente. É possível dizer que a linguagem C possui tipos “macios” (soft types) pois a
operação com variáveis de tipos diferentes é perfeitamente possível. Esta característica do C se contrapõe
a algumas linguagens em que isto não é possível (Fortran, por exemplo). Estas linguagens possuem tipos
“duros” (hard types).

3.1.2 Limites do intervalo do tipo de dado.

Também é importante observar que os tipos em C tem intervalos bem definidos e os resultados
das operações devem respeitar estes intervalos. Se a uma variável for atribuído um valor que esteja fora
dos seus limites então este valor será alterado.

Exemplo: Observe as expressões abaixo, assuma que i seja uma variável do tipo int.
i = 4999; // o valor de i e’ 4999
i = 4999 + 1; // o valor de i e’ 5000
i = 5000 + 30000; // o valor de i e’ -30536

O valor de 35000 ultrapassou o limite superior do tipo int (32767).

É importante observar que em C, ao contrário de outras linguagens, a ultrapassagem do limite de


um tipo não é interpretado como erro. Isto pode acarretar resultados inesperados para o programador
desatento.

3.1.3 Atribuição múltipla.

E possível atribuir um valor a muitas variáveis em uma única instrução. A esta operação dá-se o
nome de atribuição múltipla.

Sintaxe: A sintaxe da atribuição múltipla é seguinte:


var_1 = [var_2 = ... ] expressão;
25
onde var_1, var_2, ... são os identificadores de variáveis e expressão é uma expressão
válida.

Observe que na atribuição múltipla as operações ocorrem da direita para a esquerda, isto é,
inicialmente o valor de expressão é atribuído a var_2 e depois o valor de var_2 é atribuído a
var_1. Deve-se tomar cuidado com as conversões de tipo e limites de intervalo para atribuições de tipos
diferentes.

Exemplo: Observe a instrução de atribuição múltipla abaixo: as variáveis inteiras i, j e k


são todas inicializadas com o valor 1. E as variáveis de dupla precisão max e min são inicializadas
com o valor 0.0:

int i, j, k;
double max, min;
i = j = k = 1;
max = min = 0.0;

Programa Exemplo: O arquivo e0301.cpp traz um programa para visualizar alguns aspectos
relacionados com o operador de atribuição. Execute o programa passo-a-passo e observe o valor das
variáveis.

3.2 Operadores Aritméticos

Existem cinco operadores aritméticos em C. Cada operador aritméticos está relacionado ao uma
operação aritmética elementar: adição, subtração, multiplicação e divisão. Existe ainda um operador (%)
chamado operador de módulo cujo significado é o resto da divisão inteira. Os símbolos dos operadores
aritméticos são:

Operador Operação
+ adição.
- subtração.
* multiplicação
/ divisão
% módulo (resto da divisão inteira)

26
Sintaxe: A sintaxe de uma expressão aritmética é:
operando operador operando

onde operador é um dos caracteres mostrados acima e operando é uma constante ou um


identificador de variável.

Exemplo: Algumas expressões aritméticas:


1+2 a-4.0 b*c valor_1/taxa num%2

Não existe em C, como existe em outras linguagens, um operador específico para a operação de
potenciação (ab). Existe, porém, uma função de biblioteca (pow()) que realiza esta operação. Veja a
seção 3.7 adiante. Embora as operações do C sejam semelhantes as operações aritméticas usuais da
matemática, alguns detalhes são específicos da linguagem, e devem ser observados.

3.2.1 Restrições de operandos.

Os operandos dos operadores aritméticos devem ser constantes numéricas ou identificadores de


variáveis numéricas. Os operadores +, -, *, / podem operar números de todos os tipos (inteiros ou
reais), porém o operador % somente aceita operandos inteiros.
Exemplo: Expressões válidas
Expressão Valor
6.4 + 2.1 8.5
7 - 2 5
2.0 * 2.0 4.0
6 / 3 2
47 % 2 1

Uma restrição ao operador de divisão (/) é que o denominador deve ser diferente de zero. Se
alguma operação de divisão por zero for realizada o correra um erro de execução do programa (run-time
error), o programa será abortado e a mensagem divide error será exibida.

Exemplo: A expressão abaixo é inválida pois o primeiro operando não é um numero inteiro.
Expressão Valor
6.4 % 3 invalido!

Podemos contornar o problema do operador inteiro da operação modulo usando o artifício da


conversão de tipo (casting) mostrada na seção 2.3.4:
27
Exemplo: Observe o trecho de programa abaixo:
int num;
float valor = 13.0;
num = valor % 2; // inválido!
num = (int)valor % 2; // válido!

Observe que usamos a conversão de tipo para que o dado armazenado em valor fosse
transformado no tipo int assim a operação módulo pode ser efetuada.

3.2.2 Conversão de tipo.

O resultado de uma operação aritmética depende dos tipos dos operandos. Se os operandos são
do mesmo tipo o resultado será do mesmo tipo. Se os operando forem de tipos diferentes então haverá
uma conversão de tipo tal que o tipo que ocupa menos espaço de memória será convertido para o tipo
que ocupa mais espaço de memória e o resultado será deste tipo. Em geral:

char → int → float → double


Esta é uma regra geral, alguns compiladores podem ter outras regras de conversão.

Exemplo: Observe as conversões de tipo abaixo:


Expressão Valor Conversão
6 + 2.0 8.0 int → float
7.000000 - 2.0000000000000 5.000000000000000 float → double
2 * 3.000000000000000 6.000000000000000 int → double

Observe que estas conversões podem gerar resultados surpreendentes para o programador
desatento.

Exemplo: Observe as expressões abaixo. Assuma que as variáveis num_i, num_f, den_i e
den_f são inicializadas como:
int num_i = 7 , den_i = 2 ;
float num_f = 7.0, den_f = 2.0;

Expressão Valor Operandos Resultado


num_f / den_f 3.5 float / float float
num_f / den_i 3.5 float / int float
num_i / den_f 3.5 int / float float
28
num_i / den_i 3 int / int int

Observe que no exemplo acima o valor da última expressão é 3 e não 3.5. Isto ocorre porque
como os dois operandos são tipo int o resultado e convertido para o tipo int e ocorre o truncamento. O
truncamento da divisão inteira é feito de modo a obter o menor valor absoluto.

Em C caracteres são armazenados na memória como números inteiros e por isso operações
aritméticas são permitidas com tipos char. Os valores usados são os correspondentes da tabela ASCII.

Exemplo: Observe as expressões abaixo:


Expressão Valor Conversão
’A’ + 1 ’B’ 65 + 1 → 66
’A’ + ’B’ ’â’ 65 + 66 → 131
’A’ + 32 ’a’ 65 + 32 → 97

3.2.4 Precedência de operadores.

Quando mais de um operador se encontram em uma expressão aritmética as operações são


efetuadas uma de cada vez respeitando algumas regras de precedência: Estas regras de precedência são as
mesmas da matemática elementar.

Os operadores de multiplicação (*), divisão (/) e módulo (%) tem precedência sobre os
operadores de adição (+) e subtração (-). Entre operadores de mesma precedência as operações são
efetuadas da esquerda para a direita. Veja a tabela 3.1.
Exemplo: Observe, nas expressões abaixo, o seu valor e a ordem das operações efetuadas:
Expressão Valor Ordem
1 + 2 - 3 0 + -
24 - 3 * 5 9 * -
4 - 2 * 6 / 4 + 1 2 * / - +
6 / 2 + 11 % 3 * 4 11 / % * +
A ordem de precedência dos operadores pode ser quebrada usando-se parênteses: ( ). Os
parênteses são, na verdade, operadores de mais alta precedência e são executados primeiro. Parênteses
internos são executados primeiro que parênteses externos.
Exemplo: Observe, nas expressões abaixo, o seu valor e a ordem das operações efetuadas:
Expressão Valor Ordem
1 + (2 - 3) 0 - +
(24 - 3) * 5 105 - *
(4 - 2 * 6) / 4 + 1 -1 * - / +
29
6 / ((2 + 11) % 3) * 4 24 + % / *

Observe que os operadores e os operandos deste exemplo são os mesmos do exemplo anterior. Os
valores, porém, são diferentes pois a ordem de execução das operações foi modificada pelo uso dos
parênteses.
Programa Exemplo: O arquivo e0302.cpp traz um programa para visualizar alguns aspectos
relacionados com os operadores aritméticos. Execute o programa passo-a-passo e observe o valor das
variáveis.

3.3 Operadores de Atribuição Aritmética


Muitas vezes queremos alterar o valor de uma variável realizando alguma operação aritmética
com ela. Como por exemplo: i = i + 1 ou val = val * 2. Embora seja perfeitamente possível
escrever estas instruções, foi desenvolvido na linguagem C uma instruções otimizadas com o uso de
operadores ditos operadores de atribuição aritmética. Os símbolos usado são (+=, -=, *=, /= ,
%=). Deste modo as instruções acima podem ser rescritas como: i += 1 e val *= 2,
respectivamente.
Sintaxe: A sintaxe da atribuição aritmética é a seguinte:
var += exp;
var -= exp;
var *= exp;
var /= exp;
var %= exp;

onde var é o identificador da variável e exp é uma expressão válida. Estas instruções são
equivalentes as seguintes:
var = var + exp;
var = var - exp;
var = var * exp;
var = var / exp;
var = var % exp;

Exemplo: Observe as atribuições aritméticas abaixo e suas instruções equivalentes:


Atribuição aritmética Instrução equivalente
i += 1; i = i + 1;
j -= val; j = j - val;
num *= 1 + k; num = num * (1 + k);
troco /= 10; troco = troco / 10;
resto %= 2; resto = resto % 2;
30
O operador de atribuição aritmética tem precedência menor que os outros operadores até aqui
discutidos. Veja a tabela 3.1.
Programa Exemplo: O arquivo e0303.cpp traz um programa para visualizar alguns aspectos
relacionados com os operadores de atribuição aritmética. Execute o programa passo-a-passo e observe o
valor das variáveis.

3.4 Operadores Incrementais


Em programação existem instruções muito comuns chamadas de incremento e decremento. Uma
instrução de incremento adiciona uma unidade ao conteúdo de uma variável. Uma instrução de
decremento subtrai uma unidade do conteúdo de uma variável.
Existem, em C, operadores específicos para realizar as operações de incremento (++) e
decremento (--). Eles são genericamente chamados de operadores incrementais.
Sintaxe: A sintaxe dos operadores incrementais é a seguinte:
instrução equivalente
++ var var = var + 1
var ++ var = var + 1
-- var var = var - 1
var -- var = var - 1
onde var é o nome da variável da qual se quer incrementar ou decrementar um unidade.

Observe que existem duas sintaxes possíveis para os operadores: pode-se colocar o operador à
esquerda ou á direita da variável. Nos dois casos o valor da variável será incrementado (ou
decrementado) de uma unidade. Porém se o operador for colocado á esquerda da variável, o valor da
variável será incrementado (ou decrementado) antes que a variável seja usada em alguma outra operação.
Caso o operador seja colocado à direita da variável, o valor da variável será incrementado (ou
decrementado) depois que a variável for usada em alguma outra operação.
Exemplo: Observe o fragmento de código abaixo e note o valor que as variáveis recebem após a
execução da instrução:
valor das variáveis
int a, b, c, i = 3; // a: ? b: ? c: ? i: 3
a = i++; // a: 3 b: ? c: ? i: 4
b = ++i; // a: 3 b: 5 c: ? i: 5
c = --i; // a: 3 b: 5 c: 4 i: 4
Os operadores incrementais são bastante usados para o controle de laços de repetição, que serão
vistos na seção ??. É importante que se conheça exatamente o efeito sutil da colocação do operador, pois
isto pode enganar o programador inexperiente.

31
Os operadores incrementais têm a mais alta precedência entre todos, sendo superados apenas
pelos parênteses que tem precedência ainda maior. Veja a tabela 3.1.
Programa Exemplo: O arquivo e0304.cpp traz um programa para visualizar alguns aspectos
relacionados com os operadores incrementais. Execute o programa passo-a-passo e observe o valor das
variáveis.

3.5 Operadores Relacionais e Lógicos


A chave para a flexibilidade de um algoritmo é a tomada de decisões através da avaliação
de condições de controle. Uma condição de controle é uma expressão lógica que é avaliadas como
verdadeira ou falsa. Uma expressão lógica é construída com operadores relacionais e lógicos.

3.5.1 Operadores relacionais


Operadores relacionais verificam a relação de magnitude e igualdade entre dois valores. São seis
os operadores relacionais em C:
Operador Significado
> maior que
< menor que
>= maior ou igual a (não menor que)
<= menor ou igual a (não maior que)
== igual a
!= não igual a (diferente de)
Sintaxe: A sintaxe das expressões lógicas é:
expressão_1 operador expressão_2

onde, expressão_1 e expressão_2 são duas expressões numéricas quaisquer, e


operador é um dos operadores relacionais.
Ao contrário de outras linguagens, em C não existem tipos lógicos, portanto o resultado de uma
expressão lógica é um valor numérico: uma expressão avaliada verdadeira recebe o valor 1, uma
expressão lógica avaliada falsa recebe o valor 0.
Se os operandos forem de tipos diferentes haverá uma conversão de tipo antes da avaliação da
expressão. Esta conversão de tipo é feita de acordo com a regra mostrada na seção 3.2.2.

Exemplo: Observe as expressões lógicas abaixo e verifique o resultado de sua avaliação. Admita
que i e j são variáveis int cujos valores são 5 e -3, respectivamente. As variáveis r e s são float
com valores 7.3 e 1.7, respectivamente.
Expressão Valor
i == 7 0
r != s 1
i > r 0
32
6 >= i 1
i < j 0
s <= 5.9 1

Os operadores relacionais de igualdade (== e !=) tem precedência menor que os de magnitude
(>, <, >= e <=). Estes, por sua vez, tem precedência menor que os operadores aritméticos. Operadores
relacionais de mesma precedência são avaliados da esquerda para a direita. Veja a tabela 3.1.

Exemplo: Observe as expressões lógicas abaixo e verifique o resultado de sua avaliação. Admita
que m e n são variáveis tipo int com valores 4 e 1, respectivamente.
Expressão Valor Ordem de Operação
m + n == 5 1 + ==
m != 2 * n > m 1 * > !=
6 >= n < 3 - m 0 - >= <
m == n <= m > m 0 <= > !=
3.5.2 Operadores lógicos
São três os operadores lógicos de C: &&, || e !. Estes operadores tem a mesma significação
dos operadores lógicos Booleanos AND, OR e NOT.

Sintaxe: A sintaxe de uso dos operadores lógicos:


expr_1 && expr_2
expr_1 || expr_2
!expr

onde expr_1 , expr_2 e expr são expressões quaisquer.


Observe que os operadores lógicos atuam sobre expressões de quaisquer valores. Para estes
operadores todo valor numérico diferente de 0 é considerado 1.

Exemplo: A seguir é mostrado o valor lógico de uma expressão qualquer:


Expressão Valor lógico
0 0
1 1
1.0 1
0.4 1
-5.2 1
onde expr_1 , expr_2 e expr são expressões quaisquer.
O resultado da operação lógica && será 1 somente se os dois operandos forem 1, caso contrário
o resultado é 0. O resultado da operação lógica || será 0 somente se os dois operandos forem 0, caso
contrário o resultado é 1. O resultado da operação lógica ! será 0 se o operandos for 1, e 1 se o
33
operando for 0. Abaixo mostra-se o resultado das possíveis combinações entre os operandos para cada
operador lógico:
Operador &&: op_1 op_2 Res
op_1 && op_2 1 1 1
1 0 0
0 1 0
0 0 0

Operador ||: op_1 op_2 Res


op_1 || op_2 1 1 1
1 0 1
0 1 1
0 0 0

Operador !: op Res
!op 1 0
0 1

O Operador && tem precedência sobre o operador ||. Estes dois têm precedência menor que os
operadores relacionais. O operador ! tem a mesma precedência que os operadores incrementais. Veja a
tabela 3.1.

Exemplo: Observe as expressões lógicas abaixo e verifique o resultado de sua avaliação. Admita
que a, b e c são variáveis tipo int com valores 0, 1 e 2, respectivamente.

Expressão Valor Ordem de Operação


a && b 0
c > b || a < c 1 > < ||
a + b && !c - b 1 ! + - &&
!b && c || a 0 ! && ||

Programa Exemplo: O arquivo e0305.cpp traz um programa para visualizar alguns aspectos
relacionados com os operadores lógicos e relacionais. Execute o programa passo-a-passo e observe o
valor das variáveis.

3.6 Operador Condicional


O operador condicional (?:) é usado em expressões condicionais. Uma expressão
condicional pode ter dois valores diferentes dependendo de uma condição de controle.

34
Sintaxe: A sintaxe de uma expressão condicional é:
condição ? expressão_1 : expressão_2

onde expressão_1 e expressão_2 são duas expressões quaisquer, e condição é uma


expressão lógica que será avaliada primeiro. Se o valor de condição for 1, isto é, verdadeiro, então a
expressão condicional assumirá o valor de expressão_1. Caso contrario assumirá o valor de
expressão_2. Uma expressão condicional é equivalente a uma estrutura de decisão simples:

se condição
então expressao_1
senão expressao_2
fim se

Exemplo: Observe as expressões condicionais abaixo e verifique o resultado de sua avaliação.


Admita que i, j e k são variáveis tipo int com valores 1, 2 e 3, respectivamente.

Expressão Valor
i ? j : k 2
j > i ? ++k : --k 4
k == i && k != j ? i + j : i - j -1
i > k ? i : k 3

O operador condicional tem baixa precedência, precedendo, apenas, aos operadores de atribuição.
Veja a tabela 3.1.

Programa Exemplo: O arquivo e0306.cpp traz um programa para visualizar alguns aspectos
relacionados com o operador condicional. Execute o programa passo-a-passo e observe o valor das
variáveis.

3.7 Funções de biblioteca


Uma função é um sub-programa (também chamado de rotina). Esta função recebe informações,
as processa e retorna outra informação. Por exemplo, podemos ter uma função que receba um valor
numérico, calcule seu logaritmo decimal e retorne o valor obtido. Existem dois tipos de funções: funções
de biblioteca e funções de usuário. Funções de biblioteca são funções escritas pelos fabricantes do
compilador e já estão pré-compiladas, isto é, já estão escritas em código de máquina. Funções de usuário
são funções escritas pelo programador. Nesta seção trataremos somente das funções de biblioteca, funções
de usuário serão vistas no capítulo ?.
35
3.7.1 O uso de funções
Antes de usar uma função é preciso saber como a função esta declarada, isto é, quais são os
parâmetros que a função recebe e quais são os para metros que a função retorna. Estas informações estão
contidas no manual do usuário do compilador ou em sua documentação on-line.
Sintaxe: A sintaxe de declaração de uma função é:
tipo_ret nome(tipo_1, tipo_2, ...)
onde nome é o nome da função, tipo_1, tipo_2, ... são os tipos (e quantidade) de parâmetros
de entrada da função e tipo_ret é o tipo de dado de retorno da função. Além dos tipos usuais vistos na
seção 2.3, existe ainda o tipo void (vazio, em inglês) que significa que aquele parâmetro é inexistente.

Exemplo: A função cos() da biblioteca math.h é declarada como:


double cos(double);

Isto significa que a função tem um parâmetro de entrada e um parâmetro de saída, ambos são do
tipo double.

Exemplo: A função getch() da biblioteca conio.h é declarada como:


int getch(void);

Isto significa que a função não tem parâmetros de entrada e tem um parâmetro int de saída.
Para podermos usar uma função de biblioteca devemos incluir a biblioteca na compilação do
programa. Esta inclusão é feita com o uso da diretiva #include colocada antes do programa principal,
como visto na seção 2.4.2.
Exemplo: Assim podemos usar a função no seguinte trecho de programa:
#include <math.h> // inclusão de biblioteca
void main(){ // inicio do programa principal
double h = 5.0; // hipotenusa
double co; // cateto oposto
double alfa = M_PI_4; // angulo: π/4
co = h * cos(alfa); // calculo: uso da funcao cos()
} // fim do programa

As funções têm alta precedência, sendo mais baixa apenas que os parênteses. A tabela 3.1 mostra
as precedências de todos os operadores estudados neste capítulo.

3.7.2 As bibliotecas disponíveis e algumas funções interessantes

36
A seguir segue uma lista de todas as bibliotecas disponíveis no compilador Turbo C++ 3.0
Borland: Ao longo do texto veremos o uso de muitas funções cobrindo uma boa parte destas bibliotecas,
porém o leitor que desejar tornar-se "fluente" na linguagem C pode (e deve) estudá-las com profundidade.

alloc.h assert.h bcd.h bios.h complex.h


conio.h ctype.h dir.h dirent.h dos.h
errno.h fcntl.h float.h fstream.h generic.h
graphics.h io.h iomanip.h iostream.h limits.h
locale.h malloc.h math.h mem.h process.h
setjmp.h share.h signal.h stdarg.h stddef.h
stdio.h stdiostr.h stdlib.h stream.h string.h
strstrea.h sys\stat.h sys\timeb.h sys\types.h time.h
values.h

Vejamos algumas funcoes disponiveis nas bibliotecas C.

Biblioteca math.h

int abs(int i);


double fabs(double d);
Calcula o valor absoluto do inteiro i e do real d, respectivamente.

double sin(double arco);


double cos(double arco);
double tan(double arco);
double asin(double arco);
double acos(double arco);
double atan(double arco);
Funções trigonometricas do ângulo arco, em radianos.

double ceil(double num);


double floor(double num);
Funções de arredondamento para inteiro.

ceil() arredonda para cima. Ex. ceil(3.2) == 3.0;


floor() arredonda para baixo. Ex. floor(3.2) == 4.0;

double log(double num);


double log10(double num);
37
Funções logarítmicas: log() é logaritmo natural (base e), log10() é logaritmo
decimal (base 10).

double pow(double base, double exp);


Potenciacao: pow(3.2,5.6) = 3.25.6.

double sqrt(double num);


Raiz quadrada: sqrt(9.0) = 3.0.

Biblioteca stdlib.h
int random(int num);
Gera um número inteiro aleatório entre 0 e num - 1.

Programa Exemplo: O arquivo e0307.cpp traz um programa para visualizar alguns aspectos
relacionados com funções de biblioteca. Execute o programa passo-a-passo e observe o valor das
variáveis.

3.8 Precedência entre os operadores do C


A tabela 3.1 mostra a ordem de precedência de todos os operadores estudados neste capítulo. Os
operadores de maior precedência são os parênteses e as chamadas de funções. Os operadores de menor
precedência são os operadores de atribuição.

Categoria Operadores Prioridade


parênteses ( ) interno → externo
função nome() E→D
incremental, lógico ++ -- ! E←D
aritmético * / % E→D
aritmético + - E→D
relacional < > <= >= E→D
relacional == != E→D
lógico && E→D
lógico || E→D
condicional ?: E←D
atribuição = += -= *= /= %= E←D
Tabela 3.1: Precedência dos operadores. Maior precedência no topo, menor precedência na base.

38
39
4. Entrada e Saída

Para que um programa torne-se minimamente funcional é preciso que ele receba dados do meio
externo (teclado, mouse, portas de comunicação, drives de disco, etc.) e emita o resultado de seu
processamento de volta para o meio externo (monitor, impressora, alto-falante, portas de comunicação,
drives de disco, etc.). De outro modo: um programa deve trocar informações com o meio externo. Em C,
existem muitas funções pré-definidas que tratam desta troca de informações. São as funções de entrada e
saída do C. Nos exemplos mostrados nos capítulos anteriores foram vistas algumas funções de entrada
(scanf(), getch()) e algumas funções de saída (printf()). Neste capítulo veremos, em detalhe,
estas e outras funções de modo a permitir escrever um programa completo em C.

Mostraremos, nas duas seções iniciais as mais importantes funções de entrada e saída de dados
em C: as funções printf() e scanf(). A partir do estudo destas funções é possível escrever um
programa propriamente dito com entrada, processamento e saída de dados.

4.1 Saída formatada: printf()

Biblioteca: stdio.h
Declaração: int printf (const char* st_contr [, lista_arg]);

Propósito: A função printf() (print formated) imprime dados da lista de argumentos


lista_arg formatados de acordo com a string de controle st_contr. Esta função retorna um valor
inteiro representando o número de caracteres impressos.

Esta função imprime dados numéricos, caracteres e strings. Esta função é dita de saída formatada
pois os dados de saída podem ser formatados (alinhados, com número de dígitos variáveis, etc.).

Sintaxe: A string de controle é uma máscara que especifica (formata) o que será impresso e de
que maneira será impresso.

Exemplo: Observe no exemplo abaixo as instruções de saída formatada e os respectivos


resultados.

40
Instrução Saída
printf(“Ola’, Mundo!“); Ola’, Mundo!
printf(“linha 1 \nlinha 2 “); linha 1
linha 2

Observe que na primeira instrução, a saída é exatamente igual a string de controle. Já na segunda
instrução a impressão se deu em duas linhas. Isto se deve ao \n que representa o código ASCII para
quebra de linha (veja seção 2.1.3).

Nesta mascara é possível reservar espaço para o valor de alguma variável usando especificadores
de formato. Um especificador de formato marca o lugar e o formato de impressão das variáveis contidas
na lista variáveis. Deve haver um especificador de formato para cada variável a ser impressa. Todos os
especificadores de formato começam com um %.

Exemplo: Observe no exemplo abaixo as instruções de saída formatada e os respectivos


resultados. Admita que idade seja uma variável int contendo o valor 29 e que tot e din sejam
variáveis float cujo valores são, respectivamente, 12.3 e 15.0.

Instrução:
printf(“Tenho %d anos de vida”,idade);
Saída:
Tenho 29 anos de vida

Instrução:
printf(“Total: %f.2 \nDinheiro: %f.2 \nTroco: %f.2“,tot,din,din-tot);
Saída:
Total: 12.30
Dinheiro: 15.00
Troco: 2.70

Depois do sinal %, seguem-se alguns modificadores, cuja sintaxe é a seguinte:


% [flag] [tamanho] [.precisão] tipo

[flag] justificação de saída: (Opcional)


- justificação à esquerda.

41
+ conversão de sinal (saída sempre com sinal: + ou -)
<espaço> conversão de sinal (saídas negativas com sinal, positivas sem sinal)

[tamanho] especificação de tamanho (Opcional)


n pelo menos n dígitos serão impressos (dígitos faltantes serão completados por
brancos).
0n pelo menos n dígitos serão impressos (dígitos faltantes serão completados por
zeros).

[.precisão] especificador de precisão, dígitos a direita do ponto decimal. (Opcional)


(nada) padrão: 6 dígitos para reais.
.0 nenhum digito decimal.
.n são impressos n dígitos decimais.

Tipo caracter de conversão de tipo (Requerido)


d inteiro decimal
o inteiro octal
x inteiro hexadecimal
f ponto flutuante: [-]dddd.dddd.
e ponto flutuante com expoente: [-]d.dddde[+/-]ddd
c caracter simples
s string

Programa Exemplo: O arquivo e0401.cpp contém um programa que ilustra o uso da função
printf() usando várias combinações de strings de controle e especificadores de formato. Execute o
programa passo-a-passo e verifique a saída dos dados.

4.2 Leitura formatada: scanf()

Biblioteca: stdio.h
Declaração: int scanf(const char* st_contr [, end_var, ...]);

Propósito: A função scanf() (scan formated) permite a entrada de dados numéricos, caracteres
e 'strings' e sua respectiva atribuição a variáveis cujos endereços são end_var. Esta função é dita de
entrada formatada pois os dados de entrada são formatados pela string de controle st_contr. a um
determinado tipo de variável (int, float, char, ...).
42
Sintaxe: O uso da função scanf() é semelhante ao da função printf(). A função lê da
entrada padrão (em geral, teclado) uma lista de valores que serão formatados pela string de controle e
armazenados nos endereços das variáveis da lista. A string de controle é formada por um conjunto de
especificadores de formato, cuja sintaxe é a seguinte:
% [*] [tamanho] tipo

* indicador de supressão (Opcional)


<presente> Se o indicador de supressão estiver presente o campo não é lido. Este supressor é
útil quando não queremos ler um campo de dado armazenado em arquivo.
<ausente> O campo é lido normalmente.

Tamanho especificador de tamanho(Opcional)


n Especifica n como o numero máximo de caracteres para leitura do campo.
<ausente> Campo de qualquer tamanho.

Tipo define o tipo de dado a ser lido (Requerido)


d inteiro decimal (int)
f ponto flutuante (float)
o inteiro octal (int)
x inteiro hexadecimal (int)
i inteiro decimal de qualquer formato(int)
u inteiro decimal sem sinal (unsigned int)
s string (char*)
c caracter (char)

A lista de variáveis é o conjunto de (endereços) de variáveis para os quais serão passados os


dados lidos. Variáveis simples devem ser precedidos pelo caracter &. Veja mais sobre endereços na seção
?.? Variáveis string e vetores não são precedidos pelo caracter &. Veja mais sobre strings e vetores na
seção ?.?

Programa exemplo: O arquivo e0402.cpp contém um programa que ilustra o uso da função
scanf() na leitura de dados. Execute o programa passo-a-passo e verifique como os especificadores de
formato agem sobre os dados digitados.

4.3 Entrada de caracter individual: getchar()


43
Biblioteca: stdio.h
Declaração: int getchar(void);

Propósito: A função getchar() (get character) lê um caracter individual da entrada padrão


(em geral, o teclado). Se ocorrer um erro ou uma condição de 'fim-de-arquivo' durante a leitura, a função
retorna o valor da constante simbólica EOF (end of file)definida na biblioteca stdio.h. Esta função
permite uma forma eficiente de detecção de finais de arquivos.

Esta função é dita line buffered, isto é, não retorna valores até que o caracter de controle line feed
(\n) seja lido. Este caracter, normalmente, é enviado pelo teclado quando a tecla [enter] é
pressionada. Se forem digitados vários caracteres, estes ficarão armazenados no buffer de entrada até que
a tecla [enter] seja pressionada. Então, cada chamada da função getchar() lerá um caracter
armazenado no buffer.

4.4 Saída de caracter individual: putchar()

Biblioteca: stdio.h
Declaração: int putchar(int c);

Propósito: Esta função putchar() (put character) imprime um caracter individual c na saída
padrão (em geral o monitor de vídeo).

Programa Exemplo: O programa e0403.cpp mostra o uso das funções getchar() e


putchar() em um programa que lê caracteres do teclado e os reimprime convertidos para maiúsculos.

4.5 Leitura de teclado: getch(), getche()

Biblioteca: conio.h
Declaração: int getch(void);
int getche(void);

44
Propósito: Estas funções fazem a leitura dos códigos de teclado. Estes códigos podem representar
tecla s de caracteres (A, y, *, 8, etc.), teclas de comandos ( [enter], [delete], [Page Up], [F1], etc.)
ou combinação de teclas ([Alt] + [A], [Shift] + [F1], [Ctrl] + [Page Down], etc.).

Ao ser executada, a função getch() (get character) aguarda que uma tecla (ou combinação de
teclas) seja pressionada, recebe do teclado o código correspondente e retorna este valor. A função
getche()(get character and echoe) também escreve na tela, quando possível, o caracter
correspondente.

Código ASCII: ao ser pressionada uma tecla correspondente a um caracter ASCII, o teclado
envia um código ao 'buffer' de entrada do computador e este código é lido. Por exemplo, se a tecla A for
pressionada o código 65 será armazenado no buffer e lido pela função.

Código Especial: ao serem pressionadas certas teclas (ou combinação de teclas) que não
correspondem a um caracter ASCII, o teclado envia ao 'buffer' do computador dois códigos, sendo o
primeiro sempre 0. Por exemplo, se a tecla [F1] for pressionada os valores 0 e 59 serão armazenados e a
função deve ser chamada duas vezes para ler os dois códigos.

Programa exemplo: O arquivo e0404.cpp mostra um programa para a leitura de teclado. Este
programa usa a função getch() para reconhecer teclas e combinação de teclas.

Programa exemplo: O arquivo e0405.cpp mostra um programa para a leitura de teclado


usando a função getche().

4.6 Escrita formatada em cores: cprintf()


Biblioteca: conio.h
Declaração: int cprintf (const char* st_contr [, lista_arg]);

Propósito: Esta função cprintf() (color print formated) permite a saída de dados numéricos,
caracteres e strings usando cores. O uso da função cprintf()é semelhante a printf()porém permite
que a saída seja a cores. Para que a saída seja colorida é necessário definir as cores de fundo e de letra
para a impressão antes do uso da função.

Cores (Modo Texto)


Cor Constante Valor Fundo Letra
Preto BLACK 0 ok ok
Azul BLUE 1 ok ok
45
Verde GREEN 2 ok ok
Cian CYAN 3 ok ok
Vermelho RED 4 ok ok
Magenta MAGENTA 5 ok ok
Marrom BROWN 6 ok ok
Cinza Claro LIGHTGRAY 7 ok ok
Cinza Escuro DARKGRAY 8 -- ok
Azul Claro LIGHTBLUE 9 -- ok
Verde Claro LIGHTGREEN 10 -- ok
Cian Claro LIGHTCYAN 11 -- ok
Vermelho Claro LIGHTRED 12 -- ok
Magenta Claro LIGHTMAGENTA 13 -- ok
Amarelo YELLOW 14 -- ok
Branco WHITE 15 -- ok
Piscante BLINK 128 -- ok

Estas definições são feitas pelas funções texcolor() e textbackground() cuja sintaxe é:
textcolor(cor_de_letra);
textbackground(cor_de_fundo);
onde cor_de_letra e cor_de_fundo são números inteiros referentes as cores da palheta
padrão (16 cores, modo texto). Estes valores de cor são representadas por constantes simbólicas definidas
na biblioteca conio.h. Para se usar uma letra piscante deve-se adicionar o valor 128 ao valor da cor de
letra. Alguns valores de cor não podem ser usados como cor de fundo. A relação acima mostra as cores,
suas constantes simbólicas e onde podem ser usadas:
Exemplo: O trecho de programa abaixo imprime uma mensagem de alerta em amarelo piscante
sobre fundo vermelho.
#include <conio.h>
...
textbackground(RED);
textcolor(YELLOW + BLINK);
cprintif(“ Alerta: Vírus Detectado! ”);
...

Programa Exemplo: O programa do arquivo e0406.cpp mostra todas as combinações


possíveis de impressão colorida em modo texto.

4.7 Saída sonora: sound(), delay(), nosound()

Biblioteca: dos.h
46
Declarações: void sound(unsigned freq);
void delay(unsigned tempo);
void nosound(void);

Propósito: A função sound() ativa o alto-falante do PC com uma freqüência freq (Hz). A
função delay() realiza uma pausa (aguarda intervalo de tempo) de duração tempo (milisegundos). A
função nosound() desativa o alto-falante.
Programa Exemplo: O uso destas funções é muito simples mas produz resultados interessantes.
No arquivo e0407.cpp temos um exemplo do uso de sons em programas.

4.8 Limpeza de tela: clrscr(), clreol()


Biblioteca: conio.h
Declarações: void clrscr(void);
void clreol(void);

Propósito: A função clrscr() (clear screen) limpa a janela de tela e posiciona o cursor na
primeira linha e primeira coluna da janela (canto superior esquerdo da janela). A função clreol()
(clear to end of line) limpa uma linha desde a posição do cursor até o final da linha mas não modifica a
posição do cursor. Ambas funções preenchem a tela com a cor de fundo definida pela função
textbacground().

4.9 Posicionamento do cursor: gotoxy()


Biblioteca: conio.h
Declarações: void gotoxy(int pos_x, int pos_y);

Propósito: Em modo texto padrão, a tela é dividida em uma janela de 25 linhas e 80 colunas. A
função gotoxy() permite posicionarmos o cursor em qualquer posição (pos_x,pos_y) da tela.
Sendo que a posição (1,1) corresponde ao canto superior esquerdo da tela e a posição (80,25) corresponde
ao canto inferior direito. Como as funções printf() e cprintf() escrevem a partir da posição do
cursor, podemos escrever em qualquer posição da tela.

4.10 Redimencionamento de janela: window()


Biblioteca: conio.h
Declarações: void window(int esq, int sup, int dir, int inf);

47
Propósito: Esta função permite redefinir a janela de texto. As coordenadas esq e sup definem o
canto superior esquerdo da nova janela, enquanto as coordenadas inf e dir definem o canto inferior
direito da nova janela. Para reativar a janela padrão escreve-se a instrução window(1,1,80,25).
Quando uma janela é definida, o texto que ficar fora da janela fica congelado até que se redefina a janela
original.

4.11 Monitoração de teclado: kbhit()


Biblioteca: conio.h
Declarações: int kbhit(void);
Propósito: Esta função (keyboard hitting) permite verificar se uma tecla foi pressionada ou não.
Esta função verifica se existe algum código no buffer de teclado. Se houver algum valor, ela retorna um
número não nulo e o valor armazenado no buffer pode ser lido com as funções getch() ou getche().
Caso nenhuma tecla seja pressionada a função retorna 0. Observe que, ao contrário de getch(), esta
função não aguarda que uma tecla seja pressionada.

Programa Exemplo: O arquivo e0408.cpp contém um programa para exemplificar o uso das
funções clrscr(), clreol(), gotoxy(), window(), kbhit().

48
5. Estruturas de Controle

Estruturas de controle permitem controlar a seqüência das ações lógicas de um programa.


Basicamente, existem dois tipos de estruturas de controle: estruturas de repetição e estruturas de
decisão. A estrutura de repetição permite que um bloco de instruções seja executado repetidamente uma
quantidade controlada de vezes. A estrutura de decisão permite executar um entre dois ou mais blocos de
instruções. Neste capítulo estudaremos em detalhe as instruções do C que permitem implementar estas
estruturas.

5.1 Condição de controle


Em todas as estruturas, existe pelo menos uma expressão que faz o controle de qual bloco de
instruções será executado ou quantas vezes ele será executado: é o que chamamos de condição de
controle. Uma condição de controle é uma expressão lógica ou aritmética cujo resultado pode ser
considerado verdadeiro ou falso. Conforme vimos na seção 3.5, a linguagem C não possui, entretanto,
variáveis ou constantes lógicas, possui somente expressões numéricas, assim quando uma expressão
numérica se encontra em uma condição de controle, ela será considerada falsa se seu valor for igual a
zero, e verdadeira se seu valor for diferente de zero.

Exemplo: Observe nas condições abaixo, seu valor numérico e seu significado lógico. Considere
as variáveis int i = 0, j = 3;
condição valor numérico significado lógico
(i == 0) 1 verdadeiro
(i > j) 0 falso
(i) 0 falso
(j) 3 verdadeiro

Este fato deve ficar claro pois, nas estruturas que estudaremos neste capítulo, quando for dito que
uma condição é falsa ou verdadeira quer se dizer que seu valor e igual a zero ou diferente de zero.

5.2 Estrutura do...while

Esta é uma estrutura básica de repetição condicional. Permite a execução de um bloco de


instruções repetidamente. Sua sintaxe é a seguinte:

49
Sintaxe:
do{
bloco
}while(condição);

onde: condição é uma expressão lógica ou numérica.


bloco é um conjunto de instruções.

Esta estrutura faz com que o bloco de instruções seja executado pelo menos uma vez. Após a
execução do bloco, a condição é avaliada. Se a condição é verdadeira o bloco é executado outra vez,
caso contrário a repetição é terminada. Ofluxograma desta estrutura é mostrada na figura 5.1:

bloco

condição? V

Figura 5.1: Fluxograma da estrutura do...while.

Exemplo: No trecho abaixo, a leitura de um número é feita dentro de um laço de repetição


condicional. A leitura é repetida caso o número lido seja negativo.
do{
puts("Digite um número positivo:");
scanf("%f",&num);
}while(num <= 0.0);

Programa exemplo: No arquivo e0501.cpp existe um programa que calcula o fatorial de um


número. Este programa ilustra o uso da estrutura do...while.

5.3 Estrutura while

A estrutura de repetição condicional while é semelhante a estrutura do...while. Sua


sintaxe é a seguinte:

50
Sintaxe:
while(condição){
bloco
}

onde: condição é uma expressão lógica ou numérica.


bloco é um conjunto de instruções.

Esta estrutura faz com que a condição seja avaliada em primeiro lugar. Se a condição é
verdadeira o bloco é executado uma vez e a condição é avaliada novamente. Caso a condição seja falsa a
repetição é terminada sem a execução do bloco. Observe que nesta estrutura, ao contrário da estrutura
do...while, o bloco de instruções pode não ser executado nenhuma vez, basta que a condição seja
inicialmente falsa. O fluxograma desta estrutura é mostrada na figura 5.2:

F condição?

bloco

Figura 5.2: Fluxograma da estrutura while.

Exemplo: No trecho abaixo, calcula-se a precisão (ε) do processador aritmético do PC. A


variável eps tem seu valor dividido por 2 enquanto o processador conseguir distinguir entre 1 e 1+ε.
Após a execução do laço, o valor de eps contém a precisão da máquina.
eps = 1.0;
while(1.0 + eps > 1.0){
eps /= 2.0;
}

Programa exemplo: No arquivo e0502.cpp existe um programa que calcula a raiz quadrada
de um número real positivo usando o método de Newton. Este programa ilustra o uso da estrutura
while.
51
5.4 Estrutura for

A estrutura for é muito semelhante as estruturas de repetição vistas anteriormente, entretanto


costuma ser utilizada quando se quer um número determinado de ciclos. A contagem dos ciclos é feita por
uma variável chamada de contador. A estrutura for é, as vezes, chamada de estrutura de repetição com
contador. Sua sintaxe é a seguinte:

Sintaxe:
for(inicialização; condição; incremento){
bloco
}

onde: inicialização é uma expressão de inicialização do contador.


condição é uma expressão lógica de controle de repetição.
incremento é uma expressão de incremento do contador.
bloco é um conjunto de instruções a ser executado.

Esta estrutura executa um número determinado de repetições usando um contador de iterações. O


contador é inicializado na expressão de inicialização antes da primeira iteração. Por exemplo:
i = 0; ou cont = 20;. Então o bloco é executado e depois de cada iteração, o contador é
incrementado de acordo com a expressão de incremento. Por exemplo: i++ ou cont -= 2.
Então a expressão de condição é avaliada: se a condição for verdadeira, o bloco é executado
novamente e o ciclo recomeça, se a condição é falsa termina-se o laço. Esta condição é, em geral, uma
expressão lógica que determina o ultimo valor do contador. Por exemplo: i <= 100 ou cont > 0.

Exemplo: No trecho abaixo, o contador i é inicializado com o valor 1. O bloco é repetido


enquanto a condição i <= 10 for verdadeira. O contador é incrementado com a instrução i++. Esta
estrutura, deste modo, imprime os números 1, 2, ..., 9, 10.
for(i=1; i<=10; i++){
printf(" %d",i);
}

É interessante notar que a mesma estrutura lógica pode ser implementada usando as estruturas
for ou do...while:

52
Exemplo: As seguintes instruções são plenamente equivalentes:
i = 0; for(i = 0; i <= 100; i++){
do{ bloco
bloco }
i++;
}while(i <= 100);

Podem existir mais de uma expressão de inicialização e de incremento na estrutura


for. Estas expressões devem ser separadas por vírgula (,). Mas não pode haver mais de uma expressão
de condição. Por exemplo: for(i=0, j=10; i<10; i++, j--){...}

Programa exemplo: No arquivo e0503.cpp existe um programa que calcula a amplitude de


um conjunto de valores. Este programa exemplifica o uso da estrutura for...

5.5 Estrutura de decisão if...else

A estrutura if...else é a mais simples estrutura de controle do C. Esta estrutura permite


executar um entre vários blocos de instruções. O controle de qual bloco será executado será dado por uma
condição (expressão lógica ou numérica). Esta estrutura pode se apresentar de modos ligeiramente
diferentes. Nesta seção vamos apresentar separadamente cada uma das possibilidades de sintaxe.

5.5.1 Decisão de um bloco (if...)

A estrutura de decisão de um bloco permite que se execute (ou não) um bloco de instruções
conforme o valor de uma condição seja verdadeiro ou falso. O fluxograma desta estrutura é mostrada na
figura 5.3.

condição V

F bloco

Figura 5.3: Fluxograma da estrutura de decisão if...

53
Sintaxe: Decisão com um bloco:
if(condição){
bloco
}
onde: condição é uma expressão lógica ou numérica.
bloco é um conjunto de instruções.

Se a condição verdadeira, o bloco é executado. Caso contrário, o bloco não é executado.

Exemplo: No trecho abaixo, se o valor lido for maior que 10, então o seu valor é redefinido como
10. Observe que o bloco constitui-se de um única instrução.
printf("Digite o número de repetições: (máximo 10)";
scanf("%d",&iter);
if(iter > 10){
iter = 10;
}

Programa Exemplo: O arquivo e0504.cpp mostra um programa que utiliza a estrutura


if... para emitir um sinal sonoro ao imprimir um número múltiplo de 4.

5.5.2 Decisão de dois blocos (if...else)

Também é possível escrever uma estrutura que execute um entre dois blocos de instruções. A
figura 5.4 mostra o fluxograma correspondente a esta estrutura de decisão.

condição?

bloco 1 bloco 2

Figura 5.4: Fluxograma da estrutura de decisão if...else

Sintaxe: Decisão de dois blocos:


if(condição){
54
bloco 1;
}else{
bloco 2;
}

onde: condição é uma expressão lógica ou numérica.


bloco 1 e bloco 2 são conjuntos de instruções.

Se a condição for verdadeira o bloco 1 é executado. Caso contrário, o bloco 2 é


executado.
Exemplo: No trecho abaixo, se o valor de raiz*raiz for maior que num o valor de raiz
será atribuído a max, caso contrario, será atribuído a min.
if(raiz*raiz > num){
max = raiz;
}else{
min = raiz;
}
Programa Exemplo: O arquivo e0505.cpp mostra um programa que utiliza a estrutura
if...else para determinar o tipo de raízes de uma equação de segundo grau.

5.5.3 Decisão de múltiplos blocos (if...else if...)


Também é possível escrever uma estrutura que execute um entre múltiplos blocos de instruções.
A figura 5.5 mostra o fluxograma correspondente a esta estrutura de decisão.

55
Condição
F
1?

V
Condição
F
2?
bloco 1

V
Condição
F
3?
bloco 2
...
V

bloco 3

...

Figura 5.5: Fluxograma da estrutura de decisão if...else if.

Sintaxe: Decisão de múltiplos blocos:


if(condição 1){
bloco 1;
...
}else if(condição N){
bloco N;
}else{
bloco P
}
onde: condição 1, condição 2, ... são expressões lógicas ou numéricas.
bloco 1 , bloco 2,... são conjuntos de instruções.

Se a condição 1 for verdadeira o bloco 1 é executado. Caso contrario, a condição 2 é


avaliada. Se a condição 2 for verdadeira o bloco 2 é executado. Caso contrario, a condição 3 é
avaliada e assim sucessivamente. Se nenhuma condição é verdadeira bloco P é executado. Observe
que apenas um dos blocos é executado.

56
Exemplo: No trecho abaixo, uma determinada ação é executada se o valor de num for positivo,
negativo ou nulo.
if(num > 0){
a = b;
}else if(num < 0){
a = b + 1;
}else{
a = b - 1;
}

Programa Exemplo: O arquivo e0506.cpp mostra um programa que utiliza a estrutura


if...else if para determinar se um número é maior, menor ou igual a outro.

5.6 Estrutura switch...case

A estrutura switch...case é uma estrutura de decisão que permite a execução de um


conjunto de instruções a partir pontos diferentes conforme o resultado de uma expressão inteira de
controle. O resultado deste expressão é comparado ao valor de cada um dos rótulos, e as instruções são
executadas a partir desde rótulo. A figura 5.6 mostra o fluxograma lógico desta estrutura.

57
expressão

rotulo 1

conjunto 1

rotulo 2

conjunto 2

...

rotulo N

conjunto N

rotulo D

conjunto D

Figura 5.6: Fluxograma da estrutura switch...case.

Sintaxe: Esta estrutura possui a seguinte sintaxe:


switch(expressão){
case rótulo_1:
conjunto_1
case rótulo_2:
conjunto_2
...
case rótulo_n:
conjunto n
[default:
conjunto d]
}
onde:
expressão é uma expressão inteira.
rótulo_1,rótulo_2,...rótulo_n e rótulo_d são constantes inteiras.
conjunto 1, conjunto 2, ..., conjunto n e conjunto d são
conjuntos de instruções.
58
O valor de expressão é avaliado e o fluxo lógico será desviado para o conjunto cujo rótulo
é igual ao resultado da expressão e todas as instruções abaixo deste rótulo serão executadas. Caso o
resultado da expressão for diferente de todos os valores dos rótulos então conjunto d é executado.
Os rótulos devem ser expressões constantes inteiras diferentes entre si. O rótulo default é opcional.
Esta estrutura é particularmente útil quando se tem um conjunto de instruções que se deve
executar em ordem, porém se pode começar em pontos diferentes.
Exemplo: O trecho abaixo ilustra o uso da instrução switch em um menu de seleção. Neste
exemplo, o programa iniciará o processo de usinagem de uma peça em um ponto qualquer dependendo do
valor lido.
int seleção;
puts("Digite estagio de usinagem:");
scanf("%d",&selecao);
switch(seleção){
case 1:
// desbaste grosso...
case 2:
// desbaste fino...
case 3:
// acabamento...
case 4:
// polimento...
}
Programa Exemplo: O arquivo e0507.cpp mostra um programa que utiliza a estrutura
switch para determinar o valor de um lanche.

5.7 Interrupção e desvio: break, continue, goto, exit()


As instruções vistas anteriormente podem sofrer desvios e interrupções em sua seqüência lógica
normal através do uso certas instruções. As instruções que veremos a seguir devem ser usadas com muita
parcimônia, pois fogem da lógica estruturada tem a tendência de tornar um programa incompreensível.

5.7.1 A instrução break.

Esta instrução serve para terminar a execução das instruções de um laço de repetição (for,
do...while, while) ou para terminar um conjunto switch...case.
Quando em um laço de repetição, esta instrução força a interrupção do laço independentemente
da condição de controle.
Exemplo: No trecho abaixo um laço de repetição lê valores para o cálculo de uma média. O laço
possui uma condição de controle sempre verdadeira o que, a principio, é um erro: laço infinito. Porém, a
saída do laço se dá pela instrução break que é executada quando um valor negativo é lido.
59
puts("digite valores:");
do{
puts("valor:");
scanf("%f",&val);
if(val < 0.0){
break; // saída do laço
}
num++;
soma += val;
}while(1); // sempre verdadeiro
printf("média: %f",soma/num);

Exemplo: No exemplo acima, o uso da instrução break poderia ter sido evitado, como segue:

puts("digite valores:");
do{
puts("valor:");
scanf("%f",&val);
if(val >= 0.0){
num++;
soma += val;
}
}while(val >= 0.0);
printf("média: %f",soma/num);

O outro uso da instrução break, em estruturas switch...case, serve para separar os


conjuntos de instruções em cada case.

Exemplo: Estrutura switch...case com a instrução break:


int tipo;
puts("Selecione o sabor de sua pizza:");
puts("Muzzarela Calabreza Alho&Oleo:");
tipo = getch();
switch(tipo){
case ´M´:
// prepara pizza muzzarela...
case ´C´:
// prepara pizza calabreza...
case ´A´:

60
// prepara pizza Alho&Oleo...
default:
puts("Opcao incorreta");
}

Programa Exemplo: O arquivo e0508.cpp mostra um programa que utiliza a estrutura


switch com a instrução break para simular um piano no teclado do computador.

5.7.2 A instrução continue.

Esta instrução opera de modo semelhante a instrução break dentro de um laço de repetição.
Quando executada, ela pula as instruções de um laço de repetição sem sair do laço. Isto é, a instrução
força a avaliação da condição de conttrole do laço.

Exemplo: No trecho abaixo revemos um laço de repetição lê valores para o cálculo de uma
média. Se (val < 0.0) então o programa salta diretamente para a condição de controle, sem executar
o resto das instruções.
puts("digite valores:");
do{
puts("valor:");
scanf("%f",&val);
if(val < 0.0){ // se val é negativo...
continue; // ...salta para...
}
num++; // se (val < 0.0) estas instruções
soma += val; // não são executadas!
}while(val >= 0.0); // ...fim do laço
printf("média: %f",soma/num);

5.7.3 A instrução goto.


Esta instrução é chamada de desvio de fluxo. A instrução desvia o programa para um rótulo
(posição identificada) no programa. São raros os casos onde a instrução goto é necessária, no entanto, há
certas circunstâncias, onde usada com prudência, ela pode ser útil.

61
Sintaxe: A sintaxe da instrução goto é a seguinte:
goto rótulo;
...
rótulo:
...

onde rótulo é um identificador válido.

Exemplo: No trecho abaixo revemos um laço de repetição lê valores para o cálculo de uma
média. Foram usadas duas instruções goto.
puts("digite valores:");
inicio: // rótulo
puts("valor:");
scanf("%f",&val);
if(val < 0.0){ // se val é negativo...
goto fim; // ...salta para fim
}
num++; // se (val < 0.0) estas instruções
soma += val; // não são executadas!
goto inicio; // salta para inicio
fim: // rótulo
printf("média: %f",soma/num);

5.7.4 A função exit().

Esta função (não instrução) exit() , da biblioteca stdlib.h, é uma função que termina a
execução de um programa. Normalmente um programa é terminado quando se executa a última sua
instrução, porém pode-se terminar a execução do programa a qualquer momento com o uso desta função.
A função exit() tem a seguinte declaração: void exit(int status). Onde o argumento
da função é um valor inteiro que será passado para o Sistema Operacional: (variável de sistema
errorlevel no DOS).

Exemplo: No trecho abaixo revemos um laço de repetição lê valores para o cálculo de uma
média. Foi usado a função exit para terminar a execução do programa.
62
puts("digite valores:");
do{
puts("valor:");
scanf("%f",&val);
if(val < 0.0){ // se val é negativo...
printf("média: %f",soma/num); // imprime resultado
exit(0); // termina programa
}
num++; soma += val;
}while(1);

63
6. Funções

Funções (também chamadas de rotinas, ou sub-programas) são a essência da programação


estruturada. Funções são segmentos de programa que executam uma determinada tarefa específica. Já
vimos o uso de funções nos capítulos anteriores: funções já providenciadas pelas bibliotecas-padrão do C
(como sqrt(), toupper(), getch() ou putchar()).

É possível ao programador, alem disso, escrever suas próprias rotinas. São as chamadas de
funções de usuário ou rotinas de usuário. Deste modo pode-se segmentar um programa grande em vários
programas menores. Esta segmentação é chamada de modularização e permite que cada segmento seja
escrito, testado e revisado individualmente sem alterar o funcionamento do programa como um todo.
Permite ainda que um programa seja escrito por vários programadores ao mesmo tempo, cada um
escrevendo um segmento separado. Neste capítulo, veremos como escrever funções de usuário em C.

6.1 Estrutura das funções de usuário

A estrutura de uma função de usuário é muito semelhante a estrutura dos programas que
escrevemos até agora. Uma função de usuário constitui-se de um bloco de instruções que definem os
procedimentos efetuados pela função, um nome pelo qual a chamamos e uma lista de argumentos
passados a função. Chamamos este conjunto de elementos de definição da função.

Exemplo: o código mostrado abaixo é uma função definida pelo usuário para calcular a média
aritmética de dois números reais:
float media2(float a, float b){
float med;
med = (a + b) / 2.0;
return(med);
}

No exemplo acima definimos uma função chamada media2 que recebe dois argumentos tipo
float: a e b. A média destes dois valores é calculada e armazenada na variável med declarada
internamente. A função retorna, para o programa que a chamou, um valor também do tipo float: o valor
da variável med. Este retorno de valor é feito pela função return()que termina a execução da função e
retorna o valor de med para o programa que a chamou.
64
Depois de definimos um função, podemos usá-la dentro de um programa qualquer. Dizemos que
estamos fazendo uma chamada a função.

Exemplo: No exemplo abaixo chamamos a função media2() dentro de um programa principal:


void main(){
float num_1, num_2, med;
puts(”Digite dois números:”);
scanf(”%f %f”, &num_1, &num_2);
med = media2(num_1, num_2); // chamada a função
printf(”\nA media destes números e´ %f”, med);
}

6.2 Definição de funções

De modo formal, a sintaxe de uma função é a seguinte:

tipo_de_retorno nome_da_função(tipo_1 arg_1, tipo_2 arg_2, ...){


[bloco de instruções da função]
}

A primeira linha da função contém a declaração da função. Na declaração de uma função se


define o nome da função, seu tipo de retorno e a lista de argumentos que recebe. Em seguida, dentro de
chaves {}, definimos o bloco de instruções da função.

O tipo de retorno da função especifica qual o tipo de dado retornado pela função, podendo ser
qualquer tipo de dado mostrado na seção 2.3: int, float, etc. Se a função não retorna nenhum valor
para o programa que a chamou devemos definir o retorno como void, ou seja um retorno ausente. Se
nenhum tipo de retorno for especificado o compilador entenderá que o retorno será tipo int.

Vale notar que existe apenas um valor de retorno para funções em C. Não podemos fazer o
retorno de dois ou mais valores como em algumas linguagens (no MatLab: [media,desvio] =
estat(a, b, c, d, e)). Porém isto não é um limitação séria pois o uso de ponteiros (cap. ?)
contorna o problema.

Por ser um identificador, o nome da função segue as mesmas regras de definição de


identificadores (veja seção 2.2).
65
A lista de argumentos da função especifica quais são os valores que a função recebe. As
variáveis da lista de argumentos são manipuladas normalmente no corpo da função (veja seção 6.5
adiante).

A chamada de uma função termina com a instrução return() que transfere o controle para o
programa chamador da função. Esta instrução tem duas finalidades: determina o fim lógico da rotina e o
valor de retorno da função. O argumento de return() será retornado como valor da função.

6.3 Localização das funções

Existem basicamente duas posições possíveis para escrevermos o corpo de uma função: ou antes
ou depois do programa principal. Podemos ainda escrever uma função no mesmo arquivo do programa
principal ou em arquivo separado.

6.3.1 Corpo da função antes do programa principal (no mesmo arquivo)

Quando escrevemos a definição de uma função antes do programa principal e no mesmo arquivo
deste, nenhuma outra instrução é necessária. A sintaxe geral para isto é a seguinte:

Sintaxe: Uma função escrita antes do programa principal:

tipo nomef(...){ // definição da função


[corpo de função]
}
void main(){ // programa principal
...
var = nomef(...) // chamada da função
...
}

Exemplo: Função media2() escrita antes do programa principal.

float media2(float a, float b){ // função


float med;
66
med = (a + b) / 2.0;
return(med);
}
void main(){ // programa principal
float num_1, num_2, med;
puts(”Digite dois números:”);
scanf(”%f %f”, &num_1, &num_2);
med = media2(num_1, num_2); // chamada da função
printf(”\nA media destes números e´ %f”, med);
}

Programa exemplo: No arquivo e0601.cpp existe um programa que calcula o maior valor
entre dois números digitados. Este programa faz uso da função max()escrita pelo usuário.

6.3.2 Corpo da função depois do programa principal (no mesmo arquivo)

Quando escrevemos a definição de uma função depois do programa principal e no mesmo


arquivo deste, devemos incluir um protótipo da função chamada. Um protótipo é uma instrução que
define o nome da função, seu tipo de retorno e a quantidade e o tipo dos argumentos da função. O
protótipo de uma função indica ao compilador quais são as funções usadas no programa principal os tipo.
A sintaxe geral para isto é a seguinte:

Sintaxe: Uma função escrita depois do programa principal:


void main(){ // programa principal
tipo nomef(...); // protótipo da função
...
var = nomef(...) // chamada a função
...
}
tipo nomef(...){ // definição da função
[corpo de função]
}

Exemplo: Função media2() escrita depois do programa principal.

void main(){ // programa principal


float media2(float,float); // protótipo de media2()

67
float num_1, num_2, med;
puts(”Digite dois números:”);
scanf(”%f %f”, &num_1, &num_2);
med = media2(num_1, num_2); // chamada a função
printf(”\nA media destes números e´ %f”, med);
}
float media2(float a, float b){ // função media2()
float med;
med = (a + b) / 2.0;
return(med);
}

Observe que o protótipo de uma função nada mais é que a declaração da função sem o seu corpo.
Observe ainda que na lista de argumentos do protótipo podem ser escritos apenas os tipos dos
argumentos.

Programa exemplo: No arquivo e0602.cpp existe um programa que calcula o maior valor
entre dois números digitados. Este programa faz uso da função max()escrita pelo usuário.

6.3.3 Corpo da função escrito em arquivo separado

Em C, como em muitas outras linguagens, é permitido que o usuário crie uma função em um
arquivo e um programa que a chame em outro arquivo distinto. Esta facilidade permite a criação de
bibliotecas de usuário: um conjunto de arquivos contendo funções escritas pelo usuário. Esta
possibilidade é uma grande vantagem utilizada em larga escala por programadores profissionais.

Quando escrevemos a definição de uma função em arquivo separado do programa principal


devemos incluir este arquivo no conjunto de arquivos de compilação do programa principal. Esta
inclusão é feita com a diretiva #include. Esta diretiva, vista nas seções 2.4.2 e 3.7.1, instrui o
compilador para incluir na compilação do programa outros arquivos que contem a definição das funções
de usuário e de biblioteca.

Sintaxe: A sintaxe de inclusão de funções de usuário é a seguinte:


#include ”path” // inclusão da função
void main(){ // programa principal
...
var = nomef(...) // chamada a função
...
68
}

Na diretiva #include, indicamos entre aspas duplas o caminho de localização do arquivo onde
está definida a função chamada.

Exemplo: A função media2() está escrita em um arquivo separado.


#include ”c:\tc\userbib\stat.h” // inclusão da função
void main(){ // programa principal
float num_1, num_2, med;
puts(”Digite dois números:”);
scanf(”%f %f”, &num_1, &num_2);
med = media2(num_1, num_2); // chamada a função
printf(”\nA media destes números e´ %f”, med);
}

Programa exemplo: No arquivo e0603.cpp existe um programa que calcula o maior valor
entre dois números digitados. Este programa faz uso da função max()escrita pelo usuário no arquivo
e0604.cpp.

Observação: Um arquivo pode conter a definição de uma ou mais funções. Em geral, quando o
arquivo possui apenas uma função ele é nomeado com o mesmo nome da função e extensão *.cpp ou
*.c. Por exemplo, poderíamos definir a função media() no arquivo media.cpp. Quando um arquivo
possui a definição de mais de uma função, ele é nomeado com a extensão *.h ou *.lib. Por exemplo:
poderíamos criar um conjunto de funções estatísticas chamadas media(), dsvpd(), moda(),
max(), min(), etc. definindo-as em um arquivo chamado stat.h.

6.4 Hierarquia de Funções


Sempre é possível que um programa principal chame uma função que por sua vez chame outra
função... e assim sucessivamente. Quando isto acontece dizemos que a função chamadora tem hierarquia
maior (ou superior) a função chamada. Ou que a função chamadora está em um nível hierárquico superior
a função chamada.

Quando isto ocorre, devemos ter o cuidado de definir (ou incluir) as funções em ordem crescente
de hierarquia, isto é, uma função chamada é escrita antes de uma função chamadora. Isto se deve ao fato
de que o compilador deve conhecer uma função antes de que chamada seja compilada.

Programa exemplo: No arquivo e0605.cpp existe um jogo de “jackpot” que ilustra o uso de
várias rotinas por um programa principal. Observe também que estas funções chamam-se umas as outras.
69
Neste programa exemplo, os níveis hierárquicos das funções podem ser colocados da seguinte
maneira:
main()

regras() abertura() sorte() plim_plim() saida() simnao()

imprimec() roleta()

pinta() bip()

No exemplo acima temos um primeiro nível onde se encontra a função main() [o programa
principal também é uma função] que chama as funções x, y, z. A função x por sua vez chamas as funções
s, r, e t. Observe que neste exemplo os protótipos das funções estão colocados de modo a que as funções
de menor hierarquia são escritas antes das funções de maior hierarquia.

6.5 Regra de escopo para variáveis

A regra de escopo define o âmbito de validade de variáveis. Em outras palavras define onde as
variáveis e funções são reconhecidas. Em C, uma variável só pode ser usada após ser declarada (ver
seção 2.3.2). Isto por que o processador deve reservar um local da memória para armazenar os valores
atribuídos à variável. Porém o local, do programa, onde uma variável é declarada define ainda seu escopo
de validade. Uma variável pode ser local, global ou formal de acordo com o local de declaração.

Variáveis Locais: Uma variável é dita local, se for declarada dentro do bloco de uma função.
Uma variável local tem validade apenas dentro do bloco onde é declarada, isto significa que podem ser
apenas acessadas e modificadas dentro de um bloco. O espaço de memória alocado para esta variável é
criado quando a execução do bloco é iniciada e destruído quando encerrado, assim variáveis de mesmo
nome mas declaradas em blocos distintos, são para todos os efeitos, variáveis distintas.

Exemplo:
float media2(float a, float b){
float med;
med = (a + b) / 2.0;
return(med);
}
void main(){

70
float num_1, num_2, med;
puts(”Digite dois números:”);
scanf(”%f %f”, &num_1, &num_2);
med = media2(num_1, num_2);
printf(”\nA media destes números e´ %f”, med);
}

No exemplo acima, med é uma variável local definida pela função media(). Outra variável
med é também definida pela função main(). Para todos os efeitos estas variáveis são distintas.

Variáveis Formais: Uma variável formal é uma variável local declarada na lista de parâmetros
de uma função. Deste modo, tem validade apenas dentro da função onde é declarada, porém serve de
suporte para os valores passados pelas funções. As variaveis formais na declaração da função e na
chamada da função podem ter nomes distintos. A única exigência é de que sejam do mesmo tipo.

Por serem variáveis locais, os valores que uma função passa para outra não são alterados pela
função chamada. Este tipo de passagem de argumentos é chamado de passagem por valor pois os valores
das variáveis do programa chamador são copiados para as correspondentes variáveis da função chamada.
Veremos no capitulo ? como alterar os valores das variáveis do programa chamador. Chamaremos esta
passagem de passagem por endereço.

No exemplo acima, a e b são parâmetros formais declarados na função media2(). Observe que a
função é chamada com os valores de num_1 e num_2. Mesmo que os valores de a e b fossem alterados
os valores de num_1 e num_2 não seriam alterados.

Variáveis Globais: Uma variável é dita global, se for declarada fora do bloco de uma função.
Uma variável global tem validade no escopo de todas as funções, isto é, pode ser acessadas e modificada
por qualquer função. O espaço de memória alocado para esta variável é criado no momento de sua
declaração e destruído apenas quando o programa é encerrado.

Exemplo: Uso de variáveis globais.


float a, b, med;
void media2(void){
med = (a + b) / 2.0;
}
void main(){
puts(”Digite dois números:”);
scanf(”%f %f”, &a, &b);

71
media2();
printf(”\nA media destes números e´ %f”, med);
}

No exemplo acima, a, b, med são variáveis globais definidas fora dos blocos das funções
media() e main(). Deste modo ambas as funções tem pleno acesso as variáveis, podendo ser
acessadas e modificadas por quaisquer uma das funções. Assim não é necessário a passagem de
parâmetros para a função.

6.6 Recursividade

A recursividade talvez seja a mais importante vantagem das funções em C. Recursão é o


processo pelo qual uma função chama a si mesma repetidamente um numero finito de vezes. Este
recurso é muito útil em alguns tipos de algoritmos chamados de algoritmos recursivos.

Vejamos um exemplo clássico para esclarecermos o conceito: calculo do fatorial de um número.


A definição de fatorial é:
n! = n . (n-1) . (n-2) . ... . 3 . 2 . 1
0! = 1

onde n é um numero inteiro positivo. Uma propriedade (facilmente verificável) dos fatoriais é que:
n! = n . (n-1)!

Esta propriedade é chamada de propriedade recursiva: o fatorial de um numero pode ser calculado através
do fatorial de seu antecessor. Ora, podemos utilizar esta propriedade para escrevermos uma rotina
recursiva para o calculo de fatoriais. Para criarmos uma rotina recursiva, em C, basta criar uma chamada a
própria função dentro dela mesma, como no exemplo a seguir.

Programa exemplo: No arquivo e0606.cpp existe uma rotina recursiva para o calculo de
fatoriais.

Uma função recursiva cria a cada chamada um novo conjunto de variáveis locais. Não existe
ganho de velocidade ou espaço de memória significativo com o uso de funções recursivas. Teoricamente
uma algoritmo recursivo pode ser escrito de forma iterativa e vice-versa. A principal vantagem destes
algoritmos é que algumas classes de algoritmos [de inteligência artificial, simulação numérica, busca e
ordenação em arvore binaria, etc.] são mais facilmente implementadas com o uso de rotinas recursivas. O
estudo deste tipo de algoritmo está, porém, além do alcance deste texto.

72
7. Vetores

Neste capítulo estudaremos o conceito de vetor, sua declaração e uso. Como são usados vetores
em argumentos de funções. E, ainda, como trabalhar com vetores de mais de uma dimensão.

7.1 Introdução

Em muitas aplicações queremos trabalhar com conjuntos de dados que são semelhantes em tipo.
Por exemplo o conjunto das alturas dos alunos de uma turma, ou um conjunto de seus nomes. Nestes
casos, seria conveniente poder colocar estas informações sob um mesmo conjunto, e poder referenciar
cada dado individual deste conjunto por um número índice. Em programação, este tipo de estrutura de
dados é chamada de vetor (ou array, em inglês) ou, de maneira mais formal estruturas de dados
homogêneas.

Exemplo: A maneira mais simples de entender um vetor é através da visualização de um lista,


de elementos com um nome coletivo e um índice de referência aos valores da lista.
n nota
0 8.4
1 6.9
2 4.5
3 4.6
4 7.2

Nesta lista, n representa um número de referência e nota é o nome do conjunto. Assim podemos
dizer que a 2a nota é 6.9 ou representar nota[1] = 6.9

Esta não é a única maneira de estruturar conjunto de dados. Também podemos organizar dados
sob forma de tabelas. Neste caso, cada dado é referenciado por dois índices e dizemos que se trata de um
vetor bidimensional (ou matriz)1. Vetores de mais de uma dimensão serão vistos na seção 7.5.

1
Alguns autores preferem chamar todos os tipos de estruturas homogêneas, não importando o numero de índices de referência
(ou dimensões) de vetores. Outros preferem chamar de matrizes. Outros ainda distinguem vetores (uma dimensão) de matrizes

73
7.2 Declaração e inicialização de vetores

7.2.1 Declaração de vetores

Em C, um vetor é um conjunto de variáveis de um mesmo tipo que possuem um nome


identificador e um índice de referência.

Sintaxe: A sintaxe para a declaração de um vetor é a seguinte:


tipo nome[tam];

onde:
tipo é o tipo dos elementos do vetor: int, float, double ...
nome é o nome identificador do vetor. As regras de nomenclatura de vetores são as mesmas
usadas em variáveis (seção 2.2.1).
tam é o tamanho do vetor, isto é, o número de elementos que o vetor pode armazenar.

Exemplo: Veja as declarações seguintes:


int idade[100]; // declara um vetor chamado 'idade' do tipo
// 'int' que recebe 100 elementos.
float nota[25]; // declara um vetor chamado 'nota' do tipo
// 'float' que pode armazenar 25 números.
char nome[80]; // declara um vetor chamado 'nome' do tipo
// 'char' que pode armazenar 80 caracteres.

Na declaração de um vetor estamos reservando espaço de memória para os elementos de um


vetor. A quantidade de memória (em bytes) usada para armazenar um vetor pode ser calculada como:

quantidade de memória = tamanho do tipo * tamanho do vetor

Assim, no exemplo anterior, a quantidade de memória utilizada pelos vetores é, respectivamente,


200(2x100), 100(4x25) e 80(80x1) bytes.

7.2.2 Referência a elementos de vetor

(mais de uma dimensão), etc. Não vamos entrar no mérito da questão (existem boas justificativas para todas as interpretações) e,
nesta apostila, vamos usar a primeira nomenclatura: toda estrutura homogênea de dados será chamada de vetor.
74
Cada elemento do vetor é referenciado pelo nome do vetor seguido de um índice inteiro. O
primeiro elemento do vetor tem índice 0 e o último tem índice tam-1. O índice de um vetor deve ser
inteiro.

Exemplo: Algumas referências a vetores:


#define MAX 5
int i = 7;
float valor[10]; // declaração de vetor
valor[1] = 6.645;
valor[MAX] = 3.867;
valor[i] = 7.645;
valor[random(MAX)] = 2.768;
valor[sqrt(MAX)] = 2.705; // NÃO é válido!

7.2.2 Inicialização de vetores

Assim como podemos inicializar variáveis (por exemplo: int j = 3;), podemos inicializar
vetores.

Sintaxe: A sintaxe para a inicialização dos elementos de um vetor é:


tipo nome[tam] = {lista de valores};
onde:
lista de valores é uma lista, separada por vírgulas, dos valores de cada elemento do
vetor.

Exemplo: Veja as inicializações seguintes. Observe que a inicialização de nota gera o vetor do
exemplo do início desta seção.
int dia[7] = {12,30,14,7,13,15,6};
float nota[5] = {8.4,6.9,4.5,4.6,7.2};
char vogal[5] = {'a’, ‘e’, ‘i’, ‘o’, ‘u'};

Opcionalmente, podemos inicializar os elementos do vetor enumerando-os um a um.

Exemplo: Observe que estas duas inicializações são possíveis:


int cor_menu[4] = {BLUE,YELLOW,GREEN,GRAY};
ou
int cor_menu[4];
75
cor_menu[0] = BLUE;
cor_menu[1] = YELLOW;
cor_menu[2] = GREEN;
cor_menu[3] = GRAY;

Programa Exemplo: O arquivo e0701.cpp contém um programa que mostra o uso de vetores:
declaração, inicialização, leitura e escrita de elementos...

7.3 Tamanho de um vetor e segmentação de memória

7.3.1 Limites

Na linguagem C, devemos ter cuidado com os limites de um vetor. Embora na sua declaração,
tenhamos definido o tamanho de um vetor, o C não faz nenhum teste de verificação de acesso a um
elemento dentro do vetor ou não.

Por exemplo se declaramos um vetor como int valor[5], teoricamente só tem sentido
usarmos os elementos valor[0], ..., valor[4]. Porém, o C não acusa erro se usarmos
valor[12] em algum lugar do programa. Estes testes de limite devem ser feitos logicamente dentro do
programa.

Este fato se deve a maneira como o C trata vetores. A memória do microcomputador é um espaço
(físico) particionado em porções de 1 byte. Se declaramos um vetor como int vet[3], estamos
reservando 6 bytes (3 segmentos de 2 bytes) de memória para armazenar os seus elementos. O primeiro
segmento será reservado para vet[0], o segundo segmento para vet[1] e o terceiro segmento para
vet[2]. O segmento inicial é chamado de segmento base, de modo que vet[0] será localizado no
segmento base. Quando acessamos o elemento vet[i], o processador acessa o segmento localizado em
base+i. Se i for igual a 2, estamos acessando o segmento base+2 ou vet[2](o ultimo segmento
reservado para o vetor). Porém, se i for igual a 7, estamos a acessando segmento base+7 que não foi
reservado para os elementos do vetor e que provavelmente está sendo usado por uma outra variável ou
contém informação espúria (lixo).

Observe que acessar um segmento fora do espaço destinado a um vetor pode destruir
informações reservadas de outras variáveis. Estes erros são difíceis de detectar pois o compilador não
gera nenhuma mensagem de erro... A solução mais adequada é sempre avaliar os limites de um vetor
antes de manipulá-lo.

76
A princípio este fato poderia parecer um defeito da linguagem, mas na verdade trata-se de um
recurso muito poderoso do C. Poder manipular sem restrições todos os segmentos de memória é uma
flexibilidade apreciada pelos programadores.

Programa Exemplo: O arquivo e0702.cpp contém um programa que mostra o acesso de


elementos dentro e fora de um vetor. Note que o compilador não acusa nenhum erro de sintaxe!

7.3.2 Tamanho parametrizado

Na linguagem C não é possível, usando a sintaxe descrita acima, declarar um vetor com tamanho
variável.

Exemplo: O trecho de código seguinte faz uma declaração errada de vetor.


...
int num;
puts("Quantos números?");
scanf("%d”, &num);
float valor[num]; // declaração de vetor (errado!)
...

Mas é possível declarar um vetor com tamanho parametrizado: usando uma constante
simbólica. Declaramos uma constante simbólica (parâmetro) com a diretiva #define no cabeçalho do
programa e depois declaramos o vetor com esta constante simbólica como tamanho do vetor. Deste modo
podemos alterar o número de elementos do vetor antes de qualquer compilação do programa. Esta é uma
maneira simples de administrar o espaço de memória usado pelo programa, e também testar os limites de
um vetor.

Programa Exemplo: O arquivo e0703.cpp contém um programa que mostra a declaração de


um vetor com tamanho parametrizado. Mostra também o uso deste parâmetro como teste de limite do
vetor. Compile este programa com outros valores para o parâmetro MAX e verifique que a execução do
programa é alterada automaticamente.

No capitulo seguinte, seção ?, será vista uma maneira de declararmos um vetor com um número
variável de elementos, usando ponteiros. Este tipo de declaração é chamada de alocação dinâmica de
memória.
77
7.4 Passando Vetores para Funções

Vetores, assim como variáveis, podem ser usados como argumentos de funções. Vejamos como
se declara uma função que recebe um vetor e como se passa um vetor para uma função.

Sintaxe: Na passagem de vetores para funções usamos a seguinte sintaxe:


nome_da_função(nome_do_vetor)

onde:
nome_da_função é o nome da função que se está chamando.
nome_do_vetor é o nome do vetor que queremos passar. Indicamos apenas o nome do
vetor, sem índices.

Sintaxe: Na declaração de funções que recebem vetores:


tipo_função nome_função(tipo_vetor nome_vetor[]){
...
}

onde:
tipo_função é o tipo de retorno da função.
nome_função é o nome da função.
tipo_vetor é o tipo de elementos do vetor.
nome_vetor é o nome do vetor. Observe que depois do nome do vetor temos um índice vazio
[] para indicar que estamos recebendo um vetor.

Exemplo: Observe o exemplo abaixo:


Na declaração da função:
float media(float vetor[],float N){ // declaração da função
...
}

Na chamada da função:
void main(){
float valor[MAX]; // declaração do vetor
78
...
med = media(valor, n); // passagem do vetor para a função
...
}

Programa Exemplo: O arquivo e0704.cpp contém um programa que mostra a passagem de


vetores para funções.

Atenção: Ao contrário das variáveis comuns, o conteúdo de um vetor pode ser modificado pela
função chamada. Isto significa que podemos passar um vetor para uma função e alterar os valores de seus
elementos. Isto ocorre porque a passagem de vetores para funções é feita de modo especial dito
Passagem por endereço. Uma abordagem mais detalhada deste procedimento será feita no capítulo ?
sobre ponteiros.

Portanto devemos ter cuidado ao manipularmos os elementos de um vetor dentro de uma função
para não modifica-los por descuido.

Programa Exemplo: O arquivo e0705.cpp contém um programa que mostra a modificação de


um vetor por uma função. Neste caso a modificação é desejada pois queremos ordenar os elementos do
vetor.

7.5 Vetores Multidimensionais

Vetores podem ter mais de uma dimensão, isto é, mais de um índice de referência. Podemos ter
vetores de duas, três, ou mais dimensões. Podemos entender um vetor de duas dimensões (por exemplo)
associando-o aos dados de um tabela.

Exemplo: Um vetor bidimensional pode ser visualizado através de uma tabela.


nota 0 1 2
0 8.4 7.4 5.7
1 6.9 2.7 4.9
2 4.5 6.4 8.6
3 4.6 8.9 6.3
4 7.2 3.6 7.7

79
Nesta tabela representamos as notas de 5 alunos em 3 provas diferentes (matemática, física e
química, por exemplo). O nome nota é o nome do conjunto, assim podemos dizer que a nota do 3o aluno
na 2a prova é 6.4 ou representar nota[2,1] = 6.4

7.5.1 Declaração e inicialização

A declaração e inicialização de vetores de mais de uma dimensão é feita de modo semelhante aos
vetores unidimensionais.

Sintaxe: A sintaxe para declaração de vetores multidimensionais é:


tipo nome[tam_1][tam_2]...[tam_N]={{lista},{lista},...{lista}};
onde:
tipo é o tipo dos elementos do vetor.
nome é o nome do vetor.
[tam_1][tam_2]...[tam_N] é o tamanho de cada dimensão do vetor.
{{lista},{lista},...{lista}} são as listas de elementos.

Exemplo: veja algumas declarações e inicializações de vetores de mais de uma dimensão.


Observe que a inicialização de nota gera a tabela do exemplo do início desta seção.
float nota[5][3] = {{8.4,7.4,5.7},
{6.9,2.7,4.9},
{4.5,6.4,8.6},
{4.6,8.9,6.3},
{7.2,3.6,7.7}};
int tabela[2][3][2] = {{{10,15}, {20,25}, {30,35}},
{{40,45}, {50,55}, {60,65}};

Neste exemplo, nota é um vetor duas dimensões ([][]). Este vetor é composto de 5 vetores
de 3 elementos cada. tabela é vetor de três dimensões ([][][]). Este vetor é composto de 2 vetores
de 3 sub-vetores de 2 elementos cada.

7.5.2 Passagem de vetores multidimensionais para funções

A sintaxe para passagem de vetores multidimensionais para funções é semelhante a passagem de


vetores unidimensionais: chamamos a função e passamos o nome do vetor, sem índices. A única
mudança ocorre na declaração de funções que recebem vetores:
80
Sintaxe: Na declaração de funções que recebem vetores:
tipo_f função(tipo_v vetor[tam_1][tam_2]...[tam_n]){
...
}

Observe que depois do nome do vetor temos os índices com contendo os tamanhos de cada
dimensão do vetor.

Exemplo: Observe o exemplo abaixo:


Na declaração da função:
int max(int vetor[5][7],int N, int M){ // declaração da função
...
}

Na chamada da função:
void main(){
int valor[5][7]; // declaração do vetor
...
med = media(valor, n); // passagem do vetor para a função
...
}

Programa Exemplo: O arquivo e0706.cpp contém um programa que mostra a manipulação


de vetores bidimensionais: leitura de elementos, escrita, passagem para funções, etc.

Observações: Algumas observações a respeito de vetores multidimensionais podem ser feitas:


• Do mesmo modo que vetores unidimensionais, os vetores multidimensionais podem ter seus
elementos modificados pela função chamada.
• Os índices dos vetores multidimensionais, também começam em 0. Por exemplo:
vet[0][0], é o primeiro elemento do vetor.
• Embora uma tabela não seja a única maneira de visualizar um vetor bidimensional, podemos
entender o primeiro índice do vetor como o índice de linhas da tabela e o segundo índice do
vetor como índice das colunas.

81
8. Endereços e Ponteiros

Neste capítulo veremos a definição e os principais usos de ponteiros. Veremos as operações


fundamentais como ponteiros , a estreita relação de ponteiros vetores e strings e ainda a alocação
dinâmica de memória e a passagem de funções para funções com o uso de ponteiros..

9.1 Introdução

Toda informação (dado armazenado em variável simples ou vetor) que manipulamos em um


programa está armazenado na memória do computador. Cada informação é representada por um certo
conjunto de bytes (Ver capítulo 2). Por exemplo: caracter (char): 1 byte, inteiro (int): 2 bytes, etc.

Cada um destes conjuntos de bytes, que chamaremos de bloco, tem um nome e um endereço de
localização especifica na memória.

Exemplo: Observe a instrução abaixo:


int num = 17;

ao interpretar esta instrução, o processador pode especificar:


Nome da informação: num
Tipo de informação: int
Tamanho do bloco (número de bytes ocupados pela informação): 2
Valor da informação: 17
Endereço da informação (localização do primeiro byte): 8F6F:FFF2 (hexadecimal)

Em geral, interessa ao programador apenas os nomes simbólicos que representam as


informações, pois é com estes nomes que são realizadas as operações do seu algoritmo. Porém, ao
processador interessa os endereços dos blocos de informação pois é com estes endereços que vai
trabalhar.

Programa Exemplo: O arquivo e0801.cpp contém um programa com instruções para


inspecionar o endereço de uma variável, usando o recurso Inspect do Turbo C++. Observe que o endereço
mostrado corresponde ao primeiro byte do bloco, mesmo que o bloco ocupe mais de um byte: No caso,
um float ocupa um bloco de 4 bytes.

82
8.2 Ponteiros

Ponteiros são variáveis que contém endereços. Neste sentido, estas variáveis apontam para algum
determinado endereço da memória. Em geral, o ponteiro aponta para o endereço de alguma variável
declarada no programa.

8.2.1 Declaração de ponteiros.

Quando declaramos um ponteiro, devemos declará-lo com o mesmo tipo (int, char, etc.) do bloco
a ser apontado. Por exemplo, se queremos que um ponteiro aponte para uma variável int (bloco de 2
bytes) devemos declará-lo como int também.

Sintaxe: A sintaxe da declaração de um ponteiro é a seguinte:


tipo_ptr *nome_ptr_1;
ou
tipo_ptr* nome_ptr_1, nome_ptr_2, ...;

onde:
tipo_ptr : é o tipo de bloco para o qual o ponteiro apontará.
* : é um operador que indica que nome_ptr é um ponteiro.
nome_ptr_1, nome_ptr_2,...: são os nomes dos ponteiros (os nomes dos ponteiros
obedecem as mesmas regras da seção 2.2.1)

Exemplo: Veja as seguintes instruções:


int *p;
float* s_1, s_2;

A primeira instrução declara um ponteiro chamado p que aponta para um inteiro. Este ponteiro
aponta para o primeiro endereço de um bloco de dois bytes. Sempre é necessário declarar o tipo do
ponteiro. Neste caso dizemos que declaramos um ponteiro tipo int.

A segunda instrução declara dois ponteiros (s_1 e s_2) do tipo float. Observe que o * está
justaposto ao tipo: assim todos os elementos da lista serão declarados ponteiros.

8.2.2 Operadores & e *

83
Quando trabalhamos com ponteiros, queremos fazer duas coisas basicamente:
• conhecer endereço de uma variável;
• conhecer o conteúdo de um endereço.

Para realizar estas tarefas a linguagem C nos providencia dois operadores especiais:
• o operador de endereço: &
• o operador de conteúdo: *

O operador de endereço (&) determina o endereço de uma variável (o primeiro byte do bloco
ocupado pela variável). Por exemplo, &val determina o endereço do bloco ocupado pela variável val.
Esta informação não é totalmente nova pois já a usamos antes: na função scanf().

Exemplo: Quando escreve-se a instrução:


scanf("%d", &num);

estamos nos referimos endereço do bloco ocupado pela variável num. A instrução significa:
"leia o buffer do teclado, transforme o valor lido em um valor inteiro (2 bytes) e o armazene no bloco
localizado no endereço da variável num".

Exemplo: Para se atribuir a um ponteiro o endereço de uma variável escreve-se:


int *p, val=5; // declaração de ponteiro e variável
p = &val; // atribuição

Observe que o ponteiro p deve ser declarado anteriormente com o mesmo tipo da variável para a
qual ele deve apontar.

O operador conteúdo (*) determina o conteúdo (valor) do dado armazenado no endereço de um


bloco apontado por um ponteiro. Por exemplo, *p determina conteúdo do bloco apontado pelo ponteiro p.
De forma resumida: o operador (*) determina o conteúdo de um endereço.

Exemplo: Para se atribuir a uma variável o conteúdo de um endereço escreve-se:


int *p = 0x3f8, val; // declaração de ponteiro e variável
val = *p; // atribuição

Observações:

84
• O operador endereço (&) somente pode ser usado em uma única variável. Não pode ser usado
em expressões como, por exemplo, &(a+b).
• O operador conteúdo (*) somente pode ser usado em variáveis ponteiros.

Programa Exemplo: O arquivo e0802.cpp contém um programa que mostra como se


manipulam ponteiros e variáveis. Como se transportam informações entre ponteiros e variáveis.

8.3 Operações elementares com ponteiros

Ponteiros são variáveis especiais e obedecem a regras especiais. Deste modo, existem uma série
de operações (aritméticas, lógicas, etc.) envolvendo ponteiros que são permitidas e outras não. A seguir
são destacadas algumas operações que podem ser executadas com ponteiros.

• A um ponteiro pode ser atribuído o endereço de uma variável comum.


Exemplo: Observe o trecho abaixo:
...
int *p;
int s;
p = &s; // p recebe o endereço de s
...

• Um ponteiro pode receber o valor de outro ponteiro, isto é, pode receber o endereço apontado
por outro ponteiro, desde que os ponteiros sejam de mesmo tipo.
Exemplo: Observe o trecho abaixo:
...
float *p1, *p2, val;
p1 = &val; // p1 recebe o endereço de val...
p2 = p1; // ...e p2 recebe o conteúdo de p2 (endereço de val)

• Um ponteiro pode receber um endereço de memória diretamente. Um endereço é um numero


inteiro. Em geral, na forma hexadecimal (0x....). Nesta atribuição devemos, em geral,
forçar uma conversão de tipo usando casting para o tipo de ponteiro declarado.

Exemplo: Observe o trecho abaixo:


...
85
int *p1;
float p2ç
p1 = 0x03F8; // endereço da porta serial COM1
p2 = (float)0x0FF6; // casting
...

• A um ponteiro pode ser atribuído o valor nulo usando a constante simbólica NULL (declarada
na biblioteca stdlib.h). Um ponteiro com valor NULL não aponta para lugar nenhum!
Algumas funções a utilizam para registrar uma atribuição ilegal ou sem sucesso (ver função
malloc() adiante)
Exemplo: Observe o trecho abaixo:
#include <stdlib.h>
...
char *p;
p = NULL;
...

• Uma quantidade inteira pode ser adicionada ou subtraída de um ponteiro. A adição de um


inteiro n a um ponteiro p fará com que ele aponte para o endereço do n-ésimo bloco seguinte.
Exemplo: Observe o trecho abaixo:
...
double *p, *q, var;
p = &var
q = ++p; // q aponta para o bloco seguinte ao ocupado por var
p = q - 5;// p aponta para o quinto bloco anterior a q
...

• Dois ponteiros podem ser comparados (usando-se operadores lógicos) desde que sejam de
mesmo tipo.
Exemplo: Observe o trecho abaixo:
...
if(px == py){ // se px aponta para o mesmo bloco que py ...
if(px > py){ // se px aponta para um bloco posterior a py ...
if(px != py){ // se px aponta para um bloco diferente de py ...
if(px == NULL) // se px é nulo...
...

Programa Exemplo: O arquivo e0803.cpp contém um programa que mostra como se utilizam
algumas operações elementares com ponteiros com ponteiros.

86
8.4 Ponteiros, endereços e funções

Porque usar ponteiros? A primeira vantagem da utilização de ponteiros em programas talvez


esteja relacionada a sua utilização como argumentos de funções.

8.4.1 Passagem de dados por valor ou por referencia

No capítulo 6 (seção 6.5) afirma-se que o valor de uma variável var de uma função fun_1()
passada para uma outra função fun_2() não podem ser alterado pela função fun_2(). De fato, isto é
verdade se passamos o valor da variável var para a função fun_2(). Mas o valor de var pode ser
alterado por fun_2() passamos seu endereço.

No primeiro caso, dizemos que a passagem de dados de uma função para outra ocorreu por valor.
No segundo caso, dizemos que houve uma passagem por referência. Vejamos em detalhe uma definição
destes tipos de passagem de dados entre funções:

Passagem por Valor: A passagem por valor significa que passamos de uma função para outra o
valor de uma variável, isto é, a função chamada recebe um cópia do valor da variável. Assim qualquer
alteração deste valor, pela função chamada, será uma alteração de uma cópia do valor da variável. O valor
original na função chamadora não é alterado pois o valor original e copia ficam em blocos de memória
diferentes.

Passagem por Referencia: A passagem por referencia significa que passamos de uma função
para outra o endereço de uma variável, isto é, a função chamada recebe sua localização na memória
através de um ponteiro. Assim qualquer alteração no conteúdo apontado pelo do ponteiro será uma
alteração no conteúdo da variável original. O valor original é alterado.

Sintaxe: A sintaxe da passagem de endereço é a seguinte:


• na função chamada:
tipof nomef(tipop nomep){
...

onde:
tipof é o tipo de retorno da função.
87
nomef é o nome da função chamada.
tipop é o tipo do ponteiro (igual ao tipo da variável passada).
nomep é o nome do ponteiro.

• na função chamadora:
...
nomef(end_var);
...

onde:
nomef é o nome da função chamada.
end_var é o endereço da variável passada como argumento.

Exemplo: Observe o exemplo abaixo:


void troca(int *p1, int *p1){ // declaração da função
// Observe: ponteiros
int temp; // variável temporária
temp = *p1; // temp recebe o conteúdo apontado por p1
*p1 = *p2; // o conteúdo de p1 recebe o conteúdo de p2
*p2 = temp; // o conteúdo de p2 recebe o valor de temp
}
void main(){ // programa principal
int a,b; // declaração das variáveis
scanf("%d %d",&a,&b); // leitura das variáveis
troca(&a,&b); // passagem dos endereços de a e b
printf("%d %d",a,b); // imprime valores (trocados!)
}

Neste exemplo temos uma função troca() que troca entre si os valores de duas variáveis. Esta
função recebe os endereços das variáveis passadas pela função main(), armazenando-os nos ponteiros
p1 e p2. Dentro da função, troca-se os conteúdos dos endereços apontados.

Programa Exemplo: O arquivo e0804.cpp contém um programa que mostra a diferença entre
a passagem de dados por valor e passagem por referencia.

8.4.2 Retorno de dados em funções

88
A passagem por referencia permite que (formalmente) uma função retorne quantos valores se
desejar. Dissemos no capítulo 6 (seção 6.2) que uma função somente pode retornar um valor. Isto
continua sendo valido pois o C assim define funções. Porem com o uso de ponteiros pode-se contornar
esta situação. Vejamos:

Imagine que queremos escrever uma função stat() com a finalidade de calcular a media aritmética e o
desvio padrão de um conjunto de dados. Observe: o retorno destes dados não poder ser via instrução
return() pois isto não é permitido. A solução é criar (na função main(), por exemplo) duas variáveis
para armazenar os valores desejados (med e desvio, por exemplo) e então passar os endereços destas
variáveis para a função stat(). A função recebe esses endereços e os armazena em ponteiros (pm e pd,
por exemplo). Em seguida, faz os cálculos necessários, armazenando-os nos endereços recebidos. Ao
término da execução da função os valores de med e desvio serão atualizados automaticamente. Este
recurso é bastante utilizado por programadores profissionais.

Programa Exemplo: O arquivo e0805.cpp contém um programa que mostra o ‘retorno’ de


vários dados de uma função. Na verdade trata-se da passagem de valores por referencia.

8.4.3 Ponteiro como argumento de função

Observe que nos exemplos acima, a passagem de endereços foi feita através do operador
endereço (&). Também é possível passar um endereço através de um ponteiro já que o conteúdo de um
ponteiro é um endereço.

Exemplo: Observe o trecho de programa abaixo.


...
float *p, x;
p = &x;
função(p); // passagem do ponteiro com o endereço de x.
...

Programa Exemplo: O arquivo e0806.cpp contém um programa que mostra a passagem de


endereço para uma função usando um ponteiro. Observe a sintaxe alternativa para a função scanf()!

8.5 Ponteiros, vetores e strings

89
8.5.1 Ponteiros e vetores

No capitulo 7 foi mostrado que na passagem de vetores para funções especifica-se apenas o nome
do vetor e que modificações nos elementos do vetor dentro da função chamada alteram os valores do
vetor no programa chamador (seção 7.4). Isto se deve ao fato de que, na linguagem C, vetores são
intimamente relacionados a ponteiros.

Em C, o nome de um vetor é tratado como o endereço de seu primeiro elemento. Assim ao se


passar o nome de um vetor para uma função está se passando o endereço do primeiro elemento de um
conjunto de endereços de memória.

Por exemplo, se vet é um vetor, então vet e &vet[0] representam o mesmo endereço. E
mais, podemos acessar o endereço de qualquer elemento do vetor do seguinte modo: &vet[i] e
equivalente a (vet + i). Aqui deve-se ressaltar que (vet + i) não representa uma adição
aritmética normal mas o endereço do i-ésimo elemento do vetor vet (endereço contado a partir do
endereço inicial vet[0]).

Do mesmo modo que se pode acessar o endereço de cada elemento do vetor por ponteiros,
também se pode acessar o valor de cada elemento usando ponteiros. Assim vet[i] é equivalente a
*(vet + i). Aqui se usa o operador conteúdo (*) aplicado ao endereço do i-ésimo elemento do vetor
vet.

Programa Exemplo: O arquivo e0807.cpp contém um programa que mostra a equivalência


entre ponteiros e vetores.

8.5.2 Ponteiros e strings

Como dissemos, vagamente na seção 2.3.4, uma string é um conjunto ordenado de caracteres.
Podemos, agora, dizer muito mais: Em C, uma string é um vetor unidimensional de elementos caracteres
ASCII, sendo o ultimo destes elementos o caracter especial ’\0’.

Sintaxe: As duas maneiras mais comuns de declararmos uma string são:


char nome[tam];
ou
char *nome;

90
onde:
nome é o nome do vetor de caracteres e
tam seu tamanho.

Observe que sendo um vetor, uma string pode ser declarada também como um ponteiro. Alias a
segunda declaração representa justamente isto. Sabendo isto podemos realizar uma grande variedade de
manipulações com strings e caracteres. Existe uma biblioteca padrão C chamada string.h que
providencia algumas funções de manipulação de strings muito úteis.

Programa Exemplo: O arquivo e0808.cpp contém um programa que mostra algumas


operações usando-se strings (vetores e ponteiros).

8.6 Alocação Dinâmica de Memória

Os elementos de um vetor são armazenados seqüencialmente na memória do computador. Na


declaração de um vetor, (por exemplo: int vet[10]) é dito ao processador reservar (alocar) um certo
numero de blocos de memória para armazenamento dos elementos do vetor. Porem, neste modo de
declaração, não se pode alocar um numero variável de elementos (veja seção 7.3.2).

A linguagem C permite alocar dinamicamente (em tempo de execução), blocos de memória


usando ponteiros. Dada a intima relação entre ponteiros e vetores, isto significa que podemos declarar
dinamicamente vetores de tamanho variável. Isto é desejável caso queiramos poupar memória, isto é não
reservar mais memória que o necessário para o armazenamento de dados.

Para a alocação de memória usamos a função malloc()(memory allocation) da biblioteca


alloc.h. A função malloc() reserva, seqüencialmente, um certo numero de blocos de memória e
retorna, para um ponteiro, o endereço do primeiro bloco reservado.

Sintaxe: A sintaxe geral usada para a alocação dinâmica é a seguinte:


pont = (tipo *)malloc(tam);

onde:
pont é o nome do ponteiro que recebe o endereço do espaço de memória alocado.
tipo é o tipo do endereço apontado (tipo do ponteiro).

91
tam é o tamanho do espaço alocado: numero de bytes.

A sintaxe seguinte, porem, é mais clara:


pont = (tipo*)malloc(num*sizeof(tipo));

onde:
num é o numero de elementos que queremos poder armazenar no espaço alocado.

Exemplo: Se queremos declarar um vetor chamado vet, tipo int, com num elementos podemos
usar o trecho abaixo:
...
int *vet; // declaração do ponteiro
vet = (int*)malloc(num*2); // alocação de num blocos de 2 bytes
...

ou ainda

...
int *vet; // declaração do ponteiro
vet = (int*) malloc(num * sizeof(int));
...

Caso não seja possível alocar o espaço requisitado a função malloc() retorna a constante
simbólica NULL.

Sintaxe: Para liberar (desalocar) o espaço de memória se usa a função free(), cuja sintaxe é a
seguinte:
free(pont);

onde:
pont é o nome do ponteiro que contem o endereço do inicio do espaço de memória reservado.

Programa Exemplo: O arquivo e0809.cpp contém um programa que mostra como se utiliza a
Alocação Dinâmica de Memória.

8.7 Ponteiros para Funções

92
Até agora usamos ponteiros para apontar para endereços de memória onde se encontravam as
variáveis (dados). Algumas vezes é necessário apontar para funções, isto é, apontar para o endereço de
memória que contem o inicio das instruções de uma função. Quando assim procedemos, dizemos que
usaremos ponteiros para funções.

8.7.1 Ponteiros como chamada de função.

Um uso de ponteiros para funções é passar uma função como argumento de outra função. Mas
também se pode usar ponteiros para funções ao invés de funções nas chamadas normais de funções.

Sintaxe: A sintaxe de declaração de ponteiro para funções é a seguinte:


tipo_r (*nome_p)(lista);

onde:
tipo_r é o tipo de retorno da função apontada.
nome_p é o nome do ponteiro que apontara para a função.
lista é a lista de argumentos da função.

Exemplo: Suponha que temos uma função é declarada como:


float fun(int a, int b){
...
}

o ponteiro correspondente será:


float (*pt)(int,int);

Observe que o ponteiro para função deve ser declarado entre parênteses. Observe também que o
ponteiro e a função retornam o mesmo tipo de dado e que tem os mesmos argumentos.

Sintaxe: Para atribuirmos o endereço de uma função para um ponteiro usamos a seguinte sintaxe:
pont = &função;

onde:
pont é o nome do ponteiro.
função é o nome da função.

93
Se um ponteiro contem o endereço de uma função, ele pode ser usado no lugar da chamada da
função.

Exemplo: o trecho de programa abaixo usa um ponteiro para chamar uma função:
float fun(int a,int b){
...
}
void main(void){
float temp;
float (*pt)(int,int);
pt = &fun;
temp = (*pt)(10,20); // eqüivale a: temp = fun(10,20);
...
}

Programa Exemplo: O arquivo e0810.cpp contém um programa que mostra como se utiliza o
ponteiro para função.

8.7.2 Passando uma função como argumento de outra função.

Outra utilização de ponteiros para funções é na passagem de uma função como argumento para
outra função. Para que isso ocorra necessitamos:

• Na declaração da função a ser passada:


i) Nada de especial, apenas a definição normal:
tipo nome_p(lista){
...
}

Exemplo:
float soma(float a,float b){
...
}

• Na função receptora:
i) Declarar o ponteiro que recebe a função passada na lista de argumentos:
tipo nome_r(..., tipo (*pt)(lista), ...){

94
Exemplo:
float grad(float x, float y, float (*p)(float,float)){

ii) Usar o ponteiro para funções nas chamadas da função passada:


var = (*pt)(lista);

Exemplo:
valor = (*p)(x,y);

• Na função principal:
i) Passar o nome da função chamada para a função receptora:
var = nome_g(... , nome_p , ...);

Exemplo:
g = grad(x,y,soma);

Programa Exemplo: O arquivo e0811.cpp contém um programa que mostra como se utiliza
ponteiros na passagem de funções

95
Apêndice A. Tabela ASCII

As tabelas mostradas neste apêndice representam os 256 códigos usados nos computadores da
família IBM. Esta tabela refere-se ao American Standard Code for Information Interchange (código
padrão americano para troca de informações), que é um conjunto de números representando caracteres ou
instruções de controle usados para troca de informações entre computadores entre si, entre periféricos
(teclado, monitor, impressora) e outros dispositivos. Estes códigos tem tamanho de 1 byte com valores de
00h a FFh (0 a 255 decimal). Podemos dividir estes códigos em três conjuntos: controle, padrão e
estendido.

Os primeiros 32 códigos de 00h até 1Fh (0 a 31 decimal), formam o conjunto de controle


ASCII. Estes códigos são usados para controlar dispositivos, por exemplo uma impressora ou o monitor
de vídeo. O código 0Ch (form feed) recebido por ima impressora gera um avanço de uma página. O
código 0Dh (carriage return) é enviado pelo teclado quando a tecla ENTER é pressionada. Embora exista
um padrão, alguns poucos dispositivos tratam diferentemente estes códigos e é necessário consultar o
manual para saber exatamente como o equipamento lida com o código. Em alguns casos o código também
pode representar um caracter imprimível. Por exemplo o código 01h representa o caracter ☺ (happy face).

Os 96 códigos seguintes de 20h a 7Fh (32 a 127 decimal) formam o conjunto padrão ASCII.
Todos os computadores lidam da mesma forma com estes códigos. Eles representam os caracteres usados
na manipulação de textos: códigos-fonte, documentos, mensagens de correio eletrônico, etc. São
constituídos das letras do alfabeto latino (minúsculo e maiúsculo) e alguns símbolos usuais.

Os restantes 128 códigos de 80h até FFh (128 a 255 decimal) formam o conjunto estendido
ASCII. Estes códigos também representam caracteres imprimíveis porem cada fabricante decide como e
quais símbolos usar. Nesta parte do código estão definidas os caracteres especiais: é, ç, ã, ü ...

96
Dec. Hex. Controle
0 00h NUL (Null)
1 01h SOH (Start of Heading)
2 02h STX (Start of Text)
3 03h ETX (End of Text)
4 04h EOT (End of Transmision)
5 05h ENQ (Enquiry)
6 06h ACK (Acknowledge)
7 07h BEL (Bell)
8 08h BS (Backspace)
9 09h HT (Horizontal Tab)
10 0Ah LF (Line Feed)
11 0Bh VT (Vertical Tab)
12 0Ch FF (Form Feed)
13 0Dh CR (Carriage Return)
14 0Eh SO (Shift Out)
15 0Fh SI (Shift In)
16 10h DLE (Data Link Escape)
17 11h DC1 (Device control 1)
18 12h DC2 (Device control 2)
19 13h DC3 (Device control 3)
20 14h DC4 (Device control 4)
21 15h NAK (Negative Acknowledge)
22 16h SYN (Synchronous Idle)
23 17h ETB (End Transmission Block)
24 18h CAN (Cancel)
25 19h EM (End of Media)
26 1Ah SUB (Substitute)
27 1Bh ESC (Escape)
28 1Ch FS (File Separator)
29 1Dh GS (Group Separator)
30 1Eh RS (Record Separator)
31 1Fh US (Unit Separator)

97
Caracter Dec. Hex. Caracter Dec. Hex. Caracter Dec. Hex.
<espaço> 32 20h D 68 44h h 104 68h

! 33 21h E 69 45h i 105 69h

" 34 22h F 70 46h j 106 6Ah

# 35 23h G 71 47h k 107 6Bh

$ 36 24h H 72 48h l 108 6Ch

% 37 25h I 73 49h m 109 6Dh

& 38 26h J 74 4Ah n 110 6Eh

' 39 27h K 75 4Bh o 111 6Fh

( 40 28h L 76 4Ch p 112 70h

) 41 29h M 77 4Dh q 113 71h

* 42 2Ah N 78 4Eh r 114 72h

+ 43 2Bh O 79 4Fh s 115 73h

, 44 2Ch P 80 50h t 116 74h

- 45 2Dh Q 81 51h u 117 75h

. 46 2Eh R 82 52h v 118 76h

/ 47 2Fh S 83 53h w 119 77h

0 48 30h T 84 54h x 120 78h

1 49 31h U 85 55h y 121 79h

2 50 32h V 86 56h z 122 7Ah

3 51 33h W 87 57h { 123 7Bh

4 52 34h X 88 58h | 124 7Ch

5 53 35h Y 89 59h } 125 7Dh

6 54 36h Z 90 5Ah ~ 126 7Eh

7 55 37h [ 91 5Bh <delete> 127 7Fh

8 56 38h \ 92 5Ch Ç 128 80h

9 57 39h ] 93 5Dh ü 129 81h

: 58 3Ah ^ 94 5Eh é 130 82h

; 59 3Bh _ 95 5Fh â 131 83h

< 60 3Ch ` 96 60h ä 132 84h

= 61 3Dh a 97 61h à 133 85h

> 62 3Eh b 98 62h å 134 86h

? 63 3Fh c 99 63h ç 135 87h

@ 64 40h d 100 64h ê 136 88h

A 65 41h e 101 65h ë 137 89h

B 66 42h f 102 66h è 138 8Ah

C 67 43h g 103 67h ï 139 8Bh

98
Caracter Dec. Hex. Caracter Dec. Hex. Caracter Dec. Hex.
î 140 8Ch ¦ 177 B1h + 214 D6h

ì 141 8Dh ¦ 178 B2h + 215 D7h

Ä 142 8Eh │ 179 B3h + 216 D8h

Å 143 8Fh ┤ 180 B4h + 217 D9h

É 144 90h ¦ 181 B5h + 218 DAh

æ 145 91h ¦ 182 B6h ¦ 219 DBh

Æ 146 92h + 183 B7h _ 220 DCh

ô 147 93h + 184 B8h ¦ 221 DDh

ö 148 94h ¦ 185 B9h ¦ 222 DEh

ò 149 95h ¦ 186 BAh ¯ 223 DFh

û 150 96h + 187 BBh α 224 E0h

ù 151 97h + 188 BCh ß 225 E1h

ÿ 152 98h + 189 BDh Γ 226 E2h

Ö 153 99h + 190 BEh π 227 E3h

Ü 154 9Ah + 191 BFh Σ 228 E4h

¢ 155 9Bh + 192 C0h 229 E5h

£ 156 9Ch - 193 C1h µ 230 E6h

¥ 157 9Dh - 194 C2h 231 E7h

P 158 9Eh + 195 C3h Φ 232 E8h

ƒ 159 9Fh - 196 C4h Θ 233 E9h

ááááá 160 A0h + 197 C5h Ω 234 EAh

í 161 A1h ¦ 198 C6h δ 235 EBh

ó 162 A2h ¦ 199 C7h 8 236 ECh

ú 163 A3h + 200 C8h φ 237 EDh

ñ 164 A4h + 201 C9h ∈ 238 EEh

Ñ 165 A5h - 202 CAh n 239 EFh

ª 166 A6h - 203 CBh = 240 F0h

º 167 A7h ¦ 204 CCh ± 241 F1h

¿ 168 A8h - 205 CDh = 242 F2h

¬ 169 A9h + 206 CEh = 243 F3h

¬ 170 AAh - 207 CFh ( 244 F4h

½ 171 ABh - 208 DOh ) 245 F5h

¼ 172 ACh - 209 D1h ÷ 246 F6h

¡ 173 ADh - 210 D2h ˜ 247 F7h

« 174 AEh + 211 D3h ° 248 F8h

» 175 AFh + 212 D4h · 249 F9h

¦ 176 B0h + 213 D5h · 250 FAh

99
Caracter Dec. Hex.
v 251 FBh

n 252 FCh

² 253 FDh

· 254 FEh

255 FFh

100
Entre os caracteres da tabela ASCII estendidos os mais úteis estão, talvez, os caracteres de desenho de
quadro em linhas simples e duplas: os caracteres de B3h até DAh (179 a 218 decimal). Como a visualização deste
conjunto é difícil, o desenho abaixo pode auxiliar nesta tarefa:

196 194 205 203


218 + - - + 191 201 + - - + 187
179 ¦ 186 ¦
195 + + ¦ 180 204 ¦ + ¦ 185
197 206
192 + - + 217 200 + - + 188
193 202

209 210
213 + - + 184 214 + - + 183

198 ¦ + ¦ 181 199 ¦ + ¦ 182


216 215
212 + - + 190 211 + - + 189
207 208

Figura B.1: Caracteres de desenho de quadro e seus respectivos códigos ASII.


Apêndice B. Exercícios de programação

Capítulo 4: Funções de Entrada e Saída

4.1 Faça um programa que leia 2 números reais e imprima a média aritmética entre eles.

4.2 Faça um programa escreva na tela o caracter ASCII e o respectivo códigos hexadecimal de um valor
decimal digitado pelo usuário. [Sugestão: Use a função putchar()para escrever os caracteres].

4.3 Faça um programa que leia um angulo (em graus) e imprima o valor do seno, coseno e tangente deste
angulo.

4.4 Altere o programas 4.2 e 4.3 para que utilizem efeitos de impressão colorida.

4.5 O volume de um esfera de raio R é V = 43 πR 3 . Faça um programa que leia um numero R e imprima o
volume da esfera correspondente.

4.6 Faça um programa que leia uma frase e rescreva esta frase centralizada no topo da tela.

Capítulo 5: Estruturas de Controle


5.1 Faça um programa que leia 3 números e imprima o número de maior valor absoluto.

5.2 Faça um programa escreva na tela todos os caracteres ASCII, os respectivos códigos decimais e
hexadecimais.

5.3 Faça um programa que imprima os 10 primeiros números primos.

5.4 Faça um programa que imprima os números ímpares no intervalo fechado [a, b] (a e b escolhidos
pelo usuário).

5.5 Faça um programa que leia uma frase digitada e imprima um relatório contendo: o número de
palavras, o número de vogais e o número de letras digitadas.

5.6 Altere o programa 4.1 para que o usuário determine a quantidade de números manipulados.

8, 13,... A fórmula de recorrência para esta série é ni = ni −1 + ni − 2 para i ≥ 2 pois


5.7 Faça um programa que imprima os N primeiros números da série de Fibonacci: 1, 1, 2, 3, 5,

n0 = n1 = 1 .

5.8 Altere o programa 5.1 para que o usuário determine a quantidade de números manipulados.

5.9 Altere o programa 5.3 para que o usuário determine a quantidade de números manipulados.

ii
5.10 Faça um programa que leia os três parâmetros a, b, c de uma equação de segundo grau e escreva suas
raízes (reais ou complexas).

5.11 Faça um programa que execute um proteção de tela do seguinte modo: Ao iniciar o programa, um
caracter ¦ (ou outro qualquer) percorra a tela em direções aleatórias apagando os caracteres de fundo.
Ao se pressionar qualquer tecla o texto de fundo reaparece e o programa termina. Use as funções
gettext() e puttext().

5.12 Faça um programa que peça para o usuário adivinhar um número escolhido aleatoriamente entre 1 e
100. Se o usuário digitar um número errado, o programa responde o novo intervalo do número
procurado. Se o usuário acertou o número procurado, o programa diz quantos palpites foram dados.
Por exemplo:
O número procurado está entre 1 e 100:
Palpite: 45
O número procurado está entre 1 e 44:
Palpite: 27
O número procurado está entre 28 e 44:
Palpite: 36
Parabéns! Você acertou o número em 3 tentativas.

5.13 Faça um programa que leia um valor inteiro de 0 a 1000 escreva o seu valor por extenso. Por
exemplo:
Digite valor: 279
Extenso: duzentos e setenta e nove.

5.14 Faça um programa que coloque um caracter no centro da tela e permita o movimentação deste com o
uso das setas.

5.15 Implemente um ‘rastro’ para o caracter do programa 5.14. Sugestão: use os caracteres de
preenchimento: 176d, 177d, 178d e 219d.

5.16 Faça um programa que desenhe um janela com bordas (simples ou duplas) em uma posição
centralizada da tela. Pinte o interior da janela com alguma cor diferente do fundo da tela. [Sugestão:
Use o laço for... para escrever as bordas e a função clrscr() para pintar o interior da janela].

Capítulo 6: Funções
6.1 Crie um função float round(float r) que faça o arredondamento de números reais: Por
exemplo: 5 = round(5.4), 7 = round(6.5).

6.2 Crie uma função int sim_nao(void) que espera o usuário pressionar as teclas [s] ou [n]
retornando 1 ou 0 respectivamente. Se o usuário pressionar qualquer outra tecla um som (de
advertência) de 50 Hz por 250 ms é emitido.

6.3 Transforme o programa do exercício 5.16 em uma função com a seguinte declaração: int
borda(esq, sup, dir, inf, corf, corb) onde esq, sup, dir, inf são as
posições das bordas, corf, corb as cores do fundo e da borda da janela respectivamente. A função
retorna 1 se houve algum erro na passagem dos parâmetros ( esq > dir, por exemplo) e 0 caso
contrário.

6.4 Faça uma função que determine se três números a, b, c formam um triângulo ou não. A função
deve ter a seguinte declaração int triângulo(float a, float b, float c) onde o
valor de retorno tem o seguinte significado:
0: não forma triângulo,
1: triângulo qualquer,
iii
2: triângulo isósceles,
3: triângulo equilátero.

6.5 Faça uma função que determine se um determinado numero é primo ou não. A função deve ter a
seguinte declaração int primo(int N) onde N é o valor a ser testado. A função deve retornar 1
se N é primo e 0 caso contrário. [Sugestão: Altere o programa do exercício 5.3].

6.6 Transforme o programa do exercício 5.7 em uma função int fib(int n) que retorna o n-ésimo
numero de Fibonacci.

6.7 A média elíptica2 (ou aritmético-geométrica) de dois números positivos a e b [a < b], é calculada do
seguinte modo: Chamando a n +1 = a n bn e bn +1 = ( a n + bn ) / 2 respectivamente as médias

tal que a 0 < a1 < a 2 <L < b2 < b1 < b0 . O limite desta seqüência é m = a ∞ = b∞ . Por exemplo: a
geométrica e aritmética desses números obtemos uma seqüência de números a0, a1, a2, ... e b0, b1, b2, ...

média elíptica de 4 e 7 é 5.5932... Faça uma função double elip(double a, double


b) que calcule a média elíptica de a e b. [Sugestão: Use um laço while(a < b)...].

6.8 O maior divisor comum dos inteiros positivos a e b, que abreviamos como mdc(a, b), é o maior
número m tal que m é divisor tanto de a quanto de b. Por exemplo: 4 = mdc(20,16), 7 = mdc(21,7). O
valor de m pode ser calculado com o seguinte algoritmo recursivo3, de Euclides:
se a > b então mdc(a, b) é igual a
b se resto(a, b) é 0
mdc(b, resto(a, b)) caso contrário.
Faça uma função recursiva para o cálculo do máximo divisor comum de dois números.

6.9 Caso já não tenha feito assim, transforme a função iterativa do exercício 6.6 em uma função
recursiva.

Capítulo 7: Vetores
7.1 Escreva um programa que leia um vetor de N números inteiros,(N<=100), inverta a ordem dos
elementos do vetor e imprima o vetor invertido. Por exemplo o vetor: {1, 3, 5, 7} terá seus
elementos invertidos: {7, 5, 3, 1}. Observação: É necessário inverter os elementos do vetor.
Não basta imprimi-los em ordem inversa!

7.2 Escreva um programa que leia um vetor a de N números reais, (N<=100),e um outro real k e
construa e imprima um outro vetor b cujos elementos são os respectivos elementos de a
multiplicados por k. Por exemplo: a = {1,2,3}, k = 5, b = {5,10,15}.

7.3 Escreva duas funções: uma que leia um vetor v de n números inteiros, (n<=100), e outra que
escreva este vetor. A declaração destas funções devem ser, respectivamente: void le_vet(int
v, int n) e void escreve_vet(int v, int n).

7.4 Escreva um programa que leia um vetor gabarito de 10 elementos. Cada elemento de
gabarito contem um numero inteiro 1, 2, 3, 4 ou 5 correspondente as opções corretas de
uma prova objetiva. Em seguida o programa deve ler um vetor resposta, também de 10
elementos inteiros, contendo as respostas de um aluno. O programa deve comparar os dois vetores e
escrever o numero de acertos do aluno.

2
Descoberta pelo matemático alemão Carl F. Gauss. Ver LIMA, E. L., Meu Professor de Matemática,?,
p.123
3
Ver SMITH, J. D. Design and Analysis of Algorithms, Boston: PWS-Kent Pub. Co. 1989 p.272
iv
7.5 Escreva uma função int min_vet(float v[], int n) receba um vetor e retorne o índice
do menor elemento deste vetor.

7.6 Escreva uma função int remove_dup(float v[], int n) receba um vetor e verifique a
existência de elementos duplicados. Caso não existam elementos duplicados retorne 0. Caso
existam, remova estes elementos (deixando apenas um) e retorne o número de elementos removidos.

7.7 Escreva uma função void insert(float v[], int n, float valor, int pos)
que faça a inserção de valor na posição pos do vetor v, deslocando os demais elementos.

7.8 Transforme o programa do exemplo e0705.cpp em uma função void ordem(int v, int
n) que ordene os elementos de um vetor v de n elementos inteiros.

7.9 Escreva uma função int merge(float r[], float s[], float v[], int n, int
m) receba um vetor r de n elementos e outro vetor s de m elementos e construa um vetor v com os
elementos de r e s, ordenado e não duplicado. A função deve retornar o tamanho do vetor v
construído. Sugestão: Utilize as funções dos exercícios 7.6, 7.7 e 7.8.

7.10 A função do exercício 7.9 pode ser entendida como uma função que retorna a união entre dois
conjuntos. Escreva uma função int intersec(float r[], float s[], float v[],
int n, int m) que construa um vetor v com a interseção entre r e s, ordenados. A função
deve retornar o tamanho do vetor v construído.

7.11 Escreva uma função void desordem(int v, int n) que desordene os elementos de um
vetor v (não necessariamente ordenado) de n elementos inteiros. Sugestão: use o seguinte algoritmo:

j ← valor aleatório entre 0 e i


para i de n-1 até 0 faça

v[i] ↔ v[j]
fim faça

Observação: Esta rotina pode ser usada para simular o processo de embaralhar as cartas de um
baralho.

7.12 Escreva uma função int find(char v[], char t[], int m, int n) que receba um
vetor v de m elementos e um vetor t de n elementos (n < m). Esta função deve verificar a
ocorrência do padrão t em v ou não. Se houver, deve retornar a posição inicial da primeira
ocorrência. Por exemplo: se v={As bananas do Panamá são bacanas} e p={anas}
deve retornar 6. Caso não haja ocorrência, retorne -1. Observação: Algoritmos como esses são

7.13 O produto escalar entre dois vetores pode ser definido como: e = u ⋅ v = ∑ ui v i , onde ui e vi são
usados em editores de texto4.
n
5 r r
i=0
os elementos do vetor. Escreva uma função float prod_esc(float u, float v, int
n) que receba dois vetores u e v de n elementos reais e retorne o valor do produto escalar entre eles.

7.14 O código Morse foi muito usado no tempo do telégrafo para transmitir mensagens. Neste sistema
cada símbolo (letra, numero ou sinal de pontuação) é enviado por fio em uma serie de pulsos
elétricos curtos ou longos (pontos ou traços) conforme a tabela abaixo:
a .- b -... c -.-. d -.. e . f ..-.
g --. h .... i .. j .--- k -.- l .-..
m -- n -. o --- p .--. q --.- r .-.
s ... t - u ..- v ...- w .-- x -..-

4
Ver o algoritmo de Knuth-Morris-Pratt em SMITH (op. Cit.), p 294
5
Ver SPIEGEL, M. R., Análise Vetorial, São Paulo: McGraw-Hill. 1976, p. 23.
v
y -.-- z --.. 1 .---- 2 ..--- 3 ...-- 4 ....-
5 ..... 6 -.... 7 --... 8 ---.. 9 ----. 0 -----
. .-.-.- ? ..--.. , --..-- : ---...

Escreva um programa que leia uma frase digitada pelo usuário e emita pelo alto-falante do PC o som
correspondente a uma transmissão completa em código Morse. Sugestão: Crie uma tabela
código[40][5] em que cada linha represente um sinal contendo os números 1 (ponto), 2 (traço)
ou 0 (fim do código).

7.15 Existe um problema famoso no xadrez chamado Problema das 8 damas: consiste em dispor sobre o
tabuleiro (de 8 x 8 casas) do jogo um conjunto de 8 damas de tal forma que nenhuma dama fique na
mesma linha, coluna ou diagonal que outra. Escreva um programa que calcule pelo menos uma
solução deste problema. Sugestão: crie um vetor tab[8][8] contendo 0 para uma casa vazia e 1
para uma casa ocupada. Escreva uma função que crie as configurações e outra rotina que teste a
solução.

7.16 As populares calculadoras HP (Hewllet-Packard) usam a notação RPN (Reverse Polish Notation)
para o cálculo de expressões numéricas. Este tipo de notação torna mais fácil o cálculo de expressões
complexas. Cada valor digitado é guardado em uma pilha de dados e cada tecla de operação efetua
uma operação entre os últimos dois valores da pilha. Por exemplo, para efetuar a expressão 2+5*3
digitamos:
[5] (colocamos o primeiro valor na pilha),
[enter] [3] (deslocamos 5 para a 2a posição da pilha e colocamos 3 para o 1o valor na pilha),
[*] (efetuamos a multiplicação dos dois valores, o valor 15 aparece na 1a posição da pilha),
[2] (deslocamos 15 para a 2a posição da pilha e colocamos 3 para o 1o valor na pilha)
[+] (adicionamos 2 ao resultado, 17 aparece na 1a posição da pilha).
Escreva um programa que simule uma calculadora RPN de 4 operações (+,-,*,/) utilizando
vetores para representar a pilha de dados.

7.17 Reverse é o nome de um antigo jogo de tabuleiro, que pode ser facilmente implementado em um
computador: consiste de um tabuleiro de 3x3 casas, com um disco branco ou preto dispostos,
inicialmente, de modo aleatório em cada casa.

[1][2][3]
[4][5][6]
[7][8][9]

Ao selecionar uma das casas o jogador reverte a cor do disco daquela casa e de algumas casas
vizinhas conforme o esquema acima. O objetivo do jogo é reverter todas as casas para uma mesma
cor. Escreva um programa que simule o tabuleiro do jogo de Reverse.

Ao pressionar Reverte:
[1] [1],[2] e [4]
[2] [2],[1] e [3]
[3] [3],[2] e [6]
[4] [4],[1] e [7]
[5] [5],[2],[4],[6] e [8]
[6] [6],[3] e [9]
[7] [7],[4] e [8]
[8] [8],[7] e [9]
[9] [9],[6] e [8]

7.18 Caso já não tenha feito assim, Rescreva o programa do exercício 7.1 tornando-a recursiva.

7.19 Escreva uma função que receba duas matrizes de ordem m e construa o produto matricial entre eles.

vi
Capítulo 8: Ponteiros
8.1 Rescreva a função round() do exercício 6.1 para que receba o endereço da variável a ser
arredondada. A nova função deve ter a seguinte declaração void round(float *r) e deve
arredondar o próprio numero passado.

8.2 Escreva uma função void troca(int *a, int *b) que permuta entre si os valores de a e b.

8.3 Escreva uma função void stat(float vet, int N, float *med, float *dsvpd)
que receba um vetor de números reais vet, seu tamanho N e calcule a média aritmética med e o
desvio padrão6 dsvpd destes valores.

8.4 Escreva uma função void extremos(float vet, int N, float *max, float
*min) que receba um vetor de números reais vet, seu tamanho N e determine o maior e o menor
(max e min) destes valores.

8.5 Rescreva o programa do exemplo 7.1 para que, usando alocação dinâmica de memória , construa um
vetor de N elementos, sendo N digitado pelo usuário.

8.6 Escreva um programa que, usando alocação dinâmica de memória, construa um vetor de N
elementos gerados aleatoriamente no intervalo [0,10], sendo N digitado pelo usuário. Em seguida
este programa deve chamar a função remove_dup() do exercício 7.6. É necessária alguma
modificação no código desta função?

8.7 Escreva uma rotina void graf(float a float b, float (*pf)(float)) que recebe
um endereço de uma função no ponteiro pf, os valores de extremos a e b e desenhe o gráfico da
função apontado por pf.

6
Ver GIOVANNI, J. R., BONJORNO, J. R., Matemática, vol. 3, São Paulo: FTD, s.d. p. 320.
vii

Você também pode gostar