VidaGeek.net

Linux, Open-source, Programação e Produtividade

Archive for the ‘C’ Category

YACP - Condições Booleanas

Continuando o tutorial, vamos começar agora o feijão-com-arroz da programação. Programação nada mais é do que controlar o fluxo de forma inteligente, para obter os resultados esperados. No próximo post vamos ver os dois controles mais simples, If e Else. Mas antes você precisa saber o que é

Condição Booleana e Operadores Booleanos

Uma condição booleana é uma expressão (lembram de expressões numéricas?) que resultam em um valor verdadeiro ou falso. Em C, como não existe um tipo booleano, a seguinte representação é usada:

  1. Se um número é diferente de 0, ele é considerado um valor verdadeiro;
  2. Se é igual a zero, é falso.

Isso significa que 3 + 2 é verdadeiro em C, mas 4 - 4 não.

Mas não é apenas dessa forma que fazemos operações booleanas. Existem outros operadores que servem para concatenar (ou modificar) condições booleanas. São os operadores booleanos.

Os operadores mais comuns são:

  1. Operador “E” (&&): Apenas diz que a expressão é verdadeira se as duas condições ao lado dele forem verdadeiras;
  2. Operador “Ou” inclusivo (||): Diz que uma expressão é verdadeira se uma das duas condições for verdadeira;
  3. Operador “Não” (!): Diz que uma condição é verdadeira se a condição à qual ele é aplicado for falsa e vice-versa.

Chega de teoria. Basicamente o que acontece é o seguinte:


2+3 && 5 é verdadeiro
2+3 && 0 é falso
2+3 && 4 é verdadeiro
2+3 || 0 é verdadeiro
2+3 || 1 é verdadeiro
2-2 || 1-1 é falso
!0 é verdadeiro
!1234567 é falso
(0 && 0) || 1 é verdadeiro

Notem que se você ler o que está escrito (sabendo que 0 é falso e os outros números são verdadeiros) fica bem intuitivo:


verdadeiro E verdadeiro é verdadeiro
verdadeiro E falso é falso
(falso E falso) ou verdadeiro é verdadeiro
NÃO falso é verdadeiro

Certo… tirando o último exemplo não é tão intuitivo assim mas você se acostuma.

Se você fizer todas as comparações possíveis usando duas condições e um operador você chega as seguintes tabelas:

Operador E (&&)
&& verdadeiro falso
verdadeiro verdadeiro falso
falso falso falso
Operador Ou (||)
|| verdadeiro falso
verdadeiro verdadeiro verdadeiro
falso verdadeiro falso
Operador Não (!)
! verdadeiro falso
falso verdadeiro

Existe um outro operador, chamado Ou Exclusivo. As expressões formadas por ele são verdadeiras se uma única condição (das duas em volta dele) for verdadeira. Se as duas forem verdadeiras ou falsas a expressão é falsa. Ele não costuma ser muito utilizado (só usei ele pra criptografia e mesmo assim era um operador um pouquinho diferente.

Posts Relacionados:

  • Dia C - Tuning
  • TRUE & TRUE == FALSE ?
  • YACP - Variáveis e Tipos Primitivos
  • YACP - Aprendendo a usar suas ferramentas
  • YACP (Yet Another C Primer)
  • YACP - Definindo seus próprios tipos
  • Acompanhe-nos por RSS, por Email ou via Twitter.

    YACP - Definindo seus próprios tipos

    C possui suporte a definição de novos tipos, o que torna o código muitas vezes mais legível e conciso. É possível criar esses novos tipos com typedef, struct, enum e union.

    Typedef

    Typedef serve para você mudar o nome de um tipo. Parece meio inútil mas na verdade ajuda muito com a semântica do código. Por exemplo, você decide que precisa de um tipo para guardar dinheiro. Float não serve, porque pode dar erros de precisão (faça o teste com R$0.30 . É uma dízima periódica em binário e pode gerar resultados estranhos). Então você percebe que se guardar o dinheiro contando os centavos (1 real = 100 centavos) você não vai ter problemas de precisão, pois você sabe que os postos de gasolina não podem colocar aquele terceiro digito depois da vírgula, pois não existe milésimo de real.

    Então você vai lá e declara dinheiro como int. Pronto. Seu sistema funciona e você fica feliz, mas chamar seu dinheiro de int é meio feio e não faz muito sentido semanticamente. Como resolver isso? Você cria um novo tipo chamado dinheiro com o typedef:

    Agora você armazena seu dinheiro em um tipo dinheiro. Muito mais legível, certo?

    Struct

    Struct é uma forma de você agrupar diversos tipos dentro de um único, e acessá-los de forma individual. Na minha opinião é o recurso mais poderoso para definição de novos tipos. É muito bom para juntar informações relevantes e colocá-las em um único lugar de facil manipulação.


    Para acessar qualquer tipo que esteja dentro da struct, use o operador “.”:


    E você usa como uma variável qualquer. Simples, não? Nem tanto. A sintaxe de declaração de uma variavel do tipo struct é meio chata. Você precisa dizer que aquilo é uma struct:


    É aqui que entra a verdadeira mágica do typedef. Bem agora que você estava quase acreditando que a melhor utilidade do typedef é mudar o nome de um tipo primitivo.

    Se você criar um tipo para representar “struct nome_struct”, fica bem mais fácil de declarar:


    Geralmente isso já é feito quando declaramos a struct:


    O resto é igual, mas você usa o nome real pra declarar.

    Enum

    Enum cria um tipo que pode apenas receber valores específicados durante a sua criação. Por exemplo:


    Mas como isso funciona? Cada posição recebe um valor (a partir de 0 e incrementando para cada posição) e se você colocar um valor que seja diferente desses o compilador gera um erro (ou talvez um warning). O problema é que esse nosso tipo não tem nome e sempre que você for usar você precisa colocar toda essa linha de código para declarar uma variavel:


    Novamente somos salvos pelo typedef:

    A parte mais legal é que aumenta a legibilidade do código, pois é muito mais elegante você verificar se o mês é janeiro do que verificar se ele é 0.

    Também é possível mudar o valor inicial do enum, atribuindo para o primeiro elemento um valor inteiro:

    Union

    Union é uma forma de você colocar diversos tipos em uma única variável. Um conceito interessante, mas que eu não vejo ser usado com muita frequência (Usei apenas uma vez e poderia ter feito de uma forma que evitasse isso). A sintaxe de declaração é bem semelhante à struct:

    Já declarei com o typedef, mas se não tivesse feito isso, teria que escrever union antes da declaração, como acontece com struct.

    Para utilizar, é basicamente como o struct. Possui apenas uma diferença (fundamental). Ela guarda apenas um dos valores por vez. Portanto, se você armazenar algo em m.i e depois em m.f, o valor de m.i será sobrescrito.


    E cuidado com a leitura dos valores. Se você gravar em m.f e ler com m.i, você receberá um valor que não apresenta sentido, pois o union não faz conversão entre os tipos que você coloca nele.


    A única vez que usei essa estrutura foi quando estava fazendo um leitor de arquivos .ini . Convencionei que poderiam existir apenas 3 tipos dentro do ini (string, inteiro e float) e criei um union para representar isso. Mesmo assim ainda precisava de 2 bits pra armazenar qual tipo eu tinha lido, porque o union não mantém essa informação.

    Posts Relacionados:

  • YACP - Variáveis e Tipos Primitivos
  • Linguagens de programação - C++
  • YACP - Condições Booleanas
  • YACP (Yet Another C Primer)
  • Linguagens de programação - Smalltalk
  • Guia Latex - Parte II: O Básico
  • Economizando com Software Livre
  • Acompanhe-nos por RSS, por Email ou via Twitter.

    Ultimamente tenho ouvido falar muito sobre desenvolvimento orientado a testes (Test Driven Development). Uma grande vantagem dessa forma de produzir código é que você consegue garantir a consistência do seu sistema. Quando possuímos bons casos de teste, caso um bug seja inserido durante o desenvolvimento, identificamos o problema assim que rodarmos os casos de teste. Ou seja, trocamos dezenas de horas de debug por alguns segundos (ou talvez minutos) de testes rodando. Assim você acaba produzindo software em um tempo muito menor e provavelmente a qualidade do seu sistema será melhor também.

    Infelizmente não encontrei nenhum framework que facilite este tipo de desenvolvimento em C, mas é simples produzir um script (em bash, perl, ruby, etc) que rode seus casos de teste sempre que você quiser. O grande segredo é deixar tudo automatizado (rodar os testes, checar as respostas e avisar onde um possível erro está ocorrendo), assim você não fica cansado de ficar compilando seus testes manualmente para ver se o sistema funciona.

    Algumas dicas para quem pretende desenvolver utilizando testes:

    • Escreva seus casos de teste antes de escrever suas funções. Isso força você a pensar melhor em casos que podem quebrar o código que você ainda vai escrever, além de diminuir o número de testes viesados (que contém os mesmos erros que seu código, por exemplo).
    • Idealmente, teste todas as suas funções. Na prática isso dificilmente acontece, mas é o ideal.
    • Teste como suas funções se integram com as outras.
    • Teste como seus módulos se integram com os outros.
    • Para cada bug (que inevitavelmente ocorrem), crie um caso de teste para evitar que esse bug seja reinserido em modificações futuras.
    • Testes são seus amigos. Não modifique-os apenas para ver todos os testes passando. Só modifique-os quando for realmente necessário.

    Mais informações: Wikipedia

    Com isso encerro a série Dia C. Espero que tenham gostado.

    Posts Relacionados:

  • Testes unitários em C++
  • Os criadores do Skype atacam novamente…
  • Séries
  • TDD para Ruby - Fibonacci
  • Digam adeus ao mouse
  • Game Developers Conference
  • Desenvolvimento de jogos com o Morphic
  • Acompanhe-nos por RSS, por Email ou via Twitter.

    YACP - Variáveis e Tipos Primitivos

    Variáveis

    Em C, uma variável pode ser visto de forma semelhante a que é vista em matemática. Ela é um lugar para você colocar valores. A diferença é que é um conceito mais restrito. Cada variável possui um tipo e apenas valores desse tipo podem ser colocados dentro da variável. A variável também possui limitações. Por exemplo, você não pode colocar um número real dentro de uma variável inteira. Se você fizer isso, o compilador poderá gerar um aviso, erro ou fará algum malabarismo para conseguir colocar dentro da variável. No caso, ele pegará apenas a arte inteira do número real.
    Além disso, as variáveis possuem um valor máximo e mínimo que pode ser colocado dentro delas. Qualquer valor entre esses dois extremos (inclusive) pode ser atribuído (colocado) a variável. Um valor fora desse limites geralmente irá produzir resultados estranhos, como uma multiplicação entre dois números positivos gerando um número negativo.

    Tipos Primitivos

    C possui diversos tipos de variável que já vem definidos e que você pode usar para compor outros. Esses são os tipos primitivos.

    Aqui vai uma tabela com os principais tipos primitivos e seus valores máximos e mínimos:

    Tipo Equivalente Valor Máximo Valor Mínimo Número de bytes em geral(processador de 32 bits)
    char Armazena o código de um caractere 127 -128 1
    int Armazena um inteiro 2147483647 -2147483648 4
    long Armazena um inteiro 2147483647 -2147483648 4
    float Número real com precisão simples ??? ??? 4
    double Número real com dupla precisão ??? ??? 8

    Além dos tipos primitivos, existem modificadores para o tamanho desses tipos:

    Modificador Efeito
    short Reduz pela metade o número de bytes do tipo primitivo
    long Dobra o número de bytes do tipo primitivo
    unsigned Define que o tipo apenas representará valores positivos
    signed Define que o tipo representará valores positivos e negativos

    Usando Variáveis

    Em C, para se utilizar uma variável, é necessário declará-la antes. Para isso, você deve também indicar de qual tipo que ela seja. A sintaxe é basicamente:

    Alguns exemplos:

    Em C, nomes (de qualquer coisa) podem possuir muitos caracteres (não pude encontrar um valor máximo, mas meus testes mostraram que até 10765 caracteres funciona), desde que não sejam começados por números (podem possuir números a partir do segundo caractere, mesmo que seja entre caracteres) ou operadores. Também não é permitido dar nomes iguais, mesmo que seja para coisas diferentes.

    Posts Relacionados:

  • YACP - Definindo seus próprios tipos
  • YACP - Condições Booleanas
  • Linguagens de programação - Smalltalk
  • Guia Latex - Parte II: O Básico
  • Guia Linux - Parte III: Programação
  • SNL - A Arte da Guerra
  • INC - Long Switch?
  • Acompanhe-nos por RSS, por Email ou via Twitter.


    Publicidade