25 outubro 2006

Lógica de Programação 10

Neste tópico vamos ver alguns dos operadores da nossa linguagem. Vamos começar com os operadores matemáticos:

(3 + 5) * 2 - (10 / 2)
Como você pode ver, os operadores são muito parecidos com aqueles que a gente aprende na escola: + é soma, - é subtração, * (asterisco) é multiplicação e / (barra) é divisão. Os parênteses funcionam como na matemática, mudando a ordem em que as expressões são avaliadas. Se não há parênteses, a ordem padrão é utilizada: multiplicação e divisão primeiro, depois soma e subtração.

O resultado de operadores matemáticos, que precisam de um número de cada lado, é sempre outro número: primeiro 3 + 5 é calculado, depois 8 * 2, então 10 / 2 (por causa do parênteses) e finalmente 16 - 5, resultando em 11.

Outro tipo de operadores são os de comparação:
3 == 5
3 != 5
3 < 5
1 <= 1
2 >= -5
Esses operadores precisam de um número de cada lado (por enquanto) e retornam não um número, mas um valor booleano. Valores booleanos podem apenas ser falso ou verdadeiro. Nesse exemplo, 3 é diferente de 5, então 3 == 5 (o operador para igual) retorna falso e 3 != 5 (o operador para diferente) retorna verdadeiro. Como 3 é menor que 5, 3 < 5 também retorna verdadeiro. Um é menor ou igual a 1, então 1 <= 1 também é verdadeiro, assim como 2 >= -5.

O último tipo de operador que vamos ver agora são os operadores lógicos:
falso ou verdadeiro
não verdadeiro e 3 > 2
salário > 5 * salário mínimo e idade < 30 e não solteiro
Alguns desses operadores nós já vimos, sempre precisando de um valor booleano de cada lado (com exceção do operador não). O operador ou retorna verdadeiro se qualquer um dos valores é verdadeiro (no exemplo, falso ou verdadeiro retorna verdadeiro). O operador não inverte o valor booleano: se era verdadeiro, retorna falso e vice-versa. O operador e retorna verdadeiro só se os dois valores são verdadeiros (o exemplo retorna falso, já que não verdadeiro é falso). A terceira linha mistura todos os operadores que nós já vimos: retorna verdadeiro se a variável salário tem valor maior que 5 vezes o salário mínimo (outra variável) e ao mesmo tempo idade é menor que 30 e ao mesmo tempo a variável solteiro é falsa.

05 outubro 2006

Lógica de programação 9

No último post nós vimos como trocar um número máximo de lâmpadas, e também como trocar apenas as lâmpadas queimadas dentro desse número máximo. Isso é o que nós conseguimos até agora:

trocas = 0
enquanto trocas < 10 faça
se não existir lâmpada queimada então
interrompa
fim se
// todo aquele código que troca uma lâmpada
trocas = trocas + 1
fim enquanto
Como você pode ver, estamos limitando o número de trocas na condição da repetição enquanto que dentro do bloco de código repetido nós usamos um condicional para interromper a repetição quando terminamos de trocar as lâmpadas queimadas. Vamos ver o que acontece se trocarmos as condições de lugar:
trocas = 0
enquanto existir lâmpada queimada faça
se trocas >= 10 então
interrompa
fim se
// todo aquele código que troca uma lâmpada
trocas = trocas + 1
fim enquanto
Veja como as condições se inverteram. Isso aconteceu porque a condição do enquanto deve ser verdadeira durante toda a repetição, até que fica falsa quando a repetição deve terminar; por outro lado, a condição do condicional é falsa durante toda a repetição, ficando verdadeira para sinalizar o fim das trocas de lâmpadas. Se você simular esse código vai descobrir que ele faz exatamente a mesma coisa que o anterior.

Será que existe outra maneira de fazer isso? Claro: nós podemos unir essas duas condições numa expressão só, porque no fundo elas servem para dizer "continue repetindo... continue repetindo... pare!". Se é assim, nós podemos colocá-las no nosso enquanto e mandar aquele condicional passear:
trocas = 0
enquanto existir lâmpada queimada e trocas < 10 faça
// todo aquele código que troca uma lâmpada
trocas = trocas + 1
fim enquanto
Para fazer isso, usamos uma nova palavra reservada: e. Esse tipo de palavra chave (outro nome para palavra reservada) também é conhecido como operador, porque pega expressões, fazendo alguma operação com elas, e retorna o resultado da operação. O operador e retorna um valor verdadeiro se as expressões da cada lado dele (direito e esquerdo) forem verdadeiras ao mesmo tempo. Esse código faz a mesma coisa que os dois anteriores, mas de uma maneira mais elegante e resumida.

Na próxima parte vamos conhecer outros operadores da nossa linguagem.

03 outubro 2006

Lógica de programação 8

Nós já sabemos trocar todas as lâmpadas de uma sala usando repetição (se não lembra veja a parte 6 dessa série), mas digamos que o SINDETROL (Sindicato dos Estagiários Trocadores de Lâmpadas) tenha feito um acordo que limita as trocas de lâmpadas a 10 por dia. Nesse caso, nós vamos ter que contar as trocas de lâmpadas e parar quando chegarmos na décima troca. Para fazer isso podemos usar uma variável:

trocas = 0
enquanto trocas < 10 faça
// todo aquele código que troca uma lâmpada
trocas = trocas + 1
fim enquanto
Vamos tentar entender o que está acontecendo. No começo, o valor inicial da variável trocas é zero, porque ainda não trocamos lâmpadas hoje. Como zero é menor que 10 o código que troca uma lâmpada é executado e trocas é somado com 1. Como 1 ainda é menor que 10, trocamos mais uma lâmpada e trocas passa a ser 2. Isso acontece até que trocas está valendo 9, porque já trocamos 9 lâmpadas, e o código de troca de lâmpadas é executado pela última vez. Depois disso, trocas é incrementado para 10. Como 10 não é menor que 10 a repetição pára e o estagiário vai tomar um cafezinho. Note que só podemos incrementar o valor de trocas depois que realmente fazemos uma troca. Pronto. Fim do tópico.

Não! Como você deve lembrar, a repetição da parte 6 tinha como condição ainda existir alguma lâmpada queimada para ser trocada. Agora estamos trocando 10 lâmpadas sem nem ver se elas estão queimadas ou não! Vamos tentar consertar isso com um comando novo:
trocas = 0
enquanto trocas < 10 faça
se não existir lâmpada queimada então
interrompa
fim se
// todo aquele código que troca uma lâmpada
trocas = trocas + 1
fim enquanto
Agora, enquanto a repetição limita o número de trocas a 10, o condicional que colocamos logo no começo da repetição trata de interromper a repetição se não tiver mais lâmpadas queimadas. Se as lâmpadas queimadas acabaram o comando interrompa cancela a repetição, fazendo com que o computador execute o comando seguinte ao fim da repetição.

Mas essa não é a única forma de fazer isso (dica: o que acontece se usarmos o mesmo mecanismo, mas com as condições da repetição e do condicional trocadas?). Na próxima parte, vamos ver variações desse exemplo.

02 outubro 2006

Lógica de programação 7

Como eu prometi, hoje vamos aprender a contar. Quer dizer, espero que você já saiba contar: o que nós vamos aprender é como fazer o computador contar. Para fazer isso, nós vamos usar outro conceito importante, chamado variável. Uma variável é um espaço na memória do computador que pode guardar um dado qualquer. As variáveis têm nomes, para que o computador saiba (e o programador também!) de que espaço na memória que a gente está falando. Na nossa linguagem nós criamos uma nova variável quando damos um valor para ela pela primeira vez:

x = 10
Isso faz com que o computador reserve um espaço na memória para guardar o valor da variável x e ponha o valor 10 nesse espaço. Vamos criar mais variáveis:
y = 5
x = 11
soma = x + y
salário = 1654.32
salário anual = salário * 12
média = (4 + 5 + 2 + 3.14159) / 4
Na primeira linha criamos uma nova variável y com o valor 5. Assumindo que esse exemplo é a continuação do outro, mudamos o valor da variável x, que era 10 e passou a ser 11 (no mesmo espaço de memória em que ela estava antes, porque ela já existia quando mudamos o seu valor). Também criamos uma variável soma com o resultado da soma de x com y: o valor inicial de soma é 16. A variável salário tem um valor real, em vez de ser inteiro como nos casos anteriores. Note que na nossa linguagem o separador de casas decimais é o ponto e não a vírgula; a grande maioria das linguagens de programação usa esse formato, que não por acaso é como os americanos escrevem os números deles. A variável salário anual tem o valor de salário multiplicado por 12 (19851.84). Os parênteses funcionam como na matemática: a variável média tem a soma dos 4 valores divida por 4 (3.5353975).

Veja que nesses exemplos eu só usei o valor de uma variável depois de ter dado um valor para ela. Não importa qual a linguagem, é sempre importante garantir que a variável tem valor antes de começar usar o valor dela. Algumas linguagens dão um valor padrão (zero, por exemplo); em outras o computador avisa que você esqueceu de definir um valor inicial; outras não ligam pra isso e deixam o pepino pra você (pepino porque você não tem como saber o que você vai encontrar na memória). Você pode descobrir isso lendo a documentação ou o manual da linguagem.

Mas o computador ainda não está contando! Cadê? Cadê a contagem? Calma, esse tópico foi só a vaselina. No próximo vai.

28 setembro 2006

Indentação

Se você está acompanhando os posts sobre lógica de programação, já deve ter notado que os textos têm um formato característico. Além da sintaxe da nossa linguagem de programação, isto é, da ordem em que as palavras reservadas têm que aparecer, também existe um certo padrão nos espaços que são usados no começo de cada linha. Esses espaços no início de cada linha são chamados de indentação. Na maioria das linguagens, inclusive na nossa, a indentação não faz parte da sintaxe: você pode usar a indentação que quiser, inclusive nenhuma, ou colocar espaços nos lugares que você quiser, que o significado do programa não muda.

Então para que serve a indentação? A indentação serve como um guia visual para nós, programadores humanos. Deixa o código fonte do programa mais organizado, mais fácil de ler, entender e modificar. Veja um exemplo altamente didático, sem indentação:

enquanto carros andando na rua faça
espere
olhe para um lado
olhe para o outro lado
fim enquanto
enquanto não chegar ao outro lado faça
se pessoa na frente então
desvie
senão
dê um passo
fim se
fim enquanto
Confuso, não? Agora com a indentação, colocando os blocos de código dentro das repetições e dos condicionais um nível de indentação para a direita (inclusive quando existe um bloco dentro do outro):
enquanto carros andando na rua faça
espere
olhe para um lado
olhe para o outro lado
fim enquanto
enquanto não chegar ao outro lado faça
se pessoa na frente então
desvie
senão
dê um passo
fim se
fim enquanto
Muito melhor. Tradicionalmente, a indentação era feita com tabulações (tecla Tab), com uma tabulação para cada nível. O problema é que existem alguns estilos de indentação que misturam espaços e tabulações, e quando se misturam os dois da maneira errada o resultado é uma bagunça feia de se ver. Para tentar evitar esse problema, virou moda usar só espaços para fazer a indentação: 8 ou, mais recentemente, 4 espaços para cada nível de indentação. Realmente não interessa muito o estilo a ser usado, desde que se use indentação (pode valer pontos extras nos trabalhos da universidade) e o estilo se mantenha no código fonte inteiro (é muito feio ficar trocando de estilo no meio do texto).

27 setembro 2006

Lógica de programação 6

Tudo bem, o condicional é muito divertido e tudo mais, mas e se eu for um estagiário trabalhando numa sala grande com muitas lâmpadas? Preciso copiar e colar esse código pra cada lâmpada maldita? Não, pequeno gafanhoto. É aí que entra outro conceito importatíssimo da lógica de programação: a repetição. Existem várias formas de repetição, mas todas são variações dessa:

enquanto condição faça
ações
fim enquanto
Isso faz com que o computador verifique a condição: se ela for verdadeira, ele executa as ações e verifica a condição de novo, para executar as ações de novo se ela continuar verdadeira, para verificar a condição de novo... Enfim, acho que já deu pra entender. Da mesma forma que no condicional, depois que o computador percebe que a condição ficou falsa e sai da repetição, ele não volta pra ela só porque a condição ficou verdadeira de novo. A única forma de repetir a repetição é colocar uma repetição dentro da outra. Vamos usar uma repetição na troca da lâmpada:
enquanto existir lâmpada queimada faça
se lâmpada muito alta então
por escada em baixo da lâmpada
subir na escada
remover lâmpada queimada
colocar lâmpada boa
descer da escada
guardar escada
senão
remover lâmpada queimada
colocar lâmpada boa
fim se
fim enquanto
Bonito, não? Num próximo post vamos deixar a coisa mais interessante e começar a contar.

Lógica de programação 5

Se você prestou atenção no condicional do último post, viu que eu destaquei algumas das palavras do código da troca da lâmpada. Aquelas são palavras com significado especial na nossa linguagem de programação. Todas as linguagens de programação têm palavras especiais, conhecidas como palavras reservadas, que indicam ao computador o que tem que ser feito. Essas palavras têm que ser colocadas numa ordem definida para que o computador possa entendê-las: é a sintaxe da linguagem, o formato em que o texto deve aparecer. Elas são reservadas porque são usadas pela linguagem: você não pode usá-las para outras coisas porque isso confunde o computador. Essa é a sintaxe do condicional, sem e com senão, respectivamente:

se condição então
ações (se a condição for verdadeira)
fim se

se condição então
ações (se a condição for verdadeira)
senão
ações (se a condição for falsa)
fim se
É bom lembrar que as ações são executadas apenas se a condição for verdadeira quando o computador estiver testando o condicional. O computador vai executando um comando depois do outro, na ordem em que foram escritos: se depois que o computador já tiver passado pelo condicional a condição se tornar verdadeira, isso não influi em nada nesse ponto do código — o computador não retorna a esse condicional só porque a condição mudou.

25 setembro 2006

Lógica de programação 4

Como prometido, hoje vamos fazer o nosso primeiro algoritmo. Vamos usar um problema tradicional pra isso: trocar uma lâmpada queimada. Uma primeira tentativa, usando uma linguagem conhecida por aí como Portugol ou português estruturado, poderia ser:

trocar lâmpada queimada
Simples, não? Pois é, mas os computadores são burros e não sabem o que significa trocar, nem o que seria uma lâmpada e muito menos qual a diferença entre uma lâmpada queimada e uma lâmpada boa. Vamos tentar explicar então, o que seria trocar uma lâmpada:
remover lâmpada queimada
colocar lâmpada boa
Agora está melhor. Mas e se a lâmpada estiver num lugar muito alto e você não alcançar a tal lâmpada? Nesse caso, podemos nos valer de um artifício técnico conhecido como escada. Se você subir na escada, alcança a lâmpada (espero). Vamos lá:
por escada em baixo da lâmpada
subir na escada
remover lâmpada queimada
colocar lâmpada boa
descer da escada
guardar escada
Ótimo, podemos ir pra casa. Mas peraí: isso de carregar escada pra lá e pra cá dá muito trabalho, e nós programadores somos preguiçosos. Vou até criar um fato para isso:
Fato 3: Os programadores são preguiçosos.
Não se assuste com a aparente negatividade desse fato. Os programadores são preguiçosos, mas no bom sentido: o que eles querem é poupar trabalho, tanto para eles quanto para os computadores. Trabalho humano poupado é igual a mais tempo para tomar cerveja (ou qualquer outro líquido que você costume consumir). Trabalho computacional poupado é igual a menos custos, o que algumas vezes significa mais dinheiro para os trabalhadores humanos.

É claro que os programadores usam de esperteza para poupar trabalho, em vez de realmente serem preguiçosos e simplesmente entregar uma caixa de papelão com luzinhas para o cliente (às vezes isso causava a perda de algumas vidas inocentes, e nem sempre existia um estagiário à mão para ser entregue à guilhotina). O método esperto que nós vamos usar nesse caso, conhecido como condicional, costuma poupar trabalho para os computadores, mas às vezes também poupa trabalho humano (mais sobre esses usos no futuro). Veja só:
se lâmpada muito alta então
por escada em baixo da lâmpada
subir na escada
remover lâmpada queimada
colocar lâmpada boa
descer da escada
guardar escada
senão
remover lâmpada queimada
colocar lâmpada boa
fim se
Agora sim: se a lâmpada for muito alta, fazemos todos aqueles passos que incluem pegar e guardar a escada. Por outro lado, se não precisarmos da escada nós poupamos trabalho e só trocamos a infeliz da lâmpada. No próximo post vamos ver como criar condicionais para outras coisas.

23 setembro 2006

Lógica de programação 3

Percebi que estava cometendo uma falha terrível: ainda não disse o que é a tal "lógica de programação"! Vamos lá: os computadores que nós usamos hoje em dia são baseados na arquitetura de Von Neumann, inventada por um computeiro fodão da metade do século passado. O importante nisso é que os computadores seguem sempre um ciclo: pega uma instrução da memória, pega os dados necessários, executa a instrução, põe os dados na memória (ou gospe eles na tela, por exemplo) e pega a próxima instrução da memória, continuando nesse ciclo eternamente. Da mesma forma, os programas são escritos em linguagens de programação que acabam, no geral, seguindo mais ou menos o mesmo paradigma (paradigma imperativo, se te interessa saber).

Esse paradigma é uma adaptação direta do conceito de algoritmo. "Algoritmo é uma sequência finita e não ambígua de instruções para solucionar um problema", pra usar a definição altamente didática da Wikipedia. Ou seja, é uma receita que um dia acaba (ainda bem), bem explicadinha (lembre do fato 1 — computadores são burros) que ensina alguém (o computador, por exemplo, mas não necessariamente) a fazer alguma coisa (resolver o tal problema).

O caso é que os programas são algoritmos, escritos em alguma linguagem que o computador entende. Não interessa muito a linguagem, porque todas elas se parecem. Os conceitos usados em uma costumam se aplicar às outras, com pequenas modificações. Uma receita de bolo de chocolate é muito parecida, seja em português, em inglês ou árabe. Com as linguagens de programação é a mesma coisa, com a vantagem que a semelhança entre elas é bem maior do que entre línguas humanas. Conhecendo os princípios básicos, a lógica de programação, fica fácil programar em qualquer linguagem.

Pronto, está explicado. No próximo post vamos fazer o nosso primeiro algoritmo. Aguarde e confie, como diz o glorioso Didi Mocó.

21 setembro 2006

Lógica de programação 2

A computação é uma área meio bisonha: é uma mistura de matemática e engenharia, principalmente, mas também encosta em todas as outras áreas do conhecimento. Essa influência forte da engenharia, aliada à pouca idade da computação, faz com que a programação empreste muitas idéias usadas na fabricação de coisas. O processo tradicional de programação segue o padrão análise (do problema), projeto (da solução) e implementação e teste (do programa). Tudo muito certinho e organizado, como numa fábrica de carros.

Eu sou da opinião que a técnica é importante, mas a programação se assemelha mais à literatura do que à engenharia. O funcionamento dos programas é descrito por textos (às vezes também alguns desenhos), os programas podem ser alterados muito mais facilmente do que uma peça de motor e o custo de fazer cópias de um programa é próximo de zero. Além disso, o programa é uma coisa muito mais próxima do texto que o descreve do que um patinete é próximo do projeto do patinete. É quase como se o programa fosse o texto. Programar é um processo artesanal apesar de tudo, é criativo e muitas vezes solitário (pelo menos em alguns momentos). Existem textos bonitos e textos feios de programas, e cada programador tem o seu estilo próprio que vai se desenvolvendo com o tempo. Tudo isso nos leva ao segundo fato:

Fato 2: Programar é uma arte.
Pense nesse fato assim: a técnica é importante, educação formal em programação aumenta o número e a qualidade das ferramentas que você tem e é preciso ser organizado se você quiser criar qualquer coisa com um tamanho razoável, mas no fundo um programador é um escritor de programas. Às vezes você vai quebrar as regras de propósito, vai inovar, vai bolar histórias geniais e se tiver sorte ainda vai se divertir muito fazendo isso. Espero que aos poucos você acabe concordando com esse fato.

Lógica de programação 1

Então você resolveu que quer aprender a programar. Bom, se é assim, é melhor ter uma idéia de onde você está se metendo. Para resumir bastante (para os parentes, por exemplo), programar é ensinar ao computador como fazer coisas novas. O computador é um bicho danado de burro, ao contrário de você, humano ou criatura semelhante. Computadores não são muito melhores que calculadoras grudadas numa televisão. Isso nos leva ao primeiro fato da vida de um programador:

Fato 1: Quando falar com o computador, fale beeeem devagar.
É importante ler isso realçando bem o "beeeem", para que isso penetre no seu inconsciente. É claro que esse fato não deve ser levado ao pé da letra: se você realmente começar a bater altos papos com o seu computador em público, falando beeeem devagar, os não programadores vão achar que você tem algum grave problema neurológico e vão parar de te chamar pra sair (e você provavelmente não quer isso).

O que esse fato quer dizer é que como os computadores são burros feito uma porta você deve explicar detalhadamente e claramente tudo o que ele tem que fazer. Passo a passo, beeeem devagar, como numa receita de bolo para chimpanzés (chimpanzés são ótimos cozinheiros se trabalharem numa cozinha espaçosa o suficiente). A maioria das engasgadas dos programas que você criar serão mal entendidos entre você e o seu colega digital.