Mostrando postagens com marcador operador de módulo. Mostrar todas as postagens
Mostrando postagens com marcador operador de módulo. Mostrar todas as postagens

terça-feira, 17 de novembro de 2009

Um passo de cada vez... Algoritmos (palíndromo)

Agora que já conhecemos bastante coisa sobre o C, gostaria de tocar num ponto que complica a vida de muita gente que está iniciando em programação: os algoritmos.
Já comecei a falar sobre isso (aqui), e inclusive já vimos(?) na prática, embora eu não tenha falado sobre, como criar um algoritmo.
No último post da série sobre comandos de repetição, em um dos exemplos eu mostrei como criar um programa a partir de uma situação proposta. Quem vai executar as operações não somos nós, e sim o computador. O algoritmo é o 'roteiro' dos passos que ele irá seguir para executar essa função. E quem tem que 'dizer' a ele o que fazer somos nós, afinal, computadores não pensam (ainda!).

Pensando em algoritmos
Como já é costume nosso, vamos à prática.
Nosso 1o algoritmo consiste em verificar se um número digitado pelo usuário é palíndromo.
Antes de abrir o Dev e começar a digitar os includes, vamos entender o que é um número palíndromo. Veja aqui.
Muito bem agora que sabemos o que é um número palíndromo, como descobrir se o número digitado é ou não um deles?
Vamos usar o número 171 como exemplo (logo esse?). Este número tem 3 dígitos.

Se invertermos a ordem dos dígitos, teremos o mesmo número.

Então é só comparar o número com o seu 'inverso'.
Comparar números é fácil, já vimos isso com o if e os operadores relacionais.
Mas, como inverter o número?

Aprendendo a usar os restos
Para inverter os dígitos de um número, primeiro precisamos separar estes dígitos. No caso do nosso número com 3 dígitos, primeiro precisamos retirar 2 dígitos e ficar com 1 dígito que resta. Depois, dos 2 dígitos que retiramos antes, precisamos tirar 1 dígito e ficar com o outro dígito que resta. No final, só restará 1 dígito.
Percebeu a repetição de palavras derivadas de resto (resta e restará). O segredo está aí!
Vejamos um número menor, com 2 dígitos, por exemplo 17.
Se retirarmos o 1o dígito, neste caso o 1, restará o 2o digito, neste caso o 7.
Mas como 'retirar' um dígito do número? O resto é a resposta!
Se dividirmos o número 17 por 10, teremos como resultado 1 e um resto igual a 7. Melhor ainda, se utilizarmos o operador de módulo teremos o resto desta divisão fácilmente.
 digito = 17 % 10
O comando acima armazenará em digito o valor 7, que é o último dígito do número 17.
Uma vez que já temos o dígito que nos interessa, podemos eliminá-lo do número, para poder usar o mesmo artifício afim de 'retirar' outros dígitos. Para eliminar o último dígito de um número é só dividir este número por 10.
 num = 17 / 10
O comando acima armazenará em num o valor 1, desprezando o último dígito do número 17, neste caso o 7.
Se usarmos o módulo de 10 na variável num, que agora contém o valor 1, teremos um resultado 0 e um resto 1.
Viu como é fácil fazer com um número de 2 dígitos? Com números com mais dígitos a lógica é a mesma, só tem que ser repetida outras vezes dependendo da quantidade de dígitos.
Podemos usar o módulo de 10 para obter o último dígito do número, e depois dividir o número por 10 para eliminar este dígito que já foi obtido, e ir repetindo este processo até que o resultado da divisão do número por 10 seja 0 (zero), o que significa que acabaram os dígitos do número.
Já aprendemos como 'retirar' os dígitos de um número. E agora? Como inverter este número?
Vamos voltar ao nosso exemplo com o número 17. O inverso de 17 é 71. Que é o último dígito, neste caso o 7, multiplicado por 10, somado com o 1o digito, neste caso o 1.
Agora ficou fácil mesmo!
É só pegar o último dígito, neste caso o 7, obtido usando o módulo de 10 do número 17, multiplicar por 10, e somar com o 1o dígito, neste caso o 1, obtido usando o módulo de 10 no resultado da divisão do número 17 por 10.
Com números com mais dígitos a lógica é exatamente a mesma.
Vamos ver como vai ficar o nosso código?

//PROGRAMA PARA DETERMINAR SE UM NUMERO É PALINDROMO
#include <stdio.h>
#include <stdlib.h>
 
int main(){
 int digitado,num,invertido,digito;
 printf("Digite numero inteiro: ");
 scanf("%d",&digitado);
 num = digitado;
 invertido = 0;
 while(num != 0){
    digito = num % 10;
    invertido = (invertido * 10) + digito;
    num = num / 10;
 }
 if(digitado == invertido)
    printf("Palindromo !!!\n");
 else
    printf("Nao eh Palindromo!!!\n");
 system ("pause");
}


Os nomes das variáveis já falam por si. Note que não trabalhamos diretamente com o número digitado, e sim com uma variável num. Por quê?
Se tivéssemos usado diretamente o número digitado, ele seria perdido nas 'retiradas' dos dígitos e não teríamos como compará-lo com o seu inverso.
É mais fácil do que parece. Não é?
Até a próxima.

terça-feira, 27 de outubro de 2009

Deixe que o computador decida... Parte II (else)

No post anterior, deixei uma pergunta. Vamos respondê-la hoje.
Antes disto vamos, melhorar ainda mais o nosso código.
Se você reparar bem, nós fazemos uma saída forçada do programa se o usuário digitar o valor zero para o divisor (linha 17).
Esta sáida forçada pode ser evitada! Podemos fazer com que o programa se encerre normalmente no } que encerra a função main.
Como?
É isto que veremos hoje.

O comando else
Vamos analisar o que desejamos que o programa faça.

Primeiro avaliamos qual é o valor do divisor, se for zero, informamos isto ao usuário e vamos para o final do programa sem fazer a divisão. Se não for, fazemos a divisão, mostramos o resultado desta divisão ao usuário e vamos para o final do programa.
Reparou no se não? Assim como o se, ele existe em C! É o else (se não em inglês, da mesma forma que o if é o se).
Um else sempre está ligado a um if. Ele é o caminho alternativo da condição avaliada no if, algo como um 'plano b'.
Se a condição avaliada for verdadeira, faça isto; se não for, faça aquilo.
O else não precisa avaliar nenhuma condição. A condição já foi avaliada pelo if.
E somente quando ela for falsa, o comando else entrará em cena.
Lembra do exemplo do guarda-chuva. Seria algo assim:

Se está chuvendo
 abro o guarda chuva;
Se não
 ele vai continuar fechado;

No caso do nosso código, ele ficará assim:


//Exemplo de else
 
#include <stdio.h>
#include "stdlib.h"
 
int main( )
{
 float num1, num2, resultado;
 
 printf("Digite o numero que sera dividido(dividendo)\n");
 scanf("%f",&num1);
 printf("Digite o numero que dividira o anterior (divisor), nao pode ser zero\n");
 scanf("%f",&num2);
 if (num2 == 0)
    printf("O DIVISOR NAO PODE SER ZERO! O programa sera encerrado.\n");
 else {
    resultado = num1 / num2;
    printf("O resultado da divisao de %.2f por %.2f eh igual a %.2f.\n",num1, num2, resultado);
}
 system ("pause");
}


Compile e execute este código. Para efeitos de teste, digite 0 (zero) para o divisor.
Viu como o programa foi até o final, mesmo quando o valor digitado pelo usuário foi inválido!
Mas, se a outra forma estava funcionando, qual o motivo desta alteração?
Porque esta alteração nos ajudará a resolver a questão que foi proposta.
Vamos prosseguir que logo você vai entender.
Nós alteramos nosso código para que avaliasse o divisor antes de fazer a divisão, afim de evitar uma divisão por zero. Agora desejamos avaliar se o valor do dividendo é um número par. Sendo assim, devemos fazer esta avaliação também.

Como saber se um número é par?
Dentre outras, um número é par se sua divisão por 2 for exata, ou seja, não sobrar resto. Em outras palavras, o resto tem que ser zero.
Fácil não é? Nem tanto.
Você lembra que tivemos que mudar o tipo da variável num2 de int para float, para que o resultado da divisão aparecesse corretamente? Não lembra? Veja aqui.
A divisão de um tipo float por 2 sempre será exata, já que o resultado será um número fracionário (com casas decimais). O resto sempre será zero, mesmo que o número seja ímpar.
Solução? Vamos mudar novamente o tipo da variável num2, agora de float para int.
O fato da variável num1 ser do tipo float garante que o resultado da divisão também será do tipo float.
Agora sim. Se o valor armazenado na variável do tipo int num2 for um número ímpar, ao ser dividido por 2, o resto da divisão será diferente de zero.
Então, agora teremos que fazer duas divisões? A resposta é NÃO.
Não? Mas, se para saber se um número é par ou ímpar, eu preciso saber qual é o resto da divisão deste número por 2, como não precisa dividir?
Simples! O C (sempre ele ;) nos fornece um recurso para isto: o operador de módulo (%).
O operador de módulo nos dá o resto da divisão entre 2 números inteiros.
Para saber o resto da divisão do valor armazenado na variável do tipo int num2 por 2 (que é o que desejamos para resolver este problema!), é só usar o seguinte comando:

 num2 % 2

Para saber se este resto é diferente de zero , é só usar o operador relacional diferente de (!=).
O comando completo ficaria assim:

 num2 % 2 != 0

Agora que já sabemos avaliar se um número inteiro é par ou ímpar, vamos continuar com a resolução da questão proposta.

Primeiro avaliamos qual é o valor do divisor, se for zero, informamos isto ao usuário e vamos para o final do programa sem fazer a divisão. Depois, se não for, analisamos se este valor é um número par. Se for fazemos a nossa divisão, mostramos o resultado desta divisão ao usuário e vamos para o final do programa. Se não for, informamos ao usuário e vamos para o final do programa.
Se você notou, temos um se e um se não dentro de um se não. Este é um recurso poderoso do C.

Blocos dentro de blocos (A Boneca Russa)
Já ouviu falar em Matrioshka. A Matrioshka é uma brinquedo tradicional de origem russa, que consiste em várias bonecas de tamanhos diferentes, encaixadas umas dento das outras.



O C tem sua própria versão de Matrioshka (rsrs).
É possível inserir um comando dentro de outro comando!
Imagine o comando if. É possível inserir um if dentro de outro if, ou dentro de um else. Isto é chamado de 'aninhar'. Você vai ouvir muito falar em ifs aninhados.
Vamos ver isto na prática.
Nosso código agora ficará assim:


//Exemplo de ifs/elses aninhados
 
#include
#include "stdlib.h"
 
int main( )
{
 float num1, resultado;
 int num2;
 
 printf("Digite o numero que sera dividido(dividendo)\n");
 scanf("%f",&num1);
 printf("Digite um numero par que dividira o anterior (divisor), nao pode ser zero\n");
 scanf("%d",&num2);
 if (num2 == 0)
    printf("O DIVISOR NAO PODE SER ZERO! O programa sera encerrado.\n");
 else
    if (num2 % 2 == 0){
       resultado = num1 / num2;
       printf("O resultado da divisao de %.2f por %d eh igual a %.2f.\n",num1, num2, resultado);
    }
    else
       printf("O DIVISOR NAO EH UM NUMERO PAR! O programa sera encerrado.\n");
 system ("pause");
}



Observou a indentação? Indentação são os espaços colocados no código fonte para que fiquem bem claros a quais blocos eles pertencem. Ela já apareceu em alguns exemplos de códigos anteriores. Para códigos fonte pequenos, ela não é tão necessária. Mas, para códigos um pouco maiores, como o do exemplo de hoje, ela se faz praticamente essencial.

Por hoje é só pessoal! Até o próximo post.