Escolar Documentos
Profissional Documentos
Cultura Documentos
Programação
Parte I
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.
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?
Dados
necessários Transformações
Resultados
para realizadas com os
esperados
resolver o dados de entrada
problema
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.
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.
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.
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.
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.
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.
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.
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 PI 3.12159
#define ACELERACAO_GRAVIDADE 9.8
#define VELOCIDADE_LUZ 300000
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 }
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
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.
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.
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.
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
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.
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.
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.
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
?
Corda da tirolesa
Estrutura
metálica Ponto de apoio no solo
30o
100m
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
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
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.
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.
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
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.
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.
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.
Linha Comentário
Agora responda: qual a grande limitação da versão atual do programa? Se você ainda
não percebeu imagine a situação abaixo.
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
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.
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.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 }
#include <stdio.h>
#include <stdlib.h>
int main()
{
float nota1, nota2, media
return 0;
}
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.
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;
}
(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...
(Fluxograma)
C’1 C1
C’2 C2
C’n Cn
(Portugol)
Expressão
Ordinal
Assista aos vídeos abaixo para compreender melhor a alternativa múltipla, suas
características e limitações.
4.5 Atividades
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”);
}
}
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("\nonze");
}else{
printf("\ndoze");
}
}
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.
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?
(portugol) (linguagem C)
enquanto (expressão condicional) faça while (expressão condicional) {
c1; c1;
c2; c2;
... ...
cn; cn;
fim-enquanto }
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.
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”, ¬a);
8 media = media + nota;
9 contador = contador + 1;
10 }
11 media = media / 3;
12 printf(“\nA media das notas da turma: %f“, media);
13 }
Linha Comentário
6a8 Para cada repetição será realizado a entrada de uma nota e seu acúmulo
na variável media.
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.
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”, ¬a);
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", ¬a);
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.
(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);
4.8.1 Atividade
Como exercício, sugiro que crie uma versão do programa media.c trocando a estrutura
de repetição utilizada.
(linguagem C)
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.
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
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.
(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.
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.
Altura 4:
*
**
***
****
Altura 6:
*
**
***
****
*****
******
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:
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.
í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.
índice 0 1 2 3 4
valor
endereço 2293496 2293497 2293498 2293499 2293450
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
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.
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", ¬a[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
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”.
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).
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 }
Concorda com as
informações apresentadas?
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:
19
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.
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.
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.
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.
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
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.7 Atividades
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.
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.
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:
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.
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:
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.
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
1a4 Definição de uma estrutura chamada info que contém um campo chamado
nome (vetor de char) e outro campo chamado nota.
6.1 Typedef
Onde tipo é qualquer tipo de dados definido na linguagem C e novoTipo é um novo tipo
de dados definido pelo programador.
A partir da definição acima poderíamos declarar uma variável usando esse novo nome
real salario;
main (){
struct Ponto{
int x,y;
};
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.
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
}
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.
Linha Comentário
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.
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
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.
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
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 }
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.
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.
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.
tipo-devolvido f2 (lista-de-parâmetros){
sequência-de-comandos; Escopo da
} variável LOCAL
...
7.3 Atividades
0) Considerando a função:
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:
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.
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).
#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;
}
}
}