Jump to content
passarito

Palavra reservada - WITH

Recommended Posts

passarito

Boas,

Para nos poupar trabalho, existe no Pascal uma palavra reservada WITH

Serve para indicarmos que no bloco de programação dentro do with os campos estão referenciados ao registo indicado pelo WITH, assim não necessitamos de referenciar o nome do registo, apenas o campo.

Estrutura:

WITH Registo DO (faz o que tens a fazer se for só uma linha)

ou

WITH Registo DO begin
  ... 
  (faz o que tens a fazer se forem várias linhas)
  ...
end;

Vamos a um exemplo....

Registo e variavel:

Type
  RCliente=Record
    Num      :Longint;
    Firma    :String[40];
    Contacto :String[40];
    Morada   :Array[1..4] of string[40];
    NCont    :string[20];
    Telef,Fax:string[20];
    Obs      :array[1..3] of string[40];
    Deleted  :Boolean;
  end;

Var
  RCli:RCliente

Programação tradicional:

...
  while not eof(FCli) do begin
    read(FCli,RCli);
    if not RCli.deleted then begin
      writeln(lst,'Numero.........:',RCli.Num);
      writeln(lst,'Firma..........:',RCli.Firma);
      writeln(lst,'Contacto.......:',RCli.Contacto);
      writeln(lst,'Morada.........:',RCli.Morada[1]);
      writeln(lst,'                ',RCli.Morada[2]);
      writeln(lst,'                ',RCli.Morada[3]);
      writeln(lst,'                ',RCli.Morada[4]);
      writeln(lst,'Nº Contribuinte:',RCli.NCont);
      writeln(lst,'Telefone       :',RCli.Telef);
      writeln(lst,'Fax            :',RCli.Fax);
      writeln(lst,'Observaçöes:   :',RCli.Obs[1]);
      writeln(lst,'                ',RCli.Obs[2]);
      writeln(lst,'                ',RCli.Obs[3]);
    end;
  end;
...

Programação com WITH:

...
  while not eof(FCli) do begin
     read(FCli,RCli);
     with RCli do begin
       if not deleted then begin
         writeln(lst,'Numero.........:',Num);
         writeln(lst,'Firma..........:',Firma);
         writeln(lst,'Contacto.......:',Contacto);
         writeln(lst,'Morada.........:',Morada[1]);
         writeln(lst,'                ',Morada[2]);
         writeln(lst,'                ',Morada[3]);
         writeln(lst,'                ',Morada[4]);
         writeln(lst,'Nº Contribuinte:',NCont);
         writeln(lst,'Telefone       :',Telef);
         writeln(lst,'Fax            :',Fax);
         writeln(lst,'Observaçöes:   :',Obs[1]);
         writeln(lst,'                ',Obs[2]);
         writeln(lst,'                ',Obs[3]);
      end;
    end;

Como podem ver, a "beleza" do código é completamente diferente.

NOTAS:

1. Há que precaver uma situação, cuidado se tiverem variaveis iguais aos campos dos registos, por exemplo no caso anterior tenho um campo RCli.Num, caso tivesse uma variavel Num não conseguiriamos garantir qual é que o programa iria usar. Neste aconselho ou a não usarem o WITH ou melhor ainda não usarem variaveis iguais às dos campos. Tive um caso destes em ASP!

2. Também se pode usar o WITH com ponteiros

With P^ do begin
  ...
end;

Share this post


Link to post
Share on other sites
nunopicado

Um excelente comando sem duvida.

Uso com fartura em Delphi.

Já agora, e embora o risco de meter os pés pelas mãos aumente quando não se sabe o que se está a fazer, é possível (pelo menos em alguns compiladores) usar o with com mais do que um registo (separando os registos por vírgulas na sua declaração):

type
    TPessoa = record
        Nome,Apelido:String;
    end;
    TViatura = record
        Marca,Modelo:String;
    end;

var
    Pessoa:TPessoa;
    Viatura:TViatura;

begin 
.
.
.
      with Pessoa,Viatura do
           begin
                 writeln('A pessoa ',Nome,' ',Apelido,' conduz um ',Marca,' ',Modelo);
           end;
end.

Mais uma vez, convém ter cuidado com nomes de campos iguais a nomes de variáveis ou de campos do outro registo a ser acedido pelo with... 


"A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!"

> Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum.

Share this post


Link to post
Share on other sites
passarito

Quando fiz o tópico, coo sempre, dei uma vista de olhos no Help do meu Borland Pascal também vi isso mesmo, que se podiam utilizar vários argumentos, mas, não sei se eles o irão usar com 1 argumento quanto mais com vários.

Agora, lá no help,  está lá um exemplo que fiquei no minimo intrigado

Alguém consegue explicar isto?

 
Example:
  { "with" statement }
    with Date[i] do
    begin
      month := 1;
      year  := year + 1;
    end;

This is equivalent to:
    Date[i].month := 1;
    Date[i].year  := Date[i].year + 1;

Date[ I ] será um array, record... mas com [ I ], ?!?

Já agora, instalei o FreePascal, mas não tem Help com as teclas F1 ou CTRL+F1 como o Borland Pascal... Também ainda não investiguei muito.

Alguém sabe se o Free Pascal tem help? Se tem onde está?

Share this post


Link to post
Share on other sites
nunopicado

Pois, também notei isso quando o instalei. Acho que tem de se fazer o download do help à parte, mas nunca experimentei.

Nesse exemplo, o "Date" será algo deste género:

type
    TDate = record
       Day,
       Month,
       Year:word
    end;
var
    Date: Array [1..n] of TDate;

Já agora, sobre as prioridades de quando se usa o WITH...DO com campos iguais em dois dos seus argumentos, ou campos com o mesmo nome de uma variável:

1. Prioridade máxima aos argumentos do WITH, do último para o primeiro

2. Prioridade mínima às variáveis externas, primeiro as locais e só por fim as globais

program teste;
type
   tipo1=record
     c1,c2,c3:String
   end;
   tipo2=record
     c1,c2:String;
   end;

var
   xpto1:tipo1;
   xpto2:tipo2;
   c1,c2,c4:string;

begin
   with xpto1,xpto2 do
      begin
           c1:='5';    // Isto atribui o valor '5' ao campo C1 da variavel XPTO2

           xpto1.c2:='10';    // Se quisermos atribuir um valor a um campo do primeiro argumento do WITH (neste caso, XPTO1) e esse campo também existir no XPTO2, temos de usar o nome do registo como se não estivessemos dentro do with

           c3:='15';  // Isto atribui o valor '15' ao campo C3 da variavel XPTO1, visto que na XPTO2 que tem prioridade, não existe nenhum campo com esse nome.

           teste.c1:='20';    // Se dentro do with quisermos atribuir um valor a uma variável com o mesmo nome de um campo, temos de lhe indicar o "namespace" dessa variável, ou seja, o nome do programa se for uma variavel global, ou o nome do procedimento/função, se for uma variavel local

           c4:='25';  // Isto atribui o valor 25 à variavel C4, visto que não existe nenhum campo com esse nome dentro de XPTO1 ou XPTO2
      end;
end.


"A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!"

> Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum.

Share this post


Link to post
Share on other sites
passarito
Já agora, sobre as prioridades de quando se usa o WITH...DO com campos iguais em dois dos seus argumentos, ou campos com o mesmo nome de uma variável:

1. Prioridade máxima aos argumentos do WITH, do último para o primeiro

2. Prioridade mínima às variáveis externas, primeiro as locais e só por fim as globais

Nuno,

Além de concordar com o que dizes, eu ainda continuo na minha: Evitar nomes de campos e variaveis iguais. O compilador pode não se baralhar mas nós podemos!

Share this post


Link to post
Share on other sites
nunopicado

Nuno,

Além de concordar com o que dizes, eu ainda continuo na minha: Evitar nomes de campos e variaveis iguais. O compilador pode não se baralhar mas nós podemos!

:) Ah sim, não discuto com isso... :) Como diria o meu pai, o diabo tenta-as! :cheesygrin:

Se pudermos evitar código que possa dar problemas (não pelo código em si, mas por potencial e provável falha humana), não é demais.

Better safe than sorry...  É que isso é daqueles erros que até com debugger é preciso estar com uma atenção tremenda para apanhar!


"A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!"

> Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum.

Share this post


Link to post
Share on other sites
thoga31

Existe também uma referência no nosso Tutorial aqui, muito mais breve, após uma explicação dos Records. :cheesygrin:


Knowledge is free!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.