Reputation: 4639
I am an Erlang beginner and am trying to make a simple command-line application where the user enters the width and height of a floor, the cost per square foot of flooring and they are returned a price. Essentially I'm just accepting three integer values and returning the product.
23> c(costcalc).
{ok,costcalc}
24> costcalc:start().
Calculate the cost of flooring based on width, height, and cost per square foot.
Width in feet: 5
Height in feet: 5
Cost in dollars per square foot: $4
** exception error: an error occurred when evaluating an arithmetic expression in function costcalc:start/0 (costcalc.erl, line 23)
Here is the code I am using:
start() ->
io:format("Calculate the cost of flooring based on width, height, and cost per square foot.\n"),
W = string:to_integer(io:get_line("Width in feet: ")),
H = string:to_integer(io:get_line("Height in feet: ")),
C = string:to_integer(io:get_line("Cost in dollars per square foot: $")),
Cost = W * H * C,
io:fwrite(Cost).
Line 23 is Cost = W * H * C,
which should be 100. When I run 5 * 5 * 4.
in the shell directly it calculates without issue. I should also note that this happens whether or not I use string:to_integer() which I would imagine I can get by without.
What am I missing?
Upvotes: 0
Views: 2056
Reputation: 6347
As mentioned by @Khashayar, the problem in your code is that string:to_integer/1
returns a pair (a tuple with two elements) and the integer is the first element.
However, you should not use this function. A string in Erlang is just a list of integers, and what you meant to use is list_to_integer/1
. This is the common way to convert a string to an integer.
If you used list_to_integer/1
, you would have avoided the bug in @Khashayar's code where the second pair element is matched with anything. Indeed, you can enter the following:
Calculate the cost of flooring based on width, height, and cost per square foot.
Width in feet: 1.9
Height in feet: 1.9
Cost in dollars per square foot: $ 4.9
4
While 1.9*1.9*4.9
actually equals 17.689
.
Unfortunately, there is no list_to_number/1
function which would return either an integer or a float. The most common way to handle this is to perform a try/catch with list_to_float/1
and fallback to list_to_integer/1
. Alternatively, you could use io_lib:fread/2
or string:to_float/1
which do not raise exceptions (still, as mentioned above, using string:to_float/1
is judged a bad practice).
Upvotes: 2
Reputation: 2034
the problem you have is with string:to_integer, it returns 2 values! you should use them like this.
start() ->
io:format("Calculate the cost of flooring based on width, height, and cost per square foot.\n"),
{W,_} = string:to_integer(io:get_line("Width in feet: ")),
{H,_} = string:to_integer(io:get_line("Height in feet: ")),
{C,_} = string:to_integer(io:get_line("Cost in dollars per square foot: $ ")),
Cost = (W * H) * C,
io:fwrite("~p~n",[Cost]).
The second value is the rest of the string by the way,
to_integer(String) -> {Int, Rest} | {error, Reason}
good luck
Upvotes: 1