quarta-feira, 8 de setembro de 2010

Você conhece Objective-C


Um post do Adriano Santos no seu blog Delphi To Delphi  chamou minha atenção, sobre uma fatia do mercado que percebo como pouco explorada atualmente no Brasil, os aplicativos para iPhone, iPad e iPod.

Procurando um pouco mais de informação sobre o assunto, deparei-me com a linguagem Objective-C, que para quem não sabe é a linguagem usada para criação de aplicações para os sistemas da Apple.

Um pouco de história 

O ObjC foi criado principalmente por Brad Cox e Tom Love no início da década de 1980 na empresa deles, a Stepstone. A principal descrição do Objective-C em sua forma original foi publicada no livro de Cox, Object-Oriented Programming, An Evolutionary Approach, de 1986.

Em 1988, a NeXT de Steve Jobs licenciou o Objective-C da StepStone (a dona da marca registrada Objective-C) e liberou sua própria versão do compilador e das bibliotecas da linguagem nas quais a interface do usuário e da estrutura NeXTstep eram baseadas. O sucesso das ferramentas e a qualidade do sistema operacional resultante ajudaram a NeXT a ocupar um nicho de provedor de workstations bastante popular.

O projeto GNU começou a trabalhar em seu clone livre do NeXTStep baseado no padrão OpenStep, o GNUstep. Dennis Glatting escreveu o primeiro runtime do gnu-objc em 1992, e Richard Stallman criou o segundo pouco depois. O runtime do GNU Objective-C que tem estado em uso desde 1993 é aquele desenvolvido por Kresten Krab Thorup, quando ele era estudante universitário na Dinamarca. Kresten também trabalhou para a NeXT por algum tempo.

Depois de adquirir a NeXT em 1996, a Apple usou o OPENSTEP como base para seu principal sistema operativo, o Mac OS X. Isto inclui o Objective-C e a ferramenta de desenvolvimento NeXT's Objective-C, o Project Builder (mais tarde substituído pelo Xcode), bem como sua ferramenta de projeto de interface, Interface Builder.

A maior parte da presente API Cocoa da Apple está baseada na interface de objetos OpenStep, e este é o mais significativo ambiente Objective-C sendo usado para desenvolvimento ativo.

O Objective-C é uma camada construída sobre a linguagem C e constitui-se num superconjunto estrito de C. Ou seja, é possível compilar qualquer programa C com um compilador Objective-C. O Objective-C deriva sua sintaxe tanto do C quanto do Smalltalk. A maior parte de sua sintaxe (incluindo pré-processamento, expressões, declaração e chamadas de funções) foi herdade do C, enquanto a sintaxe para os aspectos orientados a objetos foi criada para habilitar passagem de mensagens no estilo Smalltalk.

Ambiente de programação

Para programar em Objective-C, tal como em qualquer outra linguagem moderna, você precisa de um editor e um compilador. Ambos estão disponíveis gratuitamente em muitos dos sistemas operacionais atuais.

No MacOS X, você deve instalar os "Developer Tools" gratuitos da Apple, caso eles não estejam presentes no seu sistema. Essas ferramentas incluem dentre muitas outras coisas o compilador gcc e um ambiente de programação extremamente eficiente, denominado Xcode.

No Linux você já deve ter o gcc instalado, bem como muitos editores de texto (vi, pico, emacs). Você tambem pode utilizar algum ambiente de programação, como o KDevelop ou ferramentas GNUStep.

No Windows você pode instalar o compilador Objective-C que acompanha o sistema MinGW (http://www.mingw.org). Para escrever os códigos, qualquer editor de texto puro, como o Notepad, ou algum ambiente de programação devem servir.

Nos três sistemas, compilar um programa utilizando a linha de comando resume-se ao gcc (para projetos maiores costuma-se utilizar ferramentas como make, automake, etc), cujo formato geral de chamada é:

Portanto, chegamos a conclusão que por ser uma linguagem derivada do C, quem já possui algum conhecimento sobre esta linguagem larga na frente. 

Com o crescimento das vendas dos equipamentos da Apple no mercado brasileiro, creio que seja uma possibilidade a ser observada com carinho. 

Um agrande abraço e sucesso ao Adriano Santos o mais novo licenciado como desenvolvedor Apple®.

Fontes utilizadas neste post: 
http://pt.wikipedia.org/wiki/Objective-C
http://www.astro.iag.usp.br/~algol/computacao/ObjCtutorial.html

quarta-feira, 1 de setembro de 2010

Número por Extenso







Diante da necessidade de gerar valores por extenso, pesquisando na web, deparei-me com a excelente procedure abaixo, para Firebird. 

Ela não usa UDF´s e consegue gerar extenso para valores de até 8 (oito) quatrilhões.

Ela pode ignorar a geração do extenso dos centavos, para o caso de um extenso para cheques (basta atribuir 'N' ao segundo parâmetro).
 
Parabéns ao Emersom, o autor dessa "belezura" !!!


CREATE PROCEDURE EXTENSO (
    valor numeric(18,2),
    cents char(1))
returns (
    valorextenso varchar(250))
as
declare variable cmoeda varchar(10);
declare variable cmoedas varchar(10);
declare variable ccentavo varchar(10);
declare variable ccentavos varchar(10);
declare variable cmil varchar(12);
declare variable cmils varchar(12);
declare variable cmilhao varchar(12);
declare variable cmilhoes varchar(12);
declare variable cbilhao varchar(12);
declare variable cbilhoes varchar(12);
declare variable ctrilhao varchar(12);
declare variable ctrilhoes varchar(12);
declare variable cquatrilhao varchar(12);
declare variable cquatrilhoes varchar(12);
declare variable cvalor varchar(100);
declare variable nvalor smallint;
declare variable cvalorint varchar(100);
declare variable nvalorint integer;
declare variable nvalordec  numeric(6,3);
declare variable i smallint;
declare variable nconj integer;
declare variable cletra varchar(1);
declare variable caux varchar(200);
declare variable extensocentavos varchar(100);
declare variable separador varchar(3);
declare variable extensoconj varchar(150);
declare variable cdig1 varchar(10);
declare variable cdig2 varchar(10);
declare variable cdig3 varchar(10);
declare variable centenas char(108) = 'CENTO       DUZENTOS    TREZENTOS   QUATROCENTOSQUINHENTOS  SEISCENTOS  SETECENTOS  OITOCENTOS  NOVECENTOS  ';
declare variable dezenas char(79) = 'DEZ      VINTE    TRINTA   QUARENTA CINQUENTASESSENTA SETENTA  OITENTA  NOVENTA  ';
declare variable unidades char(54) = 'UM    DOIS  TRES  QUATROCINCO SEIS  SETE  OITO  NOVE  ';
declare variable unid10 char(81) = 'ONZE     DOZE     TREZE    QUATORZE QUINZE   DEZESSEISDEZESSETEDEZOITO  DEZENOVE ';
declare variable extensounidade varchar(12);
declare variable extensodezena varchar(12);
declare variable extensocentena varchar(12);
declare variable vlrextenso varchar(250);
begin
  if (cents is null) then cents = 'S';
  cents = UPPER(cents);
 
  -- poderia ter deixado esses valores fixos,
  -- mas preferi em variáveis
  cMil = 'MIL'; cMils = 'MIL';
  cMilhao = 'MILHÃO'; cMilhoes = 'MILHÕES';
  cBilhao = 'BILHÃO'; cBilhoes = 'BILHÕES';
  cTrilhao = 'TRILHÃO'; cTrilhoes = 'TRILHÕES';
  cQuatrilhao = 'QUATRILHÃO'; cQuatrilhoes = 'QUATRILHÕES';
  cMoeda = 'REAL'; cMoedas = 'REAIS';
  cCentavo = 'CENTAVO'; cCentavos = 'CENTAVOS';
  Separador = ' ';
 
  -- valores a serem utilizados para geração do extenso
  nValorInt = cast(valor/100*100 as integer);
  nValorDec = (Valor - Cast(nValorInt as numeric(18,3))) / 10;
  cAux = Cast(nValorDec as varchar(100));

  cValorInt = Cast(nValorInt as varchar(100)) || Substring(cAux from 3 for 3);
 
  -- inverto o número. assim fica mais fácil trabalhar
  -- pois não haverá necessidade de UDF's
  cLetra = Substring(cValorInt from 1 for 1);
  cAux = cValorInt;
  cValorInt = '';
  while (cAux <> '') do
  begin
    cValorInt = (cLetra || cValorInt);
    cAux = Substring(cAux from 2 for 100);
    cLetra = Substring(cAux from 1 for 1);
    if (cLetra = '') then cLetra = ' ';
  end
 
  -- obtenho os subconjuntos de números, de 3 em 3,
  -- para formar o extenso, que poderá chegar aos quatrilhões
  nConj = 1;
  extensocentavos = '';
  vlrextenso = '';
 
  if (Valor <> 0) then
  begin
    while (cValorInt <> '') do
    begin
      cValor = '';
      i = 1;
      while (i <= 3) do
      begin
        cLetra = Substring(cValorInt from 1 for 1);
        if (cLetra = '') then cLetra = ' ';
        cValor = (cLetra || cValor);
        cValorInt = Substring(cValorInt from 2 for 100);
        i = (i + 1);
      end
 
      nValor = Cast(cValor as smallint);
 
      cDig1 = Substring(cValor from 1 for 1);
      cDig2 = Substring(cValor from 2 for 1);
      cDig3 = Substring(cValor from 3 for 1);
 
      extensounidade = '';
      extensodezena = '';
      extensocentena = '';
 
      -- obtenho o extenso da unidade
      if (cDig3 > '0') then
      begin
        cAux = cast((cast(cDig3 as integer) * 6 - 5) as varchar(3));
        cAux = 'select cast(Substring(''' || unidades || ''' from ' || cAux || ' for 6) as varchar(12)) from rdb$database';
        execute statement cAux into :extensounidade;
      end
 
      -- obtenho o extenso da dezena
      if (cDig2 > '0') then
      begin
        if ((cDig3 > '0') and (cDig2 = '1')) then
        begin
          extensounidade = '';
          cAux = unid10 || ''' from ' || cast((cast(cDig3 as integer) * 9 - 8) as varchar(3));
        end
        else
          cAux = dezenas || ''' from ' || cast((cast(cDig2 as integer) * 9 - 8) as varchar(3));
        cAux = 'select cast(Substring(''' || cAux || ' for 9) as varchar(12)) from rdb$database';
        execute statement cAux into :extensodezena;
      end
 
      -- obtenho o extenso da centena
      if (cDig1 > '0') then
      begin
        if (nValor = 100) then
          extensocentena = 'CEM';
        else
        begin
          cAux = cast((cast(cDig1 as integer) * 12 - 11) as varchar(3));
          cAux = 'select cast(Substring(''' || centenas || ''' from ' || cAux || ' for 12) as varchar(12)) from rdb$database';
          execute statement cAux into :extensocentena;
        end
      end
 
      -- faço a montagem do extenso do conjunto
      if (extensounidade <> '') then
        extensoconj = extensounidade;
      else
        extensoconj = '';
 
      if (extensodezena <> '') then
      begin
        if (extensoconj <> '') then
          extensoconj = extensodezena || ' E ' || extensoconj;
        else
          extensoconj = extensodezena;
      end
 
      if (extensocentena <> '') then
      begin
        if (extensoconj <> '') then
          extensoconj = extensocentena || ' E ' || extensoconj;
        else
          extensoconj = extensocentena;
      end
 
      -- adiciono os devidos sufixos de cada conjunto
      if (nValor > 0) then
      begin
        if (nConj = 1) then -- centavos
        begin
          if (nValor > 1) then
            extensoconj = extensoconj || ' ' ||ccentavos;
          else
            extensoconj = extensoconj || ' ' || ccentavo;
        end
 
        -- obs.: o conjunto 2 não precisa ser avaliado, pois
        --       nele NÃO há necessidade de acrescentar sufixo
 
        if (nConj = 3) then -- milhares
        begin
          if (nValor > 1) then
            extensoconj = extensoconj || ' ' || cMils;
          else
            extensoconj = extensoconj || ' ' || cMil;
        end
        else
        if (nConj = 4) then -- milhoes
        begin
        if (nValor > 1) then
            extensoconj = extensoconj || ' ' || cMilhoes;
          else
            extensoconj = extensoconj || ' ' || cMilhao;
        end
        else
        if (nConj = 5) then -- bilhoes
        begin
          if (nValor > 1) then
            extensoconj = extensoconj || ' ' || cBilhoes;
          else
            extensoconj = extensoconj || ' ' || cBilhao;
        end
        else
        if (nConj = 6) then -- trilhoes
        begin
          if (nValor > 1) then
            extensoconj = extensoconj || ' ' || cTrilhoes;
          else
            extensoconj = extensoconj || ' ' || cTrilhao;
        end
        else
        if (nConj = 7) then -- quatrilhoes
        begin
          if (nValor > 1) then
            extensoconj = extensoconj || ' ' || cQuatrilhoes;
          else
            extensoconj = extensoconj || ' ' || cQuatrilhao;
        end
 
        if ((vlrextenso = '') and (nConj > 3)) then
          extensoconj = extensoconj || ' DE ';
      end
 
      -- avalio qual será o separador de conjuntos
      if (nConj < 4) then
        Separador = ' E ';
      else
        Separador = ', ';
 
      -- gero o extenso dos 'inteiros' e dos centavos
      if (nConj = 1) then -- centavos
        extensocentavos = extensoconj;
      else
      if (extensoconj <> '') then
      begin
        if (vlrextenso <> '') then
          vlrextenso = extensoconj || Separador || vlrextenso;
        else
          vlrextenso = extensoconj;
      end
 
      nConj = nConj + 1;
    end
 
    -- depois de tudo avaliado...
    -- acrescento a moeda
    if (nvalorint > 0) then
    begin
      if (nvalorint > 1) then
        vlrextenso = vlrextenso || ' ' || cmoedas;
      else
        vlrextenso = vlrextenso || ' ' || cmoeda;
    end
 
    -- monto o extenso completo: inteiros mais os centavos.
    -- obs.: a inclusão dos centavos é controlada pela variável
    -- 'cents'. fiz assim pois pode ser uma geração de extenso
    -- para cheques, que não destacam os centavos no extenso
    if ((extensocentavos <> '') and (cents = 'S')) then
    begin
      if (vlrextenso <> '') then
        vlrextenso = vlrextenso || ' E ' || extensocentavos;
      else
        vlrextenso = extensocentavos;
    end
  
    -- limpo a variavel de retorno, pois ainda preciso trabalhar os 'espaços'
    valorextenso = '';
 
    -- retiro os espacos desnecessários e populo a variável de retorno.
    -- obs.: fiz com while pra não precisar de UDF's
    cLetra = Substring(vlrextenso from 1 for 1);
    cAux = '';
    while (vlrextenso <> '') do
    begin
      cLetra = Substring(vlrextenso from 1 for 1);
      vlrextenso = Substring(vlrextenso from 2 for 250);
      if ((cLetra <> ' ') or ((cLetra = ' ') and (cAux <> ' ')))  then
        valorextenso = valorextenso || cLetra;
      cAux = cLetra;
    end
  end
  else
    valorextenso = 'ZERO';
 
  -- exibe o resultado
  suspend;
end

-----

Veja o Post Original em http://www.firebase.com.br/fb/artigo.php?id=2078