Jump to content




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


  • This topic is locked This topic is locked
12 replies to this topic

#1 NomNuggetNom

  • Members
  • 16 posts

Posted 17 September 2013 - 03: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


#2 theoriginalbit

    Semi-Professional ComputerCrafter

  • Moderators
  • 7,332 posts
  • LocationAustralia

Posted 17 September 2013 - 04: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...

#3 Yevano

  • Members
  • 376 posts
  • LocationUSA

Posted 17 September 2013 - 04:23 PM

View Posttheoriginalbit, on 17 September 2013 - 04:00 PM, said:

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.

#4 CCJJSax

  • Members
  • 262 posts

Posted 17 September 2013 - 04:53 PM

View PostNomNuggetNom, on 17 September 2013 - 03:23 PM, said:

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

#5 NomNuggetNom

  • Members
  • 16 posts

Posted 17 September 2013 - 05:59 PM

View Posttheoriginalbit, on 17 September 2013 - 04:00 PM, said:

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..

View PostYevano, on 17 September 2013 - 04:23 PM, said:

View Posttheoriginalbit, on 17 September 2013 - 04:00 PM, said:

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 :)

#6 Yevano

  • Members
  • 376 posts
  • LocationUSA

Posted 17 September 2013 - 06:15 PM

View PostNomNuggetNom, on 17 September 2013 - 05:59 PM, said:

Edit: This is perfect, thank you so much :)

Glad I could help. :)

#7 ElvishJerricco

  • Members
  • 803 posts

Posted 17 September 2013 - 06: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"))()


#8 BigTwisty

  • Members
  • 106 posts

Posted 19 September 2013 - 09:59 AM

View PostElvishJerricco, on 17 September 2013 - 06:59 PM, said:

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%+%-%*%/%%%^()]" ?

#9 ElvishJerricco

  • Members
  • 803 posts

Posted 19 September 2013 - 10:21 AM

View PostBigTwisty, on 19 September 2013 - 09:59 AM, said:

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]".

#10 immibis

    Lua God

  • Members
  • 1,033 posts
  • LocationWellington, New Zealand

Posted 19 September 2013 - 04: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

#11 BigTwisty

  • Members
  • 106 posts

Posted 19 September 2013 - 04:51 PM

View Postimmibis, on 19 September 2013 - 04:21 PM, said:

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.

#12 ElvishJerricco

  • Members
  • 803 posts

Posted 19 September 2013 - 09:35 PM

View Postimmibis, on 19 September 2013 - 04:21 PM, said:

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.

#13 immibis

    Lua God

  • Members
  • 1,033 posts
  • LocationWellington, New Zealand

Posted 20 September 2013 - 03: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)()





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users