PRG-2011-1-tiago
Instrutor
Professor: Tiago Semprebom
Email: tisemp@ifsc.edu.br
Atendimento paralelo: 4a feira 14:30h - 15:30h e 5a feira 14:30h - 15:30h (Lab. de Desenvolvimento de Tele)
Lógica de Programação
- Baseado no material Lógica de Programação, de Paulo Sérgio de Moraes - uma das referências bibliográficas da disciplina.
- diretório web da disciplina: diretório web da disciplina
16/03: Introdução
- Tópicos: instrução, sequência, problemas do dia a dia.
- Páginas da apostila: 4 a 7.
17/03: Resolução de exercícios
- Resolução de exercícios propostos aos alunos na aula do dia 06/09
- Apresentação dos trabalhos de Conclusão de Curso CST Telecomunicações (TCCII) - Auditório Campus São José
23/03: Desenvolvendo algoritmos
- Tópicos: resolvendo problemas, linguagens e instrução disponíveis (vocabulário).
- Páginas da apostila: 8 a 11.
Exemplificando com shell scripts:
#!/bin/bash
# Cada linha no script abaixo corresponde a uma instrução ...
# O conjunto de instruções na ordem apresentada forma uma sequência lógica ...
echo Iniciando o script ...
echo Vou procurar todos os arquivos de texto existentes neste diretório
find . -type f -name "*.doc" > .tmp
find . -type f -name "*.txt" >> .tmp
find . -type f -name "*.rtf" >> .tmp
find . -type f -name "*.odt" >> .tmp
echo Os arquivos são:
cat .tmp
rm -f .tmp
Videos sobre algoritmos:
Problemas exemplo
Problema dos três recipientes
Há três recipientes com tamanhos distintos: um com 8 litros, outro com 5 litros e o terceiro com 3 litros. O recipiente com 8 litros está completamente cheio. Deseja-se colocar 4 litros em dois recipientes. Considere que os recipientes não são graduados.
Problema da travessia
Um barqueiro precisa levar um saco de milho, uma galinha e uma raposa para o outro lado do rio. Porém o barco somente é capaz de levar uma coisa de cada vez (além do barqueiro). Qual a sequência de travessias necessário para atravessar o milho, a galinha e a raposa ?
Torres de Hanoi
Há três hastes. Uma das hastes serve de suporte para três discos de tamanhos diferentes. Um disco menor sempre é colocado sobre um disco maior. A figura abaixo ilustra as hastes e os discos:
Desejam-se mover os três discos para a haste da direita. Porém só pode se mover um disco por vez, e um disco maior nunca pode ficar sobre um disco menor.
Operação possível: Move disco para haste
Qual a sequência de operações para mover os discos de uma haste para outra ?
Atividade extra
- O jogo LightBot mostra de uma forma divertida como criar pequenos algoritmos. Até que fase desse jogo você consegue chegar ?
Exercícios: desenho de figuras geométricas
- kturtle é um software educacional para ajudar no ensino de matemática, geometria e introdução à programação. Ele possibilita fazer desenhos facilmente, seguindo um programa com instruções de desenho. Usando as instruções:
reset
forward X
turnright angulo
turnleft angulo
</syntaxhighlight> ... escreva algoritmos para desenhar as seguintes figuras:
- triângulo equilátero
- triângulo isósceles
- triângulo escaleno
- quadrado
- hexágono
- octógono
- 7 hexágonos interligados (um central e seis periféricos).
24/03: Desenvolvendo algoritmos
Para criar algoritmos, deve-se primeiro entender o que são instruções e sequências lógicas;
O jogo LightBot mostra de uma forma divertida como criar pequenos algoritmos. Nesse jogo o robô deve se movimentar de acordo com uma sequência de instruções elementares definidas pelo jogador. Apesar de sua simplicidade, ele pode se tornar bastante desafiador ! Até que fase desse jogo você consegue chegar ?
Desenhando figuras geométricas
- Scratch é um software educacional para ajudar no ensino de matemática, geometria e introdução à programação. Com ele pequenos programas podem ser escritos de foram visual, com instruções representadas por blocos que se encaixam como Lego. Ele possibilita fazer desenhos facilmente, seguindo um programa com instruções de desenho. Use-o para desenhar estas figuras:
- triângulo equilátero
- triângulo isósceles
- quadrado
- hexágono
- quadrado com vértices interligados
- Um círculo
- Agora tente algo mais avançado:
Projeto: um jogo muito simples
Você conhece o jogo clássico Space Invaders ?
Pros padrões atuais esse é um jogo muito simples. Você conseguiria reproduzi-lo, mesmo que simplificado, no Scratch ? Ele poderia começar assim:
- O robô se movimenta na horizontal, comandado pelas teclas seta pra direita e seta pra esquerda.
- O helicóptero se movimenta de um lado a outro constantemente, refletindo nas bordas.
- Ao teclar espaço, um tiro sai do robô em direção ao topo do palco
- Se o tiro acertar o helicóptero, o jogo termina.
O que você precisa para fazer esse jogo ?
- Movimento do helicóptero.
- Movimento do robô comandado pelo teclado.
- Acionamento do tiro.
- Detecção se o tirou acertou o helicóptero.
Mãos à obra !
24/03: Introduzindo algoritmos: variáveis e expressões
Em nosso projeto sugerido na última aula (com data de entrega para amanhã, dia 31/03)
foi necessário armazenar a posição do robô antes de disparar o tiro em direção
ao helicóptero, na aula de hoje veremos o que são variáveis e para que servem.
Variáveis são usadas em algoritmos para guardar dados. Dados podem ser:
- Números inteiros ou reais
- Letras ou textos
- Valores lógicos (booleanos)
- ... e outros que vocês descobrirão futuramente !
Uma variável possui um identificador, que nada mais é que seu nome. No Scratch as variáveis são criadas e podem ser modificadas com os comandos categorizados em Variáveis (comandos laranjas):
Variáveis podem ser globais ou locais:
- Globais: são visíveis e podem ser usadas por qualquer objeto do Scratch.
- Locais: são visíveis e podem ser usadas somente pelo objeto do Scratch ao qual está vinculada.
Variáveis podem ser usadas em qualquer comando que precise de um valor numérico, como por exemplo o comando para mover um certo número de passos. No exemplo abaixo, um programa faz com que um objeto desenhe um triângulo no palco, sendo que o comprimento do lado do triângulo é informado pelo usuário.
Variáveis podem ser usadas em expressões aritméticas, que realizam algum cálculo com valores numéricos. No Scratch expressões são criadas combinando-se os blocos contidos em Operadores(blocos verdes-claros):
Usando esses blocos podem-se calcular novos valores usando variáveis ou constantes. Por exemplo, um pequeno programa que desenha um polígono qualquer precisa calcular o ângulo de quina da figura dependendo de sua quantidade de lados:
Usando esses conceitos sobre variáveis e expressões, faça as atividades a seguir.
Pong
Outro jogo clássico chamado Pong mostrava uma bola que refletia em uma parede, voltando e devendo ser interceptada por uma pequena base (que funcionava como raquete) comandada pelo jogador. Se conseguir interceptá-la, a bola é refletida de novo em direção à parede oposta, continuando assim o jogo. Se falhar, o jogo termina. Esse é considerado o primeiro videogame lucrativo a ter sido criado ...
Tente fazer uma versão do Pong usando o Scratch, mas com duas pequenas modificações. Há apenas uma base, que fica no canto inferior do palco. O placar conta quantas vezes a bola tocou o chão (i.e. o jogador falhou em interceptá-la), e se chegar a 0 o jogo termina. A segunda modificação é uma aceleração gradual da bola, que deve deve aumentar de velocidade a cada 5 segundos de jogo.
Para que serão necessárias variáveis nesse jogo ?
O problema da reflexão da bola na barra
Em aula vimos que para fazer a reflexão da bola com a barra deve-se calcular o ângulo de reflexão. No caso da barra estar na horizontal, esse ângulo deve ser calculado assim:
No Scratch isso deve ser feito combinando-se o comando "Aponte para direção" e uma expressão para calcular a nova direção. A direção atual do objeto está contida em sua variável local direção (predefinida nos comandos de Movimentos):
31/03: Algoritmos
- kturtle é um software educacional para ajudar no ensino de matemática, geometria e introdução à programação. Ele possibilita fazer desenhos facilmente, seguindo um programa com instruções de desenho. Usando as instruções:
reset (move a tartaruga para o centro da tela)
clear (limpa a tela)
pendown (põe a caneta no papel - acendeCaneta)
penup (levanta a caneta - apagaCaneta)
forward X (avança X posições)
turnright angulo (gira pra direita)
turnleft angulo (gira pra esquerda)
... escreva programas para os algoritmos para desenhar as seguintes figuras:
- triângulo equilátero
- triângulo isósceles
- triângulo escaleno
- quadrado
- hexágono
- octógono
- quadrado com vértices interligados
- Um círculo
- 7 hexágonos interligados (um central e seis periféricos).
- 7 círculos interligados (um central e seis periféricos), parecendo uma flor
Guia de referência completo do Kturtle
Atividade para casa
- Fractais são figuras nas quais cada pedacinho é semelhante à toda figura. Um fractal bastante simples de criar é o Floco de Neve Koch, cuja criação pode ser entendida na sequência de figuras abaixo:
Usando o kturtle desenhe essas figuras, reproduzindo o maior número de iterações que conseguir. Você consegue descobrir uma regra para gerá-las ?
Obs: fonte dessas figuras
Dicas para o kturtle
- Pode-se repetir uma sequência de instruções usando-se o comando repeat. Por exemplo, para desenhar um pentágono usando repeat:
repeat 5 {
forward 50
turnleft 72
}
- Podem-se usar variáveis para generalizar os algoritmos. Uma variável tem um identificador, que deve ser precedido do caractere $:
$x=5
$lado=50
repeat $x {
forward $lado
turnleft 360/$x
}
- Pode-se usar o comando ask para ler do teclado valores a serem usados no algoritmo de desenho:
$x = ask "Quantos lados tem o polígono ?"
$lado = ask "Qual o comprimento de cada lado ?"
repeat $x {
forward $lado
turnleft 360/$x
}
- Por fim, com o comando learn é possível criar novos comandos no kturtle. Por exemplo, para criar um comando que desenhe um triângulo:
learn triangulo $lado {
repeat 3 {
forward $lado
turnleft 120
}
}
Esse novo comando desenha um triângulo equilátero cujos lados tem comprimento dado pelo parâmetro $lado. Ele poderia ser usado assim em um algoritmo:
learn triangulo $lado {
repeat 3 {
forward $lado
turnleft 120
}
}
triangulo 50
triangulo 100
triangulo 100
Nesse exemplo, três triângulos são desenhados: um com lado 50, outro com lado 100, e um terceiro com lado 150. Veja que o número escrito logo após o comando triangulo irá aparecer no lugar de $lado no algoritmo que desenha o triângulo.
06/04: Pseudocódigo e diagrama de blocos (fluxograma)
- Adoção do Portugol IDE como ferramenta didática.
- Páginas da apostila: 12 a 14.
Portugol
As aulas de Lógica de Programação usarão um software de auxílio ao ensino de algoritmos chamado Portugol, desenvolvido na Escola Superior de Engenharia do Instituto Politécnico de Tomar, em Portugal.
Guia rápido de instalação e utilização do Portugol
Abaixo segue uma breve ajuda de como obtê-lo, instalá-lo e usá-lo. Esse guia assume que você esteja usando o Ubuntu Linux 9.04 ou superior.
- Faça o download do Portugol.
- Descompacte-o com o seguinte comando:
tar xzf portugol23.tar.gz
- Repare que existe agora um subdiretório portugol no diretório onde você o descompactou. Execute o Portugol com o seguinte comando:
java -jar portugol/Portugol.jar
Obs: você precisará ter Java instalado. Caso não o tenha, execute o comando: sudo apt-get install openjdk-6-jre
- Copie esse arquivo para poder ver fluxogramas coloridos, e grave-o no memso diretório onde está o Portugol.
- Veja a ajuda do Portugol, e use-a sempre que tiver dúvidas !
A tela inicial do Portugol segue abaixo, junto com um programa demonstrativo.
Exemplos de programas iniciais em Portugol:
- Lendo um número e mostrando-o na tela em seguida:
Inicio
inteiro x
Escrever "Digite um numero: ",
Ler X
Escrever "Numero digitado: ", x
Fim
- Lendo dois números, somando-os e mostrando o resultado na tela:
Inicio
inteiro x, y
Escrever "Digite um numero: ",
Ler x
Escrever "Digite outro numero: ",
Ler y
Escrever "Soma = ", x+y
Fim
O programa abaixo é equivalente:Inicio
inteiro x, y, z
Escrever "Digite um numero: ",
Ler x
Escrever "Digite outro numero: ",
Ler y
z <- x + y
Escrever "Soma = ", z
Fim
Atividades
- Média de três números: escreva um programa para calcular a média de três números.
Inicio
Inteiro n1, n2, n3, r
Escrever "Primeiro numero: "
ler n1
Escrever "Segundo numero: "
ler n2
Escrever "Terceiro numero: "
ler n3
r <- (n1 + n2 + n3) /3
Escrever "Media=", r
Fim
- Sequência de Fibonacci: em matemática corresponde aos números:
1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
... que pode ser descrita pela relação de recorrência
... com valores iniciais e .
Numerosas formas na natureza apresentam essa sequência, como neste girassol (cujas flores se dispõem em uma espiral):
Usando o Portugol escreva um programa que mostre os 10 primeiros números dessa sequência.
07/04: Fluxogramas, constantes e Variáveis
- Diagrama de blocos (fluxograma)
- Variáveis e constantes
Fluxogramas
Diagramas de bloco para auxiliar a descrição de algoritmos. Ajudam na compreensão do algoritmo, por poder visualizar o fluxo de execução.
Fluxograma para o algoritmo da média de trẽs números.
Blocos de uso mais comum
Obs: Arquivo de configuração das cores do fluxograma do Portugol.
Variáveis e constantes
- Variável: capaz de guardar um dado a ser usado no algoritmo. Pode ser entendida como uma caixa, onde se coloca um dado e se pode consultá-lo quantas vezes for necessário. O dado pode ser modificado (substituído por outro). Exemplo em Portugol:
Inicio
inteiro anos, dias
Escrever "Quantos anos se passaram ? "
Ler anos
dias <- anos * 365
Escrever "... então se passaram ", dias, " dias"
Fim
Nesse exemplo há duas variáveis: dias e anos
- Constante: semelhante à variável, porém o dado armazenado não pode ser modificado. Exemplo em Portugol:
Inicio
constante inteiro diasPorAno <- 365
inteiro anos, dias
Escrever "Quantos anos se passaram ? "
Ler anos
dias <- anos * diasPorAno
Escrever "... então se passaram ", dias, " dias"
Fim
Nesse exemplo há uma constante: diasPorAno
Variáveis e constantes devem ser declaradas antes de serem usadas (algumas poucas linguagens, como Python e Perl, não exigem isto). A declaração consiste do tipo e identificador da variável. O tipo corresponde ao tipo de valor que pode ser guardado, e o identificador é o nome da variável. No exemplo abaixo:
constante inteiro diasPorAno <- 365
inteiro anos, dias
Fim
Há duas variáveis do tipo inteiro, e seus identificadores são dias e anos. O tipo inteiro indica que essas variáveis podem guardar somente números inteiros.
Tipos de variáveis e constantes no Portugol:
Tipo
Descrição
Exemplo
Inteiro
Número inteiro entre -2 147 483 648 e 2 147 483 647 begin_of_the_skype_highlighting 2 147 483 647 end_of_the_skype_highlighting begin_of_the_skype_highlighting 2 147 483 647 end_of_the_skype_highlighting begin_of_the_skype_highlighting 2 147 483 647 end_of_the_skype_highlighting
Inteiro x <- 10
Real
Número real entre -1.7 E 308 e 1.7 E 308
Real y <- 10.789
Lógico
Valor booleano, com valores "Verdadeiro" e "Falso"
Logico ok <- Falso
Caracter
Um caractere da tabela ASCII
Caracter letra <- "A"
Texto
Uma sequência de caracteres (ou string)
Texto palavra <- "um teste"
A declaração de constantes é semelhante à de variáveis, bastanto prefixá-las com a palavra-chave constante.
Atividade
Para os exercícios abaixo, desenhe o fluxograma e escreva o algoritmo no Portugol.
- Faça um algoritmo que calcule a média de quatro números, porém mostrando as casas decimais (caso existam).
- Escreva um algoritmo que mostre, em sequência: 9, 9^2 (ao quadrado), 9^3 (ao cubo) e a soma desses 3 números.
- Escreva um algoritmo que leia o nome, sobrenome e idade de uma pessoa, e escreva na tela:
sobrenome, nome
idade anos
13/04: Algoritmos
- Resolução de exercícios
- Exemplo de um algoritmo simples, onde após calculado os valores de entrada de um usuário, apresenta-se os valores na tele. Observe a declaração de variáveis e constantes, além dos comentários e identação do código portugol:
inicio
//declaração das variáveis
texto nome<-"", sobrenome<-"", endereco<-""
inteiro ano<-0, idade<-0
constante inteiro ano_atual <- 2010
caracter sexo<-"X"
//área de leitura de valores
escrever "Informe o Nome: "
ler nome
escrever "Informe o Sobrenome: "
ler sobrenome
escrever "Informa o endereço: "
ler endereco
escrever "Informe o ano de nascimento: "
ler ano
escrever "Informe o sexo (M ou F): "
ler sexo
//calcula idade
idade <- (ano_atual - ano)
//Mostra valores
escrever "\n ****** Dados Pessoais ******"
escrever "\nNome Completo: ", nome, " ",sobrenome
escrever "\nEndereço: ", endereco
escrever "\nAno de Nascimento: ", ano
escrever "\nIdade: ", idade
escrever "\nSexo: ", sexo
fim
</syntaxhighlight>
- Solução do exercício das poltronas no cinema, proposta pelo Ismael:
inicio
// variaveis
inteiro ncadeira <- 0 , fila <- 0 , cadeira <- 0 , calculo <- 0
// area de leitura
escrever "informe o número de sua cadeira:\n"
ler ncadeira
// area de calculo
fila <- ( ncadeira / 20 ) + 1
cadeira <- ( ncadeira % 20 )
// mostrar valores
escrever "Fila: " , fila
escrever "\nCadeira: " , cadeira
fim
</syntaxhighlight>
14/04: Expressões lógicas e aritméticas
Expressão aritmética: um conjunto de operações sobre variáveis, constantes e funções numéricas, e que gera um determinado resultado numérico.
Exemplos de expressões aritméticas:
# Uma expressão que calcula quantos segundos existem em um horário do tipo horas, minutos e segundos
3600*horas + 60*minutos + segundos
# Uma expressão que calcula a velocidade instantânea, segundo um MRV
vel_inicial + aceleracao*tempo;
# Uma expressão que calcula o módulo de um vetor bidimensional, que possui coordenadas x e y
raiz(x^2 + y^2)
Os resultados de expressões podem ser mostrados na tela, ou armazenados em variáveis:
# Uma expressão que calcula quantos segundos existem em um horário do tipo horas, minutos e segundos
segundos <- 3600*horas + 60*minutos + segundos
# Uma expressão que calcula a velocidade instantânea, segundo um MRV
escrever 'Velocidade no instante ', tempo, ' = ', vel_inicial + aceleracao*tempo;
# Uma expressão que calcula o módulo de um vetor bidimensional, que possui coordenadas x e y
modulo <- raiz(x^2 + y^2)
Repare que uma expressão fica sempre do lado direito, quando atribuída a uma variável. A expressão é primeiro calculada, e em seguida seu resultado é armazenado na variável:
segundos <- 3600*horas + 60*minutos + segundos
Operadores aritméticos
Expressões aritméticas sao compostas por números e operadores aritméticos:
Obs: para os exemplos abaixo são usadas estas variáveis:
Real x, area, lado
inteiro dias, horas
Operador
Descrição
Exemplo
+
Adição
x <- x + 1
-
Subtração
x <- x - 1
*
Multiplicação
x <- x*x*x
/
Divisão
dias <- horas / 24
%
Módulo (resto de divisão)
horas <- horas % 24
^
Potenciação
area <- lado^2
Precedência dos operadores (nesta ordem): ^, *, /, %, + e -
A precedência pode ser modificada com o uso de parênteses. Ex:
escrever 1 + 2 * 3
escrever (1 + 2)*3
No Portugol, existem também algumas funções úteis, como a função raiz:
r <- raiz(x^2 + y^2)
O resultado de expressões aritméticas depende dos tipos numéricos das variáveis e constantes:
inicio
real x
inteiro y
inteiro resultadoInteiro
real resultadoReal
x <- 9
y <- 9
escrever "O resultado de uma expressão aritmética depende dos tipos das variá¡veis e constantes\n"
escrever "usadas na expressão. Se forem todas inteiras, então o resultado será inteiro.\n"
escrever "Veja este exemplo: \n"
escrever "Variável inteira y=", y
escrever "\nExpressão: y/2=", y/2
escrever "\n\nNeste segundo exemplo, repete-se a mesma expressão, porém usando-se uma\n"
escrever "variável real:\n"
escrever "variável real x=", x
escrever "\nExpressão: x/2=", x/2
x <- 4
y <- 5
escrever "\n\nSe as variáveis de diferentes tipos forem combinadas, o resultado da\n"
escrever "expressão será real:\n"
escrever "Variável real x=", x, " e inteira y=", y
escrever "\nExpressão: (x+y)/2=", (x+y)/2
escrever "\n\nNo entanto, se uma expressão tiver um resultado real, mas este for\n"
escrever "atribuído a uma variável inteira, então apenas a parte inteira será guardada:\n"
escrever "Variável real x=", x, " e inteira y=", y
y <- (x+y)/2
escrever "\nExpressão: y <- (x+y)/2 ... após executada, y=", y
fim
Atividades
- Escreva um algoritmo que calcule a raiz de uma equação de 1o grau.
- Escreva um algoritmo que calcule as raízes de uma equação de 2o grau. Assuma que existam duas raízes reais
- Um equipamento conta o tempo desde que foi ligado. No entanto, essa contagem é feita em segundos. Faça um algoritmo que converta o valor desse contador para horas, minutos e segundos.
- Faça um algoritmo que converta um número decimal para sua representação binária. Assuma que o número decimal tenha até dois dígitos.
- Resolução do ecercício 2, proposta pelo Giovanni e Francisco:
inicio
real va , vb , vc , x1,delta,x2 <- 0.0
escrever "Digite um valor para A: "
ler va
escrever "Digite um valor para B: "
Ler vb
escrever "Digite um valor para C: "
Ler vc
escrever "Sua equação é: " ,va,"x^2+",vb,"x+",vc, "=0\n"
delta <- (vb ^ 2) - (4*va*vc)
escrever delta ,"\n"
x1 <- ((-vb) + (raiz(delta))) / (2*va)
Escrever " x ' = " , x1
x2 <- ((-vb) - (raiz(delta))) / (2*va)
Escrever "\n x '' = " , x2
fim
20/04: Estruturas de decisão
Páginas da apostila: 26 a 31.
Estruturas de decisão possibilitam que se executem diferentes sequências de instruções de um programa, dependendo de uma condição a ser avaliada. Por exemplo, um jogo poderia armazenar a maior pontuação já obtida, e verificar se foi ultrapassada ao final de cada partida:
Se pontuacao > recorde então
recorde <- pontuação
FimSe
O exemplo acima mostra a estrutura de decisão Se condição entao comandos Fimse. Veja o próximo exemplo:
Se conceito > 70 entao
escrever 'Voce esta aprovado'
senao
escrever 'Desta vez não deu ... tente de novo !'
Fimse
O uso de Se condição entao comandos Senao comandos Fimse possibilita que se execute uma sequência de comandos se a condição for verdadeira, e outra sequência se for falsa.
Para fazer um bom uso de estruturas de decisão deve-se primeiro conseguir identificar as condições a serem avaliadas. Condições são escritas com expressões lógicas, e estas são compostas de operadores lógicos e relacionais aplicados a variáveis e constantes.
Condições
Obs: para os exemplos abaixo são usadas estas variáveis:
Logico correto, multa, aprovado, barato, bombear_agua
Logico descartar, baixo, reprovado, erro, enviado, recebido
inteiro erros, pontuacao, preco, endereco, velocidade
Real faltas, nivel_agua, altura
Operadores relacionais
Operador
Descrição
Exemplo
=
Igualdade
correto <- (erros = 0)
>
Maior
multa <- (velocidade > 80)
>=
Maior ou igual
aprovado <- (pontuacao >= 70)
<
Menor
barato <- (preco < 100)
<=
Menor ou igual
bombear_agua <- (nivel_agua <= 0.7)
=/=
Diferente
descartar <- (endereco =/= 12345)
Operadores lógicos
Operador
Descrição
Exemplo
NAO
Negação
baixo <- NOT (altura > 1.8)
E
Conjunção
aprovado <- NOT (conceito = "D") E (faltas <= 0.25)
OU
Disjunção
reprovado <- (conceito = "D") OU (faltas > 0.25)
XOU
Disjunção exclusiva
erro <- enviado XOU recebido
Precedência dos operadores (nesta ordem): NAO, E, OU e XOU
Lembre que a precedência pode ser modificada com o uso de parênteses.
21/04: Exercícios estruturas de decisão
- Feriado Nacional - Tiradentes
- Resolvam os exercícios. Os exercícios serão cobrados e vistos na próxima aula.
Atividades para serem desenvolvidas em sala no dia 04/10:
- Faça um programa que leia um número e então informe se ele é par ou ímpar.
- Um radar de trânsito faz a medição de velocidade de veículos e, dependendo do valor, calcula a multa a ser aplicada. Em uma determinada via esse radar foi configurado da seguinte forma:
- Se a velocidade for maior que 80 km/h, a multa é de R$ 360.
- Se a velocidade for maior que 60 km/h, a multa é de R$ 180.
- Se a velocidade for menor ou igual a 60 km/h, não há multa.
Escreva um algoritmo que calcule a multa de acordo com a velocidade de um veículo.
- Faça um algoritmo que leia três números do teclado, e mostre o maior e menor números.
- O objetivo de um estudo médico feito entre os anos 70 e 80 foi o desenvolvimento de um método para identificar pacientes de alto risco (que não sobreviverão ao menos 30 dias) com base nos dados obtidos nas primeiras 24 horas. O diagrama abaixo mostra uma regra de classificação que foi produzida nesse estudo. A letra F significa que não há um risco alto, e a letra G quer dizer paciente de alto risco.
Essa regra classifica os pacientes como F ou G dependendo de respostas do tipo sim/não a no máximo três perguntas. Como seria um algoritmo que a implementasse ? Escreva um algoritmo que faça o teste de risco de paciente cardíaco de um paciente, conforme descrito acima.
- Um estudo sobre sensibilidade de pessoas a temperaturas da água identificou que a maioria das pessoas considera fria a água com temperaturas abaixo de 25 graus, morna entre 25 e 30 graus, e quente acima de 30 graus. Escreva um algoritmo que mostre as palavras "fria", "morna" ou "quente" dependendo da temperatura da água que for informada.
- Em uma rede de computadores, o firewall restringe o acesso a Internet dependendo do horário e do tipo de usuário que faz o acesso. Os tipos de usuário abaixo têm as seguintes restrições:
- Funcionário: apenas entre 0:00 e 7:30, entre 18:30 e 0:00, e entre 12:00 e 13:30
- Financeiro: qualquer horário
- Diretoria: qualquer horário
Escreva um algoritmo que informe se um acesso foi permitido, em função do horário e do tipo de usuário.
- Modifique o algoritmo acima para adicionar a seguinte restrição:
- Funcionário: não pode acessar sites de jornal (ex: www.rbs.com.br)
- Financeiro: não pode acessar sites de jornal durante o expediente
- Diretoria: sem restrições a sites
- Faça um algoritmo para fazer a divisão de dois números reais. Antes de dividi-los deve ser feito um teste de validade. Caso não seja possível dividi-los, deve ser mostrada uma mensagem de erro. Se for possível, deve-se mostrar o resultado da divisão.
- Faça um jogo de par ou ímpar, em que o jogador aposta contra o computador. O jogador deve digitar um número entre 0 e 5 e optar entre par ou ímpar. O computador deve sortear um número também entre 0 e 5. Se a paridade da soma dos números do jogador e do computador for a mesma que o jogador optou, então ele ganha a partida, senão o computador vence.
- Escreva um algoritmo para identificar se há, dentre três palavras lidas do teclado, ao menos duas palavras distintas que pertençam ao conjunto {azul, preto, vermelho}. Exemplos:
- Se o usuário digitar verde, preto, vermelho, o programa deve mostrar na tela verdadeiro
- Se o usuário digitar verde, preto, preto, o programa deve mostrar na tela falso
- Se o usuário digitar azul, preto, azul, o programa deve mostrar na tela verdadeiro
Solução Exercício 3 proposto:
inicio
inteiro num<-0,maior<-0,menor<-0, i<-0
constante inteiro valores<-2 //declaração da constante
escrever "Digite um valor: \n"
ler num
maior <- num
menor <- num
para i de 1 até valores passo 1
ler num
se (num > maior) então
maior <- num
fimse
se (num < menor) então
menor <- num
fimse
proximo
escrever "O maior valor digitado é: ", maior
escrever "\n"
escrever "O menor valor digitado é: ", menor
fim
27/04: Estruturas de decisão
Há situações em que se precisa fazer um conjunto de comparações, como mostrado abaixo:
// Lê a data no formato numérico dia, mes, ano, e mostra a data no formato
// dia, nome do mês, ano.
Inicio
inteiro dia, mes, ano
texto nome_mes
escrever "Dia: "
ler dia
escrever "Mes: "
ler mes
escrever "Ano: "
ler ano
se mes = 1 entao
nome_mes <- "Janeiro"
senao
se mes = 2 entao
nome_mes <- "Fevereiro"
senao
se mes = 3 entao
nome_mes <- "Março"
senao
se mes = 4 entao
nome_mes <- "Abril"
senao
se mes = 5 entao
nome_mes <- "Maio"
senao
se mes = 6 entao
nome_mes <- "Junho"
senao
se mes = 7 entao
nome_mes <- "Julho"
senao
se mes = 8 entao
nome_mes <- "Agosto"
senao
se mes = 9 entao
nome_mes <- "Setembro"
senao
se mes = 10 entao
nome_mes <- "Outubro"
senao
se mes = 11 entao
nome_mes <- "Novembro"
senao
se mes = 12 entao
nome_mes <- "Dezembro"
fimSe
fimSe
fimSe
fimSe
fimSe
fimSe
fimSe
fimSe
fimSe
fimSe
fimSe
escrever dia, " de ", nome_mes, " de ", ano
fim
Além de ser trabalhoso esse encadeamento de Se ... entao ... senao, o algoritmo resultante fica pouco legível. Quer dizer, ele fica feio e difícil de entender.
Existe uma estrutura de decisão criada justamente para casos como esse, e que resulta em um algoritmo mais limpo e compreensível:
// Lê a data no formato numérico dia, mes, ano, e mostra a data no formato
// dia, nome do mês, ano.
Inicio
inteiro dia, mes, ano
texto nome_mes
escrever "Dia: "
ler dia
escrever "Mes: "
ler mes
escrever "Ano: "
ler ano
Escolhe mes
caso 1:
nome_mes <- "Janeiro"
caso 2:
nome_mes <- "Fevereiro"
caso 3:
nome_mes <- "Março"
caso 4:
nome_mes <- "Abril"
caso 5:
nome_mes <- "Maio"
caso 6:
nome_mes <- "Junho"
caso 7:
nome_mes <- "Julho"
caso 8:
nome_mes <- "Agosto"
caso 9:
nome_mes <- "Setembro"
caso 10:
nome_mes <- "Outubro"
caso 11:
nome_mes <- "Novembro"
Defeito:
nome_mes <- "Dezembro"
fimEscolhe
escrever dia, " de ", nome_mes, " de ", ano
fim
A estrutura de decisão escolhe ... caso tem uma certa flexibilidade. No exemplo abaixo, mostra-se a possibilidade de testar mais de um valor no mesmo caso:
inicio
caracter sexo
escrever "Qual o seu sexo (f/m):"
ler sexo
escrever "Olá "
escolhe sexo
caso "m", "M" :
escrever "senhor"
caso "f","F" :
escrever "senhorita"
defeito :
escrever "Sexo indefinido"
fimescolhe
escrever ", benvindo ao portugol"
fim
Atividades
- Faça um algoritmo que converta um número de 1 a 7 para o respectivo dia da semana (ex: 1 = domingo, 2 = 2a feira, e assim por diante).
- Faça uma calculadora com as quatro operações aritméticas. Sua calculadora deve ler (nesta ordem) o primeiro número, a operação aritmética (que deve ser informada usando o símbolo da respectiva operação: +, -, * ou /), e depois o segundo número. Ao final, seu algoritmo deve mostrar o resultado, ou uma mensagem de erro se a operação não for possível de realizar (ex: divisão por zero).
- A previsão do tempo na costa brasileira pode ser feita de forma aproximada usando-se um barômetro e um termômetro. Uma estimativa com boa chance de acerto se baseia na tabela abaixo:
Faça um algoritmo que forneça uma estimativa da previsão do tempo, usando essa tabela.
- Faça um algoritmo que mostre qual o último dia de um determinado mês informado pelo teclado. Caso seja informado o mês 2 (fevereiro), seu algoritmo deve identificar se é ano bissexto (assim o mês tem 29 dias), ou não (mês tem 28 dias). Obs: anos bissextos são dados pelas regras (segundo o calendário Gregoriano):
- De 4 em 4 anos é ano bissexto.
- De 100 em 100 anos não é ano bissexto.
- De 400 em 400 anos é ano bissexto.
- Prevalecem as últimas regras sobre as primeiras.
28/04: Feriado Nacional
- Feriado Nacional
04/05: Estruturas de repetição
Páginas da apostila: 32 a 35.
Alguns algoritmos vistos anteriormente possuem sequências repetitivas de instruções. Por exemplo, o algoritmo da média de quatro avaliações:
Inicio
real m1, m2, m3, m4
real media
escrever 'Avaliação 1:'
Ler m1
escrever 'Avaliação 2:'
Ler m2
escrever 'Avaliação 3:'
Ler m3
escrever 'Avaliação 4:'
Ler m4
media <- (m1 + m2 + m3 + m4) / 4
escrever 'Média: ', media
Fim
O algoritmo acima repete quatro vezes a sequência que lê uma nota do teclado. Porém há uma forma de expressar a repetição de sequências de instruções, usando-se o que se chama de estrutura de repetição. A estrutura de repetição enquanto condição faz repete todas as instruções enquanto a condição for verdadeira. A condição é escrita como uma expressão lógica, da mesma forma que na estrutura de decisão se condição então ... senão. Veja como fica o algoritmo acima ao ser reescrito para usar essa estrutura de repetição:
Inicio
constante inteiro NUMEROS <- 4
real m
real media
inteiro contador <- 0
enquanto contador < NUMEROS faz
escrever 'Avaliação ', contador, ':'
ler m
media <- media + m
contador <- contador + 1
fimEnquanto
escrever 'Média: ', media/NUMEROS
Fim
Esse algoritmo funciona somente para médias de quatro números. Porém calcular a média de qualquer quantidade de números usa a mesma lógica: ler os números, somá-los e dividir o total pela quantidade de números lidos. Por exemplo, para fazer com que ele calcule a média de 7 números é necessário escrevê-lo assim:
Inicio
constante inteiro NUMEROS <- 7
real m
real media
inteiro contador <- 0
enquanto contador < NUMEROS faz
escrever 'Avaliação ', contador, ':'
ler m
media <- media + m
contador <- contador + 1
fimEnquanto
escrever 'Média: ', media/NUMEROS
Fim
Note que o algoritmo praticamente não foi modificado, pois somente se alterou o valor da constante NUMEROS.
A estrutura de repetição junto com a sequência de instruções a ser repetida é comumente chamada de 'laço. Assim, no algoritmo acima o laço aparece em:
enquanto contador < NUMEROS faz
escrever 'Avaliação ', contador, ':'
ler m
media <- media + m
contador <- contador + 1
fimEnquanto
Um outro exemplo ainda mais simples é mostrar na tela uma contagem numérica:
inicio
inteiro contador
contador <- 0
enquanto contador < 10 faz
escrever contador , " "
contador <- contador + 1
fimenquanto
fim
Ao executar esse algoritmo, tem-se como resultado:
0 1 2 3 4 5 6 7 8 9
Repare no uso de uma variável auxiliar contador para controlar a quantidade de repetições. Essa é uma técnica comum para
controlar a estrutura de repetição, e já foi usada no exemplo da média. Ela pode também ser combinada com outras condições, como mostrado abaixo:
inicio
inteiro contador <- 1
caracter opcao <- "s"
enquanto ((opcao = "s") ou (opcao = "S")) e contador < 11 faz
escrever contador, "\n"
contador <- contador + 1
escrever "\nContinuar (S/N) ? "
ler opcao
fimenquanto
escrever "Terminou com contador = " , contador
fim
Nesse exemplo se usa um laço para mostrar uma contagem de 1 a 10. Porém há a possibilidade de encerrar o algoritmo. Observe a condição para continuidade do laço: ela é verdadeira somente se contador < 11 e se a variável opcao for igual a "s" ou "S".
Finalmente, apesar de ser comum o uso de contadores para controle do laço, pode-se usar qualquer condição para essa finalidade. Então podem existir laços que não usam contadores para controlar a quantidade de repetições, como no próximo exemplo:
inicio
constante texto segredo <- "secreto"
texto senha
ler senha
enquanto senha =/= segredo faz
escrever "Voce continua preso ! Digite a senha correta: "
ler senha
fimenquanto
escrever "Voce foi liberado ..."
fim
Solução do problema proposto em sala)
inicio
inteiro opcao <- 0
real numero1 <- 0 , numero2 <- 0 , resultado <- 0
enquanto opcao =/= 5 faz
escrever "\n Entre com a opção desejada: 1- Adição; 2- Subtração; 3- Multiplicação; 4- Divisão , 5- Sair."
ler opcao
se opcao = 5 entao
escrever "\n Você saiu com sucesso!"
senao
escrever "\n Lembre-se: Na subtração e na divisão a ordem dos números é importante!"
escrever "\n Entre com o primeiro número: "
ler numero1
escrever "\n Entre com o segundo número: "
ler numero2
se opcao = 1 entao
resultado <- ( numero1 + numero2 )
escrever "\n A soma dos dois números é: " , resultado
fimse
se opcao = 2 entao
resultado <- ( numero1 - numero2 )
escrever "\n A subtração dos dois números é: " , resultado
fimse
se opcao = 3 entao
resultado <- ( numero1 * numero2 )
escrever "\n O produto dos dois números é: " , resultado
fimse
se opcao = 4 entao
se numero2 = 0 entao
escrever "\n Não existe divisão por 0 (zero)."
senao
resultado <- ( numero1 / numero2 )
escrever "\n A divisão dos dois números é: " , resultado
fimse
fimse
se ( opcao =/= 1 e opcao =/= 2 ) e ( opcao =/= 3 e opcao =/= 4 ) entao
escrever "\n Esta operação não está definida."
fimse
fimse
fimenquanto
fim
</syntaxhighlight>
Atividades
- Escreva um algoritmo que mostre a tabuada de um número fornecido pelo teclado. Esse número deve estar entre 1 e 10.
- Modifique o exemplo da média para que a quantidade de números a serem lidos seja previamente informada pelo teclado.
- Modifique novamente o exemplo da média para que ela funcione para um quantidade de números desconhecida de antemão. Quer dizer, o algoritmo deve ler os números para calcular a média, mas não sabe quantos números existem (e isto não pode ser informado pelo teclado).
- Modifique o exemplo da senha para que o usuário tenha somente três tentativas permitidas para digitar a senha correta. caso ao final as três senhas estejam erradas, o algoritmo deve informar que a conta foi bloqueada.
- Escreva um algoritmo que leia até 10 números do teclado, e informe ao final qual o maior e o menor deles.
- Escreva um algoritmo que teste se um número informado pelo teclado é primo.
05/05: Estruturas de repetição
- Resolução de exercícios
- Introdução a variáveis multidimencionais
11/05: Estruturas de repetição
Variáveis multidimensionais
Em matemática existem matrizes e vetores, que são variáveis multidimensionais. Por exemplo, uma matriz 3 x 3 (3 linhas e 3 colunas) pode ser:
Vetores são matrizes unidimensionais, portanto possuem somente uma linha ou uma coluna:
Cada elemento em uma matriz ou vetor é identificado pela sua posição. Por exemplo, na posição 1, 2 da matriz A acima está o valor 6, e na posição 4 do vetor v está o valor 18. Assim, a matriz A do exemplo pode ser entendida da seguinte forma:
... e o vetor v do exemplo:
Nas linguagens de programação em geral existe um conceito muito parecido, chamado de variáveis multidimensionais ou simplesmente matrizes (arrays em inglẽs). Para exemplificar, no Portugol se poderiam definir a matriz A e o vetor v:
inicio
inteiro A[2][2] <- {{1, 6}, {3, 5}}
inteiro M[3][2];
inteiro v[5] <- {1, 6, 2, 18, 5}
inteiro i, j
escrever "Valor de A[0][0]: ", A[0][0], "\n"
escrever "Valor de A[0][1]: ", A[0][1], "\n"
escrever "Valor de A[1][0]: ", A[1][0], "\n"
escrever "Valor de A[1][1]: ", A[1][1], "\n"
escrever "Valor de v[0]: ", v[0], "\n"
escrever "Valor de v[1]: ", v[1], "\n"
escrever "Valor de v[2]: ", v[2], "\n"
escrever "Valor de v[3]: ", v[3], "\n"
escrever "Valor de v[4]: ", v[4], "\n"
fim
A declaração da matriz se faz como uma variável comum, porém indicando-se suas dimensões:
inteiro A[2][2] <- {{1, 6}, {3, 5}}
inteiro M[3][2];
Exemplo de preenchimento e impressão de matrizes não quadradas
inicio
inteiro i,j, mat[2][4]
//leitura (preenchimento da matriz)
para i de 0 ate 1 passo 1
para j de 0 ate 3 passo 1
ler mat[i][j]
proximo
proximo
//impressão da matriz
para i de 0 ate 1 passo 1
para j de 0 ate 3 passo 1
escrever "O valor na linha: ",i, "Coluna: ", j, "eh: ", mat[i][j]
escrever "\n"
proximo
proximo
fim
Veja que a matriz M foi declarada sem valores iniciais, porém a matriz A foi inicializada na declaração.
O acesso aos elementos da matriz se faz usando-se índices, que funcionam como coordenadas dos elementos que se quer acessar. Os índices iniciam em 0:
# índice 0,0
escrever "Valor de A[0][0]: ", A[0][0], "\n"
O exemplo acima pode ser reescrito usando-se estruturas de repetição:
inicio
inteiro A[2][2] <- {{1, 6}, {3, 5}}
inteiro v[5] <- {1, 6, 2, 18, 5}
inteiro i, j
enquanto i < 2 faz
j <- 0
enquanto j < 2 faz
escrever "Valor do elemento de A na posição ", i, ", ", j, ": ", A[i][j], "\n"
j <- j + 1
fimenquanto
i <- i + 1
fimenquanto
i <- 0
enquanto i < 5 faz
escrever "valor de v na posição ", i, ": ", v[i], "\n"
i <- i + 1
fimenquanto
fim
Como se vê, matrizes e vetores casam perfeitamente com estruturas de repetição, e são úteis para a resolução de inúmeros problemas. Por exemplo, o problema de mostrar o nome do mês a partir do número do mês, feito anteriormente com escolhe ... caso pode ser feito assim com um vetor:
inicio
texto nome_mes[12] <- {"Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro",
"Outubro", "Novembro, "Dezembro"}
inteiro dia, mes, ano
escrever "Dia: "
ler dia
escrever "Mes: "
ler mes
escrever "Ano: "
ler ano
escrever dia, " de ", nome_mes[mes], " de ", ano
fim
Outro problema comum é precisar guardar um conjunto de valores, e depois ordená-los:
inicio
inteiro v[10]
inteiro i
inteiro quantidade
escrever "Quantos valores serão digitados (máximo = 10) ? "
ler quantidade
i <- 0
enquanto i < quantidade faz
escrever "valor ", i, ": "
ler v[i]
i <- i + 1
fimenquanto
// ordena os valores ...
escrever "valores ordenados: "
i <- 0
enquanto i < quantidade
escrever v[i], " "
i <- i + 1
fimenquanto
fim
Atividades
- Escreva um algoritmo que leia 5 números do teclado, e depois mostre-os em ordem inversa à que foi digitada.
- Escreva um algoritmo que leia dois vetores de 5 números, e depois mostre se os vetores são iguais.
- Escreva um algoritmo que leia um palavra do teclado e depois procure-a numa lista de palavras preexistente. Essa lista deve ser implementada usando um vetor.
- Escreva um algoritmo que leia 5 números, e mostre-os em ordem crescente.
- Modifique o algoritmo anterior para mostrá-los em ordem decrescente.
- Em um jogo de bingo devem-se contar quantos números de uma aposta foram sorteados no bingo. Faça um algoritmo que, dados os números sorteados e uma aposta, conta quantos números apostados forma sorteados.
Solução exercício 4 e 6 propostos pelo Luiz Gustavo
inicio
//declaração da variáveis
inteiro v [ 5 ] , i , j , troca
//entrada de dados
para i de 0 ate 4 passo 1
ler v [ i ]
proximo
//organizar em ordem crescente
para i de 0 ate 4 passo 1
para j de 0 ate 4 passo 1
se v [ i ] > v [ j ] entao
troca <- v [ i ]
v [ i ] <- v [ j ]
v [ j ] <- troca
fimse
proximo
proximo
//impressão dos dados
para i de 0 ate 4 passo 1
escrever "\n" , v [ i ]
proximo
fim
</syntaxhighlight>
inicio
//declaração das variáveis
inteiro lista_num [5][5] <- {{10, 5, 20, 31, 33}, {51, 12, 13, 15, 29}, {25, 28, 22, 26, 36},
{11, 24, 34, 54, 44}, {1, 2, 55, 3, 5}}
inteiro numero [5][5],i,j,cont
//entrada de dados
escrever "Informe os números do Bingo: "
enquanto i < 5 faz
j <- 0
enquanto j < 5 faz
ler numero [ i ] [ j ]
j <- j + 1
fimenquanto
i <- i + 1
fimenquanto
//verificando quantos números são iguais
i <- 0
enquanto i < 5 faz
j <- 0
enquanto j < 5 faz
se (numero [i][j] = lista_num [i][j]) entao
cont <- cont + 1
fimse
j <- j + 1
fimenquanto
i <- i + 1
fimenquanto
//Imprimindo os dados
escrever "A quantidade de números sorteados nesta aposta foi: " , cont
fim
</syntaxhighlight>
25/10: Revisão para avaliação de Lógica de Programação
1. Crie um programa que lê três inteiros e informa VERDADEIRO se apenas o maior deles é par ou se o menor deles é ímpar ou informa FALSO em caso contrário.
2. Desenvolva um programa que recebe do usuário o placar de um jogo de futebol (os gols de cada time) e informa se o resultado foi um empate, a vitória do primeiro time ou do segundo time.
3. Elabore um programa que recebe do usuário três cadeias de caracteres e informa VERDADEIRO se há pelo menos duas diferentes cadeias iguais aos valores 'azul', 'preto'ou 'vermelho' ou FALSO em caso contrário. Exemplos: {'azul', 'preto', 'branco'} é VERDADEIRO; {'azul', 'roxo', 'azul'} é FALSO; {'preto', vermelho', 'vermelho'} é VERDADEIRO.
4. Tendo-se como dados de entrada a altura e o sexo de uma pessoa, construa um algoritmo que calcule seu peso ideal, utilizando as seguintes fórmulas:
- para homens: (72,7 * h) – 58;
- para mulheres: (62,1 * h) – 44,7.
5. Escrever um algoritmo, que leia um conjunto de 23 dados, cada um, contendo o peso e o código do sexo ("F" ou "M") dos alunos de uma classe, calcule e imprima:
- Maior e o menor peso da turma;
- A média de peso dos homens;
- A média de peso da turma;
Solução proposta pelo Manfred Ex. 1
inicio
inteiro n1 <- 0 , n2 <- 0 , n3 <- 0 , maior <- 0 , menor <- 0
escrever "Digite o primeiro número: "
ler n1
escrever "Digite o segundo número: "
ler n2
escrever "Digite o terceiro número: "
ler n3
maior <- n1
se ( n2 > maior ) entao
maior <- n2
fimse
se ( n3 > maior ) entao
maior <- n3
fimse
menor <- n1
se ( n2 < menor ) entao
menor <- n2
fimse
se ( n3 < menor ) entao
menor <- n3
fimse
se ( maior % 2 ) = 0 ou ( menor % 2 ) =/= 0 entao
escrever "Verdadeiro"
senao
escrever "Falso"
fimse
fim
</syntaxhighlight>
Proposta do Luiz para exercício 5
inicio
//declaração das variaveis
real peso [ 5 ] <- 0 , menor <- 0 , maior <- 0 , pesom <- 0 , pesot <- 0
inteiro i , cont <- 0
caracter sexo [ 5 ]
//entrada de dados
para i de 0 ate 4 passo 1
escrever "Informe o peso do " , ( i + 1 ) , "º aluno: "
ler peso [ i ]
escrever "Informe o código do sexo do " , ( i + 1 ) , "º aluno (Masculino= M; Feminino= F): "
ler sexo [ i ]
escrever "\n"
proximo
//testando o maior e menor peso
maior <- peso [ 1 ]
menor <- peso [ 1 ]
para i de 0 ate 4 passo 1
se ( peso [ i ] > maior ) entao
maior <- peso [ i ]
fimse
se ( peso [ i ] < menor ) entao
menor <- peso [ i ]
fimse
proximo
//calculando a media de peso dos homens
para i de 0 ate 4 passo 1
se ( sexo [ i ] = "M" ) ou ( sexo [ i ] = "m" ) entao
pesom <- ( pesom + peso [ i ] )
cont <- ( cont + 1 )
fimse
proximo
//calculando a media de peso da turma
para i de 0 ate 4 passo 1
pesot <- ( peso [ i ] + pesot )
proximo
//impressão dos dados
escrever "\nO maior peso é: " , maior , "\nO menor peso é: " , menor
escrever "\nA média de peso dos homens é: " , ( pesom / cont )
escrever "\nA média de peso da turma é: " , ( pesot / 5 )
fim
25/10: Revisão Lógica de Programação, com respostas :)
1. Desenvolver um programa que efetue a leitura de 5 elementos de uma matriz A do tipo vetor. Construir uma matriz B de mesmo tipo, observando a seguinte lei de formação: Se o valor do índice for par, o valor deverá ser multiplicado por 5, sendo ímpar deverá ser somado por 5. Ao final mostrar os conteúdos das duas matrizes.
inicio
//declaração dos vetores A e B
inteiro i,a[5],b[5]
//formação do vetor A
para i de 0 ate 4 passo 1
ler a[i]
proximo
//guarda valor na posição par
para i de 0 ate 4 passo 2
b[i]<-a[i]*5
proximo
//guarda valor na posição ímpar
para i de 1 ate 4 passo 2
b[i]<-a[i]+5
proximo
//apresenta valor B resposta
escrever "Formação do vetor B (vetor respota):"
escrever "\n"
para i de 0 ate 4 passo 1
escrever "O valor da posição ",i, " é: ", b[i]
escrever "\n"
proximo
fim
</syntaxhighlight>
Solução para o exercício 1 desenvolvida pelo Thiarlles e Manfred:
inicio
real matrizA[10], matrizB[10]
inteiro i<-0
escrever "\n Construa a matriz A."
enquanto i <= 9 faz
escrever "\n Entre com a posição ", i
ler matrizA[i]
i <- i+1
fimEnquanto
i <- 0
enquanto i <= 9 faz
escrever matrizA[i], " "
i <- i+1
fimEnquanto
escrever "\n "
i <- 0
enquanto i <= 9 faz
matrizB[i] <- ((matrizA[i])*5)
matrizB[i+1] <- ((matrizA[i+1])+5)
i <- i+2
fimEnquanto
i <- 0
escrever "\n A matriz B será: "
enquanto i <= 9 faz
escrever matrizB[i], " "
i <- i+1
fimenquanto
fim
</syntaxhighlight>
2. Desenvolver um programa que efetue a leitura de 5 elementos de uma matriz A do tipo vetor. No final, apresente o total da soma de todos os elementos que sejam ímpares.
inicio
//declaração das variáveis
inteiro a [5] , i , soma <- 0
//entrada de dados
para i de 0 ate 4 passo 1
ler a [i]
proximo
//construindo a matriz "B"
para i de 0 ate 4 passo 1
se ( a [i] % 2 =/= 0 ) entao
soma <- soma + a [ i ]
fimse
proximo
//impressão dos dados
escrever "O valor da soma dos numero ímpares é: " , soma
fim
</syntaxhighlight>
3. Ler 15 elementos de uma matriz A do tipo vetor. Construir uma matriz B de mesmo tipo. Observando a seguinte lei de formação: “Todo elemento de B deverá ser o quadrado do elemento de A correspondente”.
inicio
//declaração das variáveis
inteiro a[15] ,b[15] ,i
//entrada de dados
para i de 0 ate 14 passo 1
ler a[i]
proximo
//construindo a matriz "B"
para i de 0 ate 14 passo 1
b[i] <- a[i] * a[i]
proximo
//impressão dos dados
escrever "\nMatriz A:"
para i de 0 ate 14 passo 1
escrever "" , a[i]
proximo
escrever "\nMatriz B:"
para i de 0 ate 14 passo 1
escrever "" , b [i]
proximo
fim
</syntaxhighlight>
4. Escreva um algoritmo que:
- Leia uma matriz 5 x 5 de elementos reais;
- Divida cada elemento de uma linha da matriz pelo elemento da diagonal principal desta linha;
- Imprima a matriz assim modificada.
inicio
//declaração das variáveis
real a [5] [5] , b [5] [5]
inteiro i , j
//entrada de dados
para i de 0 ate 4 passo 1
para j de 0 ate 4 passo 1
ler a [i] [j]
proximo
proximo
//dividindo a linha da matriz por sua diagonal principal
para i de 0 ate 4 passo 1
para j de 0 ate 4 passo 1
b [i] [j] <- ( a [i] [j] / a [i] [i] )
proximo
proximo
//impressão dos dados
escrever "\nMatriz: "
escrever "\n"
para i de 0 ate 4 passo 1
escrever "\n" , a [i] [0] , " " , a [i] [1] , " " , a [i] [2] , " " , a [i] [3] , " " , a [i] [4]
proximo
escrever "\n\nMatriz modificada: "
escrever "\n"
para i de 0 ate 4 passo 1
escrever "\n" , b [i] [0] , " " , b [i] [1] , " " , b [i] [2] , " " , b [i] [3] , " " , b [i] [4]
proximo
fim
</syntaxhighlight>
5. Elabore um algoritmo para corrigir provas de múltipla escolha. Assuma que em cada prova encontraremos os seguintes dados: RM, NOME DO ALUNO, MATÉRIA e BIMESTRE, além de 10 questões numeradas de 1 até 10 e que cada questão possui 5 alternativas identificadas pelas letras de “a” até “e”. Primeiramente, o algoritmo deve ler o gabarito e o número de provas a serem corrigidas . A seguir, os dados das provas a serem corrigidas devem ser lidas. Ainda, o algoritmo deverá calcular e escrever:
- O RM, NOME DO ALUNO, MATÉRIA, BIMESTRE e a NOTA de cada aluno (assumindo que cada questão correta vale 1 ponto).
- A porcentagem de aprovação, assumindo que a nota mínima para aprovação é 6.
inicio
//declaração das variáveis
caracter gab [10] , resp [10]
inteiro i , qtdprova , cont <- 0 , aprovados <- 0
real nota <- 0
texto rm <- "" , aluno <- "" , mat <- "" , bimestre <- ""
//entrada de dados
para i de 0 ate 9 passo 1
escrever "Informe o gabarito da " , (i + 1) , "ª questão:"
ler gab [i]
proximo
escrever "Informe a quantidade de provas: "
ler qtdprova
//dados das provas
enquanto cont < qtdprova faz
escrever "**************************************************"
escrever "\nInforme RM: "
ler rm
escrever "Informe o nome do aluno: "
ler aluno
escrever "Informe a matéria: "
ler mat
escrever "Informe o bimestre: "
ler bimestre
//informando as respostas
para i de 0 ate 9 passo 1
escrever "Informe a resposta da " , (i + 1) , "ª questão:"
ler resp [i]
proximo
//corrigindo a prova
nota <- 0
para i de 0 ate 9 passo 1
se ( gab [i] = resp [i] ) entao
nota <- nota + 1
fimse
proximo
//informando a nota
escrever "A nota do(a) " , aluno , " é: " , nota , "\n\n"
//verificando aprovação do aluno
se ( nota >= 6 ) entao
aprovados <- ( aprovados + 1 )
fimse
cont <- ( cont + 1 )
fimenquanto
//imprimindo valores
escrever "\n**************************************************"
escrever "\nA quantidade de aprovados é: " , aprovados
fim
</syntaxhighlight>
28/10: Avaliação de Lógica de Programação
Dicas para a avaliação (vale a pena revisar conceitos):
- Números primos
- Fatorial
- MDC: Máximo Divisor Comum
- MMC: Mínimo Múltiplo Comum
- Cálculo para série de Fibonacci
Conceitos Avaliação de Lógica:
- Conceitos avaliação de Lógica de Programação clique aqui
02/11: Feriado Nacional
- Finados (sem atividades).
04/11: Linguagem C
- Introdução a linguagem C
- Primeiros Programas
- Compilador Gcc
- Para provocar: Teach Yourself Programming in Ten Years
- Apostila adotada: Curso de Linguagem C - Engenharia Elétrica - UFMG
Obs: durante as aulas usaremos o NetBeans, um Ambiente Integrado de Desenvolvimento (IDE - Integrated Development Environment). Um IDE é um programa que auxilia o programador. Ele integra um editor de programas, um gerenciador de projetos, compilador e um depurador (debugger).
Para instalar o Netbeans:
- Faça o download do instalador. Salve-o em algum subdiretório.
- Abrindo um terminal, entre no subdiretório onde está o instalador e execute esse comando:
bash netbeans-6.8-ml-cpp-linux.sh
- Caso o instalador falhe porque não encontrou a JVM (Máquina Virtual Java), instale-a com esse comando:
sudo apt-get install -y sun-java6-jdk
- Aceite as opções de instalação sugeridas pelo instalador.
- Ao final da instalação, o Netbeans 6.8 estará acessível pelo menu Aplicativos -> Programação.
- Sempre que for escrever um novo programa com o Netbeans, crie um novo projeto (ver menu Arquivo->Novo Projeto). Selecione um projeto do tipo "Aplicativo C/C++".
Compilando o primeiro programa
- O clássico Hello World!
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("Alô mundo!\n");
}
- Mostrando mensagens de na tela: puts e printf:
#include <stdio.h>
int main() {
int n;
n = 5;
puts("Demonstração de puts e printf");
printf("Valor de n: %d\n", n);
n = n + 1;
printf("Novo valor de n: %d\n", n);
return 0;
}
- Lendo dados do teclado: scanf
#include <stdio.h>
int main() {
int n;
printf("Digite um número inteiro: ");
scanf("%d", &n);
printf("Valor digitado foi %d\n", n);
return 0;
}
Tipos de dados
Portugol
C
Exemplo
inteiro
int
int x;
caracter
char
char letra;
real
float ou double
float pi = 3.1416;
texto
char * ou vetor de char
char * mensagem = "Hello world";
char palavra[16];
logico
qualquer tipo (valor 0 = Falso, qualquer outro valor = Verdadeiro)
int ok = 1;
char teste = 0;
Comandos/funções e Estruturas de controle
Portugol
C
Exemplo
inteiro n, m
escrever "Ola, mundo!\n"
escrever "valor de n: ", n, "\n"
escrever "valor de n: ", n, ", e valor de x: ", x, "\n"
int n, m;
printf("Ola, mundo!\n");
printf("valor de n: %d\n", n);
printf("valor de n: %d, e valor de x: %d\n", n, x);
inteiro n
ler n
int n;
scanf("%d", &n);
se condição então
//comandos
fimse
if (condição) {
//comandos
}
se condição então
//comandos
senão
//comandos
fimse
if (condição) {
//comandos
} else {
//comandos
}
escolhe expressão
caso valor1:
//comandos
caso valor2:
//comandos
defeito:
//comandos
fimescolhe
switch (expressão) {
case valor1:
//comandos
case valor2:
//comandos
default:
//comandos
}
enquanto condição faz
//comandos
fimenquanto
while (condição) {
//comandos
}
para variavel de inicio ate fim passo incremento
//comandos
proximo
for (variavel=inicio; variavel <= fim; variavel++) {
//comandos
}
Atividades
- Traduza para C os seguintes algoritmos Portugol:
Inicio
inteiro x, y
Escrever "Digite um numero: ",
Ler x
Escrever "Digite outro numero: ",
Ler y
Escrever "Soma = ", x+y
Fim
Inicio
inteiro x, y, z
Escrever "Digite um numero: ",
Ler x
Escrever "Digite outro numero: ",
Ler y
z <- x + y
Escrever "Soma = ", z
Fim
Inicio
Inteiro n1, n2, n3, r
Escrever "Primeiro numero: "
ler n1
Escrever "Segundo numero: "
ler n2
Escrever "Terceiro numero: "
ler n3
r <- (n1 + n2 + n3) /3
Escrever "Media=", r
Fim
Inicio
inteiro anos, dias
Escrever "Quantos anos se passaram ? "
Ler anos
dias <- anos * 365
Escrever "... então se passaram ", dias, " dias"
Fim
Inicio
constante inteiro diasPorAno <- 365
inteiro anos, dias
Escrever "Quantos anos se passaram ? "
Ler anos
dias <- anos * diasPorAno
Escrever "... então se passaram ", dias, " dias"
Fim
inicio
real massa
real forca
real aceleracao
constante real g <- 9.8
constante real ac <- 0.01
escrever "força: "
ler forca
escrever "massa: "
ler massa
aceleracao <- forca/massa - ac*massa*g
escrever "aceleracao=", aceleracao, " m/s2"
fim
inicio
real a, b, c
real delta
real x1, x2
escrever "Forneça os coeficientes da equação de 2o grau (formato: ax^2 + bx + c):\n"
escrever "a="
ler a
escrever "b="
ler b
escrever "c="
ler c
delta <- b^2 - 4*a*c
x1 <- (-b + delta^0.5)/(2*a)
x2 <- (-b - delta^0.5)/(2*a)
escrever "1a raiz=", x1
escrever "\n2a raiz=", x2
fim
inicio
real x1, x2, x3, x4, x5
real media
real desvioPadrao
constante inteiro N <- 5
// Ler os cinco valores pelo teclado
ler x1
ler x2
ler x3
ler x4
ler x5
// Calcular a media
media <- (x1 + x2 + x3 + x4 + x5) / N
// Calcular o desvio padrao
desvioPadrao <- (x1 - media)^2 + (x2 - media)^2 + (x3 - media)^2 + (x4 - media)^2 + (x5 - media)^2
desvioPadrao <- (desvioPadrao / (N-1))^0.5
escrever "Media=", media
escrever "\nDesvio padrao=", desvioPadrao
fim
inicio
real renda
real irpf
escrever "Informe sua renda: "
ler renda
se renda < 1372.81 entao
irpf <- 0
senao
se renda < 2743.25 entao
irpf <- (renda - 205.92)*0.15
senao
irpf <- (renda - 548.82)*0.275
fimSe
fimSe
escrever "Imposto devido: ", irpf
fim
inicio
inteiro dividendo
inteiro divisor
inteiro resto , quociente
escrever "Dividendo: "
ler dividendo
escrever "Divisor: "
ler divisor
se divisor = 0 entao
escrever "Nao pode dividir: divisor = 0 !!!"
senao
resto <- dividendo % divisor
se resto = 0 entao
quociente <- dividendo / divisor
escrever dividendo , " / " , divisor , " = " , quociente
senao
escrever "Nao pode fazer divisao inteira"
escrever " (resto = " , resto , ")"
fimse
fimse
fim
inicio
inteiro termometro , barometro , tempo
escrever "Qual a condição do termômetro: \n"
escrever "Digite 1 para baixando , 2 para estacionário e 3 para subindo. \n"
ler termometro
escrever "Informe a condição do barômetro: \n"
escrever "Digite 1 para baixando , 2 para estacionário e 3 para subindo. \n"
ler barometro
tempo <- termometro*10 + barometro
escolhe tempo
caso 11:
escrever "Chuvas abundantes e ventos de sul a sudoeste fortes"
caso 12:
escrever "Chuva Provavel , ventos de sul a sudeste"
caso 13:
escrever "Tempos Bons , ventos de sul a sudeste"
caso 21:
escrever "Frente quente com chuva provavel"
caso 22:
escrever "Tempo Incerto , ventos variaveis"
caso 23:
escrever "Tempos Bons , ventos do leste frescos"
caso 31:
escrever " Tempo instavel , aproximaçao de frente"
caso 32:
escrever "Tempo Mudando para bom , ventos de leste"
caso 33:
escrever "Tempos Bons , ventos quentes e secos"
defeito:
escrever "Utilize somente os algorismos de 1 a 3 para indicar as condiçoes do equipamentos"
fimescolhe
fim
inicio
// coeficientes do polinomio [ax^2 + bx + c = 0 ]
real a , b , c
escrever "Forneça os coeficientes da equação de 2o grau:\n"
escrever "a="
ler a
escrever "b="
ler b
escrever "c="
ler c
// equação do tipo [ bx + c = 0 ]
se a = 0 entao
escrever " não é uma equação de 2o grau !!!"
senao
// calcular o delta => interior da raiz
real delta
delta <- b ^ 2 - 4 * a * c
// não existem raizes reais de números negativos
se delta < 0 entao
escrever " não tem raizes reais"
senao
// ----------- raiz dupla ----------------
se delta = 0 entao
real x1
x1 <- -b / 2 * a
escrever "\nraiz dupla : " , x1
senao
// - ---------- duas raizes ---------------
real x1 , x2
x1 <- ( -b + raiz ( delta ) ) / 2 * a
x2 <- ( -b - raiz ( delta ) ) / 2 * a
escrever "\nraiz x1 : " , x1
escrever "\nraiz x2 : " , x2
fimse//raiz dupla
fimse// delta >0
fimse// a <> 0
fim
inicio
inteiro num, bit
inteiro base
escrever "Este algoritmo converte um número inteiro para sua representação binária.\n"
Escrever "O número deve estar entre 0 e 131071, e a representação binária\n"
escrever "terá 17 bits\n\n"
escrever "Digite o numero a ser convertido para binário: "
ler num
base <- 65536
enquanto base > 0 faz
bit <- ( num / base ) % 2
escrever bit, " "
base <- base / 2
fimenquanto
fim
inicio
inteiro n , fat
ler n
fat <- 1
enquanto n > 1 faz
fat <- fat * n
n <- n - 1
fimenquanto
escrever "Fatorial=" , fat
fim
inicio
inteiro valor , menor , contador
ler menor
contador <- 9
enquanto contador > 0 faz
ler valor
se valor < menor entao
menor <- valor
fimse
contador <- contador - 1
fimenquanto
escrever "menor valor = ", menor
fim
inicio
inteiro numero , n , resto <- 1
escrever "Forneçaa um número: "
ler numero
n <- 2
enquanto n <= numero / 2 e resto =/= 0 faz
resto <- numero % n
escrever "n=" , n , ": resto=" , resto , "\n"
n <- n + 1
fimenquanto
se resto = 0 entao
escrever "nao primo: divisivel por " , n - 1
senao
escrever "primo"
fimse
fim
// Le 5 valores e identifica os dois maiores.
inicio
inteiro valor , maior1 , maior2 , contador
ler valor
maior1 <- valor
ler valor
se valor > maior1 entao
maior2 <- maior1
maior1 <- valor
senao
maior2 <- valor
fimse
contador <- 3
enquanto contador > 0 faz
ler valor
se valor > maior1 entao
maior2 <- maior1
maior1 <- valor
senao
se valor > maior2 entao
maior2 <- valor
fimse
fimse
contador <- contador - 1
fimenquanto
escrever "maior valor = " , maior1
escrever "\nsegundo maior valor = " , maior2
fim
08/11: Linguagem C
- Vista de prova (Lógica de programação)
- Refaça a avaliação completa em linguagem C
- Utilize a IDE NetBeans.
11/11: Projeto Final da Disciplina
O jogo: Campo Minado
O Campo Minado é um jogo clássico disponível em diferentes sistemas operacionais. Basicamente devem-se procurar as minas existentes em um campo quadriculado, perdendo-se o jogo se pisar em uma mina, e vencendo se descobrir todas as minas. O jogo oferece pistas sobre a localização das minas, e usando-se um pouco de lógica podem-se encontrá-las. Uma versão desse jogo para Linux aparece na figura a seguir .
A cada jogada deve-se escolher uma casa do tabuleiro, optando-se por pisá-la (revelando-a) ou marcá-la como uma provável mina. Ao pisar numa casa, três ações podem ocorrer:
- A casa contém uma mina, o que revela todas as demais minas e encerra o jogo com derrota.
- A casa é vizinha a uma ou mais minas, e assim em seu lugar aparece o número de minas em casas vizinhas.
- Nenhuma mina existe em casas vizinhas, então a casa aparece vazia. Além disso, todas as casas vizinhas que também não possuam minas são reveladas.
Ao final do jogo, a pontuação é dada pelo tempo que se levou para se descobrirem as minas. O jogo contabiliza uma lista de melhores jogadas, contendo o nome do jogador e o tempo de jogo. Melhores jogadas são aquelas com menores tempos de jogo.
A versão do jogo a ser desenvolvida será baseada em texto (mas quem quiser fazer uma versão gráfica fique à vontade !). Basicamente deve ser apresentado o tabuleiro, mostrando-se apenas as casas já reveladas e o tempo de jogo decorrido, e um prompt pedindo as coordenadas da próxima casa assim como o tipo de ação (se pisar na casa ou marcar a provável existência de uma mina).
Etapas de desenvolvimento
- Proposta de código que contempla:
- Bibliotecas e definições
- Declaração de constantes e variáveis
- Uso de variáveis com mesmo nome e diferentes escopos
- Vetor e matriz
- Operadores lógicos e matemáticos
- Expressões
- E/S
- Estruturas de decisão e repetição
- Funções
- Passagem de parâmetro por valor e por referência
- Acesso a uma matriz através de um vetor linear (função iniciaJogo)
- Ponteiros
O laço principal do jogo ...
O jogo funciona com um laço principal, que lê as coordenadas da pŕoxima casa e a ação a ser feita, e atualiza o tabuleiro apropriadamente:
Note que nesse laço devem-se contabilizar quantas minas fora descobertas. Esse valor é necessário para decidir se o jogo já acabou.
O tabuleiro
Representar o tabuleiro: etapas X a Y.
O tabuleiro do campo minado deve ser representado em formato de texto conforme a figura abaixo. Nesta figura, o tabuleiro está completamente revelado.
As colunas são identificadas por letras maiúsculas, e as linhas por números. Cada casa do tabuleiro pode conter uma mina ou um número que conta quantas minas existem em casas vizinhas. Casas já reveladas devem mostrar essa contagem de minas vizinhas, sendo que se não houver minas a casa deve ser mostrada vazia (preenchida com espaço). Casa em que se marcou a existência de uma mina deve mostrar a letra M. Por fim, casas ainda não reveladas devem ser preenchidas com o caractere ?. Um tabuleiro parcialmente revelado apareceria como a figura abaixo.
Etapa 1: Modelando o tabuleiro
Conteúdos abordados:
Deve-se nessa etapa escolher uma forma de representar o tabuleiro dentro do programa. Devem-se pensar também em como representar as casas do campo minado:
- Como definir que uma casa possui uma mina ?
- Como definir que uma casa está vazia ? Nesse caso, como informar a quantidade de minas em casas vizinhas ?
- Como definir se uma casa já foi pisada ?
Ponto de partida para mostrar um tabuleiro na tela. O tabuleiro foi modelado como uma matriz de inteiros bidimensional.
#include <stdio.h>
int main(int argc, char** argv) {
int tabuleiro[5][5] = { {0,0,1,1,0}, {1,1,2,0,0}, {10,1,0,0,0},
{1,1,1,0,0}, {0,0,0,0,10} };
int i, j;
//i indica a linha, j a coluna
for (i=0;i<5;i++){
printf("\n");
for (j=0;j<5;j++){
printf("%d ", tabuleiro[i][j]);
}
}
return (EXIT_SUCCESS);
}
Cada casa dessa matriz contém um número inteiro. Para representar o estado de cada casa do tabuleiro sugeriu-se um código numérico:
- Casa com mina: algum número > 8
- Casa sem mina: um número que conte quantas minas existem em casas vizinhas. Tal número estará entre 0 e 8.
18/11: Montando o tabuleiro completo
Conteúdos abordados:
Desenhando o tabuleiro completo
Dando continuidade à visualização do tabuleiro, agora deve-se desenhá-lo por completo na tela.
Mostrar um tabuleiro com 10 linhas e 10 colunas, seguindo a abordagem da aula anterior.
Explorando printf para mostrar dados na tela
A função printf mostra dados na tela de acordo com um formato (daí seu nome: printf = print formatted, ou imprima formatado). O exemplo mais simples de uso do printf faz com que seja mostrada somente uma constante de texto, como a seguir:
printf("Apenas uma constante de texto ...\n");
O resultado na tela é:
Apenas uma constante de texto ...
Porém printf faz muito mais do que isso. Um segundo uso envolve mostrar dados que misturam constantes de texto e valores numéricos:
int voltas = 15;
float pi = 3.1416;
printf("Contador de voltas = %d\n", voltas);
printf("Angulo da volta atual = %f radianos\n", pi);
Na tela será mostrado o seguinte:
Contador de voltas = 15
Angulo da volta atual = 3.1416 radianos
Esse segundo exemplo mostra como especificar o formato do que deve aparecer na tela. O formato é o primeiro argumento da função printf, e ele contém uma especificação do texto que deve aparecer na tela. Nesse texto podem-se indicar valores a serem substituídos (eles aparecem prefixados com %), os quais devem ser fornecidos nos demais argumentos da função. No primeiro printf do exemplo acima, o formato é:
"Contador de voltas = %d\n"
Nesse texto, toda sequência de caracteres que iniciar com % indica que ali deve-se substituir por um valor. Dependendo da letra que vier depois de %, o tipo de valor será int (inteiro), float (real), double (real com mais casas), char (caractere), string (texto). A tabela abaixo exemplifica os diferentes tipos de valores que podem ser especificados no formato da função printf:
Tipo de dados
Formato
Exemplo
O que aparece na tela
int
%d
int horas=2;
printf("Já se passaram %d horas ...\n", horas);
Já se passaram 2 horas ...
char
%c
char letra = 'S';
printf("Você digitou a letra %c !\n", letra);
Você digitou a letra S !
float
%f
float media = 4.5;
printf("Média calculada=%f\n", media);
Média calculada=4.5
double
%g
double angulo = 0.1122333;
printf("Angulo=%g\n", angulo);
Angulo=0.111222333
char * (string)
%s
char * nome = "Filomena";
printf("Cara sra. %s ...", nome);
Cara sra. Filomena ...
Para substituir mais de um valor, basta especificar no formato e fornecer os valores nos demais argumentos:
int hora = 10, minuto = 5, segundo = 0;
printf("Horario: %d:%d:%d\n", hora, minuto, segundo);
... o que faz aparecer na tela:
Horario: 10:5:0
Esse último exemplo poderia ser melhorado, pois o horário ficou esquisito de ler ... normalmente costumamos ver horas, minutos e segundos com dois algarismos, como a seguir:
Horario: 10:05:00
É possível fazer com que printf faça isso automaticamente, bastando especificar o seguinte no formato:
int hora = 10, minuto = 5, segundo = 0;
printf("Horario: %02d:%02d:%02d\n", hora, minuto, segundo);
Note que ao invés de %d se especificou %02d. Esse formato faz com que se mostre um número inteiro com no mínimo dois algarismos. Caso o número tenha somente um algarismo, printf automaticamente adiciona um 0 à esquerda. Isso funciona somente para formatos numéricos.
Além de acrescentar zeros à esquerda de valores numéricos, é possível tabular os valores mostrados de forma que ocupem uma certa quantidade de colunas. Por exemplo, caso se deseje mostrar o seguinte:
Nome Idade Sexo
Marcelo 39 M
Marina 9 F
Luis 11 M
... pode-se fazer assim:
printf("%-12s %-12s %s\n", "Nome", "Idade", "Sexo");
printf("%-12s %-12d %c\n", "Marcelo", 39, 'M');
printf("%-12s %-12d %c\n", "Marina", 9, 'F');
printf("%-12s %-12d %c\n", "Luis", 11, 'M');
Note que desta vez adicionou-se após % a sequência -12. Isso indica que o valor a ser mostrado deve ocupar no mínimo 12 posições, preenchendo-se com espaços caso necessário. Veja que os valores foram alinhados à esquerda. Caso se deseje que sejam alinhados à direita, basta fazer assim:
printf("%12s %12s %s\n", "Nome", "Idade", "Sexo");
printf("%12s %12d %c\n", "Marcelo", 39, 'M');
printf("%12s %12d %c\n", "Marina", 9, 'F');
printf("%12s %12d %c\n", "Luis", 11, 'M');
... e assim aparecerá o seguinte na tela:
Nome Idade Sexo
Marcelo 39 M
Marina 9 F
Luis 11 M
Colocando as minas
No tabuleiro devem ser colocadas 10 minas aleatoriamente. Isso significa que para cada uma dessas minas, devem-se gerar aleatoriamente suas coordenadas no tabuleiro. A geração de números aleatórios pode ser feita usando-se a função random(). Essa função gera um número inteiro entre 0 e 2147483647. Para usá-la no tabuleiro, pode-se fazer o seguinte:
#include <stdlib.h>
int main() {
int x, y;
// gera dois números aleatórios entre 0 e 9, e guarda-os nas variáveis x e y
x = random() % 10;
y = random() % 10;
}
Mais sobre a função random()
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
int main() {
int x,y,z;
time_t t;
// Lê o valor do relógio
t = time(NULL);
// Usa o valor do relógio como semente do gerador de números
// pseudo-aleatórios.
srandom(t);
// Sorteia três números pseudo-aleatórios
x = random() % 10;
y = random() % 10;
z = random() % 10;
printf("x=%d, y=%d, z=%d\n", x, y, z);
}
A versão atual do jogo está assim:
#include <stdio.h>
#include <stdlib.h>
#define MINAS 10
#define LINHAS 10
#define COLUNAS 10
#define TEM_MINA 10
/*
*
*/
int main(int argc, char** argv) {
int tabuleiro[LINHAS][COLUNAS];
int i, j;
// Zerar todas as posições do tabuleiro !
i = 0;
while ( i < LINHAS) {
j = 0;
while (j < COLUNAS) {
tabuleiro[i][j] = 0;
j++;
}
i++;
}
// Colocar as minas aqui !!!
//Agora mostrar o tabuleiro que foi gerado
//i indica a linha, j a coluna
i = 0;
while (i < LINHAS) {
// O while abaixo mostra todas as colunas da linha "i"
j = 0;
while (j < COLUNAS) {
if (tabuleiro[i][j] == TEM_MINA) {
printf("* ");
} else {
if (tabuleiro[i][j] == 0) {
printf(" ");
} else {
if ((tabuleiro[i][j] >= 1) && (tabuleiro[i][j] <= 8)) {
printf("%d ", tabuleiro[i][j]);
}
}
}
j++;
}
printf("\n");
i++;
}
return (EXIT_SUCCESS);
}
Meta desta semana
Nesta semana o seu programa deve ser capaz de:
- Representar o tabuleiro com uma matriz de inteiros bidimensional.
- Mostrar o tabuleiro na tela, indicando o que existe em cada casa. O tabuleiro deve ser apresentado enfeitado, o que significa que deve mostrar uma grade para separar as casas e a identificação de linhas e colunas. Linhas devem ser identificadas numericamente, e colunas devem ser identificadas por letras (ex: primeira coluna=A, segunda coluna=B, ...).
- Colocar minas aleatoriamente no tabuleiro.
O seu programa cumprindo as metas acima deve ser apresentado ao professor na próxima aula (22/11), já sendo parte da avaliação desta unidade.
Funções
- Material de aula Prof. Marcelo funções
- Texto introdutório sobre funções na linguagem C
Escopo de variáveis
- Texto obtido de: Uso de funções em C
Por escopo de uma variável entende-se o bloco de código onde esta variável é válida. Com base nisto, temos as seguintes afirmações:
- As variáveis valem no bloco que são definidas;
- As variáveis definidas dentro de uma função recebem o nome de variáveis locais
- As variáveis declaradas fora de qualquer função são chamadas de variáveis globais
- Os parâmetros formais de uma função (também conhecidos como argumentos da função) valem também somente dentro da função;
- Uma variável definida dentro de uma função não é acessível em outras funções, MESMO QUE ESSAS VARIÁVEIS TENHAM NOMES IDÊNTICOS.
Variáveis locais
No trecho de código a seguir tem-se um exemplo com funções e variáveis com nomes iguais.
#include <stdio.h>
void FUNC1() {
int B;
B = -100;
printf("Valor de B dentro da função FUNC1: %d\n", B);
}
void FUNC2() {
int B;
B = -200;
printf("Valor de B dentro da função FUNC2: %d\n", B);
}
void main() {
int B;
B = 10;
printf("Valor de B: %d\n", B);
B = 20;
FUNC1();
printf("Valor de B: %d\n", B);
B = 30;
FUNC2();
printf("Valor de B: %d\n", B);
}
O resultado de sua execução deve ser:
Valor de B: 10
Valor de B dentro da função FUNC1: -100
Valor de B: 20
Valor de B dentro da função FUNC2: -200
Valor de B: 30
Variáveis globais
O seguinte exemplo mostra o mesmo programa, porém fazendo com que a variável B seja global:
#include <stdio.h>
// Declaração da variável global B
int B;
void FUNC1() {
B = -100;
printf("Valor de B dentro da função FUNC1: %d\n", B);
}
void FUNC2() {
B = -200;
printf("Valor de B dentro da função FUNC2: %d\n", B);
}
void main() {
B = 10;
printf("Valor de B: %d\n", B);
B = 20;
FUNC1();
printf("Valor de B: %d\n", B);
B = 30;
FUNC2();
printf("Valor de B: %d\n", B);
}
O resultado de sua execução deve ser:
Valor de B: 10
Valor de B dentro da função FUNC1: -100
Valor de B: -100
Valor de B dentro da função FUNC2: -200
Valor de B: -200
E se existir um variável local com mesmo nome que uma global ? nesse caso, a variável local vai esconder a sua homônima global:
#include <stdio.h>
// Declaração da variável global B
int B;
void FUNC1() {
// no escopo desta função, esta variável local vai esconder a variável global B!
int B;
B = -100;
printf("Valor de B dentro da função FUNC1: %d\n", B);
}
void FUNC2() {
B = -200;
printf("Valor de B dentro da função FUNC2: %d\n", B);
}
void main() {
B = 10;
printf("Valor de B: %d\n", B);
B = 20;
FUNC1();
printf("Valor de B: %d\n", B);
B = 30;
FUNC2();
printf("Valor de B: %d\n", B);
}
O resultado de sua execução deve ser:
Valor de B: 10
Valor de B dentro da função FUNC1: -100
Valor de B: 20
Valor de B dentro da função FUNC2: -200
Valor de B: -200
Para fixar
- Escreva o programa para mostrar a tabuada de um número lido do teclado.
#include <stdlib.h>
#include <stdio.h>
/*
*
*/
int main(int argc, char** argv) {
int numero, c;
printf("Numero: ");
scanf("%d", &numero);
c = 1;
while (c < 11) {
printf("%d X %d = %d\n", numero, c, numero*c);
c++;
}
return (EXIT_SUCCESS);
}
- Reescreva o programa anterior, mas usando uma função para mostrar a tabuada.
#include <stdio.h>
int tabuada(int num) {
int c = 1;
while (c < 11) {
printf("%d X %d = %d\n", num, c, num*c);
c++;
}
}
int main(int argc, char** argv) {
int numero, c;
printf("Numero: ");
scanf("%d", &numero);
tabuada(numero);
return (EXIT_SUCCESS);
}
- Modifique o programa anterior para mostrar a tabuada de todos os números entre 1 e 10. Obs: não modifique a função tabuada!
- Escreva um programa para ler 10 números do teclado, e em seguida mostrar o maior e o menor número.
- Reescreva o programa anterior, mas criando as função "maior" e "menor", que retornam o maior e menor número de um vetor de tamanho arbitrário.
22/11: Campo Minado
Para referência: apostila online sobre linguagem C.
- Tópico sobre linguagem C: continuando funções
- ... mais especificamente: passagem de parâmetros por valor e por referência
Escondendo as casas não pisadas
No momento você deve já conseguir mostrar todo o tabuleiro, porém no jogo apenas as casas já pisadas devem ser reveladas. Pense em como modelar o seu tabuleiro de forma a esconder as casas ainda não pisadas.
Retomando o laço principal do jogo ...
O jogo funciona com um laço principal, que lê as coordenadas da casa a ser pisada ou marcada e atualiza o tabuleiro apropriadamente:
Note que nesse laço devem-se contabilizar quantas minas foram realmente descobertas - o que não corresponde necessariamente a quantas minas foram marcadas ... A quantidade de minas descobertas é necessária para decidir se o jogo já acabou.
25/11: Campo Minado
Ponteiros em linguagem C
Ponteiros é uma característica poderosa oferecida pela linguagem C. A linguagem de programação C depende muito dos ponteiros, assim, um bom programador em C precisa dominar bem ponteiros.
Ponteiro é visto pela maior parte dos programadores iniciantes como uma das partes mais difíceis na linguagem C, pois o conceito de ponteiros pode ser novo ou um mesmo símbolo usado para certa finalidade e usado para outra diferente, tornando mais difícil o entendimento.
Entendendo o que é um ponteiro
Um ponteiro é uma variável que guarda um endereço de memória de outra variável. Os ponteiros da linguagem C proporcionam uma forma fácil de acesso ao valor de variáveis sem referenciá-las diretamente. Um ponteiro possui tipo, por exemplo, inteiros, ponto flutuante e caracteres. O tipo do ponteiro indica que tipo é a variável para qual ele aponta.
Um ponteiro é declarado a seguinte forma:
tipo_do_ponteiro *nome_do_ponteiro
Exemplo:
int *p, *a;
char *pt, *ponteiro;
No exemplo acima foram criados quatro ponteiros, dois de tipo inteiro e dois de tipo caractere. É importante não confundir o asterisco (*), que indica que a variável é um ponteiro, com o mesmo sinal indicando uma multiplicação.
Conhecendo os operadores
Sempre é importante iniciar o ponteiro. Um ponteiro sempre é iniciado com o local na memória onde se localiza o valor da variável. Para iniciar a variável desejada como o endereço de memória, segue o exemplo:
int variavel_apontada=2;
int *ponteiro;
ponteiro=&variavel_apontada;
No exemplo foi criada uma variável e iniciada com valor 2, foi criado também um ponteiro que logo abaixo foi iniciado com o endereço da variável chamada variável_apontada.
A linguagem de programação C oferece dois operadores unitários, o operador de endereço (&) e o operador indireto (*). O operador de endereço retorna o endereço de memória onde fica localizado a variável, como foi mostrado no exemplo acima. O operador indireto retorna o valor da variável para qual o ponteiro aponta. Por exemplo:
main() {
int var, *p;
var=10;
p=&var;
printf("O valor da variavel eh: %d \n", *p);
printf("O endereco de memoria da variavel eh: %p \n", p);
printf("O endereco de memoria do ponteiro eh: %p \n", &p);
*p=15;
printf("O novo valor da variavel e': %d \n", var);
return (0);
}
A saída será:
O valor da variavel eh: 10
O endereco de memoria da variavel eh: 00AE4F6
O endereco de memoria do ponteiro eh: 00AE4F8
O novo valor da variavel eh: 15
No exemplo, usam-se os operadores para imprimir e aterá o valor da variável. Onde o endereço de memória varia de cada computador.
O ponteiro é usado em situações em que a passagem de valores é complicada, por isso é muito importante seu aprendizado. O conceito de ponteiro e seu uso podem, aparentemente, ser complicado, porém, não é muito difícil. O uso indevido e insensato de ponteiros pode causar sérios bugs em um programa e até comprometer todo o sistema, assim, é necessário cuidado quando se usa eles.
Outro exemplo
Considere a declaração do ponteiro abaixo:
int *pa
A instrução acima indica que pa é um ponteiro do tipo int. Agora veremos como atribuir valor ao ponteiro declarado. Para isto é necessário saber que existem dois operadores unitários que são utilizados com os ponteiros. O primeiro é o operador (*) através dele é possível retornar o valor da variável que está localizada no ponteiro. E o segundo é o operador (&) que retorna o endereço de memória que está localizado o valor da variável contida no ponteiro. Portanto para atribuirmos um valor para o ponteiro é necessário referencia o valor da variável que se encontra no ponteiro utilizando o operador (*), como será demonstrado a seguir.
*pa=25
Desta forma estamos atribuindo o valor 24 para a variável que está contida no ponteiro. Para entender melhor quando e como utilizar os operadores (*) e (&), veja o programa mostrado abaixo.
#include<stdio.h>
int main (){
int a, b;
int *pa, *pb; //declaração de ponteiros
/*inicializando variáveis*/
a=25;
b=12;
/*fazendo os ponteiros pa e pb apontarem para os endereços de
memórias das bariáves a e b, respectivamente*/
pa=&a;
pb=&b;
/*Imprimindo os dados na tela*/
printf("\n O endereco do ponteiro pa: %d", pa);
printf("\n O endereco da variavel contida no ponteiro pa: %d", &pa);
printf("\n O valor da variavel contida no ponteiro pa: %d", *pa);
printf("\n\n");
printf("\n O endereco do ponteiro pb: %d", pb);
printf("\n O endereco da variavel contida no ponteiro pb: %d", &pb);
printf("\n O valor da variavel contida no ponteiro pb: %d\n", *pb);
}
Quando os ponteiros são declarados, eles são inicializados com um endereço não valido, portanto antes de usa-los é necessário atribuir um endereço e isso é feito através do operador (&) como demonstra a instrução pa=&a e pb=&b que atribui aos ponteiros pa e pb o endereço das varieis a e b.
Uma outra novidade do programa anterior é quando queremos imprimir o endereço do próprio ponteiro isto é feito referenciando pa normalmente. Porém para imprimir o endereço contido no ponteiro é usado &pa e por ultimo para imprimir o valor do endereço contido no ponteiro usamos *pa.
Através do programa abaixo é possível verificar que se pode fazer comparações entre ponteiros.
#include<stdio.h>
int main (){
int x1=34, x2=78;
int *px1, *px2;
/*Iniciando os ponteiros com os endereços das variáveis
x1 e x2*/
px1=&x1;
px2=&x2;
printf("\n px1= %d", px1);
printf("\n px2= %d", px2);
if(px1 > px2){
printf("\n\n px1-px2=%d\n", px1-px2);
}else{
printf("\n\n px2-px1=%d\n", px2-px1);
}
}
A comparação entre ponteiros em uma expressão relacional (>=,<=,> e <) é possível quando os dois ponteiros são do mesmo tipo. Isso é feito no programa mostrado através da linha “if (px1>px2)”, Caso a instrução seja verdadeira será feita a diferença entre os dois ponteiros “px1-px2”. E caso seja falso será feito ao contrario “px2-px1”. É importante dizer que os dados de saída deste programa não são iguais em todos os computadores, depende muito da memória disponível. Mas como pode-se observar em nosso exemplo, se px1=1245064 e px2=1245060 então px1-px2 será igual a um. Isso ocorre, pois a diferença depende da unidade tipo apontado.
29/11: Campo Minado
A contagem de minas
Para ajudar a visualizar o algoritmo de contagem de minas vizinhas, segue o fluxograma abaixo. As coordenadas (x,y) correspondem à casa cujas minas vizinhas se desejam contar. Veja sua semelhança com o algoritmo para zerar o tabuleiro.
A sugestão é por o algoritmo de contagem em uma função, e dentro do programa chamá-lo para cada casa do tabuleiro:
#include <stdio.h>
#include <stdlib.h>
#define MINAS 10
#define LINHAS 10
#define COLUNAS 10
#define TEM_MINA 10
// O tabuleiro como variável global: necessário para poder ser usado e modificado por outras funções
int tabuleiro[LINHAS][COLUNAS];
// Função para contar as minas vizinhas da casa x, y
void conta(int x, int y) {
}
/*
*
*/
int main(int argc, char** argv) {
int i, j;
// Zerar todas as posições do tabuleiro !
i = 0;
while ( i < LINHAS) {
j = 0;
while (j < COLUNAS) {
tabuleiro[i][j] = 0;
j++;
}
i++;
}
// Colocar as minas aqui !!!
// contar as minas vizinhas de cada casa do tabuleiro
i = 0;
while ( i < LINHAS) {
j = 0;
while (j < COLUNAS) {
// chama a função de contagem de minas, para contar as minas
// vizinhas da casa com coordenadas i,j
conta(i, j);
j++;
}
i++;
}
//Agora mostrar o tabuleiro que foi gerado
Obs: cuidado com o seguinte ao fazer o algoritmo de contagem de minas:
- Casas na borda do tabuleiro possuem menos casas vizinhas (casas fora do tabuleiro devem ser ignoradas).
- O algoritmo não pode ser aplicado em casas que contêm minas. Quer dizer, não faz sentido calcular as minas vizinhas de uma casa que tem uma mina.
Levando em conta as restrições acima, o algoritmo deve ficar parecido com o seguinte:
- Desenvolvimento do projeto
- Arquivos em linguagem C
- Armazenar pontuação dos jogadores em arquivo modo texto
02/12: Campo Minado
- Desenvolvimento do projeto
- O código abaixo faz uso da biblioteca <time.h>, necessário para cálculo do tempo transcorrido pelo jogador
#include <stdio.h>
#include <time.h>
#include <string.h>
void calcula(){ //função calcula tempo transcorrido para executar uma operação.
time_t inicio, fim;
char nome[51];
inicio= time(NULL);
printf("Digite seu nome: ");
scanf("%s",nome);
//fgets(nome, 51, stdin);
fim= time(NULL);
printf("%s, voce demorou %.2f segundos para digitar seu nome.\n", nome, difftime(inicio,fim)*(-1));
}
void tempo()
{
time_t segundos, inicio;
inicio = time(NULL); //captura tempo nesse instante
printf("O valor lido neste instante eh %ld \n", inicio);
segundos= time(NULL); //captura e apresenta o tempo em segundos
printf("%ld horas desde 1 de Janeiro de 1970.\n", segundos/3600);
}
int main() {
tempo();
calcula();
return 0;
}
06/12: Campo Minado
- Desenvolvimento do projeto
Expansões propostas para o projeto
- Cada jogo implementado deve apresentar ao menos uma das espansões propostas abaixo:
- Ao término do jogo, com a descoberta de todas as minas pelo jogador, o programa desenvolvido deve informar o tempo de jogo transcorrido.
- Ao término do jogo, o programa deve armazenar o nome do jogador juntamente com o tempo de jogo em um arquivo.
- Antes do início do jogo, na fase de inicialização deve-se solicitar ao jogador o grau de dificuldade do jogo. O grau de dificuldade do jogo refere-se a quantidade de bombas no tabuleiro. Sugere-se três níveis possíveis:
- 1) Iniciante, 2) Intermediário, 3) Avançado.
Exemplo de utilização de funções no programa
#include<stdio.h>
//define as dimensões da matriz
#define LIN 10
#define COL 10
//declaração das funções do programa
void inicia_tabela(int tab[LIN][COL]);
void imprime_tabela(int tab[LIN][COL]);
//função que inicia a tabela com zeros
void inicia_tabela(int tab[LIN][COL]){
int i=0,j=0;
for(i=0; i<LIN; i++){
for (j=0; j<COL;j++){
tab[i][j]=0;
}
}
}
//função para impressão da tabela
void imprime_tabela(int tab[LIN][COL]){
int i=0,j=0;
for(i=0; i<LIN; i++){
printf("\n");
for (j=0; j<COL;j++){
printf("| %d ", tab[i][j]);
}
}
printf("\n \n");
}
//função principal
int main (){
int tabela[10][10];
inicia_tabela(tabela);
imprime_tabela(tabela);
}
- O código acima apresenta o uso de funções para atividades básicas como zerar a matriz e apresentar o tabuleiro.
- A passagem de parâmetro da matriz é sempre realizada por referencia.
- Não é possível utilizar tamanhos variáveis (informada pelo usuário), pois a matriz deve conter ao menos as dimensões das colunas na passagem dos parâmetro na função (delimitado aqui pelas constantes LIN e COL). No projeto pode-se adotar uma solução desse tipo =)
09/12: Campo Minado
Arquivos na linguagem C
Para um programador, arquivos são repositórios permanentes de dados, os quais usualmente ficam em midia não volátil (disco rígido, CD ou DVD, pendrive, e outros). Arquivos servem para guardar informações que devem continuar a existir mesmo que termine o processo que as criou. Um exemplo é a agenda, cujo conteúdo deve ser preservado para futuras consultas e modificações. Mas além de serem depósitos de dados, arquivos possuem características bem definidas do ponto de vista de programação.
Um arquivo é uma sequência de bytes, que pode ser acessada, lida e modificada por meio de funções específicas existentes na biblioteca padrão da linguagem C. Essas funções servem para abrir e fechar um arquivo, ler e escrever uma certa quantidade de bytes, e mudar a posição da próxima leitura ou escrita.
Escrevendo em um arquivo
Abaixo segue um exemplo de um programa para escrever uma linha em um arquivo:
#include<stdio.h>
int main() {
char linha[256];
FILE * arquivo;
printf("Digite uma linha: ");
scanf("%[^\n]", linha);
printf("Vou gravar isto no arquivo teste.txt\n");
arquivo = fopen("teste.txt", "w");
if (arquivo == NULL) {
perror("Nao conseguiu abrir o arquivo");
return 1;
}
fprintf(arquivo, "%s\n", linha);
fclose(arquivo);
printf("Pronto ... veja o arquivo teste.txt !\n");
}
Esse pequeno programa evidencia que trabalhar com arquivos é muito parecido a trabalhar com escrita na tela e leitura do teclado. Mas primeiro deve-se focar nas linhas do programa que têm relação direta com arquivos. Para começar, um arquivo é referenciado por uma variável do tipo FILE *:
FILE * arquivo;
Em seguida, o arquivo a ser lido ou escrito deve ser aberto, usando-se a função FILE * fopen(char * nome_arquivo, char * modo):
arquivo = fopen("teste.txt", "w");
Como se pode ver, a função fopen precisa de dois parâmetros do tipo char * (quer dizer, dois parâmetros string). O primeiro é o caminho do arquivo a ser aberto, e o segundo é o modo de abertura (o que se pretende fazer com ele: ler, escrever, adicionar dados ao final, ler e escrever). No exemplo acima, vai-se abrir o arquivo teste.txt para escrita (modo "w", de write). O valor de retorno de fopen é do tipo FILE *, e corresponde a uma descrição do arquivo que foi aberto. Caso aconteça algum erro (ex: não há permissão para criar o arquivo), fopen retorna o valor NULL. O exemplo testa se isto acontece da seguinte forma:
if (arquivo == NULL) {
perror("Nao conseguiu abrir o arquivo");
return 1;
}
Uma vez o arquivo estando aberto para escrita, pode-se escrever nele usando-se a função fprintf. Essa função é idêntica à função printf que se usa para escrever na tela. Porém fprintf precisa de um parâmetro adicional, deve ser a variável que corresponde ao arquivo aberto (primeiro parâmetro da função):
fprintf(arquivo, "%s\n", linha);
Finalmente, quando não se quer mais escrever no arquivo deve-se chamar a função fclose para fechá-lo:
fclose(arquivo);
Lendo uma linha de um arquivo
A leitura de um arquivo é parecida, com algumas pequenas modificações em sua abertura (deve-se indicar que o mode de operação será "r", de "read"), e usando-se a função fscanf para ler dados do arquivo. O exemplo abaixo mostra um programa para ler a primeira linha de um arquivo:
#include<stdio.h>
int main() {
char linha[1024];
char nome[256];
FILE * arquivo;
printf("Digite o nome de um arquivo: ");
scanf("%s", nome);
printf("Vou mostrar a primeira linha do arquivo %s\n", nome);
arquivo = fopen(nome, "r");
if (arquivo == NULL) {
perror("Ops ... erro ao acessar esse arquivo: ");
return 1;
}
fgets(linha, 1024, arquivo);
fclose(arquivo);
printf("Eis a primeira linha do arquivo: \n\n%s\n\n", linha);
}
Como adiantado, na abertura com fopen deve-se usar o valor "r" para o modo:
arquivo = fopen(nome, "r");
Já a leitura de uma linha pode ser feita mais facilmente com a função fgets:
fgets(linha, 1024, arquivo);
A função char * fgets(char * resultado, int max_caracteres, FILE * arquivo) lê uma linha de um arquivo com até max_caracteres e a guarda na variável passada no parâmetro resultado. No exemplo acima, fgets lê uma linha com até 1024 caracteres e a guarda na variável linha.
Lendo todas as linhas de um arquivo
Nesse próximo exemplo, abre-se um arquivo para leitura e lêem-se todas suas linhas, mostrando-as na tela:
#include<stdio.h>
int main() {
char linha[1024];
char nome[256];
char * ok;
FILE * arquivo;
printf("Digite o nome de um arquivo: ");
scanf("%s", nome);
printf("\nVou mostrar todas as linhas do arquivo %s\n\n", nome);
arquivo = fopen(nome, "r");
if (arquivo == NULL) {
perror("Ops ... erro ao acessar esse arquivo: ");
return 1;
}
do {
ok = fgets(linha, 1024, arquivo);
if (ok != NULL) printf("%s", linha);
} while (! feof(arquivo));
fclose(arquivo);
}
A diferença em relação ao exemplo anterior está na sequência que lê as linhas do arquivo:
do {
ok = fgets(linha, 1024, arquivo); // Lê a próxima linha do arquivo
if (ok != NULL) printf("%s", linha); // se conseguiu ler algo, mostra na tela
} while (! feof(arquivo)); // para se chegou ao fim de arquivo
Há algumas novidades aqui:
- O valor de retorno de fgets é testado quanto a sua validade: a função fgets retorna o valor NULL se não conseguiu ler algo do arquivo. Isto pode ter ocorrido por um erro de leitura (ex: disco com defeito) ou porque se chegou ao fim do arquivo, e assim nada mais existe para ser lido. Esse teste aparece na linha:
if (ok != NULL) printf("%s", linha)
.
- A leitura continua enquanto não se chegar ao fim de arquivo: o teste de fim de arquivo se faz com a função int feof(FILE * arquivo), que retorna 0 se ainda não se chegou ao final do arquivo, ou 1 caso contrário. A chamada de feof se faz ao final do laço:
} while (! feof(arquivo));
- Desenvolvimento do projeto final da disciplina
- Preparação para apresentação
13/12: Entrega projeto da disciplina
- Entrega do projeto final da disciplina
ATENÇÃO
- Avaliação realizada individualmente
- Entrega de avaliações e conceitos.
Conceitos Projeto Final disciplina
- Conceitos projeto final disciplina: conceitos projeto
- Critério: código clonado, soluções apresentadas sem explicação ou integração entre os membros considerou-se conceito insuficiente.
16/12: Recuperação Lógica e Programação em linguagem C
- Recuperação Lógica de Programação em Linguagem C
- Recuperação realizada utilizando linguagem C
20/12: Encerramento disciplina
- Aproveito para desejar à todos Feliz Natal e que 2011 seja repleto de boas surpresas =)
Conceitos Finais:
- Conceitos finais da disciplina: Conceitos Finais
- Encerramento disciplina
- Discussões sobre os tipos de linguagens de programação utilizadas atualmente no mercado e tendências
- Popularidade das linguagens de programação