Dividar string em Lua

borntonag

Power Member
Olá a todos.
Ando a dar os primeiros passos em Lua e estou aqui com um desafio na programação de um alarme.
Recebo do mesmo uma string (strData) que pode conter várias informações diferentes.
No caso em que tento armar o alarme e ele verifica se todas as zonas estou fechadas ou existe alguma aberta recebo uma string composta por um comando tipo "ERNN" em que o NN se for 00 significa que todas as zonas estão fechadas e arma o alarme ou 01, 02, etc. se a zona 1, zona 2, etc. estiver aberta e apresenta uma mensagem para fechar a respectiva zona.

Como posso separar a string para conseguir isolar o valor de NN numa variável? Este valor está em hexadecimal e teria de o converter para decimal.
É que se tal for possível isto resume-se a um ciclo e não uma secção de código para cada zona que o alarme tenha.

Exemplo:
Código:
for Arming in string.gmatch(strData, "ER00") do    
       C4:SendToProxy(5001, "DISPLAY_TEXT", "<text>Preparado para armar, aguarde...</text>")
   end

   for Arming_1 in string.gmatch(strData, "ER01") do   
       C4:SendToProxy(5001, "DISPLAY_TEXT", "<text>Impossivel armar. Zona 1 aberta.</text>")
   end

   for Arming_2 in string.gmatch(strData, "ER02") do   
       C4:SendToProxy(5001, "DISPLAY_TEXT", "<text>Impossivel armar. Zona 2 aberta.</text>")
   end

Esbocei qualquer coisa como:
Código:
     -- ler string e separar ER de NN e guardar numa variável, por exemplo, ER_hex
     -- converter NN_hex para NN_dec
     if NN_dec == 00
     C4:SendToProxy(5001, "DISPLAY_TEXT", "<text>Preparado para armar, aguarde...</text>")
     else
     C4:SendToProxy(5001, "DISPLAY_TEXT", "<text>Impossivel armar. Zona " .. NN_dec .. "aberta.</text>")
     end
 
Concordo, não faz sentido fazer uma condição para cada zona e o teu esboço faz sentido, mas o que é já tentaste? O problema parece fácil de resolver. Dá uma vista de olhos na biblioteca de strings de Lua e vê a função tonumber.
 
Concordo, não faz sentido fazer uma condição para cada zona e o teu esboço faz sentido, mas o que é já tentaste? O problema parece fácil de resolver. Dá uma vista de olhos na biblioteca de strings de Lua e vê a função tonumber.
Ainda não tentei nada em concreto porque ainda ando não sei separar a string.
Várias sugestões pela net para casos semelhantes sugerem dividir caracter a caracter e passa-los para uma tabela.
Deverá ser um bom ponto de partida mas ajudava imenso se alguém conseguisse esboçar esta função para dividir a string por caracteres e passar para uma tabela. Depois junto os caracteres dois a dois e está resolvido o problema maior.

Quanto à função tonumber, é mesmo essa!
 
Ainda não tentei nada em concreto porque ainda ando não sei separar a string.
Várias sugestões pela net para casos semelhantes sugerem dividir caracter a caracter e passa-los para uma tabela.
Deverá ser um bom ponto de partida mas ajudava imenso se alguém conseguisse esboçar esta função para dividir a string por caracteres e passar para uma tabela. Depois junto os caracteres dois a dois e está resolvido o problema maior.

Quanto à função tonumber, é mesmo essa!

Ok, eu fui vago na resposta porque parecia que estavas a fazer a pergunta sem ter procurado. Se as strings são sempre ER + hexadecimal, o string.sub resolve o problema, depois é só fazer o tonumber.
 
Agora que me surgiu outra dúvida reparei que não tinha deixado aqui o feedback da ajuda dada pelo nfk. De facto a função string.sub resolveu o problema sendo que o link foi o que usei para conseguir fazer o que queria.

A minha nova dúvida é como separar uma string por virgulas? Ainda à volta disto do alarme, a ideia é o utilizador dar nomes às zonas introduzindo por exemplo (sem as aspsas) "1,Quarto,2,Sala,3,WC" e conseguir separar tudo em variáveis diferentes.

A ideia que tenho é contar n blocos de dados (se for possível), que neste caso são 6, e depois fazer um ciclo de 1 até n e em cada um ir atribuindo a uma variável o numero da zona e a outra variável o nome.
Com esta estou mesmo às aranhas não tendo praticamente nada de útil implementado.

Código:
function ZonesNaming(nZones) -- Exemplo: 1,Quarto,2,Sala,3,WC
  local n -- numero de blocos, no exemplo acima existem 6 blocos
 
  for i = 1, n do ... end
 
end
 
Os números das zonas são sempre sequenciais começando em 1? Se sim, seria mais simpático pedir apenas os nomes e atribuir os números automaticamente.

Se não, primeiro tens de fazer o split da string por ",". Depois, os loops for têm um terceiro argumento opcional, o step, que permite saltar de dois em dois

Código:
for i = 1, n, 2 do
    process i
    process i+1
end
 
Ok percebi e realmente apenas vai ser preciso introduzir os nomes visto as zonas serem sequenciais e não ser possível "saltar" zonas.
A minha principal questão aqui é como separar a string por virgulas e atribuir o primeiro nome a z1, o segundo nome a z2 e por aí adiante...

Uma vez mais, obrigado pela ajuda nfk.
 
Depois de ver infinitos tópicos no Stack Overflow encontrei este onde sugeriram a seguinte solução:
Código:
local t = {}
local test = "10, 123; 1, 54"
for k, v in test:gmatch( "(%d+),%s?(%d+)" ) do
  t[k] = v
end

Ora adaptando ao meu caso esbocei a seguinte função:
Código:
function ZonesNaming(nZones) -- Exemplo: Quarto, WC
  local t = {}
 
  for k, v in nZones:gmatch( "(%d+),%s?(%d+)" ) do
  t[k] = v
  end
 
end
E chamo esta função utilizando o seguinte: ZonesNaming(znames)

Para já ainda não consegui pôr aqui o alarme a funcionar, não sei se a função está bem escrita ou até se é bem chamada.
A verdade é que quando é suposto o programa imprimir o nome da zona recebo a seguinte mensagem:
"[string "Lua Code"]:185: attempt to index global 't' (a nil value)"
 
Também tinha visto esse!
Entretanto consegui pôr isto a funcionar tal como pretendia. Acabei por escrever de outra forma a função que mencionei em cima mas o resultado será o mesmo.

Código:
function ZonesNaming(znames) -- Exemplo: znames = "Sala, Quarto, WC, ..."
  t = {}

  for match in string.gmatch(znames, "[^,]+") do
  table.insert(t, match)
  end
 
end
Inicialmente não estava a funcionar porque o vector 't' estava declarado localmente e eu imprimia-o fora dessa função.
 
É verdade que a função para separar a string por virgulas funcionou mas agora questiono-me como? O que é definido no segundo parâmetro da função string.gmatch(znames, "[^,]+")... ou seja o "[^,]+".
 
É verdade que a função para separar a string por virgulas funcionou mas agora questiono-me como? O que é definido no segundo parâmetro da função string.gmatch(znames, "[^,]+")... ou seja o "[^,]+".

O gmatch retorna um iterador com os matches que são encontrados na string, de acordo com o tal padrão "[^,]+". Este padrão é uma expressão regular. O "+" significa que vai encontrar sequências do que quer que esteja antes. Por exemplo, se fosse [abcd]+ encontrava sequências contendo apenas essas quatro letras. O "^", sendo o primeiro caracter dentro dos parênteses retos, é um prefixo de negação. Estando apenas a vírgula dentro dos parênteses, vão ser encontradas sequências de caracteres que não são vírgulas.
 
Back
Topo