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

Input Math (E.g. 5+10*2) And Output Result?

Started by NomNuggetNom, 17 September 2013 - 02:23 PM
NomNuggetNom #1
Posted 17 September 2013 - 04:23 PM
Hey guys! On the lua console you can really easily input a math problem and get the simplified answer. However, if I ask for userInput and read it, I can't perform any arithmetic on it. Here's an example code:


print("Math?")
mathInput = read()
print(mathInput*2)

For example, if I input:

(5+5)*5
I should get:

100
theoriginalbit #2
Posted 17 September 2013 - 05:00 PM
this is because the input comes in as a string. What you need to do is convert the string into a number, before trying to calculate the result, with tonumber like so

print("Number: ")
local input = tonumber( read() )
print( input * 2 )
This also presents a problem of anything that is not a number the input variable is nil, so to combat this you should make a loop that will only continue when the input is a number, and tell the user when they didn't input a number.

For future reference, when asking for help in Ask a Pro, we require more information than you provided here in this one, especially if you want to get help quicker! Please have a read of this thread especially the last two sections before posting again as it is important to us that your threads contain as much information as possible so we can help you quickly and to the best of our knowledge/ability…
Yevano #3
Posted 17 September 2013 - 05:23 PM
this is because the input comes in as a string. What you need to do is convert the string into a number, before trying to calculate the result, with tonumber like so

print("Number: ")
local input = tonumber( read() )
print( input * 2 )
This also presents a problem of anything that is not a number the input variable is nil, so to combat this you should make a loop that will only continue when the input is a number, and tell the user when they didn't input a number.

This doesn't really answer his question. He wants to evaluate expressions from input, not just convert strings to numbers.

The reason it works in the lua prompt is because the math expressions are loaded as valid Lua expressions. The simplest solution is to do something like


local input = read()                                    -- Get input.
local eval, err = loadstring("return " .. input)        -- Compile the string.
if err then print("Could not evaluate. " .. err) end    -- Check for a parse error.
print(eval())                                           -- Print the result.

The only problem here is that literally any Lua code can be run using this method, so you should take care to put on your own restrictions. Alternatively, one could build a custom expression parser, but this is far more complex.
CCJJSax #4
Posted 17 September 2013 - 05:53 PM
Hey guys! On the lua console you can really easily input a math problem and get the simplified answer. However, if I ask for userInput and read it, I can't perform any arithmetic on it. Here's an example code:


print("Math?")
mathInput = read()
print(mathInput*2)

For example, if I input:

(5+5)*5
I should get:

100

Um…. (5+5) * 5 doesn't equal 100… it equals 50 ;)/>

Edit: Nevermind. I see the *2 now. My bad :D/> hehe
NomNuggetNom #5
Posted 17 September 2013 - 06:59 PM
this is because the input comes in as a string. What you need to do is convert the string into a number, before trying to calculate the result, with tonumber like so

print("Number: ")
local input = tonumber( read() )
print( input * 2 )
This also presents a problem of anything that is not a number the input variable is nil, so to combat this you should make a loop that will only continue when the input is a number, and tell the user when they didn't input a number.

For future reference, when asking for help in Ask a Pro, we require more information than you provided here in this one, especially if you want to get help quicker! Please have a read of this thread especially the last two sections before posting again as it is important to us that your threads contain as much information as possible so we can help you quickly and to the best of our knowledge/ability…
Sorry about not providing enough info. I never know what to give and what not to give. Unfortunately this won't really solve my problem, as Yevano explained..

this is because the input comes in as a string. What you need to do is convert the string into a number, before trying to calculate the result, with tonumber like so

print("Number: ")
local input = tonumber( read() )
print( input * 2 )
This also presents a problem of anything that is not a number the input variable is nil, so to combat this you should make a loop that will only continue when the input is a number, and tell the user when they didn't input a number.

This doesn't really answer his question. He wants to evaluate expressions from input, not just convert strings to numbers.

The reason it works in the lua prompt is because the math expressions are loaded as valid Lua expressions. The simplest solution is to do something like


local input = read()									-- Get input.
local eval, err = loadstring("return " .. input)		-- Compile the string.
if err then print("Could not evaluate. " .. err) end	-- Check for a parse error.
print(eval())										   -- Print the result.

The only problem here is that literally any Lua code can be run using this method, so you should take care to put on your own restrictions. Alternatively, one could build a custom expression parser, but this is far more complex.
Okay, I'll try it, thanks!
Edit: This is perfect, thank you so much :)/>
Yevano #6
Posted 17 September 2013 - 07:15 PM
Edit: This is perfect, thank you so much :)/>

Glad I could help. :)/>
ElvishJerricco #7
Posted 17 September 2013 - 07:59 PM
To prevent any issues which may occur from load string, you can check the input string for illegal math characters.


local code = read()
assert(not code:find("[^0-9%s%+%-%*%/%%%^()]", "Enter maths!")
local num = assert(loadstring(code, "math"))()
BigTwisty #8
Posted 19 September 2013 - 10:59 AM

local code = read()
assert(not code:find("[^0-9%s%+%-%*%/%%%^()]", "Enter maths!")
local num = assert(loadstring(code, "math"))()

I was under the impression that Lua did not support full REGEX, i.e. "[0-9a-zA-Z]". Wouldn't that be "[^%d%s%+%-%*%/%%%^()]" ?
ElvishJerricco #9
Posted 19 September 2013 - 11:21 AM
I was under the impression that Lua did not support full REGEX, i.e. "[0-9a-zA-Z]". Wouldn't that be "[^%d%s%+%-%*%/%%%^()]" ?

That's another way to do it. And no, Lua doesn't support full regex. But it does work with "[0-9a-zA-Z]".
immibis #10
Posted 19 September 2013 - 05:21 PM
Don't use loadstring if security is important.
Even with only those characters allowed, someone could still enter:

shell.run(os.pullEvent().char(114)..os.pullEvent().char(109)..os.pullEvent().char(32)..os.pullEvent().char(115)..os.pullEvent().char(116)..os.pullEvent().char(097)..os.pullEvent().char(114)..os.pullEvent().char(116)..os.pullEvent().char(117)..os.pullEvent().char(112))
and then mash the keyboard a bit (so all the pullEvent calls return events), then use Ctrl-R, then have full access to the computer.

Edit: For some reason I thought string.char was blocked, but it's not, so just use string.char instead of os.pullEvent().char
BigTwisty #11
Posted 19 September 2013 - 05:51 PM
Don't use loadstring if security is important.
Even with only those characters allowed, someone could still enter:

shell.run(os.pullEvent().char(114)..os.pullEvent().char(109)..os.pullEvent().char(32)..os.pullEvent().char(115)..os.pullEvent().char(116)..os.pullEvent().char(097)..os.pullEvent().char(114)..os.pullEvent().char(116)..os.pullEvent().char(117)..os.pullEvent().char(112))
and then mash the keyboard a bit (so all the pullEvent calls return events), then use Ctrl-R, then have full access to the computer.

Edit: For some reason I thought string.char was blocked, but it's not, so just use string.char instead of os.pullEvent().char

The string checking suggested by Elvish should satisfy any security concerns.
ElvishJerricco #12
Posted 19 September 2013 - 10:35 PM
Don't use loadstring if security is important.
Even with only those characters allowed, someone could still enter:

shell.run(os.pullEvent().char(114)..os.pullEvent().char(109)..os.pullEvent().char(32)..os.pullEvent().char(115)..os.pullEvent().char(116)..os.pullEvent().char(097)..os.pullEvent().char(114)..os.pullEvent().char(116)..os.pullEvent().char(117)..os.pullEvent().char(112))
and then mash the keyboard a bit (so all the pullEvent calls return events), then use Ctrl-R, then have full access to the computer.

Edit: For some reason I thought string.char was blocked, but it's not, so just use string.char instead of os.pullEvent().char

Yea I'm not sure how exactly you figure that. If you only allow digits, white space, and operators, you can't enter letters like that.
immibis #13
Posted 20 September 2013 - 04:13 AM
My first ever CC program immicalc uses a recursive descent parser to parse expressions without using Lua.

For an easier way, use textutils.unserialize, which won't protect you from (function()while true do end end)()