Você está na página 1de 77

Curso de

Programação
Parte I

Hilton Cardoso Marins Junior


hilton.junior@ifsudestemg.edu.br
2023
1. INTRODUÇÃO ............................................................................................................................... 4
1.1. POSTURA DO ALUNO ....................................................................................................................... 4
1.2. POSTURA DO PROFESSOR ................................................................................................................. 5
2. CONCEITOS BÁSICOS ..................................................................................................................... 6
2.1 COMPUTADOR ....................................................................................................................................... 6
2.2. PROGRAMA .......................................................................................................................................... 7
2.3. ALGORITMO .......................................................................................................................................... 7
2.4. LINGUAGEM DE PROGRAMAÇÃO ............................................................................................................... 9
2.5. PROCESSO DE CRIAÇÃO DE PROGRAMAS.................................................................................................... 10
2.5.1. O processo de tradução – parte I. ........................................................................................... 11
2.5.2. O processo de tradução – parte II. .......................................................................................... 11
2.6. AMBIENTE DE DESENVOLVIMENTO ........................................................................................................... 11
2.6.1. Como instalar a IDE em seu computador. ............................................................................... 12
2.7. TIPOS DE DADOS.................................................................................................................................. 12
2.7.1. Variáveis de memória ............................................................................................................. 15
2.7.2. Constantes .............................................................................................................................. 15
2.8. O TIPO DE DADO BOOLEAN..................................................................................................................... 15
2.9. OPERADORES ...................................................................................................................................... 15
2.9.1. Operadores aritméticos e operador módulo ........................................................................... 20
2.9.2. Cuidado com a perda de informação ...................................................................................... 20
3. PRIMEIROS PASSOS .................................................................................................................... 21
3.1. 1º PASSO: ANÁLISE DO PROBLEMA E PROJETO DA SOLUÇÃO................................................................... 21
3.2. 2º PASSO: IDENTIFICAR AS TRÊS PARTES DO PROGRAMA ....................................................................... 21
3.3. 3º PASSO: ELABORAR O ALGORITMO ................................................................................................ 21
3.4. 4º PASSO: CODIFICAÇÃO EM LINGUAGEM DE PROGRAMAÇÃO ................................................................ 21
3.5. O PRIMEIRO PROBLEMA ................................................................................................................. 22
3.5.1 1º Passo: análise do problema e projeto da solução ............................................................... 22
3.5.2 2º Passo: identificar as três partes do programa ..................................................................... 23
3.5.3 3º Passo: elaborar o algoritmo ................................................................................................ 23
3.5.4 4º Passo: codificação em linguagem de programação ............................................................ 24
3.6 FUNÇÕES E BIBLIOTECAS ......................................................................................................................... 25
3.6.1 Invocando uma função............................................................................................................. 25
3.7 INSTRUÇÃO DE SAÍDA DE DADOS ............................................................................................................... 25
3.7.1 Saída de dados – parte I ........................................................................................................... 27
3.7.2 Saída de dados – parte II .......................................................................................................... 27
3.7.3 O processo de depuração ......................................................................................................... 27
3.8 INSTRUÇÃO DE ENTRADA DE DADOS .......................................................................................................... 27
3.8.1 Entrada de dados ..................................................................................................................... 28
3.8.2 Limpando o buffer do teclado .................................................................................................. 28
3.9 CONCLUSÃO......................................................................................................................................... 29
3.9.1 Análise do problema do IMC .................................................................................................... 30
3.9.2 Codificação do programa do IMC ............................................................................................ 30
3.10 ATIVIDADES ....................................................................................................................................... 30
4. CONTROLE DO FLUXO DE EXECUÇÃO .......................................................................................... 33
4.1 SEQUÊNCIA .......................................................................................................................................... 33
4.2 ALTERNATIVA SIMPLES ........................................................................................................................... 33
4.2.1 Alternativa simples .................................................................................................................. 35
4.2.2 A linguagem C não tem o tipo boolean, mas... ........................................................................ 35
4.2.3 Operador lógico E ..................................................................................................................... 35
4.2.4 Operador lógico OU ................................................................................................................. 35
4.3 ALTERNATIVA COMPOSTA ....................................................................................................................... 35
4.3.1 Alternativa composta ............................................................................................................... 36
4.4 ALTERNATIVA MÚLTIPLA ........................................................................................................................ 36
4.4.1 Alternativa múltipla com if ...................................................................................................... 37
4.4.2 Alternativa múltipla com switch – parte I ................................................................................ 37
4.4.3 Alternativa múltipla com switch – parte II ............................................................................... 37
4.5 ATIVIDADES ......................................................................................................................................... 37
4.6 REPETIÇÃO .......................................................................................................................................... 40
4.7 REPETIÇÃO COM TESTE NO INÍCIO ............................................................................................................. 41
4.7.1 Repetição com teste no iníco - parte I ...................................................................................... 45
4.7.2 Repetição com teste no início – parte II ................................................................................... 45
4.7.3 Teste de mesa para o programa media.c................................................................................. 45
4.8 REPETIÇÃO COM TESTE NO FINAL .............................................................................................................. 46
4.8.1 Atividade .................................................................................................................................. 46
4.8.2 Repetição com teste no final .................................................................................................... 46
4.9 REPETIÇÃO COM VARIÁVEL DE CONTROLE ................................................................................................... 47
4.9.1 Estrutura de repetição com variável de controle ..................................................................... 48
4.10 ATIVIDADES ....................................................................................................................................... 49
4.10.2. Gráfico de temperatura parte I ............................................................................................. 51
4.10.3. Gráfico de temperatura parte II ............................................................................................ 51
4.10.4. Gráfico de temperatura parte III ........................................................................................... 51
4.10.5. Raízes de uma equação do 2º grau parte I ........................................................................... 51
4.10.6. Raízes de uma equação do 2º grau parte II .......................................................................... 51
4.10.7. Raízes de uma equação do 2º grau parte III ......................................................................... 51
5. ARRAY ........................................................................................................................................ 52
5.1 DECLARAÇÃO DE VETOR.......................................................................................................................... 52
5.2 ACESSANDO OS ELEMENTOS DO VETOR ...................................................................................................... 53
5.3 PERCORRENDO UM VETOR ...................................................................................................................... 54
5.3.1 Vetor numérico – parte I .......................................................................................................... 56
5.3.2 Vetor numérico – parte II ......................................................................................................... 56
5.4 STRINGS .............................................................................................................................................. 56
5.4.1 String parte I ............................................................................................................................ 58
5.4.2 String parte II ........................................................................................................................... 58
5.4.3 String parte III .......................................................................................................................... 58
5.5 DIMENSÕES DE UM VETOR ...................................................................................................................... 58
5.5.1 Teste de mesa para o programa media.c versão 6.0 ............................................................... 60
5.5.2 Desafio ..................................................................................................................................... 61
5.6 INICIALIZAÇÃO DE VETOR ........................................................................................................................ 61
5.7 ATIVIDADES ......................................................................................................................................... 62
6. ESTRURURAS DE DADOS HETEROGÊNEAS ................................................................................... 65
6.1 TYPEDEF.............................................................................................................................................. 67
7. MODULARIZAÇÃO ...................................................................................................................... 68
7.1 PASSAGEM DE PARÂMETROS ................................................................................................................... 69
7.1.1 Desafio ..................................................................................................................................... 72
7.1.2 Modularização – parte I ........................................................................................................... 72
7.1.3 Modularização – parte II .......................................................................................................... 72
7.1.4 Modularização – parte III ......................................................................................................... 72
7.1.5 Modularização – parte IV ......................................................................................................... 72
7.1.6 Protótipos de funções .............................................................................................................. 72
7.1.7 Passando vetor como parâmetro ............................................................................................. 73
7.2 ESCOPO DE VARIÁVEIS ............................................................................................................................ 73
7.2.1 Escopo de variáveis .................................................................................................................. 75
7.3 ATIVIDADES ......................................................................................................................................... 75
1. INTRODUÇÃO

Pretendemos apresentar um roteiro para o aprendizado de programação, utilizando uma


metodologia baseada em problemas. Acreditamos que a resolução de problemas
estimula a proatividade, consolida o aprendizado e exige as mesmas competências que
um bom programador desempenha no exercício de suas atividades.

O processo proposto será desenvolvido, basicamente, em cinco etapas. Inicialmente


consideramos importante que o aluno domine aquelas operações básicas que todo
usuário desempenha ao utilizar o computador como ferramenta de trabalho ou lazer. O
escopo deste livro se inicia na 2ª etapa, onde apresentaremos um conceito de
programação associado a um problema e respectiva resolução. Na 3ª e 4ª etapas
convidamos o aluno a participar com mais autonomia. Acreditamos que seja o período
mais importante do aprendizado, já que o aluno terá a oportunidade de apresentar a
solução de um problema, através de um programa, empregando os conceitos de
programação que foram apresentados previamente. Finalmente a conclusão da atividade
prática validará todo o processo.

A divulgação desta proposta por si só, não é garantia de sucesso na aprendizagem. É


apenas um roteiro, porém fundamental que seja acompanhado de comprometimento e
postura adequada. Conto com a sua participação efetiva.

1.1. Postura do aluno


Acredito que todo aprendiz sabe, mesmo que intuitivamente, que a aprendizagem ativa é
melhor que a passiva. Seguiremos essa linha de ação, incentivaremos o aluno a
expressar suas dúvidas, realizar atividades práticas e até ensinar algo a seus colegas.
Tudo isso sem descartar atividades tais como leitura e palestras expositivas.

Caro aluno, o sucesso da proposta apresentada dependerá muito da sua postura frente ao
desafio de se tornar um programador. Após alguns anos lecionando na área de TI, pude
perceber que o resultado será tão proveitoso quanto a sua capacidade em seguir algumas
premissas.

Sugerimos certo grau de atrevimento, não se acomode com o que já domina, busque
sempre novas conquistas, novos níveis de conhecimento, progrida sempre. Em
contrapartida, uma postura negativa para o aluno é o isolamento, impede a troca de
experiências entre os membros da comunidade e influencia drasticamente o alcance do
processo de aprendizagem. “Escove o teclado com os dedos” é uma brincadeira para
chamar sua atenção para a importância da prática para o desenvolvimento de
habilidades de programação, aprenda praticando. Exercite seu cérebro através de
desafios cognitivos relacionados ao universo da programação, de forma que a cada
conquista você perceba aumentar sua capacidade de solucionar problemas. Ensinar
talvez seja a atitude mais
eficaz para aprender, por mais
paradoxal que possa parecer
para o aprendiz. Sugiro
fortemente que você ensine o
que sabe aos seus colegas. O
primeiro benefício é o ganho
proveniente de todo
planejamento, estratégia e
estudo que você teve que
realizar para ensinar. O
segundo, não menos
importante, é a sensação de
bem-estar que perceberá ao
contribuir com o aprendizado
de um colega. Se ao contrário,
você tiver a oportunidade de
receber um auxílio como este, certamente ficará com dívida de gratidão, aí teremos uma
situação ideal, um círculo virtuoso de colaboração. Finalmente sugerimos que exercite
sua capacidade de realizar estudos autônomos, através de fontes de pesquisas
confiáveis, como grupos de estudos, fóruns especializados, dentre outros, essa
habilidade é muito valorizada no mercado de trabalho de TI.

1.2. Postura do professor


Para alcançarmos o sucesso é importante estabelecermos comunicação além deste livro.
Divulgaremos oportunamente diversos canais de comunicação tais como serviços de
mensagens, vídeo conferências, algumas redes sociais, e-mails, dentre outros. O
importante é estabelecer pontos de apoio ao processo de aprendizagem. Essa tarefa
estará sob minha responsabilidade, claro que com a participação de todos.

Por enquanto disponibilizo meu e-mail, hilton.junior@ifsudestemg.edu.br, como forma


principal de contato.

Bons estudos!
2. CONCEITOS BÁSICOS

2.1 Computador
Qualquer tecnologia surge, desenvolve e ganha importância de forma proporcional ao
benefício que traz a sociedade. Com o computador não foi diferente, mudou nossas
vidas ao viabilizar o tratamento de um volume muito grande de informações, mantendo
a integridade dos dados para as tomadas de decisões e os aspectos de segurança
inerentes às atividades em que há manipulação de informação.

Mas quais são as características tecnológicas e fundamentais que vão além do aspecto
econômico e social, que tornam o computador uma ferramenta tão importante e
necessária? Um ponto de partida para essa questão é saber que o computador,
dispositivo móvel ou qualquer equipamento com uma CPU são capazes de processar
dados automaticamente. Mas o que é processamento de dados?

O processamento de dados sempre esteve presente em nossas vidas. É anterior ao


surgimento do computador. Ocorre quando dados necessários para se resolver um
problema são transformados em resultados esperados. O ato de comprar uma bala de um
ambulante é um exemplo de processamento de dados. Temos um problema que é o
cálculo do troco, os dados de entrada que são o custo da bala e o valor pago ao
ambulante, o processamento que é o cálculo do troco e finalmente o dado de saída, ou
resultado, que no caso é o valor do troco. Esse exemplo, de fácil compreensão, nos dá
uma ideia clara do que é processamento de dados, porém não será nosso objeto de
estudo, já que foi realizado de forma manual. Estamos interessados apenas no
processamento de dados automático, representado esquematicamente na figura abaixo.

ENTRADA PROCESSAMENTO DE SAÍDA


DADOS AUTOMÁTICO

Dados
necessários Transformações
Resultados
para realizadas com os
esperados
resolver o dados de entrada
problema

Agora já podemos relacionar uma segunda característica fundamental do computador: a


capacidade de seguir instruções. Talvez seja a característica mais importante à medida
que possibilita o processamento de dados automático, ou seja, o computador só é capaz
de processar dados de forma automática porque consegue executar instruções recebidas.

Agora já podemos apresentar um conceito mais apropriado: o computador é uma


máquina capaz de processar dados automaticamente conforme uma sequência de
instruções que fazem parte do vocabulário da linguagem que ele consegue compreender.
Podemos instruir o computador a realizar uma tarefa desde que a instrução seja
compreensível para ele. Vamos entender melhor a parte final do conceito acima: “...
desde que a instrução seja compreensível para ele”.

2.2. Programa
Vimos que para realizar o processamento de dados de forma automática, o computador
segue instruções. Agora vamos compreender melhor o papel das instruções e
consequentemente o conceito de programa.

Vamos sugerir uma nova questão: como instruir o computador de forma que ele possa
compreender o que desejamos? A resposta envolve dois aspectos. O primeiro é o
conhecimento que devemos possuir sobre um determinado problema para que sejamos
capazes de encontrar soluções em forma de instruções ao computador. Tem relação com
o nosso domínio sobre o problema, independente do nosso conhecimento sobre
programação. Por exemplo: você seria capaz dar instruções a alguém sobre os
procedimentos necessários para manutenção a uma turbina de avião? Em caso negativo,
como prosseguir? Impossível, pelo menos até estarmos capacitados para tal.

A falta de domínio sobre o problema a ser resolvido é comum entre os programadores, é


o normal, principalmente em problemas originais. Por outro lado, um programador
nunca deve iniciar o seu trabalho sem que tenha conhecimento suficiente sobre o
problema que pretende solucionar. Então como resolver esse dilema? O programador
deve possuir todo o conhecimento do universo? Óbvio que não, mas o suficiente para
construir uma solução adequada ao problema. Sugerimos fortemente que dedique
grande parte do seu esforço como programador na análise do problema e projeto da
solução.

Façamos algumas analogias para melhor entendimento: um engenheiro, para projetar a


edificação de um hospital, deve possuir uma formação na área de saúde? O processo de
seleção dos desenvolvedores do aplicativo iFood, exigiu que fossem chefs de cozinha?
Creio que todos foram capazes de analisar as necessidades e implantar a solução para o
problema de forma satisfatória sem que precisassem de formação específica na área
relacionada ao problema. Ainda bem, né?

Agora veremos o segundo aspecto que devemos observar ao instruir o computador: o


programa. Esse será o principal foco do livro, aliás o único. Portanto tenha paciência,
por enquanto, basta conhecermos o conceito de programa: conjunto de instruções em
um formato adequado ou compreensível para ser executado pelo computador.

2.3. Algoritmo
Tenha calma, não deixamos de lado a compreensão do que é um programa, você verá
adiante que esses dois termos estão intimamente ligados.

Algoritmo é um conjunto de instruções semelhante ao programa, mas sem o


compromisso de estar em uma linguagem apropriada para ser executada pelo
computador. O algoritmo pode ser mais informal pelo fato de ser dirigido a seres
humanos, já o programa deve seguir o formalismo exigido pelo computador.

Analise o algoritmo, “roteiro de como ir para casa”, abaixo. Percebemos a presença dos
dados relativos ao problema, da sequência de instruções e do resultado obtido, ou seja,
são elementos que fazem parte de todo algoritmo.
1. Vá para o ponto de ônibus.
2. Se posicione no local adequado ao ônibus desejado.
3. Fique atento até que ônibus passe e pare.
4. Entre no ônibus, pague e sente-se.
5. Permaneça sentado até que o ônibus pare no ponto de desembarque.
6. Desça do ônibus.
7. Se chegou ao destino final, vá para casa, senão volte ao passo 1 e pegue outro
ônibus.

Esse é um caso de algoritmo que nunca se tornará um programa, pelo menos em sua
totalidade, pois não seremos capazes de codificá-lo em uma linguagem adequada ao
computador. Porém servirá para algumas reflexões.

Para que você possa começar a ter um pensamento adequado para programação ou para
construção de algoritmos, sugiro que siga a seguinte premissa: o computador faz
exatamente o que foi instruído, nem mais, nem menos. Então imagine que você seja um
robô e, supostamente, pudesse seguir rigidamente o “roteiro de como ir para casa”.
Quais problemas encontraria? Você conseguiria chegar à sua casa? Se não passar ônibus
ficaria esperando eternamente até sua bateria acabar? Lembre-se, você é um robô. E se
você perceber, já dentro do ônibus, que não tem dinheiro para pagar? Esses são alguns
problemas ou situações que não foram previstas pelo nosso algoritmo, mas ainda assim,
uma pessoa poderia contorná-los sem dificuldades.

Se uma das exceções citadas acima ocorrer, não podemos colocar a culpa no robô, já
que ele não pensa, apenas segue rigidamente as instruções. Essa foi uma boa reflexão
sobre a importância de como devemos expressar a solução de um problema através de
um algoritmo. Mais adiante, ainda nesse tópico, falaremos sobre algumas considerações
nesse sentido, mas já podemos destacar a importância do programador como o principal
responsável pelos resultados obtidos por um algoritmo.

Veja abaixo um exemplo de algoritmo que pode ser codificado em linguagem adequada
ao computador, representado em forma de fluxograma portugol. Ele ainda não é um
programa, pois não está em linguagem adequada, mas pode ser tornar um, facilmente.
inicio
leia (nota1, nota2)

media = (nota1+nota2)/2
se media >= 7 então
mostra("Aprovado")
senão
mostra("Reprovado")
fim_se
fim.

Estamos quase em condições de construir algoritmos computacionais. Veja algumas


considerações importantes que nos auxiliarão nessa tarefa.

1. O ponto de partida é a existência de um problema cuja solução poderá ser construída


através de um algoritmo. Devemos ser capazes de descrever o problema de forma
clara e precisa. Se você não sabe como resolver o problema como irá instruir uma
máquina a resolvê-lo?

2. Utilizando uma forma de representação como fluxograma, portugol ou até mesmo


uma descrição narrativa, elabore o algoritmo (sequência de passos) que conduz à
solução, considerando que:

a. Produzirá uma saída. Caso contrário não possui finalidade.


b. Terminará após um número finito de passos. Caso contrário nunca acabará.
c. Cada passo deve ser definido de forma clara, sem ambiguidade. Lembre-se
de que “quem” o executará não “pensa”.
d. Os dados de entrada são necessários para produzir as saídas.
e. Haverá mais de um algoritmo para resolver um mesmo problema. Uns mais
eficientes do que outros. A eficiência pode estar ligada a tempo de execução,
ao consumo de memória, dentre outros fatores.

3. “Adequar” o algoritmo de forma que o computador possa compreendê-lo e executá-


lo. Para tanto devemos usar uma linguagem apropriada à compreensão pelo
computador.

2.4. Linguagem de programação


O propósito de uma linguagem de programação é permitir expressarmos algoritmos
computacionais com exatidão, adequando-os a um formato para ser executado pelo
computador. Cada linguagem de programação fornece um conjunto de instruções e
regras padronizadas que nós, programadores, utilizamos para criar programas.

Qualquer computador possui uma “linguagem natural”, conhecida como linguagem de


máquina, definida em seu projeto de hardware. O computador pode entender
diretamente somente instruções dadas em sua própria linguagem de máquina, composta
geralmente em strings de números (em última instância a 1s e 0s).

A programação em linguagem de máquina é um processo lento e tedioso para os


programadores. Com o surgimento das linguagens assembly a tarefa do programador foi
facilitada, já que as instruções em sequência de números foram substituídas por
abreviações para representar operações elementares. Foi necessário desenvolver
programas tradutores chamados assemblers para converter os programas de linguagem
assembly em linguagem de máquina.

Apesar das linguagens assembly terem contribuído para o aumento do uso dos
computadores, a tarefa de programar ainda era muito trabalhosa. Em seguida surgem as
linguagens de alto nível com suas instruções semelhantes à linguagem natural dos
humanos. A necessidade dos tradutores permaneceu, cada linguagem de programação
de alto nível fornece o seu tradutor (compilador ou interpretador), que nada mais é do
que um programa responsável por converter os programas de linguagens de alto nível
em linguagem de máquina.

Durante o decorrer das atividades não ficaremos limitados aos algoritmos representados
em portugol ou fluxograma, usaremos uma linguagem de programação para que você
possa perceber os efeitos produzidos pelos programas ao serem executados. Para
implementar essa metodologia somos obrigados a escolher uma linguagem de
programação, optamos por C pelo fato de ser uma linguagem bem conhecida, simples e
principalmente por ter a sintaxe similar às principais linguagens da atualidade.

Mas porque não usarmos uma linguagem de programação mais atual e que seja
requisitada pelo mercado? A resposta está no fato de que a maioria das linguagens
atuais segue o paradigma Orientado a Objetos (OO). Para utilizarmos essas linguagens
teríamos que entendermos bem o paradigma OO para termos êxito. Isso aumentaria
muito o grau de complexidade para o iniciante. Essa é uma das razões para termos
escolhido a linguagem C, ela segue o paradigma de Programação Estruturado, bem mais
simples e que servirá de base para qualquer paradigma de programação a ser escolhido
no futuro. O que estudaremos aqui é considerado universal em termos de programação.

2.5. Processo de criação de programas

1 O processo inicia quando surge um problema e decidimos solucioná-lo através


de um programa. Exemplificaremos através do problema
inicio
leia (nota1, nota2) do cálculo da situação de um aluno. Trata-se de um
problema simples, porém sua resolução de forma manual
media = (nota1+nota2)/2 está sujeita a erros e pode se tornar repetitiva, já que
se media >= 7 então
mostra("Aprovado")
pretendemos estendê-la a diversos alunos. Após
senão estabelecer a viabilidade de resolver esse problema
mostra("Reprovado") através do computador, elaboramos um algoritmo
fim_se
(imagem ao lado) que descreve os passos que o
fim.
computador deverá realizar para alcançar o resultado
desejado.

O segundo passo é transformar o algoritmo int main(){


2 float nota1, nota2, media;
em programa, traduzindo-o para um conjunto
printf("Informe a 1a. nota:");
de instruções especificas da linguagem de programação scanf("%f", &nota1);
escolhida. Em nosso caso escolhemos a linguagem C, printf("Informe a 2a. nota:");
mas poderia ser qualquer outra. Ao final dessa etapa scanf("%f", &nota2);

teremos um programa ou código-fonte ou media = (nota1+nota2)/2;


simplesmente “código”. if (media >= 7){
printf("Aprovado!");
}else{
printf("Reprovado!");
}
return 0;
}
O código produzido na 2ª etapa ainda não está pronto para ser executado pelo
3 computador, ele precisa ser traduzido para linguagem de máquina através do
compilador ou interpretador da linguagem escolhida. Após esse trabalho de tradução
podemos solicitar ao
computador que execute
o programa e verificar,
através de testes, se os
requisitos estão sendo
atendidos. No nosso
exemplo a execução do
programa produziu efeitos que podem ser verificados na imagem ao lado. Veja os dados
de entrada que foram fornecidos, os cálculos que foram realizados e que não
percebemos (ainda bem!) e o resultado produzido. O programa atendeu aos propósitos
estabelecidos? Sim, então trabalho concluído, caso contrário volte na 1ª etapa e faça as
correções necessárias.

Creio que agora você já possui um entendimento um pouco mais claro de programação,
mas ainda estamos começando, temos muito que estudar! Tenha paciência e entenda
que sua formação como programador será sólida se construir seu conhecimento em
etapas e com muita atividade prática. Por enquanto, sugiro que assista aos vídeos
abaixo.
2.5.1. O processo de tradução – parte I.
2.5.2. O processo de tradução – parte II.

2.6. Ambiente de desenvolvimento


Antes de prosseguir na apresentação de conceitos básicos de programação vamos fazer
uma pausa e voltar nossa atenção para aspectos mais práticos. Queremos que você
prepare as “ferramentas” adequadas para o seu trabalho como desenvolvedor. Crie o seu
ambiente de desenvolvimento.

Basicamente, precisaremos de duas ferramentas para compor nosso ambiente de


desenvolvimento. Uma delas é um editor de textos para que possamos criar o código
fonte, pode ser o bloco de notas do Windows, ou qualquer outro similar. A outra
ferramenta é um compilador específico para a linguagem C.

É importante saber que a linguagem C utiliza o processo de compilação para traduzir


programa em linguagem de alto nível para linguagem de máquina e que existem
linguagens que utilizam processos diferentes, porém com o mesmo propósito. Ao
estudar outra linguagem de programação sugiro que comece por entender o seu processo
de tradução.

O ambiente de desenvolvimento que descrevemos, é muito simples e de fácil utilização


pelo programador iniciante. Por outro lado, pode se tornar um grande limitador no
desenvolvimento de projetos mais complexos à medida que não propicia agilidade na
codificação dos programas.
Existem no mercado diversas ferramentas capazes de facilitar a tarefa de programar.
São conhecidas como IDEs (Integrated Development Environment) e disponibilizam
diversos recursos facilitadores que agilizam o trabalho do programador, aumentando sua
produtividade.

No nível em que estamos não acho adequado utilizar uma IDE muito sofisticada. É
fundamental sermos responsáveis diretos por todas as ações envolvidas em nosso
trabalho. Uma IDE pode ser prejudicial à medida que realiza alguns procedimentos
automaticamente, impedindo que programador iniciante entenda o que foi feito por
“baixo dos panos”. No futuro, quando possuir mais experiência, sugiro que pesquise e
escolha uma IDE que seja adequada às suas necessidades, você perceberá como sua
produtividade aumentará.

Existem no mercado algumas IDEs bem simples, gratuitas e adequadas para nosso atual
nível. Fique a vontade para escolher a que mais lhe agrada, qualquer que seja a escolha,
não fará diferença no aprendizado. Entretanto sugiro o uso do CodeBlocks, disponível
em www.codeblocks.org, principalmente pelo fato de ser simples, de código aberto e
compatível com a linguagem C.

Após os devidos esclarecimentos chegou o momento de preparar o seu ambiente de


desenvolvimento. Se você possui ou tem acesso a um computador, mãos a obra, assista
a vídeo sugerido e replique em seu computador as ações propostas.
2.6.1. Como instalar a IDE em seu computador.

2.7. Tipos de Dados


Já sabemos que um programa é constituído de um conjunto de instruções, codificadas
em uma linguagem de programação e que devem ser executadas pelo computador para
que o processamento de dados ocorra de forma automática.

O que não podemos perder de vista é que todo esse trabalho é realizado para resolver
algum problema envolvendo dados. E que a manipulação correta desses dados é parte
importante da solução do problema.

Já vimos duas características fundamentais do computador: processar dados


automaticamente e seguir instruções. Aliás não sei se poderíamos considerar duas
características distintas já que a segunda é que permite a ocorrência da primeira. De
qualquer forma nosso caminho de estudo está sendo direcionado para a terceira
característica fundamental que é capacidade de armazenar dados. É isso mesmo, o
computador possui memória. A combinação destas três características é que dão
singularidade ao computador.

Chegou o momento de compreender como os programadores devem referenciar, em


seus programas, os dados armazenados na memória para que sejam processados pelo
computador.
A maioria dos computadores modernos se baseia no
modelo de arquitetura proposta por Von Neumann.
Todos eles seguem uma de suas premissas, que é o
fato dos dados e instruções ficarem armazenados no
mesmo espaço de memória. De acordo com essa
arquitetura, para que o processamento ocorra,
programa e dados devem estar armazenados na
memória. Isso implica diretamente no nosso trabalho,
visto que ao criar um programa, devemos indicar os
locais na memória que serão reservados para o
armazenamento dos dados.

Esses locais, na memória do computador, que armazenam os valores a serem


processados, são conhecidos como variáveis de memória. O
valor associado a cada variável é armazenado em
“compartimentos” na memória, identificados por um endereço
único. O conteúdo armazenado nesses endereços pode variar
livremente, daí o nome variável de memória, entretanto
armazenam um valor de cada vez, ou seja, se colocarmos um
segundo valor em uma variável de memória o valor anterior é perdido.

Mas como, nós programadores, acessaremos os valores armazenados nesses endereços


de memória? Teremos que saber em qual endereço o valor de cada variável está
armazenado? Ainda bem que não! Para facilitar a referência a um endereço de memória,
as linguagens de programação permitem rotular cada endereço de memória com um
nome. O ato de rotular os endereços de memória com nomes, chamamos de declaração
de variáveis.

Além de rotular um local de memória com um nome, o ato de int telefone;


declarar uma variável determina o tipo de valor que este local float salario;
pode armazenar e por consequência as operações que char turma = ‘A’;
podemos realizar com esse valor. Veja ao lado alguns
exemplos de declaração de variáveis na linguagem C. Repare que a variável telefone foi
declarada como sendo do tipo int porque não vislumbramos a possibilidade de que
venha armazenar um valor real, apenas inteiros. Por outro lado, a variável salario não
pode ficar limitada a apenas valores inteiros, por isso a declaramos do tipo real (float).
Já a variável turma não ficará limitada a algarismos, ela poderá armazenar qualquer
caractere (letra, símbolo ou algarismo).

Você está lembrado do problema relativo ao cálculo da situação de um aluno? Voltamos


nossa atenção para ele, especificamente na linha destacada abaixo. Não se preocupe
com as demais linhas, por enquanto.
media.c versão 1.0
1 int main(){
2 float nota1, nota2, media;
3
4 printf("Informe a 1a. nota:");
5 scanf("%f", &nota1);
6
7 printf("Informe a 2a. nota:");
8 scanf("%f", &nota2);
9
10 media = (nota1+nota2)/2;
11
12 if (media >= 7){
13 printf("Aprovado!");
14 }else{
15 printf("Reprovado!");
16 }
17 return 0;
18 }

Repare que o programa manipula três dados: nota1, nota2 e media. Para que o programa
funcione corretamente nós somos obrigados a “avisar” ao computador que
necessitaremos de três locais na memória para armazenar os três valores. Esse “aviso”
foi realizado através da declaração de variáveis na linha 2. Nesta linha indicamos o tipo
de dado que pretendemos armazenar nas variáveis da lista que relacionamos em
seguida. No caso desse programa queríamos um tipo de dado próprio para valores
numéricos reais, por isso escolhemos o tipo float. Mas como saber quais os tipos de
dados disponíveis na linguagem que estou usando?

Toda linguagem de
programação fornece
diversos tipos de dados
pré-definidos, também
conhecidos como tipos de
dados primitivos. Se você
pensa em estudar uma
linguagem de
programação, sugiro
começar conhecendo seus
tipos primitivos. Repare
que cada tipo ocupa um
espaço diferente na
memória, além de definir
uma faixa de valores
possíveis.

Muitas vezes, o programador desavisado, declara variáveis que não deveriam ser
modificadas durante a execução de um programa. É o caso dos exemplos abaixo.

float PI = 3.14159;
float ACELERACAO_GRAVIDADE = 9.8;
int VELOCIDADE_LUZ = 300000;

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, ou melhor, é
mais seguro usar constantes no lugar de variáveis. Uma constante é um local de
memória cujo valor não pode ser alterado durante a execução do programa. 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


Para definirmos as constantes do exemplo anterior codificaríamos assim:

#define PI 3.12159
#define ACELERACAO_GRAVIDADE 9.8
#define VELOCIDADE_LUZ 300000

Os nomes que damos às variáveis, constantes e demais componentes num programa


escrito numa dada linguagem de programação são chamados de identificadores. Cada
linguagem de programação define regras básicas para os nomes dos identificadores. A
linguagem C impõe algumas regras, vejamos as principais.

a) Os caracteres utilizados sejam números, letras maiúsculas, minúsculas e o caractere


especial sublinha.
b) O primeiro caractere deve ser uma letra ou o sublinha.
c) Não são permitidos espaços em branco.
d) Palavras reservadas não podem ser utilizadas como identificadores.

Veja nos vídeos abaixo a utilização de variáveis de memória e constantes em situações


reais.

2.7.1. Variáveis de memória


2.7.2. Constantes

2.8. O tipo de dado boolean


Já que estamos falando de tipos de dados, é importante conhecer um tipo de dado
denominado boolean, suportado pela maioria das linguagens. Variáveis desse tipo
assumem apenas dois valores possíveis, que podem ser considerados como 0 ou 1, falso
ou verdadeiro. Normalmente os programadores utilizam variáveis booleanas quando
desejam representar dados que só assumem dois valores possíveis: pagou/não pagou,
aprovado/reprovado, masculino/feminino, dentre outros. É de responsabilidade do
programador, associar o valor 1 (true-verdadeiro) a um estado e o valor 0 (false-falso)
ao estado contrário.

A implementação do tipo boolean varia de acordo com a linguagem de programação.


Java por exemplo permite definir variáveis do tipo boolean, que podem assumir os
valores false e true. Já C, não possui um tipo específico booleano, mas permite que se
utilize o tipo int, onde assume que 0 corresponde a falso, enquanto qualquer valor
diferente de zero corresponde a verdadeiro.

Mais adiante será sugerido que assista ao vídeo “A linguagem C não tem o tipo
boolean, mas...”. Então você terá a oportunidade de compreender melhor, aguarde.

2.9. Operadores
Eu sei que você deve estar ansioso para usar o computador, não é mesmo? Tenha
paciência e disciplina para fazer o certo na hora certa. Não pule etapas, você está em
fase de preparação e quanto mais capacitado estiver melhor será a sua autonomia no
futuro.
Outra atitude desejada e que já deveria ter comentado com você é desenvolver a
habilidade de colocar o foco em uma pequena parte do objeto de estudo, para em um
segundo momento compreender o todo. Você deve ter reparado que nas listagens de
código anteriores não foi dada explicação sobre todas as instruções contidas no código,
certo? O motivo é simples: ainda não é o momento. Então peço que administre sua
ansiedade e se concentre apenas no ponto que estamos destacando naquele momento.
Chegará o tempo em que a compreensão será mais ampla, aguarde.

Para prosseguir em nossos estudos temos que ser capazes de realizar operações com as
variáveis e constantes declaradas em nosso programa. Veja o código abaixo,
responsável por calcular a área de um círculo.
areacirculo.c
1 #define PI 3.1415
2
3 int main()
4 {
5 float raio, area;
6
7 printf("Digite o raio: ");
8 scanf("%f", &raio);
9
10 area = PI * raio * raio;
11 printf("Área do círculo = %.2f \n",area);
12
13 return 0;
14 }

Destacaremos no código acima 3 linhas. Repare que na linha 1 declaramos uma


constante de nome PI. Percebeu que PI foi definida como constante porque
privilegiamos a segurança, queremos evitar que o seu valor seja alterado durante a
execução do programa. Repare que também que o nome da constante está em caixa alta,
trata-se um padrão de codificação seguido por muitos programadores e sugiro que siga.
Na linha 5 não temos novidade, apenas a declaração das variáveis envolvidas no
programa. Já na linha 10 você pode verificar a presença de alguns operadores que são
responsáveis pelo cálculo da área do círculo. Esses operadores serão o foco de estudo no
momento.

Toda linguagem de programação disponibiliza alguns operadores para que o


programador possa realizar operações com as variáveis e constantes. Veremos alguns
deles presentes na linguagem C.

Operadores Aritméticos Comentário


* Multiplicação
/ Divisão
% Módulo ou resto da divisão
+ Adição
- Subtração

Creio que todos os operadores acima são do seu conhecimento, exceto o operador
módulo. Este é responsável pelo cálculo do resto de uma divisão inteira. Para melhor
entendimento vamos apresentar um código em C. Analise o trecho de código abaixo e
responda: qual será o conteúdo da variável resto após a execução da linha 7?
Trecho de código
1 //código omitido
2
3 int resto;
4 int numero1 = 5; 5 2
5 int numero2 = 2;
6 1 2
7 resto = numero1 % numero2;
8
9 //código omitido

Vamos aproveitar o código acima para aprofundarmos mais no assunto. Nas linhas 4, 5
e 7 foi utilizado o operador de atribuição (=), não confunda com o operador de
igualdade (= =), que veremos adiante. Uma leitura errada e comum aos iniciantes em
programação é a de que a variável numero1 é igual a 5. O correto seria: o valor 5 será
atribuído à variável numero1; que o valor 2 será atribuído à variável numero2 e
finalmente, que o cálculo do resto da divisão do numero1 por numero2 será atribuído à
variável resto.

Veja também que nas linhas 4 e 5, as atribuições foram realizadas na mesma linha em
que a variável foi declarada, mas poderíamos realizar a operação em dois momentos
distintos conforme abaixo.

Trecho de código
1 //código omitido
2
3 int resto;
4
5 int numero1;
6 numero1 = 5;
7
8 int numero2;
9 numero2 = 2;
10
11 resto = numero1 % numero2;
12
13 //código omitido

Entenda que o computador executa operações de atribuição em dois momentos.


Primeiro é realizado as operações à direita do sinal de atribuição e em um segundo
momento, esse resultado é atribuído à variável indicada à esquerda do operador de
atribuição. Por esse motivo é que explicamos a forma correta de interpretar uma
operação de atribuição.

Já que entendeu, responda: qual o valor da variável salario após a execução da linha 4
do trecho de código abaixo?

Trecho de código
1 //código omitido
2
3 float salario = 1000;
4 salario = salario + 100;
5
6 //código omitido

Como é impossível que o valor de uma variável seja igual a ele mesmo acrescido de
100, só nos resta ler da forma correta: o resultado da operação à direita (salario + 100)
será atribuído à variável salario, ou seja, estamos realizando uma operação de
acumulação. Finalizando com a resposta correta: Após a execução da linha 4 o valor da
variável salario será de 1100.

Operadores Relacionais Comentário


> Maior
>= Maior ou igual
< Menor
<= Menor ou igual
== Igualdade
!= Diferente

Os operadores relacionais são usados quando precisamos elaborar uma expressão


condicional que verifique uma relação de igualdade, diferença, maior, menor dentre
outras, entre os dados de um programa.

Operadores Lógicos Comentário


&& E
|| OU

Já os operadores lógicos são usados para formar uma expressão condicional composta
por várias condições. É um operador que conectará essas diversas condições.

Vejamos o exemplo de uma expressão condicional para determinar se o aluno está


aprovado, composta por duas condições. A primeira condição é a nota ser maior do que
6,0 e a segunda condição é que o número de faltas do aluno seja inferior ou igual a 18
aulas. Como você elaboraria essa expressão? Escolha uma opção abaixo.

a NOTA >= 6,0 E FALTAS <= 18

b NOTA >= 6,0 OU FALTAS <= 18

Por enquanto não se pode determinar qual é a opção correta. Você só terá condições de
decidir quando souber a regra utilizada pela escola para determinar a aprovação de um
aluno. Tenho uma boa dica: Use o operador “E” (&& em C) se deseja que todas as
condições sejam obedecidas e use o operador “OU” (|| em C) quando pelo menos uma
condição sendo obedecida já é suficiente.

Voltemos ao caso das duas opções propostas acima. Eu usaria a opção 1 se para ser
aprovado o aluno tivesse que obedecer às duas condições: nota maior ou igual a 6 e
também a quantidade de faltas ser menor do que 18.

Mas para o caso de uma escola mais liberal, em que bastaria o aluno obedecer pelo
menos uma condição, eu escolheria a opção 2. Nesse caso o aluno estaria aprovado se
sua nota for maior ou igual a 6 ou a quantidade de faltas for menor do que 18, qualquer
uma das condições seria o suficiente para aprovação.

Imagine dois conjuntos, um formado pelos elementos


que obedecem à condição A e outro pelos elementos
que obedecem à condição B. Se estiver interessado
nos elementos presentes nos dois conjuntos
simultaneamente, ou seja, na interseção entre os
conjuntos (A Ո B) use o operador lógico “E”. Agora
se estiver interessado em qualquer elemento presente
na união dos dois conjuntos (A Ս B) use o operador
lógico “OU”.

Para concluir apresentaremos alguns operadores especiais da linguagem C, que resultam


da combinação de operadores aritméticos com operadores de atribuição. Veja abaixo.

Operador Operação similar


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

Acho que a tabela é autoexplicativa, porém, repare que ambos os operadores de


incremento (++) e decremento (--) podem ser utilizados como prefixo ou sufixo do
operando. Veja os exemplos abaixo para entender a diferença.

Trecho de código
1 //código omitido
2
3 int x;
4 int y = 6;
5 int z = 2;
6 x = y / ++z; //operador de incremento pré-fixo
7
8 //código omitido

Analisaremos execução da linha 6. 1º passo: o valor de z será pré-incrementado e em


seguida utilizado na operação, portanto o valor de z será alterado para 3. 2º passo:
calcula-se a divisão de y por z, que será 2. 3º passo: atribui o resultado da expressão,
que é 2, a variável x.
Trecho de código
1 //código omitido
2
3 int x;
4 int y = 6;
5 int z = 2;
6 x = y / z++; //operador de incremento pós-fixo
7
8 //código omitido

Com a mudança sutil do operador de incremento para pós-fixo o resultado do programa


será diferente.

Analisaremos novamente a execução da linha 6. 1º passo: o valor de z será pós-


incrementado, ou seja, será incrementado somente após a execução da linha, portanto,
por hora, será o usado o valor anterior de ‘z’, que é 2. 2º passo: calcula-se a divisão de y
por z, que será 3. 3º passo: atribui o resultado da expressão, que é 3, a variável x. 4º
passo: devido ao uso do pós-incremento, agora que a variável z terá seu valor atualizado
para 3.

Percebeu a diferença? Olhe que na versão com pré-incremento a variável x recebe o


valor 2, já na versão com pós-incremento a mesma variável recebe o valor 3. Tudo isso
pela possibilidade de operadores de incremento (++) e decremento (--) serem utilizados
tanto como prefixo, quanto sufixo do operando. Cuidado!

Agora chegou o momento de assistir aos vídeos que demonstrarão o uso dos operadores
aritméticos e do operador módulo. Apresentamos também um vídeo de alerta aos
programadores para situações em que pode ocorrer perda de informação.

2.9.1. Operadores aritméticos e operador módulo


2.9.2. Cuidado com a perda de informação
3. PRIMEIROS PASSOS

3.1. 1º Passo: análise do problema e projeto da solução


A análise e projeto de uma solução é o momento mais importante do trabalho de um
programador. Infelizmente é muito negligenciado. Lembre-se de que o nosso objetivo é
criar soluções para problemas através de programas. Se não conhecemos a solução de
um problema não conseguiremos instruir o computador a resolvê-lo.

Quanto mais negligenciada for essa fase maior será o custo para desenvolver a solução.
Estamos falando de uma fase anterior à codificação, esqueça o computador por
enquanto e concentre-se no problema.

Na maioria das vezes você não terá domínio da área de conhecimento em que o
problema está inserido. Como já comentei anteriormente, isso é normal. O que não é
normal é ficar impedido de desenvolver uma solução pelo fato de não conhecer um
determinado assunto. Proponho uma ação bem simples e que pode ajudá-lo: leia a
especificação do problema, pesquise, converse com o seu cliente ou chefe até que você
seja capaz de identificar as três partes que todo programa possui.

3.2. 2º Passo: identificar as três partes do programa


1. Dados de saída: Identificar e analisar todas as saídas exigidas na especificação do
problema. Assim você saberá o que o programa deverá produzir como resultado.
Utilize isso como forma de validar o seu programa.

2. Dados de entrada: Identificar e analisar todas as entradas citadas na especificação do


problema. Estamos nos referindo a toda informação necessária ao processamento,
sem as quais nada será produzido.

3. Processamento: Identificar todas as transformações necessárias para, dadas as


entradas e valores gerados internamente, produzir as saídas especificadas. Pense em
quais cálculos deverão ser realizados? Quais condições devem ser obedecidas para
uma determinada ação? Qual a sequência em que as instruções devem ser
executadas?

3.3. 3º Passo: elaborar o algoritmo


Para o iniciante é altamente recomendado que siga a proposta acima e em seguida
construa o algoritmo, seja em portugol, fluxograma ou descrição narrativa. Agindo
assim você terá mais facilidade na construção da solução.

3.4. 4º Passo: codificação em linguagem de programação


Com a experiência você perceberá que essa é a etapa menos complexa, desde que tenha
realizado os passos anteriores com êxito. Tenha em mente que toda dificuldade nessa
etapa é fruto de deficiências nas etapas anteriores.
3.5. O primeiro problema
Está lembrando o que combinamos no início do livro? Pois bem, apresentaremos uma
situação problema e a solução através de um programa.

Aproveitaremos todo o processo de construção da solução, do problema que será


proposto, para introduzir quatro conteúdos:

− Módulos de programa (funções).


− Bibliotecas de programas.
− Instruções para saída de dados.
− Instruções para entrada de dados.

Desta vez faremos juntos, principalmente pela introdução dos três conceitos acima, mas
fique preparado que na próxima vez é por sua conta, combinado? Vamos à
especificação do problema.

Um alpinista deseja instalar uma tirolesa no alto de uma estrutura metálica. Por motivos
de segurança ele deseja que o ângulo formado pela corda em contato com o solo seja de
30º e que a distância entre o ponto de apoio no solo e a base da estrutura metálica seja
de 100 metros. Ele está precisando de uma solução confiável para calcular a medida da
corda que ligará o topo da estrutura metálica ao solo. Deseja saber também a altura que
a estrutura metálica deve ter. Esses cálculos serão necessários para que ele possa
comprar a corda e encomendar a construção da estrutura metálica.

3.5.1 1º Passo: análise do problema e projeto da solução

Vamos à solução. Mas antes preciso lhe perguntar: já está sentado em frente ao
computador ligado e pronto para trabalhar? Sinto muito em desapontá-lo, mas começou
errado. Sugiro que desligue o computador, não precisaremos dele agora. Aliás, se você
começar a codificar agora, existe uma possibilidade muito grande de demorar mais
tempo do que o necessário, ou pior, não atender às necessidades do usuário, no caso o
alpinista. Analise o fluxo abaixo.

Domino o
Sim problema Não
?

Codificar Pesquisar, projetar,


o programa pensar, conversar,
estudar, etc

Então vamos continuar. Em um mundo sem computador, como você resolveria o


problema? Isso mesmo: apenas com o cérebro, lápis e papel. Então vamos usá-los para
criar um esboço da solução, pode ser um desenho, uma fórmula, o que achar melhor.
Veja o esboço da solução abaixo. Saiba que o esboço foi construído com base na
especificação fornecida.
Topo da estrutura metálica

Corda da tirolesa
Estrutura
metálica Ponto de apoio no solo
30o
100m

3.5.2 2º Passo: identificar as três partes do programa

Vamos agora identificar as três partes que todo programa possui. Faremos a
identificação das partes relativas à solução para o problema do alpinista. Repare que
essas três partes do programa estão relacionadas às etapas do processamento de dados.
As instruções em um programa devem refletir as ações envolvidas no processamento de
dados que são entrada, saída e processamento propriamente dito.

Dados de saída
Medida da corda
Altura da estrutura metálica

Dados de entrada
100m - Distância entre o ponto de apoio e a base da estrutura
30o – Ângulo formado pela corda da tirolesa com o solo

Processamento

Precisamos calcular os dados de saída: medida da corda e altura da


estrutura metálica. A solução para o problema depende do nosso
conhecimento sobre as relações trigonométricas de um triângulo retângulo,
veja abaixo.

𝑐𝑎𝑡𝑒𝑡𝑜 𝑎𝑑𝑗𝑎𝑐𝑒𝑛𝑡𝑒 100 𝟏𝟎𝟎


cos 𝛼 = cos 𝛼 = 𝐜𝐨𝐫𝐝𝐚 =
ℎ𝑖𝑝𝑜𝑡𝑒𝑛𝑢𝑠𝑎 𝑐𝑜𝑟𝑑𝑎 𝐜𝐨𝐬 𝜶

𝑐𝑎𝑡𝑒𝑡𝑜 𝑜𝑝𝑜𝑠𝑡𝑜 𝑎𝑙𝑡𝑢𝑟𝑎 𝑒𝑠𝑡𝑟𝑢𝑡𝑢𝑟𝑎


sen 𝛼 = sen 𝛼 = altura estrutura= 𝐬𝐞𝐧 𝜶 ∗ 𝒄𝒐𝒓𝒅𝒂
ℎ𝑖𝑝𝑜𝑡𝑒𝑛𝑢𝑠𝑎 𝑐𝑜𝑟𝑑𝑎

3.5.3 3º Passo: elaborar o algoritmo

Parece que agora já possuímos um domínio muito bom sobre o problema. Já somos
capazes de apresentar uma solução através de um algoritmo. Repare na informalidade
das instruções abaixo, é a característica de um algoritmo. O importante é o significado
de cada palavra, a sequência de instruções e a lógica utilizada para representar a solução
do problema.
Algoritmo do alpinista
inicio
variáveis: corda, altura, angulo, distancia

distancia = 100 Entrada


ângulo = 30

corda = (distancia / coseno(angulo)) Processamento


altura = seno(angulo) * corda

mostra(corda)
mostra(altura) Saída
fim.

Repare como o algoritmo reflete a nossa análise anterior, onde identificamos as partes
de um programa. Veja também que a ordem das instruções combina com a sequência
em que o processamento de dados ocorre.

Para você que não tinha conhecimento ou não se lembrava sobre as relações
trigonométricas de um triângulo retângulo, não fique preocupado. Na realidade não é o
programador que soluciona um problema, você é apenas um intermediário entre o
problema e o computador. Quem conhece o problema e sabe resolvê-lo é o usuário. O
programador surge como o elemento que viabiliza a solução do problema através do
computador.

E pode ter situações em que usuário não poderá ajudá-lo. No problema do alpinista, por
exemplo, não foi informada a solução matemática na especificação do problema, ou
seja, o alpinista também não sabe trigonometria. Tivemos que improvisar e pesquisar,
talvez pedir ajuda a um professor de matemática, ou outro método qualquer. O que
importa é a capacidade que o programador possui de resolver problemas. Essa talvez
seja a principal característica de um bom programador.

3.5.4 4º Passo: codificação em linguagem de programação

Bom, já realizamos o trabalho mais complexo, acredite. Agora vem a parte mais
simples, que é codificar o programa em linguagem C.

alpinista.c
1 main(){
2 float corda, radianos, altura;
3
4 radianos = 3.14159265 * 30 / 180;
5 corda = (100 / cos(radianos));
6
7
8 printf("\nMedida da corda: %.2f", corda);
9 altura = sin(radianos) * corda;
10 printf("\nAltura da Estrutura Metálica: %.2f", altura);
11 }

Creio que haja poucos esclarecimentos a serem feitos, já que o programa acima
apresenta muita semelhança com o algoritmo em portugol. Entretanto vamos comentar
aquilo que creio ser sua dúvida ou aquilo que de propósito foi planejado estudar agora,
que são: funções, bibliotecas, instruções de entrada e saída.
3.6 Funções e bibliotecas
Começamos pelo conceito de módulo de programa ou funções. Módulos são blocos de
instruções com função bem delimitada. Por isso são conhecidos, na linguagem C, como
funções. Na linguagem C, existem diversas funções já predefinidas e disponíveis para
os programadores da linguagem. Essas funções são agrupadas em arquivos, por
afinidade, desta forma esses arquivos são conhecidos como bibliotecas. Uma biblioteca
é formada por um conjunto de funções afins, por exemplo, biblioteca de funções
matemáticas, de manipulação de data e hora, dentre muitas outras.

As linguagens de programação, de uma forma geral, apresentam recursos similares a


este da linguagem C, porém utilizam termos diferentes como método, script, dentre
outros. O importante é você saber que a ideia central é a mesma da apresentada pelas
funções da linguagem C.

Vamos relacionar esse novo conceito com o programa do alpinista.c apresentado


anteriormente. Veja que usamos duas funções, cos (linha 5) e sin (linha 9), ambas estão
codificadas em uma biblioteca de nome Math da linguagem C. Elas são responsáveis
por calcular respectivamente o coseno e seno de um ângulo. Se tiver curiosidade, ao
pesquisar sobre essas funções saberá que elas exigem que o ângulo esteja expresso em
radianos, por isso que na linha 4 do programa nós realizamos a conversão de graus para
radianos.

Ah! Então, para ser programador eu tenho que saber como converter ângulos? Tenho
que saber as relações trigonométricas? Claro que não! Imagine se para cada problema
que o programador fosse resolver ele tivesse que antes se tornar um especialista. Isso
seria muito limitante. Entretanto é responsabilidade do programador conhecer o bastante
do problema para que consiga achar uma solução, caso contrário seu trabalho fica
impedido de se realizar. Existem diversas disciplinas na área de TI que desenvolvem
essas competências e que por questão de foco, não abordaremos aqui.

Mas continuando a analisar a listagem. Lembra quando falamos que para criar um
programa executável devemos unir o nosso programa fonte a outros programas, já
codificados? Esta ligação é necessária porque em nosso programa nos referimos a
funções que não estão codificadas em nosso programa e sim em sinônimo. Se achar
necessário volte a assistir aos vídeos sobre o processo de tradução de programas.
3.6.1 Invocando uma função

3.7 Instrução de saída de dados


Continuando os esclarecimentos do programa alpinista.c. Veja que main é o nome da
função principal do nosso programa e que no seu interior nos referimos a diversas
outras funções. Já explicamos as funções cos e sin, agora nos dedicaremos à função
printf.

Essa função é de grande importância em um programa em C, já que permite a


visualização dos resultados do processamento realizado. Este procedimento é conhecido
como saída de dados. Os dados de saída podem ser apresentados em qualquer
dispositivo de saída ligado ao computador (vídeo, impressora, discos, dentre outros).
Em nosso curso utilizaremos o vídeo como dispositivo padrão para saída de dados e na
linguagem C, a função responsável por esta tarefa é a printf. Segue abaixo sua sintaxe.
printf(“string de controle”, lista de variáveis).

O primeiro argumento da função printf é chamado de string de controle. A string de


controle é formada pelo texto a ser impresso e opcionalmente caracteres e códigos de
formatação. Veja os quadros abaixo.

Código de Comentário
Formatação
\n Força a mudança de linha do cursor.
\t Força o avanço de tabulação do cursor.

Caractere de Comentário
Formatação
%c Caractere simples
%d Decimal
%f Ponto flutuante
%s Cadeia de caracteres (string)
%u Decimal sem sinal
%e Notação científica

No segundo argumento da função pritnf, devemos informar o valor a ser exibido. Deve
haver tantos argumentos após a string de controle quantos forem os caracteres de
formatação.

Para facilitar o entendimento, apresentamos abaixo um trecho de programa que


exemplifica o uso da função printf em diferentes situações.
Exemplo da função printf
1 //código omitido
2
3 int idade = 15;
4 char nome[40] = “Jose da Silva”;
5 char turma = 'A';
6 float media = 8.5;
7
8 printf(“\nA idade é %d”, idade);
9 printf(“\nA idade do %s é %d”, nome, idade);
10 printf(“\nA média da Turma %c foi de %f”, turma, media);
11
12 //código omitido

Vejamos o efeito das instruções do exemplo acima.


Linha da Comentário
Instrução
4 Declaramos uma string. Por enquanto basta saber que string é uma
cadeia de caracteres. Estudaremos strings mais adiante. E toda
string para ser reconhecida como tal pelo compilador deve estar
entre aspas duplas.
5 Todo caractere, para ser reconhecido pelo compilador deve estar
entre aspas simples.
8 Haverá uma mudança de linha na tela do computador e em seguida
aparecerá em uma nova linha o seguinte texto: A idade é 15
9 Saída produzida: A idade do Jose da Silva é 15
10 Saída produzida: A média da Turma A foi de 8.5

Sugiro assistir aos vídeos abaixo para que tenha melhor compreensão do procedimento
de saída de dados, de “chamada” ou invocação de função, das bibliotecas e de um
aspecto importante para a produtividade de um programador que é a depuração de
programas. Saiba que depurar é o processo de encontrar e retirar erros de um programa.

3.7.1 Saída de dados – parte I


3.7.2 Saída de dados – parte II
3.7.3 O processo de depuração

3.8 Instrução de entrada de dados


Tão importante quanto proceder à saída de dados é obter informações necessárias ao
processamento. Este procedimento é conhecido como entrada de dados. Os dados de
entrada podem ser enviados de qualquer dispositivo de entrada ligado ao computador
(teclado, discos, mouse, dentre outros).

Em nosso curso utilizaremos o teclado como dispositivo padrão de entrada de dados. Na


linguagem C, a função responsável por esta tarefa é a scanf. Ela permite operações de
entrada de dados, ou seja, a leitura de dados após pressionar a tecla enter. Segue abaixo
sua sintaxe.
scanf (“string de controle”, lista-argumentos)

exemplo da função scanf


1 //código omitido
2
3 printf("Digite a distancia:");
4 scanf("%d", &centimetro);
5
6 //código omitido

Linha Comentário
3 Uma ação muito comum em programas é orientar o usuário a tomar alguma
atitude. Nesse caso a função printf está sendo usada apenas para mostrar uma
mensagem ao usuário de como proceder.
4 A função scanf causa uma pausa no programa, ficando em estado de espera. O
Usuário digita a informação desejada e tecla enter para que a informação
digitada seja atribuída à variável utilizada na operação de entrada, que no nosso
exemplo é centimetro. Em seguida o fluxo de execução continua e a próxima
instrução será executada. O comando scanf exige que seja informado o endereço
da variável e não simplesmente o nome da variável. Utilizamos o & para
referenciar o endereço de uma variável.

Lembre-se: quando uma variável é declarada, é alocado um espaço na memória


correspondente ao seu tipo. Este espaço, que a variável ocupa, possui um
endereço que pode ser acessado usando o operador &. A string de controle
presente na função scanf tem o mesmo comportamento que já conhecemos da
função printf.

Existem outras funções, na linguagem C, que permitem a entrada de dados. A função


getche, por exemplo, lê e retorna um caractere do teclado sem esperar enter e permite
que o mesmo seja impresso na tela. Já a função getch, tem o mesmo comportamento,
entretanto não permite que o caractere informado pelo usuário seja impresso na tela.
Mas atenção, essas funções somente poderão ser usadas para a leitura de um único
caractere, mais adiante veremos como ler uma cadeia de caracteres (strings).
exemplo das funções getche e getch
1 //código omitido
2
3 printf(“Digite a turma:”);
4 char turma = getche();
5 printf(“Tecle algo para continuar ...”);
6 getch();
7
8 //código omitido

Linha Comentário

4 A função getche causa uma parada no programa, o usuário digita um caractere


que é atribuído à variável turma e em seguida o programa continua.

6 A função getch causa uma parada no programa, o usuário digita um caractere


que não será mostrada na tela e nem é armazenado em variável, pois só foi
utilizado para provocar uma pausa no programa. Em seguida o programa
continua.

3.8.1 Entrada de dados


3.8.2 Limpando o buffer do teclado
3.9 Conclusão
Convido você a reavaliar o programa alpinista.c, agora com a perspectiva de quem
compreendeu o que estudamos até o momento.
alpinista.c
1 main(){
2 float corda, radianos, altura;
3
4 radianos = 3.14159265 * 30 / 180;
5 corda = (100 / cos(radianos));
6
7
8 printf("\nMedida da corda: %.2f", corda);
9 altura = sin(radianos) * corda;
10 printf("\nAltura da Estrutura Metálica: %.2f", altura);
11 }

Agora responda: qual a grande limitação da versão atual do programa? Se você ainda
não percebeu imagine a situação abaixo.

Após a codificação do programa você gerou o executável, entregou-o ao alpinista e


recebeu o pagamento pelo serviço. O dinheiro nem chegou a “esquentar” na sua mão e
recebeu uma mensagem do alpinista perguntando: como eu faço para considerar a
distância entre a estrutura metálica e o ponto de apoio no solo diferente de 100 metros?
E mais, como considerar um ângulo diferente de 30º?

Percebeu a limitação desta versão do programa? Ainda bem que você compreendeu bem
o papel das instruções de entrada. Veja a nova versão a seguir, ela está muito mais
flexível, permite que o usuário defina os valores de entrada.
alpinista.c versão 2.0
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <locale.h>
4 #include <math.h>
5
6 #define PI 3.14159265
7
8 main(){
9 setlocale(LC_ALL, "Portuguese");
10
11 float corda, radianos, altura, graus, distancia;
12
13 printf("\nÂngulo entre a corda e o solo [Em graus]: ");
14 scanf("%f", &graus);
15
16 printf("\nDistância entre a estrutura metálica e o ponto de apoio no solo: ");
17 scanf("%f", &distancia);
18
19 radianos = PI * graus / 180;
20 corda = (distancia / cos(radianos));
21 altura = sin(radianos) * corda;
22
23 printf("\nMedida da corda.............: %.2f", corda);
24 printf("\nAltura da estrutura metálica: %.2f", altura);
25 }
Linha Comentário

1a4 A diretiva de compilação #include indica a biblioteca necessária para que o


compilador possa vincular as funções referenciadas no programa à sua
implementação na biblioteca indicada. Para saber qual a biblioteca que uma
função pertence basta uma rápida pesquisa na Internet ou algum
livro/manual da linguagem utilizada.

6 Aqui estamos sendo seguros, já que não pretendemos alterar o valor de PI,
definimos uma constante. A diretiva de compilação #define indica valores
que não podem ser alterados durante a execução do programa.

8 e 25 Veja a presença uma chave aberta e outra fechada. Indicam início e fim de
um bloco de comandos. No nosso caso delimitam as instruções que
pertencem à função main.

9 Você já percebeu que as saídas que envolviam acentuação eram


apresentadas com problemas. Isso se deve ao fato que seu programa não
está de acordo com as configurações regionais do seu computador. Para
corrigir basta usar a instrução da linha 9. Ou se preferir use
setlocale(LC_ALL, "") para indicar que será usado a configuração
atualmente definida em seu sistema operacional.

Para concluir, sugiro assistir aos vídeos abaixo. Realizarei todos os procedimentos
citados nessa seção, desde a análise do problema até a solução via programa.

3.9.1 Análise do problema do IMC


3.9.2 Codificação do programa do IMC

3.10 Atividades

1) Quais as saídas produzidas pelos programas abaixo. Dica: utilize o “teste de mesa”
para auxiliar na depuração dos programas.
programa 1
26 main(){
27 int a=0;
28 a=a+1;
29 a=a+2;
30 a=a+3;
31 printf("%d", a);
32 }

programa 2
1 main(){
2 int a;
3 a=1;
4 ++a;
5 printf("%d", a++);
6 printf("%d", a);
7 }
programa 3
1 main(){
2 int a;
3 a=1;
4 a++;
5 printf("%d", ++a);
6 printf("%d", a);
7 }

programa 4
1 main(){
2 int i=1, j=2, k=3, l=4;
3 i++;
4 k=++i;
5 l=j++;
6 ++j;
7 printf("%d %d %d %d", i, j, k, l);
8 }

2) Copie e cole o programa abaixo em seu ambiente de desenvolvimento. Ao executar


perceberá alguns erros. Primeiro procure identificar e diferenciar os erros de
compilação dos de execução. A apresentação da palavra “Média” está com
acentuação incorreta, faça a correção. Sua tarefa é eliminar todos os erros e fazer o
programa funcionar corretamente. Atenção: Programa que executa não é sinônimo
de programa correto.

#include <stdio.h>
#include <stdlib.h>

int main()
{
float nota1, nota2, media

printf("Informe a Nota 1: ");


scanf("%d", nota1);

printf("Informe a Nota 2: ");


scanf("%d", nota2);

media = nota1 + nota2 /2;

printf("Média: %d", media);

return 0;
}

Apresentamos a seguir problemas em que você deverá criar a solução completa em


forma de programa. Coloque em prática tudo que aprendeu e não se esqueça dos quatro
passos que sugerimos para elaborar a solução de um problema:

1º Passo: análise do problema e esboço de projeto da solução


2º Passo: identificar as três partes do programa
3º Passo: elaborar o algoritmo
4º Passo: codificação em linguagem de programação
3) Procure entender a finalidade da função Sleep presente em uma das bibliotecas da
linguagem C. Em seguida codificar um programa capaz de apresentar a seguinte
mensagem na tela: “Programa em estado de espera por X segundos”. O programa
deve ser finalizado após apresentar a mensagem pelo tempo, em segundos,
determinado pelo usuário.

4) Um haras está com dificuldade em calcular a quantidade de ferraduras necessárias


para equipar todos os cavalos hospedados. Crie uma solução para o problema em
forma de programa.

5) Um professor de matemática deseja disponibilizar aos seus alunos um programa


capaz de calcular a potência de determinado número inteiro. Exemplos: 24, 35, etc. O
professor espera que os alunos utilizem o programa como forma de averiguar os
cálculos realizados manualmente.

6) Determinar a média ponderada das três notas de um aluno. Considerar que os pesos
das notas são 2, 3 e 5, respectivamente.
4. CONTROLE DO FLUXO DE EXECUÇÃO

Agora vamos subir um pouco o nível e nos dedicar ao trabalho central de todo
programador, que é controlar o fluxo de execução de um programa. Você percebeu que
em todos os programas desenvolvidos até agora, as instruções são executadas, uma após
a outra em uma sequência, da primeira até a última. Isso nem sempre será desejável.

Haverá situações em que determinadas instruções dependerão de alguma condição para


que sejam executadas ou que sejam executadas repetidas vezes. Reflita: você acha que
as instruções que calculam o valor do auxílio doença devem ser executadas para todo
funcionário de uma determinada empresa? Que esse cálculo só deva ser realizado para
um funcionário?

Para exemplificar vamos voltar ao cálculo do índice de massa corpórea (IMC) de um


indivíduo e incorporar uma funcionalidade capaz de indicar a necessidade de se realizar
um procedimento de perda de peso. É óbvio que essa indicação de perda de peso só
deve ser realizada se IMC for superior ou inferior a um determinado valor. Perceberam
a vinculação de uma ação, indicação de perda de peso, a uma condição, IMC maior que
um determinado valor?

Agora imagine outra situação em que o cálculo do IMC deverá ser realizado diversas
vezes para várias pessoas. Neste caso devemos indicar quais instruções deverão ser
executadas repetidas vezes e até quando.

Já ficou claro que nessas situações citadas estamos limitados, não conseguiremos
codificar um programa usando somente a estrutura sequencial de instruções, como
fizemos até agora. Necessitaremos de estruturas de controle que implementem a
alternativa e a repetição. Analisaremos cada uma separadamente.

4.1 Sequência
A sequência é uma estrutura presente em todo o programa. Na linguagem C as
instruções em sequência são delimitadas por chaves e executadas uma após a outra,
do início ao fim da sequência.

sequência
{
Comando-1;
Comando-2;
...
Comando-n;
}

4.2 Alternativa Simples


É uma estrutura que permite estabelecer alternativa ao fluxo de execução de um
programa, baseada no resultado de uma expressão condicional. Assim podemos
fugir da rigidez imposta pela sequência, onde todos os comandos são
executados.
Na linguagem C um dos comandos responsáveis por estabelecer alternativa é o if. A
sintaxe desse comando pode variar em diferentes linguagens de programação, mas o
importante é saber que o propósito é similar.

Veja a representação da alternativa simples através de fluxograma, portugol e em


seguida através da linguagem C.

(Fluxograma) (Portugol)
se (expressão condicional) então
c1;
c2;
.
Condição verdadeira .
.
cn;
C1 fim-se
falsa
C2

Cn

(Linguagem C)
if (expressão condicional) {
c1;
c2;
.
.
.
cn;
}

Perceba nos esquemas acima, que o comando if é responsável por decidir o fluxo de
execução, após calcular o resultado da expressão condicional. Caso o resultado seja
verdadeiro os comandos internos ao comando if serão executados. Caso contrário, os
comandos internos ao if não serão executados. Em ambas as situações o fluxo de
execução continuará na primeira instrução após o fim do if. Lembre-se de que em C e
em muitas linguagens, o início e fim de um bloco são delimitados pelas chaves.

É importante lembrar, do que já foi estudado. Vimos que uma expressão condicional
pode ser constituída de várias condições, que normalmente usam-se os operadores
relacionais para estabelecer uma condição e que os operadores lógicos (e, ou) são
usados em casos que a expressão condicional é composta por várias condições. Leve
isso em consideração quando implementar uma alternativa em seus programas.
4.2.1 Alternativa simples
4.2.2 A linguagem C não tem o tipo boolean, mas...

Para usarmos as estruturas condicionais em nossos programas é importante a


compreensão do tópico sobre os operadores lógicos (e, ou). Caso ainda tenha dúvida
sugiro que assista aos vídeos abaixo.

4.2.3 Operador lógico E


4.2.4 Operador lógico OU

4.3 Alternativa Composta


A diferença aqui é a disponibilização de duas alternativas ao fluxo de execução do
programa. Veja o esquema abaixo.

(Fluxograma)

falsa Condição Verdadeira

C’1 C1

C’2 C2

C’n Cn

(Portugol)

se (expressão condicional) então


c1;
c2;
...
cn;
senão
c’1;
c’2;
...
c’n;
fim-se
(Linguagem C)
Veja ao lado a implementação da alternativa
composta, em C. Perceba que se a expressão if (expressão condicional){
c1;
condicional for verdadeira os comandos c1, c2, …, c2;
cn serão executados, caso contrário os comandos ...
c’1, c’2, ..., c’n é que serão executados. A palavra cn;
}else{
else faz parte o comando if e é opcional. Só é usada c’1;
em casos de alternativa composta. c’2;
...
c’n;
}

4.3.1 Alternativa composta

4.4 Alternativa Múltipla


É uma estrutura ideal para situações onde há diversas alternativas de execução.

Expressão
Ordinal

Caso 1 Caso 2 Caso n

comandos_ comandos_ ... comandos_


1 2 n1

switch (expressão ordinal) {


Veja ao lado uma implementação da case constante1: instrucoes;
alternativa múltipla em linguagem break;
C.
case constante2: instrucoes;
break;
O resultado da expressão ordinal ...
(cujo resultado deve ser do tipo char
ou int) será comparado com cada default: instrucoes;
constante informada após a palavra }
case. Sendo igual, todos os
comandos relacionados ao case, serão executados até que um comando break seja
encontrado. O comando break causa o desvio do fluxo de execução para a primeira
instrução após o switch. Se não existir um comando break seguindo as instruções de um
case, o programa segue executando as instruções dos cases seguintes. Se nenhum case
for satisfeito a execução começa na primeira instrução após o default, que por sua vez é
opcional. Cada case pode ter várias instruções e não devem estar entre chaves.

Assista aos vídeos abaixo para compreender melhor a alternativa múltipla, suas
características e limitações.

4.4.1 Alternativa múltipla com if


4.4.2 Alternativa múltipla com switch – parte I
4.4.3 Alternativa múltipla com switch – parte II

4.5 Atividades

1. Informe as saídas produzidas pelos trechos de programa abaixo.


Atividade 1.1
main() {
int nota, faltas;
nota = 100;
faltas = 15;
if (nota >= 60 && faltas <= 18){
printf("Aluno aprovado.");
}else{
printf("Aluno Reprovado.");
}
}

Atividade 1.2
main() {
int nota, faltas;
nota = 50;
faltas = 25;
if (nota >= 60 && faltas <= 18){
printf("Aluno aprovado.");
}else{
printf("Aluno Reprovado.");
}
}
Atividade 1.3
main() {
int nota, faltas;
nota = 50;
faltas = 5;
if (nota >= 60 faltas <= 18){
printf("Aluno aprovado.");
}else{
printf("Aluno Reprovado.");
}
}
Atividade 1.4
main() {
int nota, faltas;
nota = 50;
faltas = 5;
if (nota < 60 || faltas > 18){
printf("Aluno Reprovado.");
}else{
printf("Aluno Aprovado.");
}
}

Atividade 1.5
main() {
int x = 10;
if (x){
printf("Executou a linha 1”);
}else{
printf("Executou a linha 2”);
}
}

Atividade 1.6
main() {
int x = 10;
if (x-10){
printf("Executou a linha 1”);
}else{
printf("Executou a linha 2”);
}
}

2. Quais as saídas produzidas pelo trecho de programa abaixo.


main(){
int a=10, b=10, c=2;

if (a){
printf("\num");
}else{
printf("\ndois");
}

if (a-b){
printf("\ntres");
}else{
printf("\nquatro");
}

if (a>b){
printf("\ncinco");
}else{
printf("\nseis");
}
if (!(a>b)){
printf("\nsete");
}else{
printf("\noito");
}

if (a == b && c > a){


printf("\nnove");
}else{
printf("\ndez");
}

if (a == b || c > a){
printf("\nonze");
}else{
printf("\ndoze");
}
}

3. Codificar um programa que seja capaz de verificar se um número é divisível por


outro.

4. Codificar um programa para verificar a situação de um aluno (Aprovado ou


reprovado) ao final do período letivo. Sabe-se que:

a. Serão realizadas 4 provas no período letivo no valor de 0 a 100.


b. O período letivo é composto de 72 aulas.
c. Para ser aprovado o aluno deverá obter média aritmética das notas superior a
60 e faltas inferior a 25% do total de aulas.

5. Codificar um programa que informe a quinzena a que pertence um determinado dia


do mês.

6. Faça um programa que dado o dia e o mês na forma numérica e imprima o mês e a
quinzena por extenso.

7. Codificar um programa para verificar se 3 valores inteiros podem ser lados de um


triângulo. Em caso positivo o programa deverá indicar o tipo de triângulo (escaleno,
isósceles ou equilátero).
4.6 Repetição
A experiência adquirida no desenvolvimento de programas, até o momento, já
permite algumas reflexões. Percebeu que em todos os problemas solucionados,
havia um padrão? E que sem a compreensão desse padrão não seria possível
criar uma solução aplicável a diversas situações?

Quando observamos padrões de ações, somos capazes de definir uma rotina e por
consequência vislumbramos uma solução para o problema. Em seguida, através de um
programa, somos capazes de replicar a solução do problema para diversas situações
similares, que seguem o mesmo padrão observado inicialmente durante a análise do
problema.

Queremos chamar sua atenção para instruções repetitivas que devem ser executadas
diversas vezes devido a grande variedade de situações similares à rotina. Como fazer
com que as instruções para calcular a situação de um aluno específico sejam utilizadas
para todo o grupo de alunos? Como replicar, para todas as vendas, os registros e
cálculos efetuados para uma única venda?

Está percebendo a importância de estabelecer a repetição de instruções em um


programa? O que veremos agora é como fazer com que um programa ou trecho de
programa seja executado diversas vezes de forma controlada. Usaremos a estrutura de
repetição. Existem 3 tipos de estruturas de repetição: com teste no início, com teste no
final e com o uso de variável de controle. Veremos cada uma delas detalhadamente.
4.7 Repetição com teste no início
Toda estrutura de repetição deve
possuir dois elementos: o bloco de
instruções a serem repetidas e uma
expressão condicional capaz de
determinar o final da ocorrência das
repetições. Perceba no fluxograma ao
lado a existência desses dois
elementos.

Como o título do tópico já esclarece,


esta estrutura verifica a condição de
repetição antes entrar no bloco de
repetição, ou seja, a condição é testada
e, se o resultado for verdadeiro, o
bloco de instruções será executado.

Até aí, vemos muita semelhança com a


estrutura que representa a alternativa
simples. Entretanto, observando com
mais atenção o fluxograma, perceba
que ao término da última instrução do bloco (Cn), o fluxo de execução volta para a
verificação da condição e tudo se repete mais uma vez. Dizemos tecnicamente que o
programa entrou em um laço ou loop.

O programa ficará repetindo a execução desse bloco de instruções enquanto a expressão


condicional obter o resultado verdadeiro. Daí a importância de elaborar a expressão de
forma que em algum momento se torne falsa para que o fluxo de execução possa sair do
laço e prosseguir. Caso contrário o programa ficará preso em loop.

(portugol) (linguagem C)
enquanto (expressão condicional) faça while (expressão condicional) {
c1; c1;
c2; c2;
... ...
cn; cn;
fim-enquanto }

É importante chamar a atenção para uma ocorrência típica de estruturas de repetição


com teste no início. Se na primeira verificação da condição, der o resultado falso, o
bloco de instruções não será executado nenhuma vez.

Apresentaremos a solução para um problema para facilitar a compreensão. Imagine uma


turma com 3 alunos, onde cada aluno realiza uma prova no valor de 100 pontos. Vamos
codificar um programa para calcular a média das notas da turma. Muito simples.
media.c versão 1.0
1 main(){
2 float media = 0;
3 float nota;
4
5 printf(“\nInforme a Nota: ”);
6 scanf(“%f”, &nota);
7 media = media + nota;
8
9 printf(“\nInforme a Nota: ”);
10 scanf(“%f”, &nota);
11 media = media + nota;
12
13 printf(“\nInforme a Nota: ”);
14 scanf(“%f”, &nota);
15 media = media + nota;
16
17 media = media / 3;
18 printf(“\nA media das notas da turma: %f“, media);
19 }

Repare que usamos uma mesma variável para armazenar todas as 3 notas. Isto não é
problema porque antes de armazenar uma nova nota, a anterior é acumulada na variável
media. É óbvio que se fosse necessário armazenar todas as notas simultaneamente, essa
solução não seria viável.

Mas analisemos o ponto central. Você percebeu a duplicidade de código no programa


acima? Veja que entre as linhas 9 e 15 só aparece código já existente. Tome muito
cuidado com isso, além de deixar nossos programas mais extensos, é uma porta aberta
para erros. Imagine um bloco de comandos que aparece em vários locais de um sistema,
e que você, para atender um novo requisito do sistema, altera apenas um desses blocos e
esquece de alterar os demais blocos duplicados. Pronto, seu sistema já está com
problemas. Portanto nunca escreva código duplicado. No futuro apresentaremos
algumas técnicas de programação para evitar a duplicidade de código, por enquanto
veremos como eliminar as linhas repetitivas através de uma estrutura de repetição.

Uma sugestão muito simples é retirar todas as linhas duplicadas e manter apenas uma
linha de cada instrução e envolvê-las pelo comando while. Veja abaixo.
media.c versão 2.0
1 main(){
2 float media = 0, nota;
3 int contador = 0;
4
5 while (contador < 3){
6 printf(“\nInforme a Nota: ”);
7 scanf(“%f”, &nota);
8 media = media + nota;
9 contador = contador + 1;
10 }
11 media = media / 3;
12 printf(“\nA media das notas da turma: %f“, media);
13 }

Na primeira repetição será lida e acumulada a 1ª nota, em seguida a 2ª nota e finalmente


a 3ª nota. Eliminamos as ocorrências de comandos repetitivos porque não precisamos
escrever código para tratar três notas, podemos digitar apenas código para o tratamento
de uma única nota e fazê-lo ser executado repetidas vezes para as demais notas. Vamos
aos comentários do programa acima.

Linha Comentário

5 A chave aberta indica o início de um bloco de comandos que serão


executados repetidas vezes enquanto a expressão condicional for
verdadeira.

Nessa linha ocorre a verificação da expressão condicional. A variável


contador representa a quantidade de notas já lidas. Queremos que ocorra
repetição enquanto a contador for menor do que 3, ou seja, enquanto a
quantidade de notas lidas for menor do que 3. Quando contador for igual
a 3 é sinal de que já foram lidas todas as 3 notas e a expressão
condicional resultará em falso, permitindo desta forma sair da repetição.

6a8 Para cada repetição será realizado a entrada de uma nota e seu acúmulo
na variável media.

9 Aqui ocorre o incremento da variável contador em 1 unidade, indicando


que mais uma nota foi lida. Repare que na linha 3 a variável contador foi
inicializada com 0 porque naquele momento nenhuma nota havia sido
lida.

Essa linha é muito importante porque faz com que a variável contador
chegue ao valor 3 (indicando que 3 notas já foram lidas). Quando a
variável contador assumir o valor 3, fará com que a expressão
condicional se torne falsa e consequentemente finaliza o loop. Sem essa
linha o programa ficaria preso no loop indefinidamente.

10 A chave fechada indica o fim do bloco de repetição e a volta do fluxo de


execução para a linha 5. A expressão condicional é analisada novamente
e se for verdadeira ocorre outra repetição, caso contrário o fluxo de
execução é desviado para a linha 11.

11 Após o término da repetição podemos calcular a media já que todas as


notas já foram lidas e acumuladas. Repare que essa é a primeira linha a
ser executada após o fim das repetições.

Você saberia explicar o motivo de inicializarmos as variáveis media e contador com 0?


Primeiro tenha em mente que é aconselhável inicializar uma variável antes de sua
primeira referência no programa. Uma variável sem valor ou com valor desconhecido
pode causar comportamento inesperado ao programa. Mas com qual valor inicializamos
uma variável? Dependerá do contexto. Veja o caso da variável media, foi inicializada
com 0 porque naquele momento (linha 2) não havia nota lida, portanto nada mais
coerente do que a média ser 0. Da mesma forma a variável contador foi inicializada com
0, porque naquele momento a quantidade de notas lidas era 0.
Evite inicializar variáveis para forçar o seu programa funcionar corretamente, o ideal é
inicializarmos as variáveis com valores significativos e coerentes com o momento em
que a instrução é executada. O importante é você saber que o valor usado para
inicializar uma variável tem que fazer sentido dentro do contexto do programa.

Mais uma questão: porque a variável nota não foi inicializada? Não foi necessário que o
programador a inicializasse porque será inicializada pelo próprio usuário, quando
executar o programa. Veja na linha 7 que ela receberá o valor que o usuário informar.

Veja que essa segunda versão do programa está preparada para manipular apenas três
notas. Se quisermos manipular 50 notas, bastaria trocarmos, em todo o programa, a
ocorrência do número 3 por 50 e pronto, o nosso programa já estaria preparado para
tratar 50 notas. Mas ainda acho muito limitante. Vamos propor uma versão mais flexível
onde o usuário é que define a quantidade de notas a serem manipuladas pelo programa.
media.c versão 3.0
1 main(){
2 float media = 0, nota;
3 int cont = 0, qtnotas;
4
5 printf(“Informe a quantidade de notas: “);
6 scanf(“%d”, &qtnotas);
7
8 while (cont < qtnotas){
9 printf(“\nInforme a Nota: ”);
10 scanf(“%f”, &nota);
11 media = media + nota;
12 cont = cont + 1;
13 }
14 media = media / qtnotas;
15 printf(“\nA media das notas da turma: %f“, media);
16 }

Ainda acho que não está bom. E se o usuário não souber a quantidade de notas a serem
digitadas? E se ele souber a quantidade, mas por algum motivo quer parar de informar
notas e finalizar o programa antes do planejado. Um programa bem flexível permitiria o
cálculo da média independente do usuário saber a quantidade de notas a serem
informadas. Apresentaremos a versão final do programa.
media.c versão 4.0
1 main(){
2 float media = 0, nota;
3 int cont = 0;
4 char continua = 'S';
5
6 while (continua == 'S' || continua =='s')
7 {
8 printf("\nInforme a Nota: ");
9 scanf("%f", &nota);
10 media = media + nota;
11 cont = cont + 1;
12
13 printf("\nDeseja Continuar? S[Sim] ou N[Não]: ");
14 continua = getche();
15
16 }
17 media = media / cont;
18 printf("\nA media das notas da turma: %f", media);
19 }

Perceba que agora o usuário consegue calcular a média das notas dos alunos, sem
precisar informar a quantidade de alunos. Creio que esta seja a versão mais flexível que
poderíamos propor ao usuário. É importante que incorpore esse tipo de solução para os
programas que desenvolverá a partir de agora, sempre tenha em mente que não está
desenvolvendo o programa para você e sim para o usuário.

Gostaria de lembrá-lo do que estudamos inicialmente sobre depuração. Naquele


momento utilizamos o debug do nosso ambiente de programação com o objetivo de
encontrar possíveis erros em um programa. Agora, no segundo vídeo abaixo, apresento
um segundo propósito, que é o de facilitador do entendimento de um programa. Sugiro
utilizar o debug da sua IDE quando desejar entender a lógica de um programa, ou se
preferir use o “teste de mesa” que seria uma forma manual de realizar o mesmo
procedimento. Em ambos os casos, o que importa é o registro dos valores assumidos
pelas variáveis durante a execução de cada linha do programa. Assim você
compreenderá a lógica do programa e também poderá descobrir possíveis erros caso as
variáveis não assumam os valores que eram devidos.

4.7.1 Repetição com teste no iníco - parte I


4.7.2 Repetição com teste no início – parte II
4.7.3 Teste de mesa para o programa media.c
4.8 Repetição com teste no final

(portugol)
faça C1
c1;
c2;
...
C2
cn;
enquanto (expressão condicional)

Cn
(linguagem C)
do{
c1;
c2;
...
cn; F
V Condição
}while (expressão condicional);

As imagens acima são autoexplicativas. Trata-se de uma estrutura semelhante à


repetição com teste no início, portanto vamos nos dedicar apenas à diferença entre
ambas. Na estrutura anterior vimos que não há garantia de que a primeira repetição
ocorra, já que a expressão condicional é avaliada previamente, antes de cada repetição,
ou seja, se a expressão condicional for falsa na primeira verificação, não ocorrerá
nenhuma repetição.

Já na estrutura de repetição com teste no final, se a expressão condicional inicialmente


for falsa, ocorrerá apenas uma repetição. Essa é única diferença para a estrutura que
implementa a repetição com teste no início.

4.8.1 Atividade

Como exercício, sugiro que crie uma versão do programa media.c trocando a estrutura
de repetição utilizada.

4.8.2 Repetição com teste no final


4.9 Repetição com variável de controle
variavel = valor
inicial
(portugol)

para (ação-1; condição; ação-2)faça


c1;
c2;
expressão
... condicional
cn; envolvendo a F
fim-para variável de controle

(linguagem C)

for(ação-1; condição; ação-2){ C1


c1;
c2;
...
C2
cn;
}

Cn

Altera o valor da
variável inicial

Esta estrutura utiliza uma variável para controlar o número de repetições. Normalmente
em ação-1 inicializamos a variável de controle, em ação-2 alteramos a variável de
controle, incrementando ou decrementando seu valor e em condição definimos uma
forma de finalizar a repetição, verificando se a variável se controle já alcançou um
determinado limite.

A ação-1 é executada somente uma vez e antes da primeira repetição. Normalmente é


usada para inicializarmos a variável de controle.

A ação-2 é executada ao final de cada repetição. Normalmente define a maneira como a


variável de controle será alterada a cada repetição. Permite que a variável de controle
chegue a um valor que torne a condição falsa, ou seja, que a repetição chegue ao fim.
Geralmente é usada para incrementar ou decrementar a variável de controle.
A condição é testada antes de cada repetição, se for verdadeira haverá mais uma
repetição e caso contrário o fluxo de execução é desviado para a próxima instrução após
o fim da estrutura. Haverá repetição enquanto a condição for verdadeira.

Para exemplificar e compreender melhor, codificaremos um programa que seja capaz de


calcular a potência de um número.
b=2
e=3

potencia.c
1 main(){
2 int i, b, e, potencia;
3
4 printf("\nInforme o valor da base:");
5 scanf("%d",&b);
6 printf("\nInforme o valor do expoente:");
7 scanf("%d",&e);
8
9 potencia = 1;
10 for (i=1; i<=e; i++){
11 potencia = potencia * b;
12 }
13
14 printf("\nPotencia: %d", potencia);
15 }
16
Linha Comentário

9 Repare que na linha 11 estamos acumulando na variável potencia o seu


próprio valor multiplicado por b. Portanto a variável potencia tem que
possuir um valor já para a primeira repetição e é isso que esta linha faz:
ela inicializa a variável potencia para que na primeira repetição ela já
tenha um valor. E porque este valor inicial é 1? Simples, porque 1 é um
valor nulo para a multiplicação, não interferindo desta forma no
resultado final. Lembra do cálculo da média no programa media.c?
Usamos o mesmo raciocínio aqui, o valor inicial da variável media foi 0
naquela situação porque é um valor nulo para a operação de soma.

10 Aqui controlamos a repetição através da variável i. Queremos que


ocorram tantas repetições quanto o valor do expoente, ou seja, e
repetições. Então a variável de controle (i) começa em 1 e vai até e
(inclusive) causando desta forma o número de repetições que desejamos.

11 Para cada repetição acumulamos o valor da base (b) na variável


potencia.

4.9.1 Estrutura de repetição com variável de controle


4.10 Atividades

1) Sugiro que faça o teste de mesa para o programa potencia.c (listagem na página
anterior) e codifique novas versões usando as outras duas estruturas de repetição
estudadas anteriormente.

2) Quais as saídas produzidas pelos trechos de programas abaixo.

(a) (e)
int i = 10; int i;
while (i < 15){ for (i=1; i <= 10; i++){
printf(“%d”, i); printf(“%d”, i);
i = i + 3; }
}
(f)
(b) int i;
int i = 2; for (i=10; i <= 10; i--){
do{ printf(“%d”, i);
printf(“%d”, i); }
i = i + 3; (g)
}while (i > 5); int i;
for (i=1; i <= 10; i++){
printf(“%d”, i);
(c) }
int i = 100;
while (i < 15){ (h)
printf(“%d”, i); int i;
i = i + 3; for (i=10; i <= 10; i--){
} printf(“%d”, i);
}
(d)
int i = 1; (i)
do{ int i;
printf(“%d”, i); for (i=1; i >= 10; i++){
i = i + 2; printf(“%d”, i);
}while (i < 5245); }

(j)
int i;
for (i=10; i >= 10; i--){
printf(“%d”, i);
}

3) Qual o primeiro e o último valor que serão produzidos como saída pelo programa
abaixo?
int n = 1;
while (n <= 100 ){
printf("\n%d", n);
n = n + 2;
}
4) A organização de um evento esportivo deseja um programa que seja responsável
por dar mais credibilidade ao sistema de pontuação manual atualmente usado.
Considere que o número de competidores é desconhecido, que cada competidor
recebe um número identificador e ao final da execução da prova esportiva recebe
uma pontuação. Vence aquele competidor com a maior pontuação. O programa
deverá ser capaz de exibir os dados do competidor vencedor que são o número
identificador e sua pontuação.

5) Foi realizada uma pesquisa sobre algumas características físicas da população de


uma região. Coletaram os seguintes dados referentes a cada habitante: sexo e idade.
Faça um programa capaz de determinar a quantidade de indivíduos do sexo
feminino cuja idade está entre 18 e 35 anos, inclusive.

6) Uma professora do Ensino Fundamental solicitou sua ajuda. Ela deseja um


programa que possa transformar o aprendizado da tabuada de multiplicação em um
jogo. O programa deve solicitar um número de 1 a 10, em seguida apresentar a
tabuada de multiplicação desse número no formato abaixo:

n x 1=? Atenção:
n x 2=?
n x 3=? 1. Antes de apresentar o resultado de cada operação o programa
n x 4=? deverá solicitar ao aluno que informe o valor da operação. Para
n x 5=? cada acerto o aluno ganha um ponto.
n x 6=?
n x 7=? 2. Ao final da tabuada o programa deverá informar a pontuação
n x 8=? total obtida pelo aluno, seguida de uma dessas mensagens:
n x 9=? a. “Excelente” para alunos com nenhum erro.
n x 10 = ? b. “Estude mais um pouquinho” para alunos com 1 erro.
c. “Estude mais” para alunos com 2 erros.
d. “Estude muito mais” para alunos com 3 erros ou mais.

7) O supermercado Excelente Preço deseja um programa para registrar as vendas


realizadas para um cliente. O programa deve permitir o registro do valor de cada
item da venda e ao final calcular o valor a ser pago pelo cliente, considerando:

a) Pagamento a vista – 5% de desconto do valor total da venda dividido em 2


parcelas.

b) Pagamento com cartão de crédito – 5% de acréscimo ao valor da total da venda.

8) Jogo de adivinhação contra o computador. Criar um programa que sorteie um


número de 1 a 100 e que permita que o usuário (sem conhecer o número sorteado)
tente acertar. Caso não acerte, o programa deve imprimir uma mensagem
informando se o número sorteado é maior ou menor que a tentativa feita e permitir
ao usuário realizar nova tentativa. Ao acertar o número, o programa deve finalizar e
imprimir a quantidade de tentativas realizadas.

9) Codificar um programa para imprimir triângulos retângulos com altura definida


pelo usuário conforme exemplos abaixo:

Altura 4:
*
**
***
****

Altura 6:
*
**
***
****
*****
******

10) Codifique um programa que lê a temperatura de várias cidades e que represente a


temperatura de cada uma delas com o caractere ‘+’ ou ‘–‘ onde cada
sinal representa um intervalo de 1◦C. Veja alguns exemplos:

Para 11º a saída será: +++++++++++


Para 16º a saída será: ++++++++++++++++
Para -4º a saída será: ----
Para 0º a saída será: 0

11) Codificar um programa para imprimir todos os divisores de um número inteiro e


positivo.

12) Codificar um programa que verifique se um determinado número é ou não primo.

13) Considere a progressão geométrica (PG) 1, 2, 4, 8, 16, 32, .... e um inteiro positivo
n. Deseja-se que um programa faça:

• Imprimir os n primeiros termos da PG.


• Calcular e imprimir a soma dos n primeiros termos da PG sem utilizar a
fórmula da soma.

14) Faça um programa que gere os n primeiros números da sequência de Fibonacci,


definida na fórmula:

Segue abaixo alguns vídeos onde demonstro várias soluções para problemas rotineiros,
através das estruturas de repetição.
4.10.1. Como calcular números aleatórios
4.10.2. Gráfico de temperatura parte I
4.10.3. Gráfico de temperatura parte II
4.10.4. Gráfico de temperatura parte III
4.10.5. Raízes de uma equação do 2º grau parte I
4.10.6. Raízes de uma equação do 2º grau parte II
4.10.7. Raízes de uma equação do 2º grau parte III
5. ARRAY

Um array (arranjo em português) é uma das estruturas de dados mais simples para
armazenamento de uma coleção de dados. Veja que agora não estamos nos referindo a
um dado isolado, mas a uma coleção deles. Nós programadores ganhamos muito com
um recurso como esse, pois o tratamento dos dados em grupo pode ser mais eficiente do
que de forma individual. Veremos a seguir, detalhadamente suas características.

1. Seus elementos devem ser do mesmo tipo, por isso, o array também é conhecido
com estrutura de dados homogênea. Essa característica é, na verdade uma limitação,
mas que pode ser contornada facilmente, como veremos mais adiante.
2. Seus elementos ocupam posições contíguas na memória. Cada elemento do array
ocupa um endereço de memória específico, onde o endereço mais baixo corresponde
ao primeiro elemento e o mais alto ao último.
3. Possui número de elementos fixo. Atenção, isso implica no fato de que o array é
criado com uma quantidade de elementos que não pode ser alterada durante a
execução do programa. Esta é outra limitação.
4. O acesso a cada elemento do array é realizado por meio de um índice, que nada
mais é do que um número inteiro correspondente à posição do elemento dentro do
array. O valor que está armazenado na primeira posição do array é acessado com o
índice 0, a segunda posição com o índice 1, a terceira com 2 e assim em diante.
Portanto um array de n elementos armazena o último elemento na posição n-1.
Explicaremos mais adiante o motivo do índice 0 (e não 1) corresponder à primeira
posição, aguarde! O uso de índice proporciona o acesso direto aos elementos de um
array, ou seja, não há necessidade procurar um elemento por todas as posições, o
acesso é feito diretamente através do índice.
5. Um array pode apresentar mais de uma dimensão. O que vai determinar a
quantidade de dimensões do array é a quantidade de vínculos que o dado
armazenado no array possui. Vamos a um exemplo para facilitar a compreensão: em
um array de notas onde cada nota está vinculada a um aluno temos uma array
unidimensional. Agora se cada nota estivesse vinculada a um aluno e bimestre,
teríamos um array bidimensional. Dedicaremos apenas ao estudo desses dois tipos
de array.
6. Você pode encontrar diferentes denominações para um array. Acho importante
conhecê-las: arranjo, vetor, matriz e variável indexada. A partir desse ponto
usaremos apenas o termo vetor.

5.1 Declaração de vetor


A primeira instrução em um programa, envolvendo um vetor, é sua declaração.
exemplo de declaração de vetor de reais
1 //código omitido
2
3 double notas[10];
4
5 //código omitido

A declaração do vetor na linha 3 indica que rotulamos um local da memória com o


nome de notas e que esse local poderá armazenar até 10 elementos do tipo double. Para
declaramos um vetor, devemos determinar o tipo de dados dos seus elementos e a
quantidade de elementos que suportará. Veja abaixo uma representação do efeito da
execução da linha 3.

índice 0 1 2 ... 7 8 9
valor
endereço 2293496 2293504 2293512 ... 2293552 2293560 2293568

Você deve estar imaginando como eu consegui aqueles endereços da última linha do
quadro acima. Eu criei um programa em C, declarei um vetor com 10 elementos e
imprimi na tela o endereço de cada um dos 10 elementos. Isso servirá de base para a
seguinte questão: se os elementos do vetor ocupam posições contíguas da memória,
porque os endereços não são consecutivos? O endereço da segunda posição não deveria
ser 2293497? Porque consta o endereço 2293504?

A resposta está no fato de que cada tipo de dado primitivo possui um determinado
tamanho em bytes. Cada elemento é armazenado em posições contíguas, levando em
consideração o tamanho em bytes definido para cada tipo na linguagem de programação
em uso. Faça uma pesquisa e verá que o tipo double, em C, ocupa 8 bytes na memória.
Faça as contas: se a primeira posição do vetor começa em 2293496 onde será
armazenado o 1º byte, em 2293497 o 2º byte e finalmente em 2293503 o 8º byte,
portanto o 1º byte do 2º elemento do vetor só poderia ser armazenado no endereço
2293504. Siga o mesmo raciocínio para os demais endereços.

Veja abaixo outro exemplo. Agora declaramos um vetor de caracteres e sua respectiva
representação na memória. Considere que na linguagem C, cada caractere ocupa 1 byte
na memória. Veja que os endereços, agora, são sequencias, visto que cada caractere
ocupa 1 byte.

exemplo de declaração de vetor de char


1 //código omitido
2
3 char nome[5];
4
5 //código omitido

índice 0 1 2 3 4
valor
endereço 2293496 2293497 2293498 2293499 2293450

5.2 Acessando os elementos do vetor


A grande diferença entre o vetor e uma variável simples é o fato de permitir o
armazenamento de vários elementos. Em função disso a referência tem que ser
diferente. Como acessar cada elemento do vetor individualmente? A forma correta de
referenciar um elemento específico do vetor é através de um índice dentro de um par de
colchetes. Vejamos mais exemplos práticos.
exemplo de acesso aos elementos de um vetor de reais
1 //código omitido
2
3 double notas[3], media;
4
5 notas[0] = 10.0;
6 notas[1] = 6.0;
7 notas[2] = 5.0;
8
9 media = (notas[0] + notas[1] + notas[2]) / 3;
10
11 //código omitido

Antes de explicar o trecho de código acima, veja abaixo uma representação da memória
do computador após a execução de todas as linhas do exemplo acima.
Notas media
índice 0 1 2 7.0
valor 10.0 6.0 5.0

Linha Comentário

3 Declaração do vetor. Será alocado 3 locais contíguos na memória do


computador para armazenar valores do tipo double. Este local foi
rotulado como notas.

5a7 Atribuímos valores a cada uma das posições do vetor notas, da primeira
até a última. O efeito dessas 3 linhas pode ser visto no quadro acima.

9 Nessa linha acessamos os valores armazenados nas posições 0, 1 e 2.

5.3 Percorrendo um vetor


Uma das operações mais comuns envolvendo vetor ou uma lista é percorrer seus
elementos. Imagine um vetor de notas, de salários, ou qualquer outro dado, não importa,
em qualquer um deles você precisará percorrer seus elementos e realizar operações
específicas com esses elementos, entretanto a forma como percorre um vetor pode ser
generalizada e é isso que veremos agora.

Apresentaremos uma nova versão do programa que calcula média de notas, procure
entender que a solução adotada aqui, pode ser generalizada para as situações mais
comuns envolvendo vetores. Agora a variável nota será um vetor e não mais uma
variável simples. Essa simples mudança já trás um enorme benefício, já que
armazenaremos todas as notas em uma única estrutura, que é o vetor. Assim todas as
notas estarão disponíveis ao mesmo tempo, diferentemente da versão anterior, em que
cada nova nota sobrepunha a anterior, fazendo com que a variável nota armazenasse
somente a última nota lida. Se for necessário, volte e releia o programa media.c versão
4.0.
media.c versão 5.0
1 #define MAX 30
2
3 main(){
4 float media = 0;
5 float nota[MAX];
6 int i;
7
8 for (i=0; i < MAX; i++){
9 printf("\nInforme a Nota: ");
10 scanf("%f", &nota[i]);
11 media = media + nota[i];
12 }
13
14 media = media / MAX;
15 printf("\nA media das notas da turma: %f", media);
16 }

Linha Comentário

1 Está lembrado que o número de elementos de um vetor é fixo. Então por


que não usar uma constante para indicar o número de elementos do
vetor? Essa linha define uma constante de nome MAX que indicará o
tamanho do vetor.

5 Veja que declarei o vetor usando a constante MAX. Em diversos pontos


do programa usarei essa constante, sempre que precisar indicar a
quantidade de elementos do vetor. Isso nos dá mais comodidade para
alterar a capacidade do vetor, basta alteramos essa constante, claro que
não poderemos fazer isso dinamicamente, ou seja, em tempo de
execução. Qualquer alteração nesse sentido deve ser seguida de nova
compilação e geração de novo executável.

8 a 12 Nesse trecho realizamos o percurso. Explicaremos cada linha


individualmente.

8 Todo percurso pelos elementos de um vetor é uma tarefa repetitiva, pois


a operação realizada com o 1º elemento será replicada aos demais. Então
o primeiro passo é definir uma estrutura de repetição. Você pode
escolher qualquer uma das três existentes. Entretanto a estrutura de
repetição com variável de controle é a mais indicada visto que esta
variável servirá de índice do vetor. Se queremos percorrer todo o vetor, o
índice deve começar com 0, ser incremento em 1 unidade a cada
repetição até chegar ao valor correspondente à última posição do vetor.
A cada repetição o índice fará referência a uma posição diferente do
vetor.

Analise o comando for. Ação-1: a variável i representa o índice do vetor,


veja que começou com 0 já que a 1ª posição de um vetor é a 0.
Condição: a repetição ocorrerá enquanto o valor de i for menor do que o
tamanho do vetor (MAX). Ação-2: o valor de i será incrementada em 1 a
cada repetição.
10 Veja que na 1ª repetição a 1ª nota lida será armazenada na posição i que
é 0, na 2ª repetição a 2ª nota lida será armazenada na posição i que agora
é 1 e por fim a 3ª repetição a 3ª nota lida será armazenada na posição i
que agora é 2.

11 Aqui acumulamos o valor que está na posição i do vetor na variável


media. Como a cada repetição a variável i terá um valor diferente (0,1 e
2), isso garante que a cada repetição acumularemos um valor diferente,
ao final das repetições teremos acumulado todas as notas.

Caso tenha alguma dúvida sugiro usar sua IDE para executar a última versão do
programa media.c. Se for necessário faça simulações com o “teste de mesa”.

Disponibilizo abaixo dois vídeos, onde resolvo um problema clássico: o cálculo do


maior e menor valor de uma lista. Como desafio sugiro que você crie uma versão mais
eficiente do que a proposta nos vídeos.
5.3.1 Vetor numérico – parte I
5.3.2 Vetor numérico – parte II

5.4 Strings
Chamamos de strings qualquer sequência de caracteres utilizada para representar
palavras, frases ou textos dentro de um programa. Muitas linguagens de programação
fornecem o tipo de dado string para o armazenamento de uma cadeia de caracteres, esse
não é o caso da Linguagem C. Em C uma string é definida como um vetor de caracteres
(char).

Veja o código abaixo onde introduzimos o uso de strings.

saudacao.c
1 #define MAX 15
2
3 main() {
4 char nome[MAX];
5 char mensagem[MAX] = "Bom dia";
6
7 printf("Digite seu nome: ");
8 gets(nome);
9
10 printf("%s, %s. \nSeja bem vindo!", mensagem, nome);
11 }

Linha Comentário
4 Foi alocado espaço em memória suficiente para uma string de 15
caracteres, ou seja, um vetor de 15 caracteres. Esse local da memória foi
rotulado de nome.
5 Aqui a diferença é que a variável mensagem, que é uma string, foi
declarada e inicializada com o conteúdo definido entres aspas duplas. As
aspas duplas servem para delimitar o conteúdo de uma string da mesma
forma que as aspas simples delimitam um caractere. É uma forma de
“avisar” ao compilador de que os caracteres entre aspas devem ser
tratados como string e não como uma palavra reservada da linguagem.
8 Foi utilizado um comando novo, específico para leitura de strings pelo
teclado. Poderia utilizar o scanf, mas o gets é mais simples e eficiente
para o caso de leitura de strings.
10 Repare que não usamos índice para referenciar os vetores nome e
mensagem. Nesse caso não queremos uma posição específica do vetor e
sim ele como um todo.

Na linguagem C, toda string possui no seu final um caractere nulo (‘\0’) para sinalizar o
seu fim. O desconhecimento desse fato pode causar comportamento inesperado em seus
programas. Para chamar sua atenção apresentaremos um programa capaz de ler uma
frase e apresentar a quantidade de vogais e de caracteres totais informados.

vogais.c
1 #define MAX 100
2 main() {
3 char frase[MAX];
4 int i, totalVogais=0, totalCaracteres=0;
5
6 printf("\nInforme uma frase:");
7 gets(frase);
8
9 for (i=0; i < MAX; i++) {
10 switch (frase[i]) {
11 case 'a':
12 case 'e':
13 case 'i':
14 case 'o':
15 case 'u':
16 totalVogais++;
17 break;
18 }
19 totalCaracteres++;
20 }
21 printf("\nTamanho da frase: %d", totalCaracteres);
22 printf("\nQuantidade de vogais na frase: %d", totalVogais);
23 }

Ao executar o programa e informar a frase “Vetor de caracteres” o programa


apresentará a seguinte saída:

Concorda com as
informações apresentadas?

Tem algo errado! A frase


possui 19 caracteres e 7
vogais. Vamos aos
esclarecimentos.

O erro está apenas na


linha 9, especificamente na expressão condicional. Da forma como foi elaborada haverá
100 repetições fazendo com que a linha 19 seja executada 100 vezes ocasionando a
saída acima com o tamanho da frase igual a 100. O erro está em percorrer
desnecessariamente toda a string.

O certo seria realizar apenas a quantidade de repetições suficientes para tratar todos os
19 caracteres da frase e não a capacidade total do vetor que é de 100 caracteres. No caso
acima era para realizar apenas 19 repetições já que a frase só possui 19 caracteres.

Agora usaremos aquela informação de que toda string em C possui como último
caractere o ‘\0’. Não confunda o final da string com o final do vetor. Nesse exemplo o
final da string é a posição após a última letra da frase onde estará o ‘\0’. Já o final do
vetor está na posição 99.

Mas como saber o tamanho da string informada pelo usuário? Basta utilizar uma
condição em que envolva o ‘\0’. Faremos o tratamento de cada caractere da string
enquanto ele for diferente de ‘\0’. A linha 9 deveria ter sido escrita assim:

for (i=0; frase[i] != '\0'; i++) {

Veja na imagem ao lado


que com essa alteração o
programa apresenta os
resultados corretos.

Uma segunda solução


seria utilizar a função
strlen da linguagem C.
Essa função nos dá o
tamanho de uma string. Como o tamanho da string informada é 19, a variável i teria
que variar de 0 até 19 (exclusive). Veja abaixo a outra forma de codificar a linha 9.

19

for (i=0; i < strlen(frase); i++) {

Para concluir chamo sua atenção para o ganho de eficiência com as alterações
propostas. Vimos que nem sempre será necessário percorrer todo o vetor. Com a última
mudança percorremos somente os elementos necessários, sem desperdício de tempo e
processamento. Sempre tenha esse tipo de preocupação ao criar os seus programas.

5.4.1 String parte I


5.4.2 String parte II
5.4.3 String parte III

5.5 Dimensões de um vetor


Até o presente momento nos dedicamos ao estudo de vetores unidimensionais. Lembre-
se de que em vetores unidimensionais vinculamos os dados armazenados a uma única
entidade que pode ser um aluno, uma venda, dentre outras. E que para diferenciar os
diversos exemplares da entidade, usamos de um único índice.
Veremos agora os vetores bidimensionais. Usamos esse tipo de vetor quando queremos
armazenar dados que estejam vinculados a duas entidades. Pra exemplificar considere
uma escola em que o período letivo é divido em bimestres e o aluno recebe uma nota
para cada bimestre. Temos nesse exemplo os dados que são as notas, vinculadas a duas
entidades: aluno e bimestre. Nesse caso não basta uma entidade para identificarmos uma
nota, necessitamos de duas entidades, o aluno e o bimestre.

Veja abaixo na figura que as linhas representam um aluno e as colunas os bimestres.


Vinculamos cada número de linha a um aluno e cada número de coluna à um bimestre.
Poderia ser ao contrário, o que importa é vincularmos uma entidade às linhas e a outra
entidade às colunas. Conclui-se que para acessar qualquer dado armazenado no vetor
bidimensional precisaremos de dois índices, um para representar as linhas e o outro as
colunas. Bimestres
0 1 2 3
0 10,0 9,5 8,5 9,5
1 7,0 8,5 9,5 10,0
Alunos
2 9,0 6,5 7,5 9,5
...
49 8,5 5,0 10,0 9,0

A estrutura acima foi projetada para armazenar 200 notas distribuídas por 50 alunos e 4
bimestres. Veja que a nota destacada está vinculada à linha 1 e coluna 2, mas eu como
programador sei que a linha 1 corresponde ao 2º aluno e coluna 2 ao 3º bimestre.

Apresentaremos abaixo um programa para manipulação do vetor acima. Trata-se de um


código clássico para percorrer os elementos de um vetor bidimensional. Nesse exemplo
calcularemos as médias de cada aluno e a média da turma.
media.c versão 6.0
1 #define L 50
2 #define C 4
3
4 main(){
5 float mediaaluno, mediaturma;
6 float notas[L][C];
7
8 int i, j;
9
10 mediaturma = 0;
11 for (i=0; i < L; i++){
12 mediaaluno = 0;
13 for (j=0; j < C; j++){
14 printf("\nNota do Aluno %d - %d Bimestre: ",i+1, j+1);
15 scanf("%f", &notas[i][j]);
16 mediaaluno = mediaaluno + notas[i][j];
17 }
18 mediaaluno = mediaaluno / C;
19 printf("\nMedia do Aluno %d: %f", i+1, mediaaluno);
20 mediaturma = mediaturma + mediaaluno;
21 }
22 mediaturma = mediaturma / L;
23 printf("\nMedia da Turma: %f", mediaturma);
24 }
Linha Comentário

1 A constante L representa o número de linhas do vetor (alunos)

2 A constante C representa o número de colunas do vetor (bimestres).

11 O comando for mais externo é responsável pela variação das linhas (alunos)
e para cada repetição será acumulado em mediaturma a mediaaluno, por
isso é necessário inicializarmos mediaturma com 0 na linha 10.

13 O comando for mais interno é responsável pela variação das colunas


(bimestres) e para cada repetição será acumulado em mediaaluno a nota de
um aluno em cada bimestre, por isso é necessário inicializarmos
mediaaluno com 0 na linha 12.

16 Acumula em mediaaluno todas as notas de um aluno.

20 Acumula em mediaturma a media de um aluno.

Mais uma vez reforçamos aqui a importância do “teste de mesa” como ferramenta para
o iniciante compreender e analisar um programa. Faremos a análise do programa acima
no vídeo que segue.

5.5.1 Teste de mesa para o programa media.c versão 6.0

Veremos agora outra utilidade para os vetores bidimensionais: armazenar diversas


strings. Essa estrutura é conhecida como vetor de strings. Basta declararmos um vetor
bidimensional de caracteres. O tamanho do índice esquerdo indica o número de strings
que desejamos armazenar e o tamanho do índice direito especifica o comprimento
máximo de cada string.

Veja abaixo a declaração de um vetor de 30 strings, cada uma com capacidade de 80


caracteres.

exemplo de declaração de vetor de strings


25 //código omitido
26
27 char nome[30[[80];
28
29 //código omitido

Para acessar uma string individualmente, especificamos apenas o índice esquerdo. A


instrução gets(str[2]) lê do teclado uma string e armazena na 3ª linha do vetor
bidimensional.

Para acessar um caractere individualmente, de uma string, especificamos os dois


índices. A instrução printf(“%c”,str[2][5]) mostra o caractere na posição 5 da
linha 2.

Vamos mostrar um programa que manipula strings. Trata-se de um editor de texto bem
simples.
editor.c
1 main(){
2 int i;
3 char texto [100][80] ;
4
5 printf("\nDigite o texto...\n" );
6 for (i=0; i<100; i++){
7 gets(texto[i]);
8 }
9
10 //mostra o texto na tela
11 for (i=0; i<100; i++){
12 if (texto[i][0] == '\0'){
13 break ;
14 }
15 printf("%s\n", texto[i]);
16 }
17 }

Linha Comentário

3 O vetor bidimensional de nome texto terá a capacidade de armazenar 100


linhas com 80 colunas cada.

12 Se o primeiro caractere de uma linha for o ‘\0’significa que não tem mais
linhas com texto, então interrompemos a repetição.

5.5.2 Desafio

Execute o programa editor.c e crie um texto com apenas 3 linhas. O que você achou do
comportamento do programa? Gostou? Tem alguma sugestão para melhorar? Apresente
sua versão melhorada com a descrição da melhoria sugerida.

5.6 Inicialização de vetor


O vetor pode ser inicializado no momento da declaração como qualquer outra variável.
Veja alguns exemplos abaixo.

exemplo de inicialização de vetor unidimensional


1 //código omitido
2
3 int numeros[10] = {1,2,3,4,5,6,7,8,9,10};
4
5 //código omitido

O efeito da instrução da linha 3: 0 1 2 3 4 5 6 7 8 9


1 2 3 4 5 6 7 8 9 10
exemplo de inicialização de vetor bidimensional
1 //código omitido
2
3 int quadrados[10][2] = {1,1,2,4,3,9,4,16,5,25,6,36,7,49,8,64,9,81,10,100};
4
5 //código omitido
0 1
O efeito da instrução da linha 3: 0 1 1
1 2 4
2 3 9
3 4 16
4 5 25
5 6 36
6 7 49
7 8 64
8 9 81
9 10 100

Vetores de caracteres (strings) permitem uma inicialização mais simplificada. Veja o


exemplo a seguir.

exemplo de inicialização de vetor de caracteres


6 //código omitido
7
8 char profissao[12] = “Programador”;
9
10 //código omitido
11
Você não precisa adicionar o caractere nulo ao final das constantes do tipo string,
manualmente. O compilador C faz isso por você automaticamente.

5.7 Atividades

1) Codificar um programa que permita o registro das informações sobre as vendas


realizadas por uma determinada empresa. Considere que as informações sobre cada
venda são a quantidade de itens vendidos e o preço de venda. O programa deverá
emitir um relatório que informe o faturamento total obtido com a venda de todos os
itens cadastrados.

2) Codificar um programa para simular a verificação se o dado usado em um


determinado jogo é “viciado” ou não. Considere que dado não “viciado” é aquele
em que não há grande variação na quantidade de vezes que cada face é sorteada ao
final de vários lançamentos. O programa deve permitir ao usuário escolher o
número de faces do dado (mínimo 2) e a quantidade de lançamentos a serem
simulados. Após a simulação, o programa deverá emitir um relatório apresentando
a quantidade de vezes que cada face fora sorteada e assim o usuário poderá
perceber se o dado é ou não viciado.

3) Crie um programa para faça o registro das pontuações que 50 juízes de uma
determinada prova esportiva atribuíram a um atleta (valores compreendidos entre 0
e 10 inclusive). Determinar e apresentar os seguintes valores:
a. A média obtida pelo atleta.
b. A melhor pontuação obtida pelo atleta.
c. A pior pontuação obtida pelo atleta.
d. A porcentagem de pontuações acima da média do atleta.
e. A porcentagem de pontuações abaixo da média do atleta.
f. Determine a quantidade de juízes que atribuíram a melhor nota ao atleta.
g. Determine a quantidade de juízes que atribuíram a pior nota ao atleta.

4) Codificar um programa para armazenar as temperaturas diárias de um determinado


mês (considere o mês com 30 dias) e produzir o seguinte relatório:
a) A temperatura mínima no mês.
b) A temperatura máxima no mês.
c) A temperatura média do mês.

5) Qual será a configuração do vetor num depois de executado o trecho de programa


abaixo?
0 1 2 3 4
int num[5][5], i , j;

for (i=0; i<5; i++){ 0


for (j=0; j<5; j++){
if (i>j){ 1
num[i][j]=1;
} 2
if (i==j){
num[i][j]=0; 3
}
if (i<j){
num[i][j]=-1; 4
}
}
}

6) Desenhe o vetor correspondente à declaração abaixo:

int vet[5][5] = {1,2,2,2,2,3,1,2,2,2,3,3,1,2,2,3,3,3,1,2,3,3,3,3,1}

Codificar um programa para gerar esse vetor e calcular:

a) A soma dos elementos da diagonal principal


b) A soma dos elementos localizados acima da diagonal principal
c) A soma dos elementos localizados abaixo da diagonal principal

7) Uma empresa especializada em produtos agropecuários plantou em um viveiro 5.000


sementes de uma determinada planta e deseja contratar os seus serviços de
programador para verificar o grau de germinação de tais sementes.

Você deverá criar um programa que permita registrar o grau de germinação de cada
semente como sendo uma nota atribuída por um técnico agropecuário usando uma
escala de 0 a 10.

Ao final o programa deverá emitir um relatório contendo o percentual de sementes


que conseguiram um grau de germinação acima da média.
Situação exemplo:
Semente Grau de Somatório 30
germinação Grau médio de germinação 6
1 10 Quantidade de sementes com 2
2 5 germinação acima da média
3 2 Percentual de sementes com grau 40%
4 10 de germinação acima da média
5 3

8) Codificar um programa para ler 2 strings, sendo que a primeira deve ser o nome do
usuário e a segunda uma saudação. O programa deverá produzir como saída uma
saudação ao usuário.

9) Fazer um programa que leia uma string e a imprima de trás para frente. Veja o
exemplo abaixo:

Entrada: Bom dia


Saída: aid moB

10) Faça um programa para determinar a quantidade de vogais presentes em um nome.

11) Fazer um programa que leia a senha do usuário e informe se a senha está correta ou
incorreta. Considere que a senha correta esteja gravada no código fonte do
programa.

12) Codificar um programa para ler um nome de uma pessoa e mostrar cada letra do seu
nome em linhas diferentes.

13) Codificar um programa para ler um nome completo de uma pessoa e mostrar cada
parte do nome em linhas diferentes. Veja o exemplo abaixo.

Entrada: José da Silva Oliveira Santos


Saída: José
da
Silva
Oliveira
Santos

14) Codificar um programa que seja capaz de criar uma sigla para cada nome
fornecido. A sigla deve ser composta da letra inicial de cada parte do nome.
Veja exemplos abaixo:

Jose da Silva => JdS


José Pedro Nogueira => JPN
Minas Gerais => MG
Goiás => G
6. ESTRURURAS DE DADOS HETEROGÊNEAS

Há situações em que será necessário o armazenamento de dados de tipos diferentes,


agrupados em torno de uma entidade representativa desse conjunto de dados de tipos
diferentes. Por exemplo podemos citar a entidade aluno que agrupa diferentes tipos de
dados como matrícula (cadeia de caracteres), notas (vetor de números reais), turma
(caractere), dentre outros.

Veremos agora como fazer com que essa estrutura de dados heterogênea represente uma
coleção de variáveis de tipos diferentes, referenciadas por um único nome, permitindo
agrupar informações que possuem algum tipo de relação.

Primeiro devemos definir a estrutura. Esta ação equivale a definir um modelo a ser
usado para criar diversas variáveis (exemplares). A palavra-chave struct, na linguagem
C, indica a definição de uma estrutura.
Exemplo de definição de uma estrutura de dados heterogênea de nome dados
1 //código omitido
2 struct dados{
3 char nome[30];
4 char curso[20];
5 char turma;
6 double nota;
7 };

O trecho de código acima, não declarou nenhuma variável, apenas definiu a forma dos
dados. Definimos que nossa estrutura possui o nome dados e que é composta de
alguns membros (elementos ou campos).

Após a definição da estrutura dados declaramos variáveis desse tipo. Veja o exemplo
abaixo.

Exemplo de declaração de variáveis


1 struct dados aluno;
2 struct dados professor
3 struct dados funcionario

Declaramos 3 variáveis do tipo dados. Para manipular os campos de uma estrutura


escrevemos assim:
nome_da_variável.nome_do_campo

Veja abaixo, um programa que calcula a distância entre dois pontos no plano cartesiano.
ponto.c
1 main (){
2 struct ponto{
3 int x,y;
4 };
5 struct ponto pontoA, pontoB;
6
7 printf("\nValor da coordenada X do Ponto A: ");
8 scanf("%d",&pontoA.x);
9
10 printf("\nValor da coordenada Y do Ponto A: ");
11 scanf("%d",&pontoA.y);
12
13 printf("\nValor da coordenada X do Ponto B: ");
14 scanf("%d",&pontoB.x);
15
16 printf("\nValor da coordenada Y do Ponto B: ");
17 scanf("%d",&pontoB.y);
18
19 float aux = ((pontoB.y - pontoA.y) * (pontoB.y - pontoA.y))+
20 ((pontoB.x - pontoA.x) * (pontoB.x - pontoA.x));
21
22 float distancia = sqrt(aux);
23
24 printf("\nA distância entre os dois pontos: %f",distancia);
25 }

Linha Comentário

2a4 Definição de uma estrutura de dados heterogênea chamada ponto que


contém dois campos inteiros (x e y).

5 Declaração de duas variáveis (pontoA e pontoB) do tipo ponto.

7 a 17 Leitura das coordenadas de cada ponto.

19 a 22 Cálculo da distância entre dois pontos através do teorema de Pitágoras.

Podemos combinar as estruturas estudadas até o momento, ou seja, podemos ter um


vetor onde cada elemento é uma struct ou uma struct onde seus campos são vetores.

Veja o exemplo abaixo.

Exemplo de um vetor de struct


1 struct info{
2 char nome[30];
3 float nota;
4 };
5
6 struct info alunos[100];
7
8 ...
9
10 printf(“Nome: %s”, alunos[5].nome);
11 printf(“Nota..: %f”, alunos[5].nota);
Linha Comentário

1a4 Definição de uma estrutura chamada info que contém um campo chamado
nome (vetor de char) e outro campo chamado nota.

6 Declaração de um vetor de nome alunos com 100 elementos do tipo


info.

10 Faz referência ao elemento de índice 5 do vetor alunos. Como os


elementos do vetor são uma struct, complementamos com .nome.

11 Faz referencia ao elemento de índice 5 do vetor alunos. Como os


elementos do vetor são uma struct, complementamos com .nota.

6.1 Typedef

A linguagem C permite a definição de novos tipos de dados, além daqueles pré-


definidos. Para tanto devemos utilizar a palavra-chave typedef. A forma geral de um
comando typedef é

typedef tipo novoTipo;

Onde tipo é qualquer tipo de dados definido na linguagem C e novoTipo é um novo tipo
de dados definido pelo programador.

Por exemplo, poderíamos criar um novo nome para float usando

typedef float real;

A partir da definição acima poderíamos declarar uma variável usando esse novo nome

real salario;

Exemplo de typef com struct

main (){
struct Ponto{
int x,y;
};

typedef struct Ponto TipoPonto;


...

TipoPonto pontaA, pontoB;


...
}
7. MODULARIZAÇÃO

Encontramos diversas inspirações em nossa sociedade para


compreendermos a aplicação da estratégia modular. A indústria
moveleira, automotiva, dentre outras utilizam desta estratégia para
aumento da produção, com melhor divisão de tarefas, redução de
custos, facilidade nos processos de manutenção, dentre outras
vantagens.

O desenvolvimento de programas utiliza dessa estratégia também e com os mesmos


objetivos. Adaptando alguns procedimentos, a modularização de programas, contribui à
medida que cada módulo delimita uma funcionalidade específica do sistema. Esse
isolamento de determinada funcionalidade de um sistema permite:

→ Evitar duplicidade de código e todos os problemas decorrentes.


→ O compartilhamento de código pelos diversos módulos do sistema.
→ Promover a abstração. Precisamos saber apenas o que um módulo faz e não como
ele faz.
→ Aumentar a produtividade à medida que facilita o trabalho em uma equipe de
programadores, onde os módulos são desenvolvidos simultaneamente por
programadores diferentes.
→ Incorporar mais confiabilidade ao sistema, já que cada módulo pode ser testado
separadamente antes de ser incorporado ao sistema.
→ Facilitar a manutenção de código à medida que as funcionalidades do sistema estão
delimitadas.
→ Dividir um programa em módulos de menor complexidade, eliminando o
inconveniente dos programas se tornarem extremamente grandes e complexos, em
aplicações de maior porte.

Mas qual critério o programador deve usar para criar os módulos? Os módulos devem
ser criados de acordo com a sua funcionalidade e serem independentes em termos
funcionais. Esta característica de independência funcional é que permitirá alcançar
todos os ganhos descritos acima.

Na linguagem C, implementamos os módulos de programa através das funções. No


início do nosso curso falamos sobre função, mas agora o enfoque será diferente.
Estamos interessados na implementação de nossas próprias funções.

Uma função é um trecho de programa que possui cabeçalho, variáveis e comandos


próprios e que pode ser chamada (invocada) por outra função. Quando uma função é
referenciada, o controle do fluxo de execução é automaticamente transferido para o
princípio dela. As instruções são então executadas e ao final, o controle é
automaticamente devolvido à instrução imediatamente a seguir à chamada da função.

Para executar uma função, ela deve ser invocada no corpo de outra função, exceto a
função main(), que é invocada pelo Sistema Operacional. O esquema abaixo mostra
como é fluxo de execução ao invocarmos uma função.
int main(){
//código omitido funcao1(){
//código omitido
funcao1(); }

//código omitido
}

Repare que o fluxo de execução é desviado da função main para a funcao1. As


instruções da funcao1 são então executadas em sequência da primeira até a última. Em
seguida, com o fim da funcao1, o fluxo de execução retorna ao seu caminho original até
o final da função main.

7.1 Passagem de parâmetros

Agora vamos estudar um recurso disponível aos programadores quando utilizam


funções em seus programas. É capacidade que as funções possuem de receber e retornar
dados.

Se uma função recebe dados necessários à sua funcionalidade, ela deve declarar
variáveis que aceitem tais valores. Estas variáveis são chamadas de parâmetros formais.
Os parâmetros formais se comportam como quaisquer outras variáveis dentro da função.

Uma função pode receber qualquer número de parâmetros, inclusive nenhum. No caso
de uma função sem parâmetros pode-se escrevê-la de duas formas: deixando a lista de
argumentos vazia (mantendo-se os parênteses) ou colocando o tipo void entre
parênteses.

Exemplo de função sem parâmetros e sem retorno


1 void mostra(){ //ou void mostra(void)
2 printf(“Ola!”);
3 }

Exemplo de função que recebe um inteiro e retorna outro inteiro


1 int triplo(int r){
2 return 3*r;
3 }

Linha Comentário

1 Nessa linha está o cabeçalho da função. O cabeçalho de uma função é


composto de 3 elementos.

O primeiro é tipo de dado que a função retornará, use void para indicar que
a função não tem retorno. No exemplo acima a função triplo retornará um
valor do tipo inteiro. Se o tipo de retorno da função não é explicitamente
declarado, o compilador C atribui automaticamente o tipo padrão, que é int.

O segundo elemento é o nome da função.


Finalmente, o terceiro é composto por uma lista de argumentos, use void
para indicar que a função não possui argumentos.
2 O comando return possui dois objetivos. Ele finaliza uma função antes do
fluxo de execução alcançar o final da função. A outra finalidade é indicar o
dado a ser retornado para a chamada da função. Esse valor de retorno
substituirá a chamada da função.

Para esclarecer melhor, considere a linha abaixo como a instrução


responsável pela invocação da função triplo:
printf(“%d”, triplo(5));

A execução da linha acima começa de dentro para fora. Primeiro a função


triplo é invocada e passamos o valor 5 como argumento. Lá no corpo da
função triplo o valor 5 é recebido pelo parâmetro formal de nome r, em
seguida é retornado 3* r, cujo resultado é 15. O return indica que esse valor
15 será retornado para a chamada da função. De volta à linha do printf
acima, o retorno do valor 15 substituirá a chamada da função e esse valor
15 é que será mostrado pelo printf.

Se quiséssemos guardar o retorno da função em uma variável poderíamos


dar a seguinte instrução: int resultado = triplo(5).

Podemos utilizar o retorno da função triplo em qualquer parte do programa,


como uma expressão condicional, expressão ordinal, operações aritméticas,
dentre outros.

Veja abaixo um exemplo de programa, que diferentemente de todos criados até o


momento, separamos cada funcionalidade em módulos específicos. O programa verifica
se um determinado número é divisível por outro.

divisivel.c
1 void apresentacao(void);
2 int eDivisivel( int a, int b);
3
4 main(){
5 int n1,n2;
6 apresentacao();
7 printf("\nInforme um numero: ");
8 scanf("%d", &n1);
9 printf("\nInforme um numero: ");
10 scanf("%d", &n2);
11
12 if ( eDivisivel(n1,n2)){
13 printf("%d e divisivel por %d", n1, n2);
14 }else{
15 printf("%d NAO e divisivel por %d", n1, n2);
16 }
17 }
18
19 void apresentacao(void){
20 system("cls");
21 printf("\n*************************************");
22 printf("\nPROGRAMA QUE EXPLICA O USO DE FUNCOES");
23 printf("\nAutor: Fulano de Tal");
24 printf("\n*************************************");
25 }
26
27
28 int eDivisivel( int a, int b){
29 if ((a%b) == 0 ){
30 return 1;
31 }else{
32 return 0;
33 }
34 }

Linha Comentário

1e2 Escrevemos os protótipos de todas as funções que fazem parte do programa


divisível.c. Ne caso são duas funções: apresentacao() e eDivisivel(). Um
protótipo de função é composto apenas do cabeçalho da função, sem
implementação. Mais adiante detalharemos melhor sobre o cabeçalho de
uma função.

6 Chamada da função apresentação(). Neste ponto o fluxo de execução é


desviado para a primeira instrução localizada dentro da função
apresentacao(). Ao executar todas as instruções da função apresentação(), o
fluxo de execução continua na próxima linha, que é a 7.

12 Verifica-se aqui uma chamada para a função eDivisivel() e o envio de duas


variável (n1 e n2). Repare que o valor de retorno da função fará parte da
expressão condicional do if. Lembre-se de que se esse valor for diferente de
zero será considerado verdadeiro e falso se for igual a zero.

19 A função apresentacao() não precisa de nenhum dado e tão pouco retorna


um dado, por isso usamos a palavra void.

28 Já a função eDivisivel(), tem como objetivo verificar se um número é


divisível por outro. Portanto ela precisa de dois dados e retorna uma
indicação se o primeiro é ou não divisível pelo segundo. Quando a função
eDivisivel() é invocada, os valores de n1 e n2 serão atribuídos às variáveis a
e b, realiza-se a verificação e a palavra return sinaliza que a função será
finalizada e o dado que aparece ao seu lado será devolvido à chamada da
função. Repare que o valor de retorno será o resultado da expressão
condicional da linha 12.
7.1.1 Desafio

Crie uma nova versão para a função eDivisivel que contenha apenas uma linha de
instrução. Apresente sua versão melhorada com a descrição da melhoria sugerida.

Vejamos mais um exemplo de programa que usa funções.

calculaMedia.c
1 float calculaMedia (float argA ,float argB );
2
3 main() {
4 float a , b , m;
5
6 printf ("\nDigite o primeiro numero: " ) ;
7 scanf ("%f", &a ) ;
8
9 printf ("\nDigite o segundo numero: " ) ;
10 scanf ("%f", &b ) ;
11 m = calculaMedia (a, b) ;
12
13 printf("\nMedia entre %.2f e %.2f é %.2f\n",a,b,m);
14 }
15
16 float calculaMedia (float argA, float argB) {
17 float mediaCalculada ;
18
19 mediaCalculada = ( argA + argB ) / 2 ;
20 return mediaCalculada ;
21 }

Linha Comentário

11 Há uma chamada à função calculaMedia() e o valor de retorno é atribuído à


variaével m.

20 Sinaliza que será retornado o valor da variável mediaCalculada.

Veja nos vídeos a seguir as diversas formas de implementar a modularização. Sempre


utilize a forma que incorpore mais flexibilidade ao programa. Flexibilidade em que
sentido? Assista aos vídeos para entender.

7.1.2 Modularização – parte I


7.1.3 Modularização – parte II
7.1.4 Modularização – parte III
7.1.5 Modularização – parte IV
7.1.6 Protótipos de funções

Agora veremos que passar um vetor bidimensional como parâmetro para uma função é
similar.
imprimeVetor.c
1 void imprimeVetor (float arg[4][4]);
2
3 int main(){
4 float vetor [4][4] ;
5 int i , j ;
6
7 printf("\nDigite os elementos da vetor\n" ) ;
8 for (i = 0 ; i < 4 ; i++ ){
9 for (j = 0 ; j < 4 ; j++ ){
10 scanf ( "%f" ,&vetor [i][j]) ;
11 }
12 }
13 imprimeVetor (vetor) ;
14 }
15
16 void imprimeVetor (float arg[4][4]){
17 int i , j ;
18
19 printf("\nImpressao da vetor\n" ) ;
20 for (i = 0 ; i < 4 ; i++ ){
21 for (j = 0 ; j < 4 ; j++ ){
22 printf("%.1f\t" ,arg[i][j]);
23 }
24 printf("\n");
25 }
26 }

7.1.7 Passando vetor como parâmetro

7.2 Escopo de variáveis

Quando construímos programas modulares temos que dar atenção especial ao local onde
declaramos as variáveis e como queremos que essas variáveis sejam acessadas pelos
diversos módulos.

O termo escopo, no contexto de programação, corresponde a uma região delimitada do


código. Em linguagens como a C, essa região é formada por um bloco de instruções
delimitado pelas chaves. Aliado a existência de vários blocos (escopos) em um
programa, podemos incorporar a ideia de aninhamento ou indentação. A indentação é
apenas um recurso visual para facilitar a visualização da relação de dependência entre
os diversos blocos de instruções.

Veja no algoritmo abaixo a presença de quatro blocos de instruções (A, B, C e D). O


bloco A, delimitado pelas palavras inicio e fim, é o bloco de nível mais externo.
Percebe-se outros níveis de indentação começando pelo bloco B, delimitado pelas
instruções enquanto...faça e fim-enquanto. Em seguida o bloco C delimitado pela
primeira instrução se...então e fim-se. E finalmente o bloco D delimitado pela segunda
instrução se...então e fim-se.
inicio
...
enquanto (condição) faça
...
se (condição) então
A ...
B se (condição) então
C D ...
fim-se
fim-se
fim-enquanto
fim.

A indentação contribui muito para visualizarmos a hierarquia entre os blocos e as


regiões do código em que podemos acessar as
variáveis. Variáveis declaradas em escopo A
superior podem ser acessadas em todas as regiões B
com escopos subordinados. Em nosso exemplo C
acima, as variáveis declaradas no bloco A podem D
ser acessadas em todos os blocos do programa, as
variáveis declaradas no bloco B podem ser
acessadas somente nos blocos B, C e D. As
variáveis declaradas no bloco C podem ser acessadas nos blocos C e D. E finalmente as
variáveis declaradas no bloco D só podem ser acessadas no bloco D.

Resumindo, podemos dizer que uma variável possui o escopo global para todos os
blocos internos e escopo local para o próprio bloco. E porque isso é importante?
Simplesmente pelo fato de que se você referenciar uma variável fora do seu escopo é
como se ela não existisse e o programa acusará erro.

Existem três locais, em programas escritos em linguagem C, onde as variáveis podem


ser declaradas e desta forma são classificadas:

1. Fora de todas as funções, inclusive da função main(). A variável assim declarada é


chamada de variável global e pode ser usada em qualquer parte do programa. Uma
variável global é criada (alocada na memória) quando o programa inicia e é
destruída (liberada da memória) quando o programa é finalizado.

2. Dentro de uma função. A variável assim declarada é chamada de variável local e só


pode ser usada dentro desta função. Uma variável local é criada quando a função é
invocada e destruída quando a função é finalizada.

3. Na lista de parâmetros formais de uma função, para receber os argumentos que são
passados para a função. Uma variável declarada como parâmetro formal de uma
função comporta-se como uma variável local.

É uma boa prática dar preferência pelo uso de variáveis locais ao invés de variáveis
globais. Com o uso de variáveis locais garantimos que as instruções do bloco em que
está vinculada, não provoquem nenhum efeito inesperado em outras partes do programa
e contribui para a independência funcional tão desejada em um módulo. Por outro lado
o uso excessivo de variáveis globais pode causar muitos erros, por permitir efeitos
colaterais indesejados.

Agora podemos apresentar a forma geral de um programa em C.


declarações das bibliotecas necessárias
declarações das variáveis globais
declarações dos protótipos das funções

tipo-devolvido main (lista-de-parâmetros){


Escopo da
sequência-de-comandos;
variável LOCAL
}
Escopo da
tipo-devolvido f1 (lista-de-parâmetros){ variável
Escopo da GLOBAL
sequência-de-comandos;
variável LOCAL
}

tipo-devolvido f2 (lista-de-parâmetros){
sequência-de-comandos; Escopo da
} variável LOCAL
...

7.2.1 Escopo de variáveis

7.3 Atividades
0) Considerando a função:

int X(int A, int B, int C){


if ((A > B) && (B > C)){
return A;
}

if ((A < B) && (B < C)){


return B;
}else{
return (A + B + C) / 3;
}
}

Calcule:
a) X(10, 8, -1) b) X(1, 3, 5)
c) X(5, 2, -1) d) X(X(10, 8, -1), 6 * X(1, 3, 5), 2)

1) Codificar uma função que calcule e retorne o saldo final de uma aplicação financeira
levando em consideração que:

• Haverá um único deposito inicial.


• A cada dia o valor aplicado deverá ser atualizado por uma taxa de juros fixa.
• O valor permanecerá aplicado por um prazo em dias.
2) Faça uma função que verifique se um valor (inteiro) é perfeito ou não. Um valor é
dito perfeito quando ele é igual à soma dos seus divisores, excetuando ele próprio.
(Ex: 6 é perfeito porque 6 = 1 + 2 + 3, que são seus divisores). A função deve
retornar verdadeiro ou falso.

3) Crie uma função de nome dado6() que retorna, através de sorteio, um número de 1
até 6.

4) Crie uma função de nome dadoN() que retorna, através de sorteio, um número de 1
até N.

5) Faça uma função capaz de calcular o resultado de uma determinada operação entre
dois operandos.

6) Codificar uma função para calcular o fatorial de um número.

7) Codificar uma função que receba a pontuação dos 1000 candidatos participantes de
um concurso e calcule e retorne a quantidade de candidatos aprovados (pontuação
acima de 650).

8) O algoritmo abaixo, implementado na linguagem C, classifica um vetor de


elementos inteiros em ordem crescente. Implementar uma versão modularizada
desse algoritmo que contemple as seguintes funcionalidades:
• Preencher o vetor.
• Ordenar o vetor.
• Mostrar os elementos do vetor.

#define MAX 5
main() {
//Preenche o vetor
int i;
int numeros[MAX];
for(i=0; i<MAX; i++) {
printf("\nNumero:");
scanf("%d",&numeros[i]);
}

//Ordena o vetor
int j,aux;
for (i=0; i<MAX; i++) {
for (j=MAX-1; j>= i; j--) {
if (numeros[j-1] > numeros[j]) {
aux=numeros[j-1];
numeros[j-1]= numeros[j];
numeros[j]=aux;
}
}
}

//Mostra os elementos do vetor


for (i=0; i<MAX; i++) {
printf("\nNumero: %d",numeros[i]);
}
}
9) Crie outra versão do programa anterior, de forma a classificá-lo em ordem decrescente.

Você também pode gostar