Ascan ?

Projeto [x]Harbour - Compilador de código aberto compatível com o Clipper.

Moderador: Moderadores

MARCELOG
Usuário Nível 4
Usuário Nível 4
Mensagens: 546
Registrado em: 15 Mar 2005 16:54
Localização: Divinópolis/MG

Ascan ?

Mensagem por MARCELOG »

Olá pessoal,
deparei-me com uma situação interessante.
Vejam isto:

aMatriz := {'a','b','c'}

? ascan(aMatriz,'b') // Retorna 2 Ok

? ascan(aMatriz,'') // Retorna 1 - ERRO

O comportamento relativo à segunda pesquisa está correto? Por quê?

MarceloG

:-o
Água mole em pedra dura tanto bate que até espirra!
Avatar do usuário
sygecom
Administrador
Administrador
Mensagens: 7131
Registrado em: 21 Jul 2006 10:12
Localização: Alvorada-RS
Contato:

Re: Ascan ?

Mensagem por sygecom »

Olá Marcelo,
Estranho esse comportamento, aqui retorna 0(ZERO). Uso xHarbour 1.2.1 + Bcc5.5.1. Testou em outra maquina( isso não deveria mudar) ? Testou com outro compilador ?
Leonardo Machado
xHarbour.org + Hwgui + PostgreSql
Avatar do usuário
Pablo César
Usuário Nível 7
Usuário Nível 7
Mensagens: 5312
Registrado em: 31 Mai 2006 10:22
Localização: Curitiba - Paraná

Ascan ?

Mensagem por Pablo César »

Eu testei Harbour + MiniGui (HMG) e obtive o mesmo resultado, isto é 1 para busca caracter vazio. Mas daí fiz este outro teste e observe:

Código: Selecionar todos

Function Main
aMatriz := {0,'b','c'}

? ascan(aMatriz,'b') // Retorna 2 Ok

? ascan(aMatriz,"") // Retorna 2 - Ok

? ascan(aMatriz,'d') // Retorna 0 - Ok
inkey(0)
Return
Que, mesmo que nos pareça esquisito, está correto, pois a pesquisa neste exemplo, denota que na verdade procura algum caracter (claro que eneste caso vazio) e que na verdade não deixa de estar acertado, pois o primeiro elemento é do tipo numérico. No entanto a terceira pesquisa ele retorna zero, pois nenhum elemento satisfaz a condição. Contudo, acho muito essa situação interessante, pois isso serve de alerta para os mais desavisados.
Um clip-abraço !

Pablo César Arrascaeta
Compartilhe suas dúvidas e soluções com todos os colegas aqui do fórum.
Evite enviar as dúvidas técnicas por MPs ou eMails, assim todos iremos beneficiar-nos.
Avatar do usuário
sygecom
Administrador
Administrador
Mensagens: 7131
Registrado em: 21 Jul 2006 10:12
Localização: Alvorada-RS
Contato:

Re: Ascan ?

Mensagem por sygecom »

Pablo, você testou apenas usando Harbour em modo console ?
Tem coisa errada, retornar 1 no meu ver está errado.
Leonardo Machado
xHarbour.org + Hwgui + PostgreSql
Avatar do usuário
Maligno
Membro Master
Membro Master
Mensagens: 6398
Registrado em: 06 Jul 2004 01:40
Localização: Londrina/PR

Re: Ascan ?

Mensagem por Maligno »

O comportamento da função AScan() em Clipper, e usando a matriz que o Marcelo postou, é exatamente o mesmo. É erro? Sim e não. Se a matriz contém {'a','b','c'} e a busca por "" (NULO) retorna 1, não se pode dizer que está errado. Pode-se entender que ele retornou o primeiro elemento que contém o NULO. Como toda string sempre contém NULO, retorna 1. Na matriz do Pablo o primeiro elemento é numérico. Logo, o primeiro elemento que contém NULO é o segundo na seqüência; primeira string a aparecer. Normal. Se não é esse o comportamento que se espera, parece erro. Mas, de fato, não se pode dizer que seja.

De qualquer forma, a solução é simples. Basta usar AScan() com um bloco de código e testar pela nulidade do elemento. O código abaixo, que procura por NULO, retorna 0 para as duas matrizes dos exemplos.

Código: Selecionar todos

? AScan(aMatriz,{|x|valtype(x)="C" .and. x != ""})
O primeiro teste no bloco é necessário porque a matriz do Pablo mistura tipos. Sem esse teste tem-se erro de run-time.
[]'s
Maligno
---
Não respondo questões técnicas através de MP ou eMail. Não insista.
As dúvidas devem ser postadas no fórum. Desta forma, todos poderão
se beneficiar das respostas.

---
Se um dia precisar de uma transfusão de sangue você perceberá como
é importante a figura do doador. Procure o hemocentro de sua cidade e
se informe sobre a doação de sangue, plaquetas e medula óssea. Doe!
MARCELOG
Usuário Nível 4
Usuário Nível 4
Mensagens: 546
Registrado em: 15 Mar 2005 16:54
Localização: Divinópolis/MG

Re: Ascan ?

Mensagem por MARCELOG »

Olá pessoal,
obrigado por responderem.
Mas vejam bem, eu não estou procurando caracteres nulos na string, mas se a entrada existe na matriz é igual a nulo.
Então, considerando o que o Maligno falou é erro e deve ser reportado.

MarceloG
Água mole em pedra dura tanto bate que até espirra!
Avatar do usuário
Maligno
Membro Master
Membro Master
Mensagens: 6398
Registrado em: 06 Jul 2004 01:40
Localização: Londrina/PR

Re: Ascan ?

Mensagem por Maligno »

Então o Clipper também está com esse bug esses anos todos? Não se pode classificar de bug só porque você não tem o que precisa. Não é bug. É só uma questão de implementação.

Mas pra resolver seu problema é fácil. Como eu disse, um bloco de código resolve. Se o que você quer é justamente saber se há uma string NULA, teste se ela está vazia com um bloco como o abaixo.

Código: Selecionar todos

AScan(aMatriz,{|x|Empty(x)})
ou
AScan(aMatriz,{|x|x==""})
ou
AScan(aMatriz,{|x|""=x})
Agora, se você não quer usar bloco de código também pode ser feito. Mas você precisará do SET EXACT ON. Aí pode usar a forma simples, como você fez antes.

Código: Selecionar todos

AScan(aMatriz,"")
Particularmente não gosto de resolver um problema desses com um SET, que é uma configuração global de sistema. Isso prejudica a abstração de qualquer função. Mas é fato: resolve também.
[]'s
Maligno
---
Não respondo questões técnicas através de MP ou eMail. Não insista.
As dúvidas devem ser postadas no fórum. Desta forma, todos poderão
se beneficiar das respostas.

---
Se um dia precisar de uma transfusão de sangue você perceberá como
é importante a figura do doador. Procure o hemocentro de sua cidade e
se informe sobre a doação de sangue, plaquetas e medula óssea. Doe!
Avatar do usuário
asimoes
Colaborador
Colaborador
Mensagens: 4919
Registrado em: 26 Abr 2007 16:48
Localização: RIO DE JANEIRO-RJ

Re: Ascan ?

Mensagem por asimoes »

Para ajudar a entender melhor o ascan, estou publicando a documentação da função.
Reparem o quinto parâmetro: lExact
AScan()
Searches a value in an array beginning with the first element.
Syntax
Ascan( <aArray> , ;
<xbSearch>, ;
[<nStart>], ;
[<nCount>], ;
[<lExact>], ;
[<lASCII>] ) --> nElement

Arguments
<aArray>
This is the array to iterate.
<xbSearch>
<xbSearch> is either the value to search in <aArray> or a code block containing the search condition. The code block receives a single parameter which is the value stored in the current array element. The code block must return a logical value. When the return value is .T. (true), the function stops searching and returns the position of the corresponding array element.
<nStart>
This is a numeric expression indicating the first element in the array to begin the search with. It defaults to 1, the first element of <aArray>.
<nCount>
A numeric expression specifying the number of elements to search. It defaults to 1+Len(<aArray>)-<nStart>.
<lExact>
This parameter influences the comparison for searching character strings in <aArray>. If .T. (true) is passed, an exact string comparison is performed. When omitted or if .F. (false) is passed, string comparison follows the SET EXACT rules.
<lASCII>
This parameter is only relevant for arrays that contain single characters in their elements. A single character is treated like a numeric ASCII value when <lASCII> is .T. (true). The default is.F. (false). Return
AScan() returns the numeric ordinal position of the array element that contains the searched value. When no match is found, the return value is 0.
Description
The array function AScan() traverses the array <aArray> for the value specified with <xbSearch>. If <xbSearch> is not a code block, AScan() compares the values of each array element for being equal with the searched value. If this comparison yields .T. (true), the function stops searching and returns the numeric position of the array element containing the searched value.
If a code block is passed for <xbSearch>, it is evaluated and receives as parameter the value of the current array element. The code block must contain a comparison rule that yields a logical value. AScan() considers the value as being found when the codeblock returns .T. (true). Otherwise the function proceeds with the next array element.
Note: use function RAscan() to search an array beginning with the last element.
►Harbour 3.x | Minigui xx-x | HwGui◄
Pense nas possibilidades abstraia as dificuldades.
Não corrigir nossas falhas é o mesmo que cometer novos erros.
A imaginação é mais importante que o conhecimento. (Albert Einstein)
Avatar do usuário
asimoes
Colaborador
Colaborador
Mensagens: 4919
Registrado em: 26 Abr 2007 16:48
Localização: RIO DE JANEIRO-RJ

Re: Ascan ?

Mensagem por asimoes »

SET EXACT
Determines the mode for character string comparison.
Syntax
SET EXACT on | OFF | ( <lOnOff> )

Arguments
on | OFF | ( <lOnOff> )
This option toggles if an exact comparison is performed with character strings. or not. The default is OFF or .F. (false), i.e. characters are compared up the length of the shorter string. To change the setting use ON or .T. (true) as parameter. The parameter can also be specified as a logical expression enclosed in parentheses. Description
The SET EXACT command determines the mode for character string comparison with the comparison operators (=, >, <, =>, =<). The following rules are applied for comparison with SET EXACT set to ON:
1) When the right operand is a null string, the result is always .T. (true)

2) When the right operand is longer than the left operand, the result is always .F. (false)

3) When the right operand contains less or the same number of characters as the left operand, the result is only true if the left operand begins with the exact same characters as the right operand.

With SET EXACT set to OFF, the same rules apply except that trailing spaces are ignored in the comparison.
Notes: The exact equal operator == always performs an exact comparison irrespectively of the SET EXACT setting.
Search commands and functions such as SEEK, DbSeek() or SET RELATEION are not affected
Vejam a 3ª comparação no exemplo abaixo:

Código: Selecionar todos

PROCEDURE Main
      SET EXACT OFF
      ? "AB" = "ABCD"             // result: .F.
      ? "ABCD" = "AB"             // result: .T.
      ? "AB" = ""                 // result: .T.
      ? "" = "AB"                 // result: .F.
      ? "AB" = "AB  "             // result: .F.

      SET EXACT ON
      ? "AB" = "ABCD"             // result: .F.
      ? "ABCD" = "AB"             // result: .F.
      ? "AB" = ""                 // result: .F.
      ? "" = "AB"                 // result: .F.
      ? "AB" = "AB  "             // result: .T.

      ? "AB" == "AB  "            // result: .F.
   RETURN
►Harbour 3.x | Minigui xx-x | HwGui◄
Pense nas possibilidades abstraia as dificuldades.
Não corrigir nossas falhas é o mesmo que cometer novos erros.
A imaginação é mais importante que o conhecimento. (Albert Einstein)
Avatar do usuário
Jairo Maia
Moderador
Moderador
Mensagens: 2785
Registrado em: 16 Ago 2010 13:46
Localização: Campinas-SP

Re: Ascan ?

Mensagem por Jairo Maia »

Caros Colegas,

Também concordo com o Maligno, pois usar SET EXACT ON pode alterar outras pontos do mesmo aplicativo. Penso que para vc resolver o problema, uma vez que isso é necessario em seu projeto, vc deva substituir Ascan por RAscan:

aMatriz := {'a','b','c'}

? RAscan(aMatriz,'b') // Retorna 2 Ok

? RAscan(aMatriz,'') // Retorna 0 - Correto

Usnado Harbour 2.1 funcionou.
Abraços, Jairo
Harbour / Clipper 5.2e - Blinker 7
(Não respondo dúvidas por MP ou E-mail. Por favor, não encaminhe via mensagem privada ou e-mail, dúvidas que podem ser compartilhadas com todos no fórum)
Avatar do usuário
Maligno
Membro Master
Membro Master
Mensagens: 6398
Registrado em: 06 Jul 2004 01:40
Localização: Londrina/PR

Re: Ascan ?

Mensagem por Maligno »

Pra quem não conhece essa função (como eu - o Clipper não tem) poderia, por favor, descrever as diferenças entre AScan() e RAScan()? Da minha parte é só curiosidade. :)
[]'s
Maligno
---
Não respondo questões técnicas através de MP ou eMail. Não insista.
As dúvidas devem ser postadas no fórum. Desta forma, todos poderão
se beneficiar das respostas.

---
Se um dia precisar de uma transfusão de sangue você perceberá como
é importante a figura do doador. Procure o hemocentro de sua cidade e
se informe sobre a doação de sangue, plaquetas e medula óssea. Doe!
Avatar do usuário
fladimir
Colaborador
Colaborador
Mensagens: 2445
Registrado em: 15 Nov 2006 20:21

Re: Ascan ?

Mensagem por fladimir »

Olá pessoal, retirei do manual do xHarbour... segue sobre o RAScan()
RAscan()
Searches a value in an array beginning with the last element.
Syntax
RAscan( <aArray> , ;
<xbSearch>, ;
[<nStart>] , ;
[<nCount>] , ;
[<lExact>] , ;
[<lASCII>] ) --> nElement

Arguments
<aArray>
This is the array to iterate.
<xbSearch>
<xbSearch> is either the value to search in <aArray> or a code block containing the search condition. The code block receives a single parameter which is the value stored in the current array element. The code block must return a logical value. When the return value is .T. (true), the function stops searching and returns the position of the corresponding array element.
<nStart>
This is a numeric expression indicating the first element in the array to begin the search with. It defaults to Len(<aArray>), the last element of the array.
<nCount>
A numeric expression specifying the number of elements to search. It defaults to 1+Len(<aArray>)-<nStart>.
<lExact>
This parameter influences the comparison for searching character strings in <aArray>. If .T. (true) is passed, an exact string comparison is performed. When omitted or if .F. (false) is passed, string comparison follows the SET EXACT rules.
<lASCII>
This parameter is only relevant for arrays that contain single characters in their elements. A single character is treated like a numeric ASCII value when <lASCII> is .T. (true). The default is.F. (false). Return
RAScan() returns the numeric ordinal position of the array element that contains the searched value. When no match is found, the return value is 0.
Description
The array function RAscan() traverses the array <aArray> for the value specified with <xbSearch>. If <xbSearch> is not a code block, RAscan() compares the values of each array element for being equal with the searched value. If this comparison yields .T. (true), the function stops searching and returns the numeric position of the array element containing the searched value.
If a code block is passed for <xbSearch>, it is evaluated and receives as parameter the value of the current array element. The code block must contain a comparison rule that yields a logical value. AScan() considers the value as being found when the codeblock returns .T. (true). Otherwise the function proceeds with the next array element.
Note: use function AScan() to search an array beginning with the first element.
Info
See also: AEval(), Asc(), Ascan(), ASort(), ATail(), Eval(), IN, SET EXACT
Category: Array functions , xHarbour extensions
Source: vm\arrayshb.c
LIB: xhb.lib
DLL: xhbdll.dll
Example

Código: Selecionar todos

// The example demonstrates the difference between AScan() and RAscan().

   PROCEDURE Main()
      LOCAL aArray := { "A", 1, Date(), 1, .F. }

      ? Ascan( aArray, 1 )             // result: 2
      ? RAScan( aArray, 1 )            // result: 4

   RETURN

Sun Tzu há mais de três mil anos cita nas epígrafes de seu livro “A Arte da Guerra“:

“Concentre-se nos pontos fortes, reconheça as fraquezas, agarre as oportunidades e proteja-se contra as ameaças”.
“Se não é vantajoso, nunca envie suas tropas; se não lhe rende ganhos, nunca utilize seus homens; se não é uma situação perigosa, nunca lute uma batalha precipitada”
.


Até 2017    Desktop Console [ Legado ] Harbour | MinGW | DBF | CDX | FastReport | MySQL


Novos Projetos:

   Desktop Visual           Windev Desktop
   Celular Android/iOS   Windev Mobile
   WEB                            Windev Web


Sejamos gratos a Deus.
Avatar do usuário
Jairo Maia
Moderador
Moderador
Mensagens: 2785
Registrado em: 16 Ago 2010 13:46
Localização: Campinas-SP

Re: Ascan ?

Mensagem por Jairo Maia »

Olá pessoal,

Peço desculpas, as vezes "peco" pelo uso da síntese, e obrigado ao Fladimir que elucidou as dúvidas.

Resumindo, é uma junção da função RATE e ASCAN, e como explicado no texto postado pelo Fladimir, Ascan retorna o primeiro elemento, enquanto RAscan retorna o último.

Isso somente resolve se a idéia é saber se tal elemento está contido na matriz, sem importar a ordem. Caso contrário, deve-se usar Ascan. Se necessário, setar SET EXACT ON na mesma função que ira usar o Ascan (sem alterar a configuração global, como destacado pelo Maligno, e que é desaconselhável), onde situação identica a do Marcelo se fizer necessário.

Código: Selecionar todos

Func Main()
 Loca := aMatriz := {'a','b','c'}, lSetExac := SET(_SET_EXACT, .t. )

  ? ascan(aMatriz,'b') // Retorna 2

  ? ascan(aMatriz,'') // Retorna 0

  SET(_SET_EXACT, lSetExac)  // seta SET EXACT anterior

 Retu
Abraços, Jairo
Harbour / Clipper 5.2e - Blinker 7
(Não respondo dúvidas por MP ou E-mail. Por favor, não encaminhe via mensagem privada ou e-mail, dúvidas que podem ser compartilhadas com todos no fórum)
Responder