You are on page 1of 183

LINGUAGEM DE PROGRAMACA~ O E

ESTRUTURAS DE DADOS
BENEDITO MELO ACIO LY
VOLUME I
FTC 2001
2
Conteudo
1 INTRODUCA~ O:SOBRE LINGUAGEM DE PROGRAMACA~ O 5
1.1 Processamento de dados . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.2 Organizac~ao de um computador . . . . . . . . . . . . . . . . . . . . . . . . 10
1.3 Sistema de programac~ao de apoio . . . . . . . . . . . . . . . . . . . . . . . 14
1.4 Construca~o de programas . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2 ALGUNS ALGORITMOS SIMPLES 21
2.1 Problemas usando o tipo abstrato de dados inteiro . . . . . . . . . . . . . . 21
2.2 Exerccios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
2.3 Algoritmos estruturados . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
3 COMANDOS ESTRUTURADOS 45
3.1 Estruturas de decis~ao de selec~ao ou de alternativas . . . . . . . . . . . . . 58
3.2 Exerccios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
4 ALTERNATIVAS MU LTIPLAS 79
4.1 Selec~ao multipla . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
4.2 Exerccios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
5 PROGRAMACA~ O MODULAR 97
5.1 Procedimentos e func~oes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
5.2 Procedimentos e func~oes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
5.3 Exerccios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
6 DADOS ESTRUTURADOS 119
6.1 Introduc~ao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
6.2 Tipos abstratos de dados . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
6.3 Tipos de dados basicos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
6.4 O tipo matriz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
6.5 Variaveis e literais de string . . . . . . . . . . . . . . . . . . . . . . . . . . 141
6.6 Registros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
3
4 
CONTEUDO
6.7 Arquivos(File) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
6.8 Aplicac~oes de matrizes e registros . . . . . . . . . . . . . . . . . . . . . . . 153
6.9 Exerccios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162
Bibliogra a 174
Captulo 1
INTRODUCA~ O:SOBRE
LINGUAGEM DE
PROGRAMACA~ O
O computador e um instrumento imprescindvel ao comercio, a industria e a pesquisa
cient ca. Ele e um aut^omato que executa processos computacionais segundo regras pre-
1

cisamente estabelecidas. O computador possui um repertorio limitado de instruc~oes ele-


mentares que ele \entende" e e capaz de obedecer. Essas instruc~oes s~ao, porem, executadas
com rapidez e con abilidade extraordinarias. A utilidade do computador provem de sua
capacidade de executar sequ^encias extremamente longas de instruc~oes, que se traduzem
em inumeras aco~es elementares. O ato de agrupar tais sequ^encias de instruc~oes em \re-
ceitas" representando certa classe de processos computacionais e chamado programaca~o.
As ideias basicas sobre as quais se apoia a construc~ao de programas podem ser explicadas
e compreendidas sem qualquer refer^encia ao computador.
A seguir apresentaremos algumas noc~oes basicas de programac~ao. Como elas s~ao
fundamentais, n~ao podem ser de nidas formalmente em termos de outros conceitos. Ser~ao,
apenas, explicadas e ilustradas por meios de exemplos.

Ac~ao
Podemos dizer de uma aca~o que:
 tem durac~ao nita;
 tem um efeito esperado e bem de nido;
1 Chamamos de automac~ao o processo em que uma tarefa deixa de ser desenvolvida pelo homem e
passa a ser realizada por uma maquina.

5
6 CAPITULO 1. INTRODUCAO:SOBRE
~ ~
LINGUAGEM DE PROGRAMACAO
 subentende a exist^encia de objetos sobre os quais ela e executada e cujo efeito e
reconhecido como mudancas de estado desses objetos;
 pode ser descrita em termos de uma linguagem ou sistema de formulas;
 sua descric~ao e chamada comando;
 pode ser simples ou composta. Uma ac~ao composta e tambem chamada processo
2

ou computa
ca~o.

Se for possvel executar as partes de uma ac~ao composta em ordem cronologica ri-
gorosa, de modo que duas quaisquer delas nunca sejam executadas simultaneamente, o
processo e chamado sequencial.
Portanto, um programa e um comando que descreve um processo composto. Em outras
palavras, um programa e um conjunto de comandos cuja ordem em que s~ao escritos pode
n~ao coincidir com a ordem cronologica das ac~oes correspondentes.
Podemos dizer de um processador que
 ele e a forca motriz que realmente executa as ac~oes, segundo comandos espec cos;
 ele pode ser um ser um humano ou um aut^omato.
Toda ac~ao requer uma certa quantidade de trabalho, dependendo do processador. Essa
quantidade pode ser expressa em termos do tempo gasto pelo processador para executar
a ac~ao. Esse intervalo de tempo, por sua vez, traduz-se mais ou menos diretamente em
uma medida de custo.Portanto, e importante conhecer o processador disponvel e, com
base nessa informac~ao, procurar a soluc~ao de menor custo.
Exemplo 1 (Multiplicac~ao)
Considere o comando:
multiplique os dois numeros naturais x e y;
denote seu produto por z: (1.1)
Se o processador disponvel entende este comando, isto e, ele sabe o que se quer
dizer por \numero natural" e por \multiplicac~ao", ent~ao qualquer elaborac~ao ulterior e
desnecessaria.
Suponha, porem, que o processador disponvel
1. n~ao entende sentencas em linguagem natural, e
2 Uma ac~ao e composta se ela puder ser decomposta em partes.
7
2. n~ao sabe multiplicar, mas, apenas, somar.
Um programa para manipular numeros(ou letras) usa nomes gerais representando
objetos variaveis. Esses nomes s~ao denominados variaveis. No incio de cada processo,
os valores espec cos(2 ou 'a', por exemplo) s~ao atribudos a essas variaveis. Essa ac~ao de
atribui ao 
c~ e fundamental nos processos computacionais executadodos por computador.
Uma variavel e comparavel a um quadro-negro: seu valor pode ser inspecionado(\lido")
tantas vezes quanto desejadas, ou pode ser apagado e reescrito. A ac~ao de reescrever, no
entanto, causa a perda do valor anteriormente escrito. A atribuic~ao de um valor k a uma
variavel v, sera denotado, de ora em diante, por

v k (1.2)
O smbolo e chamado operador de atribuic~ao.
O comando 1.1 pode, agora, ser de nido formalmente por

z xy (1.3)
Se este comando for decomposto numa sequ^encia de ac~oes que se sucedem cronolo-
gicamente, ent~ao a aca~o de multiplicac~ao torna-se um processo sequencial e o comando
1.3 toma a forma de um programa. Informalmente, descreveremos esse programa como
3

segue:

Passo 1 : z 0;
u x;
Passo 2 : repita as instruc~oes
z z+y
u u 1
ate que u=0.

Quando forem dados valores determinados a x e a y, o processo correspondente pode


ser visualizado registrando-se os valores atribudos as variaveis u e v, a propoc~ao que o
processo transcorre no tempo. Com x = 5 e y = 13, obtemos a tabela(de rastreio) a
seguir.
3 Por informalmente queremos signi car que n~ao estamos usando uma linguagem de programac~ao para
descrever esse programa.
8 CAPITULO 1. INTRODUCAO:SOBRE
~ ~
LINGUAGEM DE PROGRAMACAO
Passo valor de z valor de u
1 0 5
2 13 4
2 26 3
2 39 2
2 52 1
2 65 0
Pelo passo 2, o processo termina assim que u = 0. Neste instante, z assume o valor
nal 65 = 5  13. 4

Exemplo 2 (Divis~ao)
Considere as seguintes instruco~es:
1. divida o numero natural x pelo numero natural y;
2. denote o quociente inteiro por q e o resto por r.
A instruc~ao (2) pode ser expressa pelas seguintes relac~oes:

x=qy+r e 0r <y (1.4)


Introduzindo o operador de divis~ao div, a computac~ao pode ser descrita pelo seguinte
comando formal de atribuic~ao.

(q; r) x div y (1.5)


Novamente, para mostrar a possibilidade da transformac~ao do comando(constitudo
das duas instruc~oes acima) em programa, suponhamos que ele e destinado a um proces-
sador incapaz de dividir, isto e, sem o operador div. Vamos supor que o processador e
capaz de efetuar subtrac~oes. Portanto, divis~oes devem ser decompostas em sequ^encias de
subtrac~oes.

Passo 1 : q 0;
r x;
Passo 2 : enquanto r  y repita
q q+1
r r y
4Os objetos desta computac~ao s~ao numeros. Para se executar operac~oes sobre determinados numeros,
e necessario representa-los com uma notac~ao espec ca.
9
x e y denotam constantes que representam valores xados de antem~ao. Com x = 100
e y = 15 obtemos a seguinte tabela.
Passo valor de q valor de r
1 0 100
2 1 85
2 2 70
2 3 55
2 4 40
2 5 25
2 6 10
Ao se chegar a r < y o processo termina. Os resultados obtidos s~ao q = 6 e r = 10,
satisfazendo as relaco~es 1.4:

100 = 6  15 + 10 e 0  10 < 15 (1.6)

Os exemplos 1 e 2, descritos acima, s~ao processos sequenciais nos quais as atribuic~oes


s~ao feitas em estrita ordem cronologica. Nestas notas, assim como no curso de linguagem
de programac~ao 1, so discutiremos processos sequenciais, portanto, a palavra processo
signi cara, para nos, processo sequencial.
Os exemplos que apresentamos mostram que todo programa descreve uma sequ^encia
de mudancas de estados, do conjunto de suas variaveis. Se o programa for seguido duas
vezes, com diferentes valores de x e y, n~ao seria correto a rmar que os dois processos ou
computac~oes s~ao id^enticos. No entanto, eles s~ao regidos pelo mesmo padr~ao de compor-
tamento. A descric~ao desse padr~ao de comportamento, indepentemente do processador
particular, e normalmente denominada algoritmo. O termo programa e mais apropriado
para aqueles algoritmos, t~ao elaborados, que podem ser seguidos ou executados por um
tipo particular de processador.
Para construir programas executaveis por computadores automaticos, o programador
deve possuir algum conhecimento do processador(computador). Quanto mais preciso for
o conhecimento que tiver do processador, melhor podera converter algoritmos em progra-
mas que utilizem as caracterscas partibulares desse processador. Por outro lado, quanto
mais ajustado e \sintonizado" ao processador for o algoritmo, maior o esforco dispendido
na elaborac~ao do programa. Embora n~ao pretendamos que o aluno sai conhecendo com
profundidade um computador, e fundamental que ele conheca as caracterstcas mais im-
portantes e comuns a maioria dos computadores. A seguir descreveremos o que vem a ser
o conceito de processamento de dados e a estrutura basica dos computares.
10 CAPITULO 1. INTRODUCAO:SOBRE
~ ~
LINGUAGEM DE PROGRAMACAO
1.1 Processamento de dados
Assim como a ideia de ac~ao, o conceito de informac~ao e primitivo. Entendemos que
5

uma informac~ao e capaz de transmitir um conhecimento. Para que haja transmiss~ao de


conhecimento, isto e, para que haja informac~ao, e necessario um emissor e um receptor.
O emissor emite os dados, enquanto o receptor recebe os dados, interpretando-os para
transforma-los em informac~ao. Os dados s~ao o suporte da informac~ao e representados por
meio de uma codi cac~ao. Entretanto, para que haja informac~ao e preciso que o receptor
seja capaz de interpretar os dados atraves de uma decodi cac~ao. A tarefa do computa-
dor e executar operac~oes com os dados, como, por exemplo, copiar, alterar, gravar, etc.
Dizemos, ent~ao, que o computac~ao executa processamento de dados.
Um computador digital e capaz de representar dois tipos de dados basicos: os numeros
e as letras de algum alfabeto(caracteres). Podemos citar como exemplos de processamento
de dados por um computador os seguintes.
Exemplo 3 1. Imprimir uma relac~ao de nomes em ordem alfabetica.
2. Elaborar uma folha de pagamento.
3. Achar a soluc~ao de uma equac~ao de 2o grau.
4. Imprimir os 50 primeiros numeros pares.

1.2 Organizac~ao de um computador


As partes principais de um computador s~ao o processador (tambem conhecida como uni-
6

dade logica-aritmetica) e a unidade memoria.

Memoria e Processador
partes principais do computador
Podemos a rmar que
1. a memoria abriga, em forma codi cada, os objetos que ser~ao manipulados. Esses
objetos s~ao chamados dados. O desempenho da memoria e medido pela sua ca-
pacidade(tamanho) e pela velocidade como os dados s~ao nela armazenados e dela
retirados. A memoria tem sempre capacidade nita.
Um conceito e primitivo se ele n~ao pode ser explicado em termos de outros mais simples.
5
O processador e mais conhecido como unidade central de processamento(CPU-Central Processing
6

Unit) MEMORIA E CPU .


partes principais do computador
~ DE UM COMPUTADOR
1.2. ORGANIZACAO 11
2. O processador(unidade logica-aritmetica) executa adic~oes, multiplicac~oes, compa-
rac~oes, etc. Os dados s~ao buscados(lidos) na memoria para o processamento e, uma
vez obtido o resultado pela unidade logica-artimetica, armazenado novamente na
memoria(escritos).
O processador possui seus proprios elementos de memoria, chamados registradores.
Em cada instante eles contem, apenas, os dados a serem imediatamente processados.
Todos os outros dados s~ao deixados na memoria que, desse modo desempenha um papel
analogo ao de uma geladeira.
Para ilustrar como funciona o processamento na CPU, apresentaremos o calculo de
uma express~ao aritmetica, com varios operandos e resultados intermediarios.
Exemplo 4 Calcular a express~ao aritmetica

a  b + c  d: (1.7)
Para calcular essa express~ao usaremos, mais uma vez, a tecnica de decompo-
sic~ao de uma tarefa complicada em uma sequ^encia de tarefas mais simples.
Usando essa tecnica, cada operac~ao aritmetica e efetuada sobre operandos to-
mados dos registradores do processador, com a subsequente substituic~ao, nos
registros, dos resultados. Assim

R1 a
R2 b
R1 R1  R2
z R1
R1 c
R2 d
R1 R1  R2
R2 z
R1 R1 + R2
onde R1 e R2 denotam registros do processador e z designa um resultado intermediario,
temporariamente depositado na memoria. O resultado nal esta no registro R1.
Desse modo, o calculo da express~ao foi transformado em um programa, consistindo de
tr^es especies de instruc~oes ou comandos:
1. intruc~oes que buscam os operandos na memoria;
2. operaco~es(aritmeticas) atuando exclusivamente sobre os registros do processador;
12 CAPITULO 1. INTRODUCAO:SOBRE
~ ~
LINGUAGEM DE PROGRAMACAO
3. instruc~oes que depositam resultados na memoria.
Este exemplo mostra a necessidade de uma ntima conecc~ao entre o processador e a
memoria, pois e sempre muito grande o uxo de informac~oes entre essas duas unidades.
A memoria contem objetos acessveis atraves de nomes distintos(a, b, c, ...). Por isso
e preciso um criterio de disposic~ao dos elementos da memoria, parecido ao conjunto de
caixas de correspond^encia. Portanto, os objetos devem estar em um conjunto de posic~oes
de memoria identi cados de modo unico, cada um deles possuindo um endereco. Todo
acesso a memoria deve ser acompanhado da especi cac~ao do endereco da posic~ao de
memoria desejada.
As posic~oes de memoria tem como nalidade conter e preservar os objetos(dados). A
capacidade da memoria do computador de preservar dados n~ao e baseada no fato de que
ela abriga sicamente o objeto, mas porque certa codi cac~ao do mesmo e representada
pelo o estado da posic~ao de memoria. Portanto, cada posic~ao de memoria deve ser capaz
de assumir um certo numero de estados. Nos computadores digitais os elementos de
memoria possuem somente dois estados distintos e, por isso, s~ao chamados elementos de
memoria binarios. Se um conjunto de n elementos de memoria binarios for agrupados, ele
podera assumir 2n diferentes combinac~oes de estados. Se este grupo for considerado como
uma unidade, ent~ao ela representara uma posic~ao de memoria com 2n estados possveis.
Exemplo 5 Codi cac~ao de objetos em grupos de dgitos binarios.
Seja
x = bn :::b b
1 1 0 (1.8)
um numero binario qualquer, com n dgitos, na representac~ao posicional.7
A regra de codi caca~o desses numeros(iclusive o 0) e dada por

x = b + 2b + ::: + 2n bn
0 1
1
1 (1.9)
Esta regra n~ao e a unica possvel, mas, em muitos aspectos, e a mais adequada.
Ela e a mesma em que se baseia a representac~ao decimal desses numeros, isto
e, se

x = dm :::d d
1 1 0 (1.10)
Por exemplo, 1324 e um numero natural decimal representado na forma posicional. Aqui, o dgito
7
3, como ocupa a segunda posic~ao, da esquerda para a direita a contar de 0(portanto, a terceira posic~ao
contanto de zero), representa o valor 300.
~ DE UM COMPUTADOR
1.2. ORGANIZACAO 13
ent~ao,

x = d + 10  d + 10  d + ::: + 10m  dm
0 1
2
2
1
1 (1.11)
Exemplo 6 Alguns numeros codi cados em binario e decimal.
Binaria Decimal
1101 13
10101 21
111111 63
1101011 107
Podemos observar deste exemplo que posic~oes de memorias nitas, isto e, posic~oes de
memorias capazes de assumir somente um numero nito de estados diferentes, t^em a pos-
sibilidade de armazenar somente numeros pertencentes a um intervalo nito de valores.
O numero de elementos binarios de memoria, reunidos sob uma unica posic~ao de memoria
enderecavel(palavra), e conhecido como comprimento de palavra do computador. Os va-
lores mais comuns de comprimentos de palavras s~ao: 8, 16, 32, 32 e 64, que correspondem
a conjuntos de 2n valores distintos, com n o comprimento da palavra.
Para que o computador tivesse um acesso \facil" a um programa, para poder segui-lo,
Jonh von Neumann teve a ideia de armazena-lo na memoria. Portanto, a memoria e usada
tanto para guardar os objetos(dados), como a \receita" do processo computacional(o
programa).
Como consequ^encia do conceito de computador de programa armazenado, as instruc~oes
precisam tambem ser codi cadas. No exemplo, 4 cada instruc~ao e representavel por
um codigo de operaca~o e em alguns casos por um operando. Se os operandos forem
8

representados por enderecos na posic~ao de memoria e se os enderecos forem numeros


inteiros 0, 1, 2, 3, ..., ent~ao o programa da codi cac~ao de programas estara essencialemente
resolvido: todo programa sera representado por uma sequ^encia de numeros(ou grupos de
numeros) e podera, portanto, ser depositado na memoria do computador.
Outra consequ^encia do conceito de programa armazenado e que todo programa ocu-
para certo numero de posico~es de memoria, isto e, tomara certa porc~ao de memoria. O
numero de posic~oes de memoria ocupadas, e que n~ao estar~ao disponveis para armazena-
mento de dados, e proporcional ao comprimento do programa. Portanto, e importante ter
em vista que e \melhor" aquele programa, dentre os programas que executam a mesma
ac~ao, que seja mais conciso.
A seguir apresentaremos um resumo das func~oes de um computador que e baseado no
conceito de compartilhamento entre dados e programa.
8Para especi car o tipo de tarefa a ser executada, como leitura ou armazenamento de dados na
memoria, adic~ao, multiplicac~ao, etc.
14 CAPITULO 1. INTRODUCAO:SOBRE
~ ~
LINGUAGEM DE PROGRAMACAO
1. Assim que termina a execuc~ao de um programa P , um novo programa Q pode ser
aceito na memoria para subsequente execuc~ao( exibilida e vasta aplicabilidade).
2. Um computador pode gerar(segundo um certo programa) uma sequ^encia de numeros
que ele subsequentemente considerara e interpretara como instruc~oes codi cadas. Os
dados gerados na primeira etapa formam um programa a ser seguido na segunda.
3. Podemos instruir um computador X para considerar sequ^encias de numeros repre-
sentando programas como se fossem dados, a serem transformados(segundo a algum
programa tradutor) em sequ^encias de numeros representando programas codi cados
para um outro computador Y.
Os dados, provinientes de um meio externo, s~ao \fornecidos" ao computador e arma-
zenados na memoria atraves dos dispositivos de entradas.
Os dados s~ao transmitidos da menoria para algum meio externo atraves dos disposi-
tivos de sada.

ENTRADAS 
MEMORIA
/

E CPU SAIDAS
/

Alguns disposivos de entradas: teclado,disk driver.


Aguns dispositivos de sadas: monitor de vdeo, disk driver, impressora.

1.3 Sistema de programac~ao de apoio


Ate a decada de 60, programar consistia em fazer codi cac~ao de longas sequ^encias de
instruco~es. Inicialmente, estas codi cac~oes eram escritas em alguma notac~ao simbolica,
como os numeros na forma binaria, octal ou hexadecimal. Hoje esse tipo de atividade
e denominada codi cac~ao, para distinguir de programac~ao que abrange a tarefa mais
difcil de construc~ao de algoritmos. Com o aparecimento dos computadores mais rapidos
cou evidente as de ci^encias desse processo de codi cac~ao, dentre outras, pelas seguintes
raz~oes.
1. O codi cador era forcado a ajustar o programa as caractrsticas particulares do
computador de que dispunha. Portanto, ele tinha que levar em conta todos os por-
menores da maquina, inclusive da organizac~ao de seu processador e de seu conjunto
de instruc~oes. O interc^ambio de programas entre diferentes maquinas era impossvel.
Por isso, grande parte do conhecimento dos metodos de codi cac~ao para uma dada
maquina era praticamente inutil quando se passava para outro computador. Desse
modo, cada instituic~ao construia seus proprios programas e era forcada a desfazer-se
dos mesmo, e codi car novos, sempre que um novo computador tomava lugar do
antigo. Por tudo isso, cou evidente que a adaptac~ao e ajuste de algoritmos as
~ DE APOIO
1.3. SISTEMA DE PROGRAMACAO 15
caracterscas particulares de um computador espec co representava um mal inves-
timento da intelig^encia humana.
2. A subordinac~ao do programador as peculiariddes de um tipo de computador possi-
bilitou e ate estimulou a invenc~ao e aplicac~ao de toda sorte de truques para obter o
maximo de desempenho da maquina. Enquanto essa \trucologia" estava em moda, o
programador dispendia um tempo apreciavel na construc~ao de programas \otimos",
cuja veri cac~ao era geralmente muito difcil. Era praticamente impossvel descobrir
os princpios gerais de um programa construdo por outra pessoa. Muitas vezes,
era igualmente difcil explicar a estrutura de seus proprios programas. Esta arte
da codi cac~ao perdeu atualmente quase toda a import^ancia. O programador expe-
rimentado evita conscientemente o uso de truques, escolhemos, em contrapartida,
soluc~oes claras e sistematicas.
3. O chamado codigo de maquina continha, apenas, um mnimo de redund^ancias a
base das quais erros formais de codi cac~ao poderiam ser detectados. Consequente-
mente, mesmo os erros de digitac~ao, que poderiam ter efeitos desastrosos quando
da execuc~ao do programa, eram difceis de ser descobertos.
4. A representac~ao de um programa complexo como uma sequ^encia linear n~ao estru-
turada de comandos e uma forma muito inadequada de uma pessoa descrever ou
compreender um processo complicado. A estruturac~ao do programa foi o primeiro
passo a ajudar o programador a sintetizar sistematicamente e a manter uma vis~ao
de conjunto de programas complicados.
Essas de ci^encias levaram ao desenvolvimento das chamadas linguagens de progra-
mac~ao de \alto" nvel. Essas linguagens possilitaram os meios de instruir computador
imaginario, hipotetico, que e projetado n~ao segundo as limitac~oes da tecnologia atual,
mas, de acordo com os habitos e possibilidades de o homem expressar seus pensamentos.
Atualmente dispomos, ent~ao do seguinte cenario:
- de um lado, temos uma maquina A, que e economicamente exequvel, mas, cujo uso
n~ao e conveniente nem estimulante,
- de outro, um computador B que e adequado as necessidades humanas, mas existe,
apenas, no papel.
A ponte entre esses dois extremos e feita, atualmente, por uma entidade chamada (em
ingl^es)software (programac~ao de apoio). Em contrapartida, a maquina fsica e chamada
hardware. Um sistema de programa c~ao de apoio(sistema de softtware) e um programa
C, que, quando executado pela maquina real A, capacita A a traduzir programas escritos
para um computador hipotetico B, em programas para a maquina A. O programa C e
16 CAPITULO 1. INTRODUCAO:SOBRE
~ ~
LINGUAGEM DE PROGRAMACAO
chamado tradutor ou compilador. Ele permite que tudo se passe como se A fosse o
computador ideal B.
A utilizac~ao do compilador C alivia, assim, o programador da preocupac~ao de ter
sempre que levar em conta, em seus mnimos detalhes, as caractersticas particulares de seu
computador A. Isto n~ao libera da obrigac~ao do programador de estar permanentemente
consciente de que e a maquina A que, a nal, executara os programas e, que ela tem
limitac~oes bem de nidas, impostas por sua velocidade e capacidade de memoria nitas.
Normalmente, um sistema combinado de \hardware" e \software" processa um progra-
ma P em duas etapas distintas, que se sucedem cronologicamente. Na primeira etapa, P
e traduzido pelo compilador C numa forma interpretavel por A. Na segunda, o programa
traduzido e executado.
A esta ultima etapa chamamos execuc~ao e a primeira compilac~ao.
Compilac~ao: programa = compilador C
dados de entrada = programa P em linguagem B
dados de sada(resultados) = programa P na linguagem A.
Execuc~ao: programa = P na linguagem A
dados de entrada = argumentos X da computac~ao
dados de sada(resultados) = resultados Y da computac~ao.

1.4 Construc~ao de programas


Ja sabemos que
 o processamento de dados e feito pela execuc~ao de programas e,
 um programa e uma sequ^encia de instruc~oes codi cadas em uma linguagem de
programac~ao que,
 para serem executadas precisam ser armazenadas na memoria de um computador.
Portanto, a seguinte pergunta: para que serve um programa?
A resposta seria, para resolver um problema. Esta resposta, por sua vez, suscita uma
outra pergunta: o que e um problema? Existem muitas pesquisas para tentar responder o
que um problema e. No nosso caso, estamos interessados em problemas computacionais,
aqueles relacionados com a manipulac~ao de informac~ooes.
Poderamos dizer que um problema envolve \uma pergunta de carater geral a ser
respondida". Segundo alguns autores, um problema e descrito quando especi camos a
entrada(quais s~ao os possveis dados) e as condic~oes(ou relac~oes) que a sada deve satisfazer
para uma determinada entrada.
Uma inst^ancia de um problema e obtida quando xamos determinados valores para
os dados de entradas.
~ DE PROGRAMAS
1.4. CONSTRUCAO 17
Os dados envolvidos em um problema pertencem a um determinado conjunto de valo-
res, que podem ser organizados de formas diferentes. A resoluc~ao do problema, em geral,
exige que sejam efetuadas operac~oes sobre os dados ou que sejam veri cadas relac~oes entre
esses valores.
Essas considerac~oes nos permitem dizer que temos um tipo abstrato de dados
quando:
 especi camos um conjunto de valores munidos de algumas operac~oes e relac~oes,
 enfatizando o comportamento dos elementos desse tipo e,
 desprezando os detalhes de representac~ao. 9

Ja sabemos que um programa de computador e descrito por uma linguagem de pro-
gramaca~o. Cada linguagem de programac~ao tem seus proprios tipos de dados, isto e,
conjunto de valores, operac~oes e relac~oes ja implementadas(disponveis para uso). Na
implementaca~o surge o conceito de domnio, isto e, da limitac~ao do conjunto de valores
dos elementos representados.
Os tipos de dados existentes nas linguagens de programac~ao podem representar el-
mente ou n~ao os dados idealizados(tipos abstratos de dados). Por isso, faremos distinc~ao
entre os tipos de dados abstratos, relacionados diretamente com o problema, e os tipos
de dados no nvel concreto, quando representamos as abstrac~oes na linguagem de progra-
mac~ao utilizada.
Durante a execuca~o do programa os dados s~ao armazenados na memoria do computa-
dor. As localizac~oes de memoria em que esses dados s~ao armazenados s~ao denominadas
estruturas de dados. As estruturas de dados s~ao organizadas conforme os tipos de da-
dos disponveis na linguagem de programac~ao, de forma que elas representem, o mais
elemente possvel, os tipos abstratos de dados em considerac~ao.

Tecnicas de programac~ao
Quando estamos elaborando algoritmos complexos precisamos utilizar metodos sistematicos
de programac~ao para obter programas con aveis, exveis e e cientes.
Uma proposta de metodologia estabelece os seguintes passos:
1. Analise do problema.
2. Projeto do programa: algoritmo e estrutura de dados.
3. Implementac~ao(codi cac~ao) e teste do programa.
9 com isto queremos signi car que n~ao importa o nome do elemento nem sua representac~ao na memoria,
feita por uma linguagem de programac~ao.
18 CAPITULO 1. INTRODUCAO:SOBRE
~ ~
LINGUAGEM DE PROGRAMACAO
4. Veri cac~ao do programa.
A seguir analisaremos, sucintamente, cada um desses itens propostos. E claro que cada
um desses itens se desdobram em um ou mais cursos. Por exemplo, o primeiro item pode
ser aprofundado num curso de analise de algoritmos, o item 2 em cursos como construc~ao
de programas e estruturas de dados, e assim por diante.
Analise do problema
Esta e a fase inicial na elaborac~ao de programas. Nesta fase procuramos
 nos certi car que compreendemos o problema corretamente, sem ambiguidades,
 nos assegurar que entendemos completamente as especi cac~oes das entradas e das
sadas.
Para realizar esta fase precisamos seguir os seguintes passos:
1. escolher uma amostra signi cativa dos dados e de nir as especi cac~oes de entrada;
2. determinar a sada desejada correspondente aos dados de entrada, de nindo as es-
peci cac~oes de sada.
E bom observar que a escolha da amostra de entrada con rma a compreens~ao correta
do enunciado do problema.
Projeto do programa
Esta e a fase mais importante no desenvolvimento de programas. Aqui estudamos metodos
de resoluc~ao de problemas e estabelecemos estrategias para suas soluc~oes.
A partir da estrategia de resoluc~ao do problema desenvolvemos um algoritmo e de-
nimos as estruturas de dados que ser~ao utilizadas tendo em vista otimizar o bin^omio
espaco-tempo, isto e, visando obter um programa que apresente um tempo de execuc~ao
mnimo e com o melhor aproveitamento de espaco da memoria.
Como o algoritmo e um elemento importante nessa fase, a seguir apresentaremos
algumas de suas caractersticas e estrategias de construc~ao, necessarias neste estagio de
nosso estudo.
Algoritmo - intuitivamente,  e uma sequ^encia nita de instruc~oes ou operac~oes basicas 10

cuja execuc~ao, em tempo nito, resolve um problema computacional, qualquer que


seja sua inst^ancia. 11

10Estas operac~oes devem ser de nidas sem ambiguidade e executaveis em tempo nito dispondo-se,
apenas, de lapis e papel.
11A ordena c~ao da sequ^encia de instruc~oes do algoritmo e apoiada na estrategia estabelecida durante
a analise do problema. O desenvolvimento do algoritmo n~ao pode perder de vista os tipos de dados
considerados e a sua representac~ao.
~ DE PROGRAMAS
1.4. CONSTRUCAO 19
Desenvolvimento top-down - esta tecnica consiste em dividir o problema em varios
subproblemas de resoluc~ao mais simples. Para isso e preciso identi car partes ou
etapas na estrategia de resoluc~ao do problema, elaborando inicialmente um esboco
da resoluc~ao. Em seguida, e detalhada sucessivamente cada etapa, re nando o
processo de resoluc~ao, ate chegar a uma sequ^encia de operac~oes basicas sobre os
tipos de dados considerados.
Descri ao - um algoritmo pode ser descrito quer atrav
c~ es de um pseudocodigo(linguagem
algortmica) quer atraves de uxogramas. No uxograma, cada operac~ao basica(instruc~ao)
12

e representada por um desenho. Na linguagem algortmica cada operac~ao basica e


escrita em uma linguagem semelhante a linguagem natural, com algumas regras
comuns as linguagens de programac~ao.
Implementac~ao
Denominamos implementac~ao de um algoritmo a sua codi cac~ao em uma linguagem de
programac~ao.
O algoritmo pode ser implementado em qualquer linguagem de programac~ao. Essa
implementaca~o pode ser muito \facil", consistindo, em geral, numa transcric~ao de ope-
rac~oes basicas. A implementac~ao se torna mais trabalhosa dependendo das caractersticas
da linguagem escolhida e dos tipos de dados nela de nidos.
Veri cac~ao de Programas
A veri cac~ao de um programa tem como objetivo demonstrar que o algoritmo realmente
resolve o problema proposto, qualquer que seja sua inst^ancia. Este topico e considera-
do bastante mais avancado, requerendo do aluno muita maturidade, assim como base
matematica e logica.

12Os uxogramas s~ao preferveis nos casos onde e preciso uma visualizaca~o global do processo de
resoluc~ao e de suas partes. Por outro lado, a linguagem algortmica apresenta outras vantagens: em
geral, e mais facil escrever do que desenhar e a codi cac~ao em uma linguagem de programa acaba se
tornando uma simples transcric~ao de palavras-chave.
20 CAPITULO 1. INTRODUCAO:SOBRE
~ ~
LINGUAGEM DE PROGRAMACAO
Captulo 2
ALGUNS ALGORITMOS SIMPLES
Introduc~ao
Ja sabemos que um programa deve consistir de comandos formulados em notac~ao que
o computador \entenda". Embora n~ao saibamos ainda que especies de comandos ou
formulas uma linguagem de programac~ao deva possuir, certamente sabemos que esses
comando especi car~ao as ac~oes pretendidas. Essa necessidade de precis~ao provalemente
constitui o traco mais caracterstico que distingue a comunicac~ao entre seres humanos da
comunicac~ao com maquinas. Lidar com computadores exige precis~ao e clareza. Incerteza
e ambiguidade s~ao abosolutamente proibidos.
Nesta parte das notas de aula, desenvolveremos algoritmos onde procuraremos seguir,
na medida de nossa base matematica, as etapas recomendadas na construc~ao de programas
visto em outra parte. Na etapa da implementac~ao poderamos usar qualquer linguagem
1

de programac~ao, mais amplamenente utilizada, como C, C++ ou Java. Usaremos o C++,


sem, no entanto, explicar neste texto as caractersticas desta linguagem. O aluno deve
seguir um outro texto de linguagem C++ ou ja conhecer esta linguagem para tirar proveito
da fase de implementac~ao. Caso o aluno n~ao conheca C++ ou n~ao esteja interessado em
conhece-la pode, simplesmente, pular a fase de implementac~ao.

2.1 Problemas usando o tipo abstrato de dados in-


teiro
Nesta sec~ao so consideraremos problemas sobre a estruturas dos numeros inteiros, pro-
blemas com outros tipos ser~ao considerados mais adiante. A seguir apresentaremos uma
1N~ao abordaremos certos aspectos do desenvolvimentos de algoritmos como, por exemplo, vericac~ao
e analise de e ci^encia(complexidade). Como so abordaremos problemas muito simples, a fase de projeto
ca muito simplicada, parecendo ate desnecessaria.

21
22 CAPITULO 2. ALGUNS ALGORITMOS SIMPLES
Tipo abstrato inteiro
Objetos: numeros inteiros
Operac~oes/Notac~ao: adic~ao +
subtrac~ao -
multiplicac~ao 
quociente inteiro div
resto da divis~ao mod
Relac~oes/Notac~ao menor <
maior >
diferente 6=
menor ou igual 
maior ou igual 
Objetos constantes numerais inteiros com
ou sem sinal por exemplo,
-34, 13, 0
Figura 2.1: Tipo abstrato inteiro

tabela do tipo abstrado numero inteiro, com suas operac~oes e relac~oes.

Exemplo 7 Enunciado do problema: Calcular a soma de dois numeros in-


teiros.
1. Analise(do problema): lembramos que na fase de analise do problema
devemos especi car a entrada, a sada e, uma relac~ao entre a entrada
e a sada, a qual chamaremos de metodo. Observe que a analise do
problema consiste da sua especi cac~ao, segundo a de nic~ao que apre-
sentamos na primeira parte. E bom observar que exitem varios formas
de especi cac~ao: informal(usando linguagem natural e, quando muito,
matematica), temos a especi cac~ao formal, usando logica ou algebras es-
pec cas, ou podemos usar uma linguagem(executavel pelo computador)
de especi cac~ao. Esta fora de proposito, aqui, uma especi cac~ao que n~ao
seja informal, caso contrario teramos de fazer um curso de espec cac~ao.
(i) Entrada: um par de numeros inteiros.
(ii) Sada: um numero inteiro.
(iii) Metodo: recebe um par de inteiros e devolve um inteiro.
2. Projeto: Lembramos que na fase do projeto devemos quebrar, tanto
quanto possvel, o problema em problemas \menores" cuja soluc~ao seja
2.1. PROBLEMAS USANDO O TIPO ABSTRATO DE DADOS INTEIRO 23
absolutamente obvia. Embora esse problema seja muito simples, ele pode
ser quebrado em tr^es subproblemas ainda mais simples e basicos.
(1) Leia dois numeros inteiros. Leitura de dados.
(2) Some dois numeros inteiros. Soma dos valores lidos.
(3) Devolva o resultado. Por exemplo, imprima o resultado, ou apresente
o resultado no visor, etc.
3. Implementaca~o: Codi car na linguagem C++.
E claro que para chegarmos na fase de implementac~ao devemos desenvolver comple-
tamente o algoritmo, de modo que esta fase seja uma simples transcric~ao da linguagem
algortica para a linguagem de programac~ao. Na medida em que formos desenvolvendo a
fase de projeto iremos apresentando a nossa linguagem algortmica. Somente quando o
algoritmo estiver completamente projetado voltaremos a fase 3, de implementac~ao.
Continuando o projeto, para ler dois numeros, de (1), precisamos de duas variaveis
A e B , onde colocar os dois valores lidos. A ac~ao de colocar(atraves da leitura) os dois
inteiros nas variaveis A e B sera denotado por
leia(A,B)
Usaremos a variavel \soma" para colocar o resultado da adic~ao. Como estamos usando
o smbolo para denotar atribuic~ao, o item (2), do projeto tem a seguinte descric~ao:
soma A + B
Finalmente, para representar a sada de informac~oes, correspondente ao item (3) do
projeto, utilizaremos a instruc~ao de sada:
imprima(soma)
Essas tr^es instruc~oes, escritas sequencialmente, nessa ordem, descrevem o projeto do
2

algoritmo de resoluca~o do problema proposto. Podemos escrev^e-las na mesma linha, como


a seguir, ou em linhas diferentes, com a separac~ao entre uma instruc~ao e a seguinte sendo
feita por um ponto e vrgula:
2Do ponto de vista logico, um algoritmo e constitudo por tr^es estruturas logicas: sequenciamen-
to(sequencial), repetic~ao(repetitiva) e selec~ao(seletiva). Portanto, um algoritmo pode ser constitudo por
qualquer combinac~ao dessas tr^es estruturas. O algoritmo que estamos considerando tem uma estrutura
sequencial, as ac~oes que resolvem o problema, s~ao efetuadas em ordem sequencial, e na ordem em que
aparecem no algoritmo. Mais adiante veremos algoritmos com estruturas logicas alem da sequencial.
N~ao confundir sequencial, enquanto estrutura logica do algoritmo, com o conceito, visto noutra parte, de
algoritmo sequencial, em contrapartida a algoritmo paralelo.
24 CAPITULO 2. ALGUNS ALGORITMOS SIMPLES
leia(A,B); soma(A,B); imprima(A,B);
ou
leia(A,B);
soma(A,B);
imprima(soma)
A rigor, ao descrever um algoritmo, devemos especicar o seu objetivo, quais s~ao os
dados de entradae/ou sada, alem das instruc~oes que o comp~oem. Devemos, tambem,
dar um nome que identi que o algoritmo. Finalmente, o nosso algoritmo deve tomar a
seguinte forma:
Algoritmo adic~ao
Objetivo: dados dois numeros inteiros, calcular sua soma.
Entrada: A, B(inteiros).
Sada: soma(Inteiro)

Adic~ao();
leia(A,B);
soma A + B ;
imprima(soma);
Apos o nome adica~o, que identi ca o algoritmo, colocamos uma par de par^enteses.
Mais adiante, colocaremos par^ametros entre esses par^enteses.
Finalmente, apresentamos a implementac~ao.
Implementac~ao
#include <iostream.h>

void main()
{
int A, B, soma;

cin >> A >> B ;

cout << soma = A + B << endl;


}
2.1. PROBLEMAS USANDO O TIPO ABSTRATO DE DADOS INTEIRO 25
Exemplo 8 Enunciado: Dado um numero inteiro obter seu ultimo algarismo
da direita.
1. Analise:
 Entrada : Um numero entre 0 e 9999.
 Metodo: Escrevendo o numero no sistema decimal, o ultimo algaris-
mo da direita representa as unidades. Para obter esta unidade basta
dividir o numero por 10. Logo, o metodo e: calcule o resto da divis~ao
do numero por 10.
 Sada: O resto da divis~ao de um numero por 10.
2. projeto: O problema e divido nos seguintes subproblemas.
leia um numero inteiro A, entre 0 e 9999.
calcule A mod 10.
imprima o resultado.
Portanto, temos o seguinte algorimo.
Algoritmo ultimo
Objetivo: Obter o ultimo algarismo de um numeero dado.
Entrada: A(inteiros).
Sada: ultimo(Inteiro)

ultimo();
leia(A);
unidade A + B ;
imprima(unidade);
Implementa
c~ao.

#include <iostream.h>

void main()
{

int A, unidade;

cin >> A;
26 CAPITULO 2. ALGUNS ALGORITMOS SIMPLES
unidade = A % 10;

cout << unidade << endl;


}

Em cada um dos execcicios, abaixo, fazer analise do problema, o projeto do algoritmo


e a implementac~ao em C++.

2.2 Exerccios
1. Dado um numero inteiro de tr^es algarismos, inverter a ordem de seus algarismos.
Os tr^es algarismos do numero dado s~ao diferentes.
2. Dado um numero de tr^es algarismo construir outro numero de quatro algarismo de
acordo com a seguinte regra:
(a) os tr^es primeiros algarismos, contados da esquerda para a direita, s~ao iguais ao
do numero dado;
(b) o quarto algarismo e um dgito de controle calculado da seguinte forma: pri-
meiro algarismo + segundo algarismo 3 + terceiro algarismo 5; o dgito de
controle e igual ao resto da divis~ao dessa soma por 7.
3. Dado um numero inteiro de segundos, determinar o seu valor equivalente em graus,
mimutos e segundos. Se a quantidade de segundos for insu ciente para dar o valor
em graus, o valor em graus deve ser zero. A mesma observac~ao continua valida em
relac~ao a minutos e segundos. Por exemplo, 3.600 segundos = 1 grau, 0 minutos, 0
segundos; 3500 segundos = 0 graus, 58 minutos, 20 segundos.
4. Dadas duas frac~oes ordinarias a=b e c=d, determinar a sua soma e o seu produto.
5. Dado um numero inteiro que representa um numero binario de cinco dgitos, deter-
minar o seu equivalente decimal
6. Dado o primeiro termo e a raz~ao de uma prograss~ao aritmetica, determinar a soma
de seus primeiros cinco termos.

2.3 Algoritmos estruturados


Express~oes e comandos
Uma express~ao e uma combinac~ao de variaveis, constantes e operadores que, uma vez
avaliada, resulta um valor. Por exemplo,
2.3. ALGORITMOS ESTRUTURADOS 27

(b  h) :
2
Portanto, uma express~ao consiste de operandos e operadores. Os operandos s~ao ou
constante(por exemplo, numeros), ou variaveis, ou valores gerados por func~oes. Usual-
mente, os operadores se classi cam como unarios, como -, e binarios, como + e . A
linguagem C++ possui um operador ternario, ?:. Sua sintaxe , em geral, possui a seguinte
3

construc~ao: expr1 ? : expr2 : expr3. A sem^antica desse operador e a seguinte: A expr1 e


4

avaliada primeiro. Se seu valor for diferente de zero(verdadeiro), a expr2 e avaliada e seu
resultado sera o valor da express~ao condicional toda. Se expr1 for zero(falsa), a expr3
sera avaliada e seu valor sera o valor da express~ao condicional como um todo.
Se varios operadores ocorrem em uma express~ao, e preciso ser especi cada uma or-
dem de execuc~ao, ou pelo emprego explcito de par^enteses, ou por regras implcitas na
linguagem. Na maioria das linguagens, os operadores binarios se subdividem em aditivos
e multiplicativos. Aos ultimos e atribuda prioridade mais alta. Suporemos, tambem, que
os operadores de igual prioridade ser~ao sempre executados da esquerda para a direita.
Estas regras simples s~ao ilustradas nos exemplos a seguir:

x+y+z = (x + y) + z
xy+z = (x  y) + z
x+yz = x + (y  z)
x y  z w = (x (y  z)) w
x  y z  w = (x  y) (z  w)
x + y=z = ( x) + (y=z)
x  y=z = (x  y)=z
x=y  z = (x=y)  z
Quanto ao tipo de dados dos operandos, as express~oes podem ser:
 aritmeticas: quando os operandos s~ao aritmeticos(inteiros ou reais).
 logicos: quando os operandos s~ao valores verdades, falso ou verdadeiro.
 literais: quando os operandos s~ao letras ou palavras. Por exemplo, a express~ao
constituda do operador de concatenac~ao(+) e as palavras \sonha" e \dor" . \sonha"
+ \dor" resulta \sonhador". 5

3 Chamamos sintaxe a forma como comandos e express~oes na linguagem devem ser escritos a m de
que possam ser entendidos pelos tradutores de programas(interpretadores e copiladores.)
4 A sem^antica de um programa e o seu signi cado, isto e, o conjunto de ac~oes efetuadas pelo compu-
tador duranto a execuc~ao do referido programa.
5 Mais detalhes, sobre operadores, express~
oes logicas e literais, ver o livro de Viviane, captulo 2, sobre
operadores.
28 CAPITULO 2. ALGUNS ALGORITMOS SIMPLES
A forma mais elementar de comando e o comando de atribuic~ao. Ele e representado
por

V E
onde V denota uma variavel e E , uma express~ao. Este comando indica que E deve
ser calculado e, ent~ao, seu valor atribudo a V . Sempre que a express~ao E assumir um
valor o camando tem um efeito.
Ja observamos que o comando fundamental de qualquer programa e o comando de
atribuic~ao. Ou seja, o efeito do comando de atribuic~ao e uma ac~ao simples, precisamente
o de tornar o valor da variavel V igual ao valor da express~ao E . Outras dois comandos
basicos s~ao: o comando de leitura de dados, por exemplo, leia(A), no exemplo 24, e o
comando de sada de dados, por exemplo, imprima(soma), no exemplo 24.
As ac~oes compostas, que s~ao efeitos de comandos compostos, podem ser classi cadas
em tr^es tipos basicas: sequenciais, repetivas e alternativas. Os comandos correspon-
tes(sequenciais, repetitivos e condicionais) s~ao conhecidos como comandos estruturados. 6

Existes seis formas basicas desses comandos estruturados: uma forma sequencial, duas
repetitivas ou formas de laco(para e enquanto) e tr^es na forma alternativa( se ...ent~ao
...; se ...ent~ao ..., sen~ao ... e caso i de L1:S1; ...;ln:Sn ). A seguir estudaremos cada um
desses como comando, procurando ilustra-los com exemplos.

Estrutura sequencial
Na estrutura sequencial cada comando e executado somente apos o termino do comando
anterior. Ele tem a forma

In
cio

comando1;
comando2;
:
:
:
comandoN ;
fim

O separador \;" e um operador de continuac~ao. Ele ocasiona a execuc~ao do comando


subsequente, porem, somente apos terminada a execuc~ao do comando precedente. As
6 Esses comandos s~ao tambem conhecidos como controle de uxo de execuc~ao.
2.3. ALGORITMOS ESTRUTURADOS 29
palavras incio e fim est~ao representando, aqui, o comeco de um bloco de comandos,
que e uma nova unidade ou comando composto. Comandos compostos podem, as ve-
7

zes, se constituir de um grande numero de comando basicos ou elementares, assumindo


tamanho consideravel. E , por isso, aconselhavel que se destaque, visivelmente, os coman-
dos par^enteses(incio e fim), para, assim, se visualizar os agrupamentos de comandos
constituintes do comando composto.
Os exemplos 24 e 25, vistos anteriormente, s~ao exemplos de estruturas sequeciais.
Alias, qualquer programa que estudaremos, como ja observamos na primeira parte destas
notas, e uma estrutura sequencial. O que distingue os dois exemplos citados e que eles eles
somente s~ao constitudos por um uxo de controle sequencial, isto e, n~ao existe nenhum
comando na sequ^encia, que por sua vez, tenha uma estrutura repetitiva ou alternativa,
como teremos oportunida de observar em outros programas, mais adiante.

Estruturas de repetic~ao(lacos ou loops)


A estrutura de laco repete um trecho de programa um certo numeros de vezes. Essa
estrutura se subdivide em dois tipos:
1. Estrutura de la
co com vari
avel de controle e,
2. Estruturas de la
cos condicionais.

Procuraremos entender essas duas estruturas atraves de exemplos.


Repetic~ao com variavel de controle
Sintaxe:
para < var > de <incio> ate < final > repita
< comando composto >;
fim-para

Sem^antica: deveremos ter o seguinte entendimento desse trecho de programa.


 D^e um valor inicial a variavel < var >, no incio;
 d^e um valor nal a variavel < var >;
 enquanto a variavel < var > percorrer do valor inicial ate o valor nal(inclusive o
valores inicial e nal) execute o bloco < comando composto >. 8

7Existe outras formas de indicar o incio e o m de um bloco ou corpo de comandos, como veremos
mais adiante. Esses duas palavras tambem s~ao conhecidas como comandos-par^enteses.
8E claro que o comando < comando composto > pode ser constitudo de um unico comando basico.
30 CAPITULO 2. ALGUNS ALGORITMOS SIMPLES
Exemplo 9 Enunciado: Obter a soma dos n primeiros numeros pares posi-
tivos.
Analise: Os exemplos abaixo nos ajuda a entender o enunciado do problema:

n = 6 ! 2 + 4 + 6 + 8 + 10 = 42
n = 3 ! 2 + 4 + 6 = 12
n=2 !2+4=6
Obs: Todo numero par inteiro positivo pode ser escrito na forma 2i, onde
i 2 N = f1; 2; 3; :::g e a soma dos n primeiros numeros pares pode ser obitido
pela formula:

X
n
S= 2i
i=1

Para calcular essa soma basta guardar cada resultado parcial obtido e somar
este ultimo resultado acumulado ao numero par seguinte, repetindo esta ope-
rac~ao ate o ultimo numero. Portanto, podemos dizer que
 Entrada: um numero natural positivo, n;
 Sada: um numero natural positivo, o resulto da soma;
 Metodo: A cada numero natural positivo devolve um numero natural po-
sitivo.
Projeto:
As estruturas presentes neste algoritmo s~ao, ent~ao, a sequencial e a repetitiva.
Um esboco do algoritmo seria

Esbo
co do algoritmo
entrada de dados(valor de n)
repetir n vezes calcular um numero par
acumular numa soma
sada do resultado
2.3. ALGORITMOS ESTRUTURADOS 31
Podemos detalhar a estrategia:
 para cada valor de i 2 f1; 2; 3:::; ng, calculamos o numero par. t, corres-
pondente e,
 adicionamos o valor da soma S , previamente de nida com valor zero.
Ou seja, devemos repetir n vezes as duas operac~oes:
 calcular o numero par t, pela formula t = 2i e,
 somar t em S .
Vamos representar essa operac~ao de repetic~ao por

para i de 1 ate n repita < bloco >


onde bloco e uma sequ^encia de uma ou mais instruc~oes: e o laco desse coman-
do de repetic~ao. Dizemos que essa instruc~ao(operac~ao basica) e uma instruc~ao
de repetic~ao controlada por variavel.
Finalmente, o algoritmo tem a seguinte redac~ao:
Algoritmo somaDePares()
Objetivo: Dado um numero n, calcular a soma dos n primeiros numeros
pares.
Entrada: n(inteiro).
Sada: S (inteiro).
somaDePares()
leia(n);
S 0;
para i de 1 n ate repita tS 2S+i;t;
imprima(S );

A instruca~o de repetica~o, presente neste algoritmo, e controlodada pela variavel


i que e denominada variavel de controle da instruc~ao. A variavel i recebe o
valor inicial 1 e e incrementada de uma unidade ate atingir o valor nal n.
Enquanto o valor de i for maior ou igual que o valor de n, as instruc~oes
contidas no bloco s~ao executadas sucessivamente. Para cada valor atribudo
32 CAPITULO 2. ALGUNS ALGORITMOS SIMPLES
a i, se esse valor n~ao superar n, as instruc~oes do bloco s~ao executadas e,
em seguida, o valor de i e incrementado de uma unidade. As instruc~oes que
constituem o bloco fazem o \loop"(laco, malha, anel) da instruc~ao.
O numero de repetic~oes no laco esta previamente determinado pelo valor ini-
cial e pelo valor nal da variavel de controle. Nesse exemplo, o laco e execu-
tado

valor final valor inicial = n 1 + 1 = n vezes


Implementa
ca~o.

#include <iostream.h>

void main()
{
int i, n, t, S; // declara as vari
aveis.

cout << ``Entre com um valor n" << endl;

cin >> n;

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


{
t = 2*i;
S= S + t;
}

cout << S << endl;


}

Exerccios
1. Calcular o fatorial de n (n!).
2. Mesmo problema naterior, porem, agora n! = n  (n 1)  :::  2  1:
3. (i) Ache a soma de 10 numeros fornecidos pelo usuario.
(ii) Imprima os numeros pares entre 20 e 50.
2.3. ALGORITMOS ESTRUTURADOS 33
Exemplo 10 Enunciado: Imprimir os n primeiros numeros mpares positi-
vos.
An
alise

Este problema e analogo ao anterior.


 Entrada: um numero natural positivo, n;
 Sada: um numero natural positivo mpar;
 Metodo: A cada numero natural positivo de entrada devolve um numero
mpar impresso(no visor).
Projeto

Cada numero mpar pode ser escrito pela formula 2i 1, com i=1,2,3,... Para
que cada numero mpar calculado seja impresso, o laco deve conter a instruc~ao
de sada. A seguir apresentamos um esboco do algoritmo.

Esbo
co do algoritmo
entrada de dados(valor de n)
repetir n vezes calcular um numero mpar t
imprimir t

Finalmente, o algoritmo tem a seguinte redac~ao:


Algoritmo imprimeImpares
Objetivo: Dado um numero n, imprimir os n primeiros numeros mpares.
Entrada: n(inteiro).
Sada: t(inteiro).
imprime
Impares()
leia(n);
2  i 1;
para i de 1 ate n repita timprima (t);

Implementa
c~ao.
34 CAPITULO 2. ALGUNS ALGORITMOS SIMPLES
#include <iostream.h>

void main()
{
int i, n, t; // declara as vari
aveis.

cout << ``Entre com um valor n" << endl;

cin >> n;

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


{
t = 2*i-1;
cout << t << endl;
}
}

Exemplo 11 Enunciado: Imprimir os n primeiros numeros mpares em or-


dem oposta.
An
alise
Analogo o problema anterior, pois isso deixamos de apresentar.
Projeto

Geramos os numeros mpares desde o n-esimo ate o primeiro. A medida que


eles s~ao gerados, eles s~ao impressos. Utilizaremos a instruc~ao para-repita
com acressimo unitario negativo para descrever um laco em que a variavel de
controle assume valores na ordem decrescente.

n; n 1; :::; 3; 2; 1
Vamos indicar essa ordem escrevendo passo -1, antes da palavra repita:
para i de n ate 1 passo 1 repita < bloco >
A vers~ao nal do algoritmo pode escrito como segue.

Algoritmo imprimeImparesInvertidos
2.3. ALGORITMOS ESTRUTURADOS 35
Objetivo: Dado um numero n, imprimir os n primeiros numeros mpares na
ordem oposta.
Entrada: n(inteiro).
Sada: t(inteiro).
imprime
ImparesInvertidos()
leia(n);
2  i 1;
para i de n ate 1 repita timprima (t);

Implementa
c~ao.

#include <iostream.h>

void main()
{
int i, n, t; // declara as vari
aveis.

cout << ``Entre com um valor n" << endl;

cin >> n;

for(i=n; i>=1; i--)


{
t = 2*i-1;
cout << t << endl;
}
}

Exemplo 12 Enunciado: Imprimir os n primeiros termos da sequ^encia

yk = yk + 2; :::; com y = 1
+1 1

An
alise

 Entrada: um numero natural positivo, n;


 Sada: uma sequ^encia de numeros naturais;
36 CAPITULO 2. ALGUNS ALGORITMOS SIMPLES
 Metodo: A cada numero natural positivo n, de entrada, devolve uma
sequ^encia de numeros naturais.
Vejamos para n = 5. O primeiro termo e de nido pela condic~ao inicial e os
demais s~ao calculados pela relac~ao de recorr^encia dada:

y1 =1
y2 =y 1 +2=3
y3 =y 2 +2=5
y4 =y 3 +5=7
y5 =y 4 +7=9

Projeto:

Cada termo da sequ^encia e igual a soma do termo anterior com a constante 2.


O primeiro termo e dado e todos os demais s~ao calculados a partir dessa regra.
No exemplo acima, desejavamos obter os cinco primeiros termos da sequ^encia.
Por isso, calculamos quatro valores y2; y3; y4 e y5 porque o primeiro termo, y1 ,
da sequ^encia e dado e n~ao calculado.
Todos os 5 termos devem ser impressos. Portanto, assim que um elemento
for obtido ele deve ser impresso.
De uma forma geral, para imprimir os n primeiros termos, devemos imprimir
o primeiro, que e dado, e depois calcular e imprimir os n 1 termos seguintes,
conforme ilustramos no seguinte esboco do algoritmo:

Esbo
co do algoritmo
leia n
de na o primeiro elemento
imprima o primeiro elemento
para i de 1 ate n-1 repita calcule o elemento seguinte
imprima esse elemento

Observe que n~ao e necessario guardar todos os elementos da sequ^encia. Po-


demos calcular cada um deles pela relac~ao de recorr^encia dada e imprimir o
valor calculado. A mesma variavel y que armazena o primeiro termo pode
ser utilizada para todos os demais, tendo o seu valor sucessivamente alterado
atraves da instruc~ao y y + 2.
2.3. ALGORITMOS ESTRUTURADOS 37
A vers~ao nal do algoritmo e portanto:

Algoritmo numerosImpares
Objetivo: Imprimir os n primeiros termos da sequ^encia

yk = yk + 2; k = 1; 2; 3; :::; com y = 1
+1 1

Entrada: n(inteiro).
Sada: y (inteiro).
umeros
n Impares()
leia(n);
y 1; imprima(y);
para i de 1 ate n 1 repita yimprima
y + 2;
(y);

Observe que a sequ^encia de nida pela relac~ao de recorr^encia dada, de ne em


yk o k-esimo numero mpar. Desse modo, atraves dessa relac~ao de recorr^encia
podemos gerar os n primeiros numeros mpares.

Implementa
c~ao.

#include <iostream.h>

void main()
{
int i, y, n; // declara as vari
aveis.

cout << ``Entre com um valor n" << endl;

cin >> n;

y = 1;

cout << y << endl;

for(i=1; i<=n-1; i++)


{
38 CAPITULO 2. ALGUNS ALGORITMOS SIMPLES
Tipo abstrato real
Objetos: numeros racionais
Operac~oes/Notac~ao: adic~ao +
subtrac~ao -
multiplicac~ao 
divis~ao /
Relac~oes/Notac~ao menor <
maior >
diferente 6 =
menor ou igual 
maior ou igual 
Objetos constantes numerais racionais ponto xo(13.5, 45.0)
ou em ponto utuante com ou sem sinal
6.023E54, -1.23E-2
Figura 2.2: Tipo abstrato real
y=y+2;
cout << y << endl;
}
}

De nic~ao 1 Dizemos que dois algoritmos s~ao equivalentes quando para uma mesma en-
trada produzem a mesma sada.
Observe que os algoritmos 18 e 21 s~ao equivalentes, segundo essa de nic~ao.

Tipo abstrato de dados real

A implementac~ao do tipo inteiro, assim como do tipo real, em uma linguagem de


programac~ao exige a de nica~o de um domnio, isto e, um conjunto nito de inteiros ou
racionais, no caso de racionais escritos com uma quantidade nita de algarismos sig-
ni cativos. Consequentemente, durante a computac~ao pode haver estouro(over ow) e,
portanto, aproximac~ao dos valores exatos dos resultados.
Exemplo 13 Enunciado: A sequ^encia9
Um processo iterativo e de nido por uma relac~ao de recorr^encia que relaciona dois ou mais valores
9
consecutivos. Os valores calculados pela formula de recorr^encia chamam-se valores iterados. O processo
iterativo, de nido pela formula de recorr^encia do exemplo 22, e umapaplicac~ao do metodo de Newton-
Raphson para o calculo de valores aproximados das razes de f(x) = x.
2.3. ALGORITMOS ESTRUTURADOS 39

xn = 12 (x + xA ); x = 1; n 2 N
+1 0
n
converge para a raz quadrada de A, sendo A > 0. Calcule um valor aproxi-
mado da raz quadrada de A, atraves de 5 iterac~oes.
An
alise

 Entrada: um numero real positivo, A;


 Sada: um numero real positivo que represente um numero real aproxi-
mado da raz quadrada de A;
 Metodo: A cada entra da um numero real positivo A, devolve um numero
real.

Vamos ilustrar o processo para A = 2, considerando-se os racionais escritos


com ate 10 algarismos signi cativos:

x 0=1
x 1= (x + x0 )=2 = 1; 5
0
2

x 2= (x + x1 )=2 = 1; 416 666 667


1
2

x 3= (x + x2 )=2 = 1; 414 215 686


2
2

x 4= (x + x3 )=2 = 1; 414 213 562


3
2

x 5= (x + x4 )=2 = 1; 414 213 562


4
2

O valor da raz quadrada de 2, obtido atraves da quinta iterac~ao do processo


iterativo de nido pela relac~ao de recorr^encia anterior, e 1; 414 213 562:

Esbo
co do algoritmo
entrada de dados(valor de A)
de nic~ao do valor inicial de x
para i de 1 ate 5 repita calcular x
sada do resultado
Observe que somente o ultimo valor calculado deve ser impresso, por isso a
instruc~ao de sada deve ser colocada fora do laco. A variavel identi cada por
x devera assumir, sucessivamente, o valor dos cinco primeiros elementos da
sequ^encia gerada pela relac~ao de recorr^encia dada.
Portanto, o algoritmo tem o seguinte aspecto.
40 CAPITULO 2. ALGUNS ALGORITMOS SIMPLES
Algoritmo razQuadrada
Objetivo: Calcular um valor aproximado da raz quadrada de um
numero real dado.
Entrada: A(real).
Sada: x(real).
ra
zQuadrada()
leia(A);
x 1;
para i de 1 ate 5 repita x (x + Ax )=2
imprima(x)

Implementa
c~ao.

#include <iostream.h>

void main()
{
int x, A; // declara as vari
aveis.

cout << ``Entre com um valor para A " << endl;

cin >> A;

x = 1;

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


{
y= (x+A/x)/2;

}
cout << x << endl;
}

Exemplo 14 Enunciado: Usando a relac~ao a relac~ao de recorr^encia de nida


no exemplo 22, anterior, obter uma tabela de razes quadradas dos numeros
inteiros de dois 2 a 10. O valor aproximado de cada raz deve ser obtido
atraves de 5 iterac~oes.
An
alise
2.3. ALGORITMOS ESTRUTURADOS 41
 Entrada: valores inteiros de A de 2 a 10;
 Sada: uma tabela de numeros reais positivos que representam numeros
reais aproximados da razes quadradas de A, de 1 a 10;
 Metodo: A entrada dos numeros inteiros positivos A de 1 a 10, devolve
uma tabela de numeros realis.

Projeto:

Esbo
co do algoritmo

calcule a aproximac~ao x da raz quadrada de A


para i de 2 ate 10 repita sada do resultado

Algoritmo tabelaDeRazQuadrada
Objetivo: Obter uma tabela de raz quadrada dos numeros inteiros
de 2 a 10.
Entrada: Os dados de entrada s~ao gerado pelo proprio algoritmo,
sendo armazenado em A.
Sada: (inteiro), x(real).

tabelaDeRa
zQuadrada()

x 1;
para i de 2 ate 10 repita para i de 1 ate 5 repita x (x + A )=2;
2
imprima(A; x);
42 CAPITULO 2. ALGUNS ALGORITMOS SIMPLES
Exerccios
Em cada um dos exerccios proposto deve ser feita a analise do problema, o projeto do
algoritmo e a implementac~ao.
1. Considere a progress~ao geometica(PG) 1, 2, 4, 8, 16, 32,..., e um inteiro positivo n.
Pedimos que:
a) Imprima os n primeiros termos.
b) Calcule e imprima a soma dos n primeiros termos da PG sem utilizar a formula
da soma.
2. Imprimir os n primeiros termos das sequ^encias de nidas pelas relac~oes de recorr^encia:
(a) yk +1 = yk + k; k = 1; 2; 3; :::; y = 11

(b) yk +1 = yk + (2k + 1); k = 0; 1; 2; :::; y = 1 0

(c) yk+1 = yk + 3k + 3k + 1; k = 0; 1; 2; 3; :::; y = 1


2
0

(d) yk +1 = 2yk ; k = 1; 2; 3; :::; y = 1


1

3. Calcular as somas:
P P P
a) S = k b) T = k k 2k c) U = k k
20
=1
50
=5
2 100
=0

4. Partindo-se de um unico casal de coelhos lhotes recem-nascidos e supondo que um


casal de coelhos se torna fertil apos dois meses de vida e, a partir de ent~ao, produz
um novo casal a cada m^es e que os coelhos nunca morrem, a quantidade de casal de
coelhos apos n meses e dado pelo n-esimo termo da seguinte sequ^encia:

Fn = Fn + Fn ; n  2
2 1
F = 1;
0
F =11

Essa sequ^encia chama-se sequ^encia de Fibonacci.


a) Mostre como os termos dessa serie correspondem a soluc~ao do problema propos-
to.
b) Redija um algoritmo para calcular a quantidade de casais de coelhos apos n
meses.
5. Tabelar n! para n variando de 0 ate 10. Por de nic~ao k! = k(k 1)(k 2):::3:2:1
para k 2 N e 0! = 1.
2.3. ALGORITMOS ESTRUTURADOS 43
6. Dado um inteiro n tabelar n k para k variando de 1 ate n. Por de nic~ao, x k =
( ) ( )

x(x 1)(x 2):::(x k + 1); x 2 R; k 2 N e x = 1:


0

Se x = n = k; n n = n(n 1)(n 2):::(n n + 1) = n!


( )

7. Em um campeonato de futebol cada time tem uma lista o cial de 23 jogadores.


Cada time prepara uma relac~ao contendo o peso e a idade de cada um de seus
jogadores. Os 40 times que participam do torneio enviam listas para o CPD da
confederc~ao. Pede-se a seguinte informac~ao:
a) o peso medio e a idade para cada um dos times.
b) o peso e a idade media de todos os participantes.
8. Desenvolver um algoritmo para calcular a soma:

1 1=2 + 1=4 1=6 + 1=8 ::: + 1=200


44 CAPITULO 2. ALGUNS ALGORITMOS SIMPLES
Captulo 3
COMANDOS ESTRUTURADOS
Lacos condicionais-A construc~ao enquanto
Sintaxe:
enquanto < condic~ao > repita
< comando composto >
fim-enquanto

Sem^antica:
Temos o seguinte entendimento dessa unidade de programa:
 primeiro e testada a < condic~ao >, que e um valor verdadeiro ou falso;
 se < condic~ao > for verdadeira, executar o corpo < comando composto >;
 volta a testar < condic~ao >, se ela for verdadeira, executar o corpo < comando
composto >;
 volta a testar .....
 ate que < condic~ao > seja falsa, quando, ent~ao sera executada a proxima instruc~ao
apos fim-enquanto, isto e, o controle sai do laco \enquanto";
A seguir apresentaremos alguns exemplos da construc~ao \enquanto".
Exemplo 15 Enunciado: Dado um conjunto de numeros inteiros positivos,
determinar os seus quadrados.
45
46 CAPITULO 3. COMANDOS ESTRUTURADOS
An
alise

A entrada consiste de uma lista de numeros para os quais desejamos calcular


os seus quadrados. Assim, por exemplo, se os dados de entrada forem 3, 8, 4 e
10 a sada deve ser 9, 64, 16 e 100. Se a entrada for a relac~ao de numeros 12,
13, 17 pretendemos que a sada seja 144, 169, 289. Se a entrada for somente
o numero 11, desejamos obter a sada 121. Logo, para cada numero A dado,
basta calcular o seu quadrado por meio de t = A  A e imprimir o resultado.
Portanto,
 Entrada: Um lista de numeros inteiros positivos.
 Sada: uma listas de inteiros positivos.
 Metodo: Recebe como entrada uma lista de inteiros positivos e devolve
uma lista de numeros inteiro positivos.

Projeto:

O problema e dividido nos seguintes subproblemas.


repetir para cada elemento da lista
- leia um numero inteiro positivo A;
- calcule A  A;
- imprima o resultado.
As estruturas presentes neste algoritmo s~ao, ent~ao, a sequencial e a repetitiva.
Um esboco do algoritmo seria

Esbo
co do algoritmo
Ler um numero A
repetir para cada elemento da lista Calcular A  A
imprimir o resultado

O problema no projeto desse algoritmo e saber quantas vezes executar a repe-


tic~ao. Isto se da porque:
47
 A lista de dados de entrada e constituda por um numero desconhecido de
elementos, isto e, n~ao faz parte da entrada a informac~ao sobre quantos
numeros existem na lista.
 O que queremos e repetir o bloco(leitura, calculo, sada), enquanto existir
um numero na lista de entrada dos dados.1
Para resolver esse problema introduzimos o conceito de

Sentinela
A estrategia para veri car o m dos dados e utilizar um \sinal" de m de
dados, o qual denominaremos sentinela. Portanto, acrescentaremos no nal
da lista de numeros dados um valor que, reconhecidamente, n~ao pertenca a
lista de valores possveis dos dados de entrada.
No nosso exemplo, os dados s~ao numeros inteiros positivos, isto e, a lista de
valores permitidos para a entrada e

1; 2; 3; 4; :::
Logo, podemos usar como sentinela qualquer numero que n~ao seja positivo.
Por exemplo, o numero zero ou o numero -1.
Desse modo, a entrada do algoritmo passa a ser a lista de numeros acrescida
do valor sentinela.
Com essa estrategia, podemos apresentar o seguinte esboco do algoritmo.

Esbo
co do algoritmo
Ler o primeiro numeros da lista
Calcular o quadrado
enquanto o numero for positivo repetir imprimir
ler o proximo numero

Observe que o numero de vezes em que laco sera repetido depende do teste
de uma condic~ao. Por isso dizemos que a repetic~ao e controlada por uma
condic~ao.
1Observe que a exist^encia e mais facil de ser veri cada que o contrario. Como seria possvel veri car
que n~ao existe nenhum numero inteiro positivo na entrada de dados?
48 CAPITULO 3. COMANDOS ESTRUTURADOS
Na nossa linguagem algortmica representaremos essa estrutura de repetic~ao
atraves de uma das duas instruc~oes: enquanto-faca ou repita-ate-que.
As duas instruco~es s~ao equivalentes no sentido de que representam a repetic~ao
controlada por condic~ao. Uma condic~ao e o que chamamos uma

Express~ao booleana
Em nosso problema a condic~ao e expressa por A > 0.
Uma condic~ao e expressa utilizando-se os operadores de relac~ao:

<; >; =; ;  e 6=
A express~ao que obteremos relacionando entre si variaveis e/ou constantes
por meio de operadores de relac~ao denominamos express~ao booleana. Uma
express~ao booleano assume somente um de dois valores mutuamente exclusivos:
verdadeiro(true) ou falso(false).
A instruc~ao enquanto-faca tem o seguinte formato

enquanto < condic~ao > faca < bloco >


Nesta instruc~ao, < bloco > somente sera executado se < condic~ao > for
verdadeira. < bloco > representara uma ou mais instruc~oes e constitui o laco.
Antes de ser executado pela primeira vez e necessario que a condic~ao esteja
de nida. Se a primeira vez em que a < condic~ao > for testada ela for falsa,
o laco n~ao sera executado nenhuma vez. Dentro do laco deve existir uma
instruc~ao que altere o valor da < condic~ao >, caso contrario o laco pode se
tornar de execuca~o in nita(n~ao parar).
Em nosso problema a < condic~ao > para que as operac~oes de calculo e im-
press~ao sejam executadas e que o numero dado seja positivo. Cada numero da
entrada, inclusive a sentinela, sera lida em uma mesma variavel. Chamemos
de A essa variavel. Podemos, nalmente, apresentar o projeto do algoritmo
como a seguir:

Algoritmo quadrados
Objetivo: Calcular os quadrados de uma lista de inteiros positivos,
terminada com 0.
49
Entrada: A(inteiro).
Sada: A; t(inteiro).
quadrados()
leia(A);
enquanto A > 0 faca tleia(AA); A; imprima(A; t);

Observe que o algoritmo quadrados \funcionara" mesmo que seja colocado


outro valor como sentinela, desde que n~ao seja um numero positivo.

Implementa
c~ao.

#include <iostream.h>

void main()
{
int A, t; // declara as vari
aveis.

cout << ``Entre com um lista de n


umeros inteiros positivos,

<< quando quiser terminar entre 0" << endl;

cin >> A;

while( A > 0 )
{
t = A*A;
cout << A << t;
cin >> A;
}
}

Apresentaremos, tambem, o projeto desse algoritmo, assim como sua imple-


mentac~ao, para o caso da instruc~ao ser repita-ate-que.
Essa outra instruc~ao de repetic~ao em que a repetic~ao e controlado por instruc~ao
e
50 CAPITULO 3. COMANDOS ESTRUTURADOS

repita < bloco > ate que < condic~ao >


Nesta instruc~ao < bloco > sera executado pelo menos uma vez porque somente
apos a sua execuc~ao a < condic~ao > e testada. Dentre as instruc~oes de laco
deve existir pelo menos uma que altere o valor de < condic~ao >. Utilizando
essa instruca~o na resoluc~ao do problema, obteremos o seguinte algoritmo.

quadrados1()
leia(A);
repita
t AA
imprima(A; t)
leia(A)
ate que A  0

Observe que a primeira estrutura de repetic~ao (enquanto-faca) e mais conve-


niente para resolver o problema proposto. Se a sequ^encia de entrada for vazia
e o primeiro valor lido for o valor sentinela, ocorrera indevidamente impress~ao
na tabela e a execuca~o cara interrompida por falta de dados na execuc~ao de
quadrados1().
Do ponto de vista de formato, o laco de repita-ate-que n~ao precisa do dese-
nho de bloco mesmo quando for constitudo por uma sequ^encia de instruc~oes,
segundo a descric~ao acima. Isso porque as proprias palavras-chave repita e
at e que servem de delimitadores de bloco.
Para um mesmo problema as condic~oes de controle dos comandos enaquanto-
faca e repita-ate-que s~ao complementares. Observe que a negac~ao de A > 0 e
A  0 e vice-versa.

Implementa
c~ao de quadrados1().

#include <iostream.h>

void main()
{
int A, t; // declara as vari
aveis.

cout << ``Entre com um lista de n


umeros inteiros positivos,
51

<< quando quiser terminar entre 0" << endl;

cin >> A;

do
{
t = A*A;
cout << A << t;
cin >> A;
} while(A>0);
}

Exemplo 16 Enunciado: Suponha que no ano N a populac~ao americana seja


maior que a brasileira. Sabendo-se que os Estados Unidos possuem um cres-
cimento anual de 2% na sua populac~ao e que o Brasil tem um crescimento
anual de 4%, determinar o ano em que as duas populac~oes ser~ao iguais(em
quantidade). S~ao dados os numeros de habitantes dos Estados Unidos e do
Brasil no ano N .
An
alise

A entrada consiste de tr^es numeros: ano, populac~ao brasileira e populac~ao


americana. Portanto, a sada deve ser um numero que corresponde ao ano
em que as duas populaco~es se igualam. Assim,
 Entrada: Um lista de tr^es numeros inteiros positivos.
 Sada: um numero inteiro.
 Metodo: Recebe como entrada tr^es numeros positivos e devolve um numero
inteiro positivo.

Projeto:

Devemos corrigir os valores das duas populac~oes para cada ano, a partir de
um ano dado, ate que o valor corrigido da populac~ao brasileira seja igual ou
maior que o valor corrigido da populac~ao americana. Portanto, o problema
deve ser subdividido nos seguintes subproblemas:
- corrigir a populaca~o brasileira (aumento 4%);
- corrigir a populaca~o americana (aumento 2%);
52 CAPITULO 3. COMANDOS ESTRUTURADOS
- passar para o ano seguinte.
Repetir isto ate que as duas populac~oes estejam iguais. Logo, a condic~ao que
controla a repetic~ao e a comparac~ao entre as duas populac~oes.2
Podemos, agora, apresentar o seguinte esboco para o algoritmo.

Esbo
co do algoritmo
leitura dos dados
corrigir popBras
repetir corrigir popUsa
incrementar ano
ate que popBras  popUsa
sada do resultado

A correc~ao do valor da populac~ao e feita somando-se ao valor existente o valor


do acressimo, que e igual a taxa populac~ao:
Brasil: popBras + 0,04  popBras
Usa : popUsa + 0,02  popUsa
Podemos, agora, apresentar o algoritmo na sua vers~ao nal.

Algoritmo popIguais
Objetivo: Determinar o ano em que a populac~ao brasileira
supera ou iguala a americana.
Entrada: N (inteiro, Br; Usa(real).
Sada: N (inteiro).
popIguais1()
leia(N,Br,Usa);
repita
Br Br + 0:04  Br;
Usa Usa + 0:02  Usa;
N N + 1;
ate que Br  Usa;
imprima(\Ano",N)
Vamos usar a instruc~ao repita-ate-que porque as duas populac~oes, primeiro, sofre um acressimo de 4%
2
e 2%, respectivamente, e somente, ent~ao, o teste da condic~ao sera executado. Esta instruc~ao e a indicada
porque sabemos, inicialmente, que a populac~ao americana e maior que a brasileira. Caso contrario, se
esses valores fossem desconhecidos, a instruc~ao enquanto-faca seria mais adequada, pois primeiro o teste
da condic~ao seria efetuado e conforme seu resultado o bloco seria executado ou n~ao.
53
Se usarmos a instruca~o enquanto-faca, a condic~ao que controla o laco sera a
negaca~o da condica~o usada na instruc~ao epita-ate-que.

popIguais2()
leia(N; Br; Usa);
Br 0:04  Br;
enquanto Br < Usa faca Usa 0:02  Usa;
N N + 1;
imprima(\Ano"; N );

Na instruca~o de sada acrescentamos uma mensagem que esclarece o signi -


cado do valor de N . As mensagens que devem ser escritas s~ao colocadas sob
aspas. A mensagem e o valor de N ser~ao impressos.3

Implementa
c~ao.

#include <iostream.h>

void main()
{
int N;

float Br, Usa;

cout << "Entre com o ano, a popula


cao brasileira e a americana" << endl;

cin >> N >> Br >> Usa;

while (Br < Usa )


{
Br <-- Br + 0.04 * Br;
Usa<-- Usa + 0.02 * Usa;
N <-- N + 1;
}
cout << "O ano e" << N;
}
3 Observe que o valor de N informa o ano em que ocorrera o empate, porem ate o nal do ano N a
populac~ao brasileira podera ter superada a populac~ao americana. Durante o ano N a populac~ao brasileira
sofre um aumento de 4%, enquanto a americana de, apenas, 2%. Logo, chegara um momento, nesse ano,
em que as populac~oes(brasileira e americana) se igualam.
54 CAPITULO 3. COMANDOS ESTRUTURADOS
Exemplo 17 Enunciado: Determinar o maximo divisor comum entre dois
numeros inteiros positivos.
An
alise

Para determinar o mdc usaremos o algoritmo das divis~oes sucessivas(algoritmo


de Euclides) que ilustraremos abaixo.

6 3 3
126 20 6 2 = mdc(126,20)
6 2 0

Na linha superior do dispositivo pratico registramos os quocientes obtidos, na


linha do meio os numeros que s~ao divididos(dividendo e divisor) e na linha
inferior, os restos das divis~oes:

quociente 6 3 3
dividendo/divisor 126 20 6 2
resto 6 2 0

Podemos a rmar que


 Entrada: Dois numeros inteiros positivos.
 Sada: um inteiro positivo.
 Metodo: Para cada par de numeros inteiros positivos de entrada
devolve seu mdc.

Projeto:

Na primeira divis~ao um dos dividendos e um dos numeros dados e o divisor


e o outro. Nas divis~oes sucessivas o dividendo e substitudo pelo divisor e o
divisor pelo resto. A ultima divis~ao ocorre quando o respectivo resto for zero.
O valor de mdc e o valor do ultimo divisor:
55
dividendo divisor quociente resto
126 20 6 6
20 6 3 2
6 2 3 0

Portanto, o problema e dividido nos seguintes subproblemas.


- calcular o resto
- de nir proximo dividendo
- de nir proximo divisor
Resolver o problema consiste em repetir esses tr^es subproblemas(nesta ordem)
ate que o resto seja zero.
O novo valor de dividendo e o divisor anterior e o novo do divisor e o resto
anterior. Portanto, quando o resto for igual a zero, o novo valor do dividendo
e o valor do ultimo divisor da sequ^encia de divis~oes, isto e, e o valor do mdc.
Podemos apresentar o seginte esboco do algoritmo

esbo
co do algoritmo
leitura dos dados
de nic~ao dos valores iniciais de dividendo e divisor
calcula o resto
repita as operac~oes substitui o dividendo pelo divisor
substitui o divisor pelo resto
ate que resto = 0
o valor do mdc e o valor do ultimo dividendo
impress~ao do mdc

Tendo em vista que a operac~ao mod fornece o resto da divis~ao entre dois
numeros inteiros, podemos nalmente apresenta o algoritmo que calcula o mdc
de dois numeros inteiros positivos.

Algoritmo mdc
Objetivo: Calcular o maximo divisor comum entre dois numeros intei-
ros positivos.
Entrada: M; N (inteiros).
56 CAPITULO 3. COMANDOS ESTRUTURADOS
Sada: mdc(inteiro).
mdc()
leia(M,N);
dividendo M ; divisor N ;
repita
resto dividendo mod divisor;
dividendo divisor;
divisor resto;
ate que resto = 0
imprima(mdc)

Observe que o algoritmo funciona mesmo que M < N . Por exemplo, se


M = 20 e N = 126, o resultado de mdc(20,126) e 2.

Implementa
c~ao.

#include <iostream.h>

void main()
{
int M, N;

cout << "Entre dois inteiros positivos" << endl;

cin >> N >> M;

dividendo <-- M;
divisor <-- N;

while (resto /= 0 )
{
resto <-- dividendo mod divisor;
dividendo <-- divisor;
divisor <-- resto;
}
mdc <-- dividendo
cout << mdc << endl;;
}
57
Exerccios
Em cada um dos exerccios abaixo, fazer a analise do problema, o projeto e implementac~ao
do algoritmo.
1. Dados os lados de quadrados, determinar suas areas. Parar quando for informado
de que lado=0.
2. Determinar o numero de alunos de uma turma qualquer.
3. Fazer um programa para validar notas, que v~ao de 0 ate 10, de alunos de uma
instituica~o de ensino.
4. O departamento de markting de uma editora esta com o problema de calcular o
ponto de equilbrio para qualquer livro que se prop~oe a publicar. Isto e, deve
estabelecer o valor do preco de venda que cobre os custos de produc~ao. Os custos
de produca~o consistem em um custo xo mais um custo de copia que depende do
numero de copias produzidas e do numero de paginas do livro.

custo de produca~o = custo xo + (num de copias)  (num de pags.)  0; 031


Para cada livro que se pretenda publicar e feita uma pesquisa de campo para se
determinar o numero provavel de vendas. Esse numero e utilizado como o numero
de copias.
Em seguida e organizado uma lista dos livros que se pretende publicar contendo as
seguintes informaco~es: numero de identi cac~ao do livro, previs~ao de vendas, custo
xo e numero de paginas.
Desenvolva um programa que, a partir dos dados dessa lista, emita um relatorio
contendo o numero de identi cac~ao do livro, as vendas previstas e o preco de venda
do livro que cobre os custos de produc~ao. Para a leitura da lista e preciso utilizar
uma sentinela.
5. Dados dois numeros inteiros positivos determinar quantas vezes o primeiro divide
exatamente o segundo. Se o primeiro n~ao divide o segundo o numero de vezes e
zero.
6. Dados dois numeros inteiros positivos determinar o valor da maior pot^encia do
primeiro que divide o segundo. Se o primeiro n~ao divide o segundo, a maior pot^encia
e de nida como sendo igual a 1.
7. Dados dois numeros reais positivos determinar o quociente inteiro do primeiro pelo
segundo usando, apenas, os operadores aritmeticos reais.
58 CAPITULO 3. COMANDOS ESTRUTURADOS
8. Dado um numero real positivo determinar sua parte inteira e sua parte fracinaria
usando, apenas os operadores aritmeticos reais.
9. Dado um numero binario inteiro positivo determinar a sua convers~ao para decimal.

3.1 Estruturas de decis~ao de selec~ao ou de alternati-


vas
Nas estruturas de dicis~ao(de selec~ao ou alternativa) o uxo de intruc~oes a ser seguido e
escolhido em funca~o do resultado da avaliac~ao de uma mais condic~oes(express~ao booleana
ou logica). Podemos classi car as estruturas de decis~ao, quando ao numero de condic~oes
em
 uma condic~ao(condic~ao simples) - se;
 varias condico~es(condic~oes multiplas) - escolha(caso).
Estruturas de decis~ao do tipo \se"
Sintaxe:
se <condic~ao> ent~ao
<comando-composto1>
sen~
ao
<comando-composto2>
m-se
Sem^antica:
Devemos ter o seguinte entendimento deste tipo de comando de decis~ao:
1. Testar a condic~ao <condic~ao>, se ela for verdadeira
2. executar o comando <comando-composto1>, caso contrario, isto e, se <condic~ao>
for falsa,
3. executar <comando-composto2>.
Exemplo 18 Enunciado: Dados dois numeros A e B distintos, determinar
maior.
An
alise

Podemos de incio identi car a seguinte estrutura sequencial do algoritmo:


~ DE SELECAO
3.1. ESTRUTURAS DE DECISAO ~ OU DE ALTERNATIVAS 59
leitura dos dados(A,B)
determinar o maior
sada do resultado(maior)
Portanto,
 Entrada: Dois numeros inteiros A; B .
 Sada: Um numero inteiro, o maior dos dois.
 Metodo: Recebe como entrada dois numeros inteiros e devolve como sada
o maior dos dois.

Projeto

Para determinar o maior dos dois numeros A e B , e preciso comparar A com


B e, em func~ao do resultado dessa comparac~ao, o maior sera de nido como o
valor de A ou o valor de B :
leia(A,B)
compare A com B , de nindo o maior
imprima(maior)
Para efetuar a comparaca~o, podemos testar a condic~ao A > B . Se for verda-
deira, o maior deve receber valor de A, caso contrario, o maior deve receber
o valor de B . Isto signi ca que existem duas alternativas apos o teste e que
somente uma das duas sera executada:
A > B ? sim ! o maior e A
n~ao ! o maior e B
Da descric~ao do algoritmo essa instruc~ao e descrita por:

se A > B ent~ao
maior A
sen~ao
maior B
Essa instruc~ao e denominada instruc~ao de selec~ao de dois ramos porque a sua
execuc~ao, efetivamente, seleciona uma das duas alternativas: ou o ramo ent~ao
ou o ramo sen~ao, conforme o valor da condic~ao seja verdadeiro ou falso.
Algoritmo maior
60 CAPITULO 3. COMANDOS ESTRUTURADOS
Objetivo: Determinar o maior de dois numeros distintos.
Entrada: A; B (real).
Sada: Uma max(inteiro.
maior1()
leia(A,B);
se (A>B ) ent~ao
max A;
sen~ao
max B;
imprima(max);

Vejamos que modi cac~ao deve sofrer o algoritmo maior1() se os numeros A e


B n~ao forem necessariamente distintos. Antes vamos estabelecer que no caso
de igualdade desejamos que que a sada seja uma mensagem, por exemplo,
\Valores iguais".
Com esta modi cac~ao a condic~ao a ser testada inicialmente e a igualdade dos
dois numeros dados. Conforme o valor dessa condic~ao devemos imprimir uma
mensagem ou ent~ao determinar o maior e imprim-lo.

esbo
co do algoritmo
leitura dos dados
se A = B ent~ao
imprimir mensagem
sen~ao determinar o maior
imprimir o maior

O ramo sen~ao(<bloco2>) dessa instruc~ao nada mais e que o algoritmo ante-


rior, sem a instruca~o de leitura. Portanto, temos o seguinte algoritmo:
~ DE SELECAO
3.1. ESTRUTURAS DE DECISAO ~ OU DE ALTERNATIVAS 61
maior2()
leia(A,B);
se A = B ent~ao
imprimir(\Valores iguais');
se A > B ent~ao
maior A;
sen~ao sen~ao
maior B ;
imprimir(\maior=",maior);

Implementa
c~ao: maior1()

#include <iostream.h>

void main()
{
float max, A, B;

cout << "Digite dois n


umeros reais " << endl;

cin >> A >> B;

if (A > B )
max = A;
else
max = B;
cout << `` Maior = " << max << endl;
}

Implementa
c~ao: maior2()

#include <iostream.h>

void main()
{
float maior, A, B;

cout << "Digite dois n


umeros reais " << endl;
62 CAPITULO 3. COMANDOS ESTRUTURADOS

cin >> A >> B;

if (A = B )
cout << ``Valores iguais" << endl;
else
{
if (A > B )
maior = A;
else
maior = B;
cout << ``Maior" << maior << endl;
}
}

Exemplo 19 Enunciado: Determinar se uma pessoa e maior ou menor de


idade.
An
alise

A entrada consiste de um numero que e a idade alguem, enquanto a sada deve


ser uma a cadeia constante \Maior de idade" ou \Menor de idade".
 Entrada: Um numero inteiro positivo.
 Sada: Uma cadeia constante.
 Metodo: Tem como entrada um inteiro positivo e devolve uma cadeia
constante, \Maior de idade" ou \Menor de idade"

Projeto:

Este problema e t~ao simples que escreveremos o algoritmo sem passar pela fase
de esboco.
Algoritmo maiorIdade
Objetivo: Veri car se alguem e de maior idade, isto e,
tem idade maior ou igual a 18 anos.
Entrada: N (inteiro).
Sada: Uma cadeia constante.
~ DE SELECAO
3.1. ESTRUTURAS DE DECISAO ~ OU DE ALTERNATIVAS 63
maiorIdade()
leia(idade);
se (idade18 )
imprima(\ Maior de idade");
sen~ao
imprima(\Menor de idade");

Implementa
c~ao.

#include <iostream.h>

void main()
{
int idade;

cout << "Digite a idade" << endl;

cin >> idade;

if (idade >= 18 )
cout << "Maior de idade" << endl;
else
cout << "Menor de idade" << endl;
}

Exemplo 20 Enunciado: Numa pequena empresa, cada funcionario recebe


mensalmente o ordenado mais um pr^emio referente a comiss~oes. S~ao dados os
seguintes valores: salario bruto e pr^emio, alem dos valores de base do INPS,
base do imposto de renda e respectivas taxas(INPS E IR). Deseja-se emitir
o demonstrativo do pagamento(contracheque) de um funcionario, contendo os
valores do salario bruto, pr^emio, rendimento, desconto de IR e salario lquido.
Esclarecimento: O rendimento do funcionario e a soma do salario bruto com
o pr^emio; o desconto do INPS somente incide se o rendimento for maior do
que a base do INPS e o desconto do imposto de renda, somente se a diferenca
entre os valores do rendimento e o valor do desconto do INPS for maior do
que a base do Imposto de Renda.
An
alise
64 CAPITULO 3. COMANDOS ESTRUTURADOS
Vamos examinar um exemplo para con rmar nossa compreens~ao do problema.
Suponha que a entrada de valores numericos sejam as seguintes:
Salario bruto = 2000
pr^emio = 1000
base INPS = 1500
base IR = 2800
taxa IR = 15%
Inicialmente calculamos o rendimento atraves de:

rendimento = salario bruto + pr^emio,

Obtendo rendimento = 2000 + 1000 = 3000

Logo a seguir veri caremos se incide a taxa INPS sobre esse rendimento:

base INPS = 1500 ! rendimento > base INPS
rendimento = 3000
Como rendimento>base do INPS devemos calcular o desconto do INPS, que
e igual a 10% do rendimento:

desconto INPS = 0; 10  3000 = 300


Em seguida para veri car se existe rentenc~ao de IR na fonte, subtraimos o
desconto do INPS do valor do rendimento e comparamos essa diferenca com
o valor base IR: 
3000 300 = 2700 ! diferenca < base IR
base IR = 2800
Como diferenca e menor do que a base IR, n~ao existe desconto de IR, isto e,
o desconto de IR e nulo. Finalmente temos:

salario lquido = rendimento desconto INPS desconto IR

salario lquido = 3000 300 0 = 2700


Os valores de sada s~ao:
~ DE SELECAO
3.1. ESTRUTURAS DE DECISAO ~ OU DE ALTERNATIVAS 65
salario bruto = 2000
pr^emio = 1000
rendimento = 3000
INPS = 300
IR = 0
salario lquido = 2700
Portanto,
 Entrada: Seis numeros reais, que s~ao sBruto, pr^emio, baseINPS, ba-
seIR, taxaINPS, taxaIR.
 Sada: Seis numeros reais, que s~ao Sbruto, pr^emio,
R(salario total), INPS, IR, sLquido
 Metodo: Tem como entrada esses seis reais e devolve como seis numeros
reais.

Projeto:

Analisando o processo executado observamos que o desconto do INPS so ocorre


se o rendimento for maior que a base do INPS. Do mesmo modo, o desconto
do IR so e calculado se a diferenca(rendimento-desconto INPS) for maior que
a base IR.
Isto signi ca que o calculo dos descontos depende do valor da condic~ao, mas
n~ao existem duas alternativas: se a condic~ao for verdadeira o calculo deve ser
efetuado, mas se acondic~ao for falsa nenhum calculo deve e ser executado:

rendimento > base INPS? sim : calculo do desconto
n~ao :nada a fazer
Na descric~ao do algoritmo essa instruc~ao e descrita por:
se <condic~ao> ent~ao
<bloco>
Essa intruc~ao e denominada instruc~ao de selec~ao de um ramo porque a exe-
cuc~ao faz com que apenas uma unica alternativa seja executada ou n~ao. Apos
o teste do valor da condic~ao, o bloco somente e executado se o valor do teste
for verdadeiro.
Observe que os dois testes devem ser feitos em sequ^encia, isto e, apos ve-
ri car a condica~o \rendimento > base INPS" deve ser veri cada a condic~ao
66 CAPITULO 3. COMANDOS ESTRUTURADOS
\(rendimento-desconto INPS)> base IR"independemente do resultado do teste
anterior:
O algoritmo, portanto, apresenta a seguinte estrutura logica:

esbo
co do algoritmo
entrada de dados
calcular rendimento
calcular desconto de INPS, se incidir
calcular desconto IR, se incidir
calcular salario lquido
sada do resultado
Para identi car os valores de entrada usaremos as variaveis: sBruto, pr^emio,
baseINPS, baseIR, taxaINPS, e para os valores de sada as variaveis: R,
sLquido, INPS e IR. O re namento do esboco anterior e o seguinte:

refinamento do esbo
co
leitura dos dados
R sBruto + pr^emio
se(R >INPS) ent~ao INPS taxaINPSR
se(R>baseINPS) ent~ao IR taxaIr(R-INPS)
sLquido R-INPS-R
sada do resultado
Observe que na penultima instruc~ao em que e calculado o sLquido, a exe-
cuc~ao so podera ser feita se as parcelas do INPS e IR estiverem com valores
de nidos. Se as condic~oes que de nem INPS e IR forem falsas nenhum valor
sera atribudo a essas variaveis. Portanto, antes de testar as condic~oes deve-
mos atribuir para essas variaveis valores iniciais iguais a zero. Esses valores
somente ser~ao modi cados se as condic~oes que os de nem forem verdadeiras.
Finalmente, podemos escrever o algoritmo,

Algoritmo contraCheque
Objetivo: Calcular o rendimento, os decontos de INPS, de IR e
imprimir o respectivo demonstrativo, de funcinario
que recebe salario e pr^emio.
Entrada: sBruto, pr^emio, baseINPS, baseIR, taxaINPS, taxaIR(reaL).
~ DE SELECAO
3.1. ESTRUTURAS DE DECISAO ~ OU DE ALTERNATIVAS 67
Sada: sBruto, pr^emio, R, INPS, IR, sLquido(real)
contraCheque()
leia(sBruto,pr^emio);
leia(baseINPS,baseIR,taxaINPS,taxaIR);
INPS 0; IR 0;
R sBruto+pr^emio;
se R>baseINPS ent~ao
INPS taxaINPS  R;
se R-INPS>baseIR ent~ao
IR taxaIR  (R INPS );
sLquido R-INPS-IR;
imprima(sBruto,pr^emio,R,INPS,IR,sLquido);

Implementa
c~ao.

#include <iostream.h>

void main()
{
float sBruto, pr^
emio;
float baseINPS, baseIR, taxaINPS, taxaIR, R, sL
quido;

cout << "Digite sal


ario bruto e pr^
emio" << endl;

cin >> sBruto >> pr^


emio;

INPS = 0;
IR = 0;

if (R>baseINPS)
INPS = taxaIR*R;

if (R-INPS>baseIR)
IR = taxaIR*(R-INPS);

sL
quido = R - INPS - IR;

cout << sBruto << pr^


emio << R
<< INPS << IR << sLquido << endl;
68 CAPITULO 3. COMANDOS ESTRUTURADOS
}

Tipos de dados booleano e caracteres


A seguir apresentarem os tipos booleanos e caracteres necessarios para os problemas a
seguir.

Tipos de dados booleano(l


ogico)
Elementos : os valores logicos verdadeiro(true) e falso(false)
Operac~oes/Notaca~o : negac~ao n~ao
: onjunc~ao e
: disjunc~ao ou
Relac~oes/Notac~ao : igualdade =
: desgualdade 6 =
Constantes : T e F, representando os valores true e false, resp.
De nic~ao das operac~oes logicas pela tabela verdade
n~ao e F T ou F T
F T F F F F F T
T F T F T T T T

Tipos de dados caractere


Elementos : os caracteres alfanumericos
(letras latinas maiusculas, letras latinas minusculas, algarismos
decimais arabicos, sinais de pontuac~ao e smbolos especiais)
Operac~oes/Notac~ao : n~ao ha
Relac~oes/Notac~ao : igualdade =
: desigualdade = 6
Constantes : caractere alfanumericos sob aspas simples, por exemplo `A',
`2', `.', `<'

A implementac~ao do tipo caractere numa liguagem de programac~ao representara os


caracteres em sistema de codi cac~ao. O mais comum, principalmente, para os microcom-
putadores e o sistema ASCII(American Standard code for Interchase Information). Nesse
sistema e introduzido uma relac~ao de ordem(<; ; > e ) entre os caracteres por meio
da ordem associada a cada um dos 256 caracteres codi cados. Essa relac~ao de ordem
preserva a ordem alfabetica e estabelece que os algarismos precedem as letras maiusculas
e estas, as minusculas.
~ DE SELECAO
3.1. ESTRUTURAS DE DECISAO ~ OU DE ALTERNATIVAS 69
Exemplo 21 Enunciado: E dado o gabarito de uma prova que consta de tr^es
quest~oes, cujas respostas podem ser qualquer uma de tr^es alternativas `A', `B'
ou `C'. S~ao dadas tambem as respostas para as tr^es quest~oes fornecidadas por
um estudante que se submeteu a prova.
Desenvolver um algoritmo para imprimir o gabarito e a mensagem \elimina-
do", caso estudante tenha errado todas as quest~oes, ou o gabarito e o numero
das quest~oes certas, caso o estudante tenha acertado alguma quest~ao.
An
alise

Os dados consistem de tr^es letras que constituem o gabarito das tr^es quest~oes,
e tr^es que formam a resposta do estudante.
Exemplo de entrada e sadas:
entrada: (gabarito)B A C
(resposta)B A A
sada: gabarito: B A C
quest~ao 1, quest~ao 2
entrada: (gabarito)B B B
(resposta)A B B
sada: gabarito: B B B
quest~ao 2, quest~ao 3
Observe que o gabarito sera impresso independentemente de acertos ou erros,
isto e, imediatamente apos a entrada dos dados. Em seguida existem somen-
te duas possibilidades: ou a sada consiste da mensagem \eliminado" ou ou
consiste nos numeros das quest~oes certas. O que condiciona uma das duas
alternativas e o valor da condic~ao \errou as quest~oes":

errou as 3 quest~oes? sim ! eliminado
n~ao ! veri que quais as certas
Temos, ent~ao a seguinte estrutura logica:

esbo
co do algoritmo
entrada de dados
imprimir gabarito
se errou as 3 quest~oes ent~ao
imprimir mensagem \ELIMINADO"
sen~ao
veri car quais as certas e imprimir os respectivos numeros
70 CAPITULO 3. COMANDOS ESTRUTURADOS
Para veri car quais as certas e imprimir os respectivos numeros, basta com-
parar o gabarito com a resposta quest~ao por quest~ao, imprimindo o numero da
quest~oes somente se o valor do gabarito for igual ao valor da resposta. Apos
veri car a quest~ao 1, devemos veri car a quest~ao 2(n~ao importa se houve acer-
to ou erro no teste da quest~ao 1)e em seguida, a quest~ao 3(idependentemente
do resultado das quest~oes 1 e 2).
Portanto, a estrutura logica desse bloco e uma sequ^encia de tr^es instruc~oes de
selec~ao de um ramos, ou seja:

refinamento do ebo
co
entrada de dados
imprimir gabarito
se errou as 3 quest~oes ent~ao
imprimir mensagem \ELIMINADO"
sen~ao
imprimir \ACERTOU"
se acertou a quest~ao 1 ent~ao
imprimir \quest~ao 1"
se acertou quest~ao 2 ent~ao
imprimir \quest~ao 2"
se acertou quest~ao 3 ent~ao
imprimir \quest~ao 3"

Sejam G1, G2 e G3 as variaveis que representam o gabarito e R1, R2 e R3


as variaveis que representam as respostas do estudante. Essas variaves s~ao do
tipo caractere.
A condica~o \errou as tr^es quest~oes" representa tr^es testes:
R16=G1 e R26=G2 e R36=G3
Finamente, podemos apresentar o algoritmo

Algoritmo exameFinal
Objetivo: Dados os gabaritos de tr^es quest~oes e as resposta de um estudante
imprimir o gabarito e
a mensagem \ELIMINADO" ou a mensagem \ACERTOU" e os numeros
~ DE SELECAO
3.1. ESTRUTURAS DE DECISAO ~ OU DE ALTERNATIVAS 71
da quest~oes certas, conforme o estudante tenha errado todas
quest~oes ou n~ao.
Entrada: G1, G2, G2, R1, R2, R3(caractere).
Sada: G1, G2, G3(caractere), mensagem(cadeia de caractere).
exameFinal()
leia(G1,G2,G3,R1,R2,R3);
imprimir(\gabarito: ", G1,G2,G3);
se(R1neqG1) e (R2= 6 G2) e (R36=G3) ent~ao
imprima(\Eliminado");
sen~ao
imprima(\Acertou: ");
se R1=G1 ent~ao
imprima(\quest~ao 1");
se R2=G2 ent~ao
imprima(\quest~ao 2");
se R3=G3 ent~ao
imprim(\quest~ao 3");

A condic~ao utilizada na instruc~ao de selec~ao de dois ramos e uma condic~ao


composta porque e formada por condic~oes simples(escritas com operadores re-
lacionais) que s~ao conectados pelo operador logico \e".
Implementa
c~ao.

#include <iostream.h>

void main()
{
char G1,G2,G3,R1,R2,R3;

cout << "Digite os gabaritos G1, G2, G3: " << endl;

cout << "Digite as respostas R1, R2, R2: " << endl;

cin >> G1 >> G2 >> G3;

cin >> R1 >> R2 >> R3;


72 CAPITULO 3. COMANDOS ESTRUTURADOS

cout << G1 << G2 << G3 << \endl;

if (R1 /= G1 && R2 /= G2 && R3 /= G3)


cout << "Eliminado" << endl;
else
cout << "Acertou" << endl;
if(R1=G1)
cout << "quest~
ao 1" << endl;
if(R2=G2)
cout << "quest~
ao 2" << endl;
if(R3=G3)
cout << "quest~
ao 3" << endl;
}

Exemplo 22 Enunciado: Suponha que em vez da resposta de um unico estu-


dante se tenha uma lista de respostas de n estudantes, dado o valor de n.

Para repetir o processo acima n vezes e preciso utilizar uma instruc~ao de


repetic~ao. Como essa repetic~ao deve ocorrer n vezes, a instruc~ao adequada e
a repetic~ao controlada por variaveis:

para aluno de 1 ate n repita processo aluno

Como o gabarito e o mesmo para todos os estudantes, a leitura e a impress~ao


do gabarito deve preceder a instruc~ao de repetic~ao e o bloco \processa aluno"
e o algoritmo exameFinal tendo como entrada de dados apenas as respostas
de cada aluno.
~ DE SELECAO
3.1. ESTRUTURAS DE DECISAO ~ OU DE ALTERNATIVAS 73
exameFinal1()
leia(n);
leia(G1,G2,G3);
imprima(\gabarito: ");
imprima(G1,G2,G3);
para aluno de 1 ate n repita
leia(R1,R2,R3);
se (R16=G1)e(R26=G2)e(R36=G3) ent~ao
imprima(\Eliminado");
sen~ao
imprima(\Acertou: ");
se R1=G1 ent~ao
imprima(`Q1');
se R2=G2 ent~ao
imprima(`Q2');
se R3=G3 ent~ao
imprima(`Q');

Implementa
c~ao.

#include <iostream.h>

void main()
{
char G1,G2,G3,R1,R2,R3;
int n, aluno;
cout << ``Digite o numero de alunos: " << endl;
cin >> n;
cout << "Digite os gabaritos G1, G2, G3: " << endl;
cin >> G1 >> G2 >> G3;
cout << G1 << G2 << G3 << \endl;
for (aluno=1; aluno<=n;aluno++)
{
cout << "Digite as respostas R1, R2, R2: " << endl;
cin >> R1 >> R2 >> R3;

if (R1 /= G1 && R2 /= G2 && R3 /= G3)


cout << "Eliminado" << endl;
else
74 CAPITULO 3. COMANDOS ESTRUTURADOS
{
cout << "Acertou" << endl;
if(R1=G1)
cout << "quest~
ao 1" << endl;
if(R2=G2)
cout << "quest~
ao 2" << endl;
if(R3=G3)
cout << "quest~
ao 3" << endl;
}
}

Fuc~oes de bibliotecas
Alem das operaco~es de nidas sobre os elementos do tipo inteiro e real, vamos considerar,
a partir de agora, que temos disponvel uma biblioteca de func~oes. Isto signi ca que num
programa que for preciso usar uma ou mais dessas func~oes tudo que e preciso fazer e for-
necer os nomes das func~oes com os argumentos correspontes. Chamemos essa biblioteca
de bibliFunc e para que ela, efetivamente, funcione devemos colocar a instruc~ao inclua
biblifunc antes do programa \principal"(no pre^ambulo) e as expeci cac~oes das func~oes
que est~ao sendo usadas antes do programa. Vamos supor que essa biblioteca contem
as func~oes elementares da matematica, como, por exemplo, abs()(func~ao valor absolu-
to), sqrt()(funca~o raz quadrada), ln()(logaritmo na base natural), exp()(exponencial),
sin()(seno), cos()(coseno) etc. Podemos usar qualquer uma dessas func~oes elementares
na biblioteca, mas, alem de incluir a biblioteca no pre^ambulo, e preciso especi car a
func~ao que esta sendo usada. Por exemplo, suponha que pretendemos usar a func~ao raz
quadrada, para isso devemos uncluir a sua especi cac~ao(prototipo) sqrt : R ! R. + 4

Exemplo 23 Enunciado: Dados tr^es numeros reais correspondentes, respec-


tivamente, aos coe cientes de uma equac~ao do segundo grau, ax2 + bxx + c = 0,
determinar e imprimir suas razes nos seguintes casos: razes reais distintas,
razes reais iguais e razes complexas(complexas conjungadas). Imprimir men-
sagem se a equac~ao n~ao for do segundo grau(a=0). Considerar disponveis em
biblioteca as func~oes srt()(razQuadrada()) e abs()(valorAbsoluto()).
O programa nal que, deixaremos como exerccio, teria o seguinte aspecto
incluir biblifunc

As func~oes dinponveis, de fato, dependem da sua implementac~ao numa linguagem de programac~ao


4
e fazem parte da biblioteca da linguagem.
3.2. EXERCICIOS 75
razQuadrada()
.............

3.2 Exerccios
Em cada um dos exerccios abaixo apresentar a analise do problema, o projeto do algoritmo
e a implementac~ao em C++.
1. Dada uma sequ^encia de resultados da LOTO, identi car se cada numero e par,
mpar, multiplos de 3, multiplos de 5 ou multiplos de 7. Por exemplo,
Entrada: 27,16,42,30,10
Sada: 27 e mpar, multiplo de 3
16 e par
42 e par, multiplo de 3, multiplo de 7
30 e par, multiplo de 3, multiplo de 5
10 e par, multiplo de 5
2. Uma empresa decidiu dar uma grati cac~ao de Natal a seus funcionarios, baseada no
numero de horas extras e no numero de horas que o empregado faltou ao trabalho.
O valor do pr^emio e obtido pela consulta a tabela I, em que H e o numero de horas-
extras subtrado de dois tercos do numero de horas-faltas.
tabela I
H(horas) Pr^emios(R$)
(40,100] 100,00
(30,40] 80,00
(20,30] 60,00
(10,20] 40,00
(0,10] 20,00
Dados os numeros de identi cac~ao dos funcionarios, o numero de horas extras e o
numero de horas-faltas, imprimir uma relac~ao com duas colunas, a primeira con-
tendo o numero de funcionario e a segunda o valor do pr^emio a que faz jus.
3. O departamente do meio ambiente tem uma relac~ao de tr^es industrias altamente
poluentes, em constante estado de alerta. O ndice de poluic~ao e determinado regu-
larmente na regi~ao e e considerado normal o valor do ndice entre 0,05 e 0,25. Se o
ndice da poluica~o atingir 0,25 a situac~ao e de alerta. Se atingir 0,30, a primei-
ra industria da relac~ao e chamada a suspender as atividades, se o ndice atingir
0,40, a segunda industria tambem deve ser chamada a suspender as atividades
e se o ndice exceder 0,50, a terceira industria tambem deve ser noti cada. As
industrias s~ao identi cadas pelas letras A, B, C.
76 CAPITULO 3. COMANDOS ESTRUTURADOS
Fazer um programa para ler o ndice de poluic~ao e emitir relatorio noti cando
as industrias, caso seja necessario. Deve constar do relatorio a situac~ao ocorri-
da(abaixo do normal, norma ou alerta).
4. Em um curso de ci^encia da computac~ao a nota do estudante e calculada a partir de
tr^es notas atribudas, respectivamente, a um trabalho de laboratorio, a uma avaliac~ao
semestral e a um exame nal. As notas variam de 0 a 10 e a nota nal e a media
ponderada das tr^es notas mencionadas. A tabela abaixo fornece os pesos:

laboratorio peso 2
avaliac~ao semestral peso 3
exame nal peso 5

Dada uma relac~ao de n estudantes, cada um com o respectivo numero de matrcula


e as tr^es notas acima mencionadas, faca um programa para calcular a nota nal e
a classi cac~ao de cada estudante. A classi cac~ao e dada conforme a tabela abaixo.
Imprimir a lista dos n estudantes, com o seu numero, nota nal e classi cac~ao.

Nota nal Classi cac~ao


[8; 10] A
[7; 8) B
[6; 7) C
[5; 6) D
[0; 5) R

5. Cacular xn , supondo x um numero qualquer e n um inteiro n~ao negativo. Considerar


n~ao disponvel em biblioteca a func~ao de potenciac~ao.
6. Dados tr^es numeros inteiros correspondentes, respectivamente, ao dia, m^es e ano do
nascimento de uma pesssoa e tr^es outros numeros correspondentes, respectivamente,
ao dia, m^es e ano corrente(por exemplo, dada de hoje), determinar e imprimir
a idade em anos completos(excluir meses e dias). Se a data do nascimento for
posterior a data corrente, deve ser impressa a mensagem alusiva.
7. S~ao dados um numero n e quatro outros, a; b; c; d, correspondentes, respectivamente,
as extremidades dos intervalos [a; b] e [c; d], sendo a < b, c < d e a < c. Determinar
se n pertence somente ao intervalo [a; b] ou somente ao intervalo [c; d] ou, se n
pertence a ambos ou se n n~ao pertence a nenhum dos dois. Em cada caso imprimir
uma mensagem conveniente.
3.2. EXERCICIOS 77
8. Durante os 31 dias do m^es de julho foram tomadas as temperaturas medias diarias
da cidade de Conquista. Determinar o numero de dias desse m^es com temperaturas
menores ou iguais a 15 graus centgrados e o numero de dias com temperaturas
maiores que 15 graus centgrados.
9. Uma loja de calcados anota diariamente a quantidade de pares vendidos. Determi-
nar em que dia do m^es de marco ocorreu a maior venda e qual foi a quantidade
vendida nesse dia.
10. Dados dois numeros inteiros e positivos, i e j , determinar e imprimir os n primeiros
multiplos de i ou de j ou de ambos.
11. Um numero inteiro positivo e triangular se ele e o produto de tr^es numeros naturais
consecutivos. Por exemplo, o numero 120 e triangular porque 120 = 4  5  6.
Dado um numero inteiro e positivo veri car se ele e ou n~ao triangular, imprimindo
mensagem.
12. O governa da Republica das Bananas instituiu um controle de precos e salarios
logo apos sua eleic~ao. Uma previs~ao, baseada nas tend^encias atuais, revela que os
salarios v~ao aumentar anualmente de 5%, o custo de vida 10% e os impostos de
15%. Por outro lado, existe uma previs~ao de que, se os impostos mais o custo de
vida consumirem mais do que 70% do salario anual para um numero signi cativo
de cidad~aos, o partido eleito tera problemas na proxima eleic~ao(em quatro anos), e
se atingir 80% certamente n~ao sera vitorioso.
A SIB(Secretaria de Informatica de Bananas) coletou os dados de uma amostra de
seus eleitores, referente a salario, imposta e custo de vida, e deseja determinar o
numero e a percentagem de cidad~aos da amostra que caem nas categorias de 75% a
80%.
Prever o metodo utilizado para assinalar o m dos dados.
13. A companhia de Pulverizac~ao PX Ltda executa pulverizac~ao de lavouras. Os cus-
tos de pulverizac~ao dependem do tipo da praga e da area da regi~ao que deve ser
pulverizada, conforme a seguinte tabela:
Codigo praga e preco por acre.
A ervas daninha, 10,00 por acre.
B gafanhotos, 20,00 por acre.
C broca, 30,00 por acre.
D tudo(os tr^es acima), 25,00 por acre,
Se a area a ser pulverizada possui mais do que 1.000 acres, existe o desconto de 5%.
Se o custo de pulverizaca~o ultrapassar 25.000,00 ha um desconto de 10%. Se ambos
os descontos se aplicam, e calculado em primeiro lugar o relacionado com a area.
78 CAPITULO 3. COMANDOS ESTRUTURADOS
O CPD dessa companhia recebe a relac~ao dos servicos contratados, contendo as in-
formaco~es: numero de pedido, tipo de pulverizac~ao e area pulverizada. O CPD deve
emitir uma relaca~o da qual conste, em cada o valor da conta a pagar, correspondente
a cada pedido de servico. Prever sentinela para m de dados.
14. Dado um numero inteiro e positivo determinar e imprimir o maior divisor n~ao-
primo e o fator primo, excluindo em ambos os casos, ele proprio.
Por exemplo, se o numero for 12 dever~ao ser impressos 6(maior divisor n~ao-primo)
e 3(maior divisor primo). Se o numero for 13, devera ser impresso \n~ao existem
divisores". Se o numero for 15, devera ser impresso apenas 5 e a mensagem \o
maior divisor e primo".
15. Utilizar as informac~oes do exemplo 20 para imprimir a folha de pagamento dos
funcionarios, alem da emiss~ao do contracheque para cada um deles. Use sentinela
para assinalar m de dados.
16. Dado um numero inteiro maior que um, decomponha-o em seus fatores primos,
imprimindo uma tabela contendo os fatores e os respectivos expoentes.
Captulo 4
ALTERNATIVAS MU LTIPLAS
4.1 Selec~ao multipla
Sintaxe:

Escolha
caso <condic~ao1>
<comando-composto1>
caso <condic~ao2>
<comando-composto2>
....
...
caso <condic~aoN>
<comando-compostoN>
sen~ao
<comando-compostoL>
m-Escolha.
Sem^
antica

Entramos com um valor constante de um tipo basico, chamado chave,


 se ele for igual a <condic~ao1>, ent~ao executar <comando-composto1>;
 se ele for igual a <condic~ao2>, ent~ao executar <comando-composto2>;
 e assim continua ate,
 se ele for igual a <condic~aoN> executar <comando-compostoN>;
 se nenhuma das condic~oes anteriors casar com a chave, ent~ao executar <comando-
compostoL>
79
80 CAPITULO 4. ALTERNATIVAS MULTIPLAS

Observe que pode n~ao existir o ramo sen~ao e, neste caso sera executado o proximo
comando apos o corpo de \Escolha". Alem disso, se houver uma condic~ao que case com
a chave, o camando correspondente e executado e o controle sai do corpo de \Escolha" e
vai para o proximo comando.
Exemplo 24 Enunciado: No correio local so existem selos de 3 e de 5 cen-
tavos. A taxa mnima para correspond^encia e de 8 centavos. Desejamos de-
terminar o menor numero de selos de 3 e 5 centavos que completam o valor
de uma taxa dada.
An
alise

O valor mnimo da taxa e 8 centavos e o valor maximo n~ao esta especi cado.
Precisamos responder, inicialmente, a quest~ao de se, dado um numero inteiro
qualquer, existem parcelas de 3 e/ou 5 cuja soma seja igual a esse numero.
Isto corresponde a veri car se existe soluc~ao do problema.
Na lista abaixo relacionamos a decomposic~ao de alguns numeros inteiros a
partir de 8, em parcelas de 5 e/ou 3:
8=3+5 8=3+5
9=3+3+5 9=3+3+3
10=5+5 10=5+5
Observac~ao
11=3+8 11=3+(3+5) suc(5)=3+3 e suc(3+3+3)=5+5
a =inicial b=suc(a) c=suc(b)
12=3+9 12=3+(3+3+3) 8=3+3 9=3+3+3 10=5+5
13=3+10 13=3+(5+5) 11=3+(3+5).
A partir de suc(c) o padr~ao se repete.
14=3+11 14=3+3+(3+5)
15=3+12 15=3+3+(3+3+3)
16=3+13 16=3+3+(5+5)
A observaca~o nos permite concluir que os tr^es primeiros sucessivos de (3+3)
est~ao escritos na forma de uma soma de 3 ou 5 e que o terceiro sucessivo
reproduz, em sua decomposic~ao, novamente a parcela (3+5).
Decorre deste ultimo resultado que a construc~ao dos proximos tr^es sucessivos
mantera a decomposic~ao dos proximos numeros consecutivos em parcelas de 3
ou 5, reproduzindo novamente a parcela (3+5).
Repetindo esse procedimento tantas vezes quantas forem necessarias alcancaremos
o numero cuja decomposic~ao em parcelas de 3 ou 5 desejamos obter. A unica
restric~ao que podera existir para o valor maximo da taxa sera a limitac~ao do
tipo de dados disponvel na linguagem de implementac~ao do algoritmo.
Portanto, podemos concluir que o problema tem soluc~ao e
~ MULTIPLA
4.1. SELECAO  81
 Entrada: Um numero n, a taxa a pagar.
 Sada: Uma lista de dois naturais, quantas parcelas de 3 e quantas par-
celas de 5.
 Metodo: Recebe como entrada um numero natural e devolve como sada
um par de numeros naturais.

Projeto
Como ja concluimos, na fase de analise do problema, que ele tem soluc~ao
precisamos agora encontrar um metodo para fornec^e-la.
Se o valor da taxa fosse divisvel por 5, a soluc~ao seria obtida como o quociente
da divis~ao da taxa por 5: teramos a menor quantidade de selos de 5 cuja soma
fosse o valor da taxa. Se a divis~ao n~ao fosse exata e desse resto 1, por exemplo,
n~ao obteramos a decomposic~ao desejada. Neste caso, tentavamos diminuir a
menor quantidade possvel de selos de 5 que possibilitasse a soluc~ao. Por
exemplo, se a taxa fosse 11, retiraramos apenas um selo de 5 sobrando 6
sentavos. Como 6 e um multiplo de 3, a soluc~ao seria encontrada.
A seguir apresentamos alguns exemplos desse metodo para diferentes valores
de taxas:
taxa=75: 15 selos de 5 e nenhum de 3.
75 = 15  5 + 01
taxa=76:14 selos de 5 e 2 selos de 3.
75 = 14  5 + 1. Como 1 ! 5 e 15-1=14, temos 14 selos de 5
e 2 de 3.
taxa = 77: 13 selos de 5 e 4 de 3, pois
77 = 15  5 + 2. Como 2 selos de 5 fazem 10, temos 10 + 2 =
12 ! 3 selos de 3.
Repetindo esse racicnio para as taxas 78 e 79, e sabendo que 78 = 15  5 + 3
e 79 = 15  5 + 4, obteremos a seguinte tabela que relaciona o resto da taxa
por 5 e as quantidades de selos de 5 e 3:
1Estamos a formula de que se D e D s~ao inteiros positivos ent~ao D = quociente  d + resto; com 
resto  quociente
82 CAPITULO 4. ALTERNATIVAS MULTIPLAS

resto selos de 5 selos de 3
0 quociente 0
1 quociente - 1 2
2 quociente - 2 4
3 quociente 1
4 quociente - 1 3

Estrategia 1
A tabela, acima, sugere a seguinte estrategia:
Determinar o quociente e o resto da taxa por 5.
Veri car qual alternativa ocorreu em func~ao do resto e
conforme o caso, determinar o numero de selos de 5 e o
numero de selos de 3.
Agora, temos uma situac~ao em que existem diversas alternativas(cinco) de-
pendendo do valor de uma variavel que pode ter diversos valores(neste caso,
s~ao somente cinco valores possveis).
8
>
>
> 0 ! selos de 5 = quociente e selos de 3 = 0
>
< 1 ! selos de 5 = quociente 1 e selos de 3 = 2
resto = > 2 ! selos de 5 = quociente 2 e selos de 3 = 4
>
: 34 !
>
> selos de 5 = quociente e selos de 3 = 1
! selos de 5 = quociente 1 e selos de 3 = 3
A descric~ao dessa estrutura de selec~ao por meio da instruc~ao de selec~ao de
dois ramos levara a um encadeamente de intruc~oes de selec~ao. Adotando uma
maneira para simpli car essa \cascata", temos
caso resto seja escolha
0: selos de 5 quociente;
selos de 3 0;
1: selos de 5 quociente - 1;
selos de 3 2;
2: selos de 5 quociente - 2;
selos de 3 4;
3: selos de 5 quociente;
selos de 3 1;
4: selos de 5 quociente - 1;
selos de 3 3;
m
~ MULTIPLA
4.1. SELECAO  83
Como vimos anteriormente, esta intruc~ao e denominada selec~ao multipla, e a
variavel resto, cujos valores condicionam a selec~ao da alternativa, e chamado
seletor.

Algoritmo selos
Objetivo: determinar o menor numero de selos de cinco ou
de tr^es unidades cuja seja o valor da taxa(taxa 8).
Entrada: taxa(inteiro).
Sada: taxa, cinco, tr^es(Inteiro).

selos();
leia(taxa);
quociente taxa div 5;
resto taxa mod 5;
caso resto seja escolha
0: cinco quociente; tr^es 0;
1: cinco quociente - 1; tr^es 2;
2: cinco quociente - 2; tr^es 4;
3: cinco quociente; tr^es 1;
4: cinco quociente - 1; tr^es 3;
m
imprima(taxa,cinco,tr^es);

Observe que a mesma estrutura poderia ser descrita utilizando-se um ninho


de instruc~oes de selec~ao de dois ramos, em forma de cascata:
se resto = 0
ent~ao <bloco1>
sen~ao se resto = 1
ent~ao <bloco2>
sen~ao se resto = 2
ent~ao <bloco3>
sen~ao se resto = 3
ent~ao <bloco4>
sen~ao <bloco5>
Outra maneira de apresentar a instruc~ao de selec~ao multipla e a seguinte:
84 CAPITULO 4. ALTERNATIVAS MULTIPLAS

caso seletor seja
v1:<bloco1>;
v2:<bloco2>;
.
.
.
vn:<blocon>;
A variavel seletor so pode ser do tipo escalar(inteiro,caractere,booleano). Cada
valor v1,v2,...vn determina uma unica das alternativa bloco 1,bloco 2,...,bloco
n, respectivamente.
Se o seletor n~ao tiver nenhum dos valores especi cados na instruc~ao, nenhum
bloco sera executado.

Implementac~ao
#include <iostream.h>

void main()
{
int taxa, cinco, tr^
es, quociente, resto;

cout << "Digite a taxa: " << endl;

cin >> taxa ;

quociente = taxa/5;
resto = taxa % 5;

switch ( resto)
{
case 0:
cinco = quociente;
tr^
es = 0;
break;
case 1:
cinco = quociente - 1;
tr^
es = 2;
break;
case 2:
cinco = quociente - 2;
~ MULTIPLA
4.1. SELECAO  85
tr^
es = 4;
break;
case 3:
cinco = quociente;
tr^
es = 1;
break;
case 4:
cinco = quociente - 1;
tr^
es = 3;
break;
}
cout << taxa << cinco << tr^
es << endl;
}

Estrategia 2
Poderamos usar outra abordagem para resolver esse problema, com segue.

77 5 quociente resto observac~ao


2 15 15 2 2n~ao e multiplo de 3.
14 7 subtramos 1 do quociente e somamos 5 ao resto;
o novo resto 7 n~ao e multiplo de 3.
13 12 subtramos 1 do quociente e somamos 5 ao resto,
o novo resto 12 e um multiplo de 3.

Logo, s~ao 13 os selos de 5, e 4 os selos de 3 porque o quociente de 12 por 3 e


4.

Em resumo: inicialmente calculamos o quociente e o resto da divis~ao da taxa


por 5. Em seguida, enquanto o resto n~ao for multiplo de 3, diminuimos uma
unidade do quociente e adicionamos 5 unidades ao resto. Quando o valor
modi cado do resto tornar-se multiplo de 3 obteremos a soluc~ao procurada: o
numero mnimo de selos de 5 e valor do \quociente modi cado" e o numero
mnimo de selos de 3 e o valor do quociente da divis~ao do \resto modi cado"
por 3.
86 CAPITULO 4. ALTERNATIVAS MULTIPLAS

selos2();
leia(taxa);
quociente taxa div 5;
resto taxa mod 5;
enquanto resto mod 3 6= 0 faca
quociente quociente - 1;
resto resto + 5;
cinco quociente;
tr^es resto div 3;
imprima(taxa,cinco,tr^es);

Implementa
c~ao de selos2()

#include <iostream.h>

void main()
{
int taxa, cinco, tr^
es, quociente, resto;

cout << "Digite a taxa: " << endl;

cin >> taxa ;

quociente = taxa/5;
resto = taxa % 5;
while (resto % 3 /= 0)
{
quociente = quociente - 1;
resto = resto + 5;
}
cinco = quociente;
tr^
es = resto/3;
cout << taxa << cinco << tr^
es << endl;
}

Exemplo 25 Enunciado: Dados tr^es valores a, b e c, em que a e b s~ao


numeros reais e c e um caractere, imprimir o resultado da operac~ao de a por b
se c for um smbolo de operador aritmetico; caso contrario deve ser impressa
uma mensagem de operador n~ao de nido.
An
alise
~ MULTIPLA
4.1. SELECAO  87
Vamos considerar alguns exemplos de entradas:

(a) entrada: a b c , sada: 3 + 5 = 8.


3 5 0 +0

(b) entrada: a b c , sada: 2 - 9 = -7.


2 9 0 0

(c) entrada: a b =c , sada: erro, divis~ao por 0.


12 0 0 0

(d) entrada: a b dc , sada: erro operador n~ao de nido.


12 4 0 0

Embora no enunciado do problema n~ao haja especi cac~ao da sada desejada


no caso de ocorrer divis~ao por zero, acrescentamos uma mensagem para esse
tipo de erro.

 Entrada: a; b(real), c(caractere).


 Sada: Um real ou uma mensagem.
 Metodo: Recebe como entrada dois numeros reais e um caractere e de-
volve um real ou um caractere.

Projeto

A sada depende basicamente do valor de c. Conforme o valor de c existem


5 alternativas. Quatro correspondentes aos operadores arimeticos e uma aos
demais smbolos que n~ao s~ao operadores aritmeticos.
8
> 0+0 calcular
>
>
a+b
imprimir o resultado
>
>
>
>
>
> 0 0 calcular a - b
>
>
< imprimir o resultado
c= > 00 calcular a  b
>
> imprimir o resultado
>
>
> se b 6= a calcule a=b e imprima o resultado
>
>
> 0 =0
>
: n:o:a caso
> contrario, imprima mensagem
imprimir mensagem
Vamos descrever esse tipo de selec~ao na forma:
88 CAPITULO 4. ALTERNATIVAS MULTIPLAS


caso c seja
0 +0 : resultado a + b;
imprima(a; c; b;0 =0; resultado);
0 0 : resultado a b;
imprima(a; c; b;0 =0; resultado);
0 0 : resultado a  b;
imprima(a; c; b;0 =0; resultado);
se b 6= 0
ent~ao
0 =0 : resultado a=b;
imprima(a; c; b;0 =0; resultado);
sen~ao
imprima("erro : divis~ao por zero");
sen~ao
imprima("erro : operador n~ao de nido");
fim
Essa instruc~ao e denominada instruc~ao multipla com ramo sen~ao. Seu formato
e:
caso seletor seja
v1:<bloco1>;
v2:<bloco2>;
.
.
.
vN:<blocoN>;
sen~ao <blocoF>
m
Se a variavel seletor tiver um dos valores v1, v2,..,vN, sera executado o blo-
co correspondente, mas se o seletor tiver valor diferente de todos os valores
eseci cados na instruca~o, o bloco F sera executado.
A seleca~o contem, portanto, n+1 alternativas:
n correspondentes a cada uma das condic~oes seletor = vi com valor verda-
deiro e i um dos numeros de 1 a n.
1 correspondente a condic~ao seletor = vi com valor falso para qualquer valor
de i entre 1 e n.
~ MULTIPLA
4.1. SELECAO  89
Finalmente, podemos apresentar o algoritmo.

Algoritmo operac~ao
Objetivo: Dados dois numeros reais a e b e um caractere op, se op for um
smbolo de operac~ao aritmetica, calcular e imprimir o
resultado; caso contrario imprimir mensagem
Entrada: a; b(real), op(caractere).
Sada: resultado(real) ou mensagem(cadeia de caractere).
operac~ao();
leia(a,op,b);
caso op seja
'+': resultado a + b;
imprima(a,op,b,'=',resultado);
'-': resultado a - b;
imprima(a,op,b,'='resultado);
'*': resultado a  b;
imprima(a,op,b'=',resultado;
se b 6= 0 ent~ao
resultado a/b;
'/': imprima(a,op,b,'='resultado;
sen~ao
imprima(\erro:divis~ao por zero");
sen~ao
imprimir(\erro:operador n~ao de nido")
m

Implementa
c~ao

#include <iostream.h>

void main()
{
int a, b;
char op;

cout << "Digite a, b e op: " << endl;


90 CAPITULO 4. ALTERNATIVAS MULTIPLAS

cin >> a >> b >> op ;

switch (op)
{
case '+': cout << a + b; break;

case '-': cout << a - b; break;

case '*': cout << a*b; break;

case '/':

if (b /= 0)
cout << a/b;
else
cout << "erro: divis~
ao por zero";
break;
default : cout << "erro: operador n~
ao definido;
}

Exemplo 26 Enunciado: Uma companhia de seguros possui oito caterias de


seguros baseados na idade e ocupac~ao do segurado. Somente pessoas com pelo
menos 17 anos e n~ao mais de 70 poder~ao adquerir apolices de seguros. Quanto
as classes de ocupac~oes, foram de nidos tr^es grupos de riscos. A tabela abaixo
fornece as categorias em func~ao da faixa etaria e dos grupos de risco. Dados
idade e grupo de risco, determinar a categoria.

Grupo de risco
Idade Baixo Medio alto
17 a 20 1 2 3
21 a 24 2 3 4
25 a 34 3 4 5
35 a 64 4 5 6
65 a 70 7 8 9

An
alise

A idade e representada por um numero inteiros de anos, sendo, portanto, um


valor do tipo inteiro.
~ MULTIPLA
4.1. SELECAO  91
O grupo de risco gr, e uma variavel do tipo caractere que pode assumir os
valores `B', `M', `A'.

 Entrada: idade(real), gr(caractere).


 Sada: categoria(cat).
 Metodo: Recebe como entrada um inteiro, representando a idade, e
um caractere, representando o grupo de risco, e devolve um caractere,
representando a categoria.

Projeto

Na instruca~o de selec~ao multipla vimos que cada valor do seletor seleciona


uma alternativa, isto e, cada valor corresponde biuniocamente a uma unica
alternativa.

No nosso caso, desejamos que uma faixa de valores do seletor permita


selecionar uma mesma alternativa: para a idade na faixa de 17 a 20 anos,
temos uma mesma alternativa, que e a primeira linha da tabela dada.

Na linha selecionada, por sua vez, temos novamente que selecionar uma de
tr^es alternativas, que e a primeira linha da tabela dada.

Na linha selecionada, por sua vez, temos novamente que selecionar uma das
tr^es alternativas que depende do valor de um caractere(`B', `M',`A').

Na intruc~ao de selec~ao multipla vamos descrever a faixa de valores escre-


vendo o primeiro valor separado do ultimo por dois pontos seguidos.

Como a categoria depende da faixa etaria combinada com o caratere do grupo


de risco, faremos uso de um ninho de instruc~oes caso-seja.
92 CAPITULO 4. ALTERNATIVAS MULTIPLAS

Algoritmo seguro
Objetivo: Calcular a categoria de seguro em func~ao da idade e do grupo de risco.
Entrada: idade(inteiro), gr(caractere).
Sada: cat(inteiro).
seguro();
leia(idade,gr);
caso idade seja
17..20:caso gr seja
`B':cat 1;
`M':cat 2;
`A':cat 3;
m;
21..24:caso gr seja
`B':cat 2;
`M':cat 3;
`A':cat 4;
m;
25..34:caso gr seja
`B':cat 3;
`M':cat 4;
`A':cat 5;
m;
35..64:caso gr seja
`B':cat 4;
`M':cat 5;
`A':cat 6;
m;
65..70:caso gr seja
`B':cat 7;
`M':cat 8;
`A':cat 9;
m;
m;
imprimir(idade,gr,cat)

Implementa
c~ao

#include <iostream.h>
~ MULTIPLA
4.1. SELECAO  93
void main()
{
int idade, cat;
char gr;

cout << "Digite idade e grupo de risco: " << endl;

cin >> idade >> gr;

for(idade=17;idade<=20;idade++)
{
switch( gr )
case:`B'
cat = 1;
case:`M'
cat = 2;
case:`A'
cat = 3;
}
for(idade=21;idade<=24;idade++)
{
switch( gr )
case:`B'
cat = 2;
case:`M'
cat = 3;
case:`A'
cat = 4;
}
for(idade=25;idade<=34;idade++)
{
switch( gr )
case:`B'
cat = 3;
case:`M'
cat = 4;
case:`A'
cat = 5;
}
for(idade=35;idade<=64;idade++)
{
94 CAPITULO 4. ALTERNATIVAS MULTIPLAS

switch( gr )
case:`B'
cat = 4;
case:`M'
cat = 5;
case:`A'
cat = 6;
}
for(idade=65;idade<=70;idade++)
{
switch( gr )
case:`B'
cat = 7;
case:`M'
cat = 8;
case:`A'
cat = 9;
}
cout << idade << gr << cat;
}

4.2 Exerccios
Em cada um dos exerccios abaixo deve ser feito a analise do problema, o projeto do
algoritmo e a implementac~ao do algoritmo.
1. Dada uma lista de datas de nasciemnto de varias pessoas imprimir a lista do tipo ca-
racterstico correspondente a cada data, de acordo com a regra abaixo.(n~ao esquecer
de usar sentinela).
Mensagens sobre a personalidade de pessoas s~ao estabelecidas de acordo com as
seguintes regras:
Seja D = dia do nascimento da pessoa(D = 1..31);
M = m^es do nascimento da pessoa(M = 1..12);
A = ano do nascimento da pessoa(dado com 4 algarismos);
N = numero formado pela justaposic~ao dos tr^es anteriores: DMA;
Z = numeo obtido de N pela regra dos \noves-foras".
A tabela abaixo fornece um traco marcante da personalidade da pessoa em conside-
rac~ao:
4.2. EXERCICIOS 95
Z tipo
0 irrestvel
1 impetuoso
2 discreto
3 amoroso
4 tmido
5 paquerador
6 estudioso
7 sonhador
8 charmoso

Exemplo: Se uma pessoa nasceu em 30/10/1972, teremos D=30, M=10, e A=1972.


Portanto, N=30101972. Aplicando a regra dos \noves-fora" temos Z=5, e portanto,
seu tipo e paquerador.
Esclarecimento. Regras do noves-fora: somam-se os algarismos dos numeros en-
quanto a soma for inferior a 9. Quando igualar a 9, subtrai-se 9 e continua-se
somando-se. No caso do exemplo, acima, os valores obtidos sucessivamente s~ao:
3+0=3; 3+1=4; 4+0=4; 4+1=5; 5+9=14;, nove-fora, 5, 5+7=12, nove-fora, 3,
3+2=5. A regra dos noves-fora pode ser implementada de varias outras maneiras.
Uma delas e considerar, simplesmente, o resto da divis~ao do numero Z por 9. A im-
plementac~ao, neste caso, depende do domnio de nido na linguagem de programac~ao
utilizada.
2. Uma loja utiliza os seguintes codigos para as transac~oes de cada dia:

`*' signi ca compra a vista


`+' signi ca compra a prazo
`-' signi ca pagamento efetuado

Dada uma lista de transac~oes contendo o valor de cada transac~ao e o respectivo


codigo, imprima um relatorio com os totais de compras a vista, compras a prazo e
pagamentos efetuados. Usar o caractere zero como sentinela para o m de dados.
3. Dada a tabela abaixo, calcular e imprimir o salario reajustado.

Pro ss~ao % de reajuste


Agente tecnico 50%
Tecnico 40%
Engenheiro 30%
Outros 10%
96 CAPITULO 4. ALTERNATIVAS MULTIPLAS

4. Dado o numero do m^es, imprimir o seu nome. Por exemplo, dado 5, imprimir
maio.
5. Dado o numero do dia da semana, imprimir seu nome.
Captulo 5
PROGRAMACA~ O MODULAR
5.1 Procedimentos e func~oes
Normalmente, comecamos aprendendo programac~ao escrevendo programas pequenos e
simples que consistem somente de um programa principal, como temos visto ate aqui
nestas notas. Aqui, \programa principal", signi ca uma sequ^encia de comandos que mo-
di cam os dados, os quais s~ao globais atraves de todo o programa, no sentido de que
qualquer comando do programa pode modi car os dados. Esta tecnica de programac~ao,
chamada n~ao estruturada, e muito inconvinente quando o programa se torna razoavelmen-
te grande. Por exemplo, se a mesma sequ^encia de comandos for necessaria em diferentes
locais no programa, ela deveria ser copiada. Isto levou a ideia de extrair essas sequ^encias,
dar-lhes um nome, desenvolver uma tecnica para chama-las e retorna-las desses proce-
dimentos. Com esse tipo de programac~ao procedural somos capazes de combinar e
retornar sequ^encias de comandos em um unico local. Uma chamada de procedimento e
usada para invocar o procedimento. Apos a sequ^encia ser processada, o uxo de controle
vai para a posic~ao seguinte a que ele estava quando da chamado do procedimento. Intro-
duzindo par^ametros, assim como procedimentos de procedimentos(subprocedimentos), os
programas, agora, podem ser escritos de maneira mais estruturad0s e livres de erros. Por
exemplo, se um procedimento estiver correto, toda vez que ele for usado ele produz resul-
tados corretos. Por consequinte, em casos de erros podemos diminuir a busca daqueles
lugares que resultaram na incorrec~ao.
Agora, um programa pode ser visto como uma sequ^encia de chamadas de procedimen-
tos. O programa principal e responsavel de passar dados para as chamadas individuais,
os dados s~ao processados pelos procedimentos e, uma vez o programa tenha terminado, os
dados resultantes s~ao apresentados.
Portanto, na programac~ao procedural temos um unico programa dividido em pecas me-
nores chamadas procedimentos. Para nos habilitar a usar um procedimento ou um grupo
de procedimentos em nossos programas, eles devem estar disponveis separadamente. Por
97
98 CAPITULO 5. PROGRAMACAO
~ MODULAR
esta raz~ao, a programac~ao modular nos permite agrupar procedimentos em modulos. Com
a programac~ao modular os procedimentos com funcionalidades comuns s~ao agrupados em
modulos separados. Um programa, portanto, n~ao consiste agora somente de uma unica
parte. Ele consiste, agora, de varias pequenas partes que interagem atraves das chamadas
de procedimentos, formando o programa todo. Cada modulo possui seus proprios dados.
Isso possibilita que cada modulo administre um estado interno que e modi cado por cha-
madas de procedimentos deste modulo. Entretanto, existe um unico estado por modulo e
cada modulo existe no maximo uma vez no programa todo. A seguir analisaremos com
um pouco mais de profundidade esse modo de fazer programac~ao.

5.2 Procedimentos e func~oes


Antes de estudarmos os conceitos de func~ao e procedimento revisitaremos o conceito de
bloco, introduzindo os conceitos de variavel local e \escopo" de variaveis.

Blocos

Ate aqui usamos o conceito de bloco para agrupar comandos, com um incio e um m.
Neste sentido todo algoritmo e um bloco.
 vezes, e necessario declarar novas variaveis, ao longo do desenvolvimento do algo-
As
ritmo. Para isso poderamos retornar ao incio do algoritmo e fazer novas declarac~oes.
Podemos tambem usar o conceito de bloco para contornar esse problema.
Como ja sabemos, um bloco consiste de um conjunto de declarac~oes e comandos delimi-
tados, implicita ou explicitamente, pelas palavras incio e m, como no seguinte exemplo:
~
5.2. PROCEDIMENTOS E FUNCOES 99
incio
< declarac~oes >;
c ;
11
c ;
12
.
.
.
c n;
1
incio
< declarac~oes >;
c ;
21
c ;
22
.
.
.
c m;
2
incio
< declarac~oes >;
c ; 31
c ; 32
.
.
.
c k;3
m
c p;2
m
c r;
1
m
Quando um bloco comeca a ser executado, as variaveis declaradas dentro dele s~ao
ativadas(isto e, passam a existir efetivamente) e permanecem ativas ate o termino da
execuc~ao do bloco. Ou seja, uma variavel declarada no incio de um bloco so existe dentro
dele. Com isso, dizemos que as variaveis s~ao locais ao bloco, permitindo, desse modo,
que elas so ocupem memoria quando necessario.
Isso possibilita que o progamador gerencie a utilizac~ao de memoria.

Escopo de variaveis
Dizemos que um bloco e externo a um outro quando este faz parte dele. Neste sentido,
uma variavel em bloco e global a todos os blocos internos e local para o proprio bloco.
Podemos ter diversos blocos aninhados, conforme mostra a gura a seguir.
100 CAPITULO 5. PROGRAMACAO
~ MODULAR
M
P
A
B nvel bloco
0 M
Q 1 P, Q
R 2 A, R, S
3 B
S

P e Q s~ao internos a M M e externo a P e Q


A e interno a P P e externo a A
B e interno a A A e externo a B
R e S s~ao internos a Q Q e externo a R e S
Como ja observamos, uma variavel declarada dentro de um bloco so e conhecida dentro
deste bloco.
Se uma vaiavel A declarada em um bloco ja foi declarada com o mesmo nome num
bloco mais externo, a variavel ativa no bloco e aquela declarada localmente. A variavel
deixa de ser global para aquele bloco.
A seguir apresentamos exemplos de variaveis locais, globais e escopos de variaveis.
incio
int I, J;
leia(I);
J J  ;
incio
Exemplo 27 real X;
X J + 1;
imprima(X);
m
leia(J);
I I  J;
m
No exemplo 32, acima, I e J s~ao variaveis globais enquanto X e uma variavel local
ao bloco interno.
~
5.2. PROCEDIMENTOS E FUNCOES 101
incio
int I, J;
leia(I);
J J  ;
incio
Exemplo 28 real X, I;
X J + 1;
imprima(X);
m
leia(J);
I I  J;
m
No exemplo 33, acima, I deixa de ser global porque foi declarada(com o mesmo nome)
no bloco interno. E como se X fosse uma nova variavel I . 0

No exemplo a seguir, utilizamos o conceito de bloco para ilustrar como e possvel en-
conomizar memoria. Consideramos o problema de trocar os conteudos de duas variaveis
entre si. Mostraremos primeiro o algoritmo como tem sido feito e a nova vers~ao utilizando
bloco:
inciofsem bloco internog
int aux, a , b;
leia(a,b);
Exemplo 29 aux a;
a b;
b aux;
imprima(a,b);
m
inciofcom bloco internog
int a , b;
leia(a,b);
incio
int aux;
aux a;
a b;
b aux;
m
imprima(a,b);
m
Nesta segunda soluca~o a variavel aux so e alocada no instante da troca. Isto se torna
mais relevante num contexto onde a troca seja eventual, isto e, pode acontecer ou n~ao
dependendo do teste.
102 CAPITULO 5. PROGRAMACAO
~ MODULAR
Modulos
Os programas s~ao escritos, em geral, para resolver algum problema ou executar alguma
tarefa. Vejamos um exemplo. Uma livraria possui um arquivo organizada em ttulos
e editores de cada livro vendido. A informac~ao entra na ordem em que os livros s~ao
vendidos. Em cada duas semanas o proprietario manualmente computa o numero de
copias de cada ttulo vendido e o numero de livros vendidos de cada editor. A lista e
organizada em ordem alfabetica e usada para o proposito de reordenac~ao. Pretendemos
desenvolver um programa para realizar essa tarefa.
Como ja tivemos oportunidade de observar acima, um metodo de resolver um problema
maior e quebra-lo em um numero de problemas menores, que constituir~ao os futuros
modulos. Esperamos que estes problemas menores sejam mais faceis de resolver. No
nosso caso do problema da livraria, ele e dividido em quatro subproblemas ou tarefas
menores:
1. Ler no arquivo de vendas.
2. contar as vendas por ttulos e por editores.
3. Ordenar os ttulos por editor.
4. Imprimir os resultados.
Os itens 1, 2 e 4 representam problemas que ja sabemos resolver. Eles n~ao precisam
ser mais quebrados em problemas menores. Entretanto, o item 3 e um problema um
pouco mais complexo do que os problemas que sabemos resolver. Ent~ao, aplicaremos
nossa tecnica de re namentos a este item:1
3a. Ordenar as vendas por editor.
3b. Dentro de cada editor, ordenar as venda por ttulo.
1 Observe que as tecnicas de re namentos possibilitam ao programador, nas etapas inciais do desenvol-
vimento do algoritmo, certas abstrac~oes sobre o processo a serem descritos no algoritmo. Estas abstrac~oes
s~ao de nidas, apenas, pelo seu uso(ou efeito) e constituem uma de nic~ao funcional do processo. Nas eta-
pas posteriores, cada descric~ao funcional e substituda por trechos mais detalhados que especi cam as
etapas do processo. Quando no processo de desenvolvimento do algoritmo optamos pelos re namentos
sucessivos(que corresponde a quebrar o problema em subproblemas na fase de analise) este procedimento
conduz a modularizac~ao da soluc~ao do problema. Portanto, um modulo e um grupo de comandos, cons-
tituindo um trecho de algoritmo, com uma func~ao bem de nida. Dijkstra prop~oe a modulaizac~ao como
a regra aurea da programac~ao: dividir para conquistar. Esta divis~ao da atividade de programac~ao
permite, que a cada instante, toda atenc~ao do programador esteja concentrada na soluc~ao de cada pro-
blema espec co e bem de nido. Isto se torna muito importante na fase de veri cac~ao do programa, pois
para veri ca-lo basta veri car a correc~ao de cada modulo.
~
5.2. PROCEDIMENTOS E FUNCOES 103
3e. Comparar ttulos adjacentes dentro de cada grupo de editores. Para cada par que
casar, incrementar um contador de ocorr^encia e remover o segundo.
Os itens 3a, 3b e 3c representam, agora, problemas que sabemos como resolver. Como
poderemos resolver todos os subproblemas que geramos, resolvemos, de fato, o problema
original, maior. Observamos, agora, que a ordem original das tarefas estavam incorretas.
A sequ^encia de ac~oes requeridas e a seguinte:
1. Ler no arquivo de vendas.
2. Ordenar o arquivo de vendas. Primeiro por editor e, em seguida, por ttulo dentro
de cada editor.
3. Compactar os ttulos duplicados.
4. Escrever os resultados dentro de um novo arquivo.
Como ja sabemos, essa sequ^encia de ac~oes e o que chamamos algoritmo e cada ac~ao
constituinte um procedimento ou sub-rotina.
O problema da livraria nos mostra que um procedimento e uma ferramenta de progra-
mac~ao que serve basicamente a dois propositos:
 evitar que uma certa sequ^encia de comandos que ocorre em varios locais de um
algoritmo tenha que ser escrita repetidamente nestes locais;
 dividir e estruturar um algoritmo em partes fechadas e logicamente coerentes.
Os algoritmos cont^em, muitas vezes, grupos de comandos iguais e repetidos em varias
partes de seu corpo. Os procedimentos permitem economia de tempo de escrita e reduca~o
no tamanho do algoritmo, possibilitando a escrita dos comando repetidos apenas uma
vez. Nestes casos, a utilizac~ao de procedimentos permite tambem uma unica escrita dos
comandos que, ao serem executados, utilizam os par^amentros ou operandos adequados a
cada ocorr^encia.2
2 Bem mais importante que esta utilidade do uso de procedimentos, o seu uso na modularizac~ao de
algoritmos torna-se uma ferrramenta indispensavel na elaborac~ao de algoritmos mais complexos e de
maior tamanho. A divis~ao de estruturac~ao de algoritmos em partes logicas e uma tecnica indispensavel
em programac~ao estruturada.
Wirth considera o conceito de procedimentos um dos poucos realmente fundamentais na arte e na
tecnica da programac~ao cujo domnio exerce uma in u^encia decisiva no estilo e na qualidade do trabalho
de um programador. A divis~ao de um algoritmo em procedimentos, alem de facilitar a elaborac~ao do
algoritmo, permite uma melhor documentac~ao e veri cac~ao de sua correc~ao. Cada modulo implementado
como um procedimento deve conter sua propria documentac~ao e pode ser veri cado independetemente.
Alem disso, a modularizac~ao por procedimentos pode facilitar muito o trabalho de equipes de programac~ao
no sentido de que um algoritmo pode vir a ser dividido em partes e implementado, testado e catalogado
separadamente.
104 CAPITULO 5. PROGRAMACAO
~ MODULAR
Estrutura dos modulos de um algoritmo
Um procedimento nada mais e que um algoritmo hierarquicamente subordinado a um outro
algoritmo, comumente chamado de modulo principal. Analogamente, um procedimento
pode conter outros aninhados, como observamos anteriormente.
O conceito de objeto(variavel) local e global visto anteriormente, e tambem valido
para procedimentos. Os procedimentos s~ao tambem objetos declarados em certos pontos
de um algoritmo ou de outros procedimentos e, portanto, podendo ou n~ao ter-lhes acesso,
dependendo de sua localizac~ao. Desse modo o algoritmo que resolve o problema da livraria
apresenta a seguinte estrutura.

Algoritmo(Modulo principal)
incio
leia();
Exemplo 30 ordene();
compacte();
imprima();
m

Utilizac~ao de procedimentos
Um procedimento e criado atraves de sua declarac~ao em um algoritmo. E um objeto
estatico no sentido de que, para ser executado, precisa de uma ativac~ao provocado por um
comando especial de chamada.
A declarac~ao de um procedimento deve ser feita como as demais declarac~oes de objetos
e sempre na parte inicial de um algoritmo, um bloco ou outro procedimento.
Uma declarac~ao e constituda de um cabecalho(prototipo) e um corpo. O cabecalho
identi ca o procedimento atraves de um nome e o corpo contem as declarac~oes locais e os
comando do procedimento. A ativac~ao do procedimento e feita atraves da refer^encia feita
ao seu nome e ponto do algoritmo, respeitando as regras de escopo de objetos.
Existem dois tipos basicos de procedimentos:

 as sub-rotinas ou rotina ou procedimento propriamente dito;


 as func~oes.

Sub-rotinas
Uma sub-routina e declarada como a seguir:
~
5.2. PROCEDIMENTOS E FUNCOES 105
sub-rotina nome
declaraca~o do objetos locais a subrotina
comandos da sub-rotina
m sub-rotina
onde \nome" e o nome de refer^encia dado a sub-rotina.
A chamada de uma sub-rotina e feita com uma refer^encia a seu nome, no local do
programa onde a sub-rotina deve ser ativada. Ou seja, onde a sua execuc~ao deve ser
iniciada. Desse modo, a execuc~ao de uma subrotina se constitui em uma transfer^encia
temporaria da execuca~o do algoritmo chamador para a sub-rotina, retornando depois ao
algoritmo que chamou.

Exemplo 31 No exemplo da livraria, ordene() e uma sub-rotina e, portanto,


segundo a estruturac~ao acima, temos:

sub-rotina ordene()
< corpo >
Algoritmo(Modulo principal)
incio
leia();
ordene();
compacte();
imprima();
m

Func~oes
As func~oes constituem um tipo especial de procedimento, bastante semelhante as sub-
rotinas. As func~oes tem a caracterstica especiail de retornar ao algoritmo chamado um
valor associado ao nome da func~ao. Esta caracterstica permite uma analogia com o
conceito de func~ao em matematica.
Num dos captulos anteriores, quando apresentamos as express~oes aritmeticas usamos
func~oes como, por exemplo, abs()(func~ao valor absoluto). Podemos utilizar func~oes ma-
tematicas no algoritmo, como, por exemplo, seno, tangente, ou qualquer outra func~ao
especial, declarando um procedimento func~ao. A declarac~ao de uma func~ao e id^entica a
de uma sub-rotina, com excec~ao de que e necessario especi car na func~ao os tipos dos
argumentos de entrada e o tipo de retorno ou o tipo da func~ao propriamente dito. Dei-
xaremos os detalhes e exemplos de procedimentos func~ao e mesmo sub-rotina para a sua
implementac~ao em C++.
106 CAPITULO 5. PROGRAMACAO
~ MODULAR
Func~oes recursivas
Existem casos em que um procedimento ou func~ao chama a si proprio. Dizemos ent~ao
que o procedimento ou func~ao e recursivo. Por exemplo, o fatorial de um numero n pode
ser de nido recursivamente, ou seja:

n! = 1n;(se n 1)!; se n  1
n=0
Podemos escrever um algoritmo que implementa essa func~ao de nida recursivamente.
int fat (int)
incio
int n;
se n=0 ent~ao
fat 1;
sen~ao
fat n  fat(n 1);
m
Codi cac~ao em C++
int fat (int n)
{
if (n=0)
fat = 1;
else
fat = n*fat(n-1);
return fat;

O fatorial de 3 sera calculada a partir da chamada a func~ao pelo comando, digamos,

fat (3);
que retornara em fat o valor 6.

Implementac~ao de procedimentos em C++


Inicialmente, observamos que o conceito de procedimento(func~ao ou sub-rotina) em al-
goritmo e implementado em C++ pelo conceito de func~ao. Como numa sub-rotina n~ao
existem os par^ametros de entrada ou de retorno, a linguagem C++ usa o tipo void para
simula-los. Portanto, quando, em C++, os valores de retorno ou de entrada for do tipo
void estamos diante de uma sub-routina.
~
5.2. PROCEDIMENTOS E FUNCOES 107
Em C++, uma ac~ao e designada por uma express~ao. Uma express~ao terminada por
um ponto e vrgula e um comando. Um comando e a menor unidade idenpendente num
programa C++. Em linguagem natural o construto correspondente e a sentenca. Os
seguintes, por exemplo, s~ao comandos em C++.
int valor;
valor = 7 + 1;
cout << valor;

Ao primeiro comando chamamos declarac~ao. Ele de ne uma area de memoria do


computador associada ao nome \valor" de modo que possa conter qualquer valor inteiro.
O segundo comando e um comando de atribuic~ao. Ele coloca na area da memoria do
computador associada com o nome \valor" o resultado da soma de 7 com 1. O terceiro
comando e um comando de sada. cout e o destino da sada associada ao terminal do
usuario. O comando escreve em cout, isto e, no teminal do usuario, o valor armazenado
na area de memoria do computador associada ao nome \valor".
Os comandos est~ao logicamente agrupados em unidades chamadas func~oes. Por exem-
plo, todos os comandos necessarios para ler no arquivo de vendas, no problema da livra-
ria, est~ao organizadas numa func~ao chamada leia(). Do mesmo modo, especi camos uma
func~ao chamada ordene(), uma compacte() e uma imprima().
Em C++ todo programa deve conter uma func~ao chamada main()(principal()), forne-
cida pelo programador, antes do programa ser executado. Aqui esta como a func~ao main
deve ser de nida para o algoritmo das vendas.
void main(void)
{
leia();
ordene();
compacte();
imprima();
}

Um programa C++ comeca executando o primeiro comando de main(). No nosso


caso, o comando comeca executando a func~ao leia(). A execuc~ao do programa continua
sequencialmente executando os comandos dentro de main().
Uma funca~o e constituda de quatro partes: um tipo de retorno, o nome da func~ao,
uma lista de argumentos e o corpo da func~ao. As tr^es primeiras, em grupo, e chamada o
prototipo da func~ao. A lista de argumentos, que deve estar dentro de par^enteses, contem
uma lista de zero ou mais argumentos separados por vrgula. O corpo da func~ao esta dentro
de um par de chaves (f g). Ele consiste de uma sequ^encia de comandos do programa.
No nosso exemplo, o corpo de main() chama para execuc~ao as func~oes leia(), ordene(),
compacte() e imprima().
108 CAPITULO 5. PROGRAMACAO
~ MODULAR
Vejamos, agora, como providenciaremos para que o programa esteja pronto para exe-
cuc~ao. Primeiro devemos fornecer de nic~oes de leia(), ordene(), compacte() e imprima().
Neste ponto apresentaremos os exemplos \mudos" dessas func~oes:
void leia(void)
{
cout << cout << "leia()\n";
}

void ordene(void)
{
cout << "ordene()\n";
}

void compacte(void)
{
cout << "compacte()\n";
}

void imprima(void)
{
cout << "imprima()\n";
}

void e usado para especi car uma func~ao que implementa uma sub-rotina, isto e, que
n~ao fornece um valor de retorno ou n~ao recebe par^ametros de entrada. Cada func~ao,
como foi de nida, simplesmente anunciara sua presenca no terminal do usuario, quando
requisitada por main(). Mais adiante trocaremos essas inst^ancias mudas por de nic~oes
\reais" dessas func~oes, quando elas forem implementadas. Essa maneira passo a passo
de construir programas e o modo seguro de prevenir possveis erros de programac~ao, que
inevitavelmente cometemos. Conseguir que um programa funcione n~ao e uma tarefa t~ao
simples como, a primeira vista, parece.
A identi cac~ao de um arquivo fonte de um programa e constituda de duas partes: o
nome do arquivo e o su xo do arquivo. O su xo variara de acordo com as diferentes
implementac~oes de C++. Para diferenciar um arquivo fonte C++ de C, usaremos o
su xo cp ou cplus, dependendo do sistema operacional.
Considere o seguinte programa completo num arquivo fonte C++:
#include <iostream.h>
~
5.2. PROCEDIMENTOS E FUNCOES 109
{
cout << cout << "leia()\n";
}

void ordene(void)
{
cout << "ordene()\n";
}

void compacte(void)
{
cout << "compacte()\n";
}

void imprima(void)
{
cout << "imprima()\n";
}

void main(void)
{
leia();
ordene();
compacte();
imprima();
}

A palavra \iostream.h" se refere ao arquivo de cabecalho. ele contem informac~oes


sobre cout necessarias ao nosso programa. #include se refere a uma diretiva do pre-
processador. Essa diretiva tem como efeito que o conteudo \iostream.h" seja lido dentro
de nosso arquivo texto. Mais adiante discutiremos com mais detalhes as diretivas do
preprocessador.
Uma vez que o programa esteja constitudo num arquivo, o proximo passo e compila-
lo. O nome do comando usado para chamar o compilador C++ depende do sistema
operacional e, portanto, n~ao o discutiremos aqui. Discutiremos, apenas, o processo de
compilac~ao.
Parte do trabalho do compilador e analizar o texto do programa para dectar possveis
erros. O compilador n~ao pode detectar se o signi cado de um programa esta correto, mas
ele pode dectar erros na forma(errpsde sintaxe) do programa.
Uma outra tarefa do compilador e traduzir formalmente o texto do programa correto.
Esta traduc~ao denominada gerac~ao de codigo, gera objetos ou instruc~oes em linguagem
110 CAPITULO 5. PROGRAMACAO
~ MODULAR
de montagem entendida pelo computador, onde esta sendo executado. O resultado de uma
compilac~ao bem sucedida e um arquivo executavel.
Alem do compilador da linguagem e dos comandos C++, uma implementac~ao forne-
ce um conjunto de bibliotecas padr~ao. As bibliotecas de programas s~ao uma colec~ao de
func~oes precompiladas. Em C++, por exemplo, as entradas e as sadas s~ao suportadas
pela biblioteca padr~ao de C++. Os programadores podem usar func~oes de biblioteca dentro
de seus programas, do mesmo modo que usam func~oes que eles de nem.
Na melhor das hipoteses, uma biblioteca de programas permite a um especialista empa-
cotar seus conhecimentos para serem usados por programadores. Uma boa biblioteca pode
ser t~ao facil e util de usar quanto um interruptor de energia eletrica, que nos permite,
mesmo sem entender profundamente eletricidade, usa-las para os mais diversos ns.
Entrada/sada
As entradas e sadas n~ao fazem parte da linguagem C++, mas s~ao suportadas por uma
biblioteca escrita em C++, conhecida como biblioteca iostream.
As entradas provinientes do terminal do usuario s~ao denominadas entradas padr~ao(standart
input, em ingl^es). Elas s~ao associadas ao objeto de iostream cin. As sadas direcionadas
ao terminal do usuario, denominadas sadas padr~ao, est~ao associdas ao objeto cout.
O operador de sada (<<) e usado para direcionar a sada padr~ao. Por exemplo,
cout << "A soma de 7 + 3 = ";
cout << 7 + 3;
cout << "\n";

A sequ^encia de dois caracteres \nn" representa um caractere de nova linha. Quando


escrito, o caractere de nova linha tem como efeito que a sada seja direcionada a proxima
linha. Em vez de escrever o caractere de nova linha explicitamente podemos aplicar o
manipulador endl, prede nido em iostream. endl insere um caractere de nova linha na
cadeia de sada. Em vez de escrever
cout << "\n";

poderemos escrever
cout << endl;

As sucessivas ocorr^encias do operador de sada podem ser concatenadas. Por exemplo,


cout << "A soma 7 + 3 = " << 7 + 3 << endl;

Cada operador de sada sucessivo e aplicado em cout. Para n~ao perder a legibilidade,
o comando de sada concatenado pode ser distribudo em varias linhas. As tr^es linhas a
seguir constituem um unico comando.
~
5.2. PROCEDIMENTOS E FUNCOES 111
cout << "A soma"
<< v1 << "+"
<< v2 << "= " << v1 + v2 << endl;

Analogamente, o operador de entrada (>>) e usado para ler um valor da entrada


padr~ao. Por exemplo, o seguinte programa implementa um algoritmo para ler dois valores,
determina o maior dos dois e escreve-o
#include <iostream.h>

void leia(int&, int&);


int max(int, int);
void escrevMax(int);

main()
{
int val1, val2, maxValor;

leia(val1,val2);
escrevaMax(maxVal);
}

void leia(int&,int&)
{
cout << "Por favor entre com dois n
umeros: ";
cin >> v1 >> v2;
}

int max(int v1, int v2)


{
if( v1 > v2)
return v1;
else
return v2;
}

void escrevaMax(int val)


{
cout << val
<< "
e o maior valor."
}
112 CAPITULO 5. PROGRAMACAO
~ MODULAR
Faremos algumas observac~oes sobre esse programa. Os nomes das tr^es func~oes fo-
ram listadas antes da de nic~ao de main(). Esta lista inicial, denominada declarac~ao de
prototipo, informa ao programa que essas func~oes existem e suas de nic~oes ocorrem em
algum lugar mais adiante do programa, ou num arquivo de biblioteca ou mesmo num ar-
quivo separado construdo pelo programador. Uma func~ao deve, sempre, ser declarada ao
programa antes de ser chamada. Um prototipo e uma maneira de conseguir isso. val1 e
val2 s~ao denominadas variaveis simbolicas. O comando
int val1, val2;

de ne essas variaveis para o programa. As variaveis tambem devem ser conhecidas do


programa antes dele vir a usa-las.
v1 e v2, designadas por argumentos formais, constituem a lista de argumentos para
leia() e max(). val e o unico argumento formal de escrevaMax().
Quando esse programa for compilado e executado, ele fornece como sada o seguinte,
na hipotese de que usuario entrou com os valores 17 e 124.
Por favor entre com dois n
umeros: 17 124
124 
e o maior valor

Os dois valores fornecidos pelo usuario, 17 e 124, est~ao separados por um brando. Os
brancos, tabs e novas linhas s~ao referidos como espacos em branco em C++. O comando
cin >> v1 >> v2;

l^e, corretamente, os dois valores porque o operador de entrada (\>>" ) desconhece


qualquer espco em branco que ele encontra.
As declarac~oes de cin e cout est~ao no arquivo de biblioteca de C++, iostream.h. Se
o programador esquecer de incluir esse arquivo, cada refer^encia a cin ou cout sera consi-
derado pelo compilador como um erro. O armazenamento de prototipos e o primeiro uso
de arquivos de cabecalho.
O terceiro iostream prede nido, cerr, diz respeito ao erro padr~ao, ligado ao terminal do
usuario. cerr e usado para alertar o usuario de alguma condic~ao excepcional, que ocorre
durante a execuc~ao do programa. Por exemplo, o seguinte fragmento de codigo alerta o
programador para uma tentativa de dividir por zero:
if(v2==0)
{
cerr "erro: tente dividir por zero";
return;
}
v3 = v1/v2;
~
5.2. PROCEDIMENTOS E FUNCOES 113
O seguinte programa l^e, da entrada padr~ao, um caractere de cada vez ate o m-de-
arquivo a ser encontrado. A sua sada e a seguinte:
contaLinha contaCaractere

A sua implementaca~o e a seguinte:

#include <iostream.h>

main()
{
char ch;
int contaLinha = 0, contaChar = 0;

while(cin.get(ch) ){
switch
{
case `\':
case ` ':
break;
case `\':
++contaLinha;
break;
default;
++contaChar;
}
}
cout << contaLinha << " " << endl;
}

get() e uma func~ao em iostream que l^e um caractere de cada vez, colocando esse
caractere lido em seu argumento, no nosso caso ch. A sequ^encia de dois caracteres `nt"
representa o caractere tab.
O comando switch fornece uma forma condicional de testar um valor. Se o valor
casar com um caso explicitado, os comandos seguintes default ser~ao executados. Para
cada caractere nova linha contaLinha e incrementado de um. contaChar e incrementado
de um cada vez que e lido um caractere que n~ao e branco, tab ou novaLinha. O comando
while, denominado laco, prov^e uma repetic~ao da execuc~ao de um conjunto de comandos
desde que a condic~ao seja verdadeira. Neste caso, o comando switch sera executado
enquanto get() l^e um caractere da entrda padr~ao.
114 CAPITULO 5. PROGRAMACAO
~ MODULAR
Uma palavra sobre comentarios
Comentarios servem como uma ajuda ao leitor humano de um programa. Eles podem
resumir o que faz um algoritmo, identi car o proposito de uma variavel, ou esclarecer
um fragmento de codigo obscuro. Os comentarios n~ao aumentam o tamanho do programa
executavel. Eles s~ao retirados pelo compilador antes da gerac~ao de codigo.
Existem dois delimitadores de comentarios em C++. O primeiro deles, o par de
comentarios \/* */", e o mesmo usado em C. O comeco de um comentario e indicado
por \/*". O compilador tratara tudo que estiver entre\/*" e \*/". como comentario. Um
comentario pode ser colocado em qualquer lugar onde seja permitido um tab, um espaco
em branco ou uma nova linha e pode abranger muitas linhas do programa. Por exemplo,
/*
* Este 
e o primeiro contacto com a defini
c~ao de classe em C++.
* Classes s~
ao usadas tanto para abstra
c~
ao de dados como
* para programa
ca
~o orientada a objeto. Uma implementaca
~o
* da classe tela ser
a apresentada num cap
tulo adiante.
*/

Classe tela
{
/* Isto 
e denominado corpo da classe*/
public:
void casa() /* move o cursor para 0,0 */
void refaz() /* redesenha a tela */
private:
/* Classes suportam "encapsulamento de informa c~
ao" */
/* encapsulamento de informac
ao restringe que um programa */
/* tenha acesso a uma representa ca
~o interna de */
/* uma classe(seus dados). Isto  e realizado atrav
es do uso de
/* private:" */
char *cursor; /* posi
c~ao corrente da tela */
}

Existem muitos comentarios entremeados com os codigos do programa, o que pode


obscurecer o proprio codigo. Por exemplo, a declarac~ao de cursor esta quase imperceptvel.
Em geral, e prefervel um bloco de comentarios acima do texto que ele esta explicando.
Pares de comentarios n~ao podem estar aninhados. Isto e, um par de comentarios n~ao
pode ocorrer dentro de um outro par.
O segundo delimitador de comentarios, indicado por uma dupla barra, (\//"), serve
para delimitar uma unica linha de comentarios. Tudo na linha do programa a direita do
delimitador e tratado como um comentario e ignorado pelo cmpilador. Por exemplo,
~
5.2. PROCEDIMENTOS E FUNCOES 115
#include <iostream.h>
#include "meu-io.h"
e
int  Impar(int);

main()
{
int v1, v2; // cont
em valores do usu
ario

leia(v1,v2); // declarado em meu-io.h

e
if( Impar(v1) == 1)
cout << v1
e
<< " Impar \n";
e
if( Impar(v2) == 1)
cout << v2
e
<< " Impar\";
}

e
 Impar(int val)
{
/* retorna 1 se val 
e 
mpar; caso contr
ario 0
/* % 
e o operador de m
odulo: 3%2 resulta 1. */
return val % 2 !=0;
}
Este programa determina se os valores s~ao mpares. Ele reusa a func~ao leia(), de nida
na sec~ao anterior. O prototipo desta func~ao foi armazenado num arquivo de cabecalho,
chamado meu-io.h. Quando o programa for compilado e executado sua sada tem a se-
guinte apar^encia, na hipotes de que o usuario entrou com os valores 498 e -25:
Por favor entre dois valores inteiros: 498 -25
498 
e par
-25 
e 
mpar
Os caracteres de ambos os delomitadores de comentarios n~ao podem ser separados por
espacos em branco. As duas linhas seguintes, por exemplo, n~ao podem ser considerados
como comentarios, mas como um texto do programa:
/* n~
ao 
e um coment
ario: espa
co em branco n~
ao 
e permitido */
// tamb
em n~
ao 
e um coment
ario: deve ser //
Os programas, tipicamente, contem uma mistura de ambos as formas de comentarios.
As explicac~oes multilinhas s~ao, em geral, colocadas entre barras de cmentarios. Metade
de linha e unica linha s~ao, geralmente, comentados por barra dupla.
116 CAPITULO 5. PROGRAMACAO
~ MODULAR
Diretivas do preprocessador
As bibliotecas padr~ao s~ao um conjunto de arquivos de cabecalhos padr~ao, tais como ios-
tream.h. Esses arquivos de cabecalhos contem todas as informac~oes requeridas pelo usuario
de mdo a que ele faca uso da biblioteca. Para poder acessar uma variavel ou uma funca~o
de nida na biblioteca padr~ao, devemos incluir no nosso programa o arquivo de cabecalho
correspondente.
Os arquivos de cabecalho tornam-se parte de nosso programa atraves da diretiva inclu-
de. As diretivas s~ao especi cadas colocando-se o sinal \#" no incio das linhas atraves
das quais queremos incluir, em nosso programa, algum arquivo.
As diretivas s~ao processadas antes que o codigo fonte seja compilado. O programa que
manipula as diretivas e denominado precompilador.
A diretiva de #include l^e o conteudo dos arquivos nomeados. Ela pode ter uma das
seguinte formas:
#include <iostream.h>
#include "meu-io.h"

Se o nome do arquivo esta entre < > presume-se que o arquivo seja de cabecalho
prede nido ou padr~ao. Para pesquisar sua localizac~ao o preprocessador examinara um
conjunto prede nido de localizac~oes.
Se o nome do arquivo esta sob aspas duplas, presume-se que o arquivo de cabecalho
e fornecido pelo usuario. O arquivo includo pode, ele proprio, conter uma diretiva
#include, e isto, em geral, causa problemas. Neste caso s~ao usados diretivas condicionais
para se evitar o multiplo processamento de um arquivo de cabecalho. Por exemplo,
#ifndef STRING_H
#define STRING_H
/* O conte
udo de STRING.H vai aqui */
#endif

A diretiva condicional #ifndef e avaliada como verdadeira se o nome que segue n~ao
esta ainda de nido. Quando uma diretiva condicional for avaliada como verdadeira, as
linhas subsequentes ate um #endif ser encontrada s~ao includas. Se a diretiva condicional
for avaliada falsa, as linhas entre ela e a diretiva #endif s~ao ignoradas.
A diretiva #de ne de ne um nome que segue. No nosso exemplo, ela de ne STRING H.
Se o arquivo de cabecalho string.h for includo novamente a diretiva #ifndef sera avaliada
falso. O conteudo de string.h n~ao sera mais includo. Por exemplo,
#ifdef u3b2
/* c
odigo espec
fico do sistema
* para computaores AT&T 3B vai aqui */
5.3. EXERCICIOS 117
#endif

#ifdef sun3
/* c
odigo espec
fico do sistema
* para a esta
c~
ao de trabalho sun/3 vai aqui */

C++ prede ne o nome -cplusplus. O usuario que desejar misturar codigo de programa
em C com o de C++ deve escrever o seguinte:
#ifdef__cpp
extern min(int, int);
int *pt = novo int;
#else
extern min();
int *pt;
#endif

Os comandos entre a diretiva #else e #endif ser~ao includos se a diretiva #ifdef


ou#ifndef for avaliada falso.

5.3 Exerccios
Viviane vol1 pag 180.
118 CAPITULO 5. PROGRAMACAO
~ MODULAR
Captulo 6
DADOS ESTRUTURADOS
6.1 Introduc~ao
A ci^encia da computac~ao poderia ser considerada como o estudo de algoritmos. Como
ja sabemos, um algoritmo e um conjunto bem determinado de instruc~oes que, quando
seguidas desempenham um papel particular. Existe uma relac~ao bastante proxima entre
a estruturac~ao dos dados e a construc~ao de algoritmos. De fato, a estrutura de dados e
o algoritmo devem ser considerados como unidade, nenhum dos dois faz sentido sem o
outro. Por exemplo, considere uma lista de m pares de nomes e numeros de telefones,
f(n1; t1); (n2; t2); :::; (nm; tm)g, e suponha que pretendemos construir um programa que,
dado o nome da pessoa imprime o numero do telefone dessa pessoa. A tarefa e chamada
de busca. A maneira de como escreveremos esse algoritmo depende de como os nomes e
os numeros dos telefones estiverem armazenados ou estruturados.
Todas as estruturas de dados podem ser razoavelmente construdas dentro de uma
linguagem de programac~ao convencional. A estrutura de dados deve ser projetada de modo
que possamos saber o que ela faz(especi cac~ao) e como ela vai faz^e-lo(implementac~ao).
Uma estrutura de dados descreve o conjunto de operac~oes que podem ser aplicadas
legalmente aos objetos de dados. Por isso deveremos especi car o conjunto de operac~oes
e explicar como elas funcionam. Por exemplo, para o tipo inteiro temos as operac~oes
aritmeticas +, , , = e mod e as relac~oes >, <, , etc. Os objetos de dados numeros
inteiros conjuntamente com a descric~ao de como se comportam as operac~oes e as relac~oes
constituem a de nic~ao da estrutura de dados.
Uma implementac~ao de uma estrutura de dados e um mapeamento que especi ca como
cada objeto sera representado. Assim, os inteiros ser~ao representados pela serie de bits,
os boleanos por zero e um e uma matriz por um conjunto de palavras consecutivas na
memoria.
119
120 CAPITULO 6. DADOS ESTRUTURADOS
6.2 Tipos abstratos de dados
Tipo de dados e o termo que pode ser atribudo aos grupos de dados, que podem ser su-
portados pelas variaveis dentro de uma linguagem de programac~ao. Um tipo abstrato
de dados e uma estrutura de objetos, operac~oes e relac~oes especi cados por um formalis-
mo matematico. Exemplos de tipos abstratos de dados s~ao: booleanos, numeros inteiros,
numeros naturais, numeros reais, numeros complexos, vetores, grafos, arvores, etc. Den-
tro de cada linguagem de programac~ao existe embutida uma colec~ao de tipos de dados.
Isto signi ca que a linguagem permite as variaveis nomear os dados de determinado tipo
e fornecer um conjunto de operac~oes que manipulam essas variaveis.
Alguns tipos de dados s~ao fornecidos de maneira simples, pois ja est~ao embutidos no
conjunto de instruc~oes da maquina do computador ou e includo como um tipo abstrato
pelo usuario. Em outras palavras, para calcular o valor de uma express~ao constituda por
variaveis de tipos de dados embutidos(prede nidas) ou includas pelo usuario(tipo abstra-
do de nido pelo usuario) tudo que precisamos fazer e fornecer a express~ao a ser calculada
ao compilador, sem necessidade, portanto, de construir um programa para calcular essa
express~ao. Para esses tipos de dados tudo se passe como se o computador fosse uma
maquina de calcular. Exemplos de tipos embutidos na maioria das linguagens de progra-
mac~ao s~ao: os numeros inteiros, os naturais, os reais etc. Outros tipos de dados precisam
de um esforco consideravelmente maior para a sua implementac~ao. Em algumas lingua-
gens existem dispositivos que permitem construir as combinac~oes dos tipos embutidos.
E importante observar que a de nic~ao(especi cac~ao) de um tipo abstrato de dados n~ao
nos diz como ele sera implementado numa linguagem de programac~ao.
Desenvolveremos algoritmos e estruturas de dados no contexto de orientac~ao a objeto
usando C++. Por isso projetaremos cada estrutura de dados como um tipo abstrato que
de ne tanto a organizac~ao dos dados quanto as operac~oes que manuseiam esses dados,
assim como as relaco~es entre eles. Essa estrutura, chamada tipo abstrato de da-
dos(TAD), e um modelo abstrato que descreve a interface entre um cliente(o usuario) e
os dados. A linguagem de programac~ao C++ providencia o conceito de classe(class) para
implementar ou representar um TAD e os itens do tipo classe, chamado objetos, para
armazenar e manuzear dados numa aplicac~ao.
A abstraca~o de ne o domnio e a estrutura de dados, assim como uma colec~ao de
operac~oes que acessam esses dados.

Formato de um TAD
Um TAD e constitudo dos seguintes elementos:
 o seu nome;
 uma descrica~o dos tipos de dados;
6.2. TIPOS ABSTRATOS DE DADOS 121
 uma lista de operac~oes;

 uma lista de relac~oes.

Para cada operaca~o(uma relac~ao sera vista como uma operac~ao booleana) deveremos
especi car:

 Os valores de entrada que s~ao fornecidos pelo cliente.

 A precondic~ao que deve ser aplicada aos dados antes que a operac~ao possa ser
efetuada.

 O processo que e efetuado pela operac~ao.

 Os valores de sada que s~ao retornados aos clientes.

 A poscondic~ao que indica qualquer alterac~ao nos dados.

Muitos TAD's tem uma operac~ao de inicializac~ao, o inicializador que atribui valores
iniciais aos dados. No ambiente C++, o inicializador e chamado um construtor.
Assim um TAD tem o seguinte formato:
122 CAPITULO 6. DADOS ESTRUTURADOS
TAD nomeDoTAD
Dados
Descreve a estrutura dos dados
Operaco~es
Construtor
Valores iniciais: Dados usados para inicializar os objetos.
Processo: Inicializa os objetos.
Operaca~o1
Entrada: Dados do cliente.
Precondic~oes: O estado necessario do sistema antes de executar.
a operac~ao.
Processo: Ac~oes efetuadas sobre os dados.
Sada: Dados retornados pelo cliente.
Poscondic~ao: O estado do sistema apos executar a operac~ao.
Operaca~o2
Operaca~o3
.
.
.
Operaca~oN
m nomeDoTAD

6.3 Tipos de dados basicos


A seguir, por quest~ao de completude, introduziremos uma serie de tipos de dados basicos
que incluem os numeros, os caracteres, tipos enumerados de nidos pelo usuario e pon-
teiros. Estes tipos est~ao embutidos na maioria das linguagens de programac~ao. Cada
tipo de dados basico inclui dados e operac~oes, os componentes de um tipo abstrato de
dados(TAD). As linguagens de programac~ao implementam TAD's no computador usando
diferentes representac~oes para os dados, incluindo numeros binarios e o conjunto de carac-
teres ASCII. Continuaremos usando a linguagem de programac~ao C++ para implementar
os TAD's.
Os tipos numeros, caracteres e ponteiros descrevem dados simples porque os objetos
desses tipos n~ao podem ser divididos em partes mais simples. Por outro lado, os tipos de
dados estruturados tem componentes que s~ao construdos de tipos simples com regras para
de nir relac~oes entre suas componentes. Dentre os tipos estruturados est~ao as matrizes1,
1 Alguns autores chamam esses tipos de vetores. Usaremos sem nenhuma mens~ao explcita qualquer

6.3. TIPOS DE DADOS BASICOS 123
strings(cadeias), registros(ou estruturas, como eles s~ao denominados em C++), arquivos,
listas, pilhas, las, arvores, grafos e tabelas. Estudaremos os tr^es primeiros, deixandos
os demais para o proximo curso denominado \Algoritmo e estruturas de dados". Muitas
linguagens de programac~ao providenciam construtos ou biblioteca de func~oes para mani-
pular matrizes, strings, registros, arquivos. 2 Como tal, chamaremos esses tipos de dados
estruturados de tipos embutidos. Providenciaremos tipos de dados abstratos para esses
tipos estruturados embutidos e discutiremos suas implementac~oes em C++.

Tipos inteiros
Os inteiros positivos ou negativos consistem de um sinal e uma sequ^encia de dgitos. Aos
inteiros nos referiremos como numeros com sinal. Por exemplo, o que segue s~ao exemplos
de valores inteiros espec cos chamados constantes inteiras:

+35; 278; 19(o sinal e +); 28976510


Quem estiver familiarizado com a aritmetica elementar sabe que podemos de nir uma
serie de operadores que resultam em novos valores inteiros. Operadores que recebem ou
um simples operando(operadores unarios) ou dois operandos(operadores binarios) criam
express~oes inteiras:
(Unario +) +35 = 35 (subtrac~ao -) 73 - 50 = 23
(Adic~ao +)4 + 6 = 10 (Multiplicac~ao *) -3*7 = -21
As express~oes inteiras podem ser usadas com os operadores relacionais da aritmetica
para produzir um resultado que seja verdadeiro ou falso.
(Menor do que relacional) 5<7 (verdade)
(Maior do que ou igaul relacional) 10>=18 (falso)
Teoricamente, os inteiros n~ao possuem limites de tamanho, um fato que esta re etido
na de nic~ao do TAD.
Os TAD's que providenciaremos para os tipos primitivos assumem que o aluno esteja
familiarizado com as precondic~oes, a entrada e as poscondic~oes para cada operac~ao. Por
exemplo, uma especi cac~ao da divis~ao inteira e:
Divis~
ao inteira
Entrada: Dois valores inteiros u e v.
Precondi
c~
oes: O denominador v n~
ao pode ser 0.

um desses dois nomes.


2 Mais recentemente, a partir de 1998, a linguagem C++ est
a providenciando classes abstratas ate
para essas outras estruturas de dados.
124 CAPITULO 6. DADOS ESTRUTURADOS
Processo: Divide u por v, usando a divis~
ao inteira.
Sada: O valor do quociente.
P
oscondi
c~
oes: Vai existir uma condi
c~
ao de erro se v=0.

Em nossas especi caco~es, usaremos a notac~ao de operadores de C++ em lugar de


nomes de operac~oes genericas e tambem somente descreveremos processo.
O TAd inteiro 
e

Dado
Um n
umero inteiro N com sinal.
Opera
c~oes
Assuma que u e v s~ao express~
oes inteiras, e N 
e
uma variavel inteira.

Atribui
ca~o
= N = u Atribui o valor da express~
ao u 
a vari
avel N.

Operadores aritm
eticos bin
arios
+ u + v Adiciona dois valores inteiros.
- u - v Subtrai dois valores inteiros.
* u * v Multiplica dois valores inteiros.
/ u / v Computa o quociente usando divis~
ao inteira.
% u % v Computa o resto usando divis~
ao inteira.

Operadores aritm
eticos un
arios
- -u Troca o sinal (Menos un
ario).
+ +u +u 
e o mesmo que u (Mais un
ario).

Operadores relacionais
(A express~
ao relacional 
e verdadeira sob a condi
c~
ao
dada.)
== u == v Resulta verdadeiro se u e igual a v.
!= u != v Resulta verdadeiro se u n~ao for igual a v.
< u < v Resulta verdadeiro se u for menor que v.
<= u <= v Resulta verdadeiro se u for menor ou igual
a v.
> u > v Resulta verdadeiro se u for maior que v.
>= u >= v Resulta verdadeiro se u for maior ou igual
a v.

fim TAD inteiro.



6.3. TIPOS DE DADOS BASICOS 125
Exemplo 32 3 + 2 (A express~
ao tem valor 5)
val = 25 / 20 (val = 1)
resto = 25 % 20 (resto = 5)

Armazenamento dos inteiros no computador


A implementac~ao dos inteiros e providenciada pelas declarac~oes de tipo numa linguagem
de programac~ao e o hardware do computador. Os sistemas de computac~ao armazenam os
inteiros em blocos de memoria de tamanho xo. O domnio de valores resultante pertence
a um intervalo nito. O tamanho do bloco de armazenamento e o intervalo de valores
dependem da implementac~ao. Para conseguir certa padronizac~ao, as linguagens de pro-
gramac~ao fornecem tipos de dados primitivos embutidos para os inteiros pequenos(short) e
grandes(long). Quando s~ao necessarios valores inteiros muito grande, uma aplicac~ao de-
ve fornecer uma biblioteca de subprogramas para efetuar essas operac~oes. Uma biblioteca
de operac~oes sobre os inteiros pode estender a implementac~ao dos inteiros para qualquer
tamanho, embora usualmente as rotinas diminuam a e ci^encia de execuc~ao de uma apli-
cac~ao.
Num computador, os inteiros s~ao armazenados como numeros binarios, que consis-
tem de diferentes sequ^encias dos dgitos 0 e 1. A representac~ao e modelada na base 10
ou sistema decimal, que usa os dgitos 0, 1, 2, ..., 9. Um numero decimal e armazenadoo
como um conjunto de dgitos d0 ; d1; d2 ; etc., representando as pot^encias de dez. Por
exemplo, o numero de k dgitos

N = dk dk :::d d ; para 0  di  9
10 1 2 1 0

representa

N = dk (10k ) + dk (10k ) + ::: + di(10i ) + ::: + d (10 ) + d (10 )


10 1
1
2
2
1
1
0
0

O ndice 10 indica que N esta escrito como um numero decimal. Por exemplo, o
numero inteiro de 4-dgito 2589 representa
2589 = 2(10 ) + 5(10 ) + 8(10 ) + 9(10 ) = 2(1000) + 5(100) + 8(10) + 9
10
3 2 1 0

Os inteiros binarios usam os dgitos 0 e 1 e as pot^encias de 2(2 = 1; 2 = 2; 2 =


0 1 2

4; 2 = 8; 2 = 16; etc.). Por exemplo, 13 tem a representac~ao binaria


3 4
10

13 = 1(2 ) + 1(2 ) + 0(2 ) + 1(2 ) = 1101


10
3 2 1 0
2

Um dgito binario e chamado um bit. Em geral, um numero binario com k dgito ou


k bit tem a representac~ao
126 CAPITULO 6. DADOS ESTRUTURADOS
0 0 1 0 0 0 1 1

Figura 6.1: O numero 35 como um byte

N = bk bk :::bi:::b b = bk (2k ) + bk (2k ) + ::: + bi(2i ) + ::: + b (2 ) +


2 1 2 1 0 1
1
2
2
1
1

b (2 ); 0  bi  1
0
0

O seguinte numero de 6-bit e a representac~ao binaria de 42. O valor decimal de um


numero binario e computado adicionando os termos na soma:
101010 = 1(2 ) + 0(2 ) + 1(2 ) + 0(2 ) + 1(2 ) + 0(2 ) = 42
2
5 4 3 2 1 0
10

Exemplo 33 Calcular o valor decimal do numero binario:


1. 1101012 = 1(25 ) + 1(24) + 0(23 ) + 0(21 ) + 1(22 ) + 1(20 ) = 5310
2. 100001102 = 1(27 ) + 1(22) + 1(21) = 13410
A convers~ao de um numero decimal a seu equivalente binario pode ser feito achando
a maior pot^encia de 2 que seja menor ou igual ao numero. A progress~ao das pot^encias de
2 s~ao 1, 2, 4, 8, 16, 32, 64, etc. Isto fornece o dgito principal na representac~ao binaria.
Preenchendo o resto das pot^encias de 2 com 0. Por exemplo, considere o valor 35. A
maior pot^encia de 2 que e menor que 35 e 32 = 25, o que implica que 35 e um numero
binario de 6 dgitos:

35 = 1(32) + 0(16) + 0(4) + 1(2) + 1 = 100011


10 2

Os numeros binarios puros s~ao simplesmente a soma das pot^encias de 2. Eles n~ao
possuem sinal e s~ao designados por numeros sem sinal(unsigned). Os numeros repre-
sentam inteiros positivos. Os inteiros negativos usam a representac~ao do complemento de
dois ou a magnitude de sinal. Em qualquer um desses formatos, um bit especial, chamado
bit de sinal, indica o sinal do numero.
Dados na memoria
Os numeros s~ao armazenados na memoria como sequ^encias de dgitos binarios de com-
primento xo. Dentre os comprimento mais comuns est~ao 8, 16 e 32 bits. Uma sequ^encia
de 8 bits e chamada um byte.
A tabela 6.1 fornece o intervalo dos numeros com sinal e sem sinal para os tamanhos
mais comuns.

6.3. TIPOS DE DADOS BASICOS 127
Tamanho intervalo dos numeros sem sinal intervalo dos numeros com sinal
8(1 byte) 0 a 255 = 2 1
8
2 = 128 a 127 = 2 1
7 7

16(2 bytes) 0 a 65.535=2 1 16


2 = 32768 a 32767 = 2 1
15 15

32(4 bytes) 0 a 4.294.967.295=2 132


2 a2 1
31 31

Tabela 6.1: Intervalos dos numeros e tamanho dos bits


01010111 00000001 11110100
enderecos 0 1 2 3 4 5

Figura 6.2: Uma vista da memoria

A memoria do computador e uma sequ^encia de bytes referenciada pelos enderecos 0, 1,


2, 3, 4 e assim por diante. Na memoria, o endereco do inteiros e a localizac~ao do pri-
meiro byte da sequ^ecia. A gura 6.4 ilustra uma vista da memoria com o numero 87710 =
10101112 armazenado em um byte no endereco 3, e o numero 50010 = 00000001111101002
na memoria de endereco 4.

Representac~ao de inteiros em C++


Os tipos inteiros em C++ s~ao int, short int e long int. O tipo short int(short) fornece
um valor inteiro de 16-bits no intervalo -32768 a 32767. O tipo long int(long) fornece
o maior intervalo de valores inteiros e na maioria dos sistemas e implementado com 32
bits(4 bytes), com um intervalo de 231 a 231 1.
O tipo int, em geral, identi ca os inteiros e s~ao dependentes da maquina e do com-
pilador. Tipicamente, os compiladores usam inteiros de 16-bits ou 32-bits. Em alguns
casos, o usuario pode selecionar o tamanho do inteiro como uma opc~ao. Os tipos de
dados inteiros especi cam um domnio de valores de dados e um conjunto de operadores
aritmeticos e relacionais. Cada tipo de dados fornece uma implementac~ao do TAD inteiro
com a restrica~o de que os valores inteiros estejam no intervalo nito.

Tipos de caracteres
Os tipos de dados caracteres incluem itens alfanumericos que de nem as letras minusculas
e maiusculas, dgitos, sinais de pontuac~ao e alguns smbolos especiais. A industrias de
computadores usam representac~oes diferentes de caracteres nas aplicac~oes. O conjunto
de caracteres com 128 elementos na tabela ASCII tem a mais ampla aplicac~ao no pro-
cessamente de palavras, entrada e sada de textos e comunicac~ao de dados. Usaremos o
conjunto ASCII para nosso TAD de caracteres. Assim como os inteiros, os caracteres
ASCII contem uma relac~ao de ordem que de ne uma serie de operadores relacionais. Pa-
ra os caracteres alfanumericos, as letras seguem a ordem do dicionario. Nesta relac~ao,
128 CAPITULO 6. DADOS ESTRUTURADOS
todas as letras maiusculas s~ao menores que as letras minusculas:

T < W; b < d; T < b


O TAD caracteres 
e

Dados
O conjunto de caracteres da tabela ASCII.

Opera
c~oes
Atribui ca
~o
Um valor de caractere pode ser atribu
do a uma vari
avel
de caractere.

Relacional
Os seis operadores relacionais padr~
ao se aplicam a caracteres
usando a rela
ca
~o de ordem do dicion
ario da tabela ASCII.

fim TAD caracteres

Os caracteres ASCII
A maioria dos sistemas de computadores usam o esquema de codigo padr~ao ASCII para
a representaca~o de caracteres. Os caracteres ASCII s~ao armazenados como um codigo de
inteiros de 7-bits em um numero de 8-bits. Os 27 = 128 codigos diferentes s~ao divididos
em 95 caracteres imprimveis e 33 caracteres de controles. Um caractere de controle e
usado em comunicac~ao de dados e faz com que um dispositivo forneca uma func~ao de
controle, como o movimento de um cursor para cima e para baixo na tela do monitor.
A tabela 6.3 mostra o conjunto de caracteres imprimveis ASCII. O caractere branco
e representado por }. O codigo decimal para cada caractere e dado com os dez dgitos
nas linhas e um dgito nas colunas. Por exemplo, O caractere `T' tem valor ASCII 8410
e e armazenado em binario como 010101002 .
Dentro do conjunto de caracteres ASCII, os dgitos decimais e os caracteres alfabeticos
caem dentro de um intervalo bem de nido(tabela 6.2). Isto facilita a convers~ao entre
letras maiusculas e minusculas e de um dgito ASCII(`0', `1', ..., `9') ao numero corres-
pondente(0, 1, ..., 9).
Exemplo 34 Os valores ASCII para os dgitos '0` e 48. Os dgitos s~ao
ordenados no intervalo de 48 a 57:
Dgito ASCII: `3' e 51(48 + 3)

6.3. TIPOS DE DADOS BASICOS 129

Dgitos da direita
Dgitos da esquerda 0 1 2 3 4 5 6 7 8 9
3 } ! " # $ % & 0
4 ( )  + ` : = 0 1
5 2 3 4 5 6 7 8 9 : ;
6 < = > ? @ A B C D E
7 F G H I J K L M N O
8 P Q R S T U V W X Y
9 Z [ n ] ^ ` a b c
10 d e f g h i j k l m
11 n o p q r s t u v w
12 x y z f j g
Figura 6.3: Conjunto de caracteres ASCII imprimveis

Caracteres Decimal Binario


Espaco em branco 32 00100000
dgitos decimais 48-57 00110000-00111001
Letras maiusculas 65-90 00110000-00111001
Letras minusculas 97-122 01100001-01111010
Tabela 6.2: Intervalo dos caracteres ASCII
130 CAPITULO 6. DADOS ESTRUTURADOS
Os dgitos numericos correspondentes e obtido subtraindo `0'(48 ASCII):
Dgito numerico: 3 = `3' - `0' = 51 = 48
Para converter um caractere de minuscula para maiusculas, adicione 32
ao valor ASCII do caracterre:
ASCII(`A')=65 ASCII(`a') = 65 + 32 = 97
Em C++, o tipo primito char e usado para armazenar um caractere. Os codigos
ASCII est~ao no intervalo 0-127: entretanto, encontramos, com frequ^encia, dependentes-
do-sistema, caracteres estendidos de nidos para usar o resto dos valores no intervalo.
Como um tipo de dados inteiros, o valor e o codigo para o caractere.

Tipos de dados reais


Os tipos inteiros, que nos referimos como tipos discretos, representam valores de dados
que podem ser contados, por exemplo, -2, -1, 0, 1, 2, 3, e assim por diante. Muitas apli-
cac~oes requerem numeros que tem valores fracionarios. Esses valores, chamados numeros
reais, podem ser representados num formato de ponto xo com uma parte inteira e uma
parte fracionaria:

9; 6789 6; 245 + 18; 23


Os numeros reais podem ser escritos como numeros em ponto utuante em notac~ao
cient ca. Este formato representa os numeros como uma serie de dgitos chamados a
mantissa e o expoente, que representam uma pot^encia de 10. Por exemplo, 6,02 e 23
tem uma mantissa de 6,02 e um expoente de 23. Um numero de ponto xo e exatamente
um caso particular de um numero em ponto utuante com um expoente 0. Exatamente
como para os inteiros e os caracteres, os numeros reais constituem um tipo abstrato de
dados. A aritmetica padr~ao e as operac~oes racionais se aplicam com a divis~ao real usada
no lugar da divis~ao inteira.
1. O TAD real 
e

Dados
N
umeros descritos com o formato ponto-fixo ou ponto flutuante.

Opera
c~oes
Atribui co
~es
Uma express~ao real pode ser atribu
da a uma vari
avel real.

6.3. TIPOS DE DADOS BASICOS 131

Operadores aritmeticos
As opera
co~es aritm
eticas padr~
ao un
aria e bin
arias se aplicam
com a divis~ao real usada no lugar da divis~
ao inteira. N~
ao existe
operador de resto.

Operadores relacionais
Os seis operadores relacionais padr~
ao se aplicam aos n
umeros reais.

fim TAD real

Representac~ao dos numeros reais


Exatamente como os inteiros, o domnio dos numeros reais n~ao tem limite. Os valores dos
numeros s~ao ilimitados nas direc~oes negativas e positivas. A parte fracionaria aplica os
numeros reais sobre o contnuo de pontos numa linha reta. Os numeros reais s~ao imple-
mentados num bloco de armazenamento nito que limita o escopo dos valores, formando
pontos discretos numa reta.
Durante muitos anos, os pesquisadores de computadores tem usado varios tipos de
formatos para armazenar os numeros em ponto utuantes. O formato IEEE(Institute
of Electrical and Eletronics Engineers) e um padr~ao muito usado. Os numeros reais no
formato em ponto- xo s~ao separados numa parte inteira e numa parte fracionaria cujos
dgitos s~ao multiplicados por 101 , 100
1
, 1000
1
, e assim por diante. Uma vrgula decimal
separam as partes:

25; 638 = 2(10 ) + 5(10 ) + 6(10 ) + 3(10 ) + 8(10 )


1 0 1 2 3

Assim como para os numeros inteiros, existem representac~oes binarias correspondentes


para os numeros reais de ponto xo. Essses numeros contem uma parte inteira, uma parte
de frac~ao binaria e uma vrgula binaria, com os dgitos fracionarios correspondentes a 12 ,
1
, 1 , e assim por diante. A forma geral para tal representac~ao e
4 8

N = bn:::b :b b ::: = bn2n + ::: + b 2 + b 2 + b 2 + :::


0 1 2 0
0
1
1
2
2

Por exemplo,
10111; 11012 = 1(23 ) + 1(21) + 1(20) + 1(2 1 ) + 1(2 2 ) + 1(2 4 ) = 8 + 2 + 1 + 0; 5 +
0; 25 + 0; 0625 = 11; 812510
A convers~ao de numeros decimais para numeros binarios em ponto utuante usa algo-
ritmos analogos aqueles desenvolvidos para numeros inteiros. A convers~ao para numeros
decimais e realizada adicionando os produtos dos dgitos e as pot^encias de 10. O processo
132 CAPITULO 6. DADOS ESTRUTURADOS
inverso e mais complexo, pois os numeros podem precisar de uma representac~ao binaria
in nita para criar o numero em ponto utuante equivalente. No computador, o numero de
dgitos e limitado pois somente s~ao usados numeros em ponto utuante de comprimento
xo.
Exemplo 35 Converter um numero binario em ponto xo para decimal:
1. 0; 011012 = 14 + 18 + 321 = 0; 25 + 0; 125 + 0; 03125 = 0; 4062510
Converter o numero decimal para um numero binario em ponto utuant.
2. 4; 312510 = 4 + 0; 25 + 0; 0625 = 100; 01012
3. O numero decimal 0,15 n~ao tem uma frac~ao binaria de compriemento
xo equivalente. A convers~ao de um decimal para uma frac~ao binaria
requer uma expanc~ao in nita binaria. Pelo fato do armazenamento do
computador ser restrito a numeros de comprimento xo, a cauda da ex-
panc~ao in nita e uma soma parcial nita que e uma aproximac~ao do
valor decimal:

10
1 + 1 + 1 + ::: = 0; 0010011001:::
0; 15 = 81 + 64 128 1024
Muitos computadores armazenam numeros reais na forma binaria usando notac~ao
cient ca, com um sinal, mantissa e expoente:

N = +Dn Dn :::D D ; d d :::dn  2e


1 1 0 1 2

C++ suporta tr^es tipos de dados reais, oat, double, e double long. O tipo double
long esta disponvel para calculos que requerem alta precis~ao e n~ao usaremos em nossas
notas. Com frequ^encia, o tipo oat e implementado usando o formato IEEE de ponto
utuante de 32-bits, enquanto o formato de 64-bits e usado para o tipo double.

Tipos enumerados
O conjunto de caracteres ASCII usa uma representac~ao inteira dos dados caracteres.
Uma representac~ao similar pode ser usada para descrever conjuntos de dados de nidos
pelo programador. Por exemplo, o que segue e uma listas dos mezes de 30 dias:

abril; junho; setembro; novembro


O conjunto dos meses forma um tipo de dados enumerado. Para cada tipo, a
ordem dos itens e determinado pela maneira como os itens s~ao listados. Por exemplo,

6.3. TIPOS DE DADOS BASICOS 133
Cor do cabelo

preto // primeiro valor


loiro // segundo valor
castanho // terceiro valor
fogo // quarto valor

preto loiro castanho fogo


O tipo suporta uma operaca~o de atribuic~ao e os operadores relacionais padr~ao.
Por exemplo,
preto<fogo // preto ocorre antes de fogo
castanho>=loiro // castanho ocorre apos loiro
Um tipo enumerado tem dados e operadores e portanto constitui um TAD.
o TAD enumerado 
e

Dados
Lista de N itens distintos definidos pelo usu
ario.

Opera
c~oes
Atribuic~
ao
Qualquer item da lista pode ser atribu
do a uma vari
avel
do tipo enumerado.

Operadores relacionais
Os seis operadores relacionais usam a rela
c~
ao de ordem determinada
pelos itens que s~
ao listadas.

fim do TAD enumerado

Implementac~ao em C++ do tipo enumerado


C++ tem um tipo enumerado que de ne valores inteiros distintos referenciados pelas
constantes nomeadas.
Exemplo 36 O tipo booleano pode ser declarado como um tipo enume-
rado. O valor da constante falsa e 0, e o valor de verdadeiro e 1. A
variavel pronto e de nida como booleana com valor inicial falsa.
enum booleana {falsa, verdadeira};

booleana pronto = falsa;


134 CAPITULO 6. DADOS ESTRUTURADOS
char=`A' short int = 25
5000 5000 5001
(a) (b)

Figura 6.4: Tipo de dados ponteiro

Os meses do ano s~ao declarados como um tipo enumerado. Por con-


venc~ao, o valor inicial de janeiro e 0. Entretanto, a sequ^encia inteira
pode comecar num outro valor, contanto que se atribua esse valor ao pri-
meiro item. Neste caso, jan e 1 e os meses correspondem a sequ^encia 1,
2, ..., 12.
1. enum mes {jan=1, fev, mar, abril, maio, jun, jul, aug, set, out, nov, dez}

mes = dec;

Ponteiros
O tipo de dados ponteiro e fundamental em qualquer linguagem de programac~ao. Um
ponteiro e um inteiro sem sinal que representa um endereco de memoria. O ponteiro
tambem serve como uma refer^encia aos dados no endereco. No endereco do ponteiro, o
tipo do dado e chamado um tipo base e e usada na de nic~ao do ponteiro. Por exemplo,
descrevemos um ponteiro para um caractere, um ponteiro para um inteiro, e assim por
diante. Por exemplo, o ponteiro ptr tem valor 500 em cada um dos casos da gura 6.4.
Entretanto, em (a) o ponteiro referencia um caractere e em (b) o ponteiro referencia um
inteiro short.
Um ponteiro possibilita um acesso e ciente aos itens numa lista e e fundamental no
desenvolvimento de estruturas de dados din^amicas tais com listas encadeadas, arvores e
grafos.

O TAD ponteiro
Exatamente como um numero, um ponteiroo faz uso de certos operadores aritmeticos e
relacionais. As operac~oes aritmeticas requerem atenc~ao especial. Um ponteiro pode ser
incrementado ou decrementado por um valor inteiro para referenciar um novo dado na
memoria. Adicionando 1 atualiza o ponteiro para referenciar o proximo item daquela tipo
na memoria. Por exemplo, se ptr aponta para um objeto caractere, ptr + 1 aponta para o
proximo byte na memoria. Adicionar k > 0 tem como efeito mover o ponteiro k posic~oes
de dados para a direita. Por exemplo, se ptr aponta para um double, ptr + k referencia o
double:

6.3. TIPOS DE DADOS BASICOS 135

N = sizeof (double)  k bytes a direita de p


Tipo de dados Endereco corrente Novo endereco
char p = 5000 p + 1 = 5001
int (2 bytes) p = 5000 p + 3 = 5000 + 3*2 = 5006
double (4 bytes) p = 5000 p - 6 = 5000 -6*4 = 4976
Um ponteiro usa o operador de endereco \&" que retorna o endereco na memoria de
um item de dado. Inversamente, o operador \*" referencia o dado associado ao valor de
ponteiro. Os ponteiros s~ao ordenados comparando seus valores inteiros sem sinal.
A memoria din^amica e uma nova memoria alocada durante a execuc~ao de um pro-
grama. A memoria din^amica difere da memoria estatica cuja exist^encia e determina-
da a priori para comecar a execuc~ao do programa. Discutiremos a memoria din^amica
num curso de estruturas de dados. O operador new aceita um tipo t, aloca memoria
din^amicamente para um item do tipo t e retorna um ponteiro para a memoria alocada por
ele. O operador delete recebe um ponteiro como par^ametro e destroi a memoria din^amica
alocada previamente naquele endereco.
O TAD ponteiro 
e

Dados
O conjunto de inteiros sem sinal que representam um endere
co
de mem
oria para um item de dado do tipo b
asico t.

Opera
c~oes
Assuma que u e v s~
ao express~
oes de ponteiros, i e
 uma express~
ao
inteira, ptr 
e uma vari
avel de ponteiro, e var e uma vari
avel do tipo t.

Endere
co
& ptr = &var Atribui o endere
co de var a ptr.

Atribui
ca~o
= ptr = u Atribui o valor de ponteiro u a ptr.

Defer^
encia
* var = *ptr Atribui o item do tipo t referenciado por
ptr 
a vari
avel var.

Aloca
c~ao de Mem
oria Din^
amica e Desaloca
ca
~o
136 CAPITULO 6. DADOS ESTRUTURADOS
new ptr = new t Cria mem
oria din^
amica para um item do tipo
t e atribui seu endere
co a ptr.

delete delete ptr Destroi a mem


oria din^
amica alocada no endere
co
ptr.

Aritm
etica
+ u + i Aponta para o item localizado i itens de dados
a direita do item referenciado por u.

- u - i Aponta para o item localizado i itens de dados
a esquerda do item refenciado por u.

- u - v Retorna o n
umero de elementos do tipo base que
est
a entre os dois ponteiros.

Operadores relacionais
Os seis operadores relacionais padr~
ao se aplicam a ponteiros comparando
valores inteiros sem sinal.

fim do TAD ponteiro

Valores de ponteiros
Um valor de ponteiro e um endereco de memoria que usa 16, 32 ou mais bits, dependendo
da arquitetura da maquina. Como um exemplo, seja ptr1 um ponteiro para char(1 byte)
e ptr2 um ponteiro para um int short(2 bytes).
char str[] = "ABCDEFG";
char *ptr1 = str; // ptr1 aponta para str

short x = 33;
short *ptr2 = &x; // ptr2 aponta para short x

Os comandos que seguem ilustram as operac~oes fundamentais sobre ponteiros.


cout << *ptr1 << endl; // imprime 'A'
ptr1+ = 4; // move ptr para a direita 4 caracteres

cout << *ptr1 << endl; // imprime 'E'


ptr1--; // move ptr1 
a esquerda 1 caractere

cout << *ptr1 << endl; // imprime 'D'


cout << *ptr2 + 3 << endl;// imprime 36 = 33 + 3
6.4. O TIPO MATRIZ 137
As operac~oes de ponteiro new e delete ser~ao discutidos nas notas de curso de estruturas
de dados.

6.4 O tipo matriz


Uma matriz e um exemplo de uma colec~ao de dados. Uma matriz unidimensional e
uma lista sequencial nita de elementos do mesmo tipo de dados(matriz homog^enea).
A sequ^encia identi ca o primeiro elemento, o segundo elemento, o terceiro elemento, e
assim por diante. A cada elemento esta associado um ndice que identi ca a posic~ao
do elemento na lista. Uma matriz tem um operador de ndice que possibilita um acesso
direto aos elementos na lista para armazenar ou recuperar um item.

a a a a
0 1 2 3

O TAD matriz 
e

Dados
Uma colec~
ao de N itens do mesmo tipo de dados. Os 
ndices s~
ao
escolhidos no domnio de inteiros de 0 a N - 1, que identificam
a posi
c~ao de um item na lista e permitem acesso direto aos elementos.
O 
ndice 0 referencia o primeiro item na lista, o ndice 1 referencia o
segundo item, e assim por diante.

Opera
c~oes

Indice [ ]
Entrada: O 
ndice
Precondico
~es: O 
ndice esta no domnio de 0 a N - 1.
Processo: No lado direito de um comando de atribui c~
ao, o operador
de ndice recupera dados do item. No lado esquerdo de um
comando de atribui c~
ao, o operador de 
ndice retorna o endere
c
do elemento da matriz que armazena o lado direito da express~ a
Sa
da: Se o operador de ndice estiver no lado direito de um comando
atribuic~
ao, a operac~
ao recupera dados da matriz e retorna os d
ao cliente.
P
oscondi
ca~o: Se a operac~
ao de 
ndice estiver no lado esquerdo, o item da ma
sera alterado.

fim do TAD matriz.


138 CAPITULO 6. DADOS ESTRUTURADOS
O tipo matriz embutido em C++
Como parte de sua sintaxe basica, C++ providencia um tipo matriz estatica embutida
que de ne uma lista de itens do mesmo tipo. A declarac~ao fornece explicitamente o
tamanho constante N da matriz e especi ca que os ndices est~ao no intervalo de 0 a
N 1. A declaraca~o no exemplo 37, a seguir de ne uma matriz estatica em C++.
Usando ponteiros, criaremos mais adiante, no curso de estruturas de dados, matrizes
din^amicas.
Exemplo 37 1. Declara duas matrizes do tipo double. A matriz x tem 50
itens e a matriz y tem 200 itens:
double x[50], y[200];

2. Declara a matriz a long com tamanho de nida pela constante inteira


tamDaMatriz = 10.
const int tamDaMatriz = 10;
long a[tamDaMatriz];

O ndice da matriz, no intervalo de 0 a tamDaMatriz - 1, e usada para acessar os


elementos individuais da matriz. Um elemento no ndice i e representado por a[i].
O ndice da matriz em C++ e realizado usando o operador de ndice([ ]). Ele e um
operador binario cujo operando esquerdo e o nome da matriz e o operando da direita e a
posic~ao do elemento na matriz. Os elementos na matriz podem ser acessados em ambos
os lados de um operador de atribuic~ao:
a[i] = x; // atribui(armazena) x como dado ao elemento da matriz
t = a[i]; // recupera o dado de a[i] e o atribui a variavel t
a[i] = a[i+1] = x;
// atribui x a a[i+1]. Uma segunda atribui
c~
ao armazena os
os dados de a[i+1] em a[i]

Armazenamento numa matriz unidimensional


Uma matriz unidimensional em C++ a e logicamente armazenada como uma sequ^encia
consecutiva de itens na memoria. Cada item e do mesmo tipo de dado.
a[0] .... a[i]
" "
endereco a[0] endereco a[i]
Em C++, um nome de uma matriz e uma constante e e considerada como sendo o
endereco do primeiro elemento da matriz. Portanto, na declarac~ao
6.4. O TIPO MATRIZ 139
tipo a[tamDaMatriz];

o nome, a, da matriz e uma constante e e a localizac~ao do primeiro elemento a[0].


Os lementos a[1], a[2], e assim por diante seguem consecutivamente. Assumindo que
sizeof(tipo) = M, a matriz toda, a, ocupa M*tamDaMatriz bytes.
a[0] a[1] a[2] a[3]
O compilador usa uma tabela para manter um registro das caractersticas da matriz.
Essa tabela inclui a informac~ao do tamanho de cada item, o endereco de incio da matriz
e o numero de elementos na matriz:
Endereco de incio: a
Numero de elementos da matriz: tamDaMatriz
Tamanho do tipo: M = sizeof(tipo)
A tabela e usada tambem pelo compilador para implementar uma func~ao de aces-
so que identi ca o endereco de um item na memoria. A func~ao acessoDaMatriz usa o
endereco de incio da matriz e o tamanho do tipo de dado para mapear um ndice i no
endereco de a[i]:
endere
co a[i] = acessoDaMatriz[(a, i, M)]

acessoDaMatriz e dada por


acessoDaMatriz(a, i, M) = a + i*M;

Exemplo 38 Assuma que oat e armazenado usando 4 bytes(sizeof( oat)=4)


e a altura da matriz comeca na localizac~ao de memoria 20000.
float altura[35];

o elemento altura[18] da matriz esta localizado no endereco

20000 + 18  4 = 20072
Limites da matriz
O TAD matriz assume que os ndices est~ao no intervalo de 0 a N - 1, onde N e o tamanho
da matriz. C++ faz o mesmo. Na realidade, muitos compiladores C++ n~ao geram
o codigo que testa se um ndice esta fora do limite durante um acesso a matriz. Por
exemplo, a sequ^encia a seguir seria aceita por muitos compiladores:
140 CAPITULO 6. DADOS ESTRUTURADOS
int v = 20;
int a[20]; // o tamanho da matriz 
e 20. O 
ndice varia de 0 a 19
a[v] = 0; // o 
ndice v 
e maior do que o limite superior

Uma matriz ocupa memoria do espaco de dados do usuario. A func~ao de acesso


da matriz identi ca o endereco de memoria para um elemento particular. Geralmente,
n~ao e feito a checagem para veri car que o endereco, de fato, esta dentro do intervalo dos
elementos da matriz. Disso resulta que um programa em C++ pode usar ndices que est~ao
fora do intervalo. Os enderecos dos elementos que est~ao fora do intervalo ainda podem
cair dentro do espaco de dados do usuario. No processo, o programa pode sobrecarregar
outras variaveis e causar erros de execuc~ao indesejados.

Matrizes bidimensionais
Uma matriz bidimensional, e um tipo de dados estruturado que e criado aninhando-se
matrizes unidimensionais. Os itens s~ao acessados por ndices de linhas e colunas. Por
exemplo, a matriz de 32 elementos, t, que segue tem 4 linhas e 8 colunas. O valor 10 e
acessado pelo par, (linha, coluna), (1,2) e -3 e acessado pela par (2,6).
0 1 2 3 4 5 6 7
0
1 10
2 -3
3
O conceito de uma matriz bidimensional pode ser estendida para matriz de qualquer
dimens~ao, na qual os elementos s~ao acessados por tr^es ou mais ndices. Matrizes de duas
dimens~oes tem aplicac~oes desde processamento de dados ate equac~oes diferenciais parcias.
A declarac~ao em C++ de matriz bidimensional, t, de ne o numero de linhas, o numero
de colunas, e o tipo de dados dos elementos:
tipo t [contadorDeLinha][contadorDeColuna];

Os elementos de t s~ao referenciados pelos ndices de linhas e colunas:

t[i][j ]; 0  i  contadorDeLinha 1; 0  j  contadorDeColuna 1


Por exemplo, t e uma matriz de inteiros 4 por 8:
int t[4][8];

6.5. VARIAVEIS E LITERAIS DE STRING 141
O valores t[1][2] = 10 e t[2][6] = -3 s~ao, respectivamente, 10 e o valor da segunda
linha e terceira coluna, e -3 e o valor na terceira linha e setima coluna.
Poderemos pensar de uma matriz bidimensional como uma lista de matrizes unidi-
mensional. Por exemplo, t[0] esta na linha 0, que consiste de elementos individuais de
contadorDeColuna. Este conceito e util quando uma matriz bidimensional e passada como
par^ametro. A natoc~ao int t[ ][8] indica que t e uma lista de matrizes de 8 elementos.
0 1 2 3 4 5 6 7
t[0]
t[1] 10
t[2] -3
t[3]

Armazenamento de matrizes bidimensionais


Uma matriz bidimensional pode ser inicializada atribuindo de cada vez uma linha aos
itens. Por exemplo, a matriz t especifca uma tabela 2 por 4:
int t[3][4] = {{290,5,-30},{-40,13,32,8},{3,0,0,-1}};

Como na matriz unidimensional, os itens s~ao armazenados na ordem primeira linha,


segunda linha, terceira linha.

6.5 Variaveis e literais de string


Uma matriz e um tipo de dados estruturado que contem uma lista homog^enea de itens.
Uma forma especial de matriz contem dados de caracteres que identi cam nomes, pala-
vras, sentencas e assim por diante. Essa estrutura, chamada uma string(cadeia), trata
os caracteres como uma unica entidade e providencia operac~oes para acessar sequ^encias
de caracteres dentro da string. Uma string e uma estrutura de dados crtica para mui-
tas aplicac~oes que usam dados alfanumericos. A estrutura e necessaria para manipular
processamento de textos com suas operac~oes para editar, seus algoritmos para pesquisar-
substituir e assim por diante. Por exemplo, um linguista pode precisar da informac~ao do
numero de vezes que uma certa palavra ocorre num documento ou um programador pode
usar o padr~ao encontrar/substituir para alterar o codigo fonte num documento. Muitas
linguagens declaram a estrutura string, providenciam operadores embutidos e func~oes de
bibliotecas para manipular strings.
Para determinar o comprimento de uma string, a estrutura pode incluir um 0 no m da
string(NULL- m do string) ou um par^ametro de comprimento separado. A representaca~o
da string seguinte contem o string de seis caracteres STRING.
142 CAPITULO 6. DADOS ESTRUTURADOS
S T R I N G NULL
Contador de comprimento da string
6
comprimento S T R I N G
Uma serie de operac~oes processam uma string como um unico bloco de catacteres.
Por exemplo, podemos determinar o comprimento de uma string, copiar uma string em
outra, juntar(concatenar) strings, e processar substrings com inserc~ao, remoc~ao e ope-
rac~oes de casamento de padr~ao. As strings tambem tem uma operac~ao de comparac~ao
que possibilitam a ordenac~ao de strings. A operac~ao usa a ordem ASCII. Por exemplo,
"Bernado" 
e menor que "Martin" // B v
em antes de M
"Smith" 
e menor que "Smithson"

"Bernado" v
em antes de "bernado" // o B mai
usculo precede o b min
usculo

"123Sim" 
e menor que "AAA" // n
umeros precedem letras

O TAD string 
e

Dados
Uma string e
 uma sequ^
encia de caracteres com um comprimento
associado. A estrutura string pode ter um caractere de termina
c~
ao
NULL ou um par^
ametro de comprimento separado.

Opera
c~oes
Comprimento
Entrada: Nenhuma
Precondi
co
~es: Nenhuma
Processo: Para uma string terminando em NULL, conta os caracteres
at
e o caractere NULL. Para uma string com contador de comprimen
recupera o valor do comprimento.
P
oscondi
c~
oes: Nenhuma
Sada: Retorna o comprimento a string.

C
opia
Entrada: Duas strings str1 e str2. str2 
e a fonte e str1 o destino.
Precondi
c~
oes: Nenhuma
Processo: Copia os caracteres de str2 para str1.
P
oscondi
c~
oes: 
E criada uma nova string str1 com comprimento e dados obtidos
de str2.

6.5. VARIAVEIS E LITERAIS DE STRING 143
Sa
da: Retorna o acesso a str1.

Concatena
ca~o
Entrada: Dois strings str1 e str2. Junta str2 na cauda de str1.
P
oscondi
c~oes: Nenhuma.
Processo: Achar o fim de str1. Copiar os caracteres de str2 na cauda de s
Atualizar a informa
ca
~o do comprimento de str1.
P
oscondi
c~
oes: str1 
e modificada.
Sada: Retorna acesso a str1.

Compare
Entrada: Dois str1 e str2.
Precondi
c~
oes: Nenhuma.
Processo: Aplicar a ordem da tabela ASCII para as strings.
P
oscondi
c~
oes: Nenhuma.
Sada: Retorna um valor como segue:
str1 menor que str2: retorna um valor negativo.
str1 igual a str2: retorna valor 0
str1 maior que str2: retorna um valor positivo.


Indice
Entrada: Uma string str e um 
unico caractere ch.
Precondi
c~
oes: Nenhuma.
Processo: Pesquisa str para a entrada ch.
P
oscondi
c~
oes: Nenhuma.
Sada: Retorna o endere
co da localiza
c~
ao contendo
a primeira ocorr^
encia de ch em str ou 0 caso
o caractere n~
ao seja encontrado.

ndiceDaDireita

Entrada: Uma string str e um unico caractere ch.
Precondi
c~
oes: Nenhuma.
Processo Pesquisa str buscando a ultima ocorr^
encia de
do caractere ch.
P
oscondi
c~
oes: Nenhuma.
Sada: Retorna o endereco da localiza
c~
ao contendo a
ultima ocorr^
 encia de ch em str ou 0 se caractere
n~ao for encontrado.
Leia
Entrada: O arquivo stream do qual os caracteres s~
ao lidos e
uma string str contendo os caracteres.
144 CAPITULO 6. DADOS ESTRUTURADOS
Precondi
c~
oes: Nenhuma.
Processo: L^
e uma sequ^
encia de caracteres de stream na string str.
P
oscondi
c~
oes: Ao string str 
e atribu
do os caracteres lidos.
Sada: Nenhuma.

Escreva:
Entrada: Uma string que contem caracteres para sa
da e uma stream
para o qual os caracteres ser~ao escritos.
Precondi
c~
oes: Nenhuma.
Processo: Envia os string de caracteres ao stream.
P
oscondi
c~
oes: Nenhuma.
Sada: A stream de sa
da 
e modificada.

fim do TAD string.

Strings em C++
Numa outra oportunidade especi caremos e implementaremos uma classe C++ string.
Esta classe contera um conjunto estendido de operadores de comparac~oes e operac~oes
de E/S(Entrada/sada). Aqui, usaremos os strings de C++ com terminac~ao NULL e a
biblioteca de string C++ para implementar o TAD.
Um string de C++ e um string com terminac~ao NULL com o 0 de ASCII designando
o caractere NULL. O compilador identi ca um literal de string como uma sequ^encia
de caracteres sob aspas duplas. Uma variavel de string e uma matriz de caracteres que
contem uma sequ^encia de caracteres terminando com NULL. A declarac~ao seguinte cria
uma matriz de caracteres e atribui a ela um literal de string:

char str[9] = "Uma string";

A string "Uma string" e armazenada na memoria como uma matriz de caracteres com
onze elementos:
U m a s t r i n g NULL
C++ fornece alguns opradores de E/S para os streams cin(teclado), cout(tela), cerr(tela)
e streams de arquivos de nidos pelo usuario.
A biblioteca de string C++ < string:h > contem uma colec~ao de func~oes para ma-
nipular strings bastante exvel que implementam diretamente muitas das operac~oes do
TAD. A tabela 6.3 lista as funco~es de strings principais.

6.5. VARIAVEIS E LITERAIS DE STRING 145
char s1[20] = \dir/bin/appl", s2[20] = \ le.asm", s3[20];
char *p;
int resultado;

Exemplos

1. Comprimento int strlen(char *s);


cout << strlen(s1) << endl; // A sa
da e
 12
cout << strlen(s2) << endl; // A sa
da 
e 8

2. C
opia char *strcpy(char *s1, *s2);
strcpy(s3,s1); // s3 = "dir/bin/appl"

3. Concatena
ca
~o char *strcat(char *s1, *s2);
strcat(s2,"/");
strcat(s3,s2); // s3 = "dir/bin/appl/file.asm"
4. Compare int strcmp(char *s1, *s2);
resultado = strcmp("bernado", "Bernado"); // resultado > 0
resultado = strcmp("12", "12"); // resultado = 0
resultado = strcmp("Joe", "Joseph"); // resultado < 0

5. 
Indice char *strchr((char *s, int c);
p = strchr(s2,'.'); // p aponta para '.' ap
os file
if (p)
strcpy(p,".cpp"); // s2 = "file.cpp"

6. 
IndiceDaDireita char *strrchr(char *s, int c);
p = strrchr(s1,'/'); // p aponta para '/' ap
os bin
if (p)
*p = 0; // termina string ap
os bin
// s2 = "dirbin"

7. Leia vari
avelDeStream >> s;
8. Escreva vari
avelDeStream << s;
cin >> s1; // se a entrada for "al^
o mundo"
cout << s1; // s1 e
 "al^
o"
// sa
da 
e "al^
o"

Tabela 6.3: Func~oes de string em C++ e exemplos


146 CAPITULO 6. DADOS ESTRUTURADOS
Aplicac~oes: Revertendo nomes
Um programa de aplicac~ao de string ilustra o uso das func~oes de biblioteca de string C++.
Na aplicac~ao, as func~oes strchr(), strcpy() e strcap() ser~ao combinadas de modo que um
nome tal como \Jose Dau" seja copiado como \Dau, Jose" na string novoNome. Os
seguintes comandos implementam o algoritmo.
char nome[10] = "Jos
e Dau", novoNome[30];
char *p;

Comando 1: p = strchr(nome, ` ');


Retorna um ponteiro p para o primeiro branco no nome. A primeira
letra do 
ultimo nome come
ca no endere
co p + 1.

J o s e D a u NUL
Comando 2: *p = 0; // substitui o branco pelo caractere NULL.

J o s e NULL D a u NULL
Comando 3: strcpy(novoNome,p+1); // copia o 
ultimo nome em novoNome

J o s e NULL D a u NULL
D a u NULL

Comando 4: strcat(novoNome, " "); // adiciona `,' e branco ao novoNome

D a u , NULL
Comando 5: strcat(novoNome, nme); // concatena o primeiro nome

J o s e NULL
D a u , J o s e NULL

Programa: Reverter um nome


O programa a seguir usa os comandos de 1 a 5 para reverter um nome. As etapas ser~ao
codi cadas na func~ao reverteNome(). Um laco testa o algoritmo para tr^es strings de
entrada. Em cada a sada e o nome revertido.

6.5. VARIAVEIS E LITERAIS DE STRING 147
#include <iostream.h>
#include <string.h>

// reverte o primeiro e 
ultimo nomes e os separa com v
rgulas, copia
// o resultado em novoNome.
void reverteNome(char *nome, char *novoNome)
{
char *p;

// busca o primeiro branco em nome e o substitui pelo caractere NULL


p = strchr(nome, ` ');
*p = 0;

// copia o 
ultimo nome em novoNome, acrescenta `,' e
// concatena primeiro nome.
strcpy(novoNome, p+1);
strcat(novoNome,nome);
strcat(novoNome,nome);

// substitui o branco original pelo caractere NULL


* = ` ';
}

void main(void)
{
char nome[32], novoNome[32];
int i;

// l^
e e processa tr^
es nomes
for (i = 0; i < 3 ; i++)
{
cin.getline (nome, 32, `/');
reverteNome(nome,novoNome);
cout << ``Nome revertido:" << endl << endl;
}
}

Executando esse programa para a entrada ``Jos


e Dau", a sa
da ser
a
Dau, Jos
e.
148 CAPITULO 6. DADOS ESTRUTURADOS
6.6 Registros
Um registro e uma estrutura que combina itens de tipos diferentes num unico objeto.
Os itens no registro s~ao chamados campos. Como na matriz(tambem conhecida como
vetor ou array), um registro tem um operador de acesso que possibilita um acesso direto
a cada campo. Por exemplo, estudante e um registro que descreve informac~oes sobre um
estudante que frequenta uma escola. Dentre as informac~oes est~ao: o nome do aluno, o
endereco do local, a idade, curso, media.
nome endereco do local idade curso media
Neste exemplo, os campos nome e endereco do local s~ao do tipo string, idade e do
tipo inteiro, curso do tipo enumerac~ao e media do tipo real. Assumindo que Toni e um
estudante, podemos acessar os campos individuais combinando o nome do registro com o
campo, usando o operador \.":
Toni.nome Toni.idade Toni.m
edia Toni.curso

Um registro possibilita o agrupamento de tipos diferentes(tipos heterog^eneos) na


estrutura. Diferentemente da matriz, um registro descreve um valor unico, em vez de
uma lista de valores.
O TAD registro 
e

Dados
Um item contendo um conjunto de campos de tipos heterog^
eneos.
Cada campo possui um nome que permite um acesso direto aos dados no campo.

Opera
c~oes
Operador de acesso
Precondico
~es: Nenhuma.
Entrada: Nome do registro e do campo.
Processo: Acessa os dados no campo.
Sa
da: Quando recuperando dados, retorna o valor do campo
ao cliente.
P
oscondi
co~es: Quando armazenando dados, o registro 
e alterado.

C++ implementa registro com estrutura


C++ possui o tipo embutido struct(estrutura) que representa um registro. Essa estrutura
e herdada da linguagem C com a qual continua compatvel. C++ de ne o tipo struct como
um caso especial de uma classe na qual todos os membros s~ao publicos. Usamos o tipo
estrutura nestas notas somente quando lidarmos com uma estrutura de registro.
6.7. ARQUIVOS(FILE) 149
Exemplo 39 struct estudante
{
int ident;
char nome[30];
}

estudante s = {555, ``Dau, Samuel"};


cout << s.ident << `` " << s.nome << endl;

6.7 Arquivos(File)
Muitas vezes em nosso curso estaremos interessados no projeto e implementac~ao de estru-
turas de dados internas, que acessam informac~oes residentes na memoria. Nas apli-
cac~oes, entretanto, assumiremos, com frequ^encia, que os dados estar~ao disponveis num
dispositivo de armazenamento externo como um disco. O dispositivo(arquivo fsico)
armazena informac~oes numa stream(corrente) de caracteres e o sistema operacional pro-
videncia uma serie de operac~oes para transferir para e da memoria. Isto nos possibilita
entrar e recuperar dados que possam estar permanentemente armazenados num disposi-
tivo externo. Os dados armazenados conjuntamente com as operac~oes de transfer^encia
de ne uma estrutura de dados, chamada um arquivo( le)(logico), que tem a importante
vantagem de manter uma grande quantidade de informac~oes que residiriam tipicamente
na memoria.
As linguagens de programac~ao prov^eem operac~oes de manipulac~ao de arquivos em alto
nvel para liberar o programador de ter que usar chamadas do sistema operacional de baixo
nvel. As operac~oes de arquivos usam um dado stream que esta logicamente conectado
ao arquivo. O stream associado aos dados ui com o arquivo. Para a entrada, o stream
possibilita que os dados uam do dispositivo externo para a memoria. O mesmo programa
pode recuperar informac~oes para o arquivo usando um stream de sada.
E util de nir um TAD para um arquivo. Os dados consistem de uma sequ^encia de
caracteres que representam dados de texto ou bytes que representam dados binarios. Para
o texto, os dados s~ao armazenados como uma sequ^encia de caracteres ASCII separados
pelo caracre novaLinha. As operac~oes do TAD s~ao dados de modo que sejam bastante
gerais, focalizando as operac~oes primitivas de E/S. A operac~ao de entrada Ler()(Read)
extrai uma sequ^encia de caracteres do stream. A operac~ao de sada relacionada Escre-
ver()(Write) insere uma sequ^encia de caracteres na stream. As operac~oes especiais Get()
e Put() manipulam as E/S para um unico caractere.
Uma stream mantem um ponteiro de arquivo que identi ca a posic~ao corrente na
stream. A entrada desloca do ponteiro de arquivo para o proximo item de dado n~ao lido na
stream. A sada localiza o ponteiro de arquivo na proxima posic~ao da sada. Uma operac~ao
de procura nos possibilita posicionar o ponteiro de arquivo. Esta operac~ao assume que
150 CAPITULO 6. DADOS ESTRUTURADOS
temos acesso a todos os caracteres no arquivo e podemos nos mover para diante, para
tras, ou uma posic~ao intermediaria. Tipicamente, a operac~ao de procura e usada para os
arquivos de disco.
Usualmente, um arquivo e colocado num stream em um dos tr^es modos seguintes:
ready-only(somente leitura), write-only(somente escrita) e ready-write(leitura escrita). O
modo ready-only e write-only especi ca que o stream e usado para entrada e sada, res-
pectivamente. O modo ready-write possibilita o uxo dos dados em ambas as direc~oes.
O TAD arquivo 
e

Dados
Uma identifica
ca
~o do arquivo externo e a dire
c~
ao do fluxo de dados. Uma sequ^
enci

Opera
c~oes
Abrir
Entrada: Nome do arquivo e a dire
c~
ao do fluxo.
Precondica
~o: Para a entrada, o arquivo externo deve existir.
Processo: Conecta um stream a um aruivo.
Sada: Um aviso(flag) que indica que a opera
c~
ao foi bem sucedida.
P
oscondico
~es: Os dados podem fluir entre o arquivo externo e a mem
oria do sis
via o stream.

Fechar
Entrada: Nenhuma.
Precondi
c~oes: Nenhuma.
Processo: Desconecta o stream do arquivo.
Sada: Nenhuma.
P
oscondico
~es: Os dados n~
ao podem mais fluir do arquivo externo via
o stream entre o arquivo externo e a mem
oria do sistema.

Ler
Entrada: Uma matriz contendo blocos de dados. Um contador N.
Precondi
co~es: O stream deve estar aberto com dire
c~
ao ready-only ou ready-writ
Processo: Entram N caracteres do stream na matriz.
Para quando for encontrado fim-de-arquivo.
Sada: Retorna o n
umero de caracteres que forem lidos.
P
oscondi
co~es: O ponteiro de arquivo 
e movido para adiante N caracteres.

Escrever
Entrada: Uma matriz e um contador .
Precondic~
oes: O stream deve estar aberto para a dire
c~
ao write-only
6.7. ARQUIVOS(FILE) 151
ou ready-write.
Processo: Sai N caracteres na stream.
Sada: Retorna o n
umero de caracteres que foram lidos.
P
oscondi
co~es: O stream cont
em os dados de sa
da, e o ponteiro de arquivo
avan
ca N caracteres.

Procurar
Entrada: Par^
ametros para reinicializar o ponteiro de arquivos.
Precondico
~es: Nenhuma.
Processo: Reinicializa o ponteiro de arquivo.
Sa
da: Retorna uma mensagem(flag) que indica se a procura
foi bem sucedida.
P
oscondi
c~
oes: 
E estabelecido um novo ponteiro de arquivo.

fim do TAD arquivo

Hierarquia de stream em C++


C++ providencia para que seja possivel manipular o arquivo com um sistema de stream
E/S que e implementado usando uma hierarquia de classe C++. Um stream C++ e um
objeto correspondendo a uma classe na hierarquia. Cada stream identi ca um arquivo e
a direc~ao do uxo de dados.
A classe raz na hierarquia e ios, que contem dados e operac~oes para todas as classes
derivadas. A classe contem mensagens que identi cam atributos espec cos do stream e
metodos de formatos que s~ao precisos para a entrada e sada. Por exemplo,
cout.setf(ios::fixed);

inicializa o modo display(visualizac~ao) para os numeros reais para o formato xo em


vez do formato cient co.
As classes istream e ostream providenciam operac~oes de entradas e sadas basicas
que ser~ao usadas como classes base para o resto da hierarquia de stream de E/S.
A classe istream-withassigh e uma variante do stream que possibilita atribuic~ao de
objetos. O objeto prede nido cin e um dessa classe. Os objetos prede nidos cout e cerr
s~ao do tipo de classe ostream-wthassign. Em tempo de execuc~ao, esses tr^es streams
s~ao abertos para a entrada do teclado e sada pela tela. As declarac~oes est~ao no arquivo
< iostream:h >.
A classe ifstream e uma istream derivada usada para a entrada do arquivo de disco.
Analogamente, ostream e usado para a sada de arquivo de disco. Essas classes est~ao
declaradas no arquivo < fstream:h >. Ambas as classes contem a operac~ao abrir(open)
para colocar um arquivo no stream e a operac~ao fechar(close) para separar um arquivo de
um stream.
152 CAPITULO 6. DADOS ESTRUTURADOS
Os dois tipos de arquivos de discos s~ao arquivos de textos e arquivos de binarios.
Um arquivo de texto contem caracteres ASCII e e imprimvel, enquanto um arquivo de
binario contem dados binarios puros. Por exemplo, um editor usa arquivo de texto e
um programa de spreadsheet cria e usam arquivos binarios. A seguir apresentaremos um
exemplo de um programa de E/S de arquivo de texto e de arquivos de binarios os quais
futuramente ser~ao desenvolvidos como classes. A classe de arquivo binario e usada para
implementar busca externa e algoritmos de ordenac~ao.
A classe fstream possibilita ao usuario criar e manter arquivos que requeram acessos
de leitura e escrita.
E/S baseadas em matriz est~ao implementadas pelas classes istream e ostream que
est~ao declaradas no arquivo < iostream:h >. Aqui os dados s~ao lidos de uma matriz ou
escritos na matriz por um dispositivo externo. Editores de textos usam com frequ^encia
E/S baseados em matriz para efetuarem operac~oes de formatac~ao complexas.
Programa: arquivo E/S
Este programa ilustra os streams de C++, incluindo arquivo de texto e E/S baseadas em
matrizes.
Este programa usa cout e cerr que est~ao includos em < iostream:h >. Entradas de
arquivos de textos e sadas baseadas em matrizes usam os arquivos < fstream:h > e
< strstream:h >, respectivamente. O programa abre o arquivo e l^e cada linha contendo
os pares variavel/valor nos formatos nome valor. Usando a operac~ao de stream baseado
em matriz, o par e escrito na matriz outputstr no formato
``nome = valor"

e ent~ao com um comando cout. Por exemplo, as linhas de sada


in
cio 55
para 8.5

s~ao impressos como os strings


in
cio = 55 pare = 8.5

#include <iostream.h>
#include <fstream.h>
#include <strstream.h>
#include <stdlib.h>
#include <string.h>

void main(void)
~ DE MATRIZES E REGISTROS
6.8. APLICACOES 153
{
// arquivo de entrada de texto contendo nomes e valores
ifstream fin;

// l^
e idenficadores nos nomes e escreve os resultados no outputstr
char nome[30],

// declara uma stream de sa


da baseada em matriz que usa outputstr
ostream outs(outputstr, sizeof(outputstr));

double valor;

// abre "nomes.dat" para input. Assegura que ele existe.


fin.open("nomes.dat", ios::in | ios::nocreate);
if (!fin)
{
cerr << "N~
ao 
e poss
vel abrir "nomes.dat" " << endl;
exit(1);
}

// ler um nome e valor. Escreve para outs como "nome = valor"


while (fin >> nome)
{
fin >> valor;
outs << nome << " = " << valor << " ";
}

// termina em null o string de sa


da
outs << ends;

cout << outputstr << endl;

6.8 Aplicac~oes de matrizes e registros


Matrizes e registros s~ao estruturas de dados embutidos em muitas das linguagens de pro-
gamac~ao. Nesta seca~o introduziremos TADs para essas estruturas e discutiremos suas
implementac~oes em C++. Usaremos essas estruturas de dados para desenvolver alguns
algoritmos importantes. Uma matriz e uma estrutura de dados fundamental para listas.
154 CAPITULO 6. DADOS ESTRUTURADOS
Em muitas aplicaco~es, usaremos busca e ordenac~ao por troca para encontrar um item
numa lista baseada em matriz e para ordenar os dados. A seguir, introduzirems a busca
sequencial e a ordenac~ao por trooca que s~ao simples de codi car e entender.
Busca sequencial
Uma busca sequencial procura um item numa lista usando um valor chamado chave. O
algoritmo comeca com um ndice fornecido, chamado incio, e percorre os itens restantes
na lista, comparando cada item com a chave. A pesquisa continua ate que a chave seja
encontrada ou a lista tenha sido totalmente percorrida. Se a chave for encontrada, a
func~ao retorna o ndice do elemento da lista que casou. Caso contrario, e retornado o
valor -1. A funca~o buscaSeq() requer quatro par^ametros, o endereco da lista, o ndice de
incio para a busca, o numero de elementos e a chave. Por exemplo, considere a seguinte
lista de inteiros contida na matriz a:

a: 8 3 62 6
1. chave = 6, incio = 0, n = 5. Pesquisar a lista do incio, retornando o ndice da
primeira ocorr^encia d o elemento 6.
8 3 6 2 6

2. chave = 6, incio = 3, n = 2. Iniciar em a[3] e pesquisar a lista, retornando um


ponteiro para a primeira ocorr^encia do elemento 6.
3. chave = 9, incio = 0, n = 5. Iniciar no primeiro elemento e procurar na lista o
elemento 9. Com ele n~ao sera encontrado, retornar o valor -1.
O algoritmo da busca sequencial se aplica a qualquer matriz para o qual o operador
\==" esteja de nido para o tipo do item. Um caso mais geral sera discutido num curso
de estruturas de dados.
Fun
c~ao da busca sequencial

int buscaSeq(int lista[], int in cio, int n, int chave)


{
for (int i=incio; i < n; i++)
{
if (lista[i] == chave)
return i;
}
return -1;
}
~ DE MATRIZES E REGISTROS
6.8. APLICACOES 155
Programa da busca sequencial
Este programa testa a busca sequencial contando o numero de ocorr^encia de uma chave
numa lista. O programa principal primeiro fornece como entrada 10 inteiros numa mtriz
a e ent~ao procura uma chave.
O programa faz rpetidas chamadas da func~ao buscaSeq() usando diferentes ndices para
incio. Inicialmente, comecamos no ndice 0, o comeco da matriz. Apos cada chamada
de buscaSeq(), o o contador do numero de ocorr^encias e incrementado se a chave for
encontrada: caso contrario a busca termina e o contador e a sada. Se a chave for
encontrada, o valor de retorno identi ca sua posic~ao na lista. A proxima chamada para
buscaSeq() e feita com o incio no elemento imediatamente a direita.

#\include <iostream.h>

// pesquisa a matriz de inteiros com n elementos procurando um elemento que case com
// retorna um ponteiro para o dado ou null caso a chave n~
ao seja encontrada.
int buscaSeq(int lista[], int in
cio, int n, int chave)
{
for(int i=in
cio;i < n; i++)
if (lista[i] == chave)
return i; // retorna o 
ndice do item que cas
return -1; // caso falhe, reorne -1
}

void main(void)
{
int a[10];
int chave, contador=0, pos;

// entra uma lista de 10 inteiros


cout << "Entre uma lista com 10 inteiros:";
for (pos=0; pos < 10; pos++)
cin >> a[pos];

cout << "Entre com uma chave:";


cin >> chave;

// incia a busca no primeiro elemento da matriz


pos = 0;

// move-se na lista at


e que a chave seja encontrada
156 CAPITULO 6. DADOS ESTRUTURADOS
while ((pos = buscaSeq(a,pos,10,chave) !-1)
{
contador++;
// move-se para o pr
oximo inteiro ap
os casar
pos++;
}

cout << chave << "ocorre"<< contador


<< "na lista." << endl;
}

Executando este programa:

Entre uma lista com 10 inteiros: 5 2 9 8 1 5 8 7 5 3


Entre com uma chave: 5
5 ocorr 3 vezes na lista

Ordenac~ao por troca


A ordenac~ao dos itens numa lista e importante em muitas aplicac~oes. Por exemplo, uma
lista de inventario pode ordenar registros pelo seu numero de partes para permitir um
rapido acesso a um item, um dicionario contem palavras na ordem alfabetica, e na ordem
do registro estudantes podem ser ordenados pelo cpf.
Para criar uma lista ordenada, introduzimos um algoritmo de ordenac~ao chamado
ordPorTroca() que ordena os itens na ordem ascendente. O algoritmo e ilustrado com
a lista 8, 3, 6, 2 e produz a lista ordenada 2, 3, 6, 8.
Indice 0: Considere a lista completa 8, 3, 6, 2. O item no ndice 0 e comparado com
cada item subsequente na lista no ndice 1, 2, 3. Para cada comparac~ao, se o ndice
subsequente for menor que o elemento no ndice 0, as duas entradas ser~ao trocadas. Apos
todas as comparaco~es terem sidos feitas, o menor elemento estara localizado no ndice 0.
Lista inicial Ac~ao Lista resultante
ndice 0 8 3 6 2 troca ! 3 8 6 2
3 8 6 2 troca ! 3 8 6 2
8 3 6 2 troca
! 2 8 6 3

Indice 1: Uma vez que o menor ja esta localizado no ndice 0, consideremos a sublista
8, 6, 3. Somente os itens do ndice 1 em diante ser~ao considerados. O item no ndice
1 e comparado com os subsequentes itens nos ndices 2 e 3. Para cada comparac~ao, se
o maior estiver no item 1, as duas entradas ser~ao trocadas. Apos cada comparac~ao, o
~ DE MATRIZES E REGISTROS
6.8. APLICACOES 157
segundo menor elelento na lista e armazenado no ndice 1.
Lista inicial Ac~ao Lista resultante
ndice 1 2 8 6 3 troca ! 2 6 8 3
2 6 8 3 troca ! 2 3 8 6
ndice 2: Considere a sublista 8, 6. O processo continua para a sublista de dosi itens
com ndices 2 e 3. Uma unica comparac~ao, resultando numa troca, e feita entre esses
itens.
Lista inicial Ac~ao Lista resultante
ndice 2 8 3 8 6 troca ! 2 3 6 8
Terminamos com somente um unico item no ndice 3 e a lista esta ordenada.
Lista nal ordenada
2 3 6 8
A func~ao de C++ ordPorTroca() usa lacos aninhados. Assuma que o tamanho da
lista da lista e dado n. O laco mais externo incrementa o ndice i no intervalo de 0 a n -
2 Para cada ndice i, compare os ndices subsequentes aos 'dices j = i + 1, i + 2, ..., n -
1. Faca a comparac~ao e ent~ao troque os elementos se lista[i] > lista[j ].

Programa: Ordenando uma lista


Este programa ilustra o algoritmo de ordenac~ao. Uma lista e constituda de 15 inteiros no
intervalo de 0 a 99. A func~ao ordPorTroca() ordena a lista, usando a func~ao troca() para
trocar os elementos na matriz. O programa imprima a lista antes e apos a ordenac~ao.
#include <iostream.h>

// troca os valores das duas vari


aveis inteiras x e y.
void troca(int & x, int & y)
{
int temp = x; // armazena o valor original de x

x = y; // troca o valor de x pelo de y

y = temp; // atribu y ao valor original de x


}

// ordena a matriz inteira, a, de n elementos na ordem ascendente


void ordPorTroca(int a[], int n)
158 CAPITULO 6. DADOS ESTRUTURADOS
{
int i, j

// implementa n - 1 passos. Localiza os valores corretos em


// a[0], ..., a[n-2].
for (i=0; i < n-1; i++)
// coloca o m
nimo de a[i+1],...,a[n-1] em a[i]
for (j=i+1; j < n; j++0
// troca se a[i] > a[j]
if (a[i] > a[j])
troca(a[i],a[j]);
}

// percorre a lista e imprime cada valor


void imprimaLista(int a[], int n)
{
for (int i=0; i < n; i++)
cout << a[i] << " ";
cout << endl;
}

void main(void)
{
int lista[15] = {38,58,13,15,51,27,10,19,12,86,49,67,84,60,25,};
int i;

cout << "Lista original \n"


imprimaLista(lista,15);
ordPorTroca(lista,15);
cout << endl << "Lista ordenada:" << endl;
imprimaLista(lista,15);
}

Executando este progragrama para a lista original


38 58 13 15 51 27 10 19 12 86 49 67 84 60 25

A lista ordenada
10 12 13 15 19 25 27 38 49 51 58 60 67 84 86
~ DE MATRIZES E REGISTROS
6.8. APLICACOES 159
Contando palavras reservadas em C++
Anteriormente discutimos o tipo de dados registro que e implementado em C++ como
uma estrutura(struct). Para ilustrar o uso de registros, um programa computa o numero
de vezes que as palavras reservadas "else" "for" "if", \include" e "while" ocorrem num
programa C++. O programa usa variaveis de strings assim como uma matriz de registros.
A principal estrutura de dados do programa e a estrutura palavraChave cujos os cam-
pos consistem da variavel de string PalavraChave e o inteiro contador:
struct palavraChave
{
char PalavraChave[20];
int contador;
};

A tabela para as cinco palavras reservadas e criada na matriz tabDePalavrasChave.


Cada item na tabela e inicializado especi cando a palavra reservada e um contador ini-
cial de 0. Por exemplo, o primeiro inicializador de matriz f\else"; 0g faz com que a
tabDePalavrasChave[0] de entrada contenha o strint \else" com o contador 0:
palavraChave tabDePalavrasChave[] =
{
{"else",0},{"for",0},{"if",0},{"include",0},{"while",0}
};

O programa l^e as palavras individuais num arquivo usando a func~ao GetWord(). Uma
palavra e qualquer sequ^encia de caracteres comecando com uma letra e continua com letras
ou dgitos. Por exemplo, quando e apresentado a linha
"Express~
ao: 3 + 5 = 8 (N1 + N2 = N3) "

A func~ao GetWord() extrai as palavras \Express~ao", \N1", \N2" e \N3"e descarta os


outros smbolos.
A func~ao buscaSeq() percorre a tabela procurando por um item que case com a pala-
vraChave. Quando ocorre o casamento, a func~ao retorna o ndice do registro que casou,
o qual pode, ent~ao, ter o seu campo contador incrementado.
Programa: Contando palavras reservadas
Este programa l^e seu proprio codigo fonte como entrada. Um laco l^e cada palavra e chama
a func~ao buscaSeq() para determinar se a entrada casa com uma palavra reservada em
tabDePalavrasChave. Se for o caso, incrementamos o campo de contador do registro. Apos
a entrada estiver completada, e impresso o numero de ocorr^encias de cada palavraChave.
O programa ilustra um comando interessante que computa din^amicamente o numero
de elementos na matriz tabDePalavrasChave, usando a express~ao
160 CAPITULO 6. DADOS ESTRUTURADOS
sizeof(tabDePalavrasChave)/sizeof(palavraChave)

Esta express~ao prov^e um metodo de computar o numero de elementos numa matriz


independente da maquina. Se forem adicionadas outras palavras chave a tabela, uma
compilac~ao subsequente gerara um novo contador de elementos.
#include <iostream.h>
#include <fstream.h>
#include <string.h> // deve incluir as func~
oes de string usadas
#include <ctype.h> // prov^
e 
eAlfa e 
eD
gito
#include <stdlib.h>

// declara a estrutura de palavras


struct palavraChave
{
char PalavraChave[20];
int contador;
};

// declara e inicializa a tabela de palavras chave


palavraChave tabDePalavrasChave[ ] =
{
{"else",0},{"for",0},{"if",0},{"include",0},{"while",0}
};

// algoritmo de busca sequencial para palavras chave


int buscaSeq(palavraChave *tab, int n, char *palavra)
{
int i;

// percorre a lista. Compara palavra com palavraChave no registro corrente


for (i=0; i < n; i++, tab++)
if (strcmp(palavra, tab->palavraChave == 0)
return i; // retorna 
ndice se casar
return -1; // n~
ao casa
}

// extrai a palavra come


cando com uma letra e possivelmente
// outras letras/d
gitos
int GetWord (ifstream& fin, char w[])
{
~ DE MATRIZES E REGISTROS
6.8. APLICACOES 161
char c;
int i = 0;

// pula entrada n~
ao alfab
etica
while ( fin.get(c) && !isalpha(c))
;

// retorna 0(falha) no fim da fila.


if (fin.eof())
return 0;

// registra a primeira letra da palavra


w[i++] = c;

// coleta letras e d
gitos e strings terminando com NULL
while (fin.get(c) && (isalpha(c) || isdigit(c)))
w[i++] = c;
w[i] = "\n";

return 1; // retorna 1 (sucesso)


}

void main(void)
{
const int tamM
aximo = 50; // tamanho m
aximo de cada palavra

// declara o tamanho da tabela e inicializa seus valores


const int NpalavrasChave = sizeof(tabDePalavrasChave)/sizeof(PalavraChave);

int n;
char palavra[tamM
aximo];
ifstream fin;

// abre arquivo com cheque de erro


fin.open("prog2_5.cpp",ios::in | ios::nocreate);
if (!fin)
{
cerr << "N~
ao 
e possivel abrir arquivo 'prog2_5.cpp'" << endl;
exit(1);
}
162 CAPITULO 6. DADOS ESTRUTURADOS

// extrai palavras at


e o fim da fila
while (GetWord(fin, palavra)
// se casar na tabela de palavras chave, incrementar contador
if ((n = buscaSeq(tabDePalavrasChave, NpalavraChave, palavra)
tabDePalavrasChave[n].contador++;

// percorre a tabela de palavras chave e imprime campos do registro


for (n = 0; n < NpalavraChave; N++)
if (tabDePalavrasChave[n].contador > 0)
{
cout << tabDePalavrasChave[n].contador;
cout << " " << tabdepalavrasChave[n].palavraChave << endl;
}
fin.close();
}

Executando este programa tem a seguinte sa


da:

1 else
3 for
9 if
7 inlude
4 while

6.9 Exerccios
1. Computar o valor decimal de cada numero binario:
(a) 101
(b) 1110
(c) 110111
(d) 1111111
2. Escrever cada numero decimal em binario:
(a) 23 (b) 55 (c) 85 (d) 253

3. Nos sistemas de computadores modernos, os enderecos s~ao usualmente implementa-


dos no nvel de hardware como valores binarios de 16-bits ou 32-bits. E natural lidar
6.9. EXERCICIOS 163
com enderecos em binarios em vez de convert^e-los em decimal. Como os numeros
desses tamanhos s~ao ruins de escrev^e-los como strings de dgitos binarios, s~ao usados
os numeros na base 16 ou hexadecimais. Tais numeros referidos como numeros
hex, s~ao representac~oes importantes para os inteiros permitindo uma convers~ao facil
para e de binarios. Muitos softwares lidam com enderecos de maquinas em hex.
Os numeros hex s~ao construdos de uma base de 16 dgitos percorrendo de 0-15(decimal).
Os primeiros dez dgitos s~ao herdados dos numeros decimais: 0, 1, 2 ,3, 4, 5, 6, 7,
8, 9. Os dgito de 10 a 15 s~ao representados por A, B, C, D, E e F. As pot^encias
de 16 s~ao: 160 = 0 161 = 16 162 = 256 163 = 4096 e assim por diante. Na forma
de notac~ao posicional, exemplos de numeros s~ao: 17E, 48 e FFFF800. Os numeros
s~ao convertidos para decimal expandindo as pot^encias de 16 exatamente como para
as pot^encias de 2 s~ao expandidas para numeros binarios.
Por exemplo, o numero hex 2A3F16 e convertido para decimal expandindo as pot^encias
de 16.
2A3F16 = 2(163 ) + A(162) + 3(161 ) + F (160) = 2(4096) + 10(256) + 3(16) + 15(1) =
8192 + 2560 + 48 + 15 = 1018510
Converter cada numero hex para decimal:

(a) 1A (b) 41F (c) 10EC (d) FF (e) 10000

4. Converter cada numero decimal para hex:


(f) 23 (g) 87 (h) 115 (i) 255

5. O principal motivo para introduzir numeros hex e sua correspond^encia natural com
os numeros binarios. Eles possibilitam uma representac~ao compacta de dados binarios
e enderecos de memoria. Os dgitos hex tem uma representac~ao binaria de 4-bits
no intervalo 0-15. A tabela seguinte lista a correspond^encia entre dgitos binarios e
hex.
hex binario hex binario
0 0000 8 1000
1 0001 9 1001
2 0010 A 1010
3 0011 B 1011
4 0100 C 1100
5 0101 D 1101
6 0101 E 1110
7 0111 F 1111
164 CAPITULO 6. DADOS ESTRUTURADOS
Para representar um numero binario em hex, comecar no nal do lado direito do
numero e partir os bits em grupos de quatro, adicionando 0's no ultimo grupo da
esquerda, se for necessario. Escrever cada grupo de 4 bits como um dgito hex. Por
exemplo, 1111000111011112 = 0111 1000 1110 1110 = 78EE16
Para converter de um numero hex para para um numero binario, reverter o processo
e escrever cada dgito hex como 4 bits. Considere o seguinte exemplo:
A78916 = 101 0111 1000 1001 = 10100111100010012
Converter de binario para hex
(a) 1100 (b) 1010 0110 (c) 1111 0010 (d) 1011 1101 1110 0011

Converter hex para binario


(e) 0610 16
(f) AF 2016
6. C++ permite ao programador entrar e sair numeros em hex. Colocando o manipu-
lador \hex" no stream, o modo para a entrada ou sada de numeros e hex. O modo
tem efeito ate ele retornar o decimal com manipulador \dec". Por exemplo:
cin >> hex >> t >> dec >> u; // t 
e lido como hex e u 
e lido como decimal

< entrada; 100 256 > t = 100 e u = 256


16 10

cout << hex << 100 << t << u; // a sa


da e
 64 100 100
cout << dec << 100 << t << u; // a sa
da 
e 100 256 256

Considere a seguinte declarac~ao e comando executaveis:


int i j, k;

cin >> i;
cin >> hex >> j >> dec;
cin >> k;

Assuma que <entrada> 


e 50 50 32. Qual 
e a sa
da do comando?

(a) cout << hex << i << " " << j << " " << dec << k << endl;

(b) assuma que <entrada> 


e 32 32 64. Qual 
e a sa
da do comando?

cout << dec << i << " " << hex << j << " " << k << endl;
6.9. EXERCICIOS 165
7. Escrever uma especi cac~ao completa para operador % no tipo de dados inteiro. Faca
o mesmo para o operador de comparac~ao !=.
8. O tipo booleano de ne dados que s~ao os valor verdadeiro ou falso. Algumas lingua-
gens de programac~ao de ne o tipo nativo Boolean com uma serie de func~oes em-
butidas para processar os dados. C++ associa um valor booleano a cada express~ao
numerica.
(a) Defina um TAD booleano que descreve o domnio de dados e suas opera
c~
oes.
(b) Descreva uma implementa
ca~o do TAD usando os construtos da linguagem C++.

9. (a) Que caractere ASCII corresponde ao numero decimal 78?


(b) Qual caractere ASCII corresponde ao numero binario 10010112 ?
(c) Quais s~ao os codigos ASCII para os caracteres \*", \q" e o retorno do carro?
D^e sua resposta em binario e decimal.
10. O que sera impresso a partir do seguinte fragmento de codigo?

cout << char(86) << " " << int('q') << " " <<
char(int("0") + 8) << endl;

11. Explicar porque o operador %(resto)n~ao esta disponvel no TAD numeros reais.
12. Converter cada numero binario de ponto xo para deciamal:
(a) 110,110
(b) 1010,0101
(c) 1110,00001
(d) 11,111....111...(suagest~
ao: usar a f
ormula para a soma de uma s
erie geom
etric

13. Converter cada numero decimal de ponto xo para binario:

(a) 2,25
(b) 1,125
(c) 1,0875

14. (a) No TAD dos n


umeros reais, existe o menor n
umero real positivo?
(b) Quando os n
umeros s~
ao implementados num computador, existe o menor n
umero pos
166 CAPITULO 6. DADOS ESTRUTURADOS
15. O formato de ponto utuante IEEE armazena o sinal do numero separado e arma-
zena o expoente e a mantissa usando numeros sem sinal. Uma forma normalizada
permite uma representac~ao unica para cada numero em ponto utuante.
Forma Normalizada: O numero em ponto utuante e ajustado para ter um unico
dgito diferente de zero a esquerda do ponto binario.

N = +1; d d :::dn  2e
1 2 1

O numero em ponto utuante 0,0 e armazenado com sinal, expoente, e mantissa 0.


Como um exemplo, dois numeros binarios s~ao convertidos para a forma de reprsen-
tac~ao normalizada.
Numeros binarios Forma normalizada
1101; 101  21 1; 1011010  24
0; 0011  2 6
1; 1  23
Os numeros de ponto utuante de trinta e dois bits s~ao armazenados na forma
normalizada usando o formato interno IEEE:

Sinal O bit mais a esquerda e usado para o sinal. Um "+ " tem 0 bit de sianl. e u
tem um bit de sinal 1.

Expoente O expoente 
e armazenado em 8 bits. Para assegurar que todos os expoentes
s~
ao armazenados como n
umeros positivos(sem sinal), o formato IEEE especi
usando a nota
c~
ao "excesso-127" para o expoente. O expoente armazenado, E

Exps = Exp + 127

ExpoenteVerdadeiro ExpoenteArmazenado
Escopo escopo
-127 <= Exp <= 128 0 <= Exps <= 255

Mantissa Assumindo que o n


umero est
a armazenado na forma normalizada, o d
gito
l
der 1 est
a escondido. Os d
gitos fracion
arios s~
ao armazenados numa ma
dando 24 bits deprecis~
ao.

sinal expoente mantissa


1 bit 8 bits 23 bits
Como um exemplo, computaremos a representac~ao interna de -0,1875.
6.9. EXERCICIOS 167
Forma normalizada (-)1,1.10023
sinal 1
Expoente Exps = 3 + 127 = 124 = 011111002
Mantissa < 1 >100000...0
0; 1875 = 10111110010000000000000000000000
Registre cada numero na notac~ao de ponto utuante UEEE em 32-bits.
(a) 7,5 (b) -1/4

Qual e o valor do seguinte numero na forma decimal formatado em IEEE de 32-bits?


Cada numero e dado em hex.
(c) C1800000 (d) 41E90000

16. (a) Listar na ordem do calendario os meses do ano que tem um "a" no seu nome.
Isto e um tipo enumerado.
(b) Escrever em C++ uma impementac~ao do tipo enumerado.
(c) Na implementac~ao C++, que mes corresponde ao inteiro 4? Qual e a posic~ao
de outubro?
(d) Escrever a enum em ordem alfabetica. Quais meses tem a mesma posic~ao em
ambas as listas?
17. Adicionar as operac~oes de sucessor e predecessor ao TAD para tipos enumerados.
Use especi cac~oes completas. O sucessor retorna o proximo item na lista e o pre-
decessor retorna o item anterior. Tome cuidado em de nir o que acontece nos
extremos da lista.
18. Dados as seguintes declarac~oes e comandos, especi car os conteudos de X, Y e A
apos a execuc~ao do seguinte comando:
int X=A, y=7, *PX = &X, *Py;
double A[] = {2,3, 4,5, 8,9, 1,0, 5,5, 3,5}, *PA = A;
PY = &Y; *(PX)--; *PY+=*PX; PY = PX;
*PY = 55; *PA+=3,0; PA++; *PA++ = 6,8;
PA+=2;
*++PA = 3,3;

19. (a) A e declarado como


168 CAPITULO 6. DADOS ESTRUTURADOS
short A[5];

Quantos bytes s~ao alocados para a matriz A? Se o endereco da matriz for A =


6000, compute o endereco de A[3] e A[1].
(b) Assuma a declarac~ao
long A[] = {30, 500000, -100000, 5, 33};

Se uma palavra long for de 4-bytes e o endereco de a for 2050.


 Qual e o conteudo do endereco 2066?
 Duplique os conteudos nos enderecos 2050 e 2062. Escrever a matriz A.
 Qual e o endereco de A[3]?
20. Assuma que A e uma matriz m  n com os ndices das linhas no intervalo de 0 a
(m-1) e os das colunas no intervalo de 0 a (n-1). Gerar uma func~ao de acesso que
computa o endereco de A[linha][col], assumindo que os elementos s~ao armazenados
por colunas.
21. A e declarado como
short A[5][6];

(a) Quantos bytes s~ao alocados para a matriz A?


(b) Se o endereco da matriz for A = 1000, computar o endereco de A[3][2] e A[1][4].
(c) Qual a entrada da matriz que esta localizada no endereco 1020? e no endereco
1034?
22. (a) Declarar uma string NOME com valor inicial de seu primeiro nome.
(b) Considere as declarac~oes de variavel de string
char s1[50], s2[50];

e os comandos de entrada
cin >> s1 >> s2;

Quais os valores de s1 e s2 para a linha de entrada\George voa"? Quais os


valores de s1 e s2 na entrada do seguinte texto (3 e um caractere branco e [ e
o m de linha.)?:
Proximo [ 3333  Palavra
23. Assuma as seguintes declarac~oes de strings:
6.9. EXERCICIOS 169
char s1[30] = "Stockton, CA", s2[30] = "March 5, 1994", *p;
char s3[30];

(a) Qual e o valor de *p apos a execuc~ao de cada um dos seguintes comandos?


p = strchr(s1, 't');
p = strrchr(s1, 't');
p = strrchr(s2, '6');

(b) Qual e valor de s3 apos a execuc~ao dos seguintes comandos?


strcpy (s3,s1);
strcap (s3, ", ");
strcat (s3, s2);

(c) O que a chamada de func~ao strcmp (s1,s2) retorna?


(d) O que a chamada de func~ao strcmp (&s1[5],"tom") retorna?
24. A func~ao
void strinsert(char *s, char *t, int i);

insere o string t no string s comecando no ndice i. Se i for maior que o comprimento


de s, a inserc~ao n~ao sera efetuada. Implemente strinsert usando as func~ao de
biblioteca C++ strlen(), strcy(), e strcat(). E preciso declarar uma variavel de string
temporaria para conter os caracteres originais em s do ndice i ao ndice strlen(s)-1.
Assuma que esta cauda nunca excede 127 caracteres.
25. A func~ao
void strdelete(char *s, int i, int n);

remove uma sequ^encia de n caracteres do string s comecando o ndice i. Se i+n for


maior ou iqual que o comprimento de s, o m do string sera removido comecando no
ndice i. Implemente strdelete() usando as func~oes de biblioteca strlen() e strcy().
26. Uma alternativa do uso de string com terminac~ao NULL e colocar um contador de
caracteres no primeiro elemento da matriz de caracteres. Isto e chamado formato
de contador de bytes. Tais strings s~ao usados com frequ^encia com o nome strings
de Pascal, pois o sistema de programac~ao Pascal usa esse formato de strings.
(a) Implemente a func~ao strcat() assumindo que os strings s~ao armazenados no
formato de contador de bytes.
170 CAPITULO 6. DADOS ESTRUTURADOS
(b) As func~oes PtoCstr() e CtoPStr() fazem a covers~ao entre os dois formatos de
strings:
void PtoCStr(char *s); // converte s de Pascal para C++
void CtoPStr(char *s); // converte s de C++ para Pascal

Implemente essas duas func~oes.


27. Adicionar o operador de atribuic~ao \=" ao TAD registro usando uma especi caca~o
completa. De na com cuidado que ac~oes ter~ao lugar durante a atribuic~ao.
28. Um numero complexo e da forma x + iy , onde i2 = 1. Os numeros complexos
s~ao usados em matematica , fsica e engenharia. Eles possuem uma aritmetica
governada por uma serie de regras incluindo as seguintes:
Sejam u = a + ib, v = c + id

u+v = (a+c)+i(b+d)
u-v = (a-c)+i(b-d)
u*v = (ac-bd)+i(ad+bc)

a=v = ac c+ bd + i( bc
2 2
bd )
c +d 2

Represente um numero complexo usando a estrutura de registro:


struct complexo
{
float real;
float imag;
};

e implemente as seguintes func~oes que efetuam operac~oes sobre os numeros comple-


xos:
complexo cadd(complexo& x, complexo& y); // x + y
complexo csub(complexo& x, complexo& y); // x - y
complexo cmul(complexo& x, complexo& y); // x * y
complexo cdiv(complexo& x, complexo& y); // x / y

29. Adicone uma operac~ao tamDeArquivo() ao TAD para stream. Ele deve retornar o
numero de caracteres no arquivo. Tome cuidado quando especi car que precondic~oes
devem existir para que esta operac~ao tenha sentido. (Susgest~ao: que tal cin/cout?)
6.9. EXERCICIOS 171
30. Distinga cuidadosamente um texto dum arquivo binario. Voc^e pensa que e possvel
desenvolver um programa que recebe como entrada o nome de um arquivo e deter-
mina se ele e um texto ou um arquivo binario?
31. Escreva uma func~ao
void baseOut(unsigned int n, int b);

que devolve n na base b, 2  b  10, imprime cada numero no intervalo 2  n  50


nas bases 2, 4, 8 e 9.
32. Escrever uma func~ao
void octIn(unsignet int& );

que l^e um numero na base 8(0ctal) e atribui ele a n. Use octIn() num programa
main() que l^e os seguintes numeros octais e imprime os equivalentes decimais:
7; 177; 127; 7776; 177777
33. Escrever um programa que declara tr^es variaveis inteiras i, j, k. Entre um valor
decimal para i em decimal e valores para j e k em hex. Imprima as tr^es variaveis
em hex e decimal.
34. Considere o tipo enumerado
enum diasDaSemana {domingo, segunda, ter
ca, quarta, quinta, sexta, s
abado};

Escreva uma func~ao


void getDia(diadDASemana& dia);

que que l^e o nome de um dia do teclado como uma string e atribui o corespondente
valor enum do dia. Escreva tambem uma func~ao
void putDia(diasDaSemana dia);

que escreve o valor enum na tela. Desenvolver um programa main() para testar as
duas func~oes.
35. Entre uma serie de palavras ate m do arquivo(fda), cada uma das palavras. Se a
palavra comeca com uma consoante, mover o primeiro caractere da palavra para a
ultima posic~ao e colocar \ay". Se a palavra comeca com uma vogal, simplesmente
coloque \ay" Por exemplo,
172 CAPITULO 6. DADOS ESTRUTURADOS
Entrada: tudo 
e possvel
Sa
da: udoay eay oss
velay

36. Uma string de texto pode ser encriptado usando um mapeamento tabular que associa
a cada letra do alfabeto uma unica letra. Por exemplo,
abcdfghijklmnopqrstuvwxyz ==> ngzqtcobmuhelkpdawfyivrsj

mapeia \encrypt" em "tkzwsdf". Escreva um programa que l^e um texto ate o m do


arquivo e devolve a forma encriptada.
37. Escreva um programa que faz com que um ou mais ndices da matriz sai do limite.
Torne a situac~ao bastante ruim fazendo com que o programa trave.
38. Modi que a ordenac~ao por troca de modo que ele ordene a lista em ordem descen-
dente.
39. Considere a declarac~ao
struct mes
{
char nome[10]; // nome do mes
int numDoMes; // n
umero do dia no mes
};

(a) Escrever uma func~ao


void ordPorNome(mes Mes[], int n);

que ordena uma matriz cujos elelementos s~ao do tipo mes comparando no-
mes(use a func~ao C++ strcmp()). Escreva tambem uma func~ao
void ordPorDias(mes Mes[], int n);

que ordena a lista comparando o numero de dias num mes. Escreva um progra-
ma Main() que declara uma matriz contendo todos os meses do ano e ordena-os
usando ambas as func~oes. Imprima cada lista ordenada.
40. Escreva um programa que l^e um arquivo de texto e imprime um contador do numero
de ocorr^encias dos sinais de pontuac~ao (.,!?).
41. Escreva um programa que entra uma matriz N  N , a, de valores inteiros e imprime
o traco da matriz. O traco e de nido como a soma dos elementos da diagonal.
tra
co(a) = a[0,0] + a[1,1] + ... + a[N-1,N-1]
6.9. EXERCICIOS 173
42. Escreva uma func~ao f(z) que(use o exerccio sobre complexos) avalia a func~ao poli-
nomial complexa:

z 3
3z + 4z 2
2

Avalie o polin^omio para os seguintes valores de z:


z = 2 + 3i, -1 + i, 1 + 1, i - 1, 1 + 0i

Observe que os tr^es ultinos valores s~ao razes de f.


174 CAPITULO 6. DADOS ESTRUTURADOS
Bibliogra a
[1] Abramsky, S. Domain theory in logical form. In Domain Theory in Computing
Science, pages 47{53. Computer Society Press of the IEEE, 1987.
[2] Benedito M. Acioly. The scott interval analysis: A new approach to interval ma-
thematics. Revista de Informatica Teorica e Aplicada (RITA), 1996. To Appear.
[3] Benedito M. Acioly. The Scott Interval Analysis. In Marclia A. Campos; Dalcdio
M. Claudio, editor, Proceedings of the Second Workshop on Computer Arithmetic,
Interval and Symbolic Computation, pages 4{6. Brazilian Computer Society (SBC),
August 1996.
[4] Acioly B. & Bedregal, B. A quasi-metric topology compatible with inclusion-
monotonicity property on interval space. Reliable-Computing, 3(3), 1997.
Ed.Kluwer.
[5] Acioly, Benedito. Notas em logica. Technical report, Instituto de Informatica,
Universidade Federal do Rio Grande do Sul., Setembro 1990.
[6] Acioly, Benedito M. Computational foundations of Interval mathematics. PhD the-
sis, Instituto de Informatica, Universidade Federal do Rio Grande do Sul, Dezembro
1991. in Portuguese.
[7] Aczel, Peter H.G. Term declaration logic and generalized composita. In Six An-
nual IEEE Symposium on Logic in Computer Science(LICS'91), pages 22{30. IEEE
Press, 1991.
[8] Alefeld, G. & Herzberger, J. An Introduction to Interval Computation. Academic
Press, New York, 1983.
[9] Arbib,M.A. & Manes E.G. Arrows, Structures and Functors. Academic Press,
1975.
[10] Asperti, Andrea & Longo Giuseppe. Categories, Types and Structures. Massachu-
setts Institute of Technology, 1991.
175
176 BIBLIOGRAFIA
[11] Barendregt, H. The lambda calculus. it's syntax and semantics. In Studies in Logic
and Foundation of Mathematics, volume 103. North-Holland Publishing Company,
1984.
[12] Barr, Michael & Wells, Charles. Category Theory for Computing Science. C.A.R
Hoare, Series Editor. Pretince Hall International (UK), rst edition, 1990.
[13] Bedergal, B.R. & Acioly, B.M. Sistemas de informac~ao contiInuos. Technical
Report RT-001/95, UFPe-CCEN, Depto. de Informatica, Recife, 95.
[14] Michael Beenson. Foundation of constructive Mathematics. springer-Verlag, 1985.
[15] Beenson, M.J.ll. Formalizing constructive mathematics. why and how? In
F.Richman, editor, Constructive Mathematics. Proceedings,, number 873 in Lecture
Notes in Mathematics, pages 146{190, Las Cruces, New Mexico, 1981. Springer-
Verlag.
[16] Bell, J.L. Toposes and Local Set Theories. An Introduction. Number 14 in Oxford
Logic Guides. Clarendon Press - Oxford, 1988.
[17] Berti, S. The Solution of an Interval Equation. 1969.
[18] Bird, Richard. Programs and Machines. An Introduction to the Theory of Compu-
tation. John Wiley & Sons, 1976.
[19] Birko , Garret. On the structure of abstract algebras. Proceedings Cambridge
Philosophical Society, 31:433{454, 1935.
[20] Erret Bishop. Foundations of Constructive Analysis. Mc-Graw Hill, 1967.
[21] C.Thomas; Hahn S.W. Bullof, Jack J.; Holyoke, editor. Foundations of Mathe-
matics (Symposium Papers Commemorating the Sixtiex Birthday of Kurt Godel,
1969.
[22] Bunge, Mario. Tratado de loso a basica. In Sem^antica I, volume vol 1. EDUSP,
1976.
[23] Bunge, Mario. Tratado de loso a basica. In Sem^antica II. Interpretac~ao e Verdade,
volume vol 2. EDUSP, S~ao Paulo, 1976.
[24] Burris, Stanley & Sankappanavar, H.P. A Course in Universal Algebra. Springer-
Verlag, 1981.
[25] Georg Cantor. Contributions to the foundation of the theory of trans nite numbers.
Dover Publications.
BIBLIOGRAFIA 177
[26] Cardelli, Luca & Wagner, Peter. On understanding types, data abstraction and
polimorphism. Computing Surveys, 17(04), December 1985.
[27] Cohn, P.M. Universal Algebra. Harper & Row and John Weatherhill Inc., 1965.
[28] Costa, M.Amoroso. In Texto 4. As Ideias Fundamentais da Matematica e Outros
Ensaios, Biblioteca do Pensamento Brasileiro. EDUSP, 1981.
[29] daCosta, Newton C.A. Introduc~ao aos Fundamentos da Matematica. HUCITEC,
S~ao Paulo, 3ed., edition.
[30] B.A. Davey and H.A. Priestley. An introduction to lattices and order. Cambridge
University Press, 1992.
[31] Davis, Ruth. Truth, Deduction, and Computation. Logic and Semantics for Com-
puting Science. Computer Science Press, 1989.
[32] deQueiroz, Ruy J.G.B. A proof-theoretic account of programming and the role of
reduction rules. Dialectica, 42(04), 1988.
[33] deQueiroz, Ruy J.G.B. Proof Theory and Computer Programming. The Logical
Foundations of Computing. PhD thesis, Department of Computing, Imperial Col-
lege, University of London, 1991.
[34] deQueiroz, Ruy J.G.B. & Gabbay, M. Dov. An introduction to labelled natural de-
duction. Technical report, Departament of Computing, Imperial College, University
of London, September 1982.
[35] deQueiroz, Ruy J.G.B. & Maimbaum, Thomas S.E. Proof theory and computer
progamming. Zeitschrift Fur Mathematishe Logik und Grundlagen der Mathematik,
36:389{414, 1990.
[36] Diller A. Z. An Introduction to Formal Methods. John Wiley & Sons, 1994.
[37] Domingues, H.H. & Iezzi, G. A lgebra Moderna. 2a ed. edition, 1982.
[38] Dummet, Michael. What is a theory of meaning? In Evans & John McDowell,
editor, Essays in Semantics. Claredon Press, 1976.
[39] H. Enderton. A mathematical introduction to logic. Academic Press Inc, 1972.
[40] Bell. E.T. Men of mathematics.
[41] Ferrari, A. T. Metodologia da Pesquisa Cient ca. McGraw-Hill, 1982.
178 BIBLIOGRAFIA
[42] F.B. Feys, R.; Fitch. Dictionary of Mathematical Logic. Studies in Logic and The
Foundations of Mathematics. North-Holland, 1969.
[43] M.C. Fitting. Intuitionistic Logic Model Theory and Forcing. Studies In Logic and
the Foundations of Mathematics. North-Hollad, 1969.
[44] M. P. Fourman and D. S. Scott. Sheaves and logic. In M. P. Fourman, C. J. Mulvey,
and D. S. Scott, editors, Applications of Sheaf Theory to Algebra, Analysis, and
Topology, number 753 in Lecture Notes in Mathematics, pages 302{401. Springer-
Verlag, 1979.
[45] Frege, Gottlob. Function and concept. In Brian McGuinness, editor, Collected
Papers on Mathematics, Logic and Philosophy.
[46] F.W.Lawvere, editor. Toposes, Algebraic Geometry and Logic. Number 274 in
Lecture Notes in Mathematics. Springer-Verlag, 1972.
[47] Gabbay, Dov M. Labelled Deductive Systems. Part 1. Oxford University Press,
1996.
[48] Gabbay, M.Dov & de Queiroz, Ruy J.G.B. Extending the curry-howard interpreta-
tion to linear, relevant and other resourcer logic. The Journal of Symbolic Logic,
57(4), December 1992.
[49] Gallier, Jean. Contructive logics. Technical report, digital, Paris Research Labora-
tory, 1991.
[50] Gallier, Jean H. Logic for Computer Science. Foundations of Automatic Theorem
Proving. John Wiley & Sons inc., 1987.
[51] Gentzen, G. The collected papers of gerard gentzen. In Szabo, M.E., editor, Studies
In Logic And Foundations of Mathematics. North-Holland Publishing Company,
1969.
[52] Gierz, G.; Hofmann, K.H.;Keimel, K.; Lawson, J.D.; Mislove, M.; Scott, D.S. A
Compendium of Continuous Lattices. Springer-Verlag, 1980.
[53] Girard, Jean-Yves. Proof Theory and Logical Complexity, volume I. Bibliopolis,
1987.
[54] Girard, Jean-Yves; Lafont, Yves & Taylor, Paul. Proofs and Types, volume 7 of
Tracts in Theoretical Computer Science. Cambridge University Press, 1989.
[55] Andrew H. Gleason. Fudamentals of Abstract Analysis.
BIBLIOGRAFIA 179
[56] Goguen, Joseph A. Theorem Proving and Algebra. To be published, 1997. Draft of
May 16, 1997.
[57] Goguen,J, et.al. Initial algebra semantics and continuous algebras. Journal of ACM,
24(1):32{101, January 1977.
[58] Goldblatt, R. Topoi. The Categorial Analysis of Logic, volume 98 of Studies in
Logic and The Foundations of Mathematics. north-holland, 1984.
[59] R.L. Goodstein. Recursive Number Theory. Studies in Logic and the Foundation
of Mathematics. North-Holland, 1964.
[60] Michael J.C. Gordon. Programming Language Theory and Its Implementation.
C.A.R. Hoare. Pretince-Hall, 1988.
[61] Guelli, C.A; et.al. Algebra IV. Editora Moderna ltda.
[62] Halmos, Paul R. Naive Set Theory. D.Van Nostrand Company inc., 1960.
[63] Heijenoort, Jean Van. From frege to godel. a source book in mathematical logic 1879-
1931. Series Source Books in History Of The Science, pages xii+665pp. Harvard
University Press.
[64] Heijnoort, Jean Van. Logic as calculus and logic as language. Synthese, 53, 1967.
[65] Hennessy, Matthew. Algebraic Theory of Process. The MIT Press, 1988.
[66] Hindley, J. Roger & Seldin, Jonathan P. Introduction to Combinators and -
calculus.
[67] Howard, W.A. The formulae-as-types notion of construction. In J.P. Seldin & J.R.
Hindley, editor, Essays on Combinatory Logic, Lambda Calculus and Formalism,
pages xxv+606p. Academic Press, 1980.
[68] Huet, Gerard, editor. Logical Foundations of Functional Programming. Addison-
Wesley, 1990.
[69] Peter T. Johnstone. Stone Spaces. Cambridge University Press, 1982.
[70] P.T. Johnstone. Stone Spaces. Cambridge University, 1982.
[71] Johnstone, P.T. Stone Spaces. Cambridge University Press, 1982.
[72] Robert H. Kasriel. Undergraduate Topology.
[73] Kleene, Stephen Cole. Mathematical Logic. John Wiley & Sons, Inc., 1967.
180 BIBLIOGRAFIA
[74] Kneale, William & Kneale, Martha. O Desenvolvimento da Logica. Fundac~ao
Calouste Gulbenkian, 1991.
[75] G. Kreisel. Elements of mathematical logic (model theory). In Studies in Logic and
The Foundation of Mathematics. North-Holland Publishing Company, 1971.
[76] Lambeck,J.& Scott,P.J. Introduction to Higher Order Categorical Logic. Cambridge
University Press, 1986.
[77] P.D. Lax. Calculus with application and computing.
[78] Leisenring, A.C. Mathematical Logic and Hilbert's -Symbol. MacDonald Technical
and Scienti c, 1969.
[79] Lipschutz, Seymour. Teoria dos Conjuntos. AO Livro Tecnico S.A., 1968.
[80] Manes, Ernest G. & Arbib, Michael A. Algebraic Approaches To Program Seman-
tics. Springer-Verlag, 1986.
[81] Manzano, Maria. Teoria de Modelos. Alianza Universidad Textos, 1989.
[82] Martin-Lof, Per . Notes on Constructive Mathematics. Almqvist & Wiksell, 1968.
[83] Martin-Lof, Per. Constructive mathematics and computer programming. In J.Tos,
H.Pfei er & K.P.Pdewski L.J. Cohen, editor, Logic, Methodology and Philosophy
of Science, number VI. North-Holland, 1982.
[84] Martin-Lof, Per. Intuitionistic Type Theory. Bibliopolis, 1984.
[85] Martin-Lof, Per. Truth of a proposition, evidence of a judgement, validity of a
proof. Synthese, (73):407{420, 1987.
[86] Moore, Ramon E. Interval Analysis. Pretince Hall, New Jersey, 1966.
[87] Moore, Ramon E. Methods and Applications of Interval Analysis. SIAM, 1979.
[88] Mosses, Peter D. Handbook of Theoretical Computer Science, chapter 11, pages
577{674. 1990.
[89] Nordstrom, Bengt ; Peterson, Kent & Smith, Jan M. Programming in Martin-Lof's
Type Theory. An Introduction. Clarendon Press. Oxford, 1990.
[90] Paulson, L. Tracts in theoretical computer science. In Logic and Computation.
Interactive Proof with Cambridge LCF, volume 2. Cambridge University Press,
1987.
BIBLIOGRAFIA 181
[91] Prawitz, Dag. Ideas and results in proof theory. In Fenstad, J.E., editor, Procee-
dings of The Second Scandinavian Logic Symposium, pages 235{307, Amsterdam,
1971. North-Holland.
[92] Prawitz, Dag. Towards a foundation of general proof theory. In Proceedings ,of The
Fourth International Congress For Logic, Methodology And Philosophy of Science,
pages 225{250. North-Holland Publishing Company, 1971.
[93] Prawitz, Dag. On the idea of a general proof theory. Synthese, (27):63{77, 1974.
[94] Prior, A.N. The runabout inference-ticket. Analysis, (21):38{39, 1960.
[95] Interval'96, 1996.
[96] Revesz. Lambda-Calculus, Combinators and Functional Programing. Cambridge
Tracts in Theoretical Computer Science. Cambridge University Press, 1988.
[97] Reynolds, John C. Polymorphism is not set theoretic. Semantics of Data Types,
page 184, June. International Symposium, France.
[98] Reynolds, John C. Types, abstraction and parametric polimorphism. Information
Processing, 1983.
[99] Ross, Keneth A. & Wright, Charles R.B. Discrete Mathematics. Pretince Hall,
1988.
[100] Walter Rudin. Principles of Mathematical Analysis. McGraw-Hill, 1953.
[101] Santiago, Regivan. Toward a constructive logic to real analysis. Master's thesis,
Universidade Federal de Pernambuco, March 1995. In Portuguese.
[102] Santiago, Regivan & Acioly Benedito. Intervals as real numbers speci cation. In
Interval'96, October 1996.
[103] Santiago, Regivan & Acioly Benedito. A numerical approximation logic. In
Workshop in Arithmetic, Interval and Symbolic Computation, July 1996.
[104] Santiago, Regivan & Acioly, Benedito. Toward a logic for numerical approximations.
Revista de Informatica Teorica e Aplicada, 1996. To appear.
[105] Santiago, Regivan & deQueiroz, Ruy J.G. Toward a proof theory for proofs by
induction. In 1st. Workshop LaLLIC, pages 149{164, July 1994.
[106] Santiago, Regivan & deQueiroz, Ruy J.G. Notas em logica e topoi. Manuscript,
July 1996.
182 BIBLIOGRAFIA
[107] Dana S. Scott. Domains for denotational semantics. In M. Nielsen and E. M.
Schmidt, editors, Automata, Languages and Programming, volume 140 of Lecture
Notes in Computer Science, pages 577{613, Berlin, 1982. Springer-Verlag.
[108] Scott, Danna. Continuous lattices. In F.W.Lawvere, editor, Toposes, Algebraic
Geometry and Logic, number 274 in Lecture Notes in Mathematics, pages 97{136.
Springer-Verlag, 1972.
[109] M.B. Smith. Topology. Handbook of Logic in Computer Science, 1:641{751, 1992.
[110] Smorynski, C.A. Applications of kripke models. In A.S. Troelstra, editor, Ma-
thematical Investigation of Intuitionistic Arithmetic and Analysis, number 344 in
Lecture Notes in Mathematics, chapter V, pages 324{391. springer-Verlag, 1973.
[111] Spivey, J.M. Understanding Z.A Speci cation Language and its Formal Semantics.
Cambridge University Press, 1988.
[112] Spivey, J.M. The Z Notation. A Reference Manual. C.A.R. Hoare Series. Pretince
Hall, 1992.
[113] Sundholm, Goran. Proof theory and meaning. In Gabbay, Dov & Guenthner, F.,
editor, Handbook of Philosophical Logic, pages 471{506. D.Reidel Publishing com-
pany, 1986.
[114] Thompson, S. An introduction to type theory and constructive mathematics. No-
vember 1987.
[115] A.S. Troelstra. Mathematical Investigation of Intuitionistic Arithmetic and Analy-
sis. Lecture Notes In Mathematics. Springer-Verlag, 1973.
[116] Troelstra, A.S. Principles of Intuitionism. Lecture Notes In Mathematics. Springer-
Verlag, 1969.
[117] Troelstra, A.S. & Van Dalen, Dirk. Constructivism in mathematics. In Studies in
Logic and the Foundations of Mathematics, volume II. North-Holland, 1988.
[118] Dirk Van Dalen. Intuitionisc logic. Handbook of Philosophical Logic, 3, 1986.
[119] Van Dalen, Dirk. Intuitionistic logic. In Gabbay, Dov & Guenthner F., editor,
Handbook of Philosophical Logic, volume III, chapter III.4, pages 225{339. D.
Reidel Publishing Company, 1986.
[120] Vickers, S. Topology via logic. Number 5 in Cambridge Tracts in Theoretical
Computer Science. Cambridge University Press, 1989.
BIBLIOGRAFIA 183
[121] David A. Watt. Programming Concepts and Paradigms. C.A.R. Hoare. Pretince-
Hall, 1990.
[122] Wechler, Wolfgang. Universal Algebra For Computer Scientists. Springer-Verlag,
1992.
[123] Woodcock,J. & Davies, J. Using Z.Speci cation, Re nement, and Proof. Pretince
Hall, 1996.
[124] Martin M. Zuckerman. Sets and Trans nite Numbers. Collier Macmillian, 1974.

You might also like