Página 1 de 2

OrdWildSeek

Enviado: 12 Set 2008 12:02
por asimoes
Senhores,

Alguém sabe me dizer se esta função está funcionando 100%.
Estou fazendo testes com ela e verifiquei um problema muito estranho.

Um dbF com a seguinte estrutura:

Campo Tipo Tamanho
Nome C 30

Fiz append para este DBF com 3 nomes:
1º REGISTRO ALEXANDRE
2º REGISTRO JOAO
3º REGISTRO MARIANA

Está Indexado pelo nome:

INDEX ON Nome TAG Ind01 TO TESTE
SET INDEX TO TESTE
SET ORDER TO TAG Ind01

Antes de chamar a função OrdWildSeek, faço um DBGOTOP()
DBGOTOP()
DO WHILE OrdWildSeek("*A*",.T.)
AADD(aNomes,TESTE->Nome)
ENDDO

ACHOICE(02,00,10,40,aNomes,.T.,,)

A função OrdWildSeek só acha: JOAO E MARIANA, exibidos no ACHOICE.

Falta alguma coisa, ou estou fazendo algo de errado.
:)Pos
[]´s

Re: OrdWildSeek

Enviado: 12 Set 2008 13:16
por Toledo
aSimões, da maneira como está o seu código, com um DBGOTOP() no início e o segundo parâmetro da OrdWildSeek() com .T., sempre o primeiro registro do banco de dados será desprezado, pois a função vai fazer a busca a partir do registro atual, que neste caso é o nome ALEXANDRE.

Bom, acho que para resolver isto você teria que dar um DBSKIP(-1) depois do DBGOTOP().

Exemplo:

Código: Selecionar todos

DBGOTOP()
DBSKIP(-1)
DO WHILE OrdWildSeek("*A*",.T.)
  AADD(aNomes,TESTE->Nome)
ENDDO
Abraços,

Re: OrdWildSeek

Enviado: 12 Set 2008 13:25
por asimoes
Olá Toledo,

Fiz da forma que você sugeriu e nada feito, o resultado é o mesmo, parece que a função faz um skip de cara.

Alexandre

Re: OrdWildSeek

Enviado: 12 Set 2008 13:33
por Eolo
Alexandre, dá uma olhada na resposta do tópico ORDSCOPE. Vou repetir aqui, pra facilitar:

Testei e funciona.


"Achei uma saída (enquanto não aparece uma solução melhor): se é só o primeiro registro (do índice) que não é considerado, basta fazer WildSeek top/bott e depois bott/top. Na primeira passada, ele não vai aparecer. Mas, na segunda, sim. E, pra evitar eventuais duplicidades, é só filtrar com o ASCAN:"

Código: Selecionar todos

    aCust:={}
    GO TOP
    DO WHILE OrdWildSeek( "*BE*", .T. ) // top/bottom
       ? "aqui"
       AAdd( aCust, TESTE->Nome)
    ENDDO
    GO BOTTOM
    DO WHILE OrdWildSeek( "*BE*", .T. , .T.) // bottom/top
       IF ASCAN(ACUST, TESTE->NOME)=0
          ? "aqui"
          AAdd( aCust, TESTE->Nome)
       ENDIF
    ENDDO

Re: OrdWildSeek

Enviado: 12 Set 2008 13:44
por asimoes
Olá Eolo,

Fiz como você sugeriu e funcionou, agora nos resta aguardar a correção da função.

Obrigado,

:)Pos

Re: OrdWildSeek

Enviado: 12 Set 2008 14:20
por Toledo
ASimões, a função OrdWildSeek é um seek melhorado, onde você pode usar caracteres coringas (? *) na chave de busca. Só que se você informa o segundo parâmetro como .T., ela sempre vai desprezar o registro atual, então da maneira como você fez o seu código, não vai dar certo, pois sempre o primeiro registro não vai fazer parte da busca. Agora se você não informar o segundo parâmetro ou informar .F., ai o registro atual será considerado na busca.

Então, para resolver o seu problema, faça o seguinte:

Código: Selecionar todos

DBGOTOP()
lSai:=OrdWildSeek( "*A*")
DO WHILE lSai
  AADD(aNomes,TESTE->Nome)
  lSai:=OrdWildSeek("*A*",.T.)
ENDDO
Este exemplo eu já testei e deu certo.
A sintaxe desta função:

OrdWildSeek(cBusca, lInicio, lOrdem)

cBusca = expressão para busca, onde você pode usar caracteres coringas (? ou *).
lInicio = se .T. faz a busca a partir do registro atual, se .F. a busca será a partir do início do arquivo.
lOrdem = informe .T. para decrescente ou .F. para crescente.

Se lInicio e lOrdem não forem informados, o default será .F.
Abraços,

Re: OrdWildSeek

Enviado: 12 Set 2008 15:05
por Eolo
Toledo, a sua solução é de fato mais simples e parece que dá certo também, mas não me parece ser o que o criador dela imaginou ou, pelo menos, não é o que está demonstrado no Help do XHarbour. Segundo o Help, vc roda uma vez a função e pronto. Não precisa fazer como você fez: rodar uma vez pra posicionar e depois rodar novamente, dentro do loop:

Código: Selecionar todos

      GO TOP
      aCust := {}
      DO WHILE OrdWildSeek( "*EL*", .T. ) // assumindo o 3o. parâmetro como .F.
         AAdd( aCust, FIELD->Lastname )
      ENDDO

      AEval( aCust, {|c| QOut(c) } )
      // Found records:
      //   Feldman
      //   Hellstrom
      //   Keller
      //   Reichel
Também, você disse "...o segundo parâmetro como .T., ela sempre vai desprezar o registro atual...", mas o Help parece dizer diferente: "This parameter defaults to .F. (false) causing OrdWildSeek() to begin the search WITH THE FIRST record included in the controlling index. When .T. (true) is passed, the function begins the search WITH the current record."

A propósito, eu tentei usar o argumento .F. (para começar pelo primeiro registro no topo do índice), mas também não funcionou. A primeira ocorrência, estando no TOP, é ignorada. Estranho.

Abraço.

Re: OrdWildSeek

Enviado: 12 Set 2008 16:06
por Toledo
Eolo, ficou estranho no help dizer que o registro atual vai fazer parte da busca quando o segundo parâmetro for .T., pois deste modo não faz sentido existe tal parâmetro. A função deste segundo parâmetro é de continuar uma busca a partir do registro seguinte ao último (registro) localizado em uma busca anterior.

Imagine como ficaria o exemplo do ASimões se o help estivesse correto. Se o registro atual fizesse parte da busca, o loop do While ficaria sempre no mesmo registro, pois não existe dentro do While um SKIP para mover o ponteiro para o próximo registro.

Exemplo:
Registro 1 = ALEXANDRE
Registro 2 = JOÃO
Registro 3 = MARIANA

1ª busca: OrdWildSeek("*A*",.T.) = vai parar em ALEXANDRE
2ª busca: OrdWildSeek("*A*",.T.) = se o registro atual contar, vai parar novamente em ALEXANDRE, pois tem a letra A.
3ª busca: Idem

e assim infinitamente...
O segundo parâmetro é exatamente para isto, para dar continuidade a busca até atingir o final do arquivo. É um LOCATE super mais rápido.

Então o Help está errado.

Abraços,

Re: OrdWildSeek

Enviado: 12 Set 2008 18:23
por Eolo
Pois é, então o Help que eu tenho está danado.

Onde eu arrumo um Help que funcione? Estou usando o Xh 1.0.0.

Abraço!

Re: OrdWildSeek

Enviado: 12 Set 2008 18:31
por Toledo
Eolo, a versão mais recente do Help é esta mesmo, eu só acho que no caso da função acima o help falhou neste pequeno detalhe.

Abraços,

Re: OrdWildSeek

Enviado: 12 Set 2008 18:32
por alaminojunior
O segundo parâmetro é exatamente para isto, para dar continuidade a busca até atingir o final do arquivo. É um LOCATE super mais rápido.

Então o Help está errado.
A função OrdWildSeek() pode ser chamada passando três parâmetros.
1º parâmetro, é a parte do que se quer encontrar;
2º parâmetro, de onde a pesquisa deve iniciar (.t. para registro corrente) ou (.f. para registro inicial do indice)
3º parâmetro, em qual direção você quer que o ponteiro ande (.t. em direção ao inicio) ou (.f. em direção ao fim)

Talvez na "primeira passada", seria interessante usar o segundo parametro estando em .f., para forçar a busca do inicio. E os demais estando em .t., fazendo a busca sempre do registro corrente.

Re: OrdWildSeek

Enviado: 12 Set 2008 20:14
por alaminojunior
Realmente colegas, segue aí o código por Eolo e eu, testado e aprovado:
No primeiro OrdWildSeek ele achou dois registros, e na segunda vez, três registros.

Código: Selecionar todos

PROCEDURE Main
      LOCAL aCust := {}

      USE cdcli000
      INDEX ON clinom TO nomes
      
		go top
      DO WHILE OrdWildSeek( "*IO?", .T. )
         AAdd( aCust, FIELD->clinom )
      ENDDO

      AEval( aCust, {|c| QOut(c) } )
		wait "dinovo"
      GO TOP
      aCust := {}
      passada:= 1
      DO WHILE OrdWildSeek( "*IO?", iif(passada=1,.F.,.T.) )
         AAdd( aCust, FIELD->clinom )
         passada++
      ENDDO

      AEval( aCust, {|c| QOut(c) } )
      USE
RETURN
Independente de ser o 1º registro no índice ou não, haveria o problema.
Mas a conclusão em que eu cheguei foi a seguinte:
o segundo parâmetro determina de onde deve partir a pesquisa, se .f., registro inicial incluindo o registro atual, se .t., a partir do registro corrente, não incluindo o mesmo;
vamos imaginar a cena....
o ordwildseek foi acionado;
ele está num registro que não satisfaz a condição; o que ele faz ? retorna found() = .f. e posiciona o ponteiro em lastrec()+1;
sendo assim, quando ele chegar no registro que atende a condição e estando o segundo parâmetro em .t., ele entende que a pesquisa deve partir daquele registro em diante, e não incluindo o mesmo.
Ao passo que se estivesse em .f., ele incluiria o mesmo e retornaria found() = .t.

Re: OrdWildSeek

Enviado: 12 Set 2008 22:53
por asimoes
Alamino e Eolo,

Muito inteligente a solução, gostei. Não desprezando também a do Toledo.
Obrigado a todos.
:)Pos

Re: OrdWildSeek

Enviado: 12 Set 2008 23:07
por alaminojunior
Só falta eu descobrir como saltar linhas entre os cupons nos ecf´s. :'( :'( :'(

Re: OrdWildSeek

Enviado: 15 Set 2008 10:25
por sygecom
alaminojunior escreveu:Só falta eu descobrir como saltar linhas entre os cupons nos ecf´s
Não entendi o que tem haver com a duvida sobre ( OrdWildSeek ). Alaminio favor abrir um novo topico sobre sua duvida.