You are on page 1of 10

Fundamentos de Programação em C: Uma Abordagem Algorítmica

“ O que destrói a sociedade? Política sem


princípios; Prazer sem compromisso;
Riqueza sem trabalho; Sabedoria sem
carácter; Negócios sem moral; Ciência
sem humildade; Oração sem caridade. ”

1
- Mahatma Gandhi -

Algoritmos

Sumário:
1.1- O Computador
1.2- Conceito de Algoritmo
1.3- Metodologia para Resolução de Problemas
1.4- Metodologia para Construção de Algoritmos
1.5- Exercícios Propostos

1
Fundamentos de Programação em C: Uma Abordagem Algorítmica

Este capítulo tem por objectivo apresentar de forma geral a arquitectura de um


computador e estudar uma metodologia científica para desenvolver algoritmos.
No seu término o leitor deverá ser capaz de:

 Descrever as principais partes de um computador.


 Caracterizar as linguagens de alto nível e de baixo nível.
 Conhecer as diferenças entre linguagens interpretadas e compiladas.
 Conhecer o conceito de algoritmo.
 Dominar uma metodologia para resolução de problemas.
 Resolver problemas numéricos e não numéricos com esta metodologia.

1.1- O Computador
Segundo Von Neuman, todo computador é constituído por três partes: a
unidade central de processamento, a memória e os dispositivos de entrada e
saída.

A unidade central de processamento, também conhecida por CPU (Central


Processing Unit) é responsável pela execução dos programas e pelo
comportamento das restantes partes do computador. Ela é formada por duas
partes: A unidade de aritmética e lógica e a unidade de controle.

A unidade de aritmética e lógica, tem por finalidade, efectuar as operações


aritméticas (soma, subtração, multiplicação, divisão, resto, etc), relacionais
(maior, menor, igual, maior ou igual, etc) e lógicas ( e, ou, não).

A unidade de controle, tem por finalidade, ler as instruções, alimentar a


unidade de aritmética e lógica e enviar os resultados desses cálculos, para a
memória ou para os dispositivos de entrada e saída.

Desde a década de 80 que a unidade de aritmética e lógica e a unidade de


controle, estão inseridas num único círcuito integrado, denominado por
microprocessador.

Existem vários fabricantes de microprocessadores. Os mais importantes são: a


Intel que fabrica o Pentium, a AMD que fabrica o Athlon e a IBM que produz o
PowerPC. Todo microprocessador possui um conjunto finito de instruções, que
são executados numa determinada frequência. Actualmente as frequências
estão entre 1 a 4 GHz (Giga Hertz).

A memória pode ser representada por gavetas. Cada gaveta possui oito
regiões e cada região é chamada de bit. Os oito bits de uma região formam
um byte e cada byte está associado à uma identificação numérica que é
denominada por endereço. Em cada endereço pode-se armazenar uma
informação, que pode ser uma instrução que diz ao computador o que fazer, ou
um dado que será utilizado para algum processamento.

2
Fundamentos de Programação em C: Uma Abordagem Algorítmica

As memórias estão classificadas em dois grupos: as voláteis e as


permanentes. As memórias voláteis RAM (Randon Access Memory)
necessitam de energia para guardar informações, isto quer dizer, que elas só
podem funcionar quando o computador estiver ligado. Quando desligamos o
computador, há informações importantes que devem ser armazenadas em
dispositivos de memórias permanentes. Os dispositivos de memórias
permanentes mais comuns são os discos duros e as fitas magnéticas.

Os dispositivos de memória volátil são mais caros, de menor capacidade e


muito mais rápidos do que os dispositivos de memória permanente. Por esse
facto, os computadores são muito eficientes no processamento de grandes
volumes de informação.

Os dispositivos de entrada/saída, definem como o computador comunica-se


com o mundo exterior. Como dispositivos de entrada mais comuns temos o
teclado, o mouse, o scanner, o microfone e a câmera. Como dispositivos de
saída mais comuns, temos o monitor (tela) e a impressora.

Um programa pode ser definido como uma sequência de instruções que


resolve um determinado problema. Os programas ficam armazenados em
dispositivos de memória permanente, vulgarmente denominados por memória
secundária.

Para executar um programa é necessário transferí-lo para a memória principal


ou RAM. A esse processo de transferência dá-se o nome de carregamento do
programa.

Contudo, os programas são executados pelo computador numa linguagem de


baixo nível, denominada por linguagem máquina ou assembler.

Mas, os programadores desenvolvem os seus programas numa linguagem de


alto nível, como o Pascal, o C, o Java, etc. Esses programas só podem ser
executados pelo computador, se tivermos uma ferramenta que os converta
para a linguagem máquina.

Esta conversão é feita por um programa especial. Contudo, existem duas


técnicas de tradução: a interpretação e a compilação.

Na primeira, os interpretadores, executam um programa numa linguagem de


alto nível, como se fosse escrito numa linguagem de baixo nível. Esta tradução
é feita linha por linha, e o programa é executado a medida que a tradução é
feita. Sempre que precisarmos de executar o programa, essa tradução deverá
ser realizada.

Ao contrário, os compiladores produzem a partir de um programa escrito


numa linguagem de alto nível, um outro programa equivalente, escrito numa
linguagem de baixo nível. Esta tradução é feita uma única vez e o programa
traduzido pode ser executado sempre que for necessário.

3
Fundamentos de Programação em C: Uma Abordagem Algorítmica

Desse modo, podemos concluir que um compilador é um programa que traduz


um programa escrito numa linguagem de alto nível (chamado por código
fonte), para um programa escrito numa linguagem de baixo nível (chamado por
código objecto).

1.2- Conceito de Algoritmo


Os algoritmos fazem parte do dia-a-dia das pessoas. As indicações para
chegar à uma rua, uma planta de uma casa, as instruções para montar um
electrodoméstico, uma receita de cozinha, são alguns exemplos de algoritmos.

Informalmente, um algoritmo é uma descrição passo a passo da resolução de


um determinado problema. A sua descrição deve ser finita, os passos devem
estar bem definidos, sem ambiguidade executáveis por um agente
computacional ou humano num determinado intervalo de tempo.

De facto, um algoritmo não é a solução de um problema, mas um esquema, um


raciocínio lógico, uma sequência de acções para sua resolução. Isto quer dizer
que podem existir vários algoritmos que resolvem o mesmo problema. As
diferenças entre eles residem na estratégia de resolução e na qualidade da
resposta.

A título ilustrativo veremos um exemplo de natureza humana: Vestir uma calça,


calçar os sapatos e as meias.

A maior parte das pessoas resolve esse problema com os seguintes passos:

1º- Vestir as calças


2º- Colocar as meias
3º- Calçar os sapatos

mas, existem algumas pessoas, que resolvem esse problema da seguinte


maneira:

1º- Colocar as meias


2º- Vestir as calças
3º- Calçar os sapatos

Contudo, existem muito poucas pessoas, casos raros, que resolvem no


problema da seguinte forma:

1º- Colocar as meias


2º- Calçar os sapatos
3ª- Vestir as calças

4
Fundamentos de Programação em C: Uma Abordagem Algorítmica

Na computação (informática) é muito importante resolver um problema com um


algoritmo que gaste o menor tempo possível e que ocupe o menor espaço de
memória, ou seja um algoritmo óptimo.

1.3- Metodologia para Resolução de Problemas


Infelizmente, os computadores só executam as operações que mandamos e
não as operações que queremos. Por esse facto, as instruções de um
programa não devem ser ambíguas e não podem dar a possibilidade de
interpretações duvidosas, porque o computador sempre executará uma acção.

É necessário ter muito cuidado e ser muito preciso, para garantir que o
computador execute as acções que realmente pretendemos. Por exemplo, a
instrução “calcular a média das notas de uma turma”, é muito imprecisa, apesar
de exprimir o que queremos. Muitos detalhes foram omitidos. Para que essa
instrução possa ser executada por um computador é necessário detalhar as
seguintes acções: Onde estão as notas, quantos alunos são, quantas notas por
aluno, se os ausentes devem ser incluídos, se o cálculo da média baseia-se na
média aritmética ou ponderada, se for a média ponderada qual o valor dos
pesos, etc. Esta é a essência da programação.

A programação de computadores é uma tarefa muito difícil e complexa. Mas,


para contornar essa complexidade é necessário dividir o problema em partes
mais simples.

Em primeiro lugar é necessário separar a resolução do problema em duas


fases: A fase de especificação e a fase de implementação. A fase de
especificação consiste na construção de um algoritmo. Quando tivermos a
certeza que esse algoritmo resolve o problema, passamos para a fase de
implementação. A fase de implementação consiste na tradução do algoritmo
para uma linguagem de programação, ou seja, na elaboração de um
programa. Se o algoritmo for suficientemente preciso, a sua codificação para o
programa, consiste, em alguns casos, numa mera tradução.

1.4- Metodologia para Construção de Algoritmos


Para construir um algoritmo utilizaremos a metodologia de refinamento
sucessivo. Essa metodologia consiste em definir numa primeira abordagem,
uma solução muito abstracta para o problema. Em seguida, refinar essa
solução em várias versões, ou estágios. Em cada versão, descrever os
detalhes que foram omitidos na versão anterior. Quando chegarmos à uma
solução cujas acções são simples e sem ambiguidade o processo de
refinamento termina.

5
Fundamentos de Programação em C: Uma Abordagem Algorítmica

A técnica de refinamento sucessivo, denominada por Top-Down, foi


desenvolvida pelos seguintes cientistas da computação: Milles Harlan,
Dijkastra Edsger Wybe e Wirth Niklaus.

A título ilustrativo, vamos desenvolver um algoritmo para resolver um problema


não numérico: Trocar um pneu de um carro.

Numa primeira abordagem, a solução do nosso problema pode ser descrita


pelos seguintes passos:

1- Remover o pneu furado


2- Colocar o pneu de socorro

Suponhamos que queremos instruir um robô doméstico, que apenas realiza


operações elementares, para executar esses passos. Como esses passos não
são suficientemente precisos nem simples, o nosso robô não tem condições de
executar a tarefa. Por esse facto, vamos detalhar essa versão.

Em primeiro lugar, é necessário conhecer as operações que caracterizam o


passo “Remover o pneu furado”. Para remover um pneu de um carro,
necessitamos de um macaco, uma chave de rodas e um pneu de socorro.
Vamos admitir que temos essas ferramentas. Agora, a nossa preocupação é
saber onde elas estão guardadas. Sabemos que as ferramentas encontram-se
no porta-bagagem. Retiramos as ferramentas do porta-bagagem e iniciamos a
remoção do pneu. Essa operação consiste nas seguintes acções: levantar o
carro, desenroscar as porcas e retirar o pneu furado. Então, o passo “ Remover
o pneu furado” será expandido para:

Retirar o macaco, chaves de rodas e pneu de socorro


Desenroscar as porcas
Levantar o carro
Retirar o pneu furado

Vamos analisar em seguida o passo “ Colocar o pneu de socorro”. Nesse


instante, o pneu de socorro e o pneu furado encontram-se no chão. Logo,
podemos fixar o pneu de socorro na roda, enroscar as porcas, baixar o carro,
guardar as ferramentas e o pneu furado. Então o passo “ Colocar o pneu de
socorro” será expandido para:

Colocar o pneu de socorro na roda


Enroscar as porcas
Baixar o carro
Guardar a ferramenta e o pneu furado

Com esse refinamento, o nosso algoritmo para trocar o pneu de um carro tem
agora oito passos:

1- Retirar o macaco, as chaves de rodas e o pneu de socorro

6
Fundamentos de Programação em C: Uma Abordagem Algorítmica

2- Desenroscar as porcas
3- Levantar o carro
4- Retirar o pneu furado
5- Colocar o pneu de socorro
6- Enroscar as porcas
7- Baixar o carro
8- Guardar a ferramenta e opneu furado

Observe que as acções são executadas de forma sequencial, ou seja,


executamos uma acção, e apôs o seu término, executamos a acção seguinte.
Com isso, introduzimos um conceito muito importante de programação. A
capacidade do computador executar várias instruções de forma sequencial.

Mas, esta versão não pode ser executada pelo nosso robô doméstico, porque
algumas acções são realizadas por várias operações mais simples. Por
exemplo: Levantar o carro, consiste em:

Enquanto a roda não estiver no ar


Girar a manivela do macaco no sentido horário

Com essa acção, introduzimos mais um conceito importante de programação.


A capacidade do computador repetir uma ou várias instruções, até que
aconteça algum evento.

Em função desse novo conceito, vamos detalhar as seguintes acções:


desenroscar as porcas, enroscar as porcas e baixar o carro. O nosso algoritmo
terá agora treze passos:

1- Retirar o macaco, as chaves de rodas e o pneu de socorro


2- Para cada porca
3- Desenroscar até ficar solta
4- Enquanto a roda não estiver no ar
5- Girar a manivela do macaco no sentido horário
6- Retirar o pneu furado
7- Colocar o pneu de socorro
8- Para cada porca
9- Fixar a porca
10- Enroscar a porca até ficar presa
11- Enquanto a roda não estiver no chão
12- Girar a manivela do macaco no sentido anti-horário
13- Guardar a ferramenta e o pneu furado

Mas, o que acontece se o pneu de socorro estiver furado? O que acontece se o


macaco estiver estragado? O que acontece se houver alguma coisa que não
esteja nesse roteiro? A resposta é muito simples, o algoritmo não funciona.

Com estas perguntas, iremos introduzir mais um conceito importante de


programação. A capacidade do computador executar uma operação num
conjunto de várias alternativas possíveis.

7
Fundamentos de Programação em C: Uma Abordagem Algorítmica

Para não tornar o problema muito complexo, vamos supor que o macaco e a
chave de rodas estão em condições.

Antes de levantar o carro é necessário verificar se o pneu de socorro está em


condições. Se não estiver, levá-lo a reparação. Então, a versão anterior pode
ser detalhada com esta condição.

1- Retirar o macaco, as chaves de rodas e o pneu de socorro


2- Se o pneu socorro está vazio
3- Levar o pneu para a recauchutagem
4- Senão
5- Para cada porca
6- Desenroscar até ficar solta
7- Enquanto a roda não estiver no ar
8- Girar a manivela do macaco no sentido horário
9- Retirar o pneu
10- Colocar o pneu de socorro
11- Para cada porca faça
12- Fixar a porca
13- Enroscar até ficar presa
14- Enquanto a roda não estiver no chão
15- Girar a manivela do macaco no sentido anti-horário
16-Guardar a ferramenta e o pneu furado

Facilmente se constata, que esse processo de refinamento pode continuar de


forma quase indefinida. Contudo, esse algoritmo mostra como os algoritmos
devem ser expressos e construídos. As operações são simples, claras e sem
ambiguidade. As acções são escritas no imperativo (coloque, fixe, guarde, etc)
ou no transitivo (colocar, fixar, guardar, etc). A ordem pela qual os passos
devem ser seguidos é precisa e as decisões são tomadas e executadas
imediatamente.

Como é que sabemos que um determinado nível de detalhe é suficiente? A


resposta a essa questão é muito discutível, ela depende do nível e da
experiência do programador que vai implementar o algoritmo.

1.6- Representação de Algoritmos


Contudo, existem muitas formas de representar algoritmos. As mais comuns
são:

Linguagem Natural: Os algoritmos são expressos na língua materna do


programador. A principal vantagem é que descrevemos o algoritmo na forma
que escrevemos sem a necessidade de uma notação especial. Mas a principal
desvantagem, reside no facto desta metodologia poder dar vazão à várias
interpretações se o algoritmo não estiver bem detalhado, e com isso, dificultar o
processo de transcrição do algoritmo para o programa.

8
Fundamentos de Programação em C: Uma Abordagem Algorítmica

Fluxograma: É uma representação gráfica que emprega formas geométricas


para indicar as diversas ações e decisões que devem ser executadas para
resolver um problema. A principal vantagens reside no facto de ser mais fácil
entender a resolução gráfica do que a resolução textual. Mas as principais
desvantagens residem nos seguintes factos: os dados não são descritos com o
detalhe suficiente, o que dificulta o processo de transição do algoritmo para o
programa; necessitamos de conhecer e dominar a simbologia; para programas
muito extensos a construção de fluxogramas torna-se uma tarefa muito árdua e
inviável.

Pseudocódigo: Este forma de desenvolvimento de algoritmos procura


empregar uma linguagem que esteja o mais próximo possível das linguagens
de programação de alto nível, mas com poucas regras de construção. A ideia é
utilizar as vantagens do emprego da linguagem natural com um subconjunto de
regras sintácticas das linguagens de alto nível. Normalmente estas linguagens
são versões reduzidas do Pascal ou do C. A principal vantagem reside no facto
da passagem do algoritmo para qualquer linguagem de programação ser
quase que imediata, enquanto a principal desvantagem residir no facto de
termos a necessidade de conhecer as regras do pseudocódigo.

Em função das vantagens e desvantagens desses métodos de representação


optamos pela linguagem natural por ser mais fácil de entender e utilizar.

1.6- Exercícios Propostos

1.6.1-Desenvolva um algoritmo para substituir uma lâmpada

1.6.2-Suponhamos que temos um conjunto de 9 moedas. Uma destas moedas


é mais pesada do que as outras. Desenvolva um algoritmo para encontrar essa
moeda.

1.6.3-Desenvolva um algoritmo para efectuar uma chamada telefónica

1.6.4-Um homem necessita de atravessar um rio, mas possui um barco que só


pode carregar o homem e mais uma de suas três cargas, que são: Um lobo,
um coelho e um alface. Se o lobo e o coelho ficam sozinhos na margem do rio,
o lobo come o coelho, mas se o coelho e o alface ficam sozinhos na margem
do rio, o coelho come o alface. Desenvolva um algoritmo para que o homem
atravesse o rio com as suas três cargas sem perder uma delas.

1.6.5-Desenvolva um algoritmo para fazer uma sanduíche completa.

9
Fundamentos de Programação em C: Uma Abordagem Algorítmica

1.6.6-Desenvolva um algoritmo para fazer um bolo. Se não souber peça uma


explicação a alguém.

1.6.7-Desenvolva um algoritmo para mudar o pneu de uma bicicleta.

1.6.8-Três missionários estão na margem de um rio com três canibais e


desejam atravessá-lo, utilizando um barco com a capacidade para duas
pessoas. O problema é que se o número de canibais for maior do que o
número de missionários, em qualquer margem do rio, os canibais comem os
missionários. Desenvolva um algoritmo para resolver a questão.

1.6.9-Suponhamos que possuímos três jarras não graduadas com 8, 5 e 3


litros. A jarra de 8 litros está cheia de vinho. Desenvolva um algoritmo para
repartir esse vinho pelas duas jarras maiores em partes iguais.

1.6.10-Dados 3 discos de tamanhos necessariamente distintos e 3 hastes. A


haste origem, destino e trabalho. Os discos encontram-se na haste origem em
ordem decrescente de tamanho, de baixo para cima. O objectivo é empilhar
todos os três discos na haste destino de com base nas seguintes propriedades:

(i) Apenas um disco pode ser movido de cada vez;

(ii)Qualquer disco não pode ser colocado sobre outro de menor tamanho.

1.6.11-Suponhamos que temos dois jarros, um de cinco litros e outro com três
litros. Suponhamos também que temos uma fonte inesgotável de água.
Determine uma sequência de movimentos para encher e esvaziar os jarros de
tal modo que no fim da sequência tenhamos quatro litros de água dentro de um
jarro e cinco litros dentro de outro.

1.6.12-Suponhamos que temos 100 moedas distribuídas numa tabela (matriz)


com 10 linhas e 10 colunas. Todas as moedas têm 10 gramas com excepção
das moedas de uma coluna. Nessa coluna especial, as moedas têm 9 gramas.
Descobrir qual é a coluna que possui moedas com 9 gramas, utilizando apenas
uma balança comum.

1.6.13-Cinco pessoas necessitam de atravessar uma ponte sem iluminação.


Mas elas têm apenas uma lamparina, cuja chama tem a duração de 30
minutos. A ponte é muito estreita e só podem atravessar duas pessoas de cada
vez. Cada pessoa gasta um determinado tempo que é descrito a seguir.
Desenvolva um algoritmo que instrua as pessoas a atravessar a ponte antes de
a lamparina apagar-se. Mas quando duas pessoas atravessarem a ponte, o
tempo para atravessá-la é determinado pela pessoa mais lenta. Tempos em
minutos para atravessar a ponte são: Kizua 1, Joelma 3, Diana 6, Osvaldo 8 e
a Palmira 12.

10

You might also like