This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
baeshra's profile picture

[SOLVED] Complex String Variables

Started by baeshra, 05 April 2013 - 11:28 AM
baeshra #1
Posted 05 April 2013 - 01:28 PM
I have a decently complex question to ask. I'm not sure if I'm capable of wording it correctly, so bear with me and if you need to, ask for clarification.

I have a simple rednet system hooked up to act as my control room. The idea is that all of my systems and machines send update messages on their progress, status, and more. Let's say I want to send the message "Tree100001" from the tree farm. The first 5 digits, "Tree1" is the variable I want to set back at my control room computer. The last 5 digits, "00001" is the value I want to set it to. How would I go about doing this? Right now my control room computer receives the message and sets the value of the variable part to the string "1st 5 digits".

Short Question: I have a string. I can separate the string. I want to set the variable specified in the first half of the string to the value specified in the second half.

How would I go about doing this?
Telokis #2
Posted 05 April 2013 - 01:34 PM
You should take a look on lua's sub function:


local text = "HelloAll"
print(text:sub(1, 5)) -- Prints "Hello"
print(text:sub(6)) -- Prints "All"

Does it help you ?

EDIT : Too fast for you !
SuicidalSTDz #3
Posted 05 April 2013 - 01:34 PM
Use the string library:


local foo = "Something"
local word = string.sub(foo,5,#foo) --sub the string starting at 1 to 4. We will be left with 5 to the end of the word or #foo
print(word)
>thing

EDIT: Damn ninja's!
Telokis #4
Posted 05 April 2013 - 01:38 PM
Moreover, I should advice you to use a table instead of this.
Example:


local tData = {} -- Declare our table
tData["Tree1"] = 00001 -- Set the "Tree1" value of our table to 00001

You have to use sub (see my previous post) to correctly fill your table !
baeshra #5
Posted 05 April 2013 - 01:59 PM
I'm already using sub. I can segment the input just fine into a variable, part,with value "Tree1" and a variable, numb,with value 00001. I need to be able to then set Tree1 to numb. How do I get the variable of part into a form in which I can set it? None of the above answers are what I'm looking for.

I have an idea, testing it now
Telokis #6
Posted 05 April 2013 - 02:02 PM

list = {[part]=numb}

Should work, doesn't it ?
Engineer #7
Posted 05 April 2013 - 02:04 PM
Well you can do something like this if this is what you are looking for:

local var = ''tree''.. tostring(1000001)

is this what you were looking for? If not please clarify it more
Telokis #8
Posted 05 April 2013 - 02:05 PM
I think he wants to create a variable named "Tree1" dynamically.
baeshra #9
Posted 05 April 2013 - 02:10 PM
Sorry that I'm having issues clarifying here.


string.sub(part,1,5) = tonumber(string.sub(part,6,10))
I want something that would function as the above. For some reason it gives an error when trying to run it.

Thanks so much for the quick help.
Engineer #10
Posted 05 April 2013 - 02:12 PM
Combined with nine above;

You want to sent the variable dont you,

local var = {}
var['tree1'] = 00001
rednet.send(id, textutils.serialize(var))

--receiver
local id, message = rednet.receive()
local temp = textutils.unserialize(message)
print( temp['tree1'] )

edit nvm this.
baeshra #11
Posted 05 April 2013 - 02:16 PM
I've never seen the textutils.serialize before. I did a quick check on the wiki and believe I know what it does, would you mind explaining?

I feel like there should be an easy way to do this that I'm just missing.
Symmetryc #12
Posted 05 April 2013 - 02:21 PM
Use string.sub(<yourstring>,-5,-1) to get the last 5 digits of the string and use string.sub(<yourstring>,1, -6) to get everything but the last 5 digits.
baeshra #13
Posted 05 April 2013 - 02:26 PM
Use string.sub(<yourstring>,-5,-1) to get the last 5 digits of the string and use string.sub(<yourstring>,1, -6) to get everything but the last 5 digits.
If you would read the rest of the OP or any of the following replies you would know that is not the issue. I can do that part just fine…
Engineer #14
Posted 05 April 2013 - 02:28 PM
I've never seen the textutils.serialize before. I did a quick check on the wiki and believe I know what it does, would you mind explaining?

I feel like there should be an easy way to do this that I'm just missing.
Well, I actually dont know if its even usefull over rednet. But generally its better to do this, because you can get it better back so to say. Now I think about it, it sort of makes an table to a string and then reversed. Im not a pro to this so correct me
If Im wrong
Kingdaro #15
Posted 05 April 2013 - 02:31 PM
If you really want to do it this way:


-- assuming rednet is open

-- first computer
rednet.send('var 5')

-- receiving computer
local _, msg = rednet.receive()                -- get message
local var, value = msg:match('([%w_]+) (.+)')  -- extract variable name and value

value =                                        -- attempt to convert/parse/find value
  value:match [["(.+)"]] or                    -- try for a string
  value:match [['(.+)']] or
  value:match "[[.+]]" or
  tonumber(value) or                           -- try for a number
  value == 'true' and true or                  -- try for a boolean
  value == 'false' and false or
  getfenv()[value] or nil                      -- try for a variable defined in our scope

_G[var] = value

This code would set a global variable named "var" to 5. But this is like, really bad practice I'm pretty sure, and it's way safer and more stable to just use serialization.
baeshra #16
Posted 05 April 2013 - 02:33 PM
Sorry, I'm new. I don't understand half of the code above… Would you be able to explain in more detail how to use serialization to accomplish this?
Kingdaro #17
Posted 05 April 2013 - 02:38 PM
Serialization is, instead of actually setting the variable on the other end, just accepting a table with the values you need, as explained by Engineer at post #10. It's much simpler, way more organized, and makes it so that you don't have a bunch of global vars cluttering up your script.

What I did was a bunch of string matching and environment screwery that shouldn't really be touched.
Telokis #18
Posted 05 April 2013 - 02:42 PM
Baeshra, do you know about tables ?
I think it is the best way to do what you want to do !
Symmetryc #19
Posted 05 April 2013 - 02:44 PM
Use string.sub(<yourstring>,-5,-1) to get the last 5 digits of the string and use string.sub(<yourstring>,1, -6) to get everything but the last 5 digits.
If you would read the rest of the OP or any of the following replies you would know that is not the issue. I can do that part just fine…
Is this what you want?

local messages = {}
local function interpretMessage(a)
	string = string.sub(a, -5, -1)
	value = string.sub(a, 1, -6)
	messages[tonumber(value)] = string
end
It makes a table called "messages" and puts each message in it and sets its value to its last 5 digits.
baeshra #20
Posted 05 April 2013 - 02:48 PM
That might work… I'll do some testing. I apologize that I can't make use of some of the advice I've been given simply because I don't understand it.

Thanks again guys.
Telokis #21
Posted 05 April 2013 - 02:51 PM
That might work… I'll do some testing. I apologize that I can't make use of some of the advice I've been given simply because I don't understand it.

Thanks again guys.

If you want to check all of your message, you can do :


for part, numb in pairs(messages) do
-- Anything you want to do.
-- With your example, part will be "Tree1" and numb will be "00001".
end
SuicidalSTDz #22
Posted 05 April 2013 - 02:55 PM
Ah, serialization. Confusing people since, well, since it was founded..
baeshra #23
Posted 05 April 2013 - 03:13 PM
I'm attempting to get Ninetainedo's method to work as serialization scares me as of now. Here's my current code:


tb = {}
localsenderId, msg, distance = rednet.receive() --Receives message
dat = string.sub(msg,1,5)									--Takes first half of message and stores it as dat
datc = string.sub(msg,6,10)								--Takes second half of message and stores it as dat
tb[tonumber(dat)] = tonumber(datc)					--Stores datc in the table tb under slot dat
print(tb[tonumber(dat)])							 		  --Prints the value of tb in slot dat

Why doesn't this work? It gives me the error "attempt to call nill" when I send it 0000100005
Telokis #24
Posted 05 April 2013 - 03:15 PM
Which line is the error on ?
baeshra #25
Posted 05 April 2013 - 03:15 PM
On the very bottom line.
Telokis #26
Posted 05 April 2013 - 03:27 PM
Could you try to put some print in your code ?
Just to show variable contents
Symmetryc #27
Posted 05 April 2013 - 03:27 PM
I'm attempting to get Ninetainedo's method to work as serialization scares me as of now. Here's my current code:


tb = {}
localsenderId, msg, distance = rednet.receive() --Receives message
dat = string.sub(msg,1,5)									--Takes first half of message and stores it as dat
datc = string.sub(msg,6,10)								--Takes second half of message and stores it as dat
tb[tonumber(dat)] = tonumber(datc)					--Stores datc in the table tb under slot dat
print(tb[tonumber(dat)])							 		  --Prints the value of tb in slot dat

Why doesn't this work? It gives me the error "attempt to call nill" when I send it 0000100005
You've switched the message and number, you're turning the message into a number, and it won't work if your message is longer than 5 characters, try using this:

local messages = {}
id, msg, dist = rednet.receive()
message = string.sub(msg, 1, -6)
value = string.sub(msg, -5, -1)
messages[tonumber(value)] = message
print(messages[tonumber(value)])
Telokis #28
Posted 05 April 2013 - 03:31 PM
I'm attempting to get Ninetainedo's method to work as serialization scares me as of now. Here's my current code:


tb = {}
localsenderId, msg, distance = rednet.receive() --Receives message
dat = string.sub(msg,1,5)									--Takes first half of message and stores it as dat
datc = string.sub(msg,6,10)								--Takes second half of message and stores it as dat
tb[tonumber(dat)] = tonumber(datc)					--Stores datc in the table tb under slot dat
print(tb[tonumber(dat)])							 		  --Prints the value of tb in slot dat

Why doesn't this work? It gives me the error "attempt to call nill" when I send it 0000100005
You've switched the message and number, you're turning the message into a number, and it won't work if your message is longer than 5 characters, try using this:

local messages = {}
id, msg, dist = rednet.receive()
message = string.sub(msg, 1, -6)
value = string.sub(msg, -5, -1)
messages[tonumber(value)] = message
print(messages[tonumber(value)])

I think it won't work as he expects.


@Baeshra: First, try your code without any "tonumber". We'll see if it works
Symmetryc #29
Posted 05 April 2013 - 03:37 PM
I'm attempting to get Ninetainedo's method to work as serialization scares me as of now. Here's my current code:


tb = {}
localsenderId, msg, distance = rednet.receive() --Receives message
dat = string.sub(msg,1,5)									--Takes first half of message and stores it as dat
datc = string.sub(msg,6,10)								--Takes second half of message and stores it as dat
tb[tonumber(dat)] = tonumber(datc)					--Stores datc in the table tb under slot dat
print(tb[tonumber(dat)])							 		  --Prints the value of tb in slot dat

Why doesn't this work? It gives me the error "attempt to call nill" when I send it 0000100005
You've switched the message and number, you're turning the message into a number, and it won't work if your message is longer than 5 characters, try using this:

local messages = {}
id, msg, dist = rednet.receive()
message = string.sub(msg, 1, -6)
value = string.sub(msg, -5, -1)
messages[tonumber(value)] = message
print(messages[tonumber(value)])

I think it won't work as he expects.


@Baeshra: First, try your code without any "tonumber". We'll see if it works
Then maybe I'm missing something…let me explain to you by commenting the code:

local messages = {}                 --Creates a table that holds all of the messages
id, msg, dist = rednet.receive()				 --Receives string from rednet
message = string.sub(msg, 1, -6)			  --Gets the message
value = string.sub(msg, -5, -1)					   --Gets the value
messages[tonumber(value)] = message		  --Puts the message into the table in the place of the value
print(messages[tonumber(value)])					--Prints
So if the user put in the message "Tree100004" then messages["Tree1"]==4
baeshra #30
Posted 05 April 2013 - 03:41 PM
You've switched the message and number, you're turning the message into a number, and it won't work if your message is longer than 5 characters, try using this:

This shouldn't matter because I am no longer sending any letters. I'm sending 0000100005. It should set the value of row 1 to 5, correct?

Edit: The error lies further up than the bottom. It's not correctly setting dat and datc for some reason…
Symmetryc #31
Posted 05 April 2013 - 03:44 PM
You've switched the message and number, you're turning the message into a number, and it won't work if your message is longer than 5 characters, try using this:

This shouldn't matter because I am no longer sending any letters. I'm sending 0000100005. It should set the value of row 1 to 5, correct?

Edit: The error lies further up than the bottom. It's not correctly setting dat and datc for some reason…
Try my code, I think it might help, it is compatible with both strings and numbers.
Telokis #32
Posted 05 April 2013 - 03:48 PM
I'm attempting to get Ninetainedo's method to work as serialization scares me as of now. Here's my current code:


tb = {}
localsenderId, msg, distance = rednet.receive() --Receives message
dat = string.sub(msg,1,5)									--Takes first half of message and stores it as dat
datc = string.sub(msg,6,10)								--Takes second half of message and stores it as dat
tb[tonumber(dat)] = tonumber(datc)					--Stores datc in the table tb under slot dat
print(tb[tonumber(dat)])							 		  --Prints the value of tb in slot dat

Why doesn't this work? It gives me the error "attempt to call nill" when I send it 0000100005
You've switched the message and number, you're turning the message into a number, and it won't work if your message is longer than 5 characters, try using this:

local messages = {}
id, msg, dist = rednet.receive()
message = string.sub(msg, 1, -6)
value = string.sub(msg, -5, -1)
messages[tonumber(value)] = message
print(messages[tonumber(value)])

I think it won't work as he expects.


@Baeshra: First, try your code without any "tonumber". We'll see if it works
Then maybe I'm missing something…let me explain to you by commenting the code:

local messages = {}				 --Creates a table that holds all of the messages
id, msg, dist = rednet.receive()				 --Receives string from rednet
message = string.sub(msg, 1, -6)			  --Gets the message
value = string.sub(msg, -5, -1)					   --Gets the value
messages[tonumber(value)] = message		  --Puts the message into the table in the place of the value
print(messages[tonumber(value)])					--Prints
So if the user put in the message "Tree100004" then messages["Tree1"]==4

There is an issue because you will have messages[4] = "Tree1" with your code.
baeshra #33
Posted 05 April 2013 - 03:55 PM
Whatever the problem was, I fixed it. I now have code working nicely. This is what I ended up with:


tb = {}
local dat = ""
local datc = ""

localsenderId, msg, distance = rednet.receive()
dat = tonumber(string.sub(msg,1,5))                                                
datc = tonumber(string.sub(msg,6,10))                                           
tb[dat] = datc                             
print(tb[dat])                                                


Thanks for all the help guys.
Telokis #34
Posted 05 April 2013 - 03:56 PM
Whatever the problem was, I fixed it. I now have code working nicely. This is what I ended up with:


tb = {}
local dat = ""
local datc = ""

localsenderId, msg, distance = rednet.receive()
dat = tonumber(string.sub(msg,1,5))												
datc = tonumber(string.sub(msg,6,10))										  
tb[dat] = datc							
print(tb[dat])												


Thanks for all the help guys.

If I can ask you something : why do you convert dat into number ?
Wasn't it supposed to be a string ? ("Tree1"…)
Symmetryc #35
Posted 05 April 2013 - 04:00 PM
I'm attempting to get Ninetainedo's method to work as serialization scares me as of now. Here's my current code:


tb = {}
localsenderId, msg, distance = rednet.receive() --Receives message
dat = string.sub(msg,1,5)									--Takes first half of message and stores it as dat
datc = string.sub(msg,6,10)								--Takes second half of message and stores it as dat
tb[tonumber(dat)] = tonumber(datc)					--Stores datc in the table tb under slot dat
print(tb[tonumber(dat)])							 		  --Prints the value of tb in slot dat

Why doesn't this work? It gives me the error "attempt to call nill" when I send it 0000100005
You've switched the message and number, you're turning the message into a number, and it won't work if your message is longer than 5 characters, try using this:

local messages = {}
id, msg, dist = rednet.receive()
message = string.sub(msg, 1, -6)
value = string.sub(msg, -5, -1)
messages[tonumber(value)] = message
print(messages[tonumber(value)])

I think it won't work as he expects.


@Baeshra: First, try your code without any "tonumber". We'll see if it works
Then maybe I'm missing something…let me explain to you by commenting the code:

local messages = {}				 --Creates a table that holds all of the messages
id, msg, dist = rednet.receive()				 --Receives string from rednet
message = string.sub(msg, 1, -6)			  --Gets the message
value = string.sub(msg, -5, -1)					   --Gets the value
messages[tonumber(value)] = message		  --Puts the message into the table in the place of the value
print(messages[tonumber(value)])					--Prints
So if the user put in the message "Tree100004" then messages["Tree1"]==4

There is an issue because you will have messages[4] = "Tree1" with your code.
Oh, whoops, I see what you mean now you wanted to have the message have an Id so that you can refer to the message using it, I thought you wanted the value to be an operation, so you wanted to store it within the value, but whatever, it works now.
baeshra #36
Posted 05 April 2013 - 04:04 PM
Yup. Thanks again guys.
vidiot5533 #37
Posted 26 October 2013 - 12:12 PM
What I am understanding is that you want a variable with the name of the first part of the message, with the value of the second part. You already have the parts broken down, so the main difficulty is setting a variable name. This might help:

sorry, code wasnt entered correctly. newbie mistake, but all the same it will work. pasting it again correctly for ease of reading


function makeVar(varname,var)
    getfenv()[varname]=var --sets variable in environment
end
varname="tree1" --the name of the variable you want to set
var="00001"	    --the value you want to set it to
makeVar(varname,var) --calls the function above
print(tree1) --prints "00001"
Lyqyd #38
Posted 26 October 2013 - 04:50 PM
Please be sure to read the whole topic before replying.