Professional Documents
Culture Documents
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
Bibliograa 174
Captulo 1
INTRODUCA~ O:SOBRE
LINGUAGEM DE
PROGRAMACA~ O
O computador e um instrumento imprescindvel ao comercio, a industria e a pesquisa
cientca. Ele e um aut^omato que executa processos computacionais segundo regras pre-
1
Ac~ao
Podemos dizer de uma aca~o que:
tem durac~ao nita;
tem um efeito esperado e bem denido;
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 especcos;
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 especcos(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 denido 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.
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:
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 especca.
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:
Memoria e Processador
partes principais do computador
Podemos armar que
1. a memoria abriga, em forma codicada, 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
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 identicados de modo unico, cada um deles possuindo um endereco. Todo
acesso a memoria deve ser acompanhado da especicac~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 codicac~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 Codicac~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 codicaca~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 codicados 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 codicadas. 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
ENTRADAS
MEMORIA
/
E CPU SAIDAS
/
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 conaveis,
exveis e ecientes.
Uma proposta de metodologia estabelece os seguintes passos:
1. Analise do problema.
2. Projeto do programa: algoritmo e estrutura de dados.
3. Implementac~ao(codicac~ao) e teste do programa.
9 com isto queremos signicar 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. Vericac~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 certicar que compreendemos o problema corretamente, sem ambiguidades,
nos assegurar que entendemos completamente as especicac~oes das entradas e das
sadas.
Para realizar esta fase precisamos seguir os seguintes passos:
1. escolher uma amostra signicativa dos dados e denir as especicac~oes de entrada;
2. determinar a sada desejada correspondente aos dados de entrada, denindo as es-
pecicac~oes de sada.
E bom observar que a escolha da amostra de entrada conrma 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
10Estas operac~oes devem ser denidas 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 identicar partes ou
etapas na estrategia de resoluc~ao do problema, elaborando inicialmente um esboco
da resoluc~ao. Em seguida, e detalhada sucessivamente cada etapa, renando 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
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 codicac~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 especicar~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
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
Adic~ao();
leia(A,B);
soma A + B ;
imprima(soma);
Apos o nome adica~o, que identica 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;
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;
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 insuciente 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.
(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 classicam como unarios, como -, e binarios, como + e . A
linguagem C++ possui um operador ternario, ?:. Sua sintaxe , em geral, possui a seguinte
3
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 especicada 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 signicado, 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 classicadas
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
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 denida 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
#include <iostream.h>
void main()
{
int i, n, t, S; // declara as vari
aveis.
cin >> n;
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
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
Implementa
c~ao.
34 CAPITULO 2. ALGUNS ALGORITMOS SIMPLES
#include <iostream.h>
void main()
{
int i, n, t; // declara as vari
aveis.
cin >> n;
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.
cin >> n;
yk = yk + 2; :::; com y = 1
+1 1
An
alise
y1 =1
y2 =y 1 +2=3
y3 =y 2 +2=5
y4 =y 3 +5=7
y5 =y 4 +7=9
Projeto:
Esbo
co do algoritmo
leia n
dena o primeiro elemento
imprima o primeiro elemento
para i de 1 ate n-1 repita calcule o elemento seguinte
imprima esse elemento
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);
Implementa
c~ao.
#include <iostream.h>
void main()
{
int i, y, n; // declara as vari
aveis.
cin >> n;
y = 1;
Denic~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 denic~ao.
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
x 0=1
x 1= (x + x0 )=2 = 1; 5
0
2
Esbo
co do algoritmo
entrada de dados(valor de A)
denic~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 identicada 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.
cin >> A;
x = 1;
}
cout << x << endl;
}
Projeto:
Esbo
co do algoritmo
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 denidas pelas relac~oes de recorr^encia:
(a) yk +1 = yk + k; k = 1; 2; 3; :::; y = 11
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
Fn = Fn + Fn ; n 2
2 1
F = 1;
0
F =11
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
Projeto:
Esbo
co do algoritmo
Ler um numero A
repetir para cada elemento da lista Calcular A A
imprimir o resultado
Sentinela
A estrategia para vericar 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 vericada que o contrario. Como seria possvel vericar
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
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);
Implementa
c~ao.
#include <iostream.h>
void main()
{
int A, t; // declara as vari
aveis.
cin >> A;
while( A > 0 )
{
t = A*A;
cout << A << t;
cin >> A;
}
}
quadrados1()
leia(A);
repita
t AA
imprima(A; t)
leia(A)
ate que A 0
Implementa
c~ao de quadrados1().
#include <iostream.h>
void main()
{
int A, t; // declara as vari
aveis.
cin >> A;
do
{
t = A*A;
cout << A << t;
cin >> A;
} while(A>0);
}
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
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 );
Implementa
c~ao.
#include <iostream.h>
void main()
{
int N;
6 3 3
126 20 6 2 = mdc(126,20)
6 2 0
quociente 6 3 3
dividendo/divisor 126 20 6 2
resto 6 2 0
Projeto:
esbo
co do algoritmo
leitura dos dados
denic~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)
Implementa
c~ao.
#include <iostream.h>
void main()
{
int M, N;
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.
Projeto
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);
esbo
co do algoritmo
leitura dos dados
se A = B ent~ao
imprimir mensagem
sen~ao determinar o maior
imprimir o maior
Implementa
c~ao: maior1()
#include <iostream.h>
void main()
{
float max, 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;
if (A = B )
cout << ``Valores iguais" << endl;
else
{
if (A > B )
maior = A;
else
maior = B;
cout << ``Maior" << maior << endl;
}
}
Projeto:
Este problema e t~ao simples que escreveremos o algoritmo sem passar pela fase
de esboco.
Algoritmo maiorIdade
Objetivo: Vericar 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;
if (idade >= 18 )
cout << "Maior de idade" << endl;
else
cout << "Menor de idade" << endl;
}
Logo a seguir vericaremos 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:
Projeto:
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 identicar 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 renamento 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
denidos. Se as condic~oes que denem 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 modicados se as condic~oes que os denem 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;
INPS = 0;
IR = 0;
if (R>baseINPS)
INPS = taxaIR*R;
if (R-INPS>baseIR)
IR = taxaIR*(R-INPS);
sL
quido = R - INPS - IR;
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 ! verique 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
vericar quais as certas e imprimir os respectivos numeros
70 CAPITULO 3. COMANDOS ESTRUTURADOS
Para vericar 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
vericar a quest~ao 1, devemos vericar 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"
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");
#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;
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;
Fuc~oes de bibliotecas
Alem das operaco~es denidas sobre os elementos do tipo inteiro e real, vamos considerar,
a partir de agora, que temos disponvel uma biblioteca de func~oes. Isto signica 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 expecicac~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 especicar a
func~ao que esta sendo usada. Por exemplo, suponha que pretendemos usar a func~ao raz
quadrada, para isso devemos uncluir a sua especicac~ao(prototipo) sqrt : R ! R. + 4
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, identicar 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 graticac~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 identicac~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 noticada. As
industrias s~ao identicadas pelas letras A, B, C.
76 CAPITULO 3. COMANDOS ESTRUTURADOS
Fazer um programa para ler o ndice de poluic~ao e emitir relatorio noticando
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
Escolha
caso <condic~ao1>
<comando-composto1>
caso <condic~ao2>
<comando-composto2>
....
...
caso <condic~aoN>
<comando-compostoN>
sen~ao
<comando-compostoL>
m-Escolha.
Sem^
antica
O valor mnimo da taxa e 8 centavos e o valor maximo n~ao esta especicado.
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 vericar 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.
Vericar 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 simplicar 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);
Implementac~ao
#include <iostream.h>
void main()
{
int taxa, cinco, tr^
es, quociente, resto;
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.
Implementa
c~ao de selos2()
#include <iostream.h>
void main()
{
int taxa, cinco, tr^
es, quociente, resto;
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;
}
Projeto
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 denido");
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
esecicados 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 denido")
m
Implementa
c~ao
#include <iostream.h>
void main()
{
int a, b;
char op;
switch (op)
{
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;
}
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
Projeto
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').
Implementa
c~ao
#include <iostream.h>
~ MULTIPLA
4.1. SELECAO 93
void main()
{
int idade, cat;
char 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
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
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 renamentos 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 renamentos 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 denidas, apenas, pelo seu uso(ou efeito) e constituem uma denic~ao funcional do processo. Nas eta-
pas posteriores, cada descric~ao funcional e substituda por trechos mais detalhados que especicam as
etapas do processo. Quando no processo de desenvolvimento do algoritmo optamos pelos renamentos
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 denida. 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 especco e bem denido. Isto se torna muito importante na fase de vericac~ao do programa, pois
para verica-lo basta vericar 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 vericac~ao de sua correc~ao. Cada modulo implementado
como um procedimento deve conter sua propria documentac~ao e pode ser vericado 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
identica 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:
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.
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 especicar 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 denido recursivamente, ou seja:
n! = 1n;(se n 1)!; se n 1
n=0
Podemos escrever um algoritmo que implementa essa func~ao denida recursivamente.
int fat (int)
incio
int n;
se n=0 ent~ao
fat 1;
sen~ao
fat n fat(n 1);
m
Codicac~ao em C++
int fat (int n)
{
if (n=0)
fat = 1;
else
fat = n*fat(n-1);
return fat;
fat (3);
que retornara em fat o valor 6.
void ordene(void)
{
cout << "ordene()\n";
}
void compacte(void)
{
cout << "compacte()\n";
}
void imprima(void)
{
cout << "imprima()\n";
}
void e usado para especicar 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 denida, simplesmente anunciara sua presenca no terminal do usuario, quando
requisitada por main(). Mais adiante trocaremos essas inst^ancias mudas por denic~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 identicac~ao de um arquivo fonte de um programa e constituda de duas partes: o
nome do arquivo e o suxo do arquivo. O suxo variara de acordo com as diferentes
implementac~oes de C++. Para diferenciar um arquivo fonte C++ de C, usaremos o
suxo 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();
}
poderemos escrever
cout << 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;
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;
}
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;
#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, identicar 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 */
}
main()
{
int v1, v2; // cont
em valores do usu
ario
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(), denida
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
denida 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 especicadas 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
predenido ou padr~ao. Para pesquisar sua localizac~ao o preprocessador examinara um
conjunto predenido 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 denido. 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 #dene dene um nome que segue. No nosso exemplo, ela dene 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++ predene 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
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(especicac~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 especicar 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 denic~ao da estrutura de dados.
Uma implementac~ao de uma estrutura de dados e um mapeamento que especica 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 especicados 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 signica 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(predenidas) ou includas pelo usuario(tipo abstra-
do denido 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 denic~ao(especicac~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
dene 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 dene 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;
Para cada operaca~o(uma relac~ao sera vista como uma operac~ao booleana) deveremos
especicar:
A precondic~ao que deve ser aplicada aos dados antes que a operac~ao possa ser
efetuada.
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
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 especcos chamados constantes inteiras:
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.
N = dk dk :::d d ; para 0 di 9
10 1 2 1 0
representa
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
b (2 ); 0 bi 1
0
0
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
Tipos de caracteres
Os tipos de dados caracteres incluem itens alfanumericos que denem 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 dene 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:
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.
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 denido(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
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.
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
innita 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 innita binaria. Pelo fato do armazenamento do
computador ser restrito a numeros de comprimento xo, a cauda da ex-
panc~ao innita 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
cientca, com um sinal, mantissa e expoente:
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 denidos
pelo programador. Por exemplo, o que segue e uma listas dos mezes de 30 dias:
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.
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 denic~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 eciente 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
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.
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.
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
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.
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
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, dene o numero de linhas, o numero
de colunas, e o tipo de dados dos elementos:
tipo t [contadorDeLinha][contadorDeColuna];
"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.
Strings em C++
Numa outra oportunidade especicaremos 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 identica 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:
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 denidos 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
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"
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
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
// 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;
// copia o
ultimo nome em novoNome, acrescenta `,' e
// concatena primeiro nome.
strcpy(novoNome, p+1);
strcat(novoNome,nome);
strcat(novoNome,nome);
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;
}
}
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.
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
dene 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 denir 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 identica 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 especica 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.
#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],
double valor;
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
#\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;
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 ].
void main(void)
{
int lista[15] = {38,58,13,15,51,27,10,19,12,86,49,67,84,60,25,};
int i;
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;
};
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) "
// pula entrada n~
ao alfab
etica
while ( fin.get(c) && !isalpha(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";
void main(void)
{
const int tamM
aximo = 50; // tamanho m
aximo de cada palavra
int n;
char palavra[tamM
aximo];
ifstream fin;
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
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
cin >> i;
cin >> hex >> j >> dec;
cin >> k;
(a) cout << hex << i << " " << j << " " << dec << k << endl;
cout << dec << i << " " << hex << j << " " << k << endl;
6.9. EXERCICIOS 165
7. Escrever uma especicac~ao completa para operador % no tipo de dados inteiro. Faca
o mesmo para o operador de comparac~ao !=.
8. O tipo booleano dene dados que s~ao os valor verdadeiro ou falso. Algumas lingua-
gens de programac~ao dene 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++.
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
(a) 2,25
(b) 1,125
(c) 1,0875
N = +1; d d :::dn 2e
1 2 1
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
ExpoenteVerdadeiro ExpoenteArmazenado
Escopo escopo
-127 <= Exp <= 128 0 <= Exps <= 255
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 especicac~oes completas. O sucessor retorna o proximo item na lista e o pre-
decessor retorna o item anterior. Tome cuidado em denir o que acontece nos
extremos da lista.
18. Dados as seguintes declarac~oes e comandos, especicar 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;
e os comandos de entrada
cin >> s1 >> s2;
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
29. Adicone uma operac~ao tamDeArquivo() ao TAD para stream. Ele deve retornar o
numero de caracteres no arquivo. Tome cuidado quando especicar 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 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};
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
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 denido 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