문제

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?

도움이 되었습니까?

해결책

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

다른 팁

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

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top