Mini Ada 95 Manual



Ada 95






CONTEUDO
01 O que é Ada?
02 Estrutura Básica de Um Programa em Ada.
03 Palavras reservadas.
04 Declarações de Bibliotecas.
05 Programa Alô Mundo.
06 Cláusula Use.
07 Declaração de Variáveis.
08 Get.
09 Comentários.
10 IF.
11 For.
12 While.
13 Loop.
14 Case.
15 Null.
16 New_Line.
17 Strings.
18 Put_Line.
19 Caracters.
20 Exemplo de um pequeno programa.
21 Tipos Pré-definidos em Ada.
22 Conversão de tipos.
23 Arrays.
24 Procedimentos e Funções.
25 Arquivo de "Corpo" e "Fonte".
26 Manipulando Arquivos.
27 Unbounded Strings.
28 Ainda Strings.
29 Novos Tipos e Subtipos.
30 Registros.
31 Gerador de Números Aleatórios.
32 Números de ponto flutuante e ponto fixo.
33 Goto.
34 Access Type.
35 Generics.
36 Maiúsculas e Minúsculas.
37 Ada.Numerics.Elementary_Functions;
38 Números Complexos.
39 Exceptions.
40 Importando funções de outras linguagens.
41 Sites de Ada.
42 Manuais e Compilador.

1  O que é Ada?

Ada é uma linguagem de programação de alto nível, imperativa, tipicamente compilada (embora haja interpretadores) e baseada em Pascal, que foi criada através de um concurso realizado pelo DoD (U. S. Departament of Defense) sendo o principal projetista o francês Jean Ichbiah. Tal concurso foi realizado para por ordem na situação em que o DoD se encontrava pois eles em 1974 usavam cerca de 450 linguagens ou dialetos de programação e não havia uma linguagem adequada. A linguagem foi primeiramente padronizada em 1983 pelo ANSI e em 1985 pela ISO (Organização Internacional de Padronização) e em 1995 a ISO padronizou uma versão melhorada conhecida como Ada 95. Ada 95 foi a primeira linguagem de programação orientada ao objeto padronizada internacionalmente.
O nome Ada é homenagem a condessa de Lovelace, Augusta Ada Byron, filha de Lord Byron e que trabalhou com Charles Babage sendo considerada a primeira programadora de computadores da Hístoria. Veja que o correto é Ada e não ADA.

2  Estrutura Básica de Um Programa em Ada.

--Declaracoes de bibliotecas
Procedure nome_do_programa is
--Declaracoes de variaveis
begin
--Corpo do programa
end nome_do_programa;

Ada é uma linguagem não sensível a case, ou seja, tanto faz escrever em maiusculo ou minusculo.

3  Palavras reservadas.

De acordo com o "Ada 95 Reference Manual" essas são as palavras reservadas em Ada. Tanto faz letras maiúsculas ou minúsculas. Umas 47 1 dessas são abordadas nesse manual ou são de uso óbvio.
abort abs abstract accept access aliased all
and array at begin body case constant
declare delay delta digits do else elsif
end entry exception exit for function generic
goto if in is limited loop mod
new not null of or others out
package pragma private procedure protected raise range
record rem renames requeue return reverse select
separate subype tagged task terminate then type
untill use when while with xor

4  Declarações de Bibliotecas

Como ocorre na maioria das linguagens modernas os procedimentos de entrada e saída não são definidos na linguagem propriamente dita mas sim em bibliotecas especiais. São muito importantes em Ada as seguintes bibliotecas: Ada.Text_IO (ou simplesmente Text_IO), Ada.Integer_Text_IO e Ada.Float_Text_IO que servem para fornecer procedimentos de entrada e saída e para trabalhar com textos, números inteiros e números reais de ponto flutuante respectivamente. Para declarar a biblioteca Ada.Text_IO basta fazer assim
With Ada.Text_IO;

5  Programa Alô Mundo

--Programa Alo Mundo
With Ada.Text_IO;
Procedure AloMundo is
begin
       Ada.Text_IO.Put_Line("Alo Brasil!!!");
       Ada.Text_IO.Put_Line("Alo Mundo!!!");
end AloMundo;

6  Cláusula Use

O comando Put_Line pertence a biblioteca Ada.Text_IO. Usando Use não precisamos reescrever o nome da biblioteca cada vez e assim o programa Alô Mundo fica:
--Programa Alo Mundo
With Ada.Text_IO; Use Ada.Text_IO;
Procedure AloMundo is
begin
       Put_Line("Alo Brasil!!!");
       Put_Line("Alo Mundo!!!");
end AloMundo;
Mas é preciso cuidado ao usarmos o Use para evitar que em grandes programas não saibamos mais de que biblioteca vem o comando ou procedimento.

7  Declaração de Variaveis

Para declarar a variável x como sendo float é só fazer:
x : float;
Para declarar a variável y como sendo do tipo interio e atribuir o valor 5 e a constante Pi de valor 3.1415 basta fazer:
y :integer := 5; Pi :constant float :=3.1415;
As declarações em geral devem ficar entre o cabeçalho do programa e o begin mas o mesmo pode ser feito para funções ou procedimentos sendo nesse caso variaveis locais e não globais.

8  Get

A biblioteca Ada.Text_IO define o Put como sendo o comando padrão de saída assim como é o PRINT do BASIC ou o Write do Pascal. Já o comando de entrada padrão é o Get. Para fazer o Get ler do teclado e por numa variável x basta fazer:
Get(x);
Exemplo:
With Ada.Integer_Text_IO, Ada.Text_IO;
Use Ada.Integer_Text_IO, Ada.Text_IO;
Procedure mostraget is
       x : natural;
begin
       Put_Line("Entre um numero natural");
       Get(x);
       Put_Line("O numero que voce entrou foi: ");
       Put(x);
end mostraget;

9  Comentários

Comentários são anotações feitas dentro do próprio código do programa que servem para tornar o mesmo código mais claro e fácil de ser entendido ou ainda para alertar para algo que se deseja ser enfatizado. Um bom programa deve possuir muitos comentários. Os comentários não são lidos pelo compilador. Em Ada tudo o que estiver a direita de -- não será lido pelo compilador. Ex:
--Isso e' um comentario.
Esse é o unico tipo de comentário existente em Ada. Não existe nada análogo ao /* e */ do C e ao { e } ou (* e *) do Pascal.

10  IF

O if(se) pode ser usado assim:
if condicao then
       sequencia de comandos (executada se a condição é verdadeira)
else
       outra sequencia de comandos (executada se a condição é falsa)
end if ;
Ex:
if x > 4 and x < 10 then
       y:=x+2;
       x:=3;
else
       y:=0;
end if;
Uma outra estrutura mais simples e bastante comum é
if condicao then
       sequencia de comandos (executada se a condição é verdadeira)
end if;
O if também pode ser usado com o "elsif" permitindo assim fazer estruturas bem complexas de forma simples
if condicao1 then
       sequencia de comandos1
elsif condicao2 then
       sequencia de comandos2
elsif condicao3 then
       sequencia de comandos3
       .
       .
else
       sequencia de comandos
end if;
Ao contrario do Pascal você não precisa usar begin e end caso haja mais de um comando. Você também não precisa usar paranteses quando usar mais de um operador logico tipo and, or, etc, na condição do if, a não ser que haja ambiguidade.

11  For

O for (para) pode ser usado da seguinte forma: (Isso é um meio exemplo)
for a in 1..10 loop
        sequencia de comandos
end loop;
a não precisa estar declarado a menos que você o use explicitamente não só como indice. Esse meio exemplo executa uma sequencia de comandos para a=1 até a=10. Para fazer na ordem contraria basta fazer:
for a in reverse 1..10 loop

12  While

O While (enquanto) é usado da seguinte forma: (Outro meio exemplo)
while a /=3,e b < =15,e c=3.0 loop
        sequencia de comandos
end loop;
onde "/=" quer dizer diferente.

13  Loop

O Loop é usado para repetições infinitas. (Meio exemplo)
loop
       sequencia de comandos
end loop;
Mas é claro que podemos parar, veja:
loop
        sequencia de comandos
exit when a=3;
        outra sequencia de comandos
end loop;
No exemplo acima o loop irá parar quando a for igual a 3. A primeira sequencia de comandos será executada quando for 3 mas a outra posterior ao exit não. Um aspecto agradável em Ada é que todas as repitições terminam em end loop; o que torna fácil modifica-las de uma para outra sem jamais confundir com um if ou case por exemplo.

14  Case

O case (caso) pode ser usado assim: (novamente um meio exemplo)
case x is
        when 1 = > executa alguma coisa
        when 2 = > executa outra coisa
       when 3..10 = > executa outra coisa ainda
       when others = > Put_Line("Oi");
end case;
Nesse meio exemplo, se x for 1 vai executar alguma coisa, se for 2 outra, se estiver entre 3 e 10 incluindo 3 e 10 vai executar outra coisa ainda e irá escrever "Oi" caso não seja nenhum desses.

15  Null

Quando você não quer fazer nada use null. Ex:
Procedure nulo is
begin
null
end nulo;

16  New_Line

Você usa New_Line; para mudar de linha na saída padrão.

17  Strings

Strings são arrays (sequencias) de caracteres que você pode usar para conter textos. Você delimita uma string usando " e ", Ex:
Put("Isso aqui e' uma string"); ;
Você também pode criar variaveis do tipo string como no exemplo de declaração abaixo.
menssagem : string(1..9) :="Oi gente!";

18  Put_Line

Tem o mesmo efeito de Put seguido de New_Line mas só pode ser usado para strings.

19  Caracteres

Exemplo de uma declaração: x : Character :='w'; Note que usa ' e não " e " como no caso das strings.

20  Exemplo de um pequeno programa

--Esse e' um programa que escreve a tabuada.
With Ada.Text_IO; Use Ada.Text_IO;
With Ada.Integer_Text_IO; Use Ada.Integer_Text_IO;
Procedure Tabuada is
        A, B: Integer;
begin
for A in 1 .. 10 loop
        New_Line;
        Put(" Tabuada do ");
        Put(A);
        New_Line;
        New_Line;
        for B in 1 .. 10 loop
                Put(A);
                Put(" X");
                Put(B);
                Put(" =");
                Put(A*B);
                New_Line;
        end loop;
        New_Line;
end loop;
end Tabuada;

21  Tipos Pré-definidos em Ada

Integer:Valores inteiros de no mínimo -32767..32767 ou seja (-2**15+1..2**15-1). Long_Integer: Valores inteiros de no mínimo -2147483647..2147483647 ou seja (-2**31+1..2**31-1).
O RM sugere a existencia dos tipos Long_Long_Integer, Short_Integer, Short_Short_Integer, etc, mas não obriga a existencia deles e deixa para as implementações determinarem o range. Apenas diz que que o que tiver Long deve ter um range maior, o que tiver Short menor, etc. O tipo integer admite basicamente as operações +, -, *, /, abs, mod, ** (potencia), entre outras. Os operadores de comparação admitidos são: =, /= (diferente), < , > , < =, > =.
Natural: É um subtipo do Integer que não possui números negativos.
Positive: É um subtipo do Integer que não possui zero e números negativos.
Float: Tipo real de ponto flutuante de no mínimo -10.0**(4D)..10.0**(4D) onde D é a precisão decimal. O RM sugere o Long_Float com D=11 no mínimo e no que diz respeito aos Long_Long_Float, Short_Float, etc, se existirem a situação é a mesma da do Integer. As operações admitidas são +, -, *, /, abs, ** mas essa última deve ter o segundo nmero (expoente) inteiro embora o resultado seja float. Os operadores de comparação são os mesmos do interger.
Character: Assume os valores de caracteres correspondente aos 256 valores de codigo do Row00 também conhecido como latim 1. Os operadores de comparação são os mesmos.
String: É um array(lista) de Characters.
Boolean: Assume os valores true e false. Os operadores de comparação são os mesmos já citados. Permite as operações lógicas and, or, xor(or exclusivo), not.
Existe diversas bibliotecas padrões que podem ampliar o quadro visto. A Ada.Numerics.Elementary_Functions permite fazer as operações Sin, Cos, Tan, ArcSin, ArcCos, ArcTan, SinH, CosH, Exp, Log, Sqrt com o tipo Float além definir Pi e e, etc. A Ada.Calendar define o tipo Time com subtipos tais como Year_number, etc. Você também pode criar seus próprios tipos.

22  Conversão de Tipos

Sendo uma linguagem baseada em Pascal, Ada conserva a caracteristica de ser fortemente tipada. Suponha que você tenha duas variaveis a e b declaradas assim:
a : integer;
b : float;
Para fazer a receber o valor de b você deve fazer:
a := integer(b); --O valor sera arredondado.
Já para fazer b receber o valor de a você deve fazer:
b := float(a);
A expressão a := b (analoga a uma permitida em linguagem C) ou mesmo a mais inocente b := a (permitida em Pascal) são completamentes erradas em Ada. Ada permite conversão de tipos a vontade desde que o programador demostre que realmente sabe o que esta fazendo e que portanto não é um erro.

23  Arrays

Os arrays são uma maneira de se armazenar coisas na forma de listas, tabelas, etc. Veja um exemplo de um programinha usando arrays:
With Text_IO; Use Text_IO;
Procedure usando_array is
       vogal : array(1 .. 5) of character;
begin
       vogal(1):='a';
       vogal(2):='e';
       vogal(3):='i';
       vogal(4):='o';
       vogal(5):='u';
       for i in 1 .. 5 loop
               Put(vogal(i));
       end loop;
end usando_array;
Agora para declarar um um array bi-dimensional você pode fazer assim
tabela: array(1 .. 10, 1 .. 10) of integer;
Nesse caso, para fazer o elemento de posição 2,3 assumir o valor 5 bastaria fazer
        tabela(2,3):=5; 

24  Procedimentos e Funções

Procedimentos e funções são pedaçoes de programa que ficam separados do corpo principal do programa e servem para evitar demasiada repitição de código semelhante, para tornar o programa mais claro, etc. A declaração de um procedimento ou função deve ficar entre o procedure e o begin do procedimento principal, i.e., do programa. Veja um exemplo de declaração de um procedimento:
Procedure escreve_oiz_gente_dez_vezes is
begin
for i in 1..10 loop
        Put_Line("Oi gente");
end loop;
end escreve_oi_gente_dez_vezes;
No corpo do programa principal, cada vez que aparecer o comando escreve_oi_gente_dez_vezes; Esse procedimento será executado. Observe que não preciso declarar aqui a biblioteca Text_IO uma vez que a mesma já esta supostamente declarada no programa principal. As funções são como os procedimentos mas diferem desses por sempre retornarem um valor e poderem ser postas dentro de expressôes usadas em formulas ou ainda dentro de condições. ex:
Function fatorial(n: integer) return integer is
       numero: integer;
begin
       numero:=n;
       resultado:=1;
       while numero /= 1 loop
                resultado:=resultado*numero;
                numero:=numero-1;
       end loop;
       return resultado;
end fatorial;
Observe que nesse exemplo numero é uma variável local enquanto resultado é uma variável global já declarada no programa principal. O comando "return resultado;" faz com que a função de por saida a variável resultado. Eu poderia escrever "in" entre os "n:" e o "integer" na declaração da função mas isso não é preciso uma vez que funcões só recebem parametros de entrada que não podem ser modificados dentro da função, dai a nescessidade de criar a variável "numero" aparentemente redundante. No corpo do programa para calcular o fatorial de x basta fazer:
    fatorial(x); 

Podemos até mesmo fazer:
    a:= 3 + fatorial(b); 

Nesse outro exemplo abaixo vamos por uma função na condição de um if:
Function par(n: in integer) return boolean is
       resultado:boolean;
begin
if n mod 2 = 0 then resultado:=true; else
       resultado:=false;
end if;
return resultado;
end par;
Dai no corpo do programa podemos escrever:
if par(x)=true then
       Put_Line("Esse numero e' par");
else
       Put_Line("Esse numero e' impar");
end if;
Observe que nesse exemplo acima eu usei o "in" e nesse caso resultado esta como variável local. Para a função isso não tem importancia nenhuma, ou melhor, esse é o jeito mais correto.

25  Arquivos de Corpo e Fonte

Em Ada os programas não precisam estar contidos em um único arquivo. Existem dois tipos de arquivos. Os de "corpo" (ou "body") e os de "fonte" (ou "source"). Os primeiros contem os procedimentos e funções que constituem um programa. São geralmente identificados pela extensão .ada ou .adb (Ada Body) e correspondem aos arquivos .c em linguagem C. Os arquivos de fonte são identificados em geral com a extensão .ads (Ada Source) e correspondem aos .h do C. O compilador Gnat usa as extensões .adb e .ads enquanto outras implementações poderão usar outras extensões. Vamos ilustrar o uso desses arquivos criando um package (pacote). Crie um arquivo de texto com o nome cumprimentos.adb e com seguinte conteúdo.
With Text_IO; Use Text_IO;
Package body Cumprimentos is
       Procedure Bom_Dia is
       begin
               Put_Line("Bom dia!");
       end Bom_Dia;
       Procedure Boa_Tarde is
       begin
               Put_Line("Boa tarde!");
       end Boa_Tarde;
       Procedure Boa_Noite is
       begin
               Put_Line("Boa noite!");
       end Boa_Noite;
end Cumprimentos;
Pronto! Criamos o pacote cumprimentos contendo os procedimentos Bom_dia, Boa_Tarde e Boa_Noite. Agora precisamos criar um arquivo de "source" chamado cumprimentos.ads. Ele conterá uma relação das coisas contidas no pacote de "body". Ponha o seguinte:
Package Cumprimentos is
       Procedure bom_dia;
       Procedure boa_tarde;
       Procedure boa_noite;
end Cumprimentos;
Observe que no arquivo "source" vai a relação dos procedimentos e funções contidos no arquivo de "body". Cada um delaração indentica a que vai no arquivo "body" a menos do "is" que é substituido por ";". Os arquivos "source" também podem conter declarações de variáveis. Agora podemos criar um programa que chame esse pacote e use esses procedimentos. Considere por exemplo o programa saudacao.adb
With Cumprimentos;
Procedure saudacao is
begin
        Cumprimentos.bom_dia;
        Cumprimentos.boa_tarde;
        Cumprimentos.boa_noite;
end saudacao;
Ou se você preferir usar o "Use"
With Cumprimentos; Use Cumprimentos;
Procedure saudacao is
begin
       bom_dia;
       boa_tarde;
       boa_noite;
end saudacao;
Daí basta compilar dando gnatmake saudacao.adb (ou as vezes gnat make saudacao.adb). O gnatmake é esperto! Basta manter os três arquivos no mesmo diretório que ele faz o resto. Agora é só executar o programa saudacao.
No que diz respeito a declaração de variáveis (quase sempre nescessária) é melhor evitar o conceito de global e local e se ater ao de visível e não visível.
As variáveis declaradas no programa principal NÃO são visíveis para os pacotes. Caso o programa principal compartilhe variaveis com algum pacote tais variaveis devem ser declaradas no referido pacote.
As variáveis declaradas nos arquivos .ads são visíveis para o programa principal e podem ser visíveis para outros pacotes desde que esses outros pacotes nos arquivos de corpo invoquem o primeiro pacote usndo o "use".
Você não deve criar arquivo .ads para o programa principal uma vez que o GnatMake não irá saber quem é o programa principal, tratará o programa principal como um pacote e irá compilar cada pacote semparadamente (claro que Ada suporta compilação em separado) sem linkar ninguém.

26  Manipulando Arquivos

A manipulação de arquivos de texto em Ada 95 é muito simples. Primeiro devemos declarar uma variável que representará o arquivo perante o programa.
Arquivo_1:File_Type;

Se o arquivo que vamos trabalhar ainda não existe nos o criamos
create(arquivo_1,out_file,"Arquivo_1.txt");

A linha acima cria um arquivo associado a variável arquivo_1 e cujo nome perante o sistema operacional (seja ele qual for) será "Arquivo_1.txt".
Se o arquivo já existir basta abri-lo.
open(arquivo_1,in_file,"Arquivo_1.txt");

Mas atenção, se o arquivo já existir e você usar o create o arquivo será sobrescrito.
Para escrever algo no arquivo usamos o Put fazendo referencia a variável
Pute{arquivo_1,"Isso escreve Alo Mundo!!!!");

Se quizer mudar de linha após ter escrito uma string use o Put_Line. Se quizer só mudar de linha então faça
New_line(arquivo_1);

Para ler algo do arquivo usamos o Get também com referencia ao arquivo
get(arquivo_1,Variavel);

No exemplo acima o Variavel é uma variável qualquer que lê um dado do seu tipo do arquivo. No fim devemos fechar o arquivo.
close(arquivo_1);

27  Unbounded Strings

Unbouded Strings são um tipo de string que não possui um tamanho determinado. Para lidar com elas podemos usar o pacote "Ada.Strings.Unbounded".
with Ada.Strings.Unbounded; Use Ada.Strings.Unbounded;

Podemos declarar Unbounded Strings como fazemos como qualquer outro tipo de variável.
Frase_Verdadeira : Unbounded_String;

Dai no corpo do programa podemos atribuir um valor para essa unbouded string
Frase_Verdadeira :=To_Unbounded_String("Ada e' legal!!!");

Nesse exemplo fizemos uso da função To_Unbounded_String que pega uma string e converte para Unbounded.
Ada não possui procedimentos de entrada e saída para as unbounded strings de modo que isso precisa ser feito usando strings comuns. Veja no exemplo abaixo como entramos strings de tamanho desconhecido a partir do teclado usando strings comuns.
With text_IO; Use text_IO;
With Ada.Integer_Text_IO; Use Ada.Integer_Text_IO;
Procedure entre_seu_nome is
        n: natural;
        stringona: string(1..100);
begin
        Put_Line(" Entre o seu nome. (Ate 100 caracteres)");
        Get_Line(stringona,n);
        Put_Line("O numero de letras de seu nome e':");
        Put(n);
        New_Line;
        Put_Line("Seu nome e:");
        Put(stringona(1..n));
        Put_Line("Seu nome de traz para frente fica:");
        for I in reverse 1..N loop
                Put(Stringona(I));
        end loop;
end entre_seu_nome;
Nós fomos capazes de entrar seu nome graças ao uso do procedimento Get_Line. Ele lê do teclado preenchendo uma dada string e fornece também o numero de caracteres. É mais ou menos analogo a função gets do C mas é superior pois de cara te dá o tamanho da string entrada. Observe que aqui não se trata de Unbounded Strings mas sim de Strings de tamanho fixo. A idéia é criar strings que sejam suficientemente grandes para poderem receber qualquer tamanho de Unbounded String.
Agora façamos algo parecido já usando as Unbounded Strings.
With Text_IO, Ada.Integer_Text_IO, Ada.Strings.Unbounded;
Use Text_IO, Ada.Integer_Text_IO, Ada.Strings.Unbounded;
Procedure entre_seu_nome2 is
        n: natural;
        stringona: string(1..100);
        Stringona2,Stringona3: Unbounded_String;
begin
        Stringona2:=To_Unbounded_String("Ola ");
        Put_Line(" Entre o seu nome. (Ate 100 caracteres)");
        Get_Line(stringona,n);
        Stringona3:=To_Unbounded_String(Stringona(1..N));
        Put(To_String(Stringona2));
        Put_Line(To_String(Stringona3));
end entre_seu_nome2;
Nesse exemplo acima usamos a função To_String para converter de Unbounded para String.
Finalmente uma situação bastante tipica. Você quer criar um arquivo mas quer que a pessoa (usuário do programa) escolha o nome do arquivo. No exemplo que segue cria-se o arquivo e escreve-se uma menssagem nele.
With Text_IO, Ada.Integer_Text_IO, Ada.Strings.Unbounded;
Use Text_IO, Ada.Integer_Text_IO, Ada.Strings.Unbounded;
Procedure nome_de_arquivos is
        n: natural;
        nome:string(1..100);
        nome2:unbounded_string;
        arquivo:File_Type;
begin
        Put_Line("Entre o nome do arquivo");
        Get_Line(nome,n);
        nome2:=To_Unbounded_String(nome(1..N));
        create(arquivo,out_file,to_string(nome2));
        Put_Line(arquivo,"Alo gente!!!");
        close(arquivo);
end nome_de_arquivos;
Mas você também pode fazer isso sem usar o tipo unbounded.
With Text_IO, Ada.Integer_Text_IO;
Use Text_IO, Ada.Integer_Text_IO;
Procedure nome_de_arquivos2 is
        n: natural;
        nome:string(1..100);
        arquivo:File_Type;
begin
        Put_Line("Entre o nome do arquivo");
        Get_Line(nome,n);
        create(arquivo,out_file,nome(1..N));
        Put_Line(arquivo,"Alo gente!!!");
        close(arquivo);
end nome_de_arquivos2;
Enfim, o tipo unbounded_string é uma opção a mais para te ajudar a lidar com essas strings de tamanho indefinido, embora haja outras maneiras de lidar com elas.

28  Ainda Strings

Ada permite que concatenemos strings usando o caracter &. O seguinte código
Put_Line("Alo " & "voce!!");

gera na saída
Alo voce!!

O programa abaixo ilustra isso inclusive usando o atributo 'Image que representa uma dada variável como se fosse uma string.
With Text_IO, Ada.Integer_Text_IO;
Use Text_IO, Ada.Integer_Text_IO;
Procedure idade is
        Idade, N:Natural;
        Nome:String(1..90);
begin
       Put_Line("Qual e'" & " seu nome?");
       Get_Line(Nome,n);
       Put_Line("Quantos anos voce tem?");
       Get(Idade);
       Put("Voce " & Nome(1..N) & " tem " & Natural'Image(idade) & " anos.");
       New_Line;
       end idade;
Se idade for um natural igual a 25 Natural'Image(idade) será a string " 25".

29  Novos Tipos e Subtipos

Para criar um novo tipos basta usar na declaração do programa o comando type. Dai você coloca o nome do tipo seguindo de "is" e ai você coloca a especificação do tipo. Ex:
type segundo is range 1 .. 60;
type sinal is (verde, amarelo, vermelho);

O tipo sinal que declaramos é um exemplo dos chamados tipos de enumeração. O tipo pré-definido boolean também é desse tipo.
Já Subtipos são tipos que são constituidos de uma parte dos elementos de outro tipo.
Veja o programa a seguir.
With Ada.Text_IO; Use Ada.Text_IO;
With Ada.Integer_Text_IO; Use Ada.Integer_Text_IO;
Procedure Mostra_Tipos is
      type Dia_Do_Ano is range 1 .. 365;
      type Ano is range 1_900 .. 2_100;
      type Dia_Da_Semana is (Domingo,Segunda,Terca,Quarta,Quinta,Sexta,Sabado);
      subtype Dia_Util is Dia_Da_Semana range Segunda .. Sexta;
      type Quase_Booleano is (True, False, I_Dont_Know);
        N:Dia_Do_Ano;
        Folga: Dia_Da_Semana;
        Esse_Programa_funciona: Quase_Booleano;
begin
        N:=2;
        Folga:=Terca;
        Esse_Programa_funciona:=I_Dont_Know;
end Mostra_Tipos;

30  Registros

Registros são tipos formados pela união de outros tipos mais simples. Ex:
type Aluno is record
        Nome:Unbounded_String;
        Idade:integer range 1 .. 99;
        Nota:integer range 0 .. 100;
end record ;
Depois podemos criar uma variável chamada João do tipo aluno.
Joao:Aluno;

E podemos atribuir valores para essa variável.
Joao.Nome:=To_Unbounded_String("Joaozinho da Silva");
Joao.Idade:=15;
Joao.Nota:=70;

Veja como poderia ficar o programa completo
With Ada.Text_IO, Use Ada.Text_IO;
With Ada.Integer_Text_IO; Use Ada.Integer_Text_IO;
With Ada.Strings.Unbounded; Use Ada.Strings.Unbounded;
Procedure mostra_registro is
        type Aluno is
        record
                Nome:Unbounded_String;
                Idade:integer range 1 .. 99;
                Nota:integer range 0 .. 100;
        end record ;
        Joao:Aluno;
begin
        Joao.Nome:=To_Unbounded_String("Joaozinho da Silva");
        Joao.Idade:=15;
        Joao.Nota:=70;
end mostra_registro;

31  Gerador de Números Aleatórios

Gerar números aleatórios pode ser algo muito importante e Ada nos ajuda a fazer isso sem que tenhamos que re-inventar a roda.
With Ada.Numerics.Float_Random, Text_IO, Ada.Float_Text_IO;
Use Ada.Numerics.Float_Random, Text_IO, Ada.Float_Text_IO;
Procedure Randonico is
        G: Generator;
        Saida:Float;
begin
        Reset (G); --Linha a
        Saida:=Random(G); --Linha b
        Put(Saida); --Linha c
        New_Line; --Linha d
end Randonico;
Esse programa usa o pacote Ada.Numerics.Float_Random que possui a função Random. Ela pega uma variável do tipo generator, tipo esse declarado no mesmo pacote, e resulta num número entre 0 e 1. Para entender o que é o Reset faça o seguinte. Comente a linha 'a' e repita uma ou duas vezes as linhas de 'b' até 'd'. Ada também permite que se crie valores discretos aleatórios o que na minha opinião não seria preciso. O leitor interessando deve ver o RM para isso.

32  Números com ponto flutuante e ponto fixo.

O tipo float é um tipo real de ponto flutuante sendo que uma variável X declarada como X: float:=2.0; apareceria na tela ao darmos put(x) como algo tipo 2.00000E+00. Nós podemos no entanto mudar a precisão de digitos criando novos tipos.
type pontoflutuante8 is digits 8;

Isso acima cria um tipo de ponto flutuante de 8 digitos.
Podemos também criar tipos de ponto fixo.
type nota is delta 0.1 range 0.0 .. 10.0;

ou mesmo algo tipo
type temperatura is delta 0.1 digits 2;

O primeiro cria um tipo nota que varia de 0 a 10 com um intervalo de 0.1. O segundo cria um tipo dito temperatura que vai de -100 até 100 variando de 0.1 em 0.1.
O programa abaixo ilustra varias maneiras de se escrever o número 2.
With Text_IO, Ada.Float_Text_IO;
Use Text_IO, Ada.Float_Text_IO;
Procedure fixoflutuante is
       type Pflutuante4 is digits 4;
       type Pflutuante9 is digits 9;
       type fixo is delta 0.1 range -3.0 .. 3.0;
       F2:Pflutuante4;
       F9:Pflutuante9;
       Pf:Fixo;
begin
       F2:=Pflutuante4(2.0);
       F9:=Pflutuante9(2.0);
       Pf:=Fixo(2.0);
       Put_Line(Pflutuante4'Image(F2));
       Put_Line(Pflutuante9'Image(F9));
       Put_Line(Fixo'Image(Pf));
end fixoflutuante;
Veja que usamos o atributo 'Image, que representa a variável como uma string, para podermos imprimir usando o put uma vez que os novos tipos são incompativeis com o mesmo e uma conversão para float arruinaria a formatação.
A saída gerada por esse programa é
 2.000E+00
 2.00000000E+00
 2.0   

33  Goto.

Ada permite o uso do goto. No programa abaixo ilustramos seu uso.
With Text_IO; Use Text_IO;
Procedure vaipara is
        x:integer:=1;
begin
        << inicio >>
       Put_Line("Nao use isso!!!!");
       x:=x+1;
       if x < 30 then goto inicio; end if;
end vaipara;

34  Access Type.

Imagine que uma dada variável não guarde um valor em si mas sim uma referencia para outra variável. Esse tipo de variável é chamada de Access Type em Ada ou ponteiros em C e é algo mais ou menos parecido com os links nos sistemas operacionais.
Uma diferença entre os Access Types e os ponteiros do C é que em Ada não é permitida aritimética com os mesmos.
Ada também pode criar Access Types não apenas para variaveis mas também para subprogramas o que foge o nosso escopo.
O exemplo abaixo mostra como os Acces Types funcionam.
With Ada.Integer_Text_IO;
Use Ada.Integer_Text_IO;
Procedure Ponteiros1 is
        type Integer_Ponteiro is access Integer;
        Numero: Integer:=10;
        Link1,Link2 : Integer_Ponteiro;
begin
        Link1 := new Integer;
        Link2 := new Integer;
        Link1.all:=Numero; --O link1 aponto para numero.
        Link2.all:=Link1.all; --O link2 recebe o valor de link1.
        Put(numero);
        Put(Link1.all);
        Put(Link2.all);
end Ponteiros1;
Você também pode criar ponteiros gerais desde que as variáveis sejam Aliased.
O tipo geral é identificado pela palavra All na declaração.
With Ada.Integer_Text_IO;
Use Ada.Integer_Text_IO;
Procedure Ponteiros2 is
        type Integer_Ponteiro1 is access Integer;
        type Integer_Ponteiro2 is access all Integer;
        A: Integer:=10;
        B: aliased Integer :=10; --B e' aliased.
        Link1: Integer_Ponteiro1;
        Link2: Integer_Ponteiro2;
begin
        Link1:=new Integer;
        Link1.all:=A; --Link1 e' um ponteiro comum.
        Put(Link1.all);
        Link2:=B'Access; --Link2 e' um ponteiro geral.
        Put(Link2.all);
end Ponteiros2;
Mas você poderia perguntar: Para que isso tudo serve?
Bom, uma das muitas aplicações dos ponteiros ou access types é quando estamos trabalhando com algo de tamanho desconhecido. Suponha que tenhamos um jogo de tabuleiro qualquer e usamos aquele programa de números aleatórios para escolher a jogada. Aquele programa não saberia o "tamanho livre" do tabuleiro. Pode ser que uma jogada escolhida já tivesse sido feita. O que você sugere?? Chamar o gerador de numeros aleatórios de novo usando um goto? NUNCA! Uma solução é usar os ponteiros ou access types. Quando uma jogada fosse feita o ponteiro para aquela jogada apontaria para uma outra que ainda não tivesse sido feita e dai quando aquela jogada fosse chamada iria para outra. Simples né?

35  Generics

Suponha que você tenha que fazer um pacote contendo uma função que deverá receber 3 variaveis inteiras e retornar verdadeiro se duas forem iguais e falso caso as três sejam iguais ou as três diferentes (poderia ser util num joguinho da velha). Depos pedem para você fazer o mesmo só que com variaveis do tipo float. O que você faria? Conversão de tipos? Ao converter de float para inteiro devido ao arredondamento o resultado da função seria falseado. E se depois pedissem para você fazer para caracteres, strings, etc? Você faria tudo de novo cada vez?
Ada resolve esse problema para você permitindo a criação de pacotes genéricos. Você cria um pacote genérico que trabalhe com um tipo genérico e quando precisar usar você especifica o tipo que lhe interessa e a isso dão o nome de 'instantiation'.
Por exemplo, podemos criar um pacote genérico como
--generic_doisiguais.adb
Package body Generic_Doisiguais is
Function Generic_Sao2iguais(A,B,C: in algum_tipo) return Boolean is
        Resultado:Boolean;
begin
        Resultado:=False;
        if A=B or B=C or A=C then Resultado:=True; end if;
        if A=B and B=C then Resultado:=False; end if;
        return Resultado;
end Generic_Sao2iguais;
end Generic_Doisiguais;
e para o qual tenhamos a declaração
--generic_doisiguais.ads
package Generic_Doisiguais is
generic type algum_tipo is private;
Function Generic_Sao2iguais(A,B,C: in algum_tipo) return Boolean;
end Generic_Doisiguais;
Dai podemos criar um programa que use isso fazendo a 'instantation'. No exemplo a seguir usamos o tipo integer.
--usa2iguais.adb
With Ada.Integer_Text_IO, Generic_Doisiguais, Text_IO;
Use Ada.Integer_Text_IO, Generic_Doisiguais, Text_IO;
Procedure Usa2iguais is
        Function Sao2iguais is new Generic_sao2iguais(Integer);
        Resposta: Boolean;
begin
        Resposta:=Sao2iguais(2,2,3); --Experimente mudar os valores.
        Put(Boolean'Image(Resposta));
end Usa2iguais;
No exemplo acima criamos a função Sao2iguais como sendo a função Generic_sao2iguais com o tipo integer. Poderiamos fazer isso para qualquer outro tipo.

36  Maiúsculas e Minúsculas

Exemplo:
With Ada.Strings.Maps.Constants;
With Ada.Strings.Fixed;
With Text_IO;
Use Text_IO;
Procedure Maisculas_E_Minusculas is
        String1 : String := "Alo Mundo!";
        String2,String3 : String(1..10);
begin
        -- Converte para maiusculas.
        String2:=Ada.Strings.Fixed.Translate(String1,
        Ada.Strings.Maps.Constants.Upper_Case_Map);
        -- Converte para minusculas.
        String3:=Ada.Strings.Fixed.Translate(String1,
        Ada.Strings.Maps.Constants.Lower_Case_Map);
        -- Imprime as tres strings.
        Put_Line(String1);
        Put_Line(String2);
        Put_Line(String3);
end Maisculas_E_Minusculas;

37  Ada.Numerics.Elementary_Functions

O pacote Ada.Numerics.Elementary_Functions é a versão para o tipo float do pacote genérico Ada.Numerics.Generic_Elementary_Functions.
De acordo com o Ada95 Reference Manual temos as seguinte funções nesse pacote.
Sqrt    Arctan   Log     Arccot
Exp     Sinh     **      Cosh
Sin     Coth     Cos     Arcsinh
Tan     Arccosh  Cot     Arctanh
Arcsin  Arccoth  Arccos

Para as funções trigonométricas o ângulo é em principio em radianos.
Podemos também especificar outra medida de ângulo pondo o equivalente a uma revolução inteira.
Ex:
sin(0.7853)

é o mesmo que
sin(45.0,360.0)

A função sqrt é a raiz quadrada enquanto **continua sendo a potenciação só que agora todos os numeros devem ser do tipo float.
Log é o logaritimo natural (base e), a não ser que outra base seja especificada.
Você também pode usar outras versões não genéricas para outros intervalos do tipo float como por exemploNumerics.Short_Elementary_Functions, Numerics.Long_Elementary_Functions e assim por diante.
A seguir um pequeno programa exemplo.
With Ada.Float_Text_IO,Ada.Numerics.Elementary_Functions;
Use Ada.Float_Text_IO,Ada.Numerics.Elementary_Functions;
Procedure Funcoes_numericas is
        A,B,C,D,E,F,G:Float;
begin
        A:=3.0**2.0;
        --3 ao quadrado
        B:=2.0**0.5;
        --Raiz de 2 = 1.4142.
        C:=Sqrt(100.0);
        --Raiz de 100.
        D:=Sin(3.141592);
        --Aproximadamente seno de Pi.
        E:=Sin(180.0,360.0);
        --Seno de Pi.
        F:=Log(Exp(5.0));
        --5.0
        G:=Log(10000.0,10.0);
        --Logaritimo decimal de 10000
        Put(A);
        Put(B);
        Put(C);
        Put(D);
        Put(E);
        Put(F);
        Put(G);
end Funcoes_numericas;

38  Números Complexos

Para trabalhar com números complexos podemos usar o pacote Ada.Numerics. Complex_Types. Um número complexo pode ser declarado como do tipo complex o qual tem ambas as compontentes do tipo real. Para atribuir um valor podemos usar parentezes e para receber o valor de um número complexo podemos usar os atributos .Re e .Im.
Ex:
With Ada.Float_Text_IO, Ada.Numerics.Complex_Types;
Use Ada.Float_Text_IO, Ada.Numerics.Complex_Types;
Procedure Complexos is
        A,B,S,P: Complex;
begin
        A:=(2.3,3.4);
        B:=(1.0,1.0);
        S:=A+B;
        P:=A*B;
        Put(S.Re);
        Put(S.Im);
        Put(P.Re);
        Put(P.Im);
end Complexos;

39  Exceptions

A linguagem Ada permite o tratamento de Exceptions que são erros que aparecem quando o programa se defronta com uma situação inesperada. Em geral tais erros provacam a interrupção indesejada do programa. Com o tratamento de exceptions a interrupção pode ser evitada e pode-se contornar o problema. Ada permite que o programador declare suas próprias exceptions mas aqui iremos nos limitar a interceptar as exceptions pré-defidas. Algumas das exceptions pré-definidas que aparecem no pacote Ada.Exceptions e também no próprio pacote text_IO são: Constraint_Error, Program_Error, Storage_Error, Name_Error, etc.
Exemplo: Considere o programa Mytype que pega um arquivo e exibe o conteudo no console:
With Text_IO; Use Text_IO;
Procedure mytype is
        File : File_Type;
        N : Natural;
        File_name : String(1..99);
        MyString : String(1..999);
begin
        Put("Enter the file name: ");
        Get_Line(File_Name,N);
        Open(File,In_File,File_Name(1..N));
        while not End_of_file(File) loop
                Get_Line(File, MyString, N);
                Put_Line(MyString(1..N));
                New_Line;
        end loop;
        Close(File);
end mytype;
Se entrarmos o nome de um arquivo que não existe aparecerá a menssagem:
raised ADA.IO_EXCEPTIONS.NAME_ERROR
Com o uso de exception podemos ensinar ao programa o que ele deve fazer nessa situação. Nesse caso o programa poderia ser melhor escrito na seguinte forma:
With Text_IO; Use Text_IO;
Procedure mytype is
        File : File_Type;
        N : Natural;
        File_name : String(1..99);
        MyString: String(1..999);
        Procedure open_file is
        begin
                Put("Enter the file name: ");
                Get_Line(File_Name,N);
                Open(File,In_File,File_Name(1..N));
                exception
                when
                NAME_ERROR = > Put_Line("File not found!");
                open_file; --Uma chamada recursiva.
        end open_file;
begin
        open_file;
        while not End_of_file(File) loop
                Get_Line(File, MyString, N);
                Put_Line(MyString(1..N));
                New_Line;
        end loop;
        Close(File);
end mytype;
Nesse caso a palavra chave exception (que deve ficar após a sequencia normal de comandos), inicia a parte do programa que atua caso um erro ocorra. No caso exibe uma mensagem de advertencia e executa novamente o mesmo procedimento através de uma chamada recursiva sem que o programa seja interrompido.

40  Importando funções de outras linguagens

A linguagem Ada 95 permite complexas interfaces com C, FORTRAN e COBOL, sendo que o compilador GNAT permite interface com C++ também. Uma coisa simples de se fazer no entanto é importar funções. O pequeno exemplo a seguir mostra isso com C e FORTRAN.
Exemplo:
Procedure Uso_do_Import is
       Procedure minha_printf (x:string);
       Pragma Import (C, minha_printf, "printf");
       Procedure minha_write (x:string);
       Pragma Import (Fortran,minha_write,"write");
begin
       minha_printf("Alo Mundo!!!!");
       minha_write("Alo Brasil!!!");
end Uso_do_Import;


Google







Caeté Minas Gerais | auflex - design sites | derivados do petróleo
pecados capitais | Ada 95 | mozila | Vomicae | funk Hlera Fotolog Orkut Mensagens Carros 1