Logo Passei Direto
Material

This is a file preview. Join to view the original file.

introducao-a-programacao-livro-1.0.0/.gitignore
/livro/AAPDIR
/livro/*.png
/livro/*.zip
/livro/*.chunked
/livro/*.pdf
/livro/*.txt
/livro/slides.html
/livro/livro.xml
/livro/livro.tex
*.pdf
*.zip
releases
originais
materiais
introducao-a-programacao-livro-1.0.0/README.asciidoc
== Livro da disciplina "Introdução à Programação"
Este repositório contém um livro da disciplina "Introdução à Programação".
Para conhecer o seu processo de produção consulte 
https://github.com/edusantana/producao-computacao-ead-ufpb.
introducao-a-programacao-livro-1.0.0/ignore-html
introducao-a-programacao-livro-1.0.0/ignore-slide
introducao-a-programacao-livro-1.0.0/livro/capitulos/algoritmos.asc
[[algoritimos]]
== Algoritmos
.Objetivos do capítulo
____________________
Ao final deste capítulo você deverá ser capaz de:
* Definir algoritmo
* Descrever suas principais características
* Criar algoritmos utilizando diferentes formas de representação
____________________
É comum pensarmos em uma estratégia para executar uma tarefa do nosso 
dia a dia, mesmo que ela seja muito simples. Ao escovar os dentes, por exemplo, 
nós seguimos diferentes estratégias. Uns começam com a escovação dos 
molares e depois partem para os dentes da frente, outros fazem o inverso. 
Enfim, existem várias formas de escovarmos os dentes, assim como existem 
várias maneiras de realizarmos diversas atividades. Você sabia que o conjunto 
de passos para resolver um certo problema ou realizar determinada tarefa 
chama-se algoritmo? E que eles são importantíssimos para a programação de 
computadores? 
Neste capítulo estudaremos as características dos algoritmos, suas formas de 
representação e, sobretudo, a relação entre eles e a programação de 
computadores.
=== Introdução
Fonte inspiradora de livros e filmes, o americano Monty Roberts (<<monty>>), 
conhecido como o “encantador de cavalos”, revolucionou a forma de domar 
cavalos. Ao estudar o comportamento de cavalos selvagens, percebeu que existe 
entre eles uma linguagem corporal compartilhada. Entendendo tal linguagem, 
conseguiu rapidamente ganhar a confiança de cavalos arredios e instruí-los 
a se comportarem como desejava. Além de não usar de violência, essencial no 
emprego dos métodos convencionais, seu método é capaz de domar cavalos em 
poucos dias, ao contrário da maioria, que normalmente necessita de várias 
semanas.
[[monty]]
.Monty Roberts.
image::images/algoritmos/monty.jpg[scaledwidth="25%"]
Assim como os cavalos, os computadores também são instruídos por meio de uma 
linguagem particular. Para que eles se comportem como desejamos, basta que sejam 
comandados a partir de uma linguagem que sejam capazes de entender.
Diferentemente do que ensina o senso o comum, os computadores não possuem 
inteligência. Seu único trabalho é processar dados, conforme uma sequência 
de instruções que fazem parte do vocabulário da linguagem que eles conseguem 
compreender. A ilusão de que eles realizam tarefas de forma inteligente é 
proporcionada através desse conjunto ordenado de instruções, que é 
denominado de algoritmo. Neste caso, o “domador” do computador, responsável por 
elaborar o algoritmo que vai orientá-lo na execução de uma determinada 
tarefa, é chamado de programador de computadores.
=== O que é um algoritmo?
A palavra “algoritmo” é derivada do nome Mohammed ibn Musa 
Al-Khowarizmique, que foi um matemático, astrólogo, astrônomo e autor 
persa. Ele fez parte de um centro acadêmico conhecido como a Casa da 
Sabedoria, em Bagdá, por volta de 800 d.C. Seus trabalhos introduziram o 
cálculo hindu aos árabes e, a partir daí, ao resto da Europa. 
Não obstante os algoritmos representam um conceito central na Ciência da 
Computação, sua atuação não se limita a essa área do conhecimento. 
Rotineiramente, lidamos com algoritmos na realização das mais variadas 
tarefas. Eles podem ser utilizados para lavar um carro, preparar um bolo, tomar 
banho, montar um guarda-roupa, etc. Perceba que os algoritmos não devem ser 
confundidos com as atividades. Eles se referem aos passos seguidos para que 
estas sejam realizadas. Como exemplo de algoritmos, podemos citar as 
instruções para montagem de equipamentos, para utilização de cosméticos 
como shampoos e condicionadores, para saída de emergência em meios de 
transporte, receitas culinárias, manuais de uso, entre outros.
A partir do que foi exposto, podemos definir algoritmo como 'uma sequência 
finita, ordenada e não ambígua de passos para solucionar determinado problema 
ou realizar uma tarefa'. 
Na ciência da computação, esse conceito foi formalizado em 1936, por Alan Turing e 
Alonzo Church, da seguinte forma:
.Definição de Algorítimo
____________________
Um algoritmo é um conjunto não ambíguo e ordenado de passos executáveis que 
definem um processo finito.
____________________
////
TODO - REV.01: Sugestão de melhoria para análise pelo autor: 
apesar de parecer repetitivo, talvez fosse interessante explicar melhor a definição dada acima. 
Por exemplo, exemplificar o que seria não ambíguo, ser ordenado e passos executáveis.
////
O exemplo a seguir mostra como pode ser elaborado um algoritmo para realizar 
uma atividade com a qual lidamos corriqueiramente:
[[fritar-ovo]]
.Algoritmo para fritar um ovo
. Retire o ovo da geladeira.
. Coloque a frigideira no fogo.
. Coloque óleo na frigideira.
. Quebre ovo, separando a casca.
. Ponha a clara e a gema na frigideira.
. Espere um minuto.
. Apague o fogo.
. Retire o ovo da frigideira.
////
TODO - REV.02: Sugestão de melhoria para análise pelo autor:
talvez fosse interessante colocar aqui um parágrafo simples informando que 
várias atividades do nosso dia a dia podem ser representadas por algoritmos
e citar outros exemplos próximos do dia a dia do aluno, além de reforçar
que existe várias formas de resolver o mesmo problema. Para só em seguida, 
apresentar o exemplo dado no parágrafo seguinte.
////
Agora considere o seguinte problema. Suponha que você dispõe de duas vasilhas 
de nove e quatro litros respectivamente. Como elas não possuem marcação, não é 
possível ter medidas intermediárias sobre o volume ocupado. O problema 
consiste, então, em elaborar uma sequência de passos, por meio da 
utilização das vasilhas de nove e quatro litros, a fim de encher uma terceira 
vasilha com seis litros de água. A figura abaixo ilustra dois possíveis 
passos de um algoritmo para resolver o problema.
.Ilustra dois passos possíveis envolvendo as operações de encher e esvaziar as vasilhas. Em (a) apenas a primeira vasilha está cheia. Já em (b) os nove litros da primeira vasilha são colocados nas outras duas.
image::images/algoritmos/ilustracao-dois-passos.eps[scaledwidth="55%"]
Uma solução para o problema pode ser alcançada a partir do seguinte 
algoritmo:
[[vasilha]]
.Algoritmo para encher vasilhas
. Encha a vasilha de nove litros.
. Usando a vasilha de nove litros, encha a de quatro.
. Coloque a quantidade que sobrou (cinco litros) na terceira vasilha (*v3 = 5*).
. Esvazie a vasilha de quatro litros.
. Encha novamente a vasilha de nove litros.
. Usando a vasilha de nove litros, encha a de quatro.
. Esvazie a de quatro litros.
. Usando a sobra da de nove litros (cinco litros), encha novamente a de quatro 
litros.
. Coloque a sobra da de nove litros (agora um litro) na terceira vasilha 
(*v3 = 5 + 1 = 6*).
=== Características de um algoritmo
Todo algoritmo, seja ele computacional ou não, recebe uma entrada, processa-a 
e gera uma saída segundo seu conjunto de passos. No caso do algoritmo para 
fritar ovo, a entrada corresponde à frigideira, ao ovo e ao óleo. O 
processamento ocorre com a execução de seus passos, gerando como saída o ovo 
frito. 
////
TODO - REV.03: Sugestão de melhoria para análise pelo autor:
Não há como suavizar mais a transição de um parágrafo para o outro?
Uma sugestão seria:
"Além dessas três características básicas - entrada, processamento,
saída - um algoritmo apresenta outras características, dentre elas, podemos destacar:
..."
////
Os algoritmos computacionais, especificamente, possuem as seguintes 
características:
Definição:: Os passos de um algoritmo devem ser bem definidos, objetivando a 
clareza e evitando ambiguidades.
////
TODO - REV.04: Sugestão de melhoria para análise pelo autor:
Há como fornecer um simples exemplo do não atendimento dessa característica?
////
Finitude:: Um algoritmo deve chegar ao seu fim após um número finito de 
passos.
////
TODO - REV.05: Sugestão de melhoria para análise pelo autor:
Há como fornecer um simples exemplo do não atendimento dessa característica?
////
Efetividade:: Um algoritmo deve ser efetivo, ou seja, suas operações devem 
ser básicas o suficiente para que possam, em princípio, serem executadas de 
maneira exata e em um tempo finito.
////
TODO - REV.06: Sugestão de melhoria para análise pelo autor:
Há como fornecer um simples exemplo do não atendimento dessa característica?
////
Entradas:: Um algoritmo deve possuir zero ou mais entradas. Estas são insumos 
ou quantidades que são processados pelos algoritmos durante a execução de 
seus passos.
Saídas:: Um algoritmo deve possuir uma ou mais saídas. Elas representam o 
resultado do trabalhado realizado pelos algoritmos.
=== Formas de representação
As formas mais comumente utilizadas para representar algoritmos são as 
seguintes:
- Descrição narrativa
- Fluxograma
- Linguagem Algorítmica
Todas elas apresentam pontos fortes e fracos, não existindo consenso entre os 
especialistas sobre a melhor forma de representação. Apresentaremos as 
nuances de cada uma nas próximas seções.
==== Descrição Narrativa
Os algoritmos são expressos em linguagem natural (português, inglês, 
francês, espanhol, etc.). Sua principal desvantagem se encontra no fato da 
linguagem natural estar bem distante da linguagem utilizada pelos computadores. 
Logo, a tradução de uma para a outra se torna uma atividade bastante 
dispendiosa. Além disso, linguagens naturais são mais propensas a 
ambiguidades. Muitas vezes uma palavra pode ter vários significados, 
dependendo do contexto no qual são utilizadas. Em contrapartida, é bem mais 
fácil elaborar um algoritmo por meio de uma linguagem com a qual já temos uma 
certa familiaridade, do que através de linguagens que não são utilizadas com 
frequência no dia a dia. 
Os exemplos de algoritmos mostrados anteriormente (<<fritar-ovo>> e <<vasilha>>) 
refletem esta forma de representação.
==== Fluxograma
Consiste em usar formas geométricas padronizadas para descrever os passos a 
serem executados pelos algoritmos. As formas apresentadas na Figura 1.3 são as 
mais comumente utilizadas em fluxogramas.
.Formas geométricas utilizadas em fluxogramas
image::images/algoritmos/fluxograma.eps[scaledwidth="50%"]
A vantagem de se fazer uso dos fluxogramas está na facilidade de 
compreendê-los. Descrições de algoritmos mediante formas gráficas são mais 
facilmente compreendidas do que descrições que envolvem apenas textos. Além 
do mais, os fluxogramas possuem um padrão mundial no que se refere à sua 
simbologia, tornando sua utilização independente das peculiaridades das 
linguagens naturais. 
////
TODO - REV.07: Dúvida sobre o conteúdo:
Será explicado em algum outro momento o uso de fluxogramas para elaboração
dos algoritmos? 
////
Para exemplificar o uso de fluxogramas, a <<fluxograma-calcular-media>> 
mostra um algoritmo para 
calcular a média final de um aluno com base em suas notas e classificá-lo 
como aprovado ou reprovado. Analisando-a com mais cuidado, é possível 
perceber que os fluxogramas tendem a crescer bastante quando descrevem 
algoritmos constituídos de muitos passos, o que dificulta tanto sua 
construção como sua visualização. Além dessa desvantagem, por impor regras 
para sua utilização de acordo com cada forma geométrica, há uma limitação 
no seu poder de expressão, se comparado com a descrição narrativa.
////
TODO - REV.08: Sugestão de melhoria para análise pelo autor:
Achei o exemplo pesado para o aluno que ainda viu muito pouco
sobre a elaboração de algoritmos com fluxogramas. Talvez fosse
interessante fazer o mesmo exemplo usando a representação narrativa,
isso auxiliaria o aluno no entendimento das representações e suas vantagens
e desvantagens. 
////
[[fluxograma-calcular-media]]
.Fluxograma para calcular a média de um aluno
image::images/algoritmos/fluxograma-calcular-media.eps[scaledwidth="75%"]
==== Linguagem Algorítmica
////
TODO - REV.09: Sugestão de melhoria para análise pelo autor:
Para não assustar muito os alunos, eu colocaria toda essa seção que se fala
da arquitetura de von Neumann em uma seção a parte do tipo "Você sabia?". 
Deixaria apenas a discussão que a linguagem algorítmica são linguagens intermediárias etc. 
////
A linguagem que o computador é capaz de compreender tem grande influência na 
elaboração de algoritmos projetados para ele. Seus passos não podem conter 
instruções desconhecidas ou fazer referência a símbolos ou expressões que 
os computadores não conseguem decifrar. Tal linguagem, tantas vezes mencionada 
neste capítulo, se baseia em conceitos e em arquiteturas de hardware que 
determinam o funcionamento básico de um computador. Dentre as existentes, a 
mais utilizada nos computadores atuais é a arquitetura de von Neumann. Seu 
autor, John Von Neumann (<<john-von-neumann>>), propôs um modelo em que as instruções 
e os dados ficam juntos na memória.
O processador busca as instruções na memória e as executa uma de cada vez, 
segundo o seguinte ciclo de execução:
. Busca instrução;
. Decodifica instrução;
. Executa instrução;
. Volta para o passo 1 para buscar a instrução seguinte na memória.
[[john-von-neumann]]
.John von Neumann
image::images/algoritmos/john-von-neumann.jpg[scaledwidth="15%"]
Para esclarecer como funciona a execução de um algoritmo baseado no ciclo de 
execução mencionado, considere uma memória com 32 posições para 
armazenamento, organizada conforme <<memoria32posicoes>>.
[[memoria32posicoes]]
.Representação de uma memória com 32 posições para armazenamento. 
image::images/algoritmos/memoria32posicoes.eps[scaledwidth="40%"]
Os números do canto superior direito de cada célula indicam os endereços de 
memória correspondentes a cada posição da memória representada. Nas três 
primeiras células constam as instruções que serão executadas e, da oitava 
à décima, constam valores armazenados nas posições de memória nomeadas por 
x, y e z, respectivamente.
Supondo que a execução do algoritmo em questão inicia-se com a busca da 
instrução no endereço 0 (zero), o ciclo de execução continua com a 
decodificação da instrução x = 2, que, após sua realização, resulta no 
armazenamento do valor 2 na posição de memória de número 8, nomeada de x. O 
passo 4 então é executado, dando início à busca da próxima instrução. 
Com isso, a instrução y = 3 é encontrada e decodificada, gerando como 
resultado o armazenamento do valor 3 na posição de número 9, nomeada de y. O 
mesmo ocorre com a instrução z = x.y, que, após sua decodificação, 
armazena o valor 6 (produto de x por y) na posição de endereço 10 e rotulada 
de z. O algoritmo em descrição narrativa para a execução das instruções 
anteriores encontra-se logo abaixo:
.Algoritmo para multiplicar dois números
. Escreva 2 na posição de memória nomeada de x.
. Escreva 3 na posição de memória nomeada de y.
. Multiplique x e y e o resultado escreva em z.
Modelos como o mencionado anteriormente não apenas definem a forma como os 
dados são processados pelo computador, mas também a linguagem que eles são 
capazes de compreender. Assim sendo, a linguagem utilizada pelos computadores 
está restrita a um conjunto limitado de instruções, cujo funcionamento 
depende
de sua arquitetura de hardware. As linguagens de programação 
imperativas (Pascal, C, Cobol etc), por exemplo, foram criadas em função da 
arquitetura de von Neumman.
////
TODO - REV.10: Sugestão de melhoria para análise pelo autor:
Nada foi falado sobre linguagem de alto nível ou baixo nível, dessa forma,
será que vale a pena mencionar isso sem explicá-las aqui? Não confundiria 
mais o aluno? Um sugestão seria colocar links para seções "Você sabia?" ou 
vídeos, etc. 
////
A linguagem algorítmica, também chamada de pseudocódigo ou pseudo-linguagem, 
por sua vez, consiste no emprego de uma linguagem intermediária entre a 
linguagem natural e uma linguagem de programação. Esse meio termo resulta em 
uma linguagem que se aproxima das construções de uma linguagem de 
programação, sem exigir, no entanto, rigidez na definição das regras para 
utilização de suas instruções. Geralmente, essa forma de representação de 
algoritmos é uma versão reduzida de linguagens de alto nível como C e 
Pascal. Segue abaixo o algoritmo da <<fluxograma-calcular-media>> 
em pseudocódigo:
////
TODO: criar um hightlight para pseudocódigo
Ver: http://xpt.sourceforge.net/techdocs/nix/tool/asciidoc-usg/ascu03-SourceCodeHighlighting/single/
Ou : asciidoc-8.6.8/filters/code
////
[source,pascal,numbered]
-------------------------------------------
ALGORITMO
 DECLARE nota1, nota2, M : NUMÉRICO
 LEIA nota1
 LEIA nota2
 M ← (nota1 + nota2) / 2
 SE M >= 7.0 ENTÃO
 ESCREVA “Aprovado”
 SENÃO
 ESCREVA “Reprovado”
 FIM-SE
FIM_ALGORITMO.
-------------------------------------------
////
TODO - REV.11: Dúvida do conteúdo:
Na explicação das palavras reservadas do pseudocódigo há
palavras que não estão representadas no exemplo e são mencionados. Por exemplo,
'INICIO' e 'FIM'. Precisa deixar coerente com o apresentado, pois, em princípio 
o aluno ainda não entende nada do assunto, e assim, é dificil se abstrair
dos detalhes. 
////
As palavras em letras maiúsculas correspondem a palavras reservadas que fazem 
parte do conjunto de regras que a linguagem algorítmica deve seguir.
////
TODO - REV.12: Sugestão de melhoria para análise pelo autor - referente as linhas 388 e 389
Acho que vale a pena aqui reforçar ao aluno que isso significa que qualquer algoritmo
desenvolvido com a linguagem só poderá ser feito usando as palavras reservadas e apenas elas.
////
Embora 
sejam mais flexíveis do que as linguagens de programação em relação ao seu 
uso (a instrução `LEIA`, por exemplo, muitas vezes é substituída por 
`LER`, `OBTER`, etc.), algumas palavras são necessárias, pois 
facilitam o entendimento e aproximam o pseudocódigo de um programa de 
computador. As palavras `INÍCIO` e `FIM`, por exemplo, indicam onde 
começa e termina o algoritmo. Já as instruções `LEIA` e `ESCREVA` 
referem-se a operações de entrada e saída de dados (ex.: ler dados do 
teclado ou exibir uma frase no monitor), presentes na maioria das linguagens de 
programação. 
Seguindo com a explicação do algoritmo, perceba que a linha com a instrução 
`M ← (nota1 + nota2) / 2` contém dois símbolos ainda não apresentados. 
O símbolo `/` diz respeito à operação aritmética da divisão, ao passo 
que o símbolo `←` expressa uma operação de atribuição, que pode ser 
lida da seguinte forma: 'A posição de memória, representada simbolicamente 
por M, recebe o valor da soma de nota1 e nota2, dividido por dois'. Para 
finalizar, a linha 6 apresenta uma estrutura de controle condicional essencial 
para as linguagens de programação. Operações de atribuição, expressões e 
estruturas de controle fazem parte do núcleo das linguagens de programação 
imperativas e são, portanto, fundamentais para o aprendizado da programação. 
Todos esses assuntos serão abordados de forma mais aprofundada em capítulos 
posteriores.
A principal vantagem da forma de representação em linguagem algorítmica 
está na facilidade com a qual um pseudocódigo pode ser transcrito para uma 
linguagem de programação. Assim como os fluxogramas, a desvantagem fica por 
conta da limitação do seu poder de expressão, devido às regras impostas 
para a elaboração das instruções.
////
TODO - REV.13: Sugestão de melhoria para análise pelo autor 
Talvez fosse interessante ser mencionado algumas ferramentas que podem auxiliar
o aluno no desenvolvimento de algoritmos em pseudo código como o Visualg, dentre 
outros exemplos. Também há um joguinho muito bacana que pode ser utilizado
para ensinar algoritmos o Light-bot, como curiosidade dá para colocar seções
com links e etc para despertar mais a curiosidade do aluno sobre
o desenvolvimento de algoritmos, antes de apresentar uma linguagem de programação, o choque
é grande para o aluno, muito mesmo. Acho que poderia ser explorado mais
seções do tipo "Você sabia?" ou "Para saber mais...". 
////
=== Recapitulando
Neste capítulo você estudou algoritmos, suas principais características e 
suas formas de representação. 
Apesar de ser um tema mais abordado na ciência da computação, algoritmos 
estão presentes nas mais diversas áreas e em várias atividades do cotidiano. 
Lidamos com eles, por exemplo, quando tomamos banho, cozinhamos, planejamos 
uma rota para fugirmos do trânsito, consultamos um manual de montagem, enfim, 
sempre que nos deparamos com um conjunto lógico de passos para realizarmos uma 
tarefa ou solucionarmos um problema, estamos em contato com algoritmos. É por 
meio deles que os computadores passam a ilusão de que são inteligentes, 
realizando tarefas capazes de impressionar qualquer ser humano. No entanto, 
sabemos que eles apenas processam dados, segundo um conjunto de instruções 
que lhe são passadas -- os algoritmos.
Você viu que os algoritmos computacionais, aqueles elaborados para serem 
executados em computadores, devem ser claros, ter um número finito de passos, 
e que estes devem ser simples o suficiente para serem executados de maneira 
exata e em um tempo finito. Além disso, os algoritmos computacionais devem 
possuir zero ou mais entradas e uma ou mais saídas.
As formas de representação de algoritmos mais comuns são a linguagem 
algorítmica, o fluxograma e o pseudocódigo. Da primeira à última há uma 
aproximação em relação às linguagens de programação, ou seja, o 
pseudocódigo é a forma de representação que mais se assemelha às 
linguagens utilizadas na programação de computadores. Na direção inversa, 
há uma maior liberdade na elaboração de algoritmos, aumentando, assim, a 
capacidade de expressá-los. 
No próximo capítulo abordaremos o processo de tradução de um programa 
escrito em uma linguagem de alto nível, os paradigmas de programação 
existentes, e introduziremos os conceitos básicos da programação de 
computadores. Além disso, você terá o primeiro contato com a linguagem de 
programação a ser estudada neste livro: a linguagem C.
////
TODO - REV.14: Sugestão de melhoria para análise pelo autor 
Em relação aos exercícios seria interessante ter uma seção de exercícios 
resolvidos e comentados, outra de exercícios propostos e uma pequena seção
com um ou dois desafios. 
////
=== Exercícios Propostos
1. Explique, com suas próprias palavras, o que é algoritmo.
2. Rotineiramente, usamos algoritmos para as mais diversas tarefas. Cite três 
algoritmos que podemos encontrar no dia a dia.
3. Em que consiste a característica de efetividade de um algoritmo?
4. Suponha que o quarto passo de um determinado algoritmo ordene que a 
execução retorne ao primeiro. Qual característica não está sendo 
satisfeita por esse algoritmo?
5. Discorra sobre as formas de representação de algoritmos mais comuns, 
destacando suas vantagens e desvantagens.
6. Suponha que você foi premiado com um robô capaz de auxiliá-lo nas tarefas 
domésticas. Antes que execute determinada atividade, você precisa instruí-lo 
corretamente através de um algoritmo específico. Sabendo disso, escreva 
algoritmos, em linguagem
natural, para ensiná-lo a realizar cada uma das 
tarefas abaixo:
a. Trocar a lâmpada do seu quarto.
b. Trocar o pneu do seu carro.
c. Fazer uma vitamina de banana com açaí.
d. Lavar e secar os pratos.
e. Calcular quanto você precisar tirar na terceira nota para passar por média 
em Introdução à Programação.
7. Escreva um algoritmo, utilizando fluxograma, que receba como entrada o peso e 
altura de uma pessoa, calcule seu IMC (Índice de Massa Corpórea) e exiba sua 
situação, segundo os seguinte critério:
+
Se o IMC > 25, a pessoa está acima de seu peso, caso contrário, está abaixo. Onde o IMC = (Peso)/(Altura^2^)
8. Usando fluxograma, faça um algoritmo que receba como entrada a idade de uma 
pessoa expressa em anos, meses e dias (Atenção: são 3 entradas) e mostre-a 
expressa apenas em dias. Considere anos de 365 dias e meses de 30 dias.
9. Considere as instruções armazenadas na memória a seguir:
+
image::images/algoritmos/memoria-exercicio.eps[scaledwidth="50%"]
+
Considerando que a instrução inicial se encontra no endereço `0` (zero) e as 
posições `8`, `9` e `10` correspondem a `x`, `y` e `z`, respectivamente, 
explique como funciona a execução das instruções acima, segundo a arquitetura 
de von Neumann. Antes da execução da instrução de endereço 2 `(z=x/y + z)`, a 
posição de memória referente a `z` possuía o valor `1` (um).
10. Escreva um algoritmo, em pseudocódigo, que receba como entrada a base e a 
altura de um triângulo, calcule e exiba sua área.
// Sempre termine os arquivos com uma linha em branco.
introducao-a-programacao-livro-1.0.0/livro/capitulos/asciidoc-cheatsheet.asc
== AsciiDoc cheatsheet
Nesta seção são apresentadas vários recursos do 
asciidoc. Verifique
o código fonte para aprender qual a sintaxe que produz este texto.
=== Como aprender a sintaxe do asciidoc?
A melhor forma é através dos exemplos contidos na página do asciidoc.
AsciiDoc cheatsheet:: http://powerman.name/doc/asciidoc
Exemplo de livro:: https://asciidoc.googlecode.com/hg/doc/book.txt
Guida do usuário:: http://www.methods.co.nz/asciidoc/userguide.html 
Para matemática:: http://www.methods.co.nz/asciidoc/latexmath.pdf
=== Seções
----
== Nível de capítulo (section) 1
Texto.
=== Nível de subseção 2
Texto.
==== Level 3
Texto.
===== Level 4
Texto.
----
CAUTION: Não pode existir seções sem texto. Sempre coloque algum texto,
caso contrário o arquivo não será gerado.
=== Parágrafos
.Título do parágrafo opcional
Texto do parágrafo
aqui.
.Título do parágrafo opcional
 Texto do parágrafo aqui.
 Precisa começar com espaço em branco.
.Optional Title
[source,perl]
die 'connect: '.$dbh->errstr;
Este parágrafo não faz parte do código.
.Optional Title
NOTE: This is an example
 single-paragraph note.
.Optional Title
[NOTE]
This is an example
single-paragraph note.
TIP: Texto.
IMPORTANT: Texto.
WARNING: Texto.
CAUTION: Texto.
=== Blocos
.Optional Title
----
*Listing* Block
Use: code or file listings
----
.Optional Title
[source,perl]
----
# *Source* block
# Use: highlight code listings
# (require `source-highlight` or `pygmentize`)
use DBI;
my $dbh = DBI->connect('...',$u,$p)
 or die "connect: $dbh->errstr";
----
.Optional Title
****
*Sidebar* Block
Use: sidebar notes :)
****
.Optional Title
==========================
*Example* Block
Use: examples :)
Default caption "Example:"
can be changed using
 [caption="Custom: "]
before example block.
==========================
.Optional Title
[NOTE]
===============================
*NOTE* Block
Use: multi-paragraph notes.
===============================
////
*Comment* block
Use: hide comments
////
.Optional Title
....
*Literal* Block
Use: workaround when literal
paragraph (indented) like
 1. First.
 2. Second.
incorrectly processed as list.
....
.Optional Title
[quote, cite author, cite source]
____
*Quote* Block
Use: cite somebody
____
[[texto-secao]]
=== Text
forçando +
quebra de linha.
normal, _italic_, *bold*, +mono+.
``double quoted'', `single quoted'.
normal, ^super^, ~sub~.
Command: `ls -al`
Path: '/some/filez.txt', '.b'
// Comentário de linha.
////
Comentários aqui dentro,
com várias linhas.
////
(C) (R) (TM) -- ... -> <- => <= &#182;
''''
[[macro-secao]]
=== Macros: Referencias, images & include
Exemplo de referências.
anchor:anchor-2[]
Paragraph or block 2.
Exemplo de referencias: <<texto-secao>>,
<<texto-secao,Capitulo sobre texto>>.
.Block image
image::images/novo-capitulo/bug.png[scaledwidth="60%"]
=== Código fonte de programas
Exemplo de código fonte.
-------------------------------------------
include::code/helloworld.c[]
-------------------------------------------
<1> Incluindo biblioteca de entrada/saída.
<2> Chamada à função printf, que envia para a saída padrão (o console) o texto recebido.
==== Trecho de código
Exemplo de trecho de código.
 #include<stdio.h> 
 main() { printf("Hello World"); }
=== Listas
.Bulleted
* bullet
* bullet
 - bullet
 - bullet
* bullet
** bullet
** bullet
*** bullet
*** bullet
**** bullet
**** bullet
***** bullet
***** bullet
**** bullet
*** bullet
** bullet
* bullet
.Bulleted 2
- bullet
 * bullet
.Ordered
. number
. number
 .. letter
 .. letter
. number
.. loweralpha
.. loweralpha
... lowerroman
... lowerroman
.... upperalpha
.... upperalpha
..... upperroman
..... upperroman
.... upperalpha
... lowerroman
.. loweralpha
. number
.Ordered 2
a. letter
b. letter
 .. letter2
 .. letter2
 . number
 . number
 1. number2
 2. number2
 3. number2
 4. number2
 . number
 .. letter2
c. letter
.Labeled
Termo 1::
 Definição 1
Termo 2::
 Definição 2
 Termo 2.1;;
 Definição 2.1
 Termo 2.2;;
 Definição 2.2
Termo 3::
 Definição 3
Termo 4:: Definição 4
Termo 4.1::: Definição 4.1
Termo 4.2::: Definição 4.2
Termo 4.3::: Definição 4.3
Termo 5:: Definição 5
.Labeled 2
Termo 1;;
 Definição 1
 Termo 1.1::
 Definição 1.1
[horizontal]
.Labeled horizontal
Termo 1:: Definição 1. ashkjahgsjhagkjshgkjhag jhasgjh agfsjhgafsjhgafhsgfjasjh
aj shgkjahsg khagskjhagskjhsak.
Termo 2:: Definição 2 kajshkljahskjah lskjha lkjshlaksjlkagsksjahgskjhgk ahsgka
la shlkajhsl kjahlskjahls.
[qanda]
.Q&A
Questão 1::
 Resposta da pergunta 1 aqui.
Questão 2:: Resposta da pergunta 2 aqui.
.Indent is optional
- bullet
 * another bullet
 1. number
 . again number
 a. letter
 .. again letter
.. letter
. number
* bullet
- bullet
.Break two lists
. number
. number
Independent paragraph break list.
. number
.Header break list too
. number
--
. List block define list boundary too
. number
. number
--
--
. number
. number
--
.Continuation
- bullet
continuation
. number
 continuation
* bullet
 literal continuation
.. letter
+
Non-literal continuation.
+
----
any block can be
included in list
----
+
Last continuation.
.List block allow sublist inclusion
- bullet
 * bullet
+
--
 - bullet
 * bullet
--
 * bullet
- bullet
 . number
 .. letter
+
--
 . number
 .. letter
--
 .. letter
 . number
=== Tabelas
You can fill table from CSV file using +include::+ macros inside table.
.An example table
[options="header,footer"]
|=======================
|Col 1|Col 2 |Col 3
|1 |Item 1 |a
|2 |Item 2 |b
|3 |Item 3 |c
|6 |Three items|d
|=======================
.CSV data, 15% each column
[format="csv",width="60%",cols="4"]
[frame="topbot",grid="none"]
|======
1,2,3,4
a,b,c,d
A,B,C,D
|======
[grid="rows",format="csv"]
[options="header",cols="^,<,<s,<,>m"]
|===========================
ID,FName,LName,Address,Phone
1,Vasya,Pupkin,London,+123
2,X,Y,"A,B",45678
|===========================
.Multiline cells, row/col span
|====
|Date |Duration |Avg HR |Notes
|22-Aug-08 .2+^.^|10:24 | 157 |
Worked out MSHR (max sustainable
heart rate) by going hard
for this interval.
|22-Aug-08 | 152 |
Back-to-back with previous interval.
|24-Aug-08 3+^|none
|====
=== Matemática
Ver https://asciidoc.googlecode.com/hg/doc/latexmath.txt e comparar com 
http://www.methods.co.nz/asciidoc/latexmath.pdf
[[equacao-qualquer]]
.Uma equação qualquer.
[latexmath]
++++++++++++++++++++++++++++++++++++++++++++
\[C = \alpha + \beta Y^{\gamma} + \epsilon\]
++++++++++++++++++++++++++++++++++++++++++++
Colocar equação no meio do texto, 
latexmath:[$C = \alpha + \beta Y^{\gamma} + \epsilon$], também é 
possível. Mas o mais legal é referencia-la (ver <<equacao-qualquer>>).
introducao-a-programacao-livro-1.0.0/livro/capitulos/cap4-arranjos.asc
== Arranjos
.Objetivos do capítulo
____
Ao final deste capítulo você deverá ser capaz de:
* Apresentar os conceitos de vetores e matrizes
* Apresentar o conceito de strings e como manipulá-las
____
=== Introdução
Até agora vimos que uma variável armazena um único valor por vez. Por 
exemplo, em um programa para ler as notas de vários alunos, cada nota é 
armazenada em uma variável, e assim que as notas de um novo aluno são lidas, 
as notas do aluno anterior são perdidas. Em alguns problemas, é necessário 
armazenar todos ou um conjunto de valores lidos sem que haja perda de 
informação. Nesse caso, seria inviável declarar uma variável distinta para 
armazenar cada valor, quando a quantidade de valores a serem manipulados for 
relativamente grande. Para situações como essas utilizamos Arranjos (em 
inglês _Arrays_), que consistem em estruturas de dados capazes de agrupar em 
uma única variável vários elementos de um mesmo tipo. O conceito de 
Arranjos, bem como as diferentes formas de utilizá-los serão discutidos em 
detalhes no decorrer deste capítulo, que ainda apresentará as cadeias de 
caracteres, conhecidas como _strings_. 
=== Vetores
Os arranjos podem ter diferentes dimensões. Um tipo especial de arranjo com 
apenas uma dimensão é chamado de *((vetor))*. Portanto, vetores são arranjos 
unidimensionais que representam um conjunto de variáveis com o mesmo tipo, as 
quais são acessadas através de um índice que as identificam. A <<fig_vetor>> 
ilustra o conceito de vetor, apresentando um vetor de inteiros com cinco 
elementos, cada um com seu índice correspondente. O índice do primeiro 
elemento é sempre zero.
[[fig_vetor]]
.Vetor com cinco elementos.
image::images/cap4/vetor5.eps[scaledwidth="50%"]
NOTE: O conceito de arranjo nas diferentes linguagens de programação é o 
mesmo. Entretanto, em algumas linguagens alguns detalhes podem ser diferentes. 
Na linguagem C, por exemplo, o índice inicial é sempre zero. Já na 
linguagem Pascal, o índice inicial é definido pelo próprio programador. 
==== Declaração de Vetores
Na linguagem C, devemos declarar um vetor da seguinte forma: 
	tipo_vetor nome_vetor[quantidade_elementos];
O `tipo_vetor` é o tipo de cada elemento do vetor. O `nome_vetor` é o nome da 
variável que irá identificar o vetor. A `quantidade_elementos` representa a 
quantidade máxima de elementos que o vetor poderá armazenar. Observe que essa 
quantidade deve ficar entre colchetes. Os índices do vetor irão de zero até 
`quantidade_elementos - 1`. O compilador irá reservar o espaço de memória 
correspondente ao que o programador definiu em `quantidade_elementos`.
Vamos ver alguns exemplos de declarações de vetores:
	int idades[50]; 
	char nomes[200];
	float precos[30];
No exemplo acima temos três declarações de vetores diferentes. Na primeira 
linha temos a declaração de um vetor chamado `idades` que terá no máximo 50 
elementos do tipo `int`, com índices de 0 a 49. Na segunda linha temos um 
vetor chamado `nomes` com 200 elementos do tipo `char`, com índices de 0 a 
199. Por fim, temos na última linha um vetor com identificador `precos`, com 
espaço para armazenar 30 elementos do tipo `float`, cujos índices variam de 0 
a 29.
==== Acessando os elementos de um vetor
Uma vez que um vetor foi declarado, poderemos armazenar e ler os valores dos 
elementos desse vetor. Para isso, devemos identificar o elemento do vetor que 
queremos acessar através do nome do vetor seguido do índice do elemento entre 
colchetes. Observe o exemplo abaixo:
[source,c,numbered]
----
...
int main() {
	int v[5], i;
	for (i = 0 ; i < 5 ; i++)
		scanf("%d", &v[i]);
...
----
// FIXME linhas
Na linha 3, um vetor `v` de 5 elementos do tipo `int` é declarado. Em seguida, 
temos um comando `for` que irá se repetir 5 vezes, com a variável `i` 
variando de 0 a 4. No corpo da estrutura de repetição, na linha 5, ocorre a 
leitura de valores inteiros, na qual cada valor lido é armazenado em um 
elemento do vetor `v` com índice igual ao valor da variável `i` em cada 
iteração. Para um melhor entendimento, considere a situação hipotética a 
seguir. Suponha que o usuário digitou os seguintes valores na leitura de 
dados: 4, 3, 7, 2 e 9. Nesse caso, o vetor ficaria da seguinte forma após a 
leitura dos valores:
.Configuração do vetor v após a leitura dos valores.
image::images/cap4/vetor_apos_leitura.eps[scaledwidth="30%"]
Uma vez que os elementos de um vetor foram inicializados, isto é, receberam 
algum valor através de uma operação de escrita na memória, podemos acessar 
tais valores para diversos fins. Por exemplo, podemos implementar um laço para 
percorrer todo o vetor e imprimir na tela os valores da cada um de seus 
elementos. O trecho de código a seguir ilustra como os elementos de um vetor 
são acessados e mostra como um laço para percorrer um vetor pode ser 
implementado:
[source,c,numbered]
----
...
printf("%d", v[0]); //mostra o valor 4 na saída
printf("%d", v[2]); // mostra o valor 7 na saída
for (i = 0 ; i < 5 ; i++) 
	printf("%d ", v[i]); //mostra todos os valores 
printf("%d", v[5]);
...
----
Na linha 2 estamos pedindo para ser mostrado o valor do elemento de índice 0 
do vetor `v`. Sendo assim, o valor 4 é mostrado na tela. Na linha 3, é 
mostrado o valor do elemento de índice 2 do vetor `v`, cujo valor é 7. Já na 
linha 4 temos um laço de repetição que irá mostrar todos os valores dos 
elementos do vetor `v`. Em seguida, na linha 6, estamos tentando acessar o 
elemento de índice 5, que não existe. O programa irá compilar normalmente, 
entretanto, ocorrerá um erro em tempo de execução assim que o programa 
tentar acessar o elemento inexistente do vetor.
CAUTION: Tenha cuidado ao acessar elementos de um vetor cujo índice não 
existe. Caso isso aconteça, o programa irá compilar, entretanto, ocorrerá um 
erro em tempo de execução. 
Vamos fazer um outro exemplo para fixar melhor o assunto. Digamos que queremos 
um programa para ler 20 valores do tipo inteiro e que após isso, sejam 
mostrados esses mesmos valores na ordem inversa da qual foram lidos. O exemplo 
abaixo mostra a solução do problema.
[source,c,numbered]
----
int main() {
	int i, valores[20];
	for (i = 0 ; i < 20 ; i++ ) //primeira etapa 
		scanf("%d", &valores[i]); 
	for (i = 19 ; i >= 0 ; i--) //segunda etapa 
	printf("%d ", valores[i]);
	return 0;
}
----
Podemos dividir o problema em duas etapas. A primeira é para ``montar'' um vetor 
com 20 valores digitados pelo usuário. A segunda parte é para mostrar os 
valores desse vetor na ordem inversa da qual foram lidos. Inicialmente, 
declaramos o vetor ``valores` com 20 elementos do tipo `int`. Para resolver 
cada etapa do problema, utilizamos um laço de repetição com o comando `for`. 
 Na linha 3, o laço `for` é utilizado para ler os valores, cada um sendo 
armazenado em um elemento do vetor. Na linha 5, temos
um outro laço `for`, 
cuja variável de controle i é inicializada com o valor 19, que representa o 
índice do último elemento do vetor. A condição de parada do laço é que a 
variável `i` seja maior ou igual a zero e a última expressão do `for` é o 
decremento da variável `i`. Isso significa que o valor da variável `i` irá 
de 19 a 0 dentro do laço de repetição. Consequentemente, os valores dos 
elementos do vetor `valores` irão ser mostrados na ordem inversa da que foram 
lidos.
==== Exercício resolvido
ER 4.1:: Escreva um programa que leia 20 notas de alunos de uma turma. O 
programa deve calcular a média da turma e apresentar na tela apenas as notas 
dos alunos que ficaram acima da média calculada.
Resposta::
A primeira etapa para resolver esse problema é analisar se precisamos 
realmente utilizar um arranjo. Mas antes disso, vamos tentar dividir o problema 
em subproblemas menores para facilitar a elaboração da solução. 
[width="100%",cols="1,3",frame="topbot",options="header"]
|====
| Subproblema| Descrição
| Subproblema 1|Ler 20 notas de uma turma
| Subproblema 2|Calcular a média da turma considerando as 20 notas lidas
| Subproblema 3|Apresentar na tela as notas da turma que estão acima da 
média calculada
|====
O primeiro subproblema é ler 20 notas dos alunos. A princípio conseguiríamos 
ler as 20 notas utilizando um laço de repetição e apenas uma variável. 
Entretanto, se utilizarmos apenas uma variável para ler as notas, só teremos 
a última nota armazenada ao final do laço. Como precisamos de todas as notas 
para saber quais delas estão acima da média calculada, a solução do 
subproblema 3 requer que um vetor seja utilizado ao invés de apenas uma 
variável. Resolveremos, a partir de agora, a questão gradativamente a partir 
das soluções dos subproblemas. Vejamos o trecho de código abaixo que resolve 
o subproblema 1 da questão.
[source,c,numbered]
----
int main() {
	float nota[20];
	int i;
	for (i = 0 ; i < 20 ; i++ )
		scanf("%f", &nota[i]); 
...
----
Como foi explicado, precisaremos de um vetor para armazenar todas as notas da 
turma. Portanto, na linha 3 declaramos um vetor de `float` chamado `notas` com 
20 elementos. Utilizamos a estrutura de repetição `for` para ler as 20 notas 
passadas como entrada para o programa (linha 6 e 7). 
O subproblema 2 consiste em calcular a média das 20 notas lidas. Para isso, 
precisamos primeiramente somar todas as notas lidas. Uma vez que temos essas 
notas armazenadas em um vetor, poderíamos resolver esse subproblema de duas 
maneiras. Uma delas é criar, após o laço de leitura das notas, um outro 
laço para acessar os elementos do vetor para realizar a soma das notas. A 
segunda forma, mais interessante, é somar as notas à medida que forem lidas, 
no mesmo laço de repetição. Dessa forma, teremos apenas um laço de 
repetição, tornando nosso código mais eficiente. Verifiquemos como ficou o 
trecho de código anterior com a inclusão da solução para o subproblema 2.
[source,c,numbered]
----
int main() {
	float nota[20], media, soma = 0;
	int i;
	for (i = 0 ; i < 20 ; i++ ) {
		scanf("%f", &nota[i]); 
		soma += nota[i];
	}
	media = soma / 20;
...
----
Perceba que incluímos na declaração as variáveis `media` e `soma`, para 
armazenar, respectivamente, os valores da média e da soma das notas. Verifique 
também, na linha 8, que a soma das notas é realizada à medida que cada nota 
é lida. O cálculo da média, na linha 11, só pode ser feita depois que todas 
as notas forem lidas e acumuladas na variável `soma`. Desse modo, ela deve 
ficar fora do laço.
O subproblema 3 consiste em apresentar na tela as notas da turma que ficaram 
acima da média. Uma vez que já temos a média calculada, podemos resolver 
facilmente esse problema. Para tanto, precisamos percorrer todo o vetor e 
comparar cada elemento deste com a média. Caso o valor do elemento seja maior 
que a média, ele deve ser apresentado na tela. A versão final do programa 
está descrita abaixo:
[source,c,numbered]
----
int main() {
	float nota[20], media, soma = 0;
	int i;
	for (i = 0 ; i < 20 ; i++) {
		scanf("%f", &nota[i]); 
		soma += nota[i];
	}
	media = soma / 20;
	for (i = 0 ; i < 20 ; i++)
		if (nota[i] > media) 
			printf("%f ", nota[i]);
	return 0;
}
----
As linhas 12 a 14 resolvem o subproblema 3, utilizando o comando `for` para 
percorrer todo o vetor de notas e comparar cada elemento com a média. Para 
realizar tal comparação, utilizamos o comando `if`. Caso o elemento `nota[i]` 
seja maior que a média, ele será exibido na tela.
=== Strings
Na maioria dos programas que implementamos, precisamos lidar com cadeias de 
caracteres no processamento e armazenamento das informações que nos são 
fornecidas. Nas linguagens de programação, essas cadeias são chamadas de 
*((strings))*. Como não há, na linguagem C, um tipo de dados específico para 
representar as strings, utilizamos vetores de elementos do tipo `char` para a 
manipulação de cadeias de caracteres. Em outras palavras, quando queremos 
declarar uma variável para armazenar uma cadeia de caracteres, declaramos um 
vetor do tipo `char`.
No exemplo abaixo, temos a declaração de três strings: `nome`, `logradouro` 
e `bairro`. Perceba que cada `string` é um `array` de `char`. Significa dizer 
que a string `nome` tem a capacidade de armazenar 60 caracteres, a string 
`logradouro` 200 caracteres e a string `bairro` 40 caracteres. 
	char nome[60]; 
	char logradouro[200];
	char bairro[40];
Na linguagem C, toda string tem um caractere especial que determina o seu fim. 
Esse caractere é o `\0`, que significa *((NULO))*, e ele é inserido 
automaticamente pelo compilador no último elemento do vetor de elementos do 
tipo `char`. Por essa razão, deve-se levar isso em consideração na hora de 
declarar suas strings. Assim sendo, se você deseja que uma string armazene `N` 
caracteres, você deve declará-la com um tamanho `N+1`. 
==== Lendo e imprimindo Strings
Para ler e imprimir strings na linguagem C, podemos utilizar as funções 
`scanf()` e `printf()` que já conhecemos. Entretanto, como muitas vezes 
precisamos manipular strings no nosso programa, as linguagens de programação 
possuem funções pré-definidas para serem utilizadas pelo programador, 
facilitando a manipulação das cadeias de caracteres. A linguagem C, por 
exemplo, possui as funções `gets()` e `puts()`, elaboradas especialmente para 
ler e imprimir `strings`, respectivamente. Vejamos um exemplo.
[source,c,numbered]
----
int main() {
	char s[7];
	gets(s);
	puts(s);
	printf("%c", s[4]);
	printf("%c", s[2]);
	return 0; 
}
----
Na linha 3, declaramos uma string `s` que armazena 6 caracteres (além do 
caractere NULO). Em seguida, utilizamos a função `gets()`,que faz a leitura 
de uma string, esperando que o usuário a digite e tecle ENTER. Na linha 6, 
utilizamos a função `puts()`, que imprime na saída padrão a string `s` 
lida. Digamos que o usuário digite a string `‘BRASIL’`. Dessa forma, a 
cadeia de caracteres será armazenada na memória da seguinte forma:
.Cadeia de caracteres.
image::images/cap4/cadeia_caracteres.eps[scaledwidth="60%"]
Como uma string em C trata-se na verdade de um vetor de caracteres, podemos 
acessá-los individualmente do mesmo modo que acessamos os elementos de um 
vetor qualquer. Ao serem executadas as linhas 8 e 9 do código anterior, por 
exemplo, são exibidos na saída padrão os caracteres ``I'' e ``A'', respectivamente.
==== Manipulando strings
Existem ainda outras funções interessantes para manipular strings na 
linguagem C. A tabela abaixo apresenta algumas dessas funções, todas 
presentes na biblioteca `string.h`.
[width="100%",cols="1m,2",frame="topbot",options="header"]
|======================
|Função|Descrição
|strlen(s)
|Retorna a quantidade de caracteres da string `s`
|strcpy(s1, s2)
|Copia o conteúdo da string `s2` para
`s1`
|strcat(s1, s2)
|Concatena (junta) o conteúdo da string `s2` em `s1`
|strchr(s, c)
|Retorna a posição (inteiro) do caractere `c` na string `s`
|======================
Para entender melhor o uso destas funções, considere o exemplo a seguir.
.Código fonte
{gitrepo}/blob/master/livro/capitulos/code/cap4/manipulacao_string.c[code/cap4/manipulacao_string.c]
[source, c,numbered]
----
include::code/cap4/manipulacao_string.c[]
----
Inicialmente declaramos duas strings: `str1` e `str2`. Nas linhas 6 e 7, 
utilizamos o comando `gets()` para que o usuário informe as duas strings que 
serão armazenadas nas variáveis mencionadas. As linhas 9 e 10 imprimem os 
tamanhos das strings `str1` e `str2`, enquanto que a linha 12 é responsável 
por concatenar as strings `str2` e `str1`, ou seja, `str1` passa a ter o 
conteúdo anterior com a adição do conteúdo de str2. Por fim, a linha 13 
exibe o tamanho de `str1` após a sua concatenação com `str2`.
==== Exercício resolvido
ER 4.2:: Escreva um programa que leia uma string e substitua todos os espaços 
por um traço (caractere ``-'').
Resposta::
Primeiramente, declaramos uma string `s` com capacidade para armazenar 40 
caracteres e utilizamos a função `gets()`, na linha 5, a fim de que o 
usuário digite uma string. Tendo a string digitada armazenada na variável 
`s`, podemos agora manipulá-la. Para resolver essa questão, é importante ter 
entendido o conceito de que uma string é um vetor de caracteres. Na linha 7, 
utilizamos um `for` para percorrer os elementos da string. Veja que a 
condição de parada do comando `for` é `i < strlen(s)`. Isso significa que o 
bloco de instruções será repetido até o final da string, uma vez que 
`strlen()` retorna a quantidade de caracteres de uma string. Dentro do `for`, 
verificamos se o caractere da posição `i` é igual a um espaço. Caso seja, 
esse elemento do array recebe o caractere ``-''. Finalmente, depois do 
comando `for`, utilizamos a função `puts()` para imprimir a nova string com 
os espaços trocados por ``-''.
.Código fonte
{gitrepo}/blob/master/livro/capitulos/code/cap4/resolvido4-2.c[code/cap4/resolvido4-2.c]
[source, c,numbered]
----
include::code/cap4/resolvido4-2.c[]
----
=== Matrizes
Como foi dito no início do capítulo, arranjos podem ter várias dimensões. 
Quando possuem mais de uma dimensão, eles são chamados de *((matrizes))*. O 
conceito de matrizes em programação é bem semelhante ao homônimo da 
matemática. A figura a seguir apresenta o formato de uma matriz `m` x `n`, onde 
`m` é representa o número de linhas e `n` o número de colunas.
.Matriz M x N
image::images/cap4/matriz.eps[scaledwidth="45%"]
Analisemos os exemplos abaixo. A primeira matriz é 3 x 3, pois possui 3 linhas 
e 3 colunas. A segunda matriz é 2 x 3, pois possui 2 linhas e 3 colunas. Se 
quisermos saber o elemento da primeira matriz que possui índice A~2,3~, basta 
seguirmos em direção à 2ª linha e depois em direção à 3ª coluna. Logo 
o valor de A~2,3~ é 1.
.4.5. Exemplos de matrizes
image::images/cap4/matriz-exemplos.eps[scaledwidth="50%"]
Podemos representar essas matrizes na linguagem C acrescentando mais um índice 
entre colchetes no identificador do arranjo. Abaixo temos alguns exemplos de 
como declaramos matrizes:
	int matriz[3][3];
	int outra_matriz[2][3];
	float matriz_de_float[30][20];
	char nomes[10][50];
Na primeira linha temos a declaração de uma matriz de inteiros com 3 linhas e 
3 colunas, na segunda novamente uma matriz de inteiros, só que agora com 2 
linhas e 3 colunas, e na terceira uma matriz de elementos do tipo `float` com 
30 linhas e 20 colunas. Agora atenção para última linha. Trata-se da 
declaração de um arranjo de strings. Lembre-se que uma string é um arranjo 
de caracteres. Se declararmos uma matriz de `char`, então teremos na prática 
um vetor de strings, onde cada linha da matriz é uma cadeia de caracteres.
Já sabemos como declarar matrizes, agora aprenderemos a montá-las a partir da 
leitura de dados da entrada padrão. Para isso, precisaremos utilizar dois 
comandos `for` aninhados. Considere o exemplo abaixo:
.Código fonte
{gitrepo}/blob/master/livro/capitulos/code/cap4/matriz_populando.c[code/cap4/matriz_populando.c]
[source, c,numbered]
----
include::code/cap4/matriz_populando.c[]
----
Na linha 2, temos uma declaração de uma matriz 20 x 30. Se quisermos pedir 
para o usuário digitar os valores da matriz, precisaremos utilizar um `for` 
para percorrer as linhas e um `for` para percorrer as colunas da matriz. 
Portanto, na linha 5, temos o primeiro `for` onde `i` irá variar de 0 a 19, 
justamente os índices que representam a posição dos elementos nas linhas da 
matriz. Na linha 6, temos um outro `for` dentro do primeiro, onde `j` irá 
variar de 0 a 29, que são justamente os índices que representam a posição 
dos elementos nas colunas da matriz. Perceba que quando `i = 0`, `j` irá 
variar de 0 a 29. Depois `i` passa a valer 1 e novamente o `j` irá variar de 0 
a 29 novamente. Isso acontecerá repetidamente até `i` atingir o valor 19. Em 
suma, o código anterior preenche os elementos da matriz linha por linha. 
Inicia preenchendo a linha de índice 0, em seguida preenche a linha de índice 
1, seguindo de forma sucessiva até que a linha de índice 19 seja preenchida.
=== Recapitulando
Como vimos neste capítulo, arranjos consistem em um conjunto de elementos do 
mesmo tipo, que podem ter diferentes dimensões e são acessados por um 
índice. Os arranjos de uma dimensão são chamados de vetores e quando possuem 
mais de duas dimensões são chamados de matrizes. 
Aprendemos também que strings são cadeias (arranjos) de caracteres, ou seja, 
um vetor de elementos do tipo `char`. Devido à sua importância para a 
programação de computadores, as linguagens de programação disponibilizam um 
conjunto de funções para facilitar sua manipulação. Algumas das funções 
mais utilizadas na linguagem C foram conhecidas neste capítulo, contudo, deve 
ficar claro ao leitor que existe um número bem maior de funções com tal 
objetivo. 
=== Exercícios Propostos
1. Crie um programa que armazene números em dois vetores inteiros de cinco 
elementos cada, depois gere e imprima o vetor soma dos dois.
2. Crie um programa que armazene 10 números em um vetor `A`, e gere um vetor 
`B` onde cada elemento é o quadrado do elemento de `A`.
+
Exemplo:
+
....
A[1] = 4 B[1] = 16
A[2] = 3 B[2] = 9
A[3] = 6 B[3] = 36
....
3. Escreva um programa para ler uma string qualquer e exiba as seguintes 
informações: quantidade de caracteres, primeira e última letra.
4. Escreva um programa para ler uma frase de no máximo 70 caracteres e exibir 
a quantidade de vogais dessa frase.
5. Escreva um programa que leia uma string qualquer e mostre-a invertida. 
+
--
Exemplo: 
....
Entrada: casa <ENTER>
Saída: asac
....
--
6. Um palíndromo é uma cadeia de caracteres que representa a mesma palavra 
nos sentidos direto e inverso. Por exemplo, ``asa'' é um palíndromo, porque o 
inverso dela também é ``asa''. Faça um programa que leia uma string e diga 
se esta é ou não um palíndromo.
7. Escreva um programa para ler 9 números inteiros para preencher uma matriz 
`D` 3x3, ou seja, com 3 linhas e 3 colunas (considere que não serão 
informados valores duplicados). A seguir, ler um número inteiro `X` e escrever 
uma mensagem indicando se o valor de `X` existe ou não na matriz `D`.
////
Sempre termine os arquivos com uma linha em branco.
////
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/cap4/Makefile
CFLAGS=-Wall -g
all: manipulacao_string \
		matriz_populando resolvido4-2 \
clean:
	rm -rf manipulacao_string \
		matriz_populando resolvido4-2
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/cap4/manipulacao_string.c
#include <stdio.h>
int main() {
	char str1[100], str2[100];
	gets(str1);
	gets(str2);
printf("%d", strlen(str1));
	printf("%d", strlen(str2));
	strcat(str1, str2);
	printf("%d", strlen(str1));
	return 0;
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/cap4/matriz_populando.c
int main() {
	int matriz[20][30];
	int i, j;
	for (i=0; i < 20; i++) 
		for (j = 0; j < 30; j++) 
			scanf("%d", &matriz[i][j]); 
	return 0;
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/cap4/resolvido4-2.c
int main() {
	char s[40];
	int i;
	gets(s);
	for (i=0; i < strlen(s); i++) {
		if (s[i] == ' ') 
			s[i] = '-';
	}
	puts(s); 
	return 0;
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/estruturas-de-controle/Makefile
CFLAGS=-Wall -g
all: break_interrompe \
		comparaab continue_desvio \
		entre10e20 \
		do_while \
		entre10e20 \
		for_cont for_cont_decremento \
		if5 \
		laco_infinito \
		menorq20 mostrado10vezes menor_deles menor_deles_resposta\
		nota7 notas_alunos \
		semana \
		whilenota
clean:
	rm -rf break_interrompe \
		comparaab continue_desvio \
		entre10e20 \
		do_while \
		entre10e20 \
		for_cont for_cont_decremento \
		if5 \
		laco_infinito \
		menorq20 mostrado10vezes menor_deles menor_deles_resposta\
		nota7 notas_alunos \
		semana \
		whilenota
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/estruturas-de-controle/break_interrompe.c
#include <stdio.h>
int main() {
 int cont;
 
 for (cont = 1; ; cont++) {
 printf("Valor de cont: %i\n", cont);
 if (cont == 10) break;
 }
 
 return 0;
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/estruturas-de-controle/comparaab.c
#include <stdio.h>
int main() {
 int a, b;
 
 scanf("%i", &a);
 scanf("%i", &b);
 
 if (a > b)
 printf("A e' maior que B.");
 else if (b > a)
 printf("B e' maior que A.");
 else
 printf("A = B");
 
 return 0;
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/estruturas-de-controle/continue_desvio.c
#include <stdio.h>
int main() {
 int cont;
 
 for (cont = 1; cont <= 20; cont++) {
 if (cont % 2 == 0) continue;
 printf("Valor de cont: %i\n", cont);
 } 
 return 0;
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/estruturas-de-controle/do_while.c
#include <stdio.h>
int main() {
 int cont = 1;
 
 do {
 printf("Isto sera' mostrado 10 vezes.\n");
 cont++;
 } while (cont <= 10);
 
 return 0;
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/estruturas-de-controle/entre10e20.c
#include <stdio.h>
int main() {
 int x;
 
 scanf("%d", &x);
 
 if (x > 10 && x < 20)
 printf("x esta' entre 10 e 20."); 
 return 0;
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/estruturas-de-controle/for_cont.c
#include <stdio.h>
int main() {
 int cont;
 
 for (cont = 1; cont <= 10; cont++)
 printf("Isto sera' mostrado 10 vezes.\n"); 
 
 return 0;
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/estruturas-de-controle/for_cont_decremento.c
#include <stdio.h>
int main() {
 int cont;
 
 for (cont = 10; cont > 0; cont--)
 printf("Valor de cont: %i\n", cont);
 
 return 0;
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/estruturas-de-controle/if5.c
#include <stdio.h>
int main() {
 int x = 5;
 
 if (x)
 printf("Isto sera' mostrado");
 
 if (x - 5)
 printf("Isto nao sera' mostrado");
 
 return 0;
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/estruturas-de-controle/laco_infinito.c
#include <stdio.h>
int main() {
 int cont;
 
 for (cont = 1; ; cont++)
 printf("Laco infinito.\n"); 
 
 return 0;
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/estruturas-de-controle/menor_deles.c
#include <stdio.h>
int main() {
 int quantidade = 1; 
 float valor, menor;
 
 printf("Informe um valor: ");
 scanf("%f", &menor);
 
 while (quantidade < 50) {
 printf("Informe um valor: ");
 scanf("%f", &valor);
 if (valor < menor)
 menor = valor;
 }
 
 printf("Menor valor lido: %f", menor);
 
 return 0;
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/estruturas-de-controle/menor_deles_resposta.c
#include <stdio.h>
int main() {
 int quantidade = 1;
 float valor, menor;
 
 printf("Informe um valor: ");
 scanf("%f", &menor);
 
 while (quantidade < 50) {
 printf("Informe um valor: ");
 scanf("%f", &valor);
 
 if (valor < menor)
 menor = valor;
 
 quantidade++; // Solucao do problema
 }
 
 printf("Menor valor lido: %.2f", menor); 
 
 return 0;
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/estruturas-de-controle/menorq20.c
#include <stdio.h>
int main() {
 int x;
 
 scanf("%d", &x);
 
 if (x < 20)
 printf("O valor de x e' menor que 20.");
 
 return 0; 
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/estruturas-de-controle/mostrado10vezes.c
#include <stdio.h>
int main() {
 int cont = 1;
 
 while (cont <= 10) {
 printf("Isto sera' mostrado 10 vezes.\n");
 cont++;
 }
 
 return 0;
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/estruturas-de-controle/nota7.c
#include <stdio.h>
int main() {
 float nota;
 
 scanf("%f", &nota);
 
 if (nota >= 7)
 printf("Aprovado");
 else
 printf("Reprovado");
 
 return 0;
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/estruturas-de-controle/notas_alunos.c
#include <stdio.h>
int main() {
 float nota = 0, soma = 0;
 int cont = 0;
 
 while (nota != -1) {
 printf("Entre com a nota: ");
 scanf("%f", &nota);
 
 if (nota != -1) {
	 soma += nota;
			cont++;
		}
 }
 
 printf("Media das notas: %.2f", soma / cont);
 
 return 0;
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/estruturas-de-controle/semana.c
#include <stdio.h>
int main() {
 int semana;
 
 printf("Digite um numero de 1 a 7: ");
 scanf("%d", &semana);
 
 switch (semana) {
	 case 1:
	 printf("Domingo");
	 break;
	 case 2:
	 printf("Segunda-feira");
	 break;
	 case 3:
	 printf("Terca-feira");
	 break;
	 case 4:
	 printf("Quarta-feira");
	 break;
	 case 5:
	 printf("Quinta-feira");
	 break;
	 case 6:
	 printf("Sexta-feira");
	 break;	 
	 case 7:
	 printf("Sabado");
	 break;
	 default:
	 printf("Numero fora do intervalo permitido.");
	 break;
 }
 
 return 0;
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/estruturas-de-controle/whilenota.c
#include <stdio.h>
int main() {
 float nota;
 scanf("%f", &nota); 
 while (nota != -1) {	 
 if (nota >= 7)
 printf("Aprovado\n");
 else
 printf("Reprovado\n");
		
		scanf("%f", &nota); 
 }
 
 return 0;
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/funcoes/Makefile
CFLAGS=-Wall -g -c
#
# Este Makefile precisa ser revisto,
# ele não está gerando os executáveis no linux.
# 
all: equacao \
		equacao2 \
		exercicio4 \
		fatorial2 \
		fatorial \
		media_globais \
		media_param2 \
		media_param \
		media_proc
\
		media_sem_proc \
		retorno_func \
		retorno_proc \
		situacao \
		situacao_prot \
		sombra \
		troca \
		troca_glob \
		troca_main \
		troca_ref
clean:
	rm -rf \
		equacao2 \
		equacao \
		exercicio4 \
		fatorial2 \
		fatorial \
		media_globais \
		media_param2 \
		media_param \
		media_proc \
		media_sem_proc \
		retorno_func \
		retorno_proc \
		situacao \
		situacao_prot \
		sombra \
		troca \
		troca_glob \
		troca_main \
		troca_ref
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/funcoes/equacao.c
#include <stdio.h>
#include <math.h>
float calculo_delta(float a, float b, float c) { // <1>
	return (b * b) - (4 * a * c);
}
float raiz_positiva(float a, float b, float delta) { // <2>
	return (-b + sqrt(delta)) / 2 * a;
}
float raiz_negativa(float a, float b, float delta) { // <3>
	return (-b - sqrt(delta)) / 2 * a;
}
int main() {
	float a, b, c;
	float delta;
	printf("Entre os coeficientes A, B e C, nesta ordem: ");
	scanf("%f %f %f", &a, &b, &c);
	delta = calculo_delta(a, b, c);
	if (delta < 0.0)
		printf("Delta negativo, nao existem raizes\n");
	else if (delta == 0)
		printf("Delta = 0, uma raiz: %f\n", raiz_positiva(a, b, delta));
	else
		printf("Raizes: %f e %f\n", raiz_positiva(a, b, delta), raiz_negativa(a, b, delta));
	return 0;
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/funcoes/equacao.out
Entre os coeficientes A, B e C, nesta ordem: 1.0 -5.0 6.0
Raizes: 3.000000 e 2.000000
Entre os coeficientes A, B e C, nesta ordem: 1.0 -6.0 9.0
Delta = 0, uma raiz: 3.000000
Entre os coeficientes A, B e C, nesta ordem: 4.0 -3.0 7.0
Delta negativo, nao existem raizes
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/funcoes/equacao2.c
#include <stdio.h>
#include <math.h>
float calculo_delta(float a, float b, float c) {
	return (b * b) - (4 * a * c);
}
float raiz(float a, float b, float delta, int sinal) {
	if (sinal == 1)
		return (-b + sqrt(delta)) / 2 * a;
	else
		return (-b - sqrt(delta)) / 2 * a;
}
int main() {
	float a, b, c;
	float delta;
	printf("Entre os coeficientes A, B e C, nesta ordem: ");
	scanf("%f %f %f", &a, &b, &c);
	delta = calculo_delta(a, b, c);
	if (delta < 0.0)
		printf("Delta negativo, nao existem raizes\n");
	else if (delta == 0)
		printf("Delta = 0, uma raiz: %f\n", raiz(a, b, delta, 1));
	else
		printf("Raizes: %f e %f\n", raiz(a, b, delta, 1), raiz(a, b, delta, -1));
	return 0;
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/funcoes/exercicio4.c
#include <stdio.h>
int x = 5;
int y = 9;
int f(int x) {
	int z = x * x;
	return z * y;
}
int main() {
	int y = 3;
	printf("%d \n", x);
	printf("%d \n", f(y));
	return 0;
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/funcoes/fatorial.c
#include <stdio.h>
// prototipo
int fatorial(int); // <1>
int main() {
	int n;
	printf("Entre o numero para calcular o fatorial: ");
	scanf("%d", &n);
	printf("%d! = %d\n", n, fatorial(n));
	return 0;
}
int fatorial(int n) { 
	if (n == 0 || n == 1)
		return 1; // <2>
	else 
		return n * fatorial(n - 1); // <3>
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/funcoes/fatorial.out
Entre o numero para calcular o fatorial: 4
4! = 24
Entre o numero para calcular o fatorial: 5
5! = 120
Entre o numero para calcular o fatorial: 6
6! = 720
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/funcoes/fatorial2.c
#include <stdio.h>
// prototipo
int fatorial(int);
int main() {
	int n;
	printf("Entre o numero para calcular o fatorial: ");
	scanf("%d", &n);
	printf("%d! = %d\n", n, fatorial(n));
	return 0;
}
int fatorial(int n) { 
	if (n <= 1) // <1>
		return 1; 
	else 
		return n * fatorial(n - 1); 
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/funcoes/fatorial2.out
Entre o numero para calcular o fatorial: 5
5! = 120
Sandman:funcoes andrei$ ./fat
Entre o numero para calcular o fatorial: -4
-4! = 1
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/funcoes/fatorial_neg.out
Entre o numero para calcular o fatorial: -4
Segmentation fault: 11
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/funcoes/media_erro.c
#include <stdio.h>
float calc_media() {
	return (nota1 + nota2 + nota3) / 3.0; // <1>
}
int main() {
	float nota1, nota2, nota3;
	printf("Entre as três notas: ");
	scanf("%f %f %f", &nota1, &nota2, &nota3);
	printf("Media: %f\n", calc_media());
	return 0;
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/funcoes/media_globais.c
#include <stdio.h>
float nota1, nota2, nota3; // <1>
float calc_media() {
	return (nota1 + nota2 + nota3) / 3.0; // <2>
}
int main() {
	printf("Entre as três notas: ");
	scanf("%f %f %f", &nota1, &nota2, &nota3); // <3> 
	printf("Media: %f\n", calc_media());
	return 0;
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/funcoes/media_param.c
#include <stdio.h>
#include <math.h>
void imprime_separador(float nota) { // <1>
	int i;
	printf("\n");
	for (i = 0; i < (int) lround(nota * 5.0); i++) {
		printf("=");
	}
	printf(" %3.2f / 10.0\n", nota);
	printf("\n"); 
}
int main () {
	float nota1, nota2, nota3, media; 
	printf("Entre a nota da primeira prova: ");
	scanf("%f", &nota1);
	imprime_separador(nota1); // <2>
	printf("Entre a nota da segunda prova: ");
	scanf("%f", &nota2);
	imprime_separador(nota2);
	printf("Entre a nota da terceira prova: ");
	scanf("%f", &nota3);
	imprime_separador(nota3);
	media = (nota1 + nota2 + nota3) / 3.0;
	printf("Media: %3.2f\n", media);
	imprime_separador(media);
	return 0;	
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/funcoes/media_param.out
Entre a nota da primeira prova: 6.2
=============================== 6.20 / 10.0
Entre a nota da segunda prova: 7.8
======================================= 7.80 / 10.0
Entre a nota da terceira prova: 9.2
============================================== 9.20 / 10.0
Media: 7.73
======================================= 7.73 / 10.0
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/funcoes/media_param2.c
#include <stdio.h>
float calc_media(float n1, float n2, float n3) {
	return (n1 + n2 + n3) / 3.0;
}
int main() {
	float nota1, nota2, nota3;
	printf("Entre as três notas: ");
	scanf("%f %f %f", &nota1, &nota2, &nota3);
	printf("Media: %f\n", calc_media(nota1, nota2, nota3));
	return 0;
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/funcoes/media_proc.c
#include <stdio.h>
void imprime_separador() { // <1>
	printf("\n"); // <2>
	printf("=============================================\n"); // <2>
	printf("\n"); // <2>
}
int main () {
	float nota1, nota2, nota3, media; 
	printf("Entre a nota da primeira prova: ");
	scanf("%f", &nota1);
	imprime_separador(); // <3>
	printf("Entre a nota da segunda prova: ");
	scanf("%f", &nota2);
	imprime_separador();
	printf("Entre a nota da terceira prova: ");
	scanf("%f", &nota3);
	imprime_separador();
	media = (nota1 + nota2 + nota3) / 3.0;
	printf("Media: %f\n", media);
	return 0;	
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/funcoes/media_sem_proc.c
#include <stdio.h>
int main () {
	float nota1, nota2, nota3, media; 
	printf("Entre a nota da primeira prova: ");
	scanf("%f", &nota1);
	printf("\n"); // <1>
	printf("=============================================\n"); // <1>
	printf("\n"); // <1>
printf("Entre a nota da segunda prova: ");
	scanf("%f", &nota2);
	printf("\n");
	printf("=============================================\n");
	printf("\n");
	printf("Entre a nota da terceira prova: ");
	scanf("%f", &nota3);
	printf("\n");
	printf("=============================================\n");
	printf("\n");
	media = (nota1 + nota2 + nota3) / 3.0;
	printf("Media: %f\n", media);
	return 0;	
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/funcoes/media_sem_proc.out
Entre a nota da primeira prova: 7.0
=============================================
Entre a nota da segunda prova: 8.0
=============================================
Entre a nota da terceira prova: 9.6
=============================================
Media: 8.200000
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/funcoes/retorno_func.c
#include <stdio.h>
int possui_negativo(float n1, float n2, float n3) { // <1>
	if (n1 < 0.0 || n2 < 0.0 || n3 < 0.0) // <2>
		return 1; // <3>
	return 0; // <4>
}
int main() {
	float nota1, nota2, nota3;
	printf("Entre as três notas, separadas por espacos: ");
	scanf("%f %f %f", &nota1, &nota2, &nota3);
	if (possui_negativo(nota1, nota2, nota3) == 1) // <5>
		printf("Nao e' possivel calcular a media, uma ou mais notas sao negativas\n");
	else
		printf("Media: %f\n", (nota1 + nota2 + nota3) / 3.0);
	return 0;
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/funcoes/retorno_func.out
Entre as três notas, separadas por espacos: 6.8 9.7 -2.3
Nao e' possivel calcular a media, uma ou mais notas sao negativas
Entre as três notas, separadas por espacos: 6.8 9.7 7.2
Media: 7.900000
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/funcoes/retorno_proc.c
#include <stdio.h>
void possui_negativo(float n1, float n2, float n3) {
	if (n1 < 0.0) {
		printf("Numero negativo encontrado!\n");
		return; // <1>
	}
	if (n2 < 0.0) {
		printf("Numero negativo encontrado!\n");
		return;
	}
	if (n3 < 0.0) {
		printf("Numero negativo encontrado!\n");
		return;
	}
	printf("Nenhum numero negativo encontrado\n"); // <2>
}
int main() {
	float nota1, nota2, nota3;
	printf("Entre as três notas, separadas por espacos: ");
	scanf("%f %f %f", &nota1, &nota2, &nota3);
	possui_negativo(nota1, nota2, nota3);
	printf("Media: %f\n", (nota1 + nota2 + nota3) / 3.0);
	return 0;
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/funcoes/retorno_proc.out
Entre as três notas, separadas por espacos: 4.5 5.6 8.9
Nenhum numero negativo encontrado
Media: 6.333333
Entre as três notas, separadas por espacos: 4.5 -6.7 9.9
Numero negativo encontrado!
Media: 2.566667
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/funcoes/situacao.c
#include <stdio.h>
int main() {
	float nota1, nota2, nota3;
	printf("Entre as três notas: ");
	scanf("%f %f %f", &nota1, &nota2, &nota3); 
	situacao(nota1, nota2, nota3); // <1>
	return 0; 
}
void situacao(float n1, float n2, float n3) { // <2>
	float media = (n1 + n2 + n3) / 3.0;
	printf("Media %f, ", media);
	if (media >= 7.0)
		printf("Aluno aprovado\n");
	else if (media < 4.0)
		printf("Aluno reprovado por media\n");
	else
		printf("Aluno na prova final"); 
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/funcoes/situacao.out
situacao.c:12:6: error: conflicting types for 'situacao'
void situacao(float n1, float n2, float n3) { // <2>
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/funcoes/situacao_prot.c
#include <stdio.h>
// Prototipo da funcao situacao
void situacao(float, float, float); // <1>
int main() {
	float nota1, nota2, nota3;
	printf("Entre as três notas: ");
	scanf("%f %f %f", &nota1, &nota2, &nota3); 
	situacao(nota1, nota2, nota3); // <2> 
}
void situacao(float n1, float n2, float n3) {
	float media = (n1 + n2 + n3) / 3.0;
	printf("Media %f, ", media);
	if (media >= 7.0)
		printf("Aluno aprovado\n");
	else if (media < 4.0)
		printf("Aluno reprovado por media\n");
	else
		printf("Aluno na prova final"); 
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/funcoes/situacao_prot.out
Entre as três notas: 6.8 5.2 9.0
Media 7.000000, Aluno aprovado
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/funcoes/sombra.c
#include <stdio.h>
int x = 5; // <1>
void f() {
	int x = 60; // <2> 
	int y = x * x; // <3>
	printf("x = %d, y = %d\n", x, y);
}
int g() {
	int y = x * x; // <4>
	return y;
}
int main() {
	f();
	printf("g = %d\n", g());
	return 0;
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/funcoes/sombra.out
x = 60, y = 3600
g = 25
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/funcoes/troca.c
#include <stdio.h>
void troca_variaveis(int a, int b) {
	int temp = a;
	a = b;
	b = temp;
	printf("Dentro de troca_variaveis: a = %d, b = %d\n", a, b);
}
int main() {
	int x = 5;
	int y = 7;
	printf("Antes da troca: x = %d, y = %d\n", x, y);
	troca_variaveis(x, y);
	printf("Depois da troca: x = %d, y = %d\n", x, y);
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/funcoes/troca.out
Antes da troca: x = 5, y = 7
Dentro de troca_variaveis: a = 7, b = 5
Depois da troca: x = 5, y = 7
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/funcoes/troca_glob.c
#include <stdio.h>
int x = 5; // <1> 
int y = 7;
void troca_variaveis() { // <2> 
	int temp = x;
	x = y;
	y = temp;
	printf("Dentro de troca_variaveis: x = %d, y = %d\n", x, y);
}
int main() {
	printf("Antes da troca: x = %d, y = %d\n", x, y);
	troca_variaveis();
	printf("Depois da troca: x = %d, y = %d\n", x, y);
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/funcoes/troca_glob.out
Antes da troca: x = 5, y = 7
Dentro de troca_variaveis: x = 7, y = 5
Depois da troca: x = 7, y = 5
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/funcoes/troca_main.c
#include <stdio.h>
int main() {
	int x = 5;
	int y = 7;
	printf("Antes da troca: x = %d, y = %d\n", x, y);
	// troca_variaveis
	int a = x, b = y;
	int temp = a;
	a = b;
	b = temp;
	printf("Dentro de troca_variaveis: a = %d, b = %d\n", a, b);
	// fim de troca_variaveis
	printf("Depois da troca: x = %d, y = %d\n", x, y);
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/funcoes/troca_ref.c
#include <stdio.h>
void troca_variaveis(int *a, int *b) { // <1>
	int temp = *a;
	*a = *b; // <2>
	*b = temp;
	printf("Dentro de troca_variaveis: a = %d, b = %d\n", *a, *b);
}
int main() {
	int x = 5;
	int y = 7;
	printf("Antes da troca: x = %d, y = %d\n", x, y);
	troca_variaveis(&x, &y); // <3>
	printf("Depois da troca: x = %d, y = %d\n", x, y);
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/funcoes/troca_ref.out
Antes da troca: x = 5, y = 7
Dentro de troca_variaveis: a = 7, b = 5
Depois da troca: x = 7, y = 5
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/helloworld.c
/* Hello World program */
#include<stdio.h> // <1> 
main()
{
 printf("Hello World"); // <2> imprime "Hello Word" na tela.
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/registros/calculo_das_medias.c
#include <stdio.h>
typedef struct {
	int matricula;
	char nome[100];
	float nota1;
	float nota2;
} Aluno;
#define QUANTIDADE_DE_ALUNOS 3
int main(){
	Aluno alunos[QUANTIDADE_DE_ALUNOS];
	printf("Dados: nome(sem espacos), matricula, nota1, nota2\n");
	for(int i=0; (i < QUANTIDADE_DE_ALUNOS); i++){
		printf("\nInforme os dados do aluno(%i): ",i+1);
		scanf("%s %i %f %f",alunos[i].nome, &alunos[i].matricula,
			&alunos[i].nota1, &alunos[i].nota2);
	}
	printf("\nMatricula\tNome\tMedia\n");
	for(int i=0; (i < QUANTIDADE_DE_ALUNOS);
i++){
		printf("%i\t%s\t%1.2f\n",alunos[i].matricula,alunos[i].nome,
			(alunos[i].nota1 + alunos[i].nota2)/2);
	}
	getchar();
	return 0;
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/registros/calculo_das_medias.data
Jesuíno 2887399 6.0 7.5
Maria 2887398 7.0 9.0
Virgulino 2887400 10.0 8.0
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/registros/calculo_das_medias_pseudo.txt
QUANTIDADE_DE_ALUNOS = 3
DECLARA alunos: Aluno[QUANTIDADE_DE_ALUNOS]
PARA i=0 ATÉ QUANTIDADE_DE_ALUNOS FAÇA
 LEIA alunos[i].nome
 LEIA alunos[i].matricula
 LEIA alunos[i].nota1
 LEIA alunos[i].nota2
FIM_PARA
PARA i=0 ATÉ QUANTIDADE_DE_ALUNOS FAÇA
 ESCREVA alunos[i].matricula
 ESCREVA alunos[i].nome
 ESCREVA (alunos[i].nota1 + alunos[i].nota2)/2 <1>
FIM_PARA
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/registros/calculo_das_medias_simulacao.txt
Dados do aluno: nome(sem espacos), matricula, nota1, nota2
Informe os dados do aluno(1): Jesuíno 2887399 6.0 7.5
Informe os dados do aluno(2): Maria 2887398 7.0 9.0
Informe os dados do aluno(3): Virgulino 2887400 10.0 8.0
Matricula	Nome	Media
2887399	Jesuíno	6.75
2887398	Maria	8.00
2887400	Virgulino	9.00
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/registros/conta_bancaria.c
#include <stdio.h>
typedef struct {
	char nome[256];
	long long cpf;
} Cliente;
typedef struct {
	long numero_da_conta;
	long cpf_do_cliente;
	double saldo;
} Conta;
#define QUANTIDADE_DE_CLIENTES 3
#define OPERACAO_SAQUE 1
#define OPERACAO_DEPOSITO 2
int main(){
 Cliente clientes[QUANTIDADE_DE_CLIENTES];
 Conta contas[QUANTIDADE_DE_CLIENTES];
 printf("Campos: cpf nome deposito-inicial\n");
 for(long i=0; (i < QUANTIDADE_DE_CLIENTES); i++){
 printf("\nDados para abertura da conta(%ld): ",i+1);
 scanf("%Ld %s %lf",&clientes[i].cpf,clientes[i].nome,
 &contas[i].saldo);
 contas[i].numero_da_conta = i;
 contas[i].cpf_do_cliente = clientes[i].cpf;
 printf("\nCliente: %s Conta: %ld Saldo inicial: %1.2lf\n",
 clientes[i].nome, contas[i].numero_da_conta, contas[i].saldo);
 }
 int operacao; // como ainda não aprendemos a comparar strings,
 // vamos usar 'operação' como numérico.
 long num_conta;
 double valor;
 int sair=0; // FALSE
 while (!sair){
 printf("\nInforme a operação: 1-Saque 2-Deposito 3-Sair: ");
 scanf("%d", &operacao);
 if (operacao == OPERACAO_SAQUE || operacao == OPERACAO_DEPOSITO){
 printf("\nInforme numero-da-conta e valor: ");
 scanf("%ld %lf", &num_conta, &valor);
 for(int i=0; (i < QUANTIDADE_DE_CLIENTES); i++){
 if (contas[i].numero_da_conta == num_conta) {
 if (operacao == OPERACAO_SAQUE){
 contas[i].saldo -= valor;
 printf("\nSAQUE: %1.2lf", valor);
 }
 if (operacao == OPERACAO_DEPOSITO){
 contas[i].saldo += valor;
 printf("\nDEPOSITO: %1.2lf", valor);
 }
 for(int j=0; j < QUANTIDADE_DE_CLIENTES; j++){
 if (clientes[j].cpf == contas[i].cpf_do_cliente)
 printf("\nCliente: %s Saldo atual: %1.2lf",
 clientes[j].nome, contas[i].saldo);
 }
 }
 }
 }else{
 sair = 1; // TRUE
 }
 }
 getchar();
 return 0;
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/registros/conta_bancaria_simulacao.txt
Campos: cpf nome deposito-inicial
Dados para abertura da conta(1): 48755891748 Jesuíno 1500
Cliente: Jesuíno Conta: 0 Saldo inicial: 1500.00
Dados para abertura da conta(2): 72779162201 Maria 200
Cliente: Maria Conta: 1 Saldo inicial: 200.00
Dados para abertura da conta(3): 71443626406 Virgulino 600
Cliente: Virgulino Conta: 2 Saldo inicial: 600.00
Informe a operação: 1-Saque 2-Deposito 3-Sair: 1
Informe numero-da-conta e valor: 0 300
SAQUE: 300.00
Cliente: Jesuíno Saldo atual: 1200.00
Informe a operação: 1-Saque 2-Deposito 3-Sair: 2
Informe numero-da-conta e valor: 2 400
DEPOSITO: 400.00
Cliente: Virgulino Saldo atual: 1000.00
Informe a operação: 1-Saque 2-Deposito 3-Sair: 3
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/registros/exercicio_aluno.data
Maria 12887398 7.0 9.0
Jesuíno 12887399 3.5 6.0
Virgulino 12887400 10.0 8.0
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/registros/exercicio_pessoa.data
Jesuíno 1.82 79 48755891748 m
Maria 1.66 52 72779162201 f
Virgulino 1.75 80 71443626406 m
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/registros/exercicio_ponto.data
1 3
-2 4
-3 -3
2 -5
4 0
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/registros/exercicio_produto.data
11 laranja 1.4
12 rosquinha 3
13 leite-moca 4.5
14 farinha-de-trigo 2.7
15 coxinha 1.5
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/registros/imc_calculo.c
#include <stdio.h>
typedef struct{
	char nome[100];
	char sexo; // 'm': masculino, 'f': femino
	float peso;
	float altura;
	long long cpf;
} Pessoa;
#define QUANTIDADE_DE_PESSOAS 3
int main(){
	Pessoa pessoas[QUANTIDADE_DE_PESSOAS];
	printf("Campos: nome, altura, peso, cpf, sexo\n");
	for(int i=0; (i < QUANTIDADE_DE_PESSOAS); i++){
		printf("\nInforme os dados da pessoa(%i): ",i+1);
		scanf("%s %f %f %Lu %c",pessoas[i].nome, &pessoas[i].altura,
			&pessoas[i].peso, &pessoas[i].cpf, &pessoas[i].sexo);
	}
	printf("\nInforme o CPF da pessoa: ");
	long long cpf_localizador;
	scanf("%Lu",&cpf_localizador); // <1>
	printf("\nSexo\tNome\tIMC");
	for(int i=0; (i < QUANTIDADE_DE_PESSOAS); i++){ //<2>
		if (cpf_localizador == pessoas[i].cpf){ //<2>
			float imc = pessoas[i].peso / (pessoas[i].altura * 
				pessoas[i].altura);
			printf("\n%c\t%s\t%1.2f\n",pessoas[i].sexo, 
				pessoas[i].nome, imc);
			break;
		}
	}
	getchar();
	return 0;
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/registros/imc_calculo_pseudo.txt
QUANTIDADE_DE_PESSOAS = 3
PARA i=0 ATÉ QUANTIDADE_DE_PESSOAS FAÇA
 LEIA pessoas[i].nome
 LEIA pessoas[i].altura
 LEIA pessoas[i].peso
 LEIA pessoas[i].cpf
 LEIA pessoas[i].sexo
FIM-PARA
DECLARA cpf_localizador: NUMÉRICO
LEIA cpf_localizador <1>
PARA i=0 ATÉ QUANTIDADE_DE_PESSOAS FAÇA <2>
 SE pessoas[i].cpf == cpf_localizador ENTÃO <2>
 ESCREVE pessoas[i].nome
 ESCREVE pessoas[i].sexo
 // IMC = peso / (altura * altura)
 ESCREVE pessoas[i].peso / (pessoas[i].altura * pessoas[i].altura)
FIM-PARA
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/registros/imc_calculo_simulacao.txt
Campos: nome, altura, peso, cpf, sexo
Informe os dados da pessoa(1): Jesuíno 1.82 79 48755891748 m
Informe os dados da pessoa(2): Maria 1.66 52 72779162201 f
Informe os dados da pessoa(3): Virgulino 1.75 80 71443626406 m
Informe o CPF da pessoa: 72779162201
Sexo	Nome	IMC
f	Maria	18.87
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/registros/ponto_proximo.c
#include <stdio.h>
#include <limits.h> // contém definição de INT_MAX
typedef struct{
	int x;
	int y;
} Ponto;
#define QUANTIDADE_DE_PONTOS 5
int main(){
	Ponto pontos[QUANTIDADE_DE_PONTOS];
	printf("Campos: x, y\n");
	for(int i=0; (i < QUANTIDADE_DE_PONTOS); i++){
		printf("\nInforme as coordenadas do ponto(%i): ",i+1);
		scanf("%d %d",&pontos[i].x,&pontos[i].y);
	}
	int menor_distancia_ao_quadrado = INT_MAX; // maior inteiro
	int ponto_mais_proximo = 1;
	for(int i=1; (i < QUANTIDADE_DE_PONTOS); i++){
		int distancia_ao_quadrado = (pontos[i].x-pontos[0].x)*
			(pontos[i].x-pontos[0].x)+(pontos[i].y-pontos[0].y)*
			(pontos[i].y-pontos[0].y);
		if(distancia_ao_quadrado < menor_distancia_ao_quadrado){
			ponto_mais_proximo = i;
			menor_distancia_ao_quadrado = distancia_ao_quadrado;
		}
	}
	printf("\nPonto mais proximo: (%d,%d)\n", 
		pontos[ponto_mais_proximo].x,
pontos[ponto_mais_proximo].y);
	getchar();
	return 0;
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/registros/ponto_proximo.data
0 0
4 6
6 1
5 3
7 2
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/registros/ponto_proximo_pseudo.txt
QUANTIDADE_DE_PONTOS = 5
PARA i=0 ATÉ QUANTIDADE_DE_PONTOS FAÇA
 LEIA p[i].x
 LEIA p[i].y
FIM_PARA
menor_distancia_ao_quadrado = MAIOR_INTEIRO <1>
ponto_mais_proximo = 1 <2>
PARA i=1 ATÉ QUANTIDADE_DE_PONTOS FAÇA
 distancia_ao_quadrado = (pontos[i].x-pontos[0].x)*
 (pontos[i].x-pontos[0].x)+(pontos[i].y-pontos[0].y)*
 (pontos[i].y-pontos[0].y) <3>
 SE distancia_ao_quadrado < menor_distancia_ao_quadrado ENTÃO <1>
 ponto_mais_proximo = i <2>
 menor_distancia_ao_quadrado = distancia_ao_quadrado <1>
FIM_PARA
ESCREVA p[ponto_mais_proximo].x,p[ponto_mais_proximo].y
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/registros/ponto_proximo_simulacao.txt
Campos: x, y
Informe as coordenadas do ponto(1): 0 0
Informe as coordenadas do ponto(2): 4 6
Informe as coordenadas do ponto(3): 6 1
Informe as coordenadas do ponto(4): 5 3
Informe as coordenadas do ponto(5): 7 2
Ponto mais proximo: (5,3)
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/registros/prob_conta_bancaria_pseudo.txt
QUANTIDADE_DE_CLIENTES = 3
DECLARA clientes: Cliente[QUANTIDADE_DE_CLIENTES]
DECLARA contas: Conta[QUANTIDADE_DE_CLIENTES]
PARA i=0 ATÉ QUANTIDADE_DE_CLIENTES FAÇA
 LEIA clientes[i].cpf
 LEIA clientes[i].nome
 LEIA contas[i].saldo // depósito inicial
 clientes[i].codigo = i
 contas[i].numero_da_conta = i
 contas[i].codigo_do_cliente = clientes[i].codigo
FIM_PARA
DECLARA operacao: TEXTUAL
DECLARA num_conta, valor, sair=0: NUMÉRICO
ENQUANTO sair == 0 FAÇA
 LEIA operacao
 SE operacao == "saque" OU operacao == "deposito" ENTÃO
 LEIA num_conta, valor
 PARA i=0 ATÉ QUANTIDADE_DE_CLIENTES FAÇA
 SE contas[i].numero_da_conta == num_conta ENTÃO
 SE operacao == "saque" ENTÃO
 contas[i].saldo = contas[i].saldo - valor
 SE operacao == "deposito" ENTÃO
 contas[i].saldo = contas[i].saldo + valor
 PARA j=0 ATÉ QUANTIDADE_DE_CLIENTES FAÇA
 SE clientes[j].codigo == contas[i].codigo_do_cliente ENTÃO
 ESCREVE clientes[j].nome, contas[i].saldo
 FIM_PARA
 FIM_PARA
 SENÃO operacao == "sair" ENTÃO
 sair = 1
FIM_ENQUANTO
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/registros/prob_supermercado_pseudo.txt
QUANTIDADE_DE_PRODUTOS = 5
DECLARA produtos: Produto[QUANTIDADE_DE_PRODUTOS]
PARA i=0 ATÉ QUANTIDADE_DE_PRODUTOS FAÇA
 LEIA produtos[i].codigo
 LEIA produtos[i].nome
 LEIA produtos[i].preco
FIM_PARA
PARA i=0 ATÉ QUANTIDADE_DE_PRODUTOS FAÇA
 ESCREVA produtos[i].codigo
 ESCREVA produtos[i].nome
FIM_PARA
DECLARA codigo_digitado: NUMÉRICO
LEIA codigo_digitado
PARA i=0 ATÉ QUANTIDADE_DE_PRODUTOS FAÇA
 SE produtos[i].codigo == codigo_digitado ENTÃO
 ESCREVA produtos[i].preco
FIM_PARA
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/registros/reg_aluno.c
typedef struct {
	int matricula;
	char nome[100];
	float nota1;
	float nota2;
} Aluno;
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/registros/reg_aluno_exemplo.c
#include <stdio.h>
#include <string.h>
typedef struct {
	int matricula;
	char nome[100];
	float nota1;
	float nota2;
} Aluno;
int main(){
	Aluno aluno;
	aluno.matricula = 201328; //<1>
	strncpy(aluno.nome, "Maria Bonita", sizeof(aluno.nome)); //<2>
	aluno.nota1 = 8.0; //<1>
	aluno.nota2 = 9.0; //<1>
	printf("\n%d %s %1.2f %1.2f", aluno.matricula, aluno.nome, // <3>
		aluno.nota1, aluno.nota2); //<3>
	getchar();
	return 0;
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/registros/reg_aluno_exemplo_simulacao.txt
201328 Maria Bonita 8.00 9.00
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/registros/reg_aluno_pseudo.txt
REGISTRO Aluno
 matricula: NUMÉRICO
 nome: TEXTO
 nota1, nota2: NUMÉRICO
FIM_REGISTRO
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/registros/reg_atribuicao.c
#include <stdio.h>
typedef struct {
	int matricula; // <1>
	char nome[100];// <1>
	float nota1; // <1>
	float nota2; // <1>
} Aluno;
typedef struct {
	char nome[256];// <2>
	long long cpf; // <2>
} Cliente;
int main() {
	Aluno a = {15, "Virgulino da Silva", 9.0f, 10.0f}; // <1>
	Cliente c = {"Maria Bonita", 72779162201}; // <2>
	printf("Aluno: %s Mat.: %d Nota1: %1.2f Nota2: %1.2f\n", 
		a.nome, a.matricula, a.nota1, a.nota2);
	printf("Cliente: %s CPF: %1Ld\n", c.nome,c.cpf);
	return 0;
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/registros/reg_atribuicao_simulacao.txt
Aluno: Virgulino da Silva Mat.: 15 Nota1: 9.00 Nota2: 10.00
Cliente: Maria Bonita CPF: 72779162201
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/registros/reg_cliente.c
typedef struct {
	char nome[256];
	long long cpf;
} Cliente;
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/registros/reg_cliente_pseudo.txt
REGISTRO Cliente
 cpf: NUMÉRICO
 nome: TEXTUAL
FIM_REGISTRO
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/registros/reg_conta.c
typedef struct {
	long numero_da_conta;
	long cpf_do_cliente;
	double saldo;
} Conta;
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/registros/reg_conta_pseudo.txt
REGISTRO Conta
 numero_da_conta, cpf_do_cliente, saldo: NUMÉRICO
FIM_REGISTRO
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/registros/reg_infopessoal.c
#include <stdio.h>
typedef struct {
	long long cep;
	int estado_civil; // 1:Solteiro 2:Casado 3:Viuvo 4:Divorciado
} InformacaoPessoal;
typedef struct {
	int matricula;
	char nome[100];
	float nota1;
	float nota2;
	InformacaoPessoal info_pessoal;
} Aluno;
typedef struct {
	char nome[256];
	long long cpf;
	InformacaoPessoal info_pessoal;
} Cliente;
int main() {
	Aluno a = {15, "Virgulino da Silva", 9.0f, 10.0f, {58051400, 1}};
	Cliente c = {"Maria Bonita", 72779162201, {58051400, 2}};
	printf("Aluno: %s %1Ld %d.\n", a.nome, a.info_pessoal.cep, 
		a.matricula);
	printf("Cliente: %s %1Ld %1Ld.\n", c.nome, c.info_pessoal.cep, 
		c.cpf);
	return 0;
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/registros/reg_infopessoal_pseudo.txt
REGISTRO InformacaoPessoal
 cep: NUMÉRICO
 estado_civil: TEXTO
FIM_REGISTRO
REGISTRO Aluno
 matricula: NUMÉRICO
 nome: TEXTO
 nota1, nota2: NUMÉRICO
 info_pessoal: InformacaoPessoal
FIM_REGISTRO
REGISTRO Cliente
 cpf: NUMÉRICO
 nome: TEXTUAL
 info_pessoal: InformacaoPessoal
FIM_REGISTRO
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/registros/reg_pessoa.c
typedef struct{
	char nome[100];
	char sexo; // 'm': masculino, 'f': femino
	float peso;
	float altura;
	long long cpf;
} Pessoa;
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/registros/reg_pessoa_pseudo.txt
REGISTRO Pessoa
 nome, sexo: TEXTO
 peso, altura, cpf: NUMÉRICO
FIM_REGISTRO
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/registros/reg_ponto.c
typedef struct{
	int x;
	int y;
} Ponto;
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/registros/reg_ponto_exemplo.c
#include <stdio.h>
#include <string.h>
typedef struct{
	int x;
	int y;
} Ponto;
#define QUANTIDADE_DE_PONTOS 3 // <1>
int main(){
	Ponto pontos[QUANTIDADE_DE_PONTOS]; // <2>
	pontos[0].x = -4; pontos[0].y = 7;// <3>
	pontos[1].x = 2; pontos[1].y = -9;// <3>
	pontos[2].x = 5; pontos[2].y = 3;// <3>
	for (int i = 0; i < QUANTIDADE_DE_PONTOS ; i++){
		if(pontos[i].y > 0)
			printf("\nPonto acima da reta: (%d,%d)", 
				pontos[i].x,
pontos[i].y);
	}
	getchar();
	return 0;
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/registros/reg_ponto_exemplo_simulacao.txt
Ponto acima da reta: (-4,7)
Ponto acima da reta: (5,3)
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/registros/reg_ponto_matematica_pseudo.txt
REGISTRO Ponto
 x, y: NUMÉRICO
FIM_REGISTRO
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/registros/reg_produto.c
typedef struct {
	long codigo;
	char nome[100];
	float preco;
} Produto;
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/registros/reg_produto_exemplo.c
#include <stdio.h>
typedef struct {
	long codigo;
	char nome[100];
	float preco;
} Produto;
int main(){
	Produto p;
	scanf("%ld %s %f", &p.codigo, p.nome, &p.preco); //<1>
	if (p.preco < 4)
		printf("\nProduto em promocao: %s R$ %1.2f", p.nome, p.preco);
	else
		printf("\nProduto cadastrado.");
	getchar();
	return 0;
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/registros/reg_produto_exemplo_simulacao.txt
Produto em promocao: banana R$ 3.99
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/registros/reg_produto_supermercado_pseudo.txt
REGISTRO Produto
 codigo: NUMÉRICO
 nome: TEXTUAL
 preco: NUMÉRICO
FIM_REGISTRO
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/registros/reg_triangulo.c
#include <stdio.h>
typedef struct {
	int x;
	int y;
} Ponto ;
typedef struct {
	Ponto p1;
	Ponto p2;
	Ponto p3;
} Triangulo ;
int main() {
	Triangulo t;
	t.p1.x= 1; t.p1.y=0;
	t.p2.x=-1; t.p2.y=0;
	t.p3.x= 0; t.p3.y=1;
	printf("Triangulo: (%d, %d), (%d, %d), (%d, %d).\n", 
		t.p1.x, t.p1.y, t.p2.x, t.p2.y, t.p3.x, t.p3.y);
	return 0;
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/registros/reg_triangulo_pseudo.txt
REGISTRO Ponto
	x, y: NUMÉRICO
FIM_REGISTRO
REGISTRO Triangulo
	p1, p2, p3: Ponto
FIM_REGISTRO
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/registros/supermercado.c
#include <stdio.h>
typedef struct {
	long codigo;
	char nome[100];
	float preco;
} Produto;
#define QUANTIDADE_DE_PRODUTOS 5
int main(){
	Produto produtos[QUANTIDADE_DE_PRODUTOS];
	printf("Campos: codigo-do-produto nome preco\n");
	for(int i=0; (i < QUANTIDADE_DE_PRODUTOS); i++){
		printf("\nInforme os dados do produto(%i): ",i+1);
		scanf("%ld %s %f",&produtos[i].codigo,produtos[i].nome,
			&produtos[i].preco);
	}
	for(int i=0; (i < QUANTIDADE_DE_PRODUTOS); i++){
		printf("\n%ld\t%s R$ %1.2f", produtos[i].codigo,
			produtos[i].nome,produtos[i].preco);
	}
	long codigo_digitado;
	printf("\nInforme o codigo do produto: ");
	scanf("%ld", &codigo_digitado);
	for(int i=1; (i < QUANTIDADE_DE_PRODUTOS); i++){
		if (produtos[i].codigo == codigo_digitado) {
			printf("\nPreço: R$ %1.2f\n", produtos[i].preco);
		}
	}
	getchar();
	return 0;
}
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/registros/supermercado.data
1 laranja 1.4
2 rosquinha 3
3 leite-moca 4.5
4 farinha-de-trigo 2.7
5 coxinha 1.5
4
introducao-a-programacao-livro-1.0.0/livro/capitulos/code/registros/supermercado_simulacao.txt
Campos: codigo-do-produto nome preco
Informe os dados do produto(1): 1 laranja 1.4
Informe os dados do produto(2): 2 rosquinha 3
Informe os dados do produto(3): 3 leite-moca 4.5
Informe os dados do produto(4): 4 farinha-de-trigo 2.7
Informe os dados do produto(5): 5 coxinha 1.5
1	laranja R$ 1.40
2	rosquinha R$ 3.00
3	leite-moca R$ 4.50
4	farinha-de-trigo R$ 2.70
5	coxinha R$ 1.50
Informe o codigo do produto: 4
Preço: R$ 2.70
introducao-a-programacao-livro-1.0.0/livro/capitulos/estruturas-de-controle.asc
[[estrutura_controle]]
== Estruturas de Controle 
.Objetivos do capítulo
____________________
Ao final deste capítulo você deverá ser capaz de:
* Entender as estruturas sequenciais, de seleção e de repetição;
* Escrever estruturas de seleção utilizando os comandos if, if-else e switch 
da linguagem C; 
* Escrever estruturas de repetição utilizando os comandos for, while e 
do-while da linguagem C.
____________________
////
TODO - REV.01: Sugestão de melhoria para análise pelo autor 
Neste capítulo é importante refletir o que realmente pretendemos ensinar para o aluno.
Aqui vejo dois conteúdos distintos um é a discussão sobre as estruturas algorítmicas
e um outro seria o ensino da linguagem C para programação. Pelo que se lê
a intenção é ensinar algoritmos usando a linguagem C como padrão, contudo,
seria aconselhável nesse caso termos algo que introduza o que é uma linguagem de programação
e suas respectivas características falando um pouco mais da linguagem C. A partir daí
passaria a explanação do desenvolvimento de algoritmos utilizando como base essa
linguagem, inclusive na finalizaçaõ do capítulo de Algoritmos é dito isso. 
A transição do conteúdo do capítulo anterior para esse não está suave para 
o aluno. 
////
=== Introdução
Vimos no <<algoritimos>> que os algoritmos são instruções que contém passos para 
solucionar um determinado problema. Vimos também que estes algoritmos podem 
ser representados através de linguagens de programação, como por exemplo, a 
linguagem C, que estamos aprendendo aqui. Estes passos são executados na 
sequência que eles aparecem. Entretanto, em muitas situações, é necessário 
alterar o fluxo de execução destas instruções. Pode ser que seja necessário 
executar um passo, ou um conjunto deles, apenas se uma determinada condição `for` 
verdadeira, ou talvez, pode ser que seja preciso repetir um conjunto de passos várias vezes 
até uma determinada condição. Neste sentido, este capítulo irá explicar as 
diferentes estruturas de controle existentes nos algoritmos e seus respectivos 
comandos na linguagem C.
=== Estrutura Sequencial
Um algoritmo que possui uma estrutura sequencial significa que suas 
instruções são executadas na sequência em que elas aparecem, sem nenhuma 
alteração no seu fluxo, a não ser, claro, que exista alguma instrução 
explícita para a mudança deste fluxo. Vejamos o código em C na 
<<estrutura_sequencial>> abaixo.
[[estrutura_sequencial]]
.Estrutura sequencial na linguagem C
image::images/estruturas-de-controle/sequencia.eps[scaledwidth="40%"]
Este algoritmo irá ler dois valores e guardá-los, respectivamente, nas 
variáveis `x` e `y`. Após isso, a variável inteira 'soma' receberá a soma dos 
valores de `x` e `y`. Em seguida, será mostrada na saída padrão, o resultado 
desta soma. Perceba que os passos do algoritmo são executados de cima para 
baixo.
Entretanto, em alguns momentos os problemas que queremos resolver requerem a 
alteração no fluxo normal de execução do algoritmo. Na próxima seção, 
iremos aprender como executar um conjunto de instruções de acordo com uma determinada 
condição.
=== Estrutura de Decisão
Como foi dito, muitas vezes é necessário criar blocos de instruções no 
algoritmo que são executados apenas se uma determinada condição `for` 
verdadeira. Veja o algoritmo abaixo:
 "Se hoje não chover, então João irá à praia".
No algoritmo acima, João irá à praia se, e somente se, não chover hoje. 
Significa que esta instrução de João ir à praia só será executada se a 
condição de não chover for verdadeira. Este tipo de estrutura é chamado de 
*estrutura de decisão*, também conhecido como estrutura de seleção ou 
condicional.
Podemos ter três tipos de estrutura de decisão: decisão simples, decisão 
composta e decisão múltipla. Vamos ver adiante estes três tipos e quais são 
os comandos na linguagem C, respectivamente, para cada um destes tipos.
////
TODO - REV.02: Sugestão de melhoria para análise pelo autor 
Senti muito falta de gráficos e/ou diagramas nas explicações que seguem.
O conteúdo pode ser bem representado usando os fluxogramas que auxiliam
o entendimento das estruturas de
controle. Será que não seria interessante
ilustrar com esse tipo de gráfico?
////
==== Decisão simples
(((Se)))
Quando queremos que uma determinada instrução ou um conjunto de instruções 
execute apenas se uma determinada condição for verdadeira. A estrutura da 
decisão simples é a seguinte:
 SE condição ENTÃO instrução
Uma condição deve ter como resultado apenas dois valores possíveis: 
verdadeiro ou falso. A instrução só será executada se a condição tiver o 
valor verdadeiro.
////
TODO - REV.03: Sugestão de melhoria para análise pelo autor 
Seria possível na explicação que segue referenciar o número da linha
de código onde os comandos aparecem? Ficaria mais claro para o aluno.
Sugeriria que todo código tivesse número de linha, isso ajudaria
a referenciar durante a explicação.
////
Vamos analisar o exemplo a seguir. Este algoritmo lê um valor digitado pelo 
usuário e armazena na variável `x`. Em seguida, o comando `SE` verifica se o 
valor de `x` é menor que `20`. Caso seja, a instrução `ESCREVA` é executada, 
mostrando na tela a frase "o valor de X é menor que 20".
(((LEIA)))(((ESCREVA)))
[[alg_menorq20]]
.Algoritmo que comparava valor lido com 20
============
 LEIA x
 SE x < 20 ENTÃO 
 ESCREVA "O valor de x é menor que 20."
============
Para cada linguagem de programação há uma sintaxe para criar estruturas de 
controle. Na Linguagem C, a estrutura de decisão simples possui a seguinte 
forma: 
[source, c]
----
 if (expressão) 
 instrução;
----
Na linguagem C, a condição é definida como uma expressão, que pode ser 
lógica ou aritmética. Ao ser executada, a expressão é verificada. Se o 
resultado desta for verdadeiro, a instrução que vem após a expressão é 
executada. 
Entretanto, muitas vezes queremos que mais de uma instrução seja executada 
caso a condição seja verdadeira. Neste caso, devemos utilizar um bloco de 
instruções dentro do comando *if*, como é mostrado abaixo. 
(((if)))
.Estrutura de decisão simples com blocos na linguagem C
[source, c]
----
 if (expressão) {
 instrução 1;
 instrução 2;
 ...
 }
----
As duas formas, com e sem bloco, se diferenciam apenas pelo fato de que a 
primeira possui apenas uma instrução a ser executada caso a condição seja 
verdadeira. No segundo caso, um bloco de instruções será executado. Na 
linguagem C, um bloco de instruções deve estar entre chaves.
[IMPORTANT]
Sempre que você precisar executar um bloco de instruções, utilize as chaves 
para delimitar o início e o fim deste bloco. 
////
FIXME - REV.04: Possível erro para análise pelo autor 
No parágrafo seguinte se menciona que as expressões aritméticas foram vistas
no capítulo 2, mas o cap 2 é o capítulo corrente não? 
////
Como foi dito, a expressão pode conter uma expressão lógica ou aritmética. 
As expressões aritméticas foram vistas no capítulo 2. Vamos ver agora como 
funcionam as expressões lógicas na linguagem C.
// FIXME adicionar link para o capítulo 2 no paragrafo acima.
===== Expressões lógicas
(((Expressões lógicas)))
////
TODO - REV.05: Sugestão de melhoria para análise pelo autor 
Seria interessante deixar claro que são os operandos e o operador 
em uma expressão lógica. 
////
As expressões lógicas são usualmente utilizadas para fazer comparações 
entre operandos. Para isso, estas expressões são compostas por operadores 
lógicos e relacionais, e possuem apenas dois valores possíveis: verdadeiro ou 
falso. Por exemplo, quando queremos saber se um valor é maior, menor, igual ou 
diferente de um outro valor.
Na linguagem C, os seguintes operadores relacionais podem ser utilizados:
[width="50%",cols="^1,^1",options="header"]
|========================
| Operador | Descrição
| `>` | Maior que
| `<` | Menor que
| `>=` | Maior ou igual a
| `<=` | Menor ou igual a
| `==` | Igual a
| `!=` | Diferente de
|========================
	
Considere o código <<menorq20>> abaixo. Este reflete o mesmo algoritmo de <<alg_menorq20>>, 
sendo que agora, implementado na linguagem C. Na linha 6, estamos pedindo para 
o usuário entrar com o valor de `x`. Na linha 8, temos um comando `if`, onde há 
uma expressão relacional `x < 20`. Portanto, essa expressão é verificada e caso 
seja verdadeira, será mostrado na saída padrão "O valor de x é menor que a 
20." (linha 9). Caso a expressão seja falsa, o algoritmo se encerra sem mostrar 
nada na saída padrão, pois a instrução após o comando `if` não é executada. 
////
TODO - REV.06: Sugestão de melhoria para análise pelo autor 
Seria interessante representar esse algoritmo em c também usando
o fluxograma, isso daria ao aluno uma visão mais clara do condicional 
e o que seria executado dependendo do resultado da expressfão lógica. 
////
.Código fonte
{gitrepo}/blob/master/livro/capitulos/code/estruturas-de-controle/menorq20.c[code/estruturas-de-controle/menorq20.c]
[[menorq20]]
[source, c, numbered]
.menorq20.c
----
include::code/estruturas-de-controle/menorq20.c[]
----
Em outros casos, necessitamos utilizar operadores lógicos nas expressões para 
avaliar mais de uma expressão relacional. Por exemplo, digamos que no problema 
acima queremos verificar se o valor digitado para a variável `x` está dentro do 
intervalo entre `10` *e* `20`. Neste caso, precisamos que a condição verifique as 
duas expressões relacionais: `(x > 10)` *e* `(x < 20)`. Portanto, precisamos 
conectar as duas expressões relacionais utilizando um operador lógico `E`. A 
tabela abaixo apresenta os operadores lógicos possíveis:
////
TODO - REV.07: Sugestão de melhoria para análise pelo autor 
O quadro apresentado a seguir parece confuso. Na verdade,
ele apresenta o operador na linguagem C e diz como descrição o equivalente
em linguagem algoritmica (LA). Sugeriria fazer o inverso e adicionar uma 
melhor explicação do que é cada operador, por exemplo, na 1a
coluna seria o operador em LA, em seguida fornecer uma descrição mais 
explicativa, e depois apresentar a sintaxe equivalente na linguagem C. 
////
(((E))) (((Ou))) (((Não)))
[width="50%",cols="^1,^1",options="header"]
|========================
| Operador em C | Operador em linguagem algorítmica
| && | E
| \|\| | OU
| ! | NÃO
|========================
Portanto, o algoritmo para resolver o problema acima, na linguagem C, é o 
seguinte:
.Código fonte
{gitrepo}/blob/master/livro/capitulos/code/estruturas-de-controle/[code/estruturas-de-controle/entre10e20.c]
[source, c, numbered]
.entre10e20.c
----
include::code/estruturas-de-controle/entre10e20.c[]
----
Perceba que agora a condição do comando `if` possui duas expressões 
relacionais conectadas por um operador lógico `E` (`&&`). Nesse caso, se ambas as 
expressões forem verdadeiras, será mostrada na saída padrão "x esta' entre 
10 e 20". Caso alguma das expressões seja falsa, nada será mostrado, pois o 
resultado da expressão completa é falso. Vejamos a tabela abaixo, denominada de tabela verdade,
que mostra a relação lógica entre duas expressões e seus respectivos resultados.
////
TODO - REV.09: Sugestão de melhoria para análise pelo autor 
Sugeriria dividir o quadro que segue em três, isso deixaria o texto mais
legível para o leitor. 
Seria interessante falar que os operadores tem precedência e como
fazer para alterá-la de forma explícita.
////
[cols="^1,^1m,^1,^1",options="header"]
|========================
|Expressão 1|Operador|Expressão 2|Resultado
|Verdadeiro|E|Verdadeiro|Verdadeiro
|Verdadeiro|E|Falso|Falso
|Falso|E|Falso|Falso
|Verdadeiro|OU|Verdadeiro|Verdadeiro
|Verdadeiro|OU|Falso|Verdadeiro
|Falso|OU|Falso|Falso
|Verdadeiro|NÃO|-|Falso
|Falso|NÃO|-|Verdadeiro
|========================
////
TODO - REV.10: Sugestão de melhoria para análise pelo autor 
Considerando os exercícios resolvidos, nesse ponto o leitor sabe o que é uma variável? Sabe o que é uma atribuição de valor?
Acredito não ter ficado claro até o momento esses pontos básicos da programação. 
Não seria interessante ter falado um pouco sobre isso antes?
////
===== Exercício resolvido
*ER 3.1.* Considere quatro variáveis `a`, `b`, `c` e `d` com valores iniciais de 5, 7, 3 
e 9. Dada as condições abaixo, indique se o resultado final da expressão 
será verdadeiro ou falso.
a. `(a != 3 || b < 10 || c == 5)`
b. `(d > 8 && c == 3 || a >=10)`
c. `!(d == 12 && a != 10)`
d. `(c == 4 || d <= 6) && (a >= 5 && b != 9) || (!(a < 5))`
Resposta:
a. Neste caso temos três expressões lógicas. A primeira `(a != 3)` é 
verdadeira. A segunda `(b < 10)` é verdadeira, e a terceira `(c == 5)` é falsa. 
Como as expressões estão conectadas por um operador OU (`||`), então basta que 
uma das expressões seja verdadeira para o resultado da expressão completa ser 
verdadeira. 
b. Temos neste caso três expressões. Para um melhor entendimento, vamos 
utilizar uma tabela. As duas primeiras expressões `(d > 8 e c == 3)` são verdadeiras
e estão conectadas pelo operador lógico `&&`, logo `R1 && R2` é verdadeiro. 
A terceira expressão `(a >= 10)`, por sua vez, é falsa. Então, resolvendo `R3 || R4`, 
temos o resultado final como verdadeiro.
+
[format="csv",cols="^1,^1,^1",options="header"]
|===================================================
Rs, Expressão,	Resultado
R1,	`d > 8`,	VERDADEIRO
R2,	`c == 3`,	VERDADEIRO
R3,	`R1 && R2`,	VERDADEIRO
R4,	`a >= 10`,	FALSO
R5,	`R3 || R4`,	VERDADEIRO
|===================================================
c. Utilizando novamente a tabela, temos que a primeira expressão `(d == 12)` é 
falsa. A segunda expressão `(a != 10)` verdadeira. A relação entre `R1 && R2` 
é falsa, pois apenas `R2` é verdadeira. A última expressão é uma negação 
de `R3`, ou seja, se `R3` é falso, então `R4` é verdadeiro.
+
[format="csv",cols="^1,2,3",options="header"]
|===================================================
R,	Expressão,	Resultado
R1,	`d == 12`,	FALSO
R2,	`a != 10`,	VERDADEIRO
R3,	`R1 && R2`,	FALSO
R4,	`!R3`,	VERDADEIRO
|===================================================
d. Vamos utilizar novamente a tabela para nos auxiliar. Temos que prestar 
bastante atenção nos parênteses das expressões que podem ser utilizadas 
para explicitar a precedência da avaliação. 
+
[format="csv",cols="^1,2,3",options="header"]
|===================================================
Rs,	Expressão,	Resultado
R1,	`c == 4`,	FALSO
R2,	`d <= 6`,	FALSO
R3,	`R1 || R2`,	FALSO
R4,	`a >= 5`,	VERDADEIRO
R5,	`b != 9`,	VERDADEIRO
R6,	`R4 && R5`,	VERDADEIRO
R7,	`a < 5`,	FALSO
R8,	`!R7`,	VERDADEIRO
R9,	`R3 && R6`,	FALSO
R10,	`R9 || R8`,	VERDADEIRO
|===================================================
===== Verificação da condição com expressões aritméticas na Linguagem C
(((if)))
Anteriormente, dissemos que a expressão dentro de um comando `if` pode ser 
lógica ou aritmética. Vimos como funciona nos casos de expressões lógicas. 
Nos casos de expressões aritméticas, na linguagem C, 'Falso' assume o valor 
zero, e 'Verdadeiro' assume qualquer valor diferente de zero. Neste sentido, 
quando utilizamos uma expressão aritmética dentro da condição de um comando 
`if` para verificar se esta é verdadeira ou falsa, temos que ter o cuidado de 
analisar o valor resultante. Vamos verificar o exemplo no código abaixo.
.Código fonte
{gitrepo}/blob/master/livro/capitulos/code/estruturas-de-controle/if5.c[code/estruturas-de-controle/if5.c]
[source, c, numbered]
.if5.c
----
include::code/estruturas-de-controle/if5.c[]
----
Inicialmente a variável inteira `x` recebe o valor `5` (linha 4). Na linha 6 existe uma 
estrutura de decisão simples, onde há a verificação da expressão que está entre parênteses.
Nesse caso, a expressão é apenas a própria variável `x`, logo o resultado da expressão é 
o valor desta, que é `5`. Considerando o que foi dito, quando o resultado for 
*diferente de zero*, ele é considerado *verdadeiro*. Logo, o resultado da 
expressão também é verdadeiro, e então a instrução que vem após a condição é executada.
Já na linha 9, também há outra estrutura de decisão simples, na qual a 
condição a ser avaliada é a expressão `x - 5`. O resultado dessa expressão é *zero*, fazendo com
seja avaliada como *falsa*. Consequentemente, a instrução que vem após a condição não é executada.
==== Decisão composta 
(((if-else)))
////
FIXME - REV.11: Possível erro para análise pelo autor 
Rever a frase: "...momentos, ao termos uma estrutura...". 
////
Em alguns momentos, ao termos uma estrutura de decisão, queremos que uma outra 
instrução ou um outro bloco de instruções seja executado caso a condição 
de decisão seja falsa. Esta estrutura é chamada de decisão composta.
O pseudocódigo abaixo exemplifica uma estrutura de decisão composta. 
////
TODO - REV.12: Sugestão de melhoria para análise pelo autor 
Sugeriria adicionar também um gráfico em fluxograma exemplificando
a decisão composta. 
////
[[alg_decisao_composta]]
.Pseudocódigo com decisão composta
=====================
 LEIA nota
 SE nota >= 7 ENTÃO 
 ESCREVA "Aprovado"
 SENÃO
 ESCREVA "Reprovado"
=====================
Na linguagem C, utilizamos a palavra `else`, após a instrução ou bloco de 
instruções do `if`, para definir que queremos executar um outro conjunto de 
instruções, caso a expressão condicional seja falsa. 
////
TODO - REV.13: Sugestão de melhoria para análise pelo autor 
Sugeriria adicionar um quadro em que apresentasse o comando equivalente em C. 
////
[source, c]
----
 if (expressão) 
 instrução 1;
 else 
 instrução 2;
----
////
TODO - REV.14: Sugestão de melhoria para análise pelo autor 
Sugeriria adicionar lembretes em seções do tipo "Atenção!" ou "Importante!" reforçando
algumas particularidades da linguagem C. Por exemplo, toda instrução precisa ser terminada
com ";" e coisas assim.
////
Quando possuímos apenas uma instrução a ser executada, não precisamos 
utilizar o delimitador de bloco de instruções (as chaves). Neste caso, a 
condição é verificada. Caso seja positiva, a instrução 1 é executada, 
caso contrário, a instrução 2 é executada. Caso queiramos que um conjunto 
de instruções seja executado, devemos utilizar então as chaves, como mostra 
o código abaixo.
////
TODO - REV.15: Sugestão de melhoria para análise pelo autor 
Sugeriria representar o mesmo código também usando o fluxograma.
////
[source, c]
----
 if (condição) {
 instrução 1;
 instrução 2;
 ...
 } else {
 instrução 3;
 instrução 4;
 ...
 }
----
Neste caso temos dois blocos de instruções: um para o bloco do `if`, que será 
executado caso a condição seja verdadeira, e o bloco de instruções do `else`, 
caso a condição seja falsa.
(((indentação)))
IMPORTANT: Tabule as instruções que estão dentro dos blocos, colocando-os mais a 
direita (utilize a tecla TAB do teclado). Esta organização do código 
chama-se *indentação*. Dessa maneira, seu código se torna mais legível, e 
consequentemente mais fácil de encontrar possíveis erros. 
Vamos traduzir o pseudocódigo apresentado no <<alg_decisao_composta>> para a linguagem C.
.Código fonte
{gitrepo}/blob/master/livro/capitulos/code/estruturas-de-controle/nota7.c[code/estruturas-de-controle/nota7.c]
[source, c, numbered]
.nota7.c
----
include::code/estruturas-de-controle/nota7.c[]
----
===== Exercício resolvido
////
TODO - REV.16: Sugestão de melhoria para análise pelo autor 
Sugeriria adicionar pelo menos mais dois exercícios resolvidos.
Outro ponto para refletir em relação aos exercícios é a sintaxe
de programação da linguagem C, será que os alunos tem
amadurecimento para fazer o código como apresentado no 
exemplo, entender & e etc? Particularmente, estou achando 
que com o que eles conhecem até o momento não conseguiriam fazer.
////
*ER 3.2.* Escreva um programa para ler 2 números inteiros do teclado (A e B), 
verificar e imprimir
qual deles é o maior, ou a mensagem "A=B", caso sejam 
iguais.
Resposta:
.Código fonte
{gitrepo}/blob/master/livro/capitulos/code/estruturas-de-controle/comparaab.c[code/estruturas-de-controle/comparaab.c]
[source, c, numbered]
.comparaab.c
----
include::code/estruturas-de-controle/comparaab.c[]
----
==== Comando de decisão múltipla
(((switch)))
////
TODO - REV.17: Sugestão de melhoria para análise pelo autor 
Aqui já se fala direto no comando equivalente em C para o comando
escolha da linguagem algoritmica, isso deixa um pouco confuso o capítulo
em termos de conteúdo. É preciso estabelecer uma coerência para auxiliar o leitor
no entendimento do assunto que é considerado dificil por boa parte dos alunos.
////
Uma outra forma de escrever uma estrutura de condição é utilizando o comando 
de decisão múltipla `switch`. Este tipo de estrutura condicional tem a mesma 
função do `if-else-if`, com a diferença que o comando `switch` não aceita 
expressões, apenas constantes. A vantagem de se utilizar este comando é a 
legibilidade do código quando conhecemos os possíveis valores para uma 
determinada variável. Vamos ver o formato de uso do comando `switch`. 
[source, c]
----
 switch (variável) {
 case VALOR1: 
 instruçao1;
 instrução2;
 break;
 case VALOR2: 
 instruçao3;
 instrução4;
 break;
 default: 
 instruçao5;
 instrução6;
 break;
 }
----
Uma variável do tipo `char` ou `int` é colocada entre parênteses após o comando 
`switch`. Os valores desta variável que serão avaliados logo em seguida, através 
das declarações `case`. Para cada possível valor da variável, existe uma 
declaração `case` correspondente. Caso o valor seja aquele que corresponde na 
declaração `case`, então as instruções abaixo dela serão executadas até 
encontrar o comando `break`. A declaração `default` é opcional, e é executada 
apenas se a variável não for igual a nenhuma das constantes definidas nas 
declarações `case`.	
IMPORTANT: O comando `break` tem a função de interromper um determinado fluxo de 
execução. Este comando será melhor explicado na seção 3.4.5 que fala sobre 
os comandos de desvio. O importante a saber por hora é que o comando `break` 
deve ser utilizado ao final das instruções de cada declaração `case`. Caso 
não seja colocado, as instruções das outras declarações `case` também 
serão executadas.
//FIXME corrigir seção acima
////
TODO - REV.18: Sugestão de melhoria para análise pelo autor 
Nada foi falado sobre tipos de variáveis possiveis. Sugeriria 
mais uma vez que o código C apresentado fosse representado também
usando gráficos (fluxograma). Precisamos ser o mais didático possível,
principalmente, considerando essa parte introdutória da programação!
////
Para um melhor entendimento, vamos analisar o código <<semana_c>> abaixo. A ideia deste 
programa é que o usuário digite o valor numérico correspondente ao dia da 
semana e o programa mostre por extenso este dia. Uma variável chamada `semana` 
do tipo `int` é declarada (linha 4) e guardará o valor que o usuário irá 
digitar (linha 7). Em seguida, o comando `switch` foi utilizado (linha 9). Para 
cada dia da semana existe uma declaração `case` correspondente. Isto significa 
que se o usuário digitou o valor 1, a instrução da linha 11 será executada, mostrando 
na saída a string "Domingo". Caso o valor digitado seja 2, a instrução da linha 14 é 
executada, mostrando na saída a string "Segunda-feira". A mesma ideia acontece 
para os outros 5 dias da semana. Caso o valor digitado pelo usuário não esteja 
entre 1 e 7, as instruções da declaração `default` serão executadas, mostrando a 
string "Numero fora do intervalo permitido.".
.Código fonte
{gitrepo}/blob/master/livro/capitulos/code/estruturas-de-controle/semana.c[code/estruturas-de-controle/semana.c]
[[semana_c]]
[source, c, numbered]
.semana.c
----
include::code/estruturas-de-controle/semana.c[]
----
=== Estrutura de Repetição
(((Enquanto)))
Considere um algoritmo em que você precise repetir um determinado conjunto de 
passos, por exemplo, um algoritmo para retirar uma lâmpada do bocal. Um passo 
deste algoritmo é realizar um movimento com a mão para girar a lâmpada. Este 
passo deve ser repetido até que a lâmpada desencaixe do bocal. Neste sentido, 
existem as estruturas de repetições nas linguagens de programação para 
permitir que uma instrução ou um bloco de instruções seja repetido em um 
algoritmo computacional. Estas estruturas também são conhecidas como 
estruturas de iteração ou estruturas de laço.
Vamos tomar como base <<alg_decisao_composta>>, onde uma nota é solicitada ao 
usuário. Caso a nota seja maior que 7, é mostrado ``Aprovado'' na tela, caso 
contrário, é mostrado "Reprovado". O algoritmo utilizado, até então, só 
permite que uma nota seja digitada, ou seja, quando o usuário digita a nota, 
o programa apresenta o resultado e em seguida fecha. Mas digamos que agora 
queremos que o programa continue executando, solicitando notas e apresentando o 
resultado, até que o usuário digite o valor -1 para sair do programa.
Este algoritmo é mostrado no pseudocódigo abaixo. Perceba 
que temos uma condição `nota <> -1` que será avaliada antes de executar as 
instruções que estão dentro do bloco do `ENQUANTO`. Desse modo, enquanto a nota 
digitada pelo usuário for diferente de `-1`, o programa irá solicitar uma nota 
e apresentar o resultado.
////
TODO - REV.19: Sugestão de melhoria para análise pelo autor 
Sugeriria adicionar a forma gráfica para apoiar ainda mais a explicação.
////
[[alg_estrutura_repeticao]]
.Pseudocódigo com estrutura de repetição
========================
 LEIA nota
 ENQUANTO nota <> -1 FAÇA
 SE nota >= 7 ENTÃO
 ESCREVA "Aprovado"
 SENÃO
 ESCREVA "Reprovado"
 
 LEIA nota 
 FIM-ENQUANTO 
========================
Na linguagem C há três opções diferentes para se criar estruturas de 
repetição. São os comandos `while`, `do-while` e `for`. Veremos cada um deles em 
detalhes a seguir.
==== Comando while
(((while)))
Podemos usar o comando `while` quando desejamos que uma ou mais instruções 
sejam repetidas até que uma determinada condição seja atendida. A estrutura 
do `while` na linguagem C é bastante parecida com a do pseudocódigo apresentado
anteriormente. Veja abaixo:
[source, c]
----
 while (expressão) {
 instrução 1;
 instrução 2;
 ...
 }
----
As instruções serão executadas repetidamente enquanto a expressão for 
verdadeira. Assim que essa condição tornar-se falsa, o laço para. Vejamos o 
exemplo abaixo, que consiste no pseudocódigo do <<alg_estrutura_repeticao>>
escrito na linguagem C.
.Código fonte
{gitrepo}/blob/master/livro/capitulos/code/estruturas-de-controle/whilenota.c[code/estruturas-de-controle/whilenota.c]
[source, c, numbered]
.whilenota.c
----
include::code/estruturas-de-controle/whilenota.c[]
----
Vamos tentar entender o código acima. Inicialmente, uma variável `nota`, do tipo `float`, 
é declarada (linha 4). Logo depois ocorre a leitura da primeira nota.
Caso ela seja diferente de `-1`, o bloco de instruções dentro do `while` (linhas 8 a 14)
será executado. O comando `while` fará com que as instruções em seu corpo sejam executadas,
repetidamente, enquanto a condição `nota != -1` for verdadeira.
Vejamos outro exemplo. O programa <<mostrado10vezes>> abaixo escreve 10 vezes na tela "Isto sera' 
mostrado 10 vezes.". A condição de parada do comando `while` é `cont <= 10`, o que 
significa que enquanto o valor de `cont` for menor ou igual a `10`, o bloco de 
instruções será executado. Para que o laço tenha fim, a variável `cont` precisa ser incrementada
até que alcance o valor `11`.
.Código fonte
{gitrepo}/blob/master/livro/capitulos/code/estruturas-de-controle/mostrado10vezes.c[code/estruturas-de-controle/mostrado10vezes.c]
[[mostrado10vezes]]
[source, c, numbered]
.mostrado10vezes.c
----
include::code/estruturas-de-controle/mostrado10vezes.c[]
----
===== Exercício resolvido
*ER 3.3*: Escreva um programa que leia várias notas de alunos de uma turma. O 
programa deve ler notas até que o usuário digite o valor `-1`. Após isso, o 
programa deve mostrar a média dessas notas.
Resposta:
Neste programa não sabemos previamente a quantidade de notas que o usuário 
precisa. Precisamos, nesse caso, utilizar um laço de repetição que fique 
lendo notas até que o valor `-1` seja passado pelo usuário. Desse modo, podemos 
utilizar o comando `while` (linha 7) com a condição de parada `nota != -1`, ou seja,
o usuário seguirá entrando com as notas enquanto os valores digitados forem 
diferentes de `-1`. Dentro do laço, é solicitado que o usuário digite a nota (linha 8).
Na linha 9, o valor digitado pelo usuário é armazenado na variável `nota`.
Para calcular a média das notas, precisamos de 
duas informações: a soma de todas as notas e a quantidade de notas lidas. 
Utilizamos a variável `soma` para armazenar a soma das notas (linha 12) e a
variável `cont` para armazenar a quantidade de notas (linha 13). A média 
das notas será mostrada depois do laço, ou seja, quando o usuário digitar `-1` 
para a nota. Como o cálculo da média precisa da quantidade total das notas, seu
cálculo e o comando para sua exibição devem ser executados após o término do laço (linha 17).
.Código fonte
{gitrepo}/blob/master/livro/capitulos/code/estruturas-de-controle/notas_alunos_c.c[code/estruturas-de-controle/notas_alunos_c.c]
[[notas_alunos_c]]
[source, c, numbered]
.notas_alunos.c
----
include::code/estruturas-de-controle/notas_alunos.c[]
----
////
TODO - REV.22: Sugestão de melhoria para análise pelo autor 
Sugeriria adicionar, pelo menos, mais um exercício resolvido e
comentado.
////
==== Comando do-while
(((do-while)))
Assim como o `while`, o comando `do-while` também é uma estrutura de repetição.
Com semelhanças que vão além dos seus nomes, sobretudo em termos de funcionalidade,
a principal diferença entre eles é que, no caso do `do-while`, o bloco de instruções 
dentro do laço é executado pelo menos uma vez, mesmo que a condição seja 
falsa. Isso acontece porque a condição de parada só é avaliada depois que 
as instruções são executadas. Segue abaixo a estrutura do comando `do-while`.
[source, c]
----
 do {
 instrução 1;
 instrução 2;
 ...
 } while (condição);
----
O comando começa com a palavra `do`, seguida do bloco de instruções a ser 
repetido. Após a execução dessas instruções, a condição é avaliada. 
Caso seja verdadeira, as instruções são executadas novamente, caso 
contrário, o laço se encerra. Para entender melhor, observe o exemplo abaixo. 
Este exemplo faz exatamente o mesmo que o exemplo <<mostrado10vezes>>, porém, utilizando 
o comando `do-while`.
////
FIXME: faz exatamente o mesmo que o exemplo anterior... qual anterior?
////
.Código fonte
{gitrepo}/blob/master/livro/capitulos/code/estruturas-de-controle/do_while.c[code/estruturas-de-controle/do_while.c]
[[do_while_c]]
[source, c, numbered]
.do_while.c
----
include::code/estruturas-de-controle/do_while.c[]
----
==== Comando for
(((for)))
Este comando também serve para criar um laço de repetição e geralmente é 
utilizado quando conhecemos a quantidade de vezes que queremos que as 
instruções sejam repetidas. 
O formato do comando `for` é o seguinte:
[source, c]
----
 for (expressão1; condição; expressão2) {
 instrução1;
 instrução2;
 ...
 }
----
////
TODO - REV.23: Sugestão de melhoria para análise pelo autor 
Sugeriria explicar melhor o que é um incremento e o que é um decremento. 
Normalmente, o aluno tem uma certa dificuldade em entender a primeira vista
esses conceitos.
////
Em `expressão1`, uma variável, geralmente um contador, recebe um valor inicial. 
Essa variável será incrementada ou decrementada de acordo com a expressão 
definida em `expressão2`. O laço ficará executando as instruções 
(`instrução1` e `instrução2`) até que a `condição` seja falsa. 
Vejamos o exemplo abaixo para entender a sequência de operações que são realizadas
durante a execução do comando `for`. O programa <<for_cont>> abaixo tem o mesmo 
resultado de <<do_while_c>> mostrado anteriormente. Inicialmete, uma variável inteira é 
declarada (linha 4). 
Diferentemente do programa <<do_while_c>>, não atribuímos nenhum valor inicial à variável, 
visto que ela será inicializada na primeira expressão do comando `for`. Na linha 6 
existe um comando `for`, cuja primeira expressão é a inicialização da variável `cont`. 
Em seguida, a condição `cont <= 10` é avaliada. Como inicialmente `cont = 0`, 
expressão é avaliada como verdadeira, e a instrução na linha 7 é executada. No fim da 
execução das instruções (nesse caso, especificamente, há apenas uma instrução) contidas 
dentro do `for`, a terceira expressão do `for` 
é avaliada, que nesse caso é um incremento `(cont++)`. Então a variável `cont` 
é incrementada e passa a valer `2`. Em seguida, a condição é verificada 
novamente e, caso seja verdadeira, executa novamente a instrução dentro do 
`for`. Essa sequência de passos é repetida até que a condição seja avaliada como falsa.
.Código fonte
{gitrepo}/blob/master/livro/capitulos/code/estruturas-de-controle/for_cont.c[code/estruturas-de-controle/for_cont.c]
[[for_cont]]
[source, c, numbered]
.for_cont.c
----
include::code/estruturas-de-controle/for_cont.c[]
----
Para entender melhor o funcionamento do comando `for`, vamos ver outro exemplo 
que utiliza decremento (`--`) ao invés do incremento. A ideia é muito parecida com a do 
exemplo anterior, entretanto, ao invés de incremento, temos um 
decremento da variável `cont`. No comando `for`, a variável `cont` é inicializada 
com o valor `10`. Em seguida, a condição `cont > 0` é avaliada. Como o valor de 
`cont` é `10`, a condição é verdadeira, e a instrução dentro do `for` é 
executada (linha 7). Ao fim da execução dessa instrução, a variável `cont` 
é decrementada e passa a valer `9`. Novamente a condição `cont >` 0 é 
verificada e continua sendo verdadeira, o que faz com que a instrução da 
linha 7 seja executada novamente. O laço continua até a variável `cont` 
passar a valer `0`, caso no qual a condição `cont > 0` será falsa.
.Código fonte
{gitrepo}/blob/master/livro/capitulos/code/estruturas-de-controle/for_cont_decremento.c[code/estruturas-de-controle/for_cont_decremento.c]
[source, c, numbered]
.for_cont_decremento.c
----
include::code/estruturas-de-controle/for_cont_decremento.c[]
----
Uma particularidade do comando `for` é que nenhum dos três elementos que o compõe é 
obrigatório, ou seja, podemos omitir qualquer um desses elementos ou até mesmo
uma combinação deles. Contudo, essa é uma prática que deve ser evitada.
==== Laço infinito
(((Laço infinito)))
Quando a condição de parada de uma determinada estrutura de repetição nunca 
é alcançada, as intruções do laço são executadas indefinidamente, e consequentemente
o programa nunca chega ao seu fim. Tal comportamento é algo que deve ser evitado
em programação (na grande maioria das situações) e, por ser um problema tão recorrente,
recebe um nome especial: laço infinito. O exemplo abaixo ilustra esse tipo de laço:
.Código fonte
{gitrepo}/blob/master/livro/capitulos/code/estruturas-de-controle/laco_infinito.c[code/estruturas-de-controle/laco_infinito.c]
[source, c, numbered]
.laco_infinito.c
----
include::code/estruturas-de-controle/laco_infinito.c[]
----
Observe que na linha 6 temos um comando `for` cuja condição de parada não 
foi definida. Consequentemente, o laço entra em loop e a 
execução da instrução na linha 7 é executada indefinidamente.
WARNING: Ao criar uma estrutura de repetição, observe bem a condição de parada 
para verificar se ela realmente será alcançada em algum momento. Sem esse cuidado
você corre
o risco de criar um laço infinito, e seu programa, possivelmente, não 
terá o resultado esperado. 
==== Exercício Resolvido
*E.R 3.4.* Analise o programa abaixo. O objetivo do programa é ler 50 valores e 
mostrar, ao final da leitura, o menor deles. Entretanto, ele possui um problema. 
Identifique e corrija o erro.
.Código fonte
{gitrepo}/blob/master/livro/capitulos/code/estruturas-de-controle/menor_deles.c[code/estruturas-de-controle/menor_deles.c]
[source, c, numbered]
.menor_deles.c
----
include::code/estruturas-de-controle/menor_deles.c[]
----
Resposta:
Vamos analisar o código considerando seu objetivo: ler 50 valores e apresentar 
o menor deles. Vamos iniciar nossa análise na estrutura de repetição `while`, 
na linha 10. A condição é `quantidade < 50`. Logo percebemos que a variável 
`quantidade`, que tem o valor inicial de `1` na sua declaração, não é alterada 
em nenhum momento dentro do laço, o que sugere algum problema. Para o laço 
ter um fim, é necessário que a variável `quantidade` atinja o valor `50` em 
algum momento, e não é isso que está acontecendo. Portanto, temos um laço 
infinito. Para corrigir o problema, devemos incluir uma linha dentro do laço
a fim de incrementar o valor da variável `quantidade`. 
O código abaixo apresenta a solução do problema com a inclusão da linha 12, 
na qual a variável `quantidade` é incrementada. Dessa forma, o laço deixou de ser 
infinito, uma vez que ele atingirá o valor `50` em algum momento, tornando 
falsa a condição `quantidade < 50` do laço.
.Código fonte
{gitrepo}/blob/master/livro/capitulos/code/estruturas-de-controle/menor_deles_resposta.c[code/estruturas-de-controle/menor_deles_resposta.c]
[source, c, numbered]
.menor_deles_resposta.c
----
include::code/estruturas-de-controle/menor_deles_resposta.c[]
----
==== Comandos de desvio
Vimos no último exemplo o que é um laço infinito. Em alguns momentos, 
precisamos utilizar um comando para realizar um desvio dentro do laço de 
repetição. Esses comandos são: `break` e `continue`. Ambos podem ser utilizados 
em qualquer estrutura da repetição. 
===== Comando break
(((break)))
O comando `break` interrompe a execução do laço, fazendo com que as 
instruções dentro do laço após esse comando não sejam executadas. Vamos 
ver o exemplo <<break_interrompe>>. Apesar de não haver condição de parada 
no `for`, ele irá parar quando o comando `break` for executado, ou seja, quando 
o valor da variável `cont` for igual a `10`. Caso houvesse mais alguma outra 
instrução após a linha 8, dentro do bloco de instruções do `for`, ela não seria
executada.
////
TODO - REV.28: Sugestão de melhoria para análise pelo autor 
Sugeriria exemplificar também de forma gráfica ou com animação.
////
.Código fonte
{gitrepo}/blob/master/livro/capitulos/code/estruturas-de-controle/break_interrompe.c[code/estruturas-de-controle/break_interrompe.c]
[[break_interrompe]]
[source, c, numbered]
.break_interrompe.c
----
include::code/estruturas-de-controle/break_interrompe.c[]
----
===== Comando continue
(((continue)))
O comando `continue` faz com que o fluxo de execução "salte" para a avaliação da 
condição de parada do laço, no caso do `while` e `do-while`, e para a expressão 
de incremento e decremento, no caso do comando `for`. Isso significa que as 
instruções após esse comando não são executadas.
Agora vamos analisar o programa <<continue_desvio>> abaixo. Esse programa mostra na tela os 
números ímpares no intervalo de 1 a 20. A variável `cont` é inicializada com 
o valor `1` no `for`. Como a condição é verdadeira, as instruções dentro do 
bloco são executadas. Agora atenção para o comando `if` (linha 7). Na 
condição do `if`, há uma expressão `cont % 2 == 0`, o que significa que se o 
resto da divisão inteira entre a variável `cont` e `2` for `0`, o comando 
`continue` é executado. Entretanto, o resto da divisão será `1`. Nesse caso, a 
a instrução da linha 8 é executada, mostrando o valor `1` na saída.
Em seguida, a expressão de incremento do `for` é 
avaliada, e `cont` passa a valer `2`. Como `cont` ainda é menor ou igual a `20`, as 
instruções do bloco são executadas novamente. Mais uma vez, na linha 6, a 
condição do `if` é avaliada. Todavia, o resto da divisão de `cont` e `2` agora é 
igual a `0`, e então a instrução `continue` é executada. Com sua execução, o fluxo de
volta para o `for`, e a expressão de incremento é avaliada. Note que a instrução da linha 7,
nesse caso, não será mais executada. O valor de `cont` então é incrementado para `3`, 
repetindo o que foi explicado quando `cont` era igual a `1`. 
.Código fonte
{gitrepo}/blob/master/livro/capitulos/code/estruturas-de-controle/continue_desvio.c[code/estruturas-de-controle/continue_desvio.c]
[[continue_desvio]]
[source, c, numbered]
.continue_desvio.c
----
include::code/estruturas-de-controle/continue_desvio.c[]
----
=== Recapitulando
Este capítulo apresentou as estruturas de controle da linguagem C e como 
elas podem ser utilizadas.
A estrutura sequencial significa que o fluxo de execução das instruções 
segue uma linha sequencial, que no caso da linguagem C, é de cima para baixo
e da esquerda para a direita.Entretanto, podemos mudar o fluxo de execução 
desas instruções utilizando as estruturas de decisão e de repetição.
No caso da estrutura de decisão, aprendemos a utilizar os comandos `if`,
`else` e `switch` para executar uma instrução ou um bloco de instruções caso
uma determinada condição seja verdadeira. 
Aprendemos também a construir laços de repetição com os comandos `while`, 
`do-while` e `for`. Vimos que todos esses comandos proporcionam a repetição de 
instruções até que uma determinada condição seja falsa. Diante disso, é 
importante ter bastante atenção na condição de parada dessas estruturas de 
repetição, para não criar um laço infinito.
No próximo capítulo estudaremos os arranjos: uma estrutura de dados que
tem o objetivo de representar um conjunto de valores do mesmo tipo. Vamos também aprender a 
manipular as cadeias de caracteres, também conhecidas como strings.
////
TODO - REV.31: Sugestão de melhoria para análise pelo autor 
De uma maneira geral, acho que o que foi explicado até o momento
não é o suficiente para os alunos sozinhos resolverem os exercícios propostos.
Precisamos ser mais ilustrativos, mais explicativos e didáticos. Apesar de parecer
redundante algumas explicações, o aluno EAD precisa de um material que lhe
dê um maior apoio a aprendizagem.
Não há curiosidades, links para outras informações que poderíamos estar
adicionando aqui para despertar maior interesse do aluno pelo assunto?
////
=== Exercícios Propostos
1. Escreva um programa que verifique se um número digitado pelo usuário é 
menor, igual ou maior que zero.
2. Dado o algoritmo abaixo, explique o que acontece se o valor lido para a 
variável `x` for: `3`, `1` e `0`. Explique o porquê.
+
[source, c]
----
#include <stdio.h>
int main() {
 int x;
 
 scanf(&x);
 if (x) printf("verdadeiro");
 
 return 0;
}
----
3. Escreva um programa que informe se um dado ano é ou não bissexto. Obs.: um 
ano é bissexto se ele for divisível por 400 ou se ele for divisível por 4 e 
não por 100.
4. Escreva um programa que mostre todos os números pares no intervalo de 1 a 
40 de forma decrescente, utilizando o comando `while`. Depois faça o mesmo, mas 
desta vez, utilizando o comando `for`.
5. Um determinado banco abriu uma linha de crédito para os funcionários 
públicos. Porém, o valor máximo da prestação não poderá ultrapassar 30% 
do salário deste funcionário. Faça um programa para ajudar este banco. O 
programa deve permitir o usuário entrar com o salário do funcionário e o 
valor da prestação e informar se o empréstimo pode ou não ser concedido.
6. Escreva um programa que leia o mês do ano em valor numérico e exiba este 
mês por extenso (utilize o comando `switch`).
7. Faça três
programas que mostrem de 1 a 10 na tela, utilizando, em cada um, 
uma estrutura de laço de repetição diferente. 
8. Escreva um programa que mostre na tela os números múltiplos de 3 no 
intervalo de 2 a 100.
9. Escreva um programa para ler dois números inteiros M e N e, a seguir, 
imprimir os números pares existentes no intervalo [M, N]. 
10. A organização de um evento esportivo deseja um programa que faça a 
leitura do nome e a pontuação de cada um dos 10 participantes e exiba o nome 
do vencedor. Elabore este programa.
11. O supermercado Excelente Preço está precisando ser informatizado. Neste 
sentido, o dono quer um programa que leia os preços dos produtos até que seja 
informado o valor zero. No final o programa deve informar o total da compra e 
perguntar a forma de pagamento. As opções da forma de pagamento são: 1) A 
vista; 2) No cartão de crédito. Se a opção escolhida for a vista, então o 
programa informa o valor da compra com um desconto de 5%. Caso a compra seja no 
cartão de crédito, o programa informa o valor da compra dividido em 4 vezes.
// Sempre termine os arquivos com uma linha em branco.
introducao-a-programacao-livro-1.0.0/livro/capitulos/funcoes.asc
== Funções
.Objetivos do capítulo
____________________
Ao final deste capítulo você deverá ser capaz de:
* Criar e usar funções e procedimentos em C
* Identificar quando escrever uma função ou um procedimento
* Entender as regras de escopo para variáveis em C
* Entender os diferentes tipos de passagem de parâmetro e quando utilizá-los
* Trabalhar com funções recursivas
____________________
Quando elaboramos um algoritmo para resolver um problema, e quando 
escrevemos um programa para implementar este algoritmo, muitas vezes 
identificamos uma parte do algoritmo que deve ser realizada várias 
vezes para chegar ao resultado. Ou, ao trabalhar com vários algoritmos 
diferentes, identificamos algumas partes em comum entre eles. Nestes 
casos, é uma boa ideia isolar essas partes que se repetem, de maneira 
que elas possam ser realizadas sem repetir o mesmo código várias vezes. 
Esse objetivo pode ser atingido com o uso de *funções* e *procedimentos*.
Neste capítulo, vamos estudar as funções e procedimentos como uma forma 
de reaproveitar o código de tarefas que se repetem em um programa. Funções 
são importantes para a modularização de um programa, ou seja, para dividir
o programa em partes menores, cada parte com uma função específica; sem 
funções ou procedimentos, um programa maior e mais complicado ficaria 
organizado em uma única parte que faz tudo e é mais difícil de entender. 
Neste capítulo, vamos entender quando utilizar as funções ou procedimentos 
para melhor dividir o código dos nossos programas. 
[IMPORTANT]
====
Neste capítulo, vamos *descartar a utilização de pseudocódigo*. Agora que você já
possui um conhecimento básico sobre a linguagem C e, provavelmente, escreveu alguns
programas nela, consideramos que não haverá mais necessidade de 
apresentar sintaxes para pseudocódigos. Portanto, deste capítulo em diante, o conteúdo 
apresentadao utilizará somente a sintaxe da linguagem C.
====
=== O que são funções?
((Funções)) e ((procedimentos)) podem ser compreendidos como trechos reutilizáveis 
de código. Uma função ou procedimento pode, então, ser utilizado várias 
vezes por um mesmo programa. Isso simplifica a criação de programas maiores, 
dividindo-os em unidades menores que trabalham em conjunto. Funções e procedimentos 
são bastante semelhantes e, posteriormente, vamos entender as diferenças entre eles.
[NOTE]
.Revisão
====
Lembre-se que durante o curso você já utilizou funções diversas vezes,
o que nós sabemos sobre funções até agora?
* Uma função implementa um comportamento que pode ser reutilizado;
* Para executar uma função, utilizamos o nome da função e passamos alguns 
parâmetros entre parênteses e separados por vírgula. Exemplo: `printf("R$ %1.2f", preco)`;
* A função `printf` é utilizada para imprimir texto na saída;
* As funções `scanf` e `getchar` para ler dados da entrada;
* As funções `strlen`, `strcpy`, `strcat` e `strchr` são utilizadas para 
manipular strings;
* As ((funções)) são agrupadas em ((módulos)). Exemplo: `stdio`;
====
Quando realizamos um processo com um determinado objetivo, é comum 
identificarmos partes que se repetem. Quando se trata de processos 
no mundo físico, muitas vezes criamos máquinas que ajudam a realizar 
as partes que se repetem. 
Por exemplo, pense no processo de limpar 
as roupas que usamos para podermos usá-las novamente. Este processo 
envolve lavar as roupas com água e sabão, secar as roupas lavadas e, 
finalmente, passar as roupas para evitar que fiquem amassadas. Para 
reduzir a quantidade de trabalho necessária para realizar esse processo,
foi inventada uma máquina de lavar, que realiza a lavagem das roupas. 
Uma pessoa que tem uma máquina de lavar pode usá-la repetidamente e, 
sempre que precisa de roupas limpas, precisa apenas se encarregar de 
enxugar e passar as roupas; a lavagem fica por conta da máquina. 
Dizemos inclusive que a *função* da máquina é lavar as roupas. 
As funções e os procedimentos funcionam desta forma, capturando 
partes menores de um algoritmo que podem ser utilizadas por 
outros algoritmos, economizando o trabalho de sempre refazer
uma determinada tarefa. 
==== Um exemplo
Vejamos um exemplo. Queremos criar um programa que calcule a média
final de um aluno em uma disciplina com três provas; o programa 
deve pedir ao usuário que entre com as notas das três provas, 
calcular a média aritmética das três notas e apresentar o resultado. 
O programador que resolveu o problema decidiu imprimir um separador 
na tela entre cada entrada de dados e o resultado final, desta forma,
produzindo o seguinte código: 
.Código fonte
{gitrepo}/blob/master/livro/capitulos/code/funcoes/media_sem_proc.c[code/funcoes/media_sem_proc.c]
[source, c]
.Cálculo da média de um aluno em uma disciplina
----
include::code/funcoes/media_sem_proc.c[]
----
<1> Código que imprime um separador na tela. 
.Resultado da execução do programa
....
include::code/funcoes/media_sem_proc.out[]
....
É fácil de notar que o código usado para imprimir um separador se repete três 
vezes no programa. Podemos melhorar esse programa utilizando um procedimento 
que terá a tarefa de imprimir o separador. Isso teria o seguinte resultado:
.Código fonte
{gitrepo}/blob/master/livro/capitulos/code/funcoes/media_proc.c[code/funcoes/media_proc.c]
[source, c]
.Cálculo da média usando procedimento
----
include::code/funcoes/media_proc.c[]
----
<1> Definição do procedimento `imprime_separador`.
<2> Código no *corpo* do procedimento. 
<3> *Chamada* do procedimento `imprime_separador`.
A linha `void imprime_separador()` inicia a definição do procedimento 
chamado `imprime_separador`; o *corpo* do procedimento é o conjunto 
de comandos entre chaves que vem logo após o nome do procedimento. 
Os parênteses e a palavra `void` no início serão explicados depois. 
Dizemos que o uso de um procedimento é uma *chamada* ao mesmo. No 
exemplo anterior, o código do programa chama `imprime_separador` 
três vezes. 
É importante notar que além de economizar a repetição de linhas 
de código, o programa usando o procedimento `imprime_separador` também 
é mais fácil de entender porque transmite melhor as partes que 
compõem o programa. A melhor modularização do código do programa é
um motivo extremamente importante para usar funções e procedimentos, 
principalmente à medida que os programas se tornam maiores e 
mais complexos. 
=== Parâmetros
O exemplo usando `imprime_separador` é o caso mais simples, 
mas menos interessante do uso de procedimentos e funções, 
quando o código a ser reutilizado é sempre o mesmo. Na maioria 
das situações de interesse, queremos utilizar uma função ou 
procedimento em situações com algumas
diferenças. Para tornar 
um procedimento (ou função) mais flexível, é preciso que 
informações sejam passadas para o procedimento. Isso é 
feito com o uso de *parâmetros*.
Já vimos muitas vezes o uso de procedimentos com parâmetros. 
Por exemplo, `printf` é um procedimento da biblioteca padrão 
da linguagem C que imprime a _string_ passada como parâmetro. 
Assim, 
 printf("ola, mundo!");
é uma chamada ao procedimento `printf` com parâmetro `"ola, mundo!"`. 
Como exemplo do uso de parâmetros em um procedimento, voltemos ao 
exemplo do cálculo das médias. Vamos utilizar o separador para 
fazer uma visualização simples das notas e da média, imprimindo 
uma barra de tamanho proporcional a cada valor. 
.Código fonte
{gitrepo}/blob/master/livro/capitulos/code/funcoes/media_param.c[code/funcoes/media_param.c]
[source, c]
.Uso de um procedimento com parâmetro
----
include::code/funcoes/media_param.c[]
----
<1> Definição do procedimento `imprime_separador`, com o parâmetro `nota`, do tipo `float`.
<2> Chamada do procedimento `imprime_separador`, passando o argumento `nota1`.
.Resultado da execução do programa code/funcoes/media_param.c
....
include::code/funcoes/media_param.out[]
....
Como se pode ver no resultado da execução do programa, o novo procedimento
`imprime_separador` imprime uma barra de tamanho proporcional à nota passada 
como argumento (são 5 caracteres `=` para cada ponto da nota). Note a 
diferença de nomenclatura: o procedimento `imprime_separador` é definido 
com um *((parâmetro))* de nome `nota`, mas é chamado com um *((argumento))*, 
o valor que é comunicado ao procedimento. No exemplo acima, `imprime_separador`
é chamado com os argumentos `nota`, `nota2`, `nota3` e `media`. É necessário 
especificar o tipo de cada parâmetro que deve ser passado para o procedimento; 
no caso, o parâmetro `nota` do procedimento `imprime_separador` é do tipo 
`float`. 
Na chamada de um procedimento com um parâmetro, o controle do programa 
executa o código do procedimento, atribuindo o valor passado como argumento 
à variável `nota` dentro do procedimento `imprime_separador`. Ou seja, o 
seguinte código 
[source, c]
----
int main() {
	float nota1; 
	printf("Entre a nota da primeira prova: ");
	scanf("%f", &nota1);
	imprime_separador(nota1);
	// resto do programa ...
}
----
funciona como se fosse o seguinte (utilizando o procedimento):
[source, c]
----
int main() {
	float nota1; 
	printf("Entre a nota da primeira prova: ");
	scanf("%f", &nota1);
	float nota = nota1; // <1>
	int i; // <2>
	printf("\n");
	for (i = 0; i < (int) lround(nota * 5.0); i++) {
		printf("=");
	}
	printf(" %3.2f / 10.0\n", nota);
	printf("\n");
	// resto do programa ...
}
----
<1> Atribuição do valor do argumento `nota1` para o parâmetro `nota`.
<2> Resto do corpo do procedimento `imprime_separador`. 
Este exemplo é apenas uma ilustração; na prática, o chamado do procedimento 
não funciona exatamente desta forma. Em particular, a variável `nota`, que 
designa o parâmetro do procedimento, só existe enquanto o procedimento 
executa. Isso será detalhado mais tarde. 
O uso de parâmetros nos procedimentos os tornam muito mais flexíveis para 
uso em diferentes situações. Mas assim como é útil que o código que chama 
o procedimento comunique informações para o procedimento chamado, muitas 
vezes também é útil que o procedimento comunique algo de volta para o 
código que o chamou; neste caso, passamos dos procedimentos para as funções. 
=== Retorno de Valores com Funções
Até agora só temos usado procedimentos como ferramenta de modularização do 
código, mas muitas vezes é útil chamar um procedimento que retorna alguma 
informação de volta para o código que o chamou. Esta é a diferença entre 
procedimentos e funções: as funções retornam algum valor. Desta forma, as 
funções em linguagem C são similares às funções da matemática: uma função 
como 
[latexmath]
+++++
\[
f: \mathbb{Z} \rightarrow \mathbb{Z},\quad f(x) = x^2 + 2
\]
+++++
tem um parâmetro x (um inteiro), e retorna um determinado valor que depende do
parâmetro passado; por exemplo, 
[latexmath]
+++++
\[
f(5) = 5^2 + 2 = 27
\]
+++++
É fácil escrever a mesma função em linguagem C:
[source, c]
----
int f(int x) { // <1>
	return x * x + 2; // <2>
}
----
<1> Definição da função `f`. A definição começa com `int f(...)`, significando 
que o tipo de retorno da função é `int`.
<2> A palavra-chave `return` determina o valor de retorno da função `f`, que será 
o resultado da expressão `x * x + 2`.
A função `f` do exemplo faz o mesmo que a versão matemática: dado o valor do parâmetro 
`x`, retorna um valor que é igual a `x` ao quadrado, somado a dois. Note que é preciso 
especificar o tipo do valor que é retornado pela função e, por isso, toda função começa 
com o tipo de retorno antes do nome. Especificar os tipos dos parâmetros e o tipo do 
valor de retorno também é similar às funções na matemática, para as quais devemos 
especificar os conjuntos domínio e contra-domínio. 
==== Funções, Procedimentos e o Tipo `void`
Neste ponto pode surgir uma pergunta: se é preciso especificar o tipo do valor 
retornado por uma função antes do nome da função (por exemplo `int f(...)`), 
por que nos procedimentos usa-se a palavra-chave `void`? 
A verdade é que, embora algumas linguagens de programação façam uma distinção 
entre procedimentos e funções, na linguagem C existem apenas funções. Como a 
diferença entre procedimentos e funções é apenas o fato de retornar ou não 
um valor, os procedimentos em C são considerados funções que retornam um valor 
_vazio_. É isso que significa o `void` no início da definição de um procedimento 
como `imprime_separador`, que vimos anteriormente; a rigor, `imprime_separador` 
é uma função, mas retorna um valor _vazio_, ou seja, nenhum valor. O tipo `void` 
na linguagem C é um tipo especial que denota a ausência de valores. 
Como procedimentos em C são funções, também é possível usar `return` em 
procedimentos, mas apenas para terminar sua execução e retornar 
imediatamente. Isso às vezes é útil para terminar um procedimento em pontos 
diferentes do seu final. Também pode-se utilizar `return` ao final do 
procedimento, mas este uso é supérfluo e não é recomendado. 
O seguinte exemplo demonstra o uso do `return` em procedimentos. Continuando 
no tema relacionado ao cálculo de médias, queremos detectar se uma das notas 
entradas pelo usuário é uma nota inválida antes de fazer o cálculo da média. 
Neste caso, o programa deve apenas imprimir se algum valor negativo foi 
entrado pelo usuário. O procedimento `possui_negativo` será responsável por 
imprimir uma mensagem caso um dos valores seja negativo. 
.Código fonte
{gitrepo}/blob/master/livro/capitulos/code/funcoes/retorno_proc.c[code/funcoes/retorno_proc.c]
[source, c]
.Uso de `return` em um procedimento
----
include::code/funcoes/retorno_proc.c[]
----
<1> Uso do `return` para sair prematuramente do procedimento. 
<2> Este comando de impressão será executado se nenhuma das 
condições testadas em `possui_negativo` for verdade, ou seja, 
se nenhum dos valores dos parâmetros for negativo. 
.Resultado de duas execuções do programa code/funcoes/retorno_proc.c
....
include::code/funcoes/retorno_proc.out[]
....
O procedimento `possui_negativo` deve verificar se um dos três números passados 
como argumentos, mas basta achar um número entre eles para que o resultado possa 
ser impresso imediatamente e o procedimento pode retornar; por isso, usamos 
`return` assim que o primeiro valor negativo é encontrado. 
Esse exemplo ainda tem um problema: como pode ser visto nos exemplos de execução, 
mesmo que o usuário entre um valor negativo, a média aritmética das três notas 
ainda é impressa na tela (o usuário apenas é avisado que um dos valores foi negativo).
Isso é uma indicação
que seria melhor que `possui_negativo` fosse uma função, e que o 
programa principal verificasse o valor retornado e tomasse uma decisão. Se fizermos 
essas alterações ficamos com o seguinte programa:
.Código fonte
{gitrepo}/blob/master/livro/capitulos/code/funcoes/retorno_func.c[code/funcoes/retorno_func.c]
[source, c]
.Reescrevendo o exemplo anterior para usar uma função
----
include::code/funcoes/retorno_func.c[]
----
<1> A função `possui_negativo` agora retorna um inteiro de valor 1 caso um dos 
valores dos parâmetros seja negativo, e 0 caso contrário (todos são positivos).
<2> Teste para identificar se um ou mais dos parâmetros informados são negativos.
<3> A função retorna `1` se um dos números passados para a função for negativo. 
<4> Caso nenhum dos números seja negativo, o controle passa para o comando `return`
ao final da função e o valor `0` é retornado para indicar que nenhum número negativo 
foi encontrado. 
<5> O programa principal verifica o valor de retorno da função `possui_negativo` e
imprime informações adequadas na tela para cada caso. 
.Resultado de duas execuções do programa code/funcoes/retorno_func.c
....
include::code/funcoes/retorno_func.out[]
....
Como pode-se ver nos dois exemplos de execução do programa, a saída agora é mais 
adequada. Caso uma das notas informadas seja negativa, o programa não imprime um 
valor de média, apenas avisando o usuário do erro na entrada de dados. O código 
da função `possui_negativo` também foi simplificado pelo uso do operador lógico 
OU. 
Como funções e procedimentos são tratados de maneira uniforme na linguagem C 
(e em muitas outras linguagens atuais), a partir de agora vamos usar o termo 
*função* tanto para funções como para procedimentos. Isso não deve gerar nenhuma 
confusão. Em caso de dúvida, basta olhar para a definição da função no código-fonte 
do programa; se a função for declarada com o tipo de retorno `void`, então é um 
procedimento. 
=== Um Exemplo Matemático: Equação de Segundo Grau
Nesta seção, veremos mais um exemplo do uso de funções em um programa 
para calcular as raízes de uma equação de segundo grau. Neste exemplo, 
as funções não serão utilizadas várias vezes, mas o programa principal 
será mais claro e mais fácil de entender graças à melhor modularização 
conseguida com o uso das funções. 
Lembremos que um _polinômio de segundo grau_ é uma soma de três termos 
em potências de uma variável, por exemplo
[latexmath]
++++
\[
 P(x) = ax^2 + bx + c
\]
++++
onde latexmath:[$a$], latexmath:[$b$] e latexmath:[$c$] são coeficientes 
constantes. Uma _equação de segundo grau_ é formada ao igualar um polinômio 
de segundo grau a zero, ou seja
[latexmath]
++++
\[
 ax^2 + bx + c = 0
\]
++++
Sabemos que uma equação de segundo grau pode ter até duas *raízes* reais; cada 
raiz é um valor da variável latexmath:[$x$] que satisfaz a equação. Essas raízes 
podem ser encontradas pela chamada _fórmula de Bhaskara_. A fórmula consiste 
em calcular um valor auxiliar chamado de latexmath:[$\Delta$] (_delta_), e 
usar o valor calculado para identificar quantas raízes reais distintas podem 
ser encontradas para a equação: 
* se latexmath:[$\Delta < 0$], a equação não tem raízes reais;
* se latexmath:[$\Delta = 0$], a equação possui uma raiz real;
* se latexmath:[$\Delta > 0$], a equação possui duas raízes reais distintas. 
A fórmula para calcular latexmath:[$\Delta$] é
[latexmath]
++++
\[
 \Delta = b^2 - 4 a c
\]
++++
No caso latexmath:[$\Delta >= 0$], as raízes da equação são dadas por
[latexmath]
++++
\[
 x = \frac{-b \pm \sqrt{\Delta}}{2a}
\]
++++
uma das raízes sendo obtida pelo uso do sinal positivo em 
latexmath:[$-b \pm \sqrt{\Delta}$], enquanto que a outra raiz é calculada pelo 
uso do sinal negativo. Se [$\Delta = 0$], ambos os valores serão iguais. 
Como exemplo do uso da fórmula de Bhaskara, considere a equação:
[latexmath]
++++
\[
x^2 - 5x + 6 = 0
\]
++++
Nesta equação os coeficientes são latexmath:[$a=1, b=-5$] e latexmath:[$c=6$]. 
Calculamos o latexmath:[$\Delta$] usando os valores dos coeficientes:
[latexmath]
++++
\[
\Delta = b^2 - 4ac = (-5)^2 - 4 \times 1 \times 6 = 25 - 24 = 1
\]
++++
E assim, podemos calcular as raízes:
[latexmath]
++++
\[
 x = \frac{-b \pm \sqrt{\Delta}}{2a} = \frac{5 \pm \sqrt{1}}{2} = \frac{5 \pm 1}{2}
\]
++++
Ou seja, as raízes são latexmath:[$6/2 = 3$] e latexmath:[$4/2 = 2$]. 
Agora vamos escrever um programa que resolve equações do segundo grau, usando o 
processo mostrado acima. 
.Código fonte
{gitrepo}/blob/master/livro/capitulos/code/funcoes/equacao.c[code/funcoes/equacao.c]
[source, c]
.Cálculo de raízes de uma equação de segundo grau
----
include::code/funcoes/equacao.c[]
----
<1> Função que calcula o valor do latexmath:[$\Delta$].
<2> Função que calcula a raiz positiva da equação. 
<3> Função que calcula a raiz negativa da equação. 
.Resultado de três execuções do programa code/funcoes/equacao.c
....
include::code/funcoes/equacao.out[]
....
Podemos ver neste exemplo funções para calcular o valor do latexmath:[$\Delta$] e 
das duas raízes da equação. O programa obtém o valor do latexmath:[$\Delta$] e 
verifica se a equação tem nenhuma, uma ou duas raízes, e imprime o resultado 
de acordo com isso. Embora cada função seja usada apenas uma vez, o programa 
principal é mais claro e mais fácil de entender porque cada função faz uma 
parte do processo necessário, ao invés de ter todo o código junto na função `main`. 
Funções são importantes não só para reutilizar código e diminuir esforço de 
programação, mas também para melhorar a modularização do programa e torná-lo mais 
fácil de ser lido. Em situações práticas, muitas vezes é necessário ler um código 
que já foi produzido antes e entendê-lo, seja para consertar defeitos encontrados 
ou para extender suas funcionalidades. Tornar um programa mais legível auxilia e 
reduz o custo relacionado à _manutenção_ do mesmo. 
Entretanto, este último exemplo pode parecer estranho do ponto de vista da 
modularização, já que duas de suas funções são quase idênticas. As funções que 
calculam o valor das raízes, `raiz_positiva` e `raiz_negativa`, mudam apenas em 
uma operação. Podemos pensar em como reescrever o programa para usar apenas uma 
função ao invés de duas funções quase idênticas. A repetição desnecessária 
de código pode ser um problema para a manutenção de um programa. 
A chave para criar uma só função que calcula os dois valores é criar um novo 
parâmetro que indica qual das duas raízes deve ser calculada. Vamos usar um 
parâmetro chamado `sinal` que indica, pelo seu valor, se será usada uma soma ou 
subtração no cálculo da raiz. Se `sinal` for 1, será usada uma soma, e se for 
`-1` será usada uma subtração. O código resultante é mais compacto e evita 
repetições:
.Código fonte
{gitrepo}/blob/master/livro/capitulos/code/funcoes/equacao2.c[code/funcoes/equacao2.c]
[source, c]
.Cálculo de raízes de uma equação de segundo grau
----
include::code/funcoes/equacao2.c[]
----
É comum quando escrevemos programas nos concentrarmos, inicialmente, em fazê-lo 
funcionar, ou seja, resolver o problema desejado. Entretanto, é importante 
depois reler o código escrito e revisá-lo para torná-lo mais claro, mais 
legível e mais fácil de manter. Esse processo de revisar o código de um programa
sem mudar sua funcionalidade é muito importante na programação de computadores, 
e normalmente recebe o nome de *refatoração*. 
=== Escopo de Variáveis 
Quando trabalhamos com programas compostos por várias funções, nos deparamos com 
questões relativas à _visibilidade_ das variáveis em diferentes partes do programa. 
Ou seja, se uma variável é visível ou acessível em certas partes de um programa. 
Um programador iniciante poderia escrever o seguinte programa para calcular a 
média aritmética de três notas:
.Código fonte
{gitrepo}/blob/master/livro/capitulos/code/funcoes/media_erro.c[code/funcoes/media_erro.c]
[source, c]
.Cálculo da média usando código incorreto
----
include::code/funcoes/media_erro.c[]
----
<1> Esta linha contém erros e o programa não será compilado. 
O raciocínio do programador é "se as variáveis `nota1`, `nota2` e `nota3` existem na 
função `main` e a função `calc_media` é chamada dentro de `main`, as variáveis 
`nota1`, `nota2` e `nota3` não deveriam ser visíveis dentro de `calc_media` ?"
Acontece que isso não é válido na linguagem C, e qualquer compilador da linguagem 
vai acusar erros de compilação neste programa, avisando que as variáveis `nota1`, 
`nota2` e `nota3` não foram declaradas. 
Para entender como funciona a visibilidade das variáveis em um programa na linguagem 
C, precisamos falar sobre as regras de *escopo* desta linguagem. O ((escopo)) de 
uma variável é a parte do programa na qual ela é visível e pode ser acessada. 
A linguagem C usa um conjunto de regras de escopo que recebe o nome de _escopo estático_ 
ou _escopo léxico_. Essas regras são bastante simples de entender e aplicar, 
como veremos a seguir. 
Em programas na linguagem C existem dois tipos de escopo (regiões de visibilidade):
* escopo global;
* escopos locais. 
Existe apenas um escopo global e, como indicado pelo seu nome, ele contém elementos 
que são visíveis em todo o programa. Já os escopos locais são vários e particulares: 
basicamente, cada função define um escopo local que corresponde com o _corpo_ da 
função. 
Desta forma, variáveis declaradas no escopo global (ou seja, "fora" de qualquer 
função) são visíveis em todo programa, enquanto variáveis declaradas dentro de 
uma função são visíveis apenas dentro da mesma função. No exemplo anterior, as 
variáveis `nota1`, `nota2` e `nota3` são visíveis apenas dentro da função `main`, 
e por isso não podem ser acessadas dentro da função `calc_media`. 
Isso pode ser resolvido mudando as variáveis `nota1`, `nota2` e `nota3` para 
o escopo global, ou seja, tornando-as _variáveis globais_, como no seguinte 
programa:
.Código fonte
{gitrepo}/blob/master/livro/capitulos/code/funcoes/media_globais.c[code/funcoes/media_globais.c]
[source, c]
.Cálculo de raízes de uma equação de segundo grau
----
include::code/funcoes/media_globais.c[]
----
<1> Declaração das variáveis `nota1`, `nota2` e `nota3` como variáveis globais. 
Note que elas estão declaradas "fora" de qualquer função. 
<2> Código dentro de `calc_media` que usa as variáveis globais. Neste programa, 
as variáveis estão visíveis e não ocorrerá um erro durante a compilação. 
<3> Código dentro de `main` que usa as variáveis globais. Variáveis globais 
são visíveis em todo o programa, incluindo na função principal. 
Este programa agora compila corretamente e funciona para o cálculo da média. 
Mas é importante observar que esse tipo de prática _não é recomendada_. 
Entre as boas práticas da programação está a sugestão de usar variáveis 
globais apenas quando absolutamente necessário. Como variáveis globais 
podem ser acessadas e ter seu valor alterado por qualquer parte do 
programa, fica difícil saber que partes podem influenciar ou serem 
influenciadas pelas variáveis globais, o que torna todo o programa 
mais difícil de entender. Para o exemplo das notas, é melhor e mais 
de acordo com boas práticas de programação comunicar as notas para 
a função `calc_media` usando parâmtros, como segue: 
.Código fonte
{gitrepo}/blob/master/livro/capitulos/code/funcoes/media_param2.c[code/funcoes/media_param2.c]
[source, c]
.Cálculo de raízes de uma equação de segundo grau
----
include::code/funcoes/media_param2.c[]
----
Este código funciona corretamente e evita o uso desnecessário de 
variáveis globais. 
==== Escopo dos Parâmetros
Uma pergunta que pode surgir (especialmente após o exemplo anterior) 
é "qual o escopo dos parâmetros das funções?" A resposta é simples: 
para questões de visibilidade, o escopo dos parâmetros das funções é 
o escopo local da função da qual eles pertencem. Ou seja, os parâmetros 
de uma função funcionam exatamente como variáveis locais declaradas 
dentro da função. 
==== Sombreamento e Sobreposição de Escopos
O que acontece se duas variáveis tiverem o mesmo nome em um só 
programa? A resposta depende de onde as variáveis em questão 
são declaradas. 
Não podem existir duas variáveis de mesmo nome em um mesmo escopo; 
um programa que tente declarar duas variáveis de mesmo nome no mesmo 
escopo ocasionará um erro quando for compilado. Assim, não podem 
existir duas variáveis globais de nome `x` ou duas variáveis de nome 
`y` em uma mesma função. 
Em escopos diferentes a regra muda: variáveis de mesmo nome podem 
existir em um programa se forem declarados em escopos distintos. 
Isso é bastante útil: imagine um programa com 20 ou 30 mil linhas 
de código (o que hoje em dia é considerado um programa de _pequeno_ 
a _médio_ porte); um programa deste tamanho precisa usar um grande 
número de variáveis, se cada uma delas precisasse ter um nome 
diferente de todas as outras, seria muito difícil dar nomes a vários
milhares de variáveis. Imagine que um programa deste tamanho pode 
ter mais de mil laços `for`, cada um com uma variável de controle, e 
cada uma dessas variáveis teria que ter um nome diferente. Por isso, 
as regras de escopo também são úteis para estabelecer espaços locais
onde os nomes não entram em conflitos com os nomes de outros 
escopos locais. 
Quando temos duas variáveis de mesmo nome em diferentes escopos locais, 
ou seja, duas funções diferentes, o resultado é 
simples, já que essas variáveis de mesmo nome nunca seriam visíveis 
no mesmo local do programa. Mas e se tivermos duas variáveis de mesmo 
nome, sendo uma variável local e uma global? Neste caso, dentro da 
função que declara a variável com mesmo nome da global, existirão 
duas variáveis que poderiam ser visíveis com o mesmo nome. O que 
acontece nesses casos é chamado de *sombreamento*: a variável do 
escopo local _esconde_ a variável do escopo global. Vamos ilustrar 
essa regra com um exemplo: 
.Código fonte
{gitrepo}/blob/master/livro/capitulos/code/funcoes/sombra.c[code/funcoes/sombra.c]
[source, c]
.Exemplo de sombreamento de variáveis globais
----
include::code/funcoes/sombra.c[]
----
<1> Declaração da variável global `x`.
<2> Declaração da variável local `x` na função `f`.
<3> Declaração da variável local `y` na função `f`.
<4> Declaração da variável local `y` na função `g`.
Vemos no exemplo que existe uma variável global chamada `x` e uma 
variável local `x` na função `f`. A função `f` também tem 
uma variável local chamada `y`, e há uma variável local de mesmo 
nome na função `g`. As variáveis chamadas `y` em `f` e `g` não 
interferem, pois são escopos totalmente diferentes. 
Já as variáveis chamadas `x` interferem, já que uma está no escopo 
global e outra está no escopo local da função `f`. A questão é: o que 
é impresso pelo programa? Isso depende dos valores de `x` dentro da 
função `f` e na função `g` (que usa `x` para calcular o valor de `y`, que 
é retornado). A execução do programa imprime o seguinte:
.Resultado da execução do programa code/funcoes/sombra.c
....
include::code/funcoes/sombra.out[]
....
A primeira linha é o que é impresso na função `f`. Como existe uma 
variável local `x` declarada em `f`, dentro da função `f` a variável 
`x` tem o valor 60, como declarado; o valor de `y` calculado em 
`f` é, então, latexmath:[$60 \times 60 = 3600$]. Já na função `g` 
não existe uma variável `x` local, então o valor de `x` dentro de `g` 
é o valor da variável global `x`, que é igual a 5; desta forma, `y` em 
`g` tem valor latexmath:[$5 \times 5 = 25$]. Isso explica a saída do 
programa como visto acima. 
[NOTE]
====
Uma consequência da regra de sombreamento é que dentro de funções que 
tenham variáveis locais que escondem variáveis globais de mesmo nome, 
é impossível acessar ou utilizar as variáveis globais escondidas.
No 
exemplo anterior, dentro da função `f` é impossível ter acesso à 
variável global `x`. 
====
=== Passagem de Parâmetros 
Com o que vimos até agora sobre parâmetros de funções, eles funcionam 
de maneira simples: o código que chama uma função especifica expressões 
para cada um dos argumentos da função. Os valores de cada expressão são 
calculados e transmitidos como o valor dos parâmetros declarados na 
função. 
Entretanto, isso não é suficiente para todos os casos em que podemos 
querer usar parâmetros. Por exemplo, digamos que temos uma situação 
em que é necessário trocar o valor de duas variáveis, e que isso é 
necessário várias vezes ao longo do programa. Para evitar repetição, 
a melhor solução é escrever uma função que realiza a troca do valor 
de duas variáveis. O exemplo a seguir mostra o que acontece quando 
tentamos fazer isso apenas com o que vimos até agora: 
.Código fonte
{gitrepo}/blob/master/livro/capitulos/code/funcoes/troca.c[code/funcoes/troca.c]
[source, c]
.Tentativa de trocar o valor de duas variáveis usando uma função
----
include::code/funcoes/troca.c[]
----
.Resultado da execução do programa code/funcoes/troca.c
....
include::code/funcoes/troca.out[]
....
Como se vê no resultado da execução do programa, embora as variáveis 
`a` e `b` realmente troquem de valor dentro da função `troca_variaveis`, 
isso não afeta o valor das variáveis `x` e `y` em `main`. Isso acontece 
porque, normalmente, os parâmetros em C são passados *por valor*, ou seja, 
apenas o valor de `x` e `y` são copiados para `a` e `b`. Precisamos que 
as variáveis na função `troca_variaveis`, de alguma maneira, afetem as variáveis 
que foram usadas como parâmetro, e para isso é necessário usar o modo de 
passagem de parâmetros chamado de passagem *por referência*. A seguir, vamos 
ver em maiores detalhes como funcionam esses dois modos de passagem de 
parâmetros. 
==== Passagem Por Valor
A passagem de parâmetros por valor é a situação padrão na linguagem C. 
Este modo de passagem de parâmetros comunica apenas valores entre 
o código chamador e a função chamada. 
A passagem por valor funciona da seguinte forma: para uma função `f` 
com N parâmetros, uma chamada de `f` deve conter N expressões como 
argumentos (se o número de argumentos não corresponder ao número 
de parâmetros declarados, o compilador acusará um erro no programa). 
Então o seguinte processo de chamada de função acontece:
1. O valor de cada uma das N expressões usadas como argumento é calculado
e guardado;
2. N variáveis locais são criadas para a função chamada, uma para cada 
parâmetro da função, e usando o nome declarado na função; 
3. Os valores calculados no passo 1 são atribuídos às variáveis criadas 
no passo 2. 
4. O corpo da função `f` é executado. 
Como as variáveis criadas para os parâmetros são locais, elas deixam 
de existir quando a função chamada termina, e isso não tem nenhum efeito 
nas expressões que foram usadas para atribuir valor aos parâmetros ao início 
da função. Isso significa que o programa para troca de valor de variáveis 
mostrado acima funciona de maneira similar ao seguinte programa (no qual 
colocamos o código da função `troca_variaveis` diretamente na função `main`):
.Código fonte
{gitrepo}/blob/master/livro/capitulos/code/funcoes/troca_main.c[code/funcoes/troca_main.c]
[source, c]
.Tentativa de trocar o valor de duas variáveis usando uma função
----
include::code/funcoes/troca_main.c[]
----
Neste caso, fica claro que as variáveis `x` e `y` são usadas apenas para obter
o valor inicial das variáveis `a` e `b`, e portanto a mudança de valor das 
duas últimas não deve afetar `x` e `y`. 
A passagem de parâmetros por valor é simples e funciona bem na maioria dos 
casos. Mas em algumas situações pode ser desejável ter uma forma de afetar 
variáveis externas à uma determinada função e, para isso, usa-se a passagem de 
parâmetros por referência. 
==== Passagem Por Referência
A passagem de parâmetros por referência funciona passando para a função chamada 
_referências_ para variáveis ao invés de valores de expressões. Isso permite à 
função chamada afetar as variáveis usadas como argumento para a função. 
Vamos ilustrar como isso funciona demonstrando como criar uma função que troca 
o valor de duas variáveis e realmente funciona:
.Código fonte
{gitrepo}/blob/master/livro/capitulos/code/funcoes/troca_ref.c[code/funcoes/troca_ref.c]
[source, c]
.Função para trocar o valor de duas variáveis usando passagem por referência
----
include::code/funcoes/troca_ref.c[]
----
<1> Definição do procedimento. Os parâmetros `a` e `b` são declarados 
usando `int *` ao invés de simplesmente `int`. Isso indica passagem 
por referência. 
<2> Ao usar as variáveis `a` e `b` que foram passadas por referência, 
é necessário usar `*a` e `*b` para acessar ou modificar seu valor. 
<3> Na chamada da função `troca_variaveis` é preciso passar referências 
para as variáveis `x` e `y`, isso é conseguido usando `&x` e `&y`. 
.Resultado da execução do programa code/funcoes/troca_ref.c
....
include::code/funcoes/troca_ref.out[]
....
A primeira coisa a notar é que são necessárias algumas mudanças sintáticas 
para usar parâmetros por referência. A declaração dos parâmetros no início 
da função agora define os parâmetros `a` e `b` como tendo tipo `int *`. 
Quando esses parâmetros são usados na função `troca_variaveis`, eles precisam 
ser precedidos de asterisco (`*a` ao invés de `a`). E para chamar a função, é 
preciso passar referências para as variáveis `x` e `y` ao invés de passar seu 
valor, por isso usamos `&x` e `&y` na chamada. 
De maneira simplificada, a passagem por referência funciona da seguinte forma: 
ao escrever um argumento como `&x` para a função `troca_variaveis`, não estamos
passando o _valor_ de `x` para a função, mas sim uma _referência_ para a própria 
variável `x`. Isso significa que, dentro de `troca_variáveis`, o parâmetro `a` 
se torna um nome diferente para a mesma variável `x`; desta forma, alterações 
feitas em `a` (através da sintaxe `*a`) são alterações também no valor da 
variável original `x`. É por isso que o programa acima funciona, como pode 
ser visto no resultado da execução: a função `troca_variaveis` recebe referências 
para as variáveis `x` e `y`, e por isso pode alterar o valor destas variáveis 
diretamente, trocando o valor das duas. 
A passagem de parâmetros por referência é usada quando uma função precisa alterar 
o valor de uma variável que existe fora da própria função e que não necessariamente 
é uma variável global. O mesmo efeito de ter uma função alterando uma variável 
externa poderia ser atingido usando variáveis globais ao invés de passagem por 
referência, mas com grande perda de flexibilidade. Além disso, o uso desnecessário 
de variáveis globais não é recomendado, como comentado antes. 
Por exemplo, poderíamos trocar os valores das variáveis `x` e `y` no exemplo 
anterior se ambas fossem alteradas para serem variáveis globais: 
.Código fonte
{gitrepo}/blob/master/livro/capitulos/code/funcoes/troca_glob.c[code/funcoes/troca_glob.c]
[source, c]
.Função para trocar o valor de duas variáveis usando passagem por referência
----
include::code/funcoes/troca_glob.c[]
----
<1> `x` e `y` agora são variáveis globais. 
<2> `troca_variaveis` não utiliza parâmetros, já que acessa diretamente as 
variáveis globais. 
.Resultado da execução do programa code/funcoes/troca_glob.c
....
include::code/funcoes/troca_glob.out[]
....
O programa funciona, mas note que agora `troca_variaveis` só altera o valor de 
duas variáveis específicas, `x` e `y`, enquanto que a versão usando passagem por 
referência era geral e podia trocar o valor de quaisquer duas variáveis inteiras. 
Se um programa precisa trocar os valores de vários pares de variáveis, em vários 
locais diferentes, seria preciso criar uma função de troca para cada par,
e 
fazer todas as variáveis serem globais. Isso acarretaria em muita repetição, e 
muito uso desnecessário de variáveis globais que tornariam a manutenção do código 
muito mais difícil. Neste caso, é muito mais recomendado usar a passagem por 
referência para chegar a um código mais geral, mais fácil de manter e com menos
repetição. 
[NOTE]
====
A passagem por referência vem sido usada neste livro há vários capítulos, 
pois a função `scanf` usa esse modo de passagem de parâmetros. Em toda chamada 
a `scanf` passamos referências para as variáveis que vão receber os valores, e 
não os valores dessas variáveis. Isso faz sentido já que `scanf` precisa alterar 
o valor das variáveis passadas como parâmetro, e ao mesmo tempo `scanf` não 
utiliza o valor original dessas variáveis para nada. 
====
[NOTE]
====
Com a passagem por referência e por valor na linguagem C acontece algo semelhante
ao que vimos com os conceitos de procedimento e função: a rigor na linguagem C 
só existe a passagem por valor, mas a passagem por referência pode ser 
obtida pelo uso de *ponteiros*, um conceito avançado da linguagem C. Como se 
trata de um conceito avançado, não vamos detalhar mais sobre eles aqui neste 
livro. 
====
=== Protótipos e Declaração de Funções
Em todos os exemplos que vimos neste capítulo até agora, nós sempre definimos
uma função antes de chamá-la em outra função. Nesses exemplos, a função 
`main` sempre aparece no final do arquivo, já que as chamadas para as outras 
funções apareciam apenas em `main`. 
Mas em muitos casos pode ser necessário chamar uma função que é definida 
posteriormente no arquivo, sem precisar mudar as funções de lugar. O mesmo 
ocorre em programas maiores, quando usamos vários arquivos de código-fonte 
para um programa (mas este caso não será detalhado aqui).
Se tentarmos usar uma função antes de sua definição vamos observar um erro 
de compilação. No exemplo abaixo, a intenção é definir uma função que 
imprime a situação de um aluno em uma disciplina cuja média é 7.0. Para 
isso é necessário passar para a função as três notas do aluno na disciplina. 
Mas se definirmos a função após `main`, como abaixo: 
.Código fonte
{gitrepo}/blob/master/livro/capitulos/code/funcoes/situacao.c[code/funcoes/situacao.c]
[source, c]
.Chamando uma função antes de sua definição
----
include::code/funcoes/situacao.c[]
----
<1> A função `main` chama `situacao` antes de sua definição. 
<2> A definição de `situacao` começa após a função `main`.
Ao tentar compilar esse programa, um erro similar ao seguinte será acusado: 
.Resultado da execução do programa code/funcoes/situacao.c
....
include::code/funcoes/situacao.out[]
....
Isso acontece porque o compilador não pode identificar se a função foi 
realmente definida em algum lugar e, principalmente, se o tipo dos parâmetros 
e o tipo do retorno da função estão sendo usados corretamente. 
Esse problema pode ser resolvido através do uso de *protótipos* para 
declarar uma função antes que seja definida. Um protótipo de função 
é uma declaração que especifica as seguintes informações: 
1. O tipo de retorno da função;
2. O nome da função;
3. O número de parâmetros;
4. Os tipos de cada um dos parâmetros.
Com essas informações, o compilador pode identificar se a função está sendo 
usada de maneira correta com relação aos tipos, e evita os erros anteriores. 
Para consertar o erro no exemplo anterior basta adicionar uma linha com o 
protótipo da função: 
.Código fonte
{gitrepo}/blob/master/livro/capitulos/code/funcoes/situacao_prot.c[code/funcoes/situacao_prot.c]
[source, c]
.Usando protótipos de funções
----
include::code/funcoes/situacao_prot.c[]
----
<1> Protótipo da função `situacao`. Note que o protótipo inclui o tipo de retorno 
(`void`), o nome da função, que a função aceita três parâmetros, e que todos eles 
possuem tipo `float`. Não é preciso especificar o nome dos parâmetros em um protótipo,
mas é possível especificar os nomes, se desejado; incluir os nomes dos parâmetros pode 
ser útil como uma forma simples de documentação. 
<2> A chamada a `situacao` em `main` agora pode acontecer sem problema. 
.Resultado da execução do programa code/funcoes/situacao_prot.c
....
include::code/funcoes/situacao_prot.out[]
....
Nesse exemplo, seria possível consertar o problema simplesmente movendo a 
função `situacao` completa para antes da função `main`, mas em programas 
maiores o uso de protótipos toma grande importância. 
=== Funções Recursivas
Uma função pode ser chamada a partir de qualquer outra função no mesmo programa. 
Dessa forma, podemos pensar em uma função chamando a si mesma. Isso é possível 
e útil em muitos casos. Quando uma função `f` chama a si mesma em algum ponto, 
dizemos que `f` é uma *((função recursiva))*. _Recursividade_ se refere a um 
objeto auto-referente, ou seja, que referencia a si próprio; isso inclui as 
funções recursivas mas também outros tipos de objetos.
Um exemplo é o cálculo do fatorial de um número. O _fatorial_ de um número 
inteiro positivo N (cuja notação é latexmath:[$N!$]) é definido como o 
produto de todos os números de 1 até N:
[latexmath]
++++
\[
N! = N \times (N-1) \times \dots \times 2 \times 1
\]
++++
por exemplo, o fatorial de 3 é latexmath:[$3! = 3 \times 2 \times 1 = 6$], 
e o fatorial de 4 é latexmath:[$4! = 4 \times 3 \times 2 \times 1 = 24$], 
e assim por diante. 
Para números N maiores que 1, sempre podemos fazer a seguinte relação: 
[latexmath]
++++
\[
N! = N \times (N-1)!
\]
++++
ou seja, latexmath:[$4! = 4 \times 3! = 4 \times 6 = 24$]. Isso indica 
a estrutura recursiva do cálculo do fatorial: o fatorial de um número N 
é igual a N vezes o fatorial do número anterior a N, N-1. 
Seguindo essa ideia, podemos escrever uma função recursiva que calcula 
o valor do fatorial de um número. Como a função chama a si mesma, é muito 
importante saber quando a cadeia de chamadas da função a ela mesma termina. 
No caso do fatorial, quando queremos calcular o fatorial do número 1 ou do número 0, 
podemos responder diretamente: latexmath:[$1! = 0! = 1$], sem usar a recursividade. Esse 
é o chamado *caso-base* da recursão. Sem isso, a função nunca pararia de chamar a 
si mesmo, e o programa seria finalizado com algum erro dependente do sistema 
operacional e do compilador utilizados.
O programa com a função que calcula o fatorial é o seguinte: 
.Código fonte
{gitrepo}/blob/master/livro/capitulos/code/funcoes/fatorial.c[code/funcoes/fatorial.c]
[source, c]
.Cálculo do fatorial usando uma função recursiva
----
include::code/funcoes/fatorial.c[]
----
<1> Protótipo da função `fatorial`. 
<2> Caso-base na função `fatorial`: para `n` igual a 0 ou 1, retorna 1.
<3> Caso recursivo na função `fatorial`: se `n` for maior que 1, 
retorne `n` multiplicado pelo fatorial de `n - 1`.
.Resultado de três execuções do programa code/funcoes/fatorial.c
....
include::code/funcoes/fatorial.out[]
....
O código calcula o fatorial de um número inteiro recursivamente. Se o número 
for 0 ou 1, a resposta é direta: 1. Se o número for maior do que 0 ou 1, a resposta 
é obtida pela multiplicação do número pelo fatorial do número anterior a ele. Note 
que esse processo sempre termina se o parâmetro `n` da função fatorial for um 
inteiro positivo, pois em cada chamada recursiva o argumento da função fatorial 
será um número menor que o anterior, até eventualmente chegar a 1, cuja resposta é 
direta. Como a função tem um parâmetro declarado como inteiro, o compilador C 
não permitiria passar como parâmetro um número não-inteiro, então, isso não pode 
criar problema para essa função recursiva. Entretanto, um erro que pode acontecer 
neste caso é se o usuário especificar um número negativo: 
.Cálculo do fatorial usando número negativo, usando o programa code/funcoes/fatorial.c
....
include::code/funcoes/fatorial_neg.out[]
....
A falha de segmentação
(_segmentation fault_) mostrada quando se passa um argumento 
negativo para a função `fatorial` é o resultado da recursão infinita que ocorre na 
função: como em cada etapa o número é diminuído de um, um número negativo nunca vai 
chegar a 1 (ou 0) e portanto nunca vai parar no caso-base. Mesmo a noção matemática 
do fatorial não está definida para números negativos. Uma forma de consertar o 
programa acima seria imprimir um erro quando `fatorial` fosse chamado com um 
argumento negativo, ou retornar um valor qualquer, sem chamar a função recursivamente. 
Uma forma de fazer isso seria mudando o teste do caso base: 
.Código fonte
{gitrepo}/blob/master/livro/capitulos/code/funcoes/fatorial2.c[code/funcoes/fatorial2.c]
[source, c]
.Cálculo do fatorial usando uma função recursiva
----
include::code/funcoes/fatorial2.c[]
----
<1> Caso-base da função `fatorial`. O teste agora é se o parâmetro é menor ou 
igual a 1, o que inclui os números negativos. Neste caso, a função retorna 1 
sem fazer chamadas recursivas. 
.Resultado de duas execuções do programa code/funcoes/fatorial2.c
....
include::code/funcoes/fatorial2.out[]
....
Neste caso, a função sempre retorna 1 para números negativos, o que é um 
resultado estranho, mas como o fatorial não está definido para números 
negativos, isso não chega a ser um grande problema. 
A recursividade é um conceito de programação considerado avançado, mas 
se torna bastante importante em programas mais complexos. Alguns paradigmas 
de programação como a _programação funcional_ e a _programação lógica_ são 
bastante baseadas no uso de funções recursivas, e muitos processos se tornam 
muito mais fáceis de implementar usando funções recursivas. Por isso, apesar 
de não entrarmos em mais detalhes sobre funções recursivas aqui, é importante 
ter em mente que esse é um dos conceitos que se tornam importantes para a 
evolução de um programador.
=== Recapitulando
Neste capítulo, vimos uma importante ferramenta para a criação de programas 
na linguagem C: funções. As funções (e os procedimentos, que são tratados na linguagem C 
como funções) possibilitam a reutilização de trechos de código em várias partes 
de um programa, e permitem isolar determinadas componentes do programa em unidades 
mais autocontidas, melhorando a modularização do programa. É raro que um programa 
não-trivial na linguagem C não faça uso de funções. 
Vimos exemplos do uso de procedimentos 
(funções que não retornam valores) com e sem parâmetros. Vimos também como usar parâmetros para 
funções e como retornar valores a partir de uma função. 
As regras que regem a visibilidade 
de variáveis locais, globais e parâmetros de funções foram apresentadas, assim como os 
diferentes modos de passagem de parâmetros e como utilizá-los: passagem por valor e por 
referência. 
Também vimos como declarar funções usando protótipos, para poder utilizar essas funções 
antes de sua definição (ou em arquivos diferentes de onde elas estão definidas). Um 
exemplo simples de função recursiva foi mostrado, como forma de introdução ao conceito. 
Compreender o conteúdo deste capítulo é extremamente importante para 
aprender a programar bem na linguagem C. 
=== Exercícios Propostos 
1. Escreva uma função que calcula a média final de um aluno que fez prova 
final em uma disciplina. A função deve receber a média parcial do aluno 
(média das notas nas provas regulares da disciplina) e a nota obtida na 
prova final. O cálculo para a média final é
[latexmath]
++++
MF = \frac{6 \times MP + 4 \times PF}{10}
++++
onde latexmath:[$MF$] é a média final, latexmath:[$MP$] é a média parcial 
e latexmath:[$PF$] é a nota da prova final. Escreva um programa que utiliza 
esta função, pedindo os dados necessários ao usuário e imprimindo o valor 
da média final na tela. 
2. Às vezes é útil limpar a "tela" antes de imprimir informações adicionais no 
console. Uma forma de limpar a tela é imprimir mais de 24 linhas em branco 
(dependendo do tamanho do console). Em geral, imprimir 30 linhas em branco 
deve ser suficiente. Escreva uma função (procedimento) que limpe a tela 
imprimindo 30 linhas em branco. 
3. Escreva uma função que recebe dois parâmetros `a` e `b` e troca o valor 
de `a` com o valor de `b` se o valor de `a` for maior do que o de `b`; 
o objetivo é ter, ao final, o menor dos dois valores em `a` e o maior em 
`b`. Por exemplo, se `a = 5` e `b = 3`, então os valores das duas 
variáveis devem ser trocados, mas se `a = 2` e `b = 7`, então a ordem já 
está correta e não é necessário trocar os valores. Utilize passagem de 
parâmetros por referência para poder afetar o valor das variáveis. 
Escreva um programa para testar a função. 
4. O que é impresso pelo seguinte programa?
.Código fonte
{gitrepo}/blob/master/livro/capitulos/code/funcoes/exercicio4.c[code/funcoes/exercicio4.c]
[source, c]
.Cálculo do fatorial usando uma função recursiva
----
include::code/funcoes/exercicio4.c[]
----
introducao-a-programacao-livro-1.0.0/livro/capitulos/introducao-a-programacao.asc
== Introdução à Programação
.Objetivos do capítulo
____________________
Ao final deste capítulo você deverá ser capaz de:
* Entender o processo de tradução de programas escritos em linguagem de alto 
nível para código de máquina
* Compreender o conceito de variável e sua relação com a memória do 
computador
* Criar instruções que envolvam operações aritméticas
* Utilizar instruções de entrada e saída da linguagem C
* Escrever um programa simples em C
____________________
////
TODO - REV.00: Sugestão de melhoria para análise pelo autor - Comentário Geral
Seria interessante rever a estruturação desse capítulo como um todo. A impressão
é que o aluno sentirá uma certa dificuldade para entender devido a forma como
está estruturado. Como sugestão o livro poderia quebrar em capítulos como:
cap 01 - introdução ao algoritmo - descrevendo os conceitos básicos de algoritmo
cap 02 - linguagem algoritmica - descrevendo maiores detalhes sobre pseudocódigo (explicando conceitos básicos como estruturação, variáveis e etc)
cap 03 - introdução a programação - seria o capítulo corrente, tirando o conteúdo da linguagem C
cap 04 - A linguagem c - introduzindo a linguagem c
cap 05 - ...
Também recomendaria adicionar um maior número de exemplos, ilustrações e exercícios comentados
no decorrer de todo capítulo.
////
////
TODO - REV.01: Dúvida sobre a ordem dos capítulos 
Ao iniciar a leitura fiquei em dúvida da ordem do capítulo, este
seria o 2 ou o 3? 
////
Agora que você já conhece as características de um algoritmo computacional e 
é capaz de criar algoritmos utilizando suas diferentes formas de 
representação, está na hora de você escrever seu primeiro programa. Porém, 
antes que isso ocorra, você deve aprender alguns conceitos básicos, como o 
de variável, e conhecer o processo de tradução de um programa 
escrito em linguagem de alto nível (a linguagem C, por exemplo) para código 
de máquina, ou seja, para a linguagem que o computador trabalha. Além desses 
conceitos, este capítulo também aborda a elaborações de expressões 
aritméticas em C, bem como alguns de seus comandos básicos.
=== Introdução
Você viu no capítulo anterior que existe uma linguagem que os computadores 
são capazes de compreender e que é utilizada na elaboração de algoritmos 
para instruí-los a executarem as mais diversas tarefas. Essa linguagem é 
chamada de linguagem de programação e consiste no principal assunto deste 
capítulo.
Assim como as linguagens naturais (português, inglês, espanhol, etc.), as 
linguagens de programação têm o objetivo de prover um meio eficaz de 
comunicação. Elas são constituídas de um conjunto de palavras especiais 
(vocabulário), que associadas a um conjunto de regras de utilização, 
determinam como os algoritmos devem ser especificados para que possam ser 
corretamente decodificados pelo computador.
As linguagens de programação diferem das naturais de várias formas. 
Primeiramente, apesar de ser possível de serem utilizadas como meio de 
comunicação entre pessoas, seu principal propósito é possibilitar a 
comunicação entre uma pessoa e um computador. Além disso, as linguagens 
naturais são mais tolerantes a erros. Um erro gramatical, por exemplo, não 
impossibilita uma conversa entre duas pessoas. Já no caso das linguagens de 
programação, a simples omissão de um ponto e vírgula é capaz até de 
impedir que a comunicação seja iniciada.
////
TODO - REV.02: Sugestão de melhoria para análise pelo autor 
Acho que o nome de área de conhecimento (l.63) como ciência da computação são 
sempre iniciadas em maiúscula. 
////
O conteúdo da comunicação por meio de uma linguagem de programação tem um 
significado especial para a ciência da computação. Enquanto que nos 
expressamos nas linguagens naturais através de textos e da emissão de sons, 
nas linguagens de programação nos expressamos através de programas, que nada 
mais são do que algoritmos escritos em uma linguagem de programação. O 
estudo das técnicas para elaboração de programas consiste em um dos pilares 
da ciência da computação, conferindo uma importância particular à 
disciplina de Introdução à Programação.
Antes que você conheça as peculiaridades de uma linguagem de programação 
estruturada, como suas principais instruções e regras para a construção de 
um programa, estudaremos os paradigmas de programação existentes e o processo 
de tradução de um programa escrito em linguagem de alto nível para um 
programa em código de máquina.
=== Níveis das Linguagens de Programação
Os computadores representam as informações através da manipulação de dois 
estados. Esse sistema de representação, denominado de sistema binário, 
decorre do fato da grande maioria dos componentes eletrônicos poder assumir 
apenas dois valores. Por exemplo, uma lâmpada pode estar no estado 
"ligado" ou "desligado", um capacitor pode estar "carregado" ou 
"descarregado" e um circuito elétrico pode estar energizado ou não.
A representação binária utiliza os algarismos "0" e "1", chamados de 
dígitos binários. Eles são os valores que um bit (menor unidade de 
informação em um computador) pode assumir e estão associados aos valores de 
tensão presentes nos circuitos elétricos do computador. Para representar o 
bit zero, por exemplo, normalmente utiliza-se um valor próximo a zero volts. 
Para o bit um, utiliza-se um valor um pouco maior, da ordem de poucos volts.
////
TODO - REV.03: Sugestão de melhoria para análise pelo autor 
É mais legível no decorrer do texto fazer referência ao identificador da legenda de figuras/quadros/tabelas,
ao invés de mencionar "o quadro abaixo" ou algo parecido. 
////
Repare que trabalhar com uma combinação de zeros e uns não é uma tarefa 
fácil para um ser humano. Para que você perceba a dificuldade, imagine como 
seria escrever um pseudocódigo substituindo comandos como "LEIA", 
"ESCREVA" e expressões aritméticas por uma combinação de zeros e uns. 
O quadro de código binário hipotético abaixo ilustra tal situação, 
apresentando um algoritmo em pseudocódigo 
que calcula a média de duas notas lidas da entrada padrão e sua versão 
hipotética em código binário. 
.Algoritmo em pseudocódigo
-------------
ALGORITMO 
DECLARE nota1,
 nota2, 
 M : NUMÉRICO
LEIA nota1
LEIA nota2
M <= (nota1 + nota2) / 2 
FIM_ALGORITMO.
-------------
////
TODO - REV.03: Sugestão de melhoria para análise pelo autor 
Seria interessante fazer referência cruzada entre os dois exemplos (ex. o código binário
representar hipoteticamente o código acima). 
////
.Ilustração de um código binário hipotético referente a um algoritmo escrito em pseudocódigo.
-------------
10100001
10100011 10010001
 10010010
 10010011 11000001
10100100 10010001
10100100 10010010
10010011 11110011 10010001 11110001 10010010 11110010 00000010
10100010
-------------
IMPORTANT: O código binário acima apresentado tem fins meramente 
didáticos, não sendo elaborado com base em nenhuma máquina real.
Com o intuito de tornar menos complicada, mais eficiente e menos sujeita a 
erros a tarefa de programar computadores, foram criadas linguagens de 
programação mais próximas às linguagens naturais. Elas são compostas de um 
conjunto de palavras-chave, normalmente em inglês, e símbolos que estabelecem 
os comandos e instruções que podem ser utilizados pelo programador na 
construção de seus programas.
As linguagens com essa característica são chamadas de linguagens de alto 
nível, ao passo que as mais próximas da linguagem de máquina 
(representação binária), são denominadas de linguagens de baixo nível. 
São exemplos de linguagens de alto nível: Pascal, C (linguagem abordada neste 
livro), Java, C++ e Python. Como exemplo de linguagem de baixo nível, temos a 
linguagem Assembly. 
////
TODO - REV.04: Sugestão de melhoria para análise pelo autor 
Seria interessante colocar aqui link para outras informações, ou curiosidades, e 
assim vai. 
////
=== Tradutores e Interpretadores
Se por um lado as linguagens de programação facilitam o trabalho dos 
programadores, por outro impossibilitam que os programas desenvolvidos nessas 
linguagens sejam compreendidos pelos computadores, visto que eles são capazes 
de manipular apenas códigos binários. Dessa forma, os cientistas do passado 
se depararam com o seguinte desafio: como executar um programa em linguagem de 
programação, seja ela de baixo ou alto nível, em um computador que trabalha 
apenas como números binários?
À primeira vista, o desafio em questão parece ser complexo demais para ser 
solucionado por um iniciante na ciência da computação. Todavia, você vai 
perceber que a solução para o problema está mais próxima da sua realidade 
do que imagina. Suponha que você recebeu uma proposta milionária para 
trabalhar em uma empresa de desenvolvimento de software da China. Seus patrões 
pagarão suas passagens, hospedagem, transporte e todo o aparato necessário 
para que você possa ter uma vida tranquila no país asiático. Apesar de a 
proposta ser atraente, existe um problema: todos os funcionários da empresa 
falam somente o chinês, inclusive seus patrões. Além disso, o contrato a ser 
assinado também está escrito em chinês. O que você faria em tal situação? 
////
TODO - REV.05: Sugestão de melhoria para análise pelo autor 
A resposta a pergunta realizada (l.189) pode ser reescrita de uma forma mais
suave, como: "Recusaria a proposta? Certamente não, pois uma solução possível seria utilizar
um tradutor para resolver o problema. 
////
Recusaria a proposta? É isso mesmo que você está pensando, um tradutor seria 
a solução para seus problemas.
Do mesmo modo que você precisaria de um tradutor para poder lidar com uma 
linguagem que não consegue entender, os computadores também necessitam de um 
tradutor para traduzir um programa escrito em linguagem de programação para 
um programa correspondente em linguagem de máquina. Dois softwares básicos 
são responsáveis por realizar a tradução em questão: os tradutores e os 
interpretadores.
////
TODO - REV.06: Sugestão de melhoria para análise pelo autor 
Sugeriria adicionar figuras para ilustrar o texto apresentado abaixo
também. 
////
Os tradutores podem ser classificados como montadores e compiladores. Quando o 
processo de tradução converte um programa que se encontra no nível de 
linguagem de montagem (representação simbólica da linguagem de máquina, 
ex.: linguagem Assembly) para a linguagem de máquina, o tradutor utilizado é 
o montador. Já na tradução de programas em linguagem de alto nível para a 
linguagem de montagem, o software responsável é o compilador. Perceba que 
não há tradução direta da linguagem de alto nível para a linguagem de 
máquina. Para que esta seja alcançada, são necessários vários passos 
intermediários,
sendo um deles a tradução para a linguagem de montagem. 
[[fig_compilacao_passos]]
["graphviz"]
.Passos no processo de compilação
----
digraph automata_0 {
 rankdir=LR;
 size ="8.5, 11";
 node [shape = box];
 
 subgraph clusterCodigos {
 label = "Código fonte";
 node [style=filled,color=white];
 style=filled;
 color=lightgrey;
 code_assembly [label="Linguagem de Baixo Nível\n(Linguagem de montagem)"];
 code_c [label="Linguagem de Alto Nível\n(Ex: C, Pascal, ...)"];
 }
 subgraph clusterTradutor {
 label = "Tradutor";
 node [style=filled,color=white,shape="doubleoctagon"];
 style=filled;
 color=lightgrey;
 montador [label="Montador"];
 compilador [label="Compilador"];
 }
 code_gerado [label="Código traduzido\n(Linguagem de montagem)"];
 subgraph clusterCodigoObjeto {
 label = "Código Objeto\n(binário)";
 node [style=filled,color=white];
 style=filled;
 color=lightgrey;
 objeto1 [label="Código Objeto 1"];
 objeto2 [label="Código Objeto 2"];
 }
 ligador [label="Ligador",shape="doubleoctagon"];
 programa [label="Código Binário\nExecutável", shape="component", fillcolor="grey", style="filled"];
 carregador[label = "Carregador", colorscheme=oranges4, fillcolor=3, color=2];
 code_assembly -> montador -> objeto1 [color="forestgreen", style="bold"];
 code_c -> compilador -> code_gerado -> montador -> objeto2 [color="blue", style="bold"];
 
 objeto1->ligador [color="red", style="bold"];
 objeto2->ligador [color="red", style="bold"]; 
 ligador-> programa [color="red", style="bold"];
 
 programa -> carregador -> memoria 
 {rank=source; code_c code_assembly }
 {rank=same; montador compilador}
 {rank=same; objeto1 objeto2}
 {rank=sink; programa}
}
----
No processo de compilação, cada parte de um programa (módulo) escrito em 
linguagem de alto nível é traduzido para um módulo objeto diferente, que 
consiste em sua representação em linguagem de montagem. Esse passo no 
processo de compilação corresponde ao passo 1 da <<fig_compilacao_passos>>. Antes de serem 
traduzidos para linguagem de máquina pelo montador, é necessário que os 
vários módulos objetos sejam integrados de modo a formarem um único código. 
Essa tarefa é realizada no passo 2. O passo 3 é o responsável por carregar o 
programa na memória, a fim de tornar suas instruções prontas para serem 
executadas pelo processador.
Os interpretadores, além de realizar a tradução de um programa para a 
linguagem de máquina, ainda executam suas instruções. Assim que traduz uma 
instrução, ela é imediatamente executada, gerando assim um ciclo de 
tradução e execução que prossegue de instrução a instrução até o fim 
do programa (<<fig_interpretacao>>).
[[fig_interpretacao]]
.Processo de Interpretação
["graphviz", scaledwidth="90%"]
----
digraph automata_0 {
 rankdir=LR;
 node [shape = box];
 linguagem [label="Linguagem\nde Alto Nível", shape="polygon"];
 interpretador [label="Interpretador"];
 traduz [label="Traduz e executa \numa intrução", shape="hexagon"];
 linguagem -> interpretador -> traduz
 traduz -> interpretador [label="Busca nova intrução"]
 {rank=sink; traduz}
}
----
Por não traduzir um programa escrito em linguagem de alto nível diretamente 
para linguagem de máquina, o processo de compilação tende a ser mais rápido 
que o processo de interpretação. Além disso, uma vez compilado, um programa 
pode ser executado várias vezes sem a necessidade de haver uma recompilação. 
 Já na interpretação, cada vez que um programa tiver que ser reexecutado, 
todo o processo de interpretação deverá ser refeito, independente de ter 
ocorrido modificações no código fonte do programa desde sua última 
execução. A vantagem da interpretação fica por conta da possibilidade de 
testar os programas ao mesmo tempo em que são desenvolvidos. 
IMPORTANT: A linguagem utilizada neste livro (linguagem C) como ferramenta para iniciá-lo 
na programação de computadores é uma linguagem compilada, portanto, os 
programas que você irá desenvolver passarão pelos passos explanados 
anteriormente.
// XXX Como manter as referencias aos outros livros da coleção consistente?
NOTE: Para saber mais sobre o processo de montagem e compilação, leia a Seção 3 
do Capítulo 5 do Livro de Introdução ao Computador.
////
TODO - REV.07: Sugestão de melhoria para análise pelo autor 
Não haveria outros materiais que pudessem ser adicionados como links ou curiosidades?
////
=== Paradigmas de Programação
////
TODO - REV.08: Sugestão de melhoria para análise pelo autor 
É importante deixar mais suave para o leitor a transição de uma seção para a outra.
Perceba que saímos de uma seção que explica os compiladores e interpretadores e caímos, de repente,
em outra, que explica paradigmas. Que relação temos com os dois assuntos? Por que, eu como aluno, preciso
saber disso mesmo? Que relação há com o ato de programar? Parece blá blá, mas para o aluno que 
está lendo e aprendendo sozinho faz uma diferença grande, pode ter certeza.
////
Um paradigma de programação está relacionado com a forma de pensar do 
programador na construção de soluções para os problemas com os quais se 
depara. Programar seguindo um determinado paradigma de programação significa 
representar soluções a partir de uma forma particular de raciocinar na 
elaboração dos algoritmos. Como os paradigmas mencionados sustentam a 
atividade de programas, eles influenciam todo o processo de desenvolvimento de 
software. Alguns dos paradigmas de programação mais utilizados estão 
relacionados abaixo:
////
TODO - REV.09: Sugestão de melhoria para análise pelo autor 
Foi explicado o que é uma variável?
////
Paradigma imperativo:: Representa a computação como ações, enunciados ou 
comandos que alteram o estado (variáveis) de um programa. Consiste na 
elaboração de programa a partir de comandos que dizem o que o computador deve fazer 
a cada momento.
Paradigma estruturado:: Soluciona problemas a partir de sua quebra em problemas 
menores, de mais fácil solução, denominados de sub-rotinas ou subprogramas. 
Normalmente, o trabalho de cada sub-rotina consiste em receber dados como 
entrada, processar esses dados e retornar o resultado do processamento para o 
módulo de software que o executou. Este paradigma ainda defende que todo 
processamento pode ser realizado pelo uso de três tipos de estruturas: 
sequencial, condicional e de repetição. É o paradigma adotado neste livro.
Paradigma declarativo:: Descreve as características da solução desejada sem 
especificar como o algoritmo em si deve agir. Em contraste com o paradigma 
imperativo, que informa ao computador como as instruções devem ser 
executadas, o paradigma declarativo preocupa-se apenas em definir o que deve 
ser feito, deixando a cargo de outros softwares decidirem como alcançar a 
solução descrita. É bastante utilizado no desenvolvimento das páginas web 
(linguagem html) e na descrição de documentos multimídia através da 
linguagem Nested Context Language – NCL, adotada pelo padrão brasileiro de 
TV Digital. 
Paradigma orientado a objetos:: Enxerga o problema como uma coleção de objetos 
que se comunicam por meio da troca de mensagens. Os objetos são estruturas de 
dados que possuem estado (variáveis) e comportamento (lógica). 
////
TODO - REV.10: Sugestão de melhoria para análise pelo autor 
Aqui nesse ponto também seria interessante ter seções "Para saber mais..." ou 
links e gravuras que ilustram um pouco mais o que está sendo explicado.
////
=== Linguagem C
////
TODO - REV.11: Sugestão de melhoria para análise pelo autor 
Sugeriria que a explicação da linguagem C fosse em um capítulo a parte.
////
A linguagem C foi desenvolvida por Dennis Ritchie, entre os anos 1971 e 1973, 
nos laboratórios da AT&T. O objetivo de Ritchie era criar uma linguagem para a 
implementação de sistemas operacionais e softwares básicos
que combinasse a 
eficiência das linguagens de baixo nível com características das linguagens 
de alto nível, como legibilidade, portabilidade e manutenibilidade.
////
TODO - REV.12: Sugestão de melhoria para análise pelo autor 
Sugeriria deixar os detalhes do processo evolutivo da linguagem C como parte 
de seções "Para saber mais..." ou algo assim. Estamos tratando de um aluno iniciante
a distância e de repente colocamos várias informações que para ele, no momento, seria
sobrecarga.
////
A criação da linguagem C é resultado de um processo evolutivo de linguagens, 
iniciado com uma linguagem chamada BCPL, desenvolvida por Martin Richards. Essa 
linguagem influenciou a linguagem B, inventada por Ken Thompson, que por sua 
vez levou ao desenvolvimento de C.
////
TODO - REV.13: Sugestão de melhoria para análise pelo autor 
Caso seja realmente julgado necessário citar o Unix é interessante dizer que se trata
de um sistema operacional e adicionar link para "maiores informações ou para saber mais..".
////
Em 1973, Dennis Ritch não deixou dúvidas que seu objetivo foi alcançado, 
desenvolvendo eficientemente parte do sistema Unix na linguagem C. A partir de 
meados dos anos 80, C começou a ganhar popularidade e, devido à sua 
flexibilidade em atuar com características de linguagens de alto e baixo 
nível, foi reconhecida como uma linguagem de propósito geral, sendo utilizada 
na implementação de uma grande variedade de sistemas.
Devido à importância auferida na área da programação de computadores, C é 
hoje uma das linguagens mais utilizadas em cursos de programação do mundo 
inteiro. Sendo assim, ela é a linguagem que guiará você na compreensão das 
nuances da arte de programar e servirá como ferramenta para elaboração dos 
seus primeiros programas. A linguagem C será apresentada, de forma 
conveniente, a partir da próxima seção.
=== Núcleo de um programa
////
TODO - REV.14: Sugestão de melhoria para análise pelo autor 
Para ser mais didático não haveria como correlacionar o núcleo do programa
com o que já foi apresentado em linguagem algoritmica? Sinto que Precisamos ser mais
didático nas explicações.
////
A organização da sequência de instruções em um programa obedece a um 
conjunto de regras estabelecidas pela linguagem de programação. Um programa 
em C é estruturado em funções, que são, basicamente, trechos de código que 
podem ser chamados várias vezes para realizar uma certa tarefa. Assim, todas 
as instruções pertencentes a um programa em C devem estar contidas em uma 
função.
Além de ser um meio de agrupar trechos de um código, uma função em 
programação tem características semelhantes a uma função matemática, no 
sentido de que recebe parâmetros como entrada (seria o domínio da função) e 
retorna um valor como saída (imagem).
Em C existe uma função especial, denominada de `main` (principal), que 
determina o início e o fim da execução de um programa. De forma mais 
específica, a execução de um programa tem seu início com a execução da 
primeira instrução da função `main` e termina com a execução da sua 
última instrução. Dessa maneira, todo programa em C deve possuir tal 
função.
IMPORTANT: Você conhecerá mais sobre as funções no Capítulo 6 deste 
livro. Por enquanto é necessário apenas que você saiba que todo programa em 
C deve ter uma função `main` e que a execução de um programa inicia e termina 
com a execução de seus comandos.
////
TODO - REV.15: Sugestão de melhoria para análise pelo autor 
Diga apenas que iniciaremos nosso estudo com um programa simples... evite 
os advérbios, pois haverá aluno que ainda não entenderá o exemplo mesmo sendo simples.
////
Iniciaremos nosso estudo com um programa extremamente simples, que apenas 
imprime uma mensagem na tela:
////
TODO - REV.16: Sugestão de melhoria para análise pelo autor 
Colocar uma representação mais abstrata de como um programa em c é estruturado, tipo
o que normalmente é apresentado quando quando se inicia o estudo de uma linguagem 
algoritmica, informando por exemplo, a estrutura em blocos de um programa c.
Outro ponto é verificar se está realmente aparecendo a numeração das linhas que 
apresentam o código. Na versão html não está aparecendo.
////
[source, c]
----------------
#include <stdio.h>
int main() {
 printf("Meu primeiro programa!");
 return 0;
}
----------------
Analisemos o que ocorre em cada linha de código:
 #include <stdio.h>
Esta linha de código solicita ao compilador que inclua no programa a 
biblioteca padrão para comandos de entrada e saída da linguagem C. Uma 
biblioteca consiste em um conjunto de arquivos que contém funções que podem 
ser incorporadas a outros programas. Neste caso, a inclusão da biblioteca 
`stdio.h` permite que o programa utilize suas funções para ler dados da entrada 
padrão (teclado) e para escrever dados na saída padrão (tela).
(((Entrada padrão))) (((Saída padrão)))
 int main(){
Com esta linha de código definimos a função `main` e demarcamos o seu início 
com o caractere `{` (abre-chaves). Todo conteúdo de uma função em C fica 
delimitado por chaves ( `{}` ).
 printf("Meu primeiro programa!");
O programa tem seu início com a execução desta instrução, uma vez que ela 
é a primeira instrução da função `main`. 
A função `printf` tem a finalidade de escrever na tela os dados recebidos por 
parâmetro. Como resultado de sua execução, neste caso, será exibida a 
frase "Meu primeiro programa!" no canto superior esquerdo do monitor do 
computador.
O ponto-e-vírgula no fim da instrução serve para separar esta instrução da 
próxima, dessa maneira, cada instrução deve terminar com sua utilização.
 return 0;
Essa instrução encerra a execução do programa, de modo que deve ser sempre 
a última da função `main` (antes do fecha-chaves, é claro). O número 0 
(zero) serve para indicar ao sistema operacional que o programa terminou com 
sucesso (números diferentes de zero indicariam um erro). Você entenderá 
melhor como isso funciona quando abordarmos detalhadamente as funções, no 
capítulo 6.
=== Memória e Variáveis
A memória principal do computador ou memória RAM (<<fig_memoria_ram>>) é constituída 
por componentes eletrônicos capazes de armazenar dados. Cada dígito binário 
(0 ou 1) ocupa uma porção de memória chamada de bit, e um conjunto de 8 bits 
é denominado de byte. A memória é dividida em células de memória de um 
byte de tamanho, que podem ser acessadas a partir de um número único que as 
identifica de forma particular. Esse número é chamado de endereço e tem a 
mesma função que os endereços de nossas casas, que é identificar de forma 
única nossas residências, a fim de possibilitar o envio e o recebimento de 
correspondências. No caso do computador, as correspondências são os dados 
que serão armazenados nas células de memória.
[[fig_memoria_ram]]
.Figure 2.3: Memória RAM.
image::images/introducao-a-programacao/memoria.png[]
Uma variável em programação representa, através de símbolos, o conteúdo 
de uma célula ou posição de memória. Por exemplo, se uma variável de nome 
`x` possui o valor 10, significa dizer que a posição de memória, representada 
pelo símbolo `x`, armazena o valor 10. Em programação, podemos enxergar a 
memória como um conjunto de posições que possuem um endereço e uma 
representação simbólica (variável), como ilustrado na <<fig_memoria_representacao>>.
[[fig_memoria_representacao]]
.Representação da memória em função dos endereços, das posições de memória e das variáveis. 
image::images/introducao-a-programacao/memoria-representacao.eps[scaledwidth="70%"]
////
TODO - REV.17: Sugestão de melhoria para análise pelo autor 
Talvez fosse interessante mencionar que as regras para nomes de variáveis
dependem da linguagem de programação.
////
NOTE: As variáveis podem ter nomes diversos, desde símbolos comuns na 
matemática, como é o caso das variáveis `x`, `y` e `z`, até
nomes como `var`, 
`endereco`, `cpf`, etc. As regras para dar nome às variáveis serão 
apresentadas na próxima seção. Perceba também que os valores que as 
variáveis podem armazenar não se limitam apenas a valores numéricos 
inteiros. Elas podem armazenar, por exemplo, um conjunto de caracteres, como é 
o caso da variável `z`, e valores fracionários, como é o caso das variáveis `y` 
e `var`.
==== Identificadores 
Os nomes que damos às variáveis, rotinas, constantes e demais componentes num 
programa escrito numa dada linguagem de programação são chamados de 
identificadores. Na seção anterior, por exemplo, utilizamos os 
identificadores `x`, `y`, `z` e var para dar nome às variáveis da <<fig_memoria_representacao>>. 
As palavras que possuem significado especial nas linguagens de programação, como 
é o caso dos nomes dados às estruturas de controle (`for`, `while`, `if`, etc.), 
tipos de variáveis, dentre outros, são chamadas de palavras-chave.
As regras básicas para formação de identificadores são:
* Os caracteres utilizados são os números, letras maiúsculas, minúsculas e o 
caractere especial sublinha (_);
* O primeiro caractere deve ser uma letra ou o sublinha;
* Não são permitidos espaços em branco;
* Palavras reservadas não podem ser utilizadas como identificadores.
Abaixo, alguns exemplos de identificadores válidos:
---------------
B
b
X2
computacao
COMPUTACAO
nota1
nota_2
cpf
RG
---------------
Identificadores inválidos:
---------------
3B -> Não pode começar com número.
X 2 -> Não pode conter espaço em branco.
Computaçao -> Não é permitido utilizar o caractere cedilha.
COMPUTACÃO -> Caracteres especiais como o til (~) não são permitidos.
while -> while é uma palavra reservada.
function -> function também é uma palavra reservada.
---------------
////
TODO - REV.17: Sugestão de melhoria para análise pelo autor 
Explicar o porquê dessa boa prática, isto é, informar que melhora
a legibilidade do código.
////
Uma boa prática de programação é escolher nomes que indiquem a função de 
uma variável, como por exemplo: `soma, ano, idade, media, dataNascimento, 
numero_filhos, nota1, nota2, notaFinal, salario,` etc. Também é uma prática 
bastante difundida iniciar os identificadores com letras minúsculas e usar 
letras maiúsculas ou sublinha para separar palavras. Por exemplo, para 
escolher um identificador para uma variável que deve armazenar a data de 
nascimento de uma pessoa, as duas opções citadas correspondem à 
`dataNascimento` e `data_nascimento`, respectivamente.
////
TODO - REV.18: Sugestão de melhoria para análise pelo autor 
Sugeriria fornecer outro exemplo ao invés de var e Var, simplesmente para evitar
confusões.
////
IMPORTANT: A linguagem C faz distinção entre letras maiúsculas e minúsculas, sendo 
assim, variáveis de nomes var e Var são consideradas como duas variáveis 
diferentes.
==== Tipos de dados primitivos
Vimos anteriormente que as variáveis podem armazenar valores de diversos 
tipos, tais como números inteiros, fracionários e um conjunto de caracteres. 
Os tipos de dados ou tipo de variáveis são representados de forma diferente 
em cada linguagem de programação, algumas dando suporte a mais tipos que 
outras. Embora haja certa variação de uma linguagem para outra, a maioria 
delas dá suporte a um grupo de tipos básicos, incorporados na própria 
linguagem, chamados de tipos primitivos. Em C há a possibilidade da criação, 
por parte do programador, de tipos particulares, denominados de tipos 
derivados. Estudaremos as formas de definirmos tipos derivados no Capítulo 5. 
Existem três tipos primitivos na linguagem C: números inteiros, números de 
ponto flutuante (números fracionários) e caracteres. Os números 
fracionários são chamados de números de ponto flutuante devido à forma como 
eles são armazenados no computador. Portanto, sempre que você ouvir o termo 
ponto flutuante, tenha em mente que o tipo de dados em questão diz respeito 
aos números fracionários. 
////
TODO - REV.19: Sugestão de melhoria para análise pelo autor 
Adiciona exemplo dos tipos mencionados.
////
Os tipos de dados primitivos em C estão descritos na tabela abaixo:
.Tipos primitivos da linguagem C
[width="90%",cols="^1m,^2,4",frame="topbot",options="header,footer"]
|======================
|Tipo|Tamanho (em bytes)|Função
| int|4|Armazenar um número inteiro.
| float|4|Armazenar números de ponto flutuante.
| double|8|Armazenar números de ponto flutuante com maior precisão.
| char|1|Armazenar um caractere.
|======================
Como as variáveis de tipos primitivos distintos são representadas na memória 
de formas diferentes, elas exigem uma quantidade de bytes distinta para seu 
armazenamento. Uma variável do tipo *int*, por exemplo, ocupa normalmente quatro 
bytes na memória, ao passo que uma variável do tipo *char* ocupa apenas 1 (um) 
byte. 
É importante salientar que o tipo *char* na linguagem C, diferentemente de 
outras linguagens, pode também armazenar números inteiros que requerem apenas 
um byte de memória. O que ocorre é que há uma correspondência entre um 
caractere e um número inteiro, conforme uma tabela padrão. Por exemplo, 
quando atribuímos a variáveis do tipo *char* valores como a, b e c, na verdade 
estamos atribuindo os valores inteiros 97, 98 e 99. Os números inteiros que 
correspondem aos caracteres estão todos listados em uma tabela padrão, 
conhecida como tabela ASCII. 
////
TODO - REV.20: Sugestão de melhoria para análise pelo autor 
Adiciona exemplo dos tipos mencionados.
////
O tipo int pode ainda ser qualificado de acordo com as seguintes palavras-chave:
short ou long:: se referem ao tamanho das variáveis;
signed ou unsigned:: indicam, respectivamente, se as variáveis do tipo *int* 
poderão ser positivas e negativas (com sinal) ou apenas positivas (sem sinal) .
A qualificação de tipo é realizada quando os qualificadores são antepostos 
aos tipos. Por exemplo, uma variável do tipo *unsigned long int* armazena 
inteiros positivos de tamanhos grandes, enquanto que uma variável do tipo 
*signed short int* armazena inteiros positivos e negativos de tamanhos menores.
A tabela a seguir ilustra os valores que normalmente podem ser armazenados nas 
variáveis do tipo *int* e diversas de suas variações.
.Intervalos de valores de tipos inteiros utilizados por grande parte dos compiladores de C.
[width="100%",cols="^2,^2,3",frame="topbot",options="header"]
|======================
|Tipo|Tamanho (em bytes)|Valores que podem ser armazenados
| int|4|-2^31^ a 2^31^ - 1
| short int|2|-2^15^ a 2^15^ - 1
| long int|4|-2^31^ a 2^31^ - 1
| unsigned int|4|0 a 2^32^ - 1
| unsigned short int|2|0 a 2^16^ - 1
| unsigned long int|4|0 a 2^32^ - 1
| signed char|1|-2^7^ a 2^7^ - 1
| unsigned char|1|0 a 2^8^ - 1
| long long int|8|-2^63^ a 2^63^ - 1
| unsigned long long int|8|0 a 2^64^ - 1
|======================
NOTE: Os tamanhos e valores presentes nas tabelas anteriores podem variar de 
compilador para compilador. Desse modo, eles servem apenas como um guia de 
referência para de norteá-lo na escolha dos tipos adequados aos programas que 
você desenvolverá. 
==== Declaração de variáveis
Cada variável utilizada na elaboração de um programa precisa ser definida 
com antecedência. Para isso, o programador precisa definir o identificador da 
variável e o seu tipo por meio do que chamamos de declaração de variáveis. 
Sua forma geral é a seguinte:
 tipo_da_variável identificador;
O exemplo a seguir declara, na linguagem C, as variáveis x e y como sendo do 
tipo *int*.
 int x, y;
////
TODO - REV.21: Sugestão de melhoria para análise pelo autor 
Não seria interessante ilustrar a explicação abaixo com uma gravura?
////
A declaração de variáveis, além de estabelecer uma interpretação sobre os 
bits armazenados na memória, também é responsável por alocar espaço para 
armazenamento desses
bits. No exemplo anterior, a declaração das variáveis `x` 
e `y` resulta na alocação de 4 bytes (provavelmente) para cada uma delas, bem 
como determina que os bits a serem armazenados no espaços alocados deverão 
ser interpretados como números inteiros. Seguem abaixo alguns exemplos de 
declarações de variáveis:
 int idade;
 int numeroFilhos;
 int dia, mes, ano;
 float altura;
 float nota, media;
Os tipos das variáveis tem uma relação muito próxima com a função que 
elas exercem em um programa. Caso precisemos armazenar e realizar cálculos 
sobre a idade de alguém, deveremos declarar a variável `idade` como *int*, visto 
que a idade corresponde a um número inteiro positivo. Do mesmo modo, como 
sabemos que a altura de uma pessoa é um número fracionário (ex.: 1,80 cm), 
devemos declarar a variável `altura` como sendo do tipo *float*. Variáveis do 
mesmo tipo podem ser declaradas em uma mesma linha, sendo separadas por 
vírgulas, como na declaração das variáveis `dia`, `mes` e `ano` do exemplo 
anterior. Já variáveis de tipos diferentes devem ser declaradas 
obrigatoriamente de forma separada.
Um programa elaborado com base no paradigma estruturado pode ser visto como uma 
sequência de transições de estado do início até o fim de sua execução. 
Se pudéssemos tirar uma "foto" da execução de um programa em determinado 
momento, o que observaríamos seria o conjunto de suas variáveis e os valores 
nelas armazenados no momento, isto é, o estado do programa. Se os programas 
podem mudar de estado, então deve existir um comando nas linguagens de 
programação que permitam alterar o conteúdo de uma variável. Tal comando é 
denominado de *atribuição*, e o exemplo a seguir mostra como ele é utilizado 
em pseudocódigo.
////
TODO - REV.22: Sugestão de melhoria para análise pelo autor 
Note que agora utilizamos de explicações da linguagem algoritmica para fazer
a correlação com a linguagem de programação C. Este talvez fosse um recurso mais
didático.
////
 idade ← 18
Essa instrução deve ser lida como "a variável `idade` recebe o valor 18 
(dezoito)". Em C, o comando correspondente é:
 idade = 18;
NOTE: Podemos utilizar o comando de atribuição no momento da declaração de uma 
variável. Esse procedimento é chamado de inicialização de variáveis.
// FIXME Equação x pertence aos reais
Embora C e outras linguagens de programação utilizem o operador aritmético 
da igualdade para representar a atribuição, as semânticas de ambos não 
podem ser confundidas. Por exemplo, em matemática a equação 
`x=x+1`, onde `x pertece aos Reais`, nunca 
pode ser satisfeita, visto que um número real não poder ser igual a ele 
próprio mais um. Já em programação, o comando `x = x + 1` quer dizer que a 
variável `x` irá receber o conteúdo armazenado nela própria mais um. Supondo 
que `x` possuía conteúdo igual a 10 antes da execução da atribuição em 
questão, após sua execução `x` seria igual a 11 (`x = 10 + 1 = 11`). A tabela 
abaixo ilustra o cenário apresentado.
[width="50%",cols="^1m,^1m",frame="topbot",options="header"]
|======================
|Comando |Valor atual de x
| `int x;` |Indefinido
| `x = 10;` |10
| `x = x + 1;` |11
|======================
Essa forma de atribuição é um artifício bastante empregado na 
programação, sendo denominado de *incremento*.
==== Constantes simbólicas
(((Constantes)))
Muitas vezes declaramos algumas variáveis que não devem ser modificadas 
durante a execução de um programa. É o caso das variáveis abaixo:
 PI = 3.14159;
 ACELERACAO_GRAVIDADE = 9.8;
 VELOCIDADE_LUZ = 300000;
(((Constantes simbólicas)))
Não faz sentido alterar o valor de uma variável que representa a aceleração 
da gravidade, por exemplo, pois o valor da constante gravitacional, como seu 
próprio nome já diz, permanece sempre o mesmo. Para casos como esse é 
preferível que usemos *constantes simbólicas* no lugar de variáveis. A 
linguagem C permite que um identificador seja associado a uma constante 
através da diretiva `#define`, cuja sintaxe é descrita abaixo: 
 #define nome_constante valor_constante;
Dessa forma, a definição da constante `PI` mencionada acima poderia ser 
realizada através da linha de código:
 #define PI = 3.14159;
Quando o programa que contém essa instrução é compilado, o compilador 
substitui todas as ocorrências de `PI` pelo seu valor associado. 
Outra utilidade proveniente da definição de constantes diz respeito à 
facilidade de modificação de um programa. Imagine que você desenvolveu 
um programa para o registro contábil de uma locadora de veículos e que em 
vários trechos de código você usou o valor da diária de locação para 
realizar diversos cálculos. Suponha agora que o dono da locadora aumentou o 
valor da diária de locação e que você foi chamado para modificar o programa 
a fim de adequá-lo ao novo valor. Dessa forma, você terá que alterar cada 
ocorrência contendo o valor antigo e o seu trabalho será proporcional ao 
número de ocorrências desse valor. Utilizando constantes simbólicas, você 
precisaria apenas alterar a definição da constante, conforme sugere o quadro 
abaixo:
 #define VALOR_LOCACAO 80.0
 #define VALOR_LOCACAO 100.0
Apesar das regras para definição dos nomes das constantes simbólicas serem 
as mesmas daquelas utilizadas para identificadores, é uma boa prática de 
programação defini-las com letras maiúsculas, separando as palavras que as 
compõem, se houverem, pelo caractere sublinha (`_`).
=== Comentários e indentação
À medida que um programa cresce, ele vai ficando cada vez mais difícil de ser 
lido e consequentemente de ser entendido. É comum um programador ter grandes 
dificuldades para compreender seus próprios programas após passar alguns dias 
sem trabalhar em suas linhas de código. Por isso, algumas medidas devem ser 
tomadas no sentido de preparar um código-fonte legível. Existem várias 
formas de aprimorar a legibilidade de um programa, contudo nos restringiremos 
aos comentários e à indentação. 
Explicar o código-fonte em linguagem natural é uma estratégia óbvia para 
facilitar sua compreensão. Esse é o papel dos comentários em uma linguagem 
de programação. Em C, qualquer sequência de caracteres localizada entre os 
delimitadores `/*` e `*/` é um comentário. Por exemplo:
 z = x + y; /* z é o resultado da soma entre x e y. */
A explicação da linha de código acima, embora desnecessária devido à 
simplicidade da instrução, é um comentário na linguagem C. Outras 
linguagens podem usar delimitadores distintos para expressar os comentários. A 
linguagem C ainda possui o delimitador //, muitas vezes chamado de delimitador 
de comentário de linha. Os caracteres colocados à sua frente e na mesma linha 
em que ele se encontra são considerados comentários e ignorados pelo 
compilador. Exemplo de sua utilização:
 int idade; // Variável inteira para representar
 // a idade de uma pessoa.
Perceba que para comentar mais de uma linha com o delimitador //, precisamos 
utilizá-lo em cada linha que se deseja comentar. Dessa maneira, quando se 
deseja comentar mais de uma linha é mais adequado o uso dos delimitadores 
`/*` e `*/`.
Outra forma de tornar um programa mais legível é organizar as instruções de 
modo a refletir a hierarquia entre elas. Por exemplo:
[source, c]
-----------------
#include <stdio.h>
/* Código não-indentado */
int main() {
int x, y, z;
x = 10;
y = 2;
z = x / y;
if (x > 5) {
printf("x é maior que cinco.");
}
return 0;
}
-----------------
(((indentação)))
Repare que a declaração de variáveis, os comandos de atribuição e os 
comandos `if` (apresentado no Capítulo 3) e `return` estão todos dentro da 
função `main`. Dizemos então que eles são hierarquicamente subordinados à 
função referida. Da mesma forma, o comando `printf` está subordinado ao 
comando `if`. Uma maneira de destacar a hierarquização das instruções é 
alinhar os
comandos com o mesmo nível de hierarquia (inserindo espaços nas 
instruções de nível inferior), o que chamamos de *indentação*. Para que 
você visualize o resultado do processo de indentação, considere o código do 
exemplo anterior depois de corretamente indentado:
[source, c]
-----------------
#include <stdio.h>
/* Código indentado */
int main() {
 int x, y, z;
 x = 10;
 y = 2;
 z = x / y;
 if (x > 5) {
 printf("x é maior que cinco.");
 }
 return 0;
}
-----------------
=== Matemática Básica
O computador foi criado com o intuito inicial de realizar contas. Portanto, é 
importante que saibamos como instruí-lo a computar as operações aritméticas 
básicas. E essa não vai ser uma tarefa difícil, já que as expressões 
aritméticas em programação são bastante semelhantes às expressões 
utilizadas na matemática. Em C, os operadores matemáticos utilizados são os 
seguintes:
.Operadores aritméticos
[width="50%",cols="^1,^1",frame="topbot",options="header"]
|======================
|Operador |Operação
| `+` |Adição
| `-` |Subtração
| `*` |Multiplicação
| `/` |Divisão
| `%` |Resto da divisão
|======================
A utilização dos operadores em C ocorrem da forma com a qual estamos 
acostumados: colocamos um operador entre dois operandos e vamos construindo as 
expressões. À medida que as expressões vão ficando mais complexas, podemos 
utilizar os parênteses para agrupar operadores e operandos. Diferentemente do 
que ocorre na matemática, em C não se utilizam colchetes e chaves para o 
agrupamento de expressões que já estão entre parênteses. Estes devem ser os 
substitutos dos primeiros quando houver necessidade. Por exemplo, a expressão 
matemática `[(x+y)-(a+b)]÷2`, em C se tornaria: 
 ((x+y)-(a+b))/2
Veja alguns exemplos de como os operadores aritméticos devem ser usados em C 
(os resultados são apresentados ao lado de cada operação):
////
TODO - REV.23: Sugestão de melhoria para análise pelo autor 
Recomendaria colocar comentários mais representativos. Além de facilitar
o entendimento dos exemplos, damos o exemplo em praticar o que estamos
dando como boa prática.
////
[source, c]
-----------------
 x = 4 * 5; // 20
 x = x / 2; // 10
 y = x % 4; // 2
 z = x * y – 5; // 15 
 z = x * (y – 5); // -30
 z = ((2 + 3) * 4 – 2)/2; // 9
-----------------
A precedência dos operadores aritméticos, isto é, a ordem em que eles são 
avaliados, pode ser alterada do mesmo modo que o fazemos quando tralhamos com 
expressões na matemática: utilizamos os parênteses para que algumas 
operações sejam realizadas antes que outras. É o que ocorre na expressão 
acima na expressão `z=x*(y-5)`. Caso os parênteses fossem omitidosfootnote::[Expressão resultante: `z=x*y-5`], a primeira 
operação a ser realizada seria a que multiplica `x` por `y`, depois, do seu 
resultado seria subtraído cinco. Com a inserção dos parênteses, ocorre 
primeiro a subtração para depois ser realizada a multiplicação. 
A linguagem C possui ainda operadores especiais que resultam da combinação de 
operadores aritméticos com operadores de atribuição. São eles:
////
TODO - REV.24: Sugestão de melhoria para análise pelo autor 
Recomendaria adicionar exemplos das operações apresentadas abaixo.
////
.Operadores aritméticos de atribuição e operadores de incremento.
[width="60%",cols="^1m,^2m",frame="topbot",options="header,footer"]
|======================
|Operador |Operação equivalente
| `x += y` | `x = x + y`
| `x -= y` | `x = x - y`
| `x *= y` | `x = x * y`
| `x /= y` | `x = x / y`
| `x %= y` | `x = x % y`
| `x++` | `x = x + 1`
| `++x` | `x = x + 1`
| `x--` | `x = x - 1`
| `--x` | `x = x - 1`
|======================
(((atribuição)))(((incremento)))
Os primeiros cinco operadores são denominados de *operadores aritméticos de 
atribuição*, ao passo que os quatro últimos são chamados de *operadores de 
incremento*.
Aqui cabe destacar as diferenças entre os operadores de incremento quanto à 
localização dos operadores aritméticos. Considere os exemplos a seguir:
[source, c]
-----------------
 x = 0;
 y = 6;
 z = 2;
 (a) x = y / ++z; // incremento antes
 // y = 6, z = 3, x = 2
-----------------
[source, c]
-----------------
 x = 0;
 y = 6;
 z = 2;
 (b) x = y / z++; // incremento depois
 // y = 6, z = 3, x = 3
-----------------
Nos exemplos apresentados, temos dois algoritmos que se diferenciam apenas pela 
utilização dos operadores de incremento de adição. Na 
expressão (a), a variável `y` é dividida por `++z`, enquanto que na expressão 
(b) ela é dividida por `z++`. A diferença é sutil, mas é determinante no 
resultado da expressão. No primeiro caso, `z` é incrementada antes da divisão, 
logo `x=6÷(2 + 1)=6÷3=2`. Na expressão (b), z é incrementado depois da divisão, 
o que resulta em `x=6÷2=3`. Repare que em ambos os casos o valor de `z` é 
incrementado, de modo que após as instruções (a) e (b) o valor de `z` é igual a 3.
=== Entrada e saída de dados
Imagine que você desenvolveu um programa para controlar suas finanças 
pessoais e com ele intenciona conter seus gastos e ainda guardar uma parte do 
que ganha na poupança. Esse programa necessita de interação? Como você 
informará suas receitas e despesas? Como ele apresentará o resultado dos seus 
cálculos com a finalidade de auxiliá-lo no controle de suas finanças? 
As respostas de todas essas perguntas convergem para a seguinte conclusão: um 
programa de computador é praticamente inútil se não apresentar algum tipo de 
interação com o usuário. No cenário anterior, por exemplo, você precisa 
informar ao programa quais são as suas receitas e despesas. Além disso, é 
necessário que ele o deixe a par dos resultados dos seus cálculos, caso 
contrário ele não terá serventia alguma. 
(((stdio)))
Os mecanismos que as linguagens de programação oferecem para interação com 
o usuário estão presentes em suas bibliotecas de entrada e saída. Em C, as 
funções responsáveis pelas operações básicas de entrada e saída se 
encontram na biblioteca *stdio*, que é utilizada por meio da diretiva:
 #include <stdio.h>
////
TODO - REV.25: Sugestão de melhoria para análise pelo autor 
Rever linhas 1073 e 1074.
////
 
Vimos não seção 2.6 uma forma de exibir na tela uma sequência de caracteres 
através da função `printf()`, que, além de imprimir caracteres, também é 
capaz de exibir o conteúdo de variáveis de diversos tipos. Os detalhes de 
sua utilização, bem como uma função similar para entrada de dados são 
apresentados não nas seções posteriores.
==== Função printf()
A função de saída `printf()` permite que dados sejam escritos na saída 
padrão, que normalmente é a tela do computador. Uma chamada da função 
`printf` tem o seguinte formato:
 int printf(string_de_formato, arg1, arg2, ..., argn)
Isso quer dizer que a função `printf` irá escrever na saída padrão os 
argumentos `arg1,arg2,...,argn` de acordo com o que está especificado no 
parâmetro `string_de_formato`. Além disso, o tipo *int* indica que a função 
retorna um número inteiro, que neste caso corresponde ao número de caracteres 
impressos. O exemplo a seguir ilustra a utilização da função `printf()`:
[source, c]
-------------
#include <stdio.h>
int main() {
 int idade;
 float altura; 
 idade = 18;
 altura = 1.90;
 printf("Tenho %d anos e %.2f de altura.", idade, altura);
 return 0;
}
-------------
Após a execução do código acima será exibida na tela a seguinte frase:
 Tenho 18 anos e 1.90 de altura.
Os caracteres `%d` e `%.2f` são denominados de especificadores de formato e têm o 
objetivo de definir o formato das variáveis que serão escritas na saída 
padrão. De outro modo, podemos entendê-los como "guardadores de lugar" 
para as variáveis a serem exibidas. No exemplo acima, no lugar do `%d` será 
colocada a primeira variável passada por parâmetro
(`idade`) e no lugar do `%.2f` 
a segunda variável (`altura`). Além disso, elas deverão ser dos tipos `int` e 
`float`, respectivamente. O ponto seguido de um número antes do código de 
formato indica a quantidade de casas decimais a serem exibidas (quando 
aplicados a variáveis do tipo ponto-flutuante) e são denominados de 
especificadores de precisão. No exemplo anterior eles foram os responsáveis 
pela exibição da variável `altura` com duas casas decimais.
A tabela abaixo lista os especificadores de formato mais comuns utilizados na 
função `printf()`. 
////
TODO - REV.26: Sugestão de melhoria para análise pelo autor 
Recomendaria adicionar exemplos.
////
.Especificadores de formatos mais utilizados na função printf()
[width="65%",cols="^1m,2",frame="topbot",options="header"]
|======================
|Código |Formato
| %d ou %i | Inteiro (int) decimal
| %ld ou %li | Inteiro (long int) decimal
| %u | Inteiro sem sinal
| %c | Caractere
| %s | Cadeira de caracteres
| %f | Número de ponto-flutuante 
|======================
==== Função scanf()
A função de entrada `scanf()` possibilita a leitura de dados da entrada 
padrão, ou seja, do teclado. O que ela faz é interromper a execução do 
programa até que o usuário digite algo e depois pressione a tecla Enter. 
Depois que o programa retoma sua execução, o conteúdo digitado é armazenado 
em uma ou mais variáveis. Uma chamada da função `scanf` tem o seguinte formato:
 int scanf(string_de_formato, arg1, arg2, ..., argn)
O parâmetro `string_de_formato` especifica os tipos de dados que serão lidos e 
os parâmetros `arg, arg2, ..., argn` correspondem aos endereços das variáveis 
nas quais serão armazenados os valores digitados pelo usuário. A função 
`scanf()` retorna um valor inteiro que indica o número de variáveis que tiveram 
valores atribuídos, sendo utilizado para verificar algum problema na entrada 
de dados. O exemplo a seguir ilustra a utilização da função `scanf()`:
[source, c]
-----------------
#include <stdio.h>
int main() {
 int idade;
 float altura; 
 printf("Informe sua idade: ");
 scanf("%d", &idade)
 printf("Informe sua altura: ");
 scanf("%f", &altura);
 printf("\nVocê tem %d anos e %.2f de altura.", idade, altura);
 return 0;
}
-----------------
Ao contrário do exemplo da seção anterior, os dados a serem exibidos não 
estão pré-determinados, isto é, as variáveis não possuem valores a priori. 
As atribuições apenas ocorrem quando o usuário entra com valores via 
teclado. No exemplo, depois que a sequência de caracteres `"Informe sua 
idade: "` é exibida, a execução do programa é interrompida até que o 
usuário digite um valor. Quando isso ocorre, ele é armazenado no endereço da 
variável `idade`, obtido quando ela é precedida pelo caractere `&`. Por 
conseguinte, o `printf()` ao final do código irá exibir os dados informados 
pelo usuário e não os dados pré-determinados pelo programador. 
IMPORTANT: A tecla Enter também possui um caractere que a representa, a saber, o 
caractere especial ‘\n’. Portanto, quando o ’\n’ é escrito na saída 
padrão, o efeito gerado é o mesmo da digitação da tecla Enter.
A função `scanf()` também pode ler numa mesma linha diversos dados, 
armazenando-os em diferentes variáveis. As leituras do código anterior, por 
exemplo, podem ser reescritas da seguinte forma:
[source, c]
-------------
printf("Informe sua idade e sua altura:");
scanf("%d %.2f", &idade)
-------------
Para que esse código funcione como desejado, o usuário precisa digitar um 
número inteiro seguido de um espaço e depois um número de ponto-flutuante. O 
espaço é requerido porque ele é utilizado na especificação do formato 
(entre o `%d` e o `%.2f` há um espaço). Assim como `printf()`, a função `scanf()` 
também possui uma lista de especificadores de formato. Os mais utilizados 
seguem abaixo:
.Especificadores de formatos mais utilizados da função scanf()
[width="75%",cols="^1m,4",frame="topbot",options="header,footer"]
|======================
|Código |Significado
| `%d ou %i` | Leitura de um inteiro (int) decimal
| `%ld ou %li` | Leitura deum inteiro (long int) decimal
| `%u` | Leitura de um inteiro sem sinal
| `%c` | Leitura de um único caractere
| `%s` | Leitura de uma cadeira de caracteres
| `%f` | Leitura de um número de ponto-flutuante 
|======================
////
TODO - REV.27: Sugestão de melhoria para análise pelo autor 
Precisamos adicionar exercícios, tanto comentados como propostos. 
////
=== Recapitulando
Neste capítulo você pôde conhecer um pouco mais sobre o funcionamento dos computadores, mais especificamente sobre a forma com a qual eles decodificam as instruções que lhes são passadas. Vimos, portanto, que as linguagens de programação podem ser classificadas em linguagens de alto nível ou baixo nível, de acordo com sua proximidade em relação à linguagem que os computadores podem compreender: o código de máquina.
Como programar em linguagem de baixo nível é uma tarefa árdua, foram criadas as linguagens de alto nível para facilitar a vida dos programadores. Desse modo, surgiu a necessidade de um software que fosse capaz de realizar a tradução de programas escritos em linguagem de alto nível para programas equivalente em código de máquina. Esses softwares são os tradutores e interpretadores. 
Aprendemos que a maneira de pensar de um programador na resolução de um problema está relacionada com um paradigma de programação. Se um programador utilizar a linguagem C, por exemplo, ele vai raciocinar segundo os paradigmas imperativo e estruturado.
Falando em linguagem C, conhecemos a estrutura de um programa escrito nessa linguagem, seus tipos primitivos, como podem ser elaborados nomes para as variáveis e como estas podem ser declaradas. Enfim, você deu os primeiros passos para a elaboração do seu primeiro programa.
No próximo capítulo você vai estudar as estruturas de controle em C. Elas simplesmente são as instruções mais importantes para o desenvolvimento da lógica de programação. Por isso, estude atentamente o próximo capítulo e tente elaborar o maior número de programas possível para consolidar o aprendizado.
=== Exercícios Propostos
1. Diferencie linguagem de programação de alto nível de linguagem de programação de baixo nível. Dê exemplos de linguagens que se enquadram em ambos os tipos.
2. Qual é o principal objetivo dos tradutores e interpretadores?
3. Defina montador e compilador, enfatizando suas diferenças.
4. Explique como funcionam os interpretadores.
5. Quais as vantagens da compilação em relação à interpretação?
6. O que é um paradigma de programação? Cite exemplos.
7. Quais dos seguintes itens não podem ser utilizados como identificadores na linguagem C? Explique por quê?
+
--
a. `3x`
b. `Inflação`
c. `COMPUTACAO`
d. `nota_1`
e. `nota 2`
f. `prof.`
g. `$4`
h. `RG`
i. `main`
j. `return`
--
8. Descreva os tipos primitivos de C, destacando os valores que eles podem armazenar.
9. Qual a diferença entre os operadores prefixo e sufixo de incremento?
10. Qual é valor de `(x1 + x2)` após a execução dos grupos de comandos abaixo:
+
--
.. `y = 6;`
.. `z = 8;`
.. `c = 2;`
.. `x1 = ((y * z) – z)/c;`
.. `x2 = (z / 2)/ y++;`
--
11. Considerando as atribuições `x = 20` e `y = 2`, calcule o resultado de cada uma das expressões abaixo:
+
--
a. `(x-- + x * (x % y))` 
b. `(x-- + x * (x % y))`
c. `(x-- + x * (x % 3))`
d. `(--x + x * (x % 3))`
e. `(--x + x * (x % x))`
--
12. Faça um programa em C que solicite ao usuário que digite o ano de seu nascimento, armazene o valor digitado em uma variável e em seguida imprima na saída padrão a sua idade.
// Sempre termine os arquivos com uma linha em branco.
introducao-a-programacao-livro-1.0.0/livro/capitulos/novo-capitulo.asc
== Novo capítulo
.Objetivos do capítulo
____________________
Ao final deste capítulo você deverá ser capaz de:
*
objetivo 1
* objetivo 2
* objetivo N
____________________
Neste lugar você deve apresentar o conteúdo em forma de diálogo.
NOTE: Para começar a escrever um novo capítulo, copie este arquivo e 
salve com outro nome (não utilize espaço no nome do arquivo). Em seguida,
atualize o arquivo *livro.asc* para incluir o novo arquivo criado. 
Consulte o manual.
=== Minha primeira seção
Texto da sua seção.
==== Exemplo de subseção
Texto da subseção.
=== Minha segunda seção
Texto da sua seção.
=== Recapitulando
Revisão do que foi aprendido.
Reserve o último parágrafo para realizar uma *ponte* para o próximo capítulo.
=== Atividades
. Texto da atividade.
. Texto da atividade.
. Texto da atividade.
CAUTION: *Sempre termine os arquivos com uma linha em branco*, caso 
contrário você poderá encontrar erros inesperados.
introducao-a-programacao-livro-1.0.0/livro/capitulos/prefacio.asc
[[prefacio]]
[preface]
== Prefácio
Este livro é destinado a alunos de cursos como Ciência da Computação, Sistemas de Informação, Engenharia da Computação e, sobretudo, Licenciatura em Computação. Ele tem o objetivo de apresentar os principais conceitos da programação de computadores, de modo que sua utilização é mais adequado a disciplinas introdutórias como a de Introdução à Programação. De forma alguma o presente livro tem a pretensão de cobrir todos os assuntos relacionados à área de programação. Sua principal finalidade é a de servir como guia para os alunos que estão dando os primeiros passos nessa área que é tão importante para a ciência da computação. 
A disciplina de Introdução à Programação é a primeira de uma sequência de disciplinas que têm o objetivo de tornar os alunos capazes dominar os fundamentos e as técnicas relacionadas à programação de computadores. Durante o curso de Licenciatura em Computação, especificamente, os alunos terão a chance de conhecer em detalhes algumas das linguagens de programação mais utilizadas atualmente e estarão habilitados a ministrar cursos de programação para diversos públicos.
Mais importante do que conhecer as peculiaridades das linguagens de programação é aprender como funciona a lógica aplicada na elaboração de soluções desenvolvidas a partir de algoritmos computacionais. Sendo assim, o principal objetivo deste livro é ensiná-los a resolver problemas com base nos comandos e mecanismos presentes nas linguagens de programação, desenvolvendo assim o que chamamos de lógica de programação. No decorrer do livro, o leitor aprenderá gradativamente a dar instruções ao computador através de programas que ele próprio será capaz de criar. Para isso, conhecerá a linguagem de programação C, uma das mais utilizadas e mais importantes linguagens na área de Ciência da Computação.
No Capítulo 1 será abordado o conceito de algoritmo, e suas principais formas de representação serão apresentadas. No Capítulo 2, descrevemos todo o processo de tradução de um programa escrito em linguagem de alto nível para um programa equivalente em código de máquina, isto é, a linguagem que os computadores conhecem. Além disso, será apresentado ao leitor a estrutura de um programa na linguagem C, o que o habilitará o leitor a desenvolver seu primeiro programa. O Capítulo 3 consiste no conteúdo do livro que mais desenvolve a lógica de programação. É nele que se encontram as principais instruções de uma linguagem de programação: as estruturas de controle. No Capítulo 4 será apresentado o conceito de arranjos e, por fim, no Capítulo 5, explicaremos como programas complexos podem ser divididos em programas menores, mais fáceis de serem solucionados, através da utilização das funções.
Recomendamos ao aluno, iniciante na programação de computadores, que não se limite à leitura e ao conteúdo deste livro. Pesquise na internet outros materiais, leia outros livros e faça todos os exercícios propostos. Programação, assim como matemática, requer muito exercício, muita prática. Como mencionado anteriormente, a programação de computadores é uma das subáreas mais importantes da carreira que você escolheu seguir. Boa parte das disciplinas do seu curso depende do conhecimento adquirido em Introdução à Programação. Portanto, dedique o máximo que puder ao aprendizado de uma área que vai permiti-lo transformar sonhos em realidade.
=== Público alvo
O público alvo desse livro são os alunos de Licenciatura em Computação, na
modalidade a distância footnote::[Embora ele tenha sido feito para atender aos alunos
da Universidade Federal da Paraíba, o seu uso não se restringe a esta 
universidade, podendo ser adotado por outras universidades do sistema UAB.].
Ele foi concebido para ser utilizado numa disciplina de 'Introdução à Programação',
no primeiro semestre do curso.
[[como_estudar]]
=== Como você deve estudar cada capítulo
* Leia a visão geral do capítulo
* Estude os conteúdos das seções
* Realize as atividades no final do capítulo
* Verifique se você atingiu os objetivos do capítulo
.Na sala de aula do curso
* Tire dúvidas e discuta sobre as atividades do livro com outros integrantes do curso
* Leia materiais complementares eventualmente disponibilizados
* Realize as atividades propostas pelo professor da disciplina
[[caixas_de_dialogo]]
=== Caixas de diálogo
Nesta seção apresentamos as caixas de diálogo que poderão ser utilizadas durante o texto.
Confira os significados delas.
[NOTE]
====
Esta caixa é utilizada para realizar alguma reflexão.
====
[TIP]
====
Esta caixa é utilizada quando desejamos remeter a materiais complementares.
====
[IMPORTANT]
====
Esta caixa é utilizada para chamar atenção sobre algo importante.
====
[CAUTION]
====
Esta caixa é utilizada para alertar sobre algo que exige cautela.
====
[WARNING]
====
Esta caixa é utilizada para alertar sobre algo potencialmente perigoso.
====
Os significados das caixas são apenas uma referência, podendo ser adaptados 
conforme as intenções dos autores.
// TODO: inclusão de vídeos
=== Compreendendo as referências
As referências são apresentadas conforme o elemento que está sendo referenciado:
Referências a capítulos:: <<prefacio>>
Referências a seções:: <<como_estudar>>, <<caixas_de_dialogo>>.
Referências a imagens e tabelas:: <<fig_issue_contribuicao>> <<tab_metodos_contribuicao_livro>>
NOTE: Na *versão impressa*, o número que aparece entre chaves ``[ ]'' corresponde
ao número da página onde está o conteúdo referenciado. Nas *versões digitais*
do livro você poderá clicar no link da referência.
=== Códigos e comandos
Os códigos ou comandos são apresentados com a seguinte formação:
 cc -S main.c teste.c
No exemplo a seguir, temos outra apresentação de código fonte. Desta vez de um 
arquivo `main.c`, que se encontra dentro do diretório `code/estruturas-de-controle`. 
O diretório `estruturas-de-controle` faz referência ao capítulo onde o código será apresentado.
.Código fonte
{gitrepo}/blob/master/livro/capitulos/code/estruturas-de-controle/for_cont.c[code/estruturas-de-controle/for_cont.c]
[source, c]
.Exemplo do comando for
----
include::code/estruturas-de-controle/for_cont.c[]
----
[[codigo_fonte]]
=== Baixando os códigos fontes
Existem duas formas de acessar os códigos fontes contidos neste livro.
Acesso on-line individual:: Você pode acessar individualmente os arquivos deste 
livro pelo endereço: {gitrepo}/tree/master/livro/capitulos/code.
Baixando todos os códigos:: 
Você também pode baixar o código fonte do livro
inteiro, que contém todos os códigos mencionados no livro. Existem duas formas
de baixar o código inteiro, através de um arquivo zip ou clonando o repositório.
Arquivo zip;; {gitrepo}/archive/master.zip. Depois de baixar o arquivo, descompacte-o. 
Clonando o repositório;; Use o comando: git clone {gitrepo}
NOTE: Independente do método utilizado para acessar os arquivos, os códigos
fontes estão organizados por capítulos no diretório `livro/capitulos/code`.
WARNING: Os códigos acessados por estes métodos são referentes à versão mais 
nova do livro (em produção). É possível que eles sejam diferentes da versão 
do livro que você esteja lendo.
=== Contribuindo com o livro
Você pode contribuir com a atualização e correção deste livro. A tabela a seguir
resume os métodos de contribuições disponíveis:
[[tab_metodos_contribuicao_livro]]
.Métodos para contribuição do livro
[width="100%",cols="1.^,2.^a,4.^",frame="topbot",options="header"]
|====
|Método de contribuição | Habilidades necessárias | Descrição
| Issue track 
| 
- Inscrição no site do github
- Preenchimento de um formulário
| Consiste em acessar o repositório do livro e submeter um erro, uma sugestão
ou uma crítica -- através da criação de um 'Issue'. Quando providências forem 
tomadas você será notificado disso.
| Submissão de correção
| 
- Realizar fork de projetos
- Atualizar texto do livro
- Realizar PullRequest
| Consiste em acessar os arquivos fontes do livro, realizar a correção desejada
e submetê-la para avaliação. Este processo é o mesmo utilizado na produção de
softwares livres.
|====
IMPORTANT: Quando for enviar sua contribuição lembre-se de informar qual a versão
e página do livro que está se referindo.
Contribuição através do Issue track:: Para contribuir com um erro, sugestão ou 
crítica através de um envio de uma mensagem acesse: {gitrepo}/issues/new 
+
[[fig_issue_contribuicao]]
.Exemplo de contribuição através do 'Issue track'
image::images/prefacio/issue.png[scaledwidth="70%"]
=== Baixando a edição mais nova deste livro
Nós estamos constantemente atualizando o nosso material didático. 
Todas as versões deste livro encontram-se disponíveis para download.
TIP: Acesse {gitrepo}/releases para baixar a versão mais nova deste livro.
// Sempre manter uma linha em branco no final
introducao-a-programacao-livro-1.0.0/livro/capitulos/registros.asc
== Registros
.Objetivos do capítulo
____________________
Ao final deste capítulo você deverá ser capaz de:
* Criar registros em C
* Analisar problemas e reconhecer os campos necessários para utilizar nos
registros
* Reconhecer campos identificadores de registros
* Criar e manipular listas de registros
____________________
Neste capítulos nós iremos estudar sobre Registros. Vamos conhecer a sua
utilidade e como declará-los em C. Depois vamos analisar diversas situações 
para aprender como é o processo de criação de um registro.
Serão apresentados alguns programas demonstrando a utilização dos registros e 
por fim, vamos aprender como compor registros a partir de outros registros.
Mas, o que são Registros?
[[sec_registro_definicao]]
=== Definição de registro
(((Registro)))
Definição de Registro::
Um Registro é um *tipo de dado* criado pelo usuário, através da *composição* 
de outros tipos de dados.
Nós utilizamos registros quando desejamos criar um tipo de dado para reunir
informações sobre o que desejamos representar. No registro, as informações são
organizadas em *campos*.
Uma analogia de registro pode ser vista quando preenchemos um formulário. Na <<tab_formulario_cliente>>
nós temos um exemplo de formulário para cadastrar *Clientes*. Os *campos* do formulário
são preenchidos com os dados do cliente que nos interessa registrar.
Sabendo as informações que desejamos registrar sobre um Cliente, nós podemos
esquematizar um registro, informando os tipos de dado de cada campo, conforme
descrito na <<tab_registro_cliente>>.
[[tab_formulario_cliente]]
.Formulário para cadastro de Cliente
|====
2+| Nome:
| Data de Nascimento: | Telefone para contato:
| CPF: | RG:
|====
[[tab_registro_cliente]]
.Representação de um registro Cliente
[width="80%",cols="1,2,1m",frame="topbot",options="header"]
|====
^| Novo tipo ^| Campo ^| Tipo do campo
.5+^.^s| Cliente
| Nome | Textual
| Data de Nascimento | Numérico
| Telefone para contato | Textual
| CPF ★ | Numérico
| RG | Numérico
|====
[TIP]
.Relembrando
====
Em nossos programas nós utilizamos *variávies* para manter as informações que
desejamos manipular. 
No momento da criação de uma variável precisamos especificar
o *tipo de dado* que desejamos que ela mantenha, através da *declaração da 
variável*. Vamos relembrar como declaramos variáveis:
.Em pseudocódigo
----
DECLARE nome_da_variavel: TEXTUAL
DECLARE var1,var2,var3: NUMÉRICO
----
.Em C
[source, c]
----
char[] nome_da_variavel;
double var1,var2,var3;
----
Quando especificamos mais de uma variável separadas por vírgula, assumimos que
todas elas possuem o mesmo tipo.
====
Na próxima seção, veremos como é a sintaxe para criação de registros, em
pseudocódigo e em C.
[IMPORTANT]
====
Embora, na prática, o uso de registro geralmente esteja associado a ((persistência)) 
de dados, sempre que mencionarmos *cadastrar* neste capítulo, estamos nos
referindo a manter os dados *em memória* para consulta posterior.
Em um sistema real, geralmente existe alguma forma de persistência dos dados
através de arquivos ou banco de dados -- caso contrário, os dados seriam perdidos.
====
=== Sintaxe para criação de registros
(((Tipo de dado))) (((Registro, sintaxe)))
Agora que temos o entendimento que um registro é um *tipo de dado*, vamos conhecer
a sintaxe para especificá-lo:
.Sintaxe em pseudocódigo para criar registro
[source, c]
----
REGISTRO nome_do_registro
	// Declarações dos campos
REGISTRO_FIM
----
.Sintaxe em C para criar registro
[source, c]
----
typedef struct {
	// Declarações dos campos
} nome_do_registro;
----
Quando criamos um novo tipo de dado precisamos nomeá-lo, para 
podermos referenciá-lo mais tarde. Nestas notações, `nome_do_registro` é
o nome do tipo de dado registro que será criado.
As `Declarações dos campos` definem os campos que *compõem* o registro. 
Esta *composição* ficará evidente nas próximas seções, onde iremos criar
e manipular vários registros.
Após a definição do novo tipo de dado registro, uma declaração de variável
com este tipo é realizada da forma usual:
.Declaração de variável do tipo criado em pseudocódigo
----
DECLARE variavel_nome: nome_do_registro 
----
.Declaração de variável do tipo criado em C
----
nome_do_registro variavel_nome;
----
=== Identificadores de registros
(((Campo Identificador)))
Antes de começarmos a especificar os registros, vamos primeiro entender a 
necessidade de identificar unicamente um 'registro'.
[IMPORTANT]
====
A palavra *registro* pode ser empregada em dois contextos diferentes.
Tipo de dado:: É o tipo de dado, conforme apresentado na definição de Registro.
Instância do registro:: Utilizando a analogia do formulário, equivaleria às 
fichas dos clientes. Cada ficha preenchida equivale a uma instância ou um
'registro' daquele tipo.
Por conveniência, sempre que utilizarmos a palavra 'registro' para indicar
instância do tipo, ela será grafada em 'itálico'.
====
Identificadores de 'registros' são campos nos registros que os *identificam e 
diferenciam* um 'registro' de qualquer outro.
No registro indicado na tabela <<tab_registro_cliente>>, como podemos 
*diferenciar* um cliente cadastrado de outro? Qual campo *identifica* um cliente?
Seria o nome? Data de Nascimento? Telefone? CPF ou RG? Neste caso, preferimos
utilizar o CPF, pois sabemos que duas pessoas diferentes não podem possuir o 
mesmo número de CPF.
Em nosso livro, os campos *identificadores* estão marcados com ★.
[NOTE]
====
Os identificadores costumam ser do tipo *inteiro*, pois a comparação
de inteiros é mais rápida do que a comparação textual.
====
Na próxima seção, faremos análises em algumas situações, caso você não tenha
compreendido o que são *campos identificadores* terá outra oportunidade.
[[sec_registro_analise]]
=== Análise para criação de Registros
Nesta seção mostramos o processo de criação de um Registro em diversas situações
diferentes.
Em cada situação apresentada faremos a seguinte *análise*:
// TODO glossário análise?
* Determinar o *tipo de registro* que vamos criar;
* Especificar quais serão os *campos* do registro, com os seus respectivos *tipos*;
* Indicar qual o *campo identificador* (★), caso exista;
* Apresentar o *código de criação* do Registro em Pseudocódigo e em C.
[[situacao_aluno]]
==== Situação do cálculo das notas de um aluno
Em uma disciplina onde os alunos possuem *duas notas*, e precisamos registrar e 
*calcular as médias* de todos eles, como seria um registro para representar 
esta situação?
Nome do Registro:: Aluno
Campos:: Obviamente vamos precisar guardar *duas notas* para cada aluno. 'Vamos 
precisar guardar a média também?' Não, uma vez que temos as duas notas 
registradas, sempre que desejarmos consultar a média poderemos calculá-las.
'O nome do aluno seria uma informação útil?' Sem dúvidas! Será importante
registrar o *nome* do aluno pois poderíamos imprimir uma lista com os nomes, notas
e médias de cada aluno. 'A matrícula do aluno é importante também?' Nós poderíamos
suprimir a matrícula do aluno, mas qual seria a consequência disso? Por exemplo,
na lista de notas poderia conter apenas os nomes, notas e médias. Mas o que 
aconteceria se tivéssemos dois alunos com o mesmo nome? Nós precisamos de um 
informação extra para *identificar* e diferenciar um aluno do outro. 
Com este intuito, vamos optar por registrar a *matrícula* também. 'O nome
da disciplina é importante?' Neste caso não, pois estamos nos limitando aos alunos 
e suas notas.
[width="80%",cols="^1s,^1m,^1m",frame="topbot",options="header"]
|====
^| Novo tipo ^| Campo ^| Tipo do campo
.4+^.^s| Aluno
| matricula ★ | Numérico
| nome | Textual
| nota1 | Numérico
| nota2 | Numérico
|====
.Registro em Pseudocódigo
----
include::code/registros/reg_aluno_pseudo.txt[]
----
[[ex_reg_aluno]]
[source, c]
.Registro em C: code/registros/reg_aluno.c
----
include::code/registros/reg_aluno.c[]
----
[NOTE]
Até agora você teve dificuldade para entender esta análise? Você compreendeu
a necessidade da utilização de `matrícula` como campo identificador? Concordou com
os tipos de dados utilizados para cada variável?
[[situacao_pessoa_imc]]
==== Situação do cálculo e consulta do IMC de uma pessoa
Nesta situação desejamos criar um sistema para *cadastrar* pessoas e em seguida
*consultar* o IMC delas.
Nome do Registro:: Pessoa
Campos:: Para o cálculo do IMC são necessárias duas informações: a *altura*
e o *peso*. Novamente, o *nome* da pessoa é uma informação relevante, pois
vamos imprimir o IMC calculado junto com o nome. 'Mas como realizar a consulta?
Após o cadastro realizado de algumas pessoas, qual o parâmetro de busca que 
iremos utilizar para encontrar a pessoa certa?' Poderíamos utilizar o nome 
completo da pessoa para encontrá-la. Mas digitar o nome todo é enfadonho. 
Poderíamos utilizar apenas o primeiro nome para busca, mas então teríamos
que apresentar um lista com todas as pessoas com aquele primeiro nome e selecionar
a pessoa correta entre elas.footnote:[A opção de utilizar o primeiro nome iria complicar o algorítmo da busca.] 
Se cadastrarmos o *CPF* da pessoa poderíamos consultá-la 
mais tarde informando apenas ele, simplificando a busca. Por último, como 
algumas tabelas do IMC apresentam os dados categorizados por *sexo*, vamos 
registrá-lo também. 
[width="80%",cols="^1s,^1m,^1m",frame="topbot",options="header"]
|====
^| Novo tipo ^| Campo ^| Tipo do campo
.5+^.^s| Pessoa
| nome | Textual
| peso | Numérico
| altura | Numérico
| cpf ★| Numérico
| sexo | Textual
|====
.Registro em Pseudocódigo
----
include::code/registros/reg_pessoa_pseudo.txt[]
----
[[ex_reg_pessoa]]
[source, c]
.Registro em C: code/registros/reg_pessoa.c
----
include::code/registros/reg_pessoa.c[]
----
[NOTE]
====
Mais uma vez, embora nosso problema não tenha indicado os campos que necessita,
fomos capazes de deduzir alguns. Aqui não há certo ou errado, cada um pode
realizar sua análise e chegar a resultados diferentes.
Você concorda com os tipos de dados apresentados aqui? Não achou estranho `cpf`
ser do tipo `long long`? Você declararia `sexo` com outro tipo, diferente 
de *char*?
cpf:: Declaramos ele como `long long` pois os tipos *long* e *int* não 
armazenam números na ordem de *11* dígitos.
sexo:: Optamos por utilizar o tipo *char* para simplificar comparações, caso
sejam necessárias. Poderíamos declará-lo do tipo *int*, fazendo uma correspondência
de valores: 1=Feminino e 2=Masculino. Ou ainda poderíamos utilizar *char[]* e
registrar o texto completo: `Feminino` ou `Masculino`.
====
[[situacao_ponto_matematica]]
==== Situação sobre manipulação de pontos no plano cartesiano
Nesta situação desejamos criar um sistema matemático para manipular pontos no 
plano cartesiano.
Nome do Registro:: Ponto
Campos:: Para registrar um ponto no plano cartesiano basta informar os 
valores de suas coordenadas (x,y).
[width="80%",cols="^1s,^1m,^1m",frame="topbot",options="header"]
|====
^| Novo tipo ^| Campo ^| Tipo do campo
.2+^.^s| Ponto
| x★ | Numérico
| y★ | Numérico
|====
.Registro em Pseudocódigo
----
include::code/registros/reg_ponto_matematica_pseudo.txt[]
----
[[ex_reg_ponto]]
[source, c]
.Registro em C: code/registros/reg_ponto.c
----
include::code/registros/reg_ponto.c[]
----
[NOTE]
====
Neste registro nós temos uma novidade: estamos utilizando dois campos como
*identificadores* simultaneamente. As vezes um único campo não é 
suficiente para identificar um 'registro'.
Neste caso, fica evidente que dois pontos são iguais se, e somente se, eles
possuírem os mesmo valores para o par (`x`,`y`).
E em relação ao tipo do dado? Você teria utilizado outro tipo, diferente 
de `int`, como `float` ou `double`? Mais uma vez, aqui não há certo ou errado,
nós optamos por `int` apenas por ser mais simples fornecer coordenadas em 
inteiro.
====
[[situacao_produto_supermercado]]
==== Situação sobre cadastro de produtos no supermercado
Nesta situação desejamos criar um sistema, para um supermercado, que cadastre 
produtos e seus preços.
Nome do Registro:: Produto
Campos:: Para registrar um produto vamos precisar do seu *nome* e o seu
*preço*. 'Mas como identificar um produto cadastrado?' Quando vamos no supermercado
e compramos alguma mercadoria no peso, o caixa do supermercado precisa fornecer 
um código para cadastrar o produto pesado. 
Geralmente ele utiliza uma tabela, onde há o nome do produto e o seu código. Para a nossa
aplicação vamos utilizar este mesmo *código* para identificar unicamente cada produto.
[width="80%",cols="^1s,^1m,^1m",frame="topbot",options="header"]
|====
^| Novo tipo ^| Campo ^| Tipo do campo
.3+^.^s| Produto
| nome | Textual
| preco | Numérico
| codigo ★| Numérico
|====
.Registro em Pseudocódigo
----
include::code/registros/reg_produto_supermercado_pseudo.txt[]
----
[[ex_reg_produto]]
[source, c]
.Registro em C: code/registros/reg_protudo.c
----
include::code/registros/reg_produto.c[]
----
[NOTE]
====
Neste registro tivemos contato com um provável campo *identificador* universal,
o `codigo`. Geralmente, quando nos deparamos com um campo código, ele será 
utilizado como o identificador.footnote:[A não ser quando o 
código for utilizado para designar uma senha.]
====
[[situacao_conta_bancaria]]
==== Situação sobre gerenciamento de contas bancárias
Nesta situação desejamos criar um sistema bancário para gerenciar clientes e 
suas contas bancárias.
Nomes dos Registros:: Cliente e Conta.
Campos:: O *nome* do cliente é uma informação relevante. O *CPF* poderá
ser utilizado para *diferenciar* clientes com o 
mesmo nome. 'Como identificar a conta do cliente?' Cada conta poderia ter um
*número de conta único*, que serviria para identificar a conta do cliente.
Cada conta terá um *saldo*, que será gerenciada pelo sistema.
Como cada cliente
pode possuir mais de uma conta bancária, junto com a conta deveremos registrar
qual cliente é o dono dela. Vamos utilizar o *CPF do cliente na conta* para 
identificar o seu *dono*.
[width="80%",cols="^1s,^1m,^1m",frame="topbot",options="header"]
|====
^| Novo tipo ^| Campo ^| Tipo do campo
.3+^.^s| Conta
| numero_da_conta ★| Numérico
| saldo | Numérico
| cpf_do_cliente | Numérico
|====
.Registro em Pseudocódigo
----
include::code/registros/reg_conta_pseudo.txt[]
----
[[ex_reg_conta]]
[source, c]
.Registro em C: code/registros/reg_conta.c
----
include::code/registros/reg_conta.c[]
----
[width="80%",cols="^1s,^1m,^1m",frame="topbot",options="header"]
|====
^| Novo tipo ^| Campo ^| Tipo do campo
.2+^.^s| Cliente
| nome | Textual
| cpf ★| Numérico
|====
.Registro em Pseudocódigo
----
include::code/registros/reg_cliente_pseudo.txt[]
----
[[ex_reg_cliente]]
[source, c]
.Registro em C: code/registros/reg_cliente.c
----
include::code/registros/reg_cliente.c[]
----
[NOTE]
====
Nesta situação temos outras novidades: a criação de *dois* Registros e utilização
de um campo para registrar o ((*relacionamento*)) entre os dois 
'registros'.footnote:[Relacionamento entre registros é um assunto que está
fora do escopo de uma disciplina de Introdução à Programação, você estudará 
este tópico numa disciplina de Banco de Dados.]
Percebam que `cpf` é o campo *identificador* de Cliente. Para identificar
que uma conta é de um determinado cliente, utilizamos o campo identificador
de cliente na conta.
Esta é uma estratégia muito importante para especificar *relacionamento*
entre registros, certifique-se que compreendeu-a antes de prosseguir.
====
=== Exemplos de utilização dos Registros
Nesta seção veremos alguns exemplos que demonstram a utilização de registros.
Nestes exemplos você irá aprender:
. Como atribuir e acessar valores aos campos do registro;
. Como atribuir valores de texto aos campos do registro;
. Como ler valores da entrada e atribui-los aos campos;
. Como declarar um arranjo de registros;
. Como acessar um campo num arranjo de registros.
==== Aluno
Exemplo de utilização do registro Aluno.
[source, c]
.code/registros/reg_aluno_exemplo.c
----
include::code/registros/reg_aluno_exemplo.c[]
----
<1> Como atribuir valores aos campos do registro.
<2> Como atribuir valores de texto aos campos do registro. Você já estudou a
função `strcpy` antes.
<3> Como acessar valores atribuídos aos campos do registro.
.Resultado ao simular a execução do programa
----
include::code/registros/reg_aluno_exemplo_simulacao.txt[]
----
==== Produto
Exemplo de utilização do registro Produto.
[source, c]
.code/registros/reg_produto_exemplo.c
----
include::code/registros/reg_produto_exemplo.c[]
----
<1> Como ler da entrada os valores e atribuí-los aos campos. Consulte a 
documentação de `scanf` (ou `fscanf`) para conhecer a sintaxe de leitura e 
conversão dos dados. Percebam a ausência de `&` antes do campo `nome`.
.Resultado ao simular a execução do programa
----
include::code/registros/reg_produto_exemplo_simulacao.txt[]
----
[WARNING]
====
Percebam que quando atribuímos um valor de texto aos campos do tipo *char[]*,
nós *suprimimos* o `&`. Isto correu com o campo `aluno.nome` em `strncpy` e `p.nome`
no `scanf`.
====
==== Pontos
Exemplo de utilização do registro Ponto com Arranjo.
[source, c]
.code/registros/reg_ponto_exemplo.c
----
include::code/registros/reg_ponto_exemplo.c[]
----
<1> Declaração de *constante* que definirá o tamanho do arranjo.
<2> Como declarar um arranjo de registros do tipo Ponto, com o tamanho definido 
pela constante `QUANTIDADE_DE_PONTOS`.
<3> Como acessar um campo em arranjo de registros. Cada posição, do arranjo
contém um registro. Você pode acessar as posições do arranjo com a mesma
sintaxe: `[índice]`.
.Resultado ao simular a execução do programa
----
include::code/registros/reg_ponto_exemplo_simulacao.txt[]
----
////
include::code/registros/reg_aluno_exemplo.txt[]
include::code/registros/reg_aluno_exemplo.c[]
include::code/registros/reg_pessoa_exemplo.txt[]
include::code/registros/reg_pessoa_exemplo.c[]
include::code/registros/reg_ponto_matematica_exemplo.txt[]
include::code/registros/reg_ponto_matematica_exemplo.c[]
include::code/registros/reg_produto_supermercado_exemplo.txt[]
include::code/registros/reg_produto_supermercado_exemplo.c[]
include::code/registros/reg_cliente_exemplo.txt[]
include::code/registros/reg_cliente_exemplo.c[]
include::code/registros/reg_conta_exemplo.txt[]
include::code/registros/reg_conta_exemplo.c[]
////
[[sec_registro_programas]]
=== Exercícios resolvidos
Nesta seção teremos a especificação de diversos problemas. Para cada um deles
iremos escrever um pseudocódigo que resolva o problema descrito, utilizando
o recurso de Registros. Em seguida, iremos implementar um programa em C.
==== Programa do cálculo de médias de alunos
Escrever um programa que cadastre o nome, a matrícula e duas notas de vários alunos.
Em seguida imprima a matrícula, o nome e a média de cada um deles.
.Pseudocódigo do programa
----
include::code/registros/reg_aluno_pseudo.txt[]
include::code/registros/calculo_das_medias_pseudo.txt[]
----
<1> Imprime a média calculada.
.Programa em C: code/registros/calculo_das_medias.c
[source,c]
----
include::code/registros/calculo_das_medias.c[]
----
.Resultado ao simular a execução do programa
----
include::code/registros/calculo_das_medias_simulacao.txt[]
----
==== Problema do cálculo e consulta do IMC de uma pessoa
Escrever um programa que cadastre o nome, a altura, o peso, o cpf e sexo
de algumas pessoas. Com os dados cadastrados, em seguida localizar uma pessoa
através do seu CPF e imprimir o seu IMC.
.Pseudocódigo do programa
----
include::code/registros/reg_pessoa_pseudo.txt[]
include::code/registros/imc_calculo_pseudo.txt[]
----
<1> O ler o campo *identificador* de Pessoa (CPF).
<2> Pesquisa pelo registro Pessoa identificado pelo CPF lido.
.Programa em C: code/registros/imc_calculo.c
[source,c]
----
include::code/registros/imc_calculo.c[]
----
<1> O ler o campo *identificador* de Pessoa (`cpf`).
<2> Pesquisa pelo registro Pessoa identificado pelo CPF lido.
.Resultado ao simular a execução do programa
----
include::code/registros/imc_calculo_simulacao.txt[]
----
==== Problema de pontos no plano cartesiano
Escrever um programa que leia 5 pontos. Em seguida imprima qual o ponto mais
próximo do primeiro ponto lido.
.Pseudocódigo do programa
----
include::code/registros/reg_ponto_matematica_pseudo.txt[]
include::code/registros/ponto_proximo_pseudo.txt[]
----
<1> `MAIOR_INTEIRO` representa o maior número inteiro que podemos armazenar numa
variável. Geralmente atribuímos *o maior* inteiro quando procuramos por
*um menor* valor. No código, comparamos `menor_distancia_ao_quadrado` com
`distancia_ao_quadrado` e salvamos o *menor* deles. Se executarmos isso 
sucessivamente, ao final, `menor_distancia_ao_quadrado` conterá o *menor* valor
comparado.footnote:[Caso tivéssemos inicializado a variável `menor_distancia_ao_quadrado`
com `0`, ao compará-lo com outro número, ele seria o *menor*, 
impossibilitando encontrar a *menor* distância.]
<2> Esta variável irá guardar a posição do ponto mais próximo. Ela é atualizada,
sempre que encontramos outro ponto com menor distância.
<3> Calculo para encontrar a distância entre dois pontos. Na realizadade, a 
distância entre os dois pontos seria a raiz de `distancia_ao_quadrado`. Mas
não há diferença em comparar a distância ao quadrado. Sabemos, por exemplo, 
que a *raiz* de `x` é *menor do que a raiz* de `y` se `x` for *menor* do 
que `y`.
.Programa em C: code/registros/ponto_proximo.c
[source,c]
----
include::code/registros/ponto_proximo.c[]
----
.Resultado ao simular a execução do programa
----
include::code/registros/ponto_proximo_simulacao.txt[]
----
==== Problema sobre cadastro de produtos no supermercado
Escrever um programa que cadastre vários produtos. Em seguida, imprima uma lista
com o código e nome da cada produto. Por último, consulte o preço de um produto
através de seu código.
.Pseudocódigo do programa
----
include::code/registros/reg_produto_supermercado_pseudo.txt[]
include::code/registros/prob_supermercado_pseudo.txt[]
----
.Programa em C: code/registros/supermercado.c
[source,c]
----
include::code/registros/supermercado.c[]
----
.Resultado ao simular a execução do programa
----
include::code/registros/supermercado_simulacao.txt[]
----
==== Problema sobre gerenciamento de contas bancárias
Escreva um programa que simule contas bancárias, com as seguintes especificações:
* Ao iniciar o programa vamos criar contas bancárias para três clientes.
** Cada conta terá o nome e o CPF do cliente associado a ela.
** No ato da criação da conta o cliente precisará fazer um depósito inicial.
* Após as contas serem criadas, o sistema deverá possibilitar realizações de 
saques ou depósitos nas contas.
** Sempre que uma operação de saque ou depósito seja realizada, o sistema deverá
imprimir o nome do titular e o saldo final da conta.
.Pseudocódigo do programa
----
include::code/registros/reg_conta_pseudo.txt[]
include::code/registros/reg_cliente_pseudo.txt[]
include::code/registros/prob_conta_bancaria_pseudo.txt[]
----
.Programa em C: code/registros/conta_bancaria.c
[source,c]
----
include::code/registros/conta_bancaria.c[]
----
.Resultado ao simular a execução do programa
----
include::code/registros/conta_bancaria_simulacao.txt[]
----
Após todos estes programas, agora vamos ver uma técnica que não utilizada ainda,
a inicialização de 'registro' com valores pré-definidos.
[[sec_registro_inicializacao]]
=== Inicializando registros
Quando declaramos uma variável do tipo registro, também podemos realizar uma
atribuição aos valores dos seus campos. O programa a seguir ilustra
esta atribuição.
WARNING: Para a atribuição poder ocorrer, os campos precisam ser inseridos
*na ordem que foram declarados* no tipo do registro.
.Programa em C: code/registros/reg_atribuicao.c
[source,c]
----
include::code/registros/reg_atribuicao.c[]
----
<1> Seguindo a ordem da declaração do registro, `matricula` recebe `15`, `nome` 
recebe ``Virgulino da Silva'', `nota1` recebe `9` e `nota2` recebe `10`.
<2> Seguindo a ordem da declaração do registro, `nome` recebe ``Maria Bonita''
e `cpf` recebe `72779162201`.
.Resultado ao simular a execução do programa
----
include::code/registros/reg_atribuicao_simulacao.txt[]
----
NOTE: O *Registro* é um tipo de dado composto por campos com outros tipos. 'Mas
será que é possível declarar um campo do tipo Registro?' Veremos a resposta
na próxima seção.
[[sec_registro_composicao]]
=== Composição de Registros
Na definição de registros (<<sec_registro_definicao>>), vimos que um Registro é
criado pela *composição* de outros tipos de dado. Agora veremos que podemos 
compor um Registro utilizando outros Registros *previamente definidos*.
CAUTION: Ao realizar composição de registros, a definição do registro que 
será utilizado na composição precisa *aparecer antes* (no código fonte)
da definição do novo registro. Caso contrário, você poderá ter erros de 
compilação.
==== Triângulo
Nesta seção vamos definir um Registro triângulo que contém *3* campos do 
tipo `Ponto`.
.Composição de registro em Pseudocódigo
----
include::code/registros/reg_triangulo_pseudo.txt[]
----
[source, c]
.Composição de registro em C: code/registros/reg_triangulo.c[]
----
include::code/registros/reg_triangulo.c[]
----
[NOTE]
====
Neste exemplo, o registro do tipo Triângulo foi criado com campos
do tipo `Ponto`, os três campos foram: `p1`, `p2` e `p3`. Para acessar a 
coordenada `x` do primeiro ponto do Triângulo `t`, chamamos: `t.p1.x`.
Foram dispostas duas atribuições de coordenadas numa mesma linha apenas para
ficar melhor visualmente, não há necessidade de serem assim.
====
==== Informação Pessoal
Nesta seção vamos definir um Registro `InformacaoPessoal` e utilizá-lo no Registro
`Aluno` e `Cliente`.
.Composição de registro em Pseudocódigo
----
include::code/registros/reg_infopessoal_pseudo.txt[]
----
[source, c]
.Composição de registro em C: code/registros/reg_infopessoal.c[]
----
include::code/registros/reg_infopessoal.c[]
----
[NOTE]
====
A composição de Registro utiliza a sintaxe usual de declaração de
campos. Uma vez que definimos um novo tipo, basta utilizar o tipo na declaração
normal do campo.
O acesso aos campos internos do registro passam pelo campo definido no registro
externo, por exemplo, para acessar o interno `cep`, primeiro precisamos referenciar
o campo externo `info_pessoal`, portanto o acesso fica: `a.info_pessoal.cep`.
====
Para finalizar nossos estudos sobre Registro, na seção seguinte vamos compará-lo
com Arranjo.
[[sec_registro_comparacao]]
=== Comparação entre Arranjo e Registro
A tabela a seguir mostra uma comparação entre Arranjos e Registros.
[cols="1a,1a",frame="topbot",options="header"]
|====
| Arranjo (ou array) | Registro
| 
* Estrutura de dados homogênea
** Arranjo de variáveis referenciadas por um mesmo nome e indexada por um inteiro. Ex: `notas[i]`.
* Armazena vários valores, mas *todos do mesmo tipo*.
|
* Estrutura de dados heterogênea
** Coleção de variáveis referencias por um mesmo nome
* Armazena vários valores, e *podem ser de diferentes tipos*
* Cada valor é armazenado num campo com um tipo próprio
|====
=== Recapitulando
Iniciamos este capítulo conhecendo a definição de *Registro* e sua utilidade. 
Em seguida aprendemos a sua *sintaxe* de criação. Vimos o que é um 
campo *identificador*, e como ele é utilizado para diferenciar
um registro de outro.
Realizamos *análises* em 5 situações demonstrando como criamos registros em
cada uma delas.
Na <<sec_registro_programas>> vimos como implementamos diversos programas em
pseudocódigo e em C.
Por fim, aprendemos como um registro pode ser inicializado 
(<<sec_registro_inicializacao>>), comparamos os registros com os arranjos 
(<<sec_registro_comparacao>>) e aprendemos como criar um registro através da 
composição de outro (<<sec_registro_composicao>>).
No próximo capítulo aprenderemos como reaproveitar código, criando
nossas próprias funções.
=== Exercícios Propostos
1. *Entenda a necessidade dos registros.* Nós poderíamos escrever os programas
sem utilizar registros. Qual a utilidade de se utilizar registros nos programas?
2. O que é um campo *identificador*? Dê exemplos *não* contidos neste capítulo.
3. Na <<sec_registro_analise>> analisamos diversas situações buscando os campos
necessários para criação de Registros. Agora chegou a sua vez de fazer o 
mesmo. Para cada situação a seguir:
+
--
* Defina o(s) *nome(s)* do tipo de registro que você criará
* Especifique os *campos* com seus respectivos *tipos*
* Indique quais são os campos *identificadores*, caso exista
* Escreva as *declarações* do(s) Registro(s) em C
--
.. Um programa para registrar os animais e os clientes de um Petshop.
.. Um programa para registrar e consultar filmes.
.. Um programa para uma biblioteca registrar os seus livros.
.. Um programa para agendar e consultar compromissos.
4. *Pratique o uso de registros*. Utilizando os registros definidos no
capítulo, faça pequenos programas e teste com as entradas indicadas.footnote:[Testar 
com valores pré-definidos facilita o desenvolvimento dos programas, 
faça disso um hábito. Veremos mais adiante como redirecionar a entrada
do programa, facilitando ainda mais os testes.]
+
--
.. Utilizando o <<ex_reg_aluno>>, faça um programa que indique
a situação de cada Aluno: *Aprovado*, se média das notas for maior ou igual 5;
*Reprovado* se a média for inferior a 5; *Aprovado com menção de honra* se
média for superior ou igual a 9.
+
--
.Entrada: nome matrícula nota1 nota2
----
include::code/registros/exercicio_aluno.data[]
----
--
.. Utilizando o <<ex_reg_pessoa>>, escreva um programa que imprima o
IMC das mulheres, depois o dos homens. Quando imprimir o IMC, exiba uma mensagem
indicando a condição em que a pessoa se encontra, segundo a tabela a seguir.
+
[width="85%",cols="2,3",frame="topbot",options="header"]
|====
| IMC | Classificação
| abaixo de 18,5 | Subnutrido ou abaixo do peso
| entre 18,6 e 24,9 | Peso ideal (parabéns)
| entre 25,0 e 29,9 | Levemente acima do peso
| entre 30,0 e 34,9 | Primeiro grau de obesidade
| entre 35,0 e 39,9 | Segundo grau de obesidade
| acima de 40 | Obesidade mórbida
|====
+
--
.Entrada: nome altura peso cpf sexo
----
include::code/registros/exercicio_pessoa.data[]
----
--
.. Utilizando o <<ex_reg_ponto>>, escreva um programa que leia alguns
pontos, indicando em qual quadrante eles estão no plano cartesiano.
+
--
.Entrada: p1.x p1.y p2.x p2.y p3.x p3.y
----
include::code/registros/exercicio_ponto.data[]
----
--
.. Utilizando o <<ex_reg_produto>>, escreva um programa que cadastra
uma lista de produtos. Em seguida imprima os produtos ordenadamente pelo
menor preço.
+
--
.Entrada: codigo nome valor
----
include::code/registros/exercicio_produto.data[]
----
--
--
5. *Criando novos Registros*. Agora que você já praticou a utilização de
Registro está no momento de criar os seus próprios Registros.
+
[IMPORTANT]
====
As questões a seguir *não* especificam os programas minuciosamente, elas foram 
elaboradas assim para permitir que você expresse a sua criatividade. 
No entanto, você deve:
* Resolver as questões utilizando os conhecimentos adquiridos neste capítulo
* Utilizar composição de registros quando for apropriado
* Preparar valores de entradas fixos para o seu programa, de forma a testá-lo
eficientemente.
====
.. Faça um programa para um Petshop, para cadastrar os clientes da loja e 
seus animais. O programa deve possibilitar pesquisa pelo cliente ou pelo
seu animal.
.. Faça um programa para gerenciar os gastos pessoais. O programa deve poder
registrar os gastos por categoria e emitir um relatório para proporcionar
um controle financeiro.
.. Faça um programa para registrar os filmes que você assistiu ou quer assistir.
Os filmes devem ser cadastrados por categorias. O programa deve emitir listas
de filmes com base em dois critérios à sua escolha.
.. Faça um programa para auxiliar a Policia Federal acompanhar as explosões de
caixas eletrônicos ao longo do tempo. Após cadastrar as explosões, o sistema
deve informar as regiões críticas.
.. Faça um programa para simular um dicionário. Ele deve cadastrar algumas
palavras e possibilitar alguma forma de navegação. Consulte um dicionário real
para verificar que além do significado da palavra, outras informações diferentes
também são cadastradas.
// Sempre termine os arquivos com uma linha em branco.
introducao-a-programacao-livro-1.0.0/livro/docinfo.xml
 v1.0.0
introducao-a-programacao-livro-1.0.0/livro/editora/editora.odt
Introdução a Programação
UNIVERSIDADE FEDERAL DA PARAÍBA
Reitora
MARGARETH DE FÁTIMA FORMIGA MELO DINIZ 
Vice-Reitor
EDUARDO RAMALHO RABENHORST 
EDITORA DA UFPB
Diretora
IZABEL FRANÇA DE LIMA 
Vice-Diretor
JOSÉ LUIZ DA SILVA 
Supervisão de Editoração
ALMIR CORREIA DE VASCONCELLOS JÚNIOR
Supervisão de Produção
JOSÉ AUGUSTO DOS SANTOS FILHO
CONSELHO EDITORIAL
Prof Dr. Lucídio Cabral 	(UFPB)
Prof Dr. Danielle Rousy	(UFPB)
Prof Ms. Eduardo de Santana 	(UFPB)
Bruno Jefferson de Sousa
José Jorge Lima Dias Júnior
Andrei de Araújo Formiga
Introdução a Programação
Editora da UFPB
João Pessoa 
2013
Capa - Projeto gráfico: Renato Arrais e Eduardo Santana
Editoração eletrônica: Eduardo de Santana Medeiros Alexandre
Revisora Ortográfica: Camyle de Araújo Silva
Catalogação na publicação
Universidade Federal da Paraíba
Biblioteca Setorial do CCEN
		
S725i Sousa, Bruno Jefferson de.
Introdução à programação / Bruno Jefferson de Sousa, José Jorge L. Dias Junior, Andrei de Araújo Formiga; editor: Eduardo de Santana Medeiros Alexandre, revisora: Camyle Araújo. – João Pessoa: Editora da UFPB, 2013. - João Pessoa: Curso de Licenciatura em Computação na Modalidade à Distância / UFPB, Novembro de 2013.
106p. : il. – 
ISBN: 978-85-237-0822-1
Curso de Licenciatura em Computação na Modalidade à Distância. Universidade Federal da Paraíba.
1. Programação de computadores. 2 Tipos de Dados básicos. 3. Arranjos. 4. Funções. I. Título.
BS-CCEN	CDU 004.42
Todos os direitos e responsabilidades dos autores.
EDITORA DA UFPB
Caixa Postal 5081 – Cidade Universitária 
João Pessoa – Paraíba – Brasil
CEP: 58.051 – 970 
http://www.editora.ufpb.br
Impresso no Brasil
Printed in Brazil
introducao-a-programacao-livro-1.0.0/livro/editora/editora.pdf
Introdução a Programação
UNIVERSIDADE FEDERAL DA PARAÍBA
Reitora
MARGARETH DE FÁTIMA FORMIGA MELO DINIZ 
Vice-Reitor
EDUARDO RAMALHO RABENHORST 
EDITORA DA UFPB
Diretora
IZABEL FRANÇA DE LIMA 
Vice-Diretor
JOSÉ LUIZ DA SILVA 
Supervisão de Editoração
ALMIR CORREIA DE VASCONCELLOS JÚNIOR
Supervisão de Produção
JOSÉ AUGUSTO DOS SANTOS FILHO
CONSELHO EDITORIAL
Prof Dr. Lucídio Cabral ..................................(UFPB)
Prof Dr. Danielle Rousy..................................(UFPB)
Prof Ms. Eduardo de Santana ........................(UFPB)
Bruno Jefferson de Sousa
José Jorge Lima Dias Júnior
Andrei de Araújo Formiga
Introdução a Programação
Editora da UFPB
João Pessoa 
2013
Capa - Projeto gráfico: Renato Arrais e Eduardo Santana
Editoração eletrônica: Eduardo de Santana Medeiros Alexandre
Revisora Ortográfica: Camyle de Araújo Silva
Catalogação na publicação
Universidade Federal da Paraíba
Biblioteca Setorial do CCEN
S725i Sousa, Bruno Jefferson de.
Introdução à programação / Bruno Jefferson de Sousa, José Jorge L. Dias 
Junior, Andrei de Araújo Formiga; editor: Eduardo de Santana Medeiros 
Alexandre, revisora: Camyle Araújo. – João Pessoa: Editora da UFPB, 2013. 
- João Pessoa: Curso de Licenciatura em Computação na Modalidade à 
Distância / UFPB, Novembro de 2013.
106p. : il. – 
ISBN: 978-85-237-0822-1
Curso de Licenciatura em Computação na Modalidade à Distância. 
Universidade Federal da Paraíba.
1. Programação de computadores. 2 Tipos de Dados básicos. 3. Arranjos. 
4. Funções. I. Título.
BS-CCEN CDU 004.42
Todos os direitos e responsabilidades dos autores.
EDITORA DA UFPB
Caixa Postal 5081 – Cidade Universitária 
 João Pessoa – Paraíba – Brasil
CEP: 58.051 – 970 
http://www.editora.ufpb.br
Impresso no Brasil
Printed in Brazil
introducao-a-programacao-livro-1.0.0/livro/images/LEIAME.txt
A gráfica nos impões diversas restrições em
relação às imagens.
Portanto as imagens devem seguir as seguintes
intruções:
* Utilizar imagens CMYK ao invés de RGB
* Preferir utilizar tons de cinza ao invés de cores nas ilustrações
* Desenhar os gráficos no Inkscape, salvar as imagens em .svg
* Expotar a imagem .svg para .eps (manter as duas no repositório)
* Evitar usar gráficos em jpeg, pois na impressão fica borrado.
* Evitar usar gráficos em png pois são RGB
Em caso de dúvida, contactar a equipe de produção.
introducao-a-programacao-livro-1.0.0/livro/images/algoritmos/fluxograma-calcular-media.eps
introducao-a-programacao-livro-1.0.0/livro/images/algoritmos/fluxograma-calcular-media.png
introducao-a-programacao-livro-1.0.0/livro/images/algoritmos/fluxograma-calcular-media.svg
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 image/svg+xml
 
 
 
 
 
 
 
 
 
 
 
 Início
 
 
 
 Obter nota1
 
 
 
 Obter nota2
 
 
 
 M= (nota1 + nota2)
 2
 
 
 
 
 M ≥ 7
 
 
 
 Aprovado
 
 
 
 Reprovado
 
 
 
 Fim
 
 Sim
 Não
 
 
 
 
 
 
 
 
 
introducao-a-programacao-livro-1.0.0/livro/images/algoritmos/fluxograma.eps
introducao-a-programacao-livro-1.0.0/livro/images/algoritmos/fluxograma.png
introducao-a-programacao-livro-1.0.0/livro/images/algoritmos/fluxograma.svg
 
 
 
 
 
 
 
 
 
 
 
 image/svg+xml
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Processamento. Sentido do fluxo de execução do algoritmo. Ponto de decisão.
 Início/Fim. Entrada de dados. Saída de dados.
 
introducao-a-programacao-livro-1.0.0/livro/images/algoritmos/ilustracao-dois-passos.eps
introducao-a-programacao-livro-1.0.0/livro/images/algoritmos/ilustracao-dois-passos.png
introducao-a-programacao-livro-1.0.0/livro/images/algoritmos/ilustracao-dois-passos.svg
 
 
 
 
 
 
 image/svg+xml
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Capacidade: 9 litros Utilização: 9 litros
 Capacidade: 4 litros Utilização: 0 litros
 Capacidade: 6 litros Utilização: 0 litros
 
 Capacidade: 9 litros Utilização: 0 litros
 Capacidade: 4 litros Utilização: 4 litros
 Capacidade: 6 litros Utilização: 5 litros
 (a) (b)
 
 
introducao-a-programacao-livro-1.0.0/livro/images/algoritmos/john-von-neumann.jpg
introducao-a-programacao-livro-1.0.0/livro/images/algoritmos/memoria-exercicio.eps
introducao-a-programacao-livro-1.0.0/livro/images/algoritmos/memoria-exercicio.png
introducao-a-programacao-livro-1.0.0/livro/images/algoritmos/memoria-exercicio.svg
 
 
 
 
 
 
 image/svg+xml
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 x=10
 10 5 3
 z=x/y+z
 y=5
 
 
 0 1 2 3
 4 5 6 7
 8 9 10 11
 12 13 14 15
 
introducao-a-programacao-livro-1.0.0/livro/images/algoritmos/memoria32posicoes.eps
introducao-a-programacao-livro-1.0.0/livro/images/algoritmos/memoria32posicoes.png
introducao-a-programacao-livro-1.0.0/livro/images/algoritmos/memoria32posicoes.svg
 
 
 
 
 
 
 image/svg+xml
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 x = 2 y = 3 z=x.y
 2 3 6
 
 
 0 1 2 3
 4 5 6 7
 8 9 10 11
 12 13 14 15
 16 17 18 19
 20 21 22 23
 24 25 26 27
 28 29 30 31
 
introducao-a-programacao-livro-1.0.0/livro/images/algoritmos/monty.jpg
introducao-a-programacao-livro-1.0.0/livro/images/cap4/cadeia_caracteres.eps
introducao-a-programacao-livro-1.0.0/livro/images/cap4/cadeia_caracteres.svg
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 image/svg+xml
 
 
 
 
 
 
 
 
 
 
 
 
 B R A S I L \0
 0 1 2 3 4 5 6
 
 
 
 Vetor
 índices
 {
 valores
 
 
 
introducao-a-programacao-livro-1.0.0/livro/images/cap4/matriz-exemplos.eps
introducao-a-programacao-livro-1.0.0/livro/images/cap4/matriz-exemplos.svg
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 image/svg+xml
 
 
 
 
 
 
 
 [ ]
 4 2 3 8 0 1 9 1 6
 Matriz 3x3
 
 
 [ ]
 5 1 0 9 2 1
 Matriz 2x3
 
 
introducao-a-programacao-livro-1.0.0/livro/images/cap4/matriz.eps
introducao-a-programacao-livro-1.0.0/livro/images/cap4/matriz.svg
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 image/svg+xml
 
 
 
 
 
 
 [ ]
 a 1,1 a 1,2 a 1,3 ... a 1,n a 2,1 a 2,2 a 2,3 ... a 2,n a 3,1 a 3,2 a 3,3 ... a 3,n a m,1 a m,2 a m,3 ... a m,n
 
 
 Linha
 Coluna
 
 
 
introducao-a-programacao-livro-1.0.0/livro/images/cap4/vetor5.eps
introducao-a-programacao-livro-1.0.0/livro/images/cap4/vetor5.svg
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 image/svg+xml
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 4 2 7 9 3
 0 1 2 3 4
 
 Vetor
 índices
 {
 valores
 
 
 
introducao-a-programacao-livro-1.0.0/livro/images/cap4/vetor_apos_leitura.eps
introducao-a-programacao-livro-1.0.0/livro/images/cap4/vetor_apos_leitura.svg
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 image/svg+xml
 
 
 
 
 
 
 v[0] = 4 v[1] = 3 v[2] = 7 v[3] = 2 v[4] = 9
 Vetor v
 {
 
introducao-a-programacao-livro-1.0.0/livro/images/estruturas-de-controle/sequencia.eps
introducao-a-programacao-livro-1.0.0/livro/images/estruturas-de-controle/sequencia.png
introducao-a-programacao-livro-1.0.0/livro/images/estruturas-de-controle/sequencia.svg
 
 
 
 
 
 
 
 
 
 
 
 image/svg+xml
void main(){ int x, y, soma; scanf(&x); scanf(&y); soma = x + y; printf("%d",soma); }
 Execução das Intruções
 
 
introducao-a-programacao-livro-1.0.0/livro/images/exemplo-de-capitulo/Babbage-Analytical-Engine-with-cards.png
introducao-a-programacao-livro-1.0.0/livro/images/exemplo-de-capitulo/ENIAC-2.jpg
introducao-a-programacao-livro-1.0.0/livro/images/exemplo-de-capitulo/ENIAC.jpg
introducao-a-programacao-livro-1.0.0/livro/images/exemplo-de-capitulo/IBM_segunda_geracao.png
introducao-a-programacao-livro-1.0.0/livro/images/exemplo-de-capitulo/JacquardCard.jpg
introducao-a-programacao-livro-1.0.0/livro/images/exemplo-de-capitulo/JacquardLoom.jpg
introducao-a-programacao-livro-1.0.0/livro/images/exemplo-de-capitulo/abaco.png
introducao-a-programacao-livro-1.0.0/livro/images/exemplo-de-capitulo/ada_lovelace.jpg
introducao-a-programacao-livro-1.0.0/livro/images/exemplo-de-capitulo/apple-I.jpg
introducao-a-programacao-livro-1.0.0/livro/images/exemplo-de-capitulo/babbage-maquina-diferencial.jpg
introducao-a-programacao-livro-1.0.0/livro/images/exemplo-de-capitulo/bug.png
introducao-a-programacao-livro-1.0.0/livro/images/exemplo-de-capitulo/circuito-integrado-comparacao-de-tamanho.jpg
introducao-a-programacao-livro-1.0.0/livro/images/exemplo-de-capitulo/computador-quarta-geracao.jpg
introducao-a-programacao-livro-1.0.0/livro/images/exemplo-de-capitulo/computador-quinta-geracao.jpg
introducao-a-programacao-livro-1.0.0/livro/images/exemplo-de-capitulo/ibm-360-arquitetura-plugavel.jpg
introducao-a-programacao-livro-1.0.0/livro/images/exemplo-de-capitulo/napier-multiplicacao-46785399x7.png
introducao-a-programacao-livro-1.0.0/livro/images/exemplo-de-capitulo/napier-ossos-tabuleiro.png
introducao-a-programacao-livro-1.0.0/livro/images/exemplo-de-capitulo/pascaline-video.png
introducao-a-programacao-livro-1.0.0/livro/images/exemplo-de-capitulo/pascaline.jpg
introducao-a-programacao-livro-1.0.0/livro/images/exemplo-de-capitulo/regua-de-calculo.jpg
introducao-a-programacao-livro-1.0.0/livro/images/exemplo-de-capitulo/transistor-e-valvula-juntos.png
introducao-a-programacao-livro-1.0.0/livro/images/exemplo-de-capitulo/valvulas.png
introducao-a-programacao-livro-1.0.0/livro/images/introducao-a-programacao/compilacao-passos.png
introducao-a-programacao-livro-1.0.0/livro/images/introducao-a-programacao/interpretacao.png
introducao-a-programacao-livro-1.0.0/livro/images/introducao-a-programacao/memoria-representacao.eps
introducao-a-programacao-livro-1.0.0/livro/images/introducao-a-programacao/memoria-representacao.png
introducao-a-programacao-livro-1.0.0/livro/images/introducao-a-programacao/memoria-representacao.svg
 
 
 
 
 
 
 
 
 image/svg+xml
 
 
 
 
 
 
 
 
 
 
 Endereço
 Variável
 Valor
 
 
 
 
 
 
 
 100
 20,5
 aula
 ...
 -1700,23
 0 x
 1 y
 2 z
 ... ... 
 n var 
 
introducao-a-programacao-livro-1.0.0/livro/images/introducao-a-programacao/memoria.png
introducao-a-programacao-livro-1.0.0/livro/images/novo-capitulo/bug.png
introducao-a-programacao-livro-1.0.0/livro/images/prefacio/issue.png
introducao-a-programacao-livro-1.0.0/livro/livro.asc
= Introdução à Programação
:doctype: book
:lang: pt-BR
:keywords: Computação
:description: Livro de Nome-da-disciplina
:ascii-ids:
:gitrepo: https://github.com/edusantana/introducao-a-programacao-livro
include::capitulos/prefacio.asc[]
include::capitulos/algoritmos.asc[]
include::capitulos/introducao-a-programacao.asc[]
include::capitulos/estruturas-de-controle.asc[]
include::capitulos/cap4-arranjos.asc[]
//include::capitulos/registros.asc[]
include::capitulos/funcoes.asc[]
////
Sempre termine os arquivos com uma linha em branco.
////
introducao-a-programacao-livro-1.0.0/livro/test.asc
== Arquivo de teste
Teste de aquivo. 
Mudando arquivo.
["graphviz"]
----
digraph colorschemes {
 node [color=2 style=filled colorscheme=greys9]
 edge [colorscheme=greys9]
 blue [color=5]
 red [color=8]
 blue->red [color=8]
 red->blue [color=5]
}
----
[[fig_compilacao_passos]]
["graphviz"]
.Passos no processo de compilação
----
digraph automata_0 {
 rankdir=LR;
 size ="8.5, 11";
 node [shape = box];
 edge [colorscheme=greys9]
 
 subgraph clusterCodigos {
 label = "Código fonte";
 node [style=filled,color=white];
 style=filled;
 color=lightgrey;
 code_assembly [label="Linguagem de Baixo Nível\n(Linguagem de montagem)"];
 code_c [label="Linguagem de Alto Nível\n(Ex: C, Pascal, ...)"];
 }
 subgraph clusterTradutor {
 label = "Tradutor";
 node [style=filled,color=white,shape="doubleoctagon"];
 style=filled;
 color=lightgrey;
 montador [label="Montador"];
 compilador [label="Compilador"];
 }
 code_gerado [label="Código traduzido\n(Linguagem de montagem)"];
 subgraph clusterCodigoObjeto {
 label = "Código Objeto\n(binário)";
 node [style=filled,color=white];
 style=filled;
 color=lightgrey;
 objeto1 [label="Código Objeto 1"];
 objeto2 [label="Código Objeto 2"];
 }
 ligador [label="Ligador",shape="doubleoctagon"];
 programa [label="Código Binário\nExecutável", shape="component", fillcolor="grey", style="filled"];
 carregador[label = "Carregador", style="filled", shape="folder"];
 memoria[label="Memória", style="filled", shape="box3d"]
 code_assembly -> montador -> objeto1 [color=8, style="bold"];
 code_c -> compilador -> code_gerado -> montador -> objeto2 [color=6, style="bold"];
 
 objeto1->ligador [color=5, style="bold"];
 objeto2->ligador [color=5, style="bold"]; 
 ligador-> programa -> carregador -> memoria [color=5, style="bold"];
 {rank=source; code_c code_assembly }
 {rank=same; montador compilador memoria}
 {rank=same; objeto1 objeto2 carregador}
 {rank=same; ligador programa}
 {rank=sink; programa}
}
----
// Sempre termine os arquivos com uma linha em branco.