Página 5 de 7
Práticas que facilitam programar Clipper/Harbour
Enviado: 14 Jan 2016 09:14
por JoséQuintas
Quanto ao post anterior, de qualquer jeito, depende do programador incluir o recurso em suas práticas.
Outro exemplo: um array de coordenadas de mouse pra click, geralmente é um array multidimensional:
Código: Selecionar todos
FOR nCont = 1 TO Len( aAreaMouse )
IF MRow() >= aAreaMouse[ nCont, 1 ] .AND. MCol() >= aAreaMouse[ nCont, 2 ] .AND. MCol() <= aAreaMouse[ nCont, 3 ]
nKey := aAreaMouse[ nCont, 4 ]
EXIT
ENDIF
NEXT
Código: Selecionar todos
FOR EACH oElement IN aAreaMouse
IF MRow() >= oElement[ 1 ] .AND. MCol() >= oElement[ 2 ] .AND. MCol() <= oElement[ 3 ]
nKey := oElement[ 4 ]
EXIT
ENDIF
NEXT
É até interessante, dá pra ter relação com um post anterior.
O "assunto" do bloco é aAreaMouse, todos os elementos do array.
E o "assunto" da rotina interna é cada um dos elementos desse array.
FOR EACH deixou isso bem claro no fonte.
Parece até que faz parte:
Acostumou a organizar o fonte e simplificar fonte, vai descobrindo técnicas/recursos que ajudam nisso.
A conclusão é que tem tudo a ver, é só começar que aos poucos tudo vém naturalmente.
Quanto a esse, pera aí que estou tentando verificar se nesse caso se aplica.
Práticas que facilitam programar Clipper/Harbour
Enviado: 14 Jan 2016 09:27
por JoséQuintas
Nem sempre dá pra aplicar o FOR EACH, depende muito do contexto.
E também não existe uma regra fixa de como usar.
Código: Selecionar todos
FOR nIdx := 1 to 25 STEP 2
nLinha ++
RestScreen(nIdx, 0, nIdx+1, 79, cTAbertura[nLinha])
SysWait(.01)
NEXT
À primeira vista é uma rotina pra retornar textos na tela, onde aí é apenas uma página.
Sendo assim, o assunto principal seria cTAbertura.
Código: Selecionar todos
nIdx := 1
FOR EACH oElement IN cTAbertura
RestScreen( nIdx, 0, nIdx + 1, 79, oElement )
SysWait( .01 )
nIdx += 2
IF nIdx > 25
// mudar página? ou EXIT?
nIdx := 1
ENDIF
NEXT
E internamente seria o controle de "quebra de página", ou algo parecido.
No meu ponto de vista, só é interessante alterar se a rotina completa tratar todo conteúdo de cTAbertura.
Vai de cada um.
Práticas que facilitam programar Clipper/Harbour
Enviado: 14 Jan 2016 11:42
por asimoes
Quintas,
Voltando ao assunto FOR EACH tem esses dois métodos muito úteis:
__enumIndex() equivalente a variável I:
FOR I:=1 TO Len(aVator)
NEXT
__enumIsLast() testa se i = Len(aVetor)
Código: Selecionar todos
cCampos:=""
FOR EACH aCampos IN aTheDBF
cCampos+=IF(aCampos:__enumIndex() > 1,Space(1),"")+cNomeCampo + ' ' + cDecode + IF(!aCampos:__enumIsLast(),",",")")+ IF(!aCampos:__enumIndex(),HB_EOL(),"")
NEXT
Práticas que facilitam programar Clipper/Harbour
Enviado: 14 Jan 2016 12:10
por JoséQuintas
São interessantes.
Mas no caso desse uso, ficou complicado de entender o fonte, eu mesmo não entendi direito.
Me parece inclusive que tem erro.
Se entendi direito, deve ser algo parecido com isto:
Código: Selecionar todos
cCampos := ""
FOR EACH cNomeCampo IN aTheDBF
cCampos += Space(1) + cNomeCampo + ' ' + cDecode + ","
NEXT
cCampos := Ltrim( Substr( cCampos, 1, Len( cCampos ) - 1 ) ) + ")" + hb_eol()
Lembre-se o fonte é pra nós, não para o compilador.
Se ficar difícil, pior pra nós.
Práticas que facilitam programar Clipper/Harbour
Enviado: 14 Jan 2016 12:24
por asimoes
No meu exemplo o destaque é para
oElemento:__enumIndex() e oElemento:__enumIsLast()
Código: Selecionar todos
aVetor:={"A", "B", "C"}
cValor:=""
FOR EACH oElemento IN aVetor
cValor += oElemento + IF(!oElemento:__enumIsLast(), ",", "")
NEXT
cValor:=""
FOR EACH oElemento IN aVetor
cValor += StrZero(oElemento:__enumIndex,2)+" "+oElemento + IF(!oElemento:__enumIsLast(), ", ", "")
NEXT
1º Resulta: A,B,C
2º Resulta: 01 A, 02 B, 03 C
Práticas que facilitam programar Clipper/Harbour
Enviado: 14 Jan 2016 12:36
por JoséQuintas
ok, era apenas pra mostrar que existe a opção de obter mais informações da variável do FOR EACH.
Em todo caso, só pra lembrar:
Nosso maior tempo é gasto em alterações, então o fonte tem que ser voltado pra ganhar tempo em alteração.
Olhou, entendeu, alterou, fim.
Olhou, não entendeu, já se começa a perder tempo a partir daí.
Só compensa complicar em casos extremos, aonde milésimos de segundo fizerem diferença.
Ainda não peguei um caso assim.
Práticas que facilitam programar Clipper/Harbour
Enviado: 14 Jan 2016 12:48
por asimoes
A questão é se vai usar FOR EACH conheça bem os recursos que pode utilizar.
Práticas que facilitam programar Clipper/Harbour
Enviado: 14 Jan 2016 12:55
por asimoes
Um exemplo que está no changelog.txt
Código: Selecionar todos
proc main()
local v, h:={"a"=>1.000,"b"=>2.000,"c"=>3.000}
heval( h, { |k,v,i| qout( k, v, i ) } ); ?
for each v in h
? v, "=>", v:__enumKey(), v:__enumValue(), v:__enumIndex(), ;
valtype(v:__enumBase())
v += 0.123
next
? ;heval( h, { |k,v,i| qout( k, v, i ) } )
return
Práticas que facilitam programar Clipper/Harbour
Enviado: 14 Jan 2016 13:00
por JoséQuintas
Acho essa invenção péssima, variável hash.
E tem gente que ainda abusa.
Práticas que facilitam programar Clipper/Harbour
Enviado: 17 Jan 2016 13:48
por fladimir
Quintas,
Dentro das práticas q facilitam programar Clipper/Harbour vc mencionou q acha péssima etc...
Gostaria de saber pq?
Eu uso para tratar arquivos INI
Exemplo:
Código: Selecionar todos
...
hINI := HB_ReadIni( cArqZ ) // ATENCAO É CASE SENSITIVE.
aGet := Inicia_Var(aGet, "MAPARES")
aGet[D_DATAMOVZ] := CTOD( hINI["ECF"]["DATAMOVIMENTO"] ) //= 09/12/13
aGet[D_NUMSERIE] := hINI["ECF"]["NUMSERIE"] //= 00000000000000000001
*-- Verifica se a Chave existe no Hash
if HHasKey( hINI["TOTALIZADORES"], "GRANDETOTAL" )
aGet[D_GT_FINAL] := StrToVal( hINI["TOTALIZADORES"]["GRANDETOTAL"] )
endif
aGet[D_DESCONTOS] := StrToVal( hINI["TOTALIZADORES"]["TOTALDESCONTOS"] )
...
Práticas que facilitam programar Clipper/Harbour
Enviado: 17 Jan 2016 15:54
por JoséQuintas
Desse jeito você não consegue validar o fonte.
Acontece isso com variável PRIVATE, PUBLIC, variável HASH, até mesmo classes e métodos.
No caso de hash, um .CH pode ajudar.
Acho até que foi feito só pra compatibilidade com xHarbour.
Quanto ao INI, não deixa de ser uma opção.
Mas prefiro XML mesmo, mais prático e com mais recursos.
No caso de classes e métodos... vale a pena o risco.
Práticas que facilitam programar Clipper/Harbour
Enviado: 18 Jan 2016 11:22
por JoséQuintas
Uia, a compilação -w3 -es2 acabou de me salvar.
d:\CDROM\FONTES\HAROLDO>hbmk2 hl.hbp -comp=msvc
hbmk2: Processing environment options: -comp=msvc
hbmk2: Building sub-project (level 2): libjose.hbp
hbmk2: Processing environment options: -comp=msvc
hbmk2: Target up to date: libjose.lib
hbmk2: Compiling Harbour sources...
Harbour 3.4.0dev (0a127e0) (2016-01-15 01:54)
Copyright (c) 1999-2016,
https://github.com/vszakats/harbour-core/
Compiling 'VHLAL01.prg'...
VHLAL01.prg(646) Warning W0032 Variable 'CPALAVRA' is assigned but not used in function 'MYSQLENDERECOLIKE(642)'
Apaguei uma linha a mais do fonte sem querer, aonde usava cPalavra, por isso o erro.
Se não fosse a compilação -w3 -es2, ia demorar muuuito pra descobrir isso.
Como ela avisou, o fonte anterior estava na mão.
Na correria do dia a gente não percebe esses detalhes.
A compilação -w3 -es2 não é apenas uma checagemzinha de escrever o fonte direito.
E também não é só na hora de criar um fonte novo.
É uma ajuda SEMPRE, pra qualquer alteração.
Acho que quando mencionei sobre a compilação com -w3 -es2 não chamei a atenção pra isso.
Imagine nesse caso acima, é um módulo com umas 15 opções de pesquisa diferentes, e a linha que apaguei era usada somente em uma determinada condição.
Eu iria demorar meses pra descobrir o que aconteceu.
Na compilação -w3 -es2 foi instantâneo, já mostrou no instante em que apaguei a linha.
É programar sem erros, mesmo errando.... rs
Práticas que facilitam programar Clipper/Harbour
Enviado: 18 Jan 2016 11:29
por JoséQuintas
O programa git também ajuda a conferir as alterações.
Acabei de alterar na parte de cima de um jeito, e alterei a parte de baixo de outro.
No fonte as coisas ficam longe, no git fica pertinho.
Dá pra conferir exatamente o que foi alterado.
Se o erro anterior passasse na compilação, talvez eu pegasse por aqui, porque ia mostrar que apaguei aquela linha.
Práticas que facilitam programar Clipper/Harbour
Enviado: 09 Jul 2016 11:11
por JoséQuintas
Reavaliando o post do ASimões:
Código: Selecionar todos
cCampos:=""
FOR EACH aCampos IN aTheDBF
cCampos+=IF(aCampos:__enumIndex() > 1,Space(1),"")+cNomeCampo + ' ' + cDecode + IF(!aCampos:__enumIsLast(),",",")")+ IF(! aCampos:__enumIndex(),HB_EOL(),"")
NEXT
Sinceramente, não entendi o que ele faz, vamos por bloco.
Código: Selecionar todos
cCampos := ""
FOR EACH aCampos IN aTheDBF
cCampos += ;
IF(aCampos:__enumIndex() > 1, Space(1), "" ) + ; // ok, só no primeiro não tem espaço, poderia ser AllTrim() fora do loop
cNomeCampo + ; // de onde vém isso?
' ' + ;
cDecode + ; // de onde vém isso?
IF( ! aCampos:__enumIsLast(), ",", ")" ) + ; // ok, no último é ")", nos demais ",", poderia trocar no final fora do loop
IF( ! aCampos:__enumIndex(), HB_EOL(), "" ) // não sei pra que serve isto. Se __enumindex() é número, tá esquisito.
NEXT
Provavelmente era o começo da alteração, e o fonte ficou parcial.
Práticas que facilitam programar Clipper/Harbour
Enviado: 28 Set 2016 13:43
por JoséQuintas
Uma pequena melhoria que uso nos GETs.
Uso um bloco alterado na GETSYS - a parte com by JPA
Código: Selecionar todos
DO WHILE ! nPos == 0
aVarGet := Array( Len( GetList ) ) // by JPA to otimize screen update
FOR EACH oElement IN GetList // by JPA to otimize screen update
aVarGet[ oElement:__EnumIndex ] := oElement:VarGet()
NEXT
// GET NEXT GET from list and post it as the active GET
PostActiveGet( oGet := GetList[ nPos ] )
// Read the GET
IF ( VALTYPE( oGet:reader ) == "B" )
EVAL( oGet:reader, oGet ) // Use custom reader block
ELSE
GetReader( oGet, lIsMouse ) // Use standard reader
ENDIF
FOR EACH oElement IN GetList // by JPA to otimize screen update
IF aVarGet[ oElement:__EnumIndex ] != oElement:VarGet()
oElement:Display()
ENDIF
NEXT
// Move to NEXT GET based on EXIT condition
nPos := Settle( GetList, nPos )
ENDDO
Nada demais, só atualiza a tela caso o conteúdo do GET tenha sido alterado.
Muito útil quando a digitação altera o conteúdo de outros GETs, porque na GETSYS normal isso só acontece se passar pelo GET.
Código: Selecionar todos
#include "hbclass.ch"
PROCEDURE Main
SetMode( 35, 100 )
SetColor( "W/B,N/W,,,W/B" )
CLS
Nota := NotaClass():New()
@ 1, 0 SAY "Valor da Nota:" GET Nota:Valor VALID Nota:CalculaImpostos()
@ 2, 0 SAY "Base ICMS....:" GET Nota:IcmBase WHEN .F.
@ 3, 0 SAY "Base Reducao.:" GET Nota:IcmReducao VALID Nota:CalculaImpostos()
@ 4, 0 SAY "Alíquota.....:" GET Nota:IcmAliquota VALID Nota:CalculaImpostos()
@ 5, 0 SAY "Valor ICMS...:" GET Nota:IcmValor WHEN .F.
@ 6, 0 SAY "Base ST......:" GET Nota:StBase WHEN .F.
@ 7, 0 SAY "IVA..........:" GET Nota:StIVA VALID Nota:CalculaImpostos()
@ 8, 0 SAY "Aliq.ST......:" GET Nota:StAliquota VALID Nota:CalculaImpostos()
@ 9, 0 SAY "Valor ST.....:" GET Nota:StValor WHEN .F.
READ
CREATE CLASS NotaClass
VAR Valor INIT 0
VAR IcmBase INIT 0
VAR IcmReducao INIT 0
VAR IcmAliquota INIT 0
VAR IcmValor INIT 0
VAR StBase INIT 0
VAR StIVA INIT 0
VAR StAliquota INIT 0
VAR StValor INIT 0
METHOD CalculaImpostos()
END CLASS
METHOD CalculaImpostos()
::IcmBase := ::Valor - ( Int( ::Valor * ::IcmReducao ) / 100 )
::IcmValor := Int( ::IcmBase * ::IcmAliquota ) / 100
::StBase := ::IcmBase + ( Int( ::IcmBase * ::StIVA / 100 ) )
::StValor := Max( 0, Int( ::StBase * ::StAliquota ) / 100 - ::IcmValor )
SetPos( 11, 0 )
? "Icmbase:", ::IcmBase, "STBase", ::StBase
RETURN .T.
Sem alterar a getsys, valores errados na tela, ou necessidade de fonte adicional:
Código: Selecionar todos
Valor da Nota: 100
Base ICMS....: 100.00
Base Reducao.: 20
Alφquota.....: 10
Valor ICMS...: 8.00
Base ST......: 80.00
IVA..........: 50
Aliq.ST......: 10
Valor ST.....: 4.00
Icmbase: 80.00 STBase 120.00
Até lembrei das estorinhas de criança, que tinham o "moral da estória".
Acho que isso era algo do tipo: "use a cabeça e pense".
Qual o moral da estória aqui:
Problema resolvido de vez, sem complicar os fontes de trabalho.
Se é pra complicar, que seja pra simplificar.