AtNum
Conta quantas vezes uma substring aparece dentro de uma string. Diferente de At() que retorna POSICAO da primeira ocorrencia, AtNum retorna QUANTIDADE.
Assinatura: AtNum(cBusca, cString) -> nQtdOcorrencias
Retorna: Numeric
AtNum e o "contador de ocorrencias". Util pra validar formato (quantos pontos tem o decimal, quantas barras tem a data), e pra split simples.
Sintaxe
AtNum(cBusca, cString) --> nQtdOcorrencias
Diferenca At vs AtNum
| Funcao | Retorna |
|---|---|
At("X", cStr) | Posicao da primeira ocorrencia (1-base) ou 0 |
AtNum("X", cStr) | Quantidade total de ocorrencias |
RAt("X", cStr) | Posicao da ultima ocorrencia |
Exemplos
AtNum("a", "banana") // 3
AtNum("/", "13/05/2026") // 2
AtNum(".", "1.234.567,89") // 2
AtNum("@", "user@example.com") // 1
AtNum("@", "sem-arroba") // 0
AtNum("", "qualquer") // 0 (busca vazia)
Casos praticos
1. Validar formato de email simples
User Function VldEmail(cEmail)
Local lOk := .T.
// Email tem exatamente 1 arroba
If AtNum("@", cEmail) != 1
lOk := .F.
EndIf
// Tem pelo menos 1 ponto apos arroba
Local nArroba := At("@", cEmail)
If AtNum(".", SubStr(cEmail, nArroba)) < 1
lOk := .F.
EndIf
Return lOk
2. Contar separadores em CSV
cLinha := "001;PRODUTO A;10;99.90"
nCampos := AtNum(";", cLinha) + 1 // 4 campos
3. Validar data em formato BR
Static Function VldDataBR(cData)
// dd/mm/aaaa deve ter exatamente 2 barras
Return AtNum("/", cData) == 2 .And. Len(cData) == 10
Pegadinhas
- Case-sensitive —
AtNum("a", "ABA")retorna 1 (so o "a" minusculo). Pra ignorar case, normalize:AtNum("a", Lower(cStr)). - Busca vazia retorna 0 — nao causa loop infinito como em algumas linguagens.
- Sobreposicao nao conta duas vezes —
AtNum("aa", "aaaa")retorna 2, nao 3. - Performance O(n) — em strings gigantes (10k+ caracteres), pode pesar em loop.
Parâmetros
| Nome | Tipo | Obrigatório | Descrição |
|---|---|---|---|
cBusca | Character | sim | Substring procurada. |
cString | Character | sim | String onde procurar. |