Mudanças entre as edições de "Programação para Redes de Computadores (técnico) (diário 2012-2)"
(30 revisões intermediárias por 2 usuários não estão sendo mostradas) | |||
Linha 1: | Linha 1: | ||
Endereço encurtado: http://bit.ly/prc20122 | Endereço encurtado: http://bit.ly/prc20122 | ||
__TOC__ | __TOC__ | ||
− | = | + | =Avaliações= |
São 4 avaliações, uma por mês - sem data pré-estabelecida: | São 4 avaliações, uma por mês - sem data pré-estabelecida: | ||
− | |||
* Novembro | * Novembro | ||
− | * Dezembro | + | * [[Programação para Redes de Computadores (técnico) (diário 2012-2) - prova 2|Dezembro]] |
+ | * [[Programação para Redes de Computadores (técnico) (diário 2012-2) - prova 3|Fevereiro]] | ||
* Março | * Março | ||
− | O conceito final da disciplina é elaborado da seguinte forma: | + | O [https://docs.google.com/spreadsheet/ccc?key=0AvKQkavuEKVtdE53Ulh3T2NoUE5TX183Ul9aT0JDT0E conceito final] da disciplina é elaborado da seguinte forma: |
* '''A''': todas as avaliações em '''A'''. | * '''A''': todas as avaliações em '''A'''. | ||
* '''B''': no máximo 1 '''C'''. | * '''B''': no máximo 1 '''C'''. | ||
Linha 201: | Linha 201: | ||
fim | fim | ||
</syntaxhighlight> | </syntaxhighlight> | ||
+ | |||
+ | ==22/10== | ||
+ | Como "descobrir" que número o usuário digitou? Usando árvore! | ||
+ | <syntaxhighlight lang=c> | ||
+ | inicio | ||
+ | |||
+ | // Entrada de dados | ||
+ | inteiro numero | ||
+ | texto resultado | ||
+ | |||
+ | escrever "Por favor, digite um número inteiro entre 0 e 7: " | ||
+ | ler numero | ||
+ | |||
+ | // Processamento | ||
+ | se numero > 3.5 então | ||
+ | se numero > 5.5 então | ||
+ | se numero > 6.5 então | ||
+ | resultado <- "7" | ||
+ | senão | ||
+ | resultado <- "6" | ||
+ | fimSe | ||
+ | senão | ||
+ | se numero > 4.5 então | ||
+ | resultado <- "5" | ||
+ | senão | ||
+ | resultado <- "4" | ||
+ | fimSe | ||
+ | fimSe | ||
+ | senão | ||
+ | se numero > 1.5 então | ||
+ | se numero > 2.5 então | ||
+ | resultado <- "3" | ||
+ | senão | ||
+ | resultado <- "2" | ||
+ | fimSe | ||
+ | senão | ||
+ | se numero > 0.5 então | ||
+ | resultado <- "1" | ||
+ | senão | ||
+ | resultado <- "0" | ||
+ | fimSe | ||
+ | fimSe | ||
+ | fimSe | ||
+ | |||
+ | // Saída de dados | ||
+ | escrever "O número é ", resultado , "." | ||
+ | fim | ||
+ | </syntaxhighlight> | ||
+ | ... ou caso a caso (meio óbvio, mas estamos ainda no terceiro dia de aula, ok? :): | ||
+ | <syntaxhighlight lang=c> | ||
+ | inicio | ||
+ | |||
+ | // Entrada de dados | ||
+ | inteiro numero | ||
+ | texto resultado | ||
+ | |||
+ | escrever "Por favor, digite um número inteiro entre 0 e 7: " | ||
+ | ler numero | ||
+ | |||
+ | // Processamento | ||
+ | escolhe numero | ||
+ | caso 9: | ||
+ | resultado <- "9" | ||
+ | caso 8: | ||
+ | resultado <- "8" | ||
+ | caso 7: | ||
+ | resultado <- "8" | ||
+ | caso 6: | ||
+ | resultado <- "6" | ||
+ | caso 5: | ||
+ | resultado <- "5" | ||
+ | caso 4: | ||
+ | resultado <- "4" | ||
+ | caso 3: | ||
+ | resultado <- "3" | ||
+ | caso 2: | ||
+ | resultado <- "2" | ||
+ | caso 1: | ||
+ | resultado <- "1" | ||
+ | defeito: | ||
+ | resultado <- "0" | ||
+ | fimEscolhe | ||
+ | |||
+ | // Saída de dados | ||
+ | escrever "O número é ", resultado , "." | ||
+ | fim | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ==29/10== | ||
+ | [[#08/10|Lembra como descobrir se um número é primo]]? Outra forma: | ||
+ | <syntaxhighlight lang=c> | ||
+ | inicio | ||
+ | |||
+ | inteiro dividendo | ||
+ | escrever "Por favor, digite um número inteiro: " | ||
+ | ler dividendo | ||
+ | |||
+ | inteiro divisores, divisor | ||
+ | real resto | ||
+ | divisores <- 0 | ||
+ | para divisor de 2 até (dividendo -1) passo 1 | ||
+ | resto <- dividendo % divisor | ||
+ | se resto = 0 então | ||
+ | divisores <- divisores + 1 | ||
+ | escrever "(",divisor,")" | ||
+ | senão | ||
+ | escrever "." | ||
+ | fimSe | ||
+ | próximo | ||
+ | |||
+ | escrever "\nO número ", dividendo, " possui ", divisores, " divisores." | ||
+ | fim | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ==05/11== | ||
+ | O [[#29/10|mesmo programa do número primo]], agora em Bash: | ||
+ | <syntaxhighlight lang=bash> | ||
+ | #!/bin/bash | ||
+ | |||
+ | # Limpa a tela. | ||
+ | clear | ||
+ | |||
+ | # Entrada de dados: pede ao usuário um número inteiro. | ||
+ | echo -n "Por favor, digite um número inteiro: " | ||
+ | read dividendo | ||
+ | |||
+ | # Assume, inicialmente, que o número é primo. | ||
+ | divisores="0" | ||
+ | |||
+ | # Agora, para todos os números compreendidos entre 2 e (número -1) | ||
+ | # é feita a divisão. Se o resto for zero, o número tem divisor e, | ||
+ | # portanto, não é primo. | ||
+ | for divisor in $(seq 2 $(expr ${dividendo} - 1)) | ||
+ | do | ||
+ | # Calcula o resto da divisão. | ||
+ | resto=$(echo "${dividendo} % ${divisor}" | bc) | ||
+ | # Verifica se o resto é zero. | ||
+ | if [ "${resto}" = "0" ] | ||
+ | then | ||
+ | # Se for zero, mostra o divisor entre parênteses. | ||
+ | echo -n "(${divisor})" | ||
+ | divisores=$(expr ${divisores} + ${divisor}) | ||
+ | else | ||
+ | # Senão, mostra apenas um ponto na tela. | ||
+ | echo -n "." | ||
+ | fi | ||
+ | done | ||
+ | # Apenas formata com uma linha a mais. | ||
+ | echo "" | ||
+ | |||
+ | # Verifica o resultado dos divisores. | ||
+ | if [ "${divisores}" -gt "0" ] | ||
+ | then | ||
+ | # Se há pelo menos um divisor, não é primo. | ||
+ | echo "O número não é primo." | ||
+ | else | ||
+ | # Senão, mantém-se como primo. | ||
+ | echo "O número é primo." | ||
+ | fi | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ==12/11== | ||
+ | Uma outra forma de resolver a questão 3 da primeira prova: | ||
+ | <syntaxhighlight lang=bash> | ||
+ | #!/bin/bash | ||
+ | |||
+ | # Entrada de dados | ||
+ | # Argumento 1: idade da mãe | ||
+ | # Argumento 2: idade do filho mais velho | ||
+ | |||
+ | # Processamento | ||
+ | idadeFilhoDoMeio=$(echo "${2} / 2" | bc) | ||
+ | idadeFilhoMaisNovo=$(echo "${idadeFilhoDoMeio} - 3" | bc) | ||
+ | idadeMaeFilhoMaisVelho=$(echo "${1} - ${2}" | bc) | ||
+ | idadeMaeFilhoDoMeio=$(echo "${1} - ${idadeFilhoDoMeio}" | bc) | ||
+ | idadeMaeFilhoMaisNovo=$(echo "${1} - ${idadeFilhoMaisNovo}" | bc) | ||
+ | |||
+ | # Saída de dados | ||
+ | echo "A mãe teve filho com ${idadeMaeFilhoMaisVelho}, ${idadeMaeFilhoDoMeio} e ${idadeMaeFilhoMaisNovo} anos." | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ==19/11== | ||
+ | Um ''menu'': estrutura de decisão combinada com outra, de repetição: | ||
+ | <syntaxhighlight lang=bash> | ||
+ | #!/bin/bash | ||
+ | |||
+ | while [ "${opcao}" != "5" ] | ||
+ | do | ||
+ | clear | ||
+ | echo "Sistema: menu principal" | ||
+ | echo "" | ||
+ | echo "1) Usuários conectados." | ||
+ | echo "2) Processos." | ||
+ | echo "3) Espaço em disco." | ||
+ | echo "4) Configuração da rede." | ||
+ | echo "5) Sair do programa." | ||
+ | echo "" | ||
+ | echo -n "Escolha a sua opção: " | ||
+ | read opcao | ||
+ | case ${opcao} in | ||
+ | "1") | ||
+ | w | ||
+ | ;; | ||
+ | "2") | ||
+ | ps | ||
+ | ;; | ||
+ | "3") | ||
+ | df -h | ||
+ | ;; | ||
+ | "4") | ||
+ | ifconfig | ||
+ | ;; | ||
+ | "5") | ||
+ | exit | ||
+ | ;; | ||
+ | esac | ||
+ | echo "" | ||
+ | echo -n "Tecle [ENTER] para avançar..." | ||
+ | read enter | ||
+ | done | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Valendo 2 pontos na próxima prova: em Bash, um programa que verifica os números entre 1 e 1000 que são primos e/ou perfeitos. Uma possível resposta: | ||
+ | <syntaxhighlight lang=bash> | ||
+ | #!/bin/bash | ||
+ | |||
+ | for numero in $(seq 1 1000) | ||
+ | do | ||
+ | divisores="0" | ||
+ | for divisor in $(seq 2 $(echo "${numero} - 1" | bc)) | ||
+ | do | ||
+ | resto=$(expr ${numero} % ${divisor}) | ||
+ | if [ "${resto}" = "0" ] | ||
+ | then | ||
+ | divisores=$(expr ${divisores} + ${divisor}) | ||
+ | echo -n "(${divisor})" | ||
+ | else | ||
+ | echo -n "." | ||
+ | fi | ||
+ | done | ||
+ | |||
+ | # Mostra os valores | ||
+ | echo -n "${numero}" | ||
+ | if [ "${divisores}" = "0" ] | ||
+ | then | ||
+ | echo -n "p" | ||
+ | fi | ||
+ | if [ "$(expr ${divisores} + 1)" = "${numero}" ] | ||
+ | then | ||
+ | echo -n "P" | ||
+ | fi | ||
+ | echo "" | ||
+ | done | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ==26/11== | ||
+ | Verifica se um valor informado pelo usuário é um endereço IPv4: | ||
+ | <syntaxhighlight lang=bash> | ||
+ | #!/bin/sh | ||
+ | # | ||
+ | # O usuário precisa digitar alguma coisa, qualquer coisa. | ||
+ | # Caso contrário, o programa encerrará por falta de informação. | ||
+ | # | ||
+ | # Verifica se o usuário não digitou um argumento. | ||
+ | # Se sim, o programa será encerrado (exit). | ||
+ | if [ "${1}" = "" ] | ||
+ | then | ||
+ | # Mostra a mensagem de como executar corretamente. | ||
+ | echo "Use: ${0} (endereço IPv4)" | ||
+ | # Fecha o programa. | ||
+ | exit | ||
+ | fi | ||
+ | # | ||
+ | # Separa o primeiro argumento em 4 partes; ou melhor, 4 octetos. | ||
+ | octeto1=$(echo ${1} | cut -d \. -f 1) | ||
+ | octeto2=$(echo ${1} | cut -d \. -f 2) | ||
+ | octeto3=$(echo ${1} | cut -d \. -f 3) | ||
+ | octeto4=$(echo ${1} | cut -d \. -f 4) | ||
+ | # | ||
+ | # Para cada um dos octetos (acima separados), é verificado se | ||
+ | # ele é um número E está entre os limites 0 e 255 (2^8 - 1). | ||
+ | for octeto in ${octeto1} ${octeto2} ${octeto3} ${octeto4} | ||
+ | do | ||
+ | # Realiza uma soma simples. | ||
+ | soma=$(echo "${octeto} - 1" | bc) | ||
+ | # Se a soma falhou ao processar usando o comando "bc", | ||
+ | # ignorando a exceção zero, significa que não é um número inteiro. | ||
+ | if [ "${soma}" = "-1" -a "${octeto}" != "0" ] | ||
+ | then | ||
+ | echo "${octeto} não é número inteiro." | ||
+ | exit | ||
+ | else | ||
+ | # Caso contrário, é um número inteiro. | ||
+ | # Próximo passo: verificar se é um byte a compor um IPv4. | ||
+ | if ! [ "${octeto}" -ge "0" -a "${octeto}" -le "255" ] | ||
+ | then | ||
+ | # Está fora dos limites. | ||
+ | echo "${octeto} é um número qualquer." | ||
+ | exit | ||
+ | fi | ||
+ | fi | ||
+ | done | ||
+ | echo "${1} é um endereço válido." | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ==03/12== | ||
+ | Aproveitando o programa da [[#26/11|aula anterior]], verificamos se a configuração de rede está OK, começando pelo arquivo <tt>/etc/resolv.conf</tt>. Como pode-se perceber, a verificação de IP - válido ou não - passa a ser uma função do programa maior: | ||
+ | <syntaxhighlight lang=bash> | ||
+ | #!/bin/sh | ||
+ | # | ||
+ | # 20121203 Ederson Torresini: validador de configuração de rede. | ||
+ | |||
+ | # Função IPvalido: valida endereço IP com 4 octetos. | ||
+ | IPvalido(){ | ||
+ | # O usuário precisa digitar alguma coisa, qualquer coisa. | ||
+ | # Caso contrário, o programa encerrará por falta de informação. | ||
+ | # | ||
+ | # Verifica se o usuário não digitou um argumento. | ||
+ | if [ "${1}" = "" ] | ||
+ | then | ||
+ | # Mostra a mensagem de como executar corretamente. | ||
+ | echo "Use: ${0} (endereço IPv4)" | ||
+ | else | ||
+ | # Separa o primeiro argumento em 4 partes; ou melhor, 4 octetos. | ||
+ | octeto1=$(echo ${1} | cut -d \. -f 1) | ||
+ | octeto2=$(echo ${1} | cut -d \. -f 2) | ||
+ | octeto3=$(echo ${1} | cut -d \. -f 3) | ||
+ | octeto4=$(echo ${1} | cut -d \. -f 4) | ||
+ | # | ||
+ | # Assume-me, inicialmente, que o endereço está correto; | ||
+ | # ou seja, o 'estado' é "sim". | ||
+ | retorno="sim" | ||
+ | # | ||
+ | # Para cada um dos octetos (acima separados), é verificado se | ||
+ | # ele é um número E está entre os limites 0 e 255 (2^8 - 1). | ||
+ | # Se for, muda o 'estado' para "não". | ||
+ | for octeto in ${octeto1} ${octeto2} ${octeto3} ${octeto4} | ||
+ | do | ||
+ | # Realiza uma soma simples. | ||
+ | soma=$(echo "${octeto} - 1" | bc) | ||
+ | # Se a soma falhou ao processar usando o comando "bc", | ||
+ | # ignorando a exceção zero, significa que | ||
+ | # não é um número inteiro. | ||
+ | if [ "${soma}" = "-1" -a "${octeto}" != "0" ] | ||
+ | then | ||
+ | retorno="não" | ||
+ | else | ||
+ | # Caso contrário, é um número inteiro. | ||
+ | # Próximo passo: verificar os limites de 1 byte (0-255). | ||
+ | if ! [ "${octeto}" -ge "0" -a "${octeto}" -le "255" ] | ||
+ | then | ||
+ | # Está fora dos limites. | ||
+ | retorno="não" | ||
+ | fi | ||
+ | fi | ||
+ | done | ||
+ | fi | ||
+ | echo ${retorno} | ||
+ | } | ||
+ | |||
+ | |||
+ | # Valida o arquivo de resolução DNS. | ||
+ | ARQUIVO="/etc/resolv.conf" | ||
+ | LINHAS=$(cat ${ARQUIVO} | wc -l) | ||
+ | echo "" | ||
+ | echo "Arquivo ${ARQUIVO}:" | ||
+ | for linha in $(seq 1 ${LINHAS}) | ||
+ | do | ||
+ | tipo=$(head -n ${linha} ${ARQUIVO}| tail -n 1 | cut -d \ -f 1) | ||
+ | valor=$(head -n ${linha} ${ARQUIVO} | tail -n 1 | cut -d \ -f 2) | ||
+ | case ${tipo} in | ||
+ | "domain") | ||
+ | if [ "${valor}" = "" ] | ||
+ | then | ||
+ | echo "[ERRO] Domínio (domain) em branco." | ||
+ | else | ||
+ | echo "[ OK ] Domínio: ${valor}." | ||
+ | fi | ||
+ | ;; | ||
+ | "search") | ||
+ | if [ "${valor}" = "" ] | ||
+ | then | ||
+ | echo "[ERRO] Busca (search) em branco." | ||
+ | else | ||
+ | echo "[ OK ] Domínio de busca: ${valor}." | ||
+ | fi | ||
+ | ;; | ||
+ | "nameserver") | ||
+ | if [ "${valor}" = "" -o "${valor}" = "nameserver" ] | ||
+ | then | ||
+ | echo "[ERRO] Servidor DNS com endereço vazio." | ||
+ | else | ||
+ | resposta=$(IPvalido ${valor}) | ||
+ | if [ "${resposta}" = "não" ] | ||
+ | then | ||
+ | echo -n "[ERRO] Servidor DNS com endereço " | ||
+ | echo "IP inválido: ${valor}." | ||
+ | else | ||
+ | echo "[ OK ] Servidor DNS: ${valor}." | ||
+ | fi | ||
+ | fi | ||
+ | ;; | ||
+ | *) | ||
+ | echo "[ERRO] Tipo inválido: ${tipo}." | ||
+ | ;; | ||
+ | esac | ||
+ | done | ||
+ | |||
+ | # Valida o arquivo de configuração de interfaces de rede | ||
+ | ARQUIVO="/etc/network/interfaces" | ||
+ | echo "" | ||
+ | echo "Arquivo ${ARQUIVO}:" | ||
+ | LINHAS=$(cat ${ARQUIVO} | wc -l) | ||
+ | for linha in $(seq 1 ${LINHAS}) | ||
+ | do | ||
+ | contexto=$(cat ${ARQUIVO} | head -n ${linha} | tail -n 1) | ||
+ | echo ${contexto} | grep -q '^auto.*' && \ | ||
+ | interface=$(echo ${contexto} | cut -d \ -f 2) | ||
+ | # E agora...? | ||
+ | done | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ==04/02== | ||
+ | No retorno às aulas, houve uma revisão da matéria com problema para contextualizar: como limpar um disco (quase) cheio? Uma solução é executar, na sequência: | ||
+ | # Identificar a(s) partição(ões) (quase) cheia(s). | ||
+ | # Identificar o(s) diretório(s) com mais espaço ocupado. | ||
+ | # Identificar o(s) arquivo(s) daquele(s) diretório(s) com mais espaço ocupado. | ||
+ | |||
+ | Uma proposta do primeiro item: | ||
+ | <syntaxhighlight lang=bash> | ||
+ | #!/bin/bash | ||
+ | |||
+ | TEMP="/tmp/.df-h" | ||
+ | |||
+ | # Primeira parte do programa: listar as partições | ||
+ | # e deixar o usuário escolher uma | ||
+ | |||
+ | mostrar_arquivo_numerado() | ||
+ | { | ||
+ | linhas=$(cat ${1} | wc -l) | ||
+ | for linha in $(seq 1 ${linhas}) | ||
+ | do | ||
+ | echo -n "[" | ||
+ | echo -n "${linha}" | ||
+ | echo -n "] " | ||
+ | cat ${1} | head -n ${linha} | tail -n 1 | ||
+ | done | ||
+ | } | ||
+ | |||
+ | listar_particoes() | ||
+ | { | ||
+ | df -h > ${TEMP} | ||
+ | mostrar_arquivo_numerado ${TEMP} | ||
+ | echo -n "Por favor, escolha uma partição: " | ||
+ | read numero | ||
+ | diretorio=$(cat ${TEMP} | head -n ${numero} | tail -n 1 | cut -d % -f 2) | ||
+ | cd ${diretorio} | ||
+ | echo "Agora você está no diretório $(echo ${diretorio})." | ||
+ | } | ||
+ | |||
+ | listar_particoes | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ==18/02== | ||
+ | Após o [http://www.boston.com/bigpicture/2013/02/carnival_2013.html carnaval], a continuação do programa, agora analisando arquivos e diretórios. Uma sugestão: | ||
+ | <syntaxhighlight lang=bash> | ||
+ | #!/bin/bash | ||
+ | |||
+ | TEMP="/tmp/.df-h" | ||
+ | |||
+ | # Primeira parte do programa: listar as partições | ||
+ | # e deixar o usuário escolher uma | ||
+ | |||
+ | mostrar_arquivo_numerado() | ||
+ | { | ||
+ | linhas=$(cat ${1} | wc -l) | ||
+ | for linha in $(seq 1 ${linhas}) | ||
+ | do | ||
+ | echo -n "[" | ||
+ | echo -n "${linha}" | ||
+ | echo -n "] " | ||
+ | cat ${1} | head -n ${linha} | tail -n 1 | ||
+ | done | ||
+ | } | ||
+ | |||
+ | listar_particoes() | ||
+ | { | ||
+ | df -h > ${TEMP} | ||
+ | mostrar_arquivo_numerado ${TEMP} | ||
+ | echo -n "Por favor, escolha uma partição: " | ||
+ | read numero | ||
+ | diretorio=$(cat ${TEMP} | head -n ${numero} | tail -n 1 | cut -d % -f 2) | ||
+ | cd ${diretorio} | ||
+ | echo "Agora você está no diretório $(echo ${diretorio})." | ||
+ | } | ||
+ | |||
+ | listar_diretorios() | ||
+ | { | ||
+ | while true | ||
+ | do | ||
+ | echo "" | ||
+ | echo "[1] Listar os arquivos/diretórios do diretório corrente." | ||
+ | echo "[2] Entrar em sub-diretório." | ||
+ | echo "[3] Voltar ao diretório anterior." | ||
+ | echo -n "Por favor, escolha uma opção: " | ||
+ | read opcao | ||
+ | echo "" | ||
+ | echo "Diretório corrente: $(pwd)" | ||
+ | case ${opcao} in | ||
+ | "1") | ||
+ | echo "Os 5 mais:" | ||
+ | du * 2> /dev/null | sort -n | tail -n 5 | ||
+ | ;; | ||
+ | "2") | ||
+ | echo -n "Por favor, informe qual o diretório: " | ||
+ | read diretorio | ||
+ | cd ${diretorio} | ||
+ | ;; | ||
+ | "3") | ||
+ | cd .. | ||
+ | ;; | ||
+ | *) | ||
+ | exit | ||
+ | esac | ||
+ | done | ||
+ | } | ||
+ | |||
+ | listar_particoes | ||
+ | listar_diretorios | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | =Projeto Integrador= | ||
+ | Serão 3 semanas para o [[Projeto Integrador - 2012.2|Projeto Integrador]]. | ||
+ | |||
+ | {{Voltar|Programação para Redes de Computadores (técnico) (página)|página principal da disciplina}} |
Edição atual tal como às 22h14min de 4 de março de 2013
Endereço encurtado: http://bit.ly/prc20122
Avaliações
São 4 avaliações, uma por mês - sem data pré-estabelecida:
O conceito final da disciplina é elaborado da seguinte forma:
- A: todas as avaliações em A.
- B: no máximo 1 C.
- C: no máximo 1 D, e para cada D no mínimo um B correspondente.
- D: demais casos.
Aulas
08/10
- Teste de conhecimento 1: instalação manual do Portugol.
- Sobre a matéria: entendimento de do sistema computacional de Von Neumann.
Um número é primo? Em Portugol:
inicio
// Entrada de dados
escrever "Por favor, escreva um número inteiro: "
inteiro dividendo
ler dividendo
// Processamento
inteiro divisor
inteiro divisores
inteiro resto
divisores <- 0
para divisor de (dividendo - 1) até 2 passo -1
escrever "."
resto <- dividendo % divisor
se resto = 0 então
divisores <- divisores + divisor
fimSe
próximo
texto resposta
se divisores > 0 então
resposta <- " não é primo."
senão
resposta <- " é primo."
fimSe
// Saída de dados
escrever "Calculei que ", dividendo, resposta
fim
E se for perfeito? O que muda no código anterior?
15/10
- Teste de conhecimento: Matemática básica aplicada.
- Sobre a matéria: tipos de funções ou procedimentos de um programa.
Um triângulo é pitagórico?
inicio
// Entrada de dados
inteiro a, b, c
escrever "Por favor, digite um número inteiro: "
ler a
escrever "Agora, outro número inteiro: "
ler b
escrever "E, por último, mais um número inteiro: "
ler c
// Processamento
inteiro a2
a2 <- potencia(a, 2)
inteiro b2c2
b2c2 <- potencia(b, 2) + potencia(c, 2)
texto resposta
se (a2 = b2c2) então
resposta <- "é pitagórico."
senão
resposta <- "não é pitagórico."
fimSe
// Saída de dados
escrever "O triângulo ", resposta
fim
Um número é potência de outro?
inicio
//Entrada de dados
texto resposta
inteiro numero
escrever "Por favor, digite um número inteiro: "
ler numero
// Processamento
real raizquadrada, resto
raizquadrada <- raiz(numero)
resto <- frac(raizquadrada)
se (resto > 0) então
resposta <- "não é potência quadrada de outro número inteiro: "
senao
resposta <- "é potência de: "
fimSe
// Saída de dados
escrever resposta, raizquadrada
fim
Outra forma (alternativa):
inicio
// Entrada de dados
inteiro numero
escrever "Por favor, digite um número inteiro: "
ler numero
// Processamento
texto resposta
inteiro respostaNumero
real expoente, resultado, rodada
para rodada de 2 ate 5 passo 1
expoente <- 1 / rodada
resultado <- potencia(numero, expoente)
se (frac(resultado) = 0) então
resposta <- "é potência de "
respostaNumero <- int(resultado)
fimSe
próximo
// Saída de dados
escrever resposta
escrever respostaNumero
fim
Desenhando uma "caixa" em volta de um número até 9999:
inicio
// Entrada de dados
inteiro numero
escrever "Por favor, digite SEMPRE um número inteiro: "
ler numero
// Processamento
inteiro colunas, linhaembranco
colunas <- 1
se (numero > 9) então
colunas <- 2
fimSe
se (numero > 99) então
colunas <- 3
fimSe
se (numero > 999) então
colunas <- 4
fimSe
se (numero > 9999) então
colunas <- 5
fimSe
colunas <- colunas + 4
linhaembranco <- colunas - 2
// Saída de dados
inteiro coluna
para coluna de 1 ate colunas passo 1
escrever "!"
próximo
escrever "\n"
escrever "!"
para coluna de 1 ate linhaembranco passo 1
escrever " "
próximo
escrever "!\n"
escrever "! ", numero, " !"
escrever "\n"
escrever "!"
para coluna de 1 ate linhaembranco passo 1
escrever " "
próximo
escrever "!\n"
para coluna de 1 ate colunas passo 1
escrever "!"
próximo
fim
22/10
Como "descobrir" que número o usuário digitou? Usando árvore!
inicio
// Entrada de dados
inteiro numero
texto resultado
escrever "Por favor, digite um número inteiro entre 0 e 7: "
ler numero
// Processamento
se numero > 3.5 então
se numero > 5.5 então
se numero > 6.5 então
resultado <- "7"
senão
resultado <- "6"
fimSe
senão
se numero > 4.5 então
resultado <- "5"
senão
resultado <- "4"
fimSe
fimSe
senão
se numero > 1.5 então
se numero > 2.5 então
resultado <- "3"
senão
resultado <- "2"
fimSe
senão
se numero > 0.5 então
resultado <- "1"
senão
resultado <- "0"
fimSe
fimSe
fimSe
// Saída de dados
escrever "O número é ", resultado , "."
fim
... ou caso a caso (meio óbvio, mas estamos ainda no terceiro dia de aula, ok? :):
inicio
// Entrada de dados
inteiro numero
texto resultado
escrever "Por favor, digite um número inteiro entre 0 e 7: "
ler numero
// Processamento
escolhe numero
caso 9:
resultado <- "9"
caso 8:
resultado <- "8"
caso 7:
resultado <- "8"
caso 6:
resultado <- "6"
caso 5:
resultado <- "5"
caso 4:
resultado <- "4"
caso 3:
resultado <- "3"
caso 2:
resultado <- "2"
caso 1:
resultado <- "1"
defeito:
resultado <- "0"
fimEscolhe
// Saída de dados
escrever "O número é ", resultado , "."
fim
29/10
Lembra como descobrir se um número é primo? Outra forma:
inicio
inteiro dividendo
escrever "Por favor, digite um número inteiro: "
ler dividendo
inteiro divisores, divisor
real resto
divisores <- 0
para divisor de 2 até (dividendo -1) passo 1
resto <- dividendo % divisor
se resto = 0 então
divisores <- divisores + 1
escrever "(",divisor,")"
senão
escrever "."
fimSe
próximo
escrever "\nO número ", dividendo, " possui ", divisores, " divisores."
fim
05/11
O mesmo programa do número primo, agora em Bash:
#!/bin/bash
# Limpa a tela.
clear
# Entrada de dados: pede ao usuário um número inteiro.
echo -n "Por favor, digite um número inteiro: "
read dividendo
# Assume, inicialmente, que o número é primo.
divisores="0"
# Agora, para todos os números compreendidos entre 2 e (número -1)
# é feita a divisão. Se o resto for zero, o número tem divisor e,
# portanto, não é primo.
for divisor in $(seq 2 $(expr ${dividendo} - 1))
do
# Calcula o resto da divisão.
resto=$(echo "${dividendo} % ${divisor}" | bc)
# Verifica se o resto é zero.
if [ "${resto}" = "0" ]
then
# Se for zero, mostra o divisor entre parênteses.
echo -n "(${divisor})"
divisores=$(expr ${divisores} + ${divisor})
else
# Senão, mostra apenas um ponto na tela.
echo -n "."
fi
done
# Apenas formata com uma linha a mais.
echo ""
# Verifica o resultado dos divisores.
if [ "${divisores}" -gt "0" ]
then
# Se há pelo menos um divisor, não é primo.
echo "O número não é primo."
else
# Senão, mantém-se como primo.
echo "O número é primo."
fi
12/11
Uma outra forma de resolver a questão 3 da primeira prova:
#!/bin/bash
# Entrada de dados
# Argumento 1: idade da mãe
# Argumento 2: idade do filho mais velho
# Processamento
idadeFilhoDoMeio=$(echo "${2} / 2" | bc)
idadeFilhoMaisNovo=$(echo "${idadeFilhoDoMeio} - 3" | bc)
idadeMaeFilhoMaisVelho=$(echo "${1} - ${2}" | bc)
idadeMaeFilhoDoMeio=$(echo "${1} - ${idadeFilhoDoMeio}" | bc)
idadeMaeFilhoMaisNovo=$(echo "${1} - ${idadeFilhoMaisNovo}" | bc)
# Saída de dados
echo "A mãe teve filho com ${idadeMaeFilhoMaisVelho}, ${idadeMaeFilhoDoMeio} e ${idadeMaeFilhoMaisNovo} anos."
19/11
Um menu: estrutura de decisão combinada com outra, de repetição:
#!/bin/bash
while [ "${opcao}" != "5" ]
do
clear
echo "Sistema: menu principal"
echo ""
echo "1) Usuários conectados."
echo "2) Processos."
echo "3) Espaço em disco."
echo "4) Configuração da rede."
echo "5) Sair do programa."
echo ""
echo -n "Escolha a sua opção: "
read opcao
case ${opcao} in
"1")
w
;;
"2")
ps
;;
"3")
df -h
;;
"4")
ifconfig
;;
"5")
exit
;;
esac
echo ""
echo -n "Tecle [ENTER] para avançar..."
read enter
done
Valendo 2 pontos na próxima prova: em Bash, um programa que verifica os números entre 1 e 1000 que são primos e/ou perfeitos. Uma possível resposta:
#!/bin/bash
for numero in $(seq 1 1000)
do
divisores="0"
for divisor in $(seq 2 $(echo "${numero} - 1" | bc))
do
resto=$(expr ${numero} % ${divisor})
if [ "${resto}" = "0" ]
then
divisores=$(expr ${divisores} + ${divisor})
echo -n "(${divisor})"
else
echo -n "."
fi
done
# Mostra os valores
echo -n "${numero}"
if [ "${divisores}" = "0" ]
then
echo -n "p"
fi
if [ "$(expr ${divisores} + 1)" = "${numero}" ]
then
echo -n "P"
fi
echo ""
done
26/11
Verifica se um valor informado pelo usuário é um endereço IPv4:
#!/bin/sh
#
# O usuário precisa digitar alguma coisa, qualquer coisa.
# Caso contrário, o programa encerrará por falta de informação.
#
# Verifica se o usuário não digitou um argumento.
# Se sim, o programa será encerrado (exit).
if [ "${1}" = "" ]
then
# Mostra a mensagem de como executar corretamente.
echo "Use: ${0} (endereço IPv4)"
# Fecha o programa.
exit
fi
#
# Separa o primeiro argumento em 4 partes; ou melhor, 4 octetos.
octeto1=$(echo ${1} | cut -d \. -f 1)
octeto2=$(echo ${1} | cut -d \. -f 2)
octeto3=$(echo ${1} | cut -d \. -f 3)
octeto4=$(echo ${1} | cut -d \. -f 4)
#
# Para cada um dos octetos (acima separados), é verificado se
# ele é um número E está entre os limites 0 e 255 (2^8 - 1).
for octeto in ${octeto1} ${octeto2} ${octeto3} ${octeto4}
do
# Realiza uma soma simples.
soma=$(echo "${octeto} - 1" | bc)
# Se a soma falhou ao processar usando o comando "bc",
# ignorando a exceção zero, significa que não é um número inteiro.
if [ "${soma}" = "-1" -a "${octeto}" != "0" ]
then
echo "${octeto} não é número inteiro."
exit
else
# Caso contrário, é um número inteiro.
# Próximo passo: verificar se é um byte a compor um IPv4.
if ! [ "${octeto}" -ge "0" -a "${octeto}" -le "255" ]
then
# Está fora dos limites.
echo "${octeto} é um número qualquer."
exit
fi
fi
done
echo "${1} é um endereço válido."
03/12
Aproveitando o programa da aula anterior, verificamos se a configuração de rede está OK, começando pelo arquivo /etc/resolv.conf. Como pode-se perceber, a verificação de IP - válido ou não - passa a ser uma função do programa maior:
#!/bin/sh
#
# 20121203 Ederson Torresini: validador de configuração de rede.
# Função IPvalido: valida endereço IP com 4 octetos.
IPvalido(){
# O usuário precisa digitar alguma coisa, qualquer coisa.
# Caso contrário, o programa encerrará por falta de informação.
#
# Verifica se o usuário não digitou um argumento.
if [ "${1}" = "" ]
then
# Mostra a mensagem de como executar corretamente.
echo "Use: ${0} (endereço IPv4)"
else
# Separa o primeiro argumento em 4 partes; ou melhor, 4 octetos.
octeto1=$(echo ${1} | cut -d \. -f 1)
octeto2=$(echo ${1} | cut -d \. -f 2)
octeto3=$(echo ${1} | cut -d \. -f 3)
octeto4=$(echo ${1} | cut -d \. -f 4)
#
# Assume-me, inicialmente, que o endereço está correto;
# ou seja, o 'estado' é "sim".
retorno="sim"
#
# Para cada um dos octetos (acima separados), é verificado se
# ele é um número E está entre os limites 0 e 255 (2^8 - 1).
# Se for, muda o 'estado' para "não".
for octeto in ${octeto1} ${octeto2} ${octeto3} ${octeto4}
do
# Realiza uma soma simples.
soma=$(echo "${octeto} - 1" | bc)
# Se a soma falhou ao processar usando o comando "bc",
# ignorando a exceção zero, significa que
# não é um número inteiro.
if [ "${soma}" = "-1" -a "${octeto}" != "0" ]
then
retorno="não"
else
# Caso contrário, é um número inteiro.
# Próximo passo: verificar os limites de 1 byte (0-255).
if ! [ "${octeto}" -ge "0" -a "${octeto}" -le "255" ]
then
# Está fora dos limites.
retorno="não"
fi
fi
done
fi
echo ${retorno}
}
# Valida o arquivo de resolução DNS.
ARQUIVO="/etc/resolv.conf"
LINHAS=$(cat ${ARQUIVO} | wc -l)
echo ""
echo "Arquivo ${ARQUIVO}:"
for linha in $(seq 1 ${LINHAS})
do
tipo=$(head -n ${linha} ${ARQUIVO}| tail -n 1 | cut -d \ -f 1)
valor=$(head -n ${linha} ${ARQUIVO} | tail -n 1 | cut -d \ -f 2)
case ${tipo} in
"domain")
if [ "${valor}" = "" ]
then
echo "[ERRO] Domínio (domain) em branco."
else
echo "[ OK ] Domínio: ${valor}."
fi
;;
"search")
if [ "${valor}" = "" ]
then
echo "[ERRO] Busca (search) em branco."
else
echo "[ OK ] Domínio de busca: ${valor}."
fi
;;
"nameserver")
if [ "${valor}" = "" -o "${valor}" = "nameserver" ]
then
echo "[ERRO] Servidor DNS com endereço vazio."
else
resposta=$(IPvalido ${valor})
if [ "${resposta}" = "não" ]
then
echo -n "[ERRO] Servidor DNS com endereço "
echo "IP inválido: ${valor}."
else
echo "[ OK ] Servidor DNS: ${valor}."
fi
fi
;;
*)
echo "[ERRO] Tipo inválido: ${tipo}."
;;
esac
done
# Valida o arquivo de configuração de interfaces de rede
ARQUIVO="/etc/network/interfaces"
echo ""
echo "Arquivo ${ARQUIVO}:"
LINHAS=$(cat ${ARQUIVO} | wc -l)
for linha in $(seq 1 ${LINHAS})
do
contexto=$(cat ${ARQUIVO} | head -n ${linha} | tail -n 1)
echo ${contexto} | grep -q '^auto.*' && \
interface=$(echo ${contexto} | cut -d \ -f 2)
# E agora...?
done
04/02
No retorno às aulas, houve uma revisão da matéria com problema para contextualizar: como limpar um disco (quase) cheio? Uma solução é executar, na sequência:
- Identificar a(s) partição(ões) (quase) cheia(s).
- Identificar o(s) diretório(s) com mais espaço ocupado.
- Identificar o(s) arquivo(s) daquele(s) diretório(s) com mais espaço ocupado.
Uma proposta do primeiro item:
#!/bin/bash
TEMP="/tmp/.df-h"
# Primeira parte do programa: listar as partições
# e deixar o usuário escolher uma
mostrar_arquivo_numerado()
{
linhas=$(cat ${1} | wc -l)
for linha in $(seq 1 ${linhas})
do
echo -n "["
echo -n "${linha}"
echo -n "] "
cat ${1} | head -n ${linha} | tail -n 1
done
}
listar_particoes()
{
df -h > ${TEMP}
mostrar_arquivo_numerado ${TEMP}
echo -n "Por favor, escolha uma partição: "
read numero
diretorio=$(cat ${TEMP} | head -n ${numero} | tail -n 1 | cut -d % -f 2)
cd ${diretorio}
echo "Agora você está no diretório $(echo ${diretorio})."
}
listar_particoes
18/02
Após o carnaval, a continuação do programa, agora analisando arquivos e diretórios. Uma sugestão:
#!/bin/bash
TEMP="/tmp/.df-h"
# Primeira parte do programa: listar as partições
# e deixar o usuário escolher uma
mostrar_arquivo_numerado()
{
linhas=$(cat ${1} | wc -l)
for linha in $(seq 1 ${linhas})
do
echo -n "["
echo -n "${linha}"
echo -n "] "
cat ${1} | head -n ${linha} | tail -n 1
done
}
listar_particoes()
{
df -h > ${TEMP}
mostrar_arquivo_numerado ${TEMP}
echo -n "Por favor, escolha uma partição: "
read numero
diretorio=$(cat ${TEMP} | head -n ${numero} | tail -n 1 | cut -d % -f 2)
cd ${diretorio}
echo "Agora você está no diretório $(echo ${diretorio})."
}
listar_diretorios()
{
while true
do
echo ""
echo "[1] Listar os arquivos/diretórios do diretório corrente."
echo "[2] Entrar em sub-diretório."
echo "[3] Voltar ao diretório anterior."
echo -n "Por favor, escolha uma opção: "
read opcao
echo ""
echo "Diretório corrente: $(pwd)"
case ${opcao} in
"1")
echo "Os 5 mais:"
du * 2> /dev/null | sort -n | tail -n 5
;;
"2")
echo -n "Por favor, informe qual o diretório: "
read diretorio
cd ${diretorio}
;;
"3")
cd ..
;;
*)
exit
esac
done
}
listar_particoes
listar_diretorios
Projeto Integrador
Serão 3 semanas para o Projeto Integrador.