4

I have a school assignment to make a basic calculator. I'm almost done but I can't understand why the program says error (felinmatning in Swedish) when the user puts a number containing a dot (example 3.2) when the number 3,2 works.

To clarify, I want the calculator to accept 3.2 and 3,2.

My code (sorry for swedish comments):

namespace ConsoleApp1
{
    class Program
    {
        // En list där nummrena förvaras

        private static int runda = 2;

        static void Main(string[] args)
        {

            // En list där nummrena förvaras
            List<double> Numbers = new List<double>();

            string Method = "";

            // Main loop, kör miniränkaren om och om igen
            while (true)
            {

            loop:
                try
                {
                    // Ta user input på först nummret, lägger till i "Numbers" listan
                    Numbers.Add(ConvStr(TakeUserInput("First Number:")));
                }
                catch
                {
                    Console.Clear();
                    Console.WriteLine("Felinmatning");
                    Console.ReadLine();
                    goto loop;
                }
                Console.Clear();

            looop:
                try
                {
                    // Tar user input på andra talet och lägger till i listan
                    Numbers.Add(ConvStr(TakeUserInput("Second Number:")));
                }
                catch
                {
                    Console.Clear();
                    Console.WriteLine("Felinmatning");
                    Console.ReadLine();
                    goto looop;
                }
                Console.Clear();

                while(!CheckMethod(Method))
                {
                    // Ta user input
                    Method = TakeUserInput("Välj Räknesätt:");

                    Console.Clear();
                    Console.WriteLine("Felinmatning");
                }
                Console.Clear();


                // Calculatar och skriver ut skiten

                Console.WriteLine("Resultat:");
                Console.WriteLine(Calc(Numbers, Method));
                Console.WriteLine("Tryck Enter för att räkna igen");
                Console.ReadLine();
                // Cleara listan av nummer, förbered för nya.
                Numbers.Clear();
            }


        }

        private static string TakeUserInput(string DisplayText)
        {
            Console.Write(DisplayText);
            return Console.ReadLine();
        }

        private static bool CheckMethod(string method)
        {
            switch(method)
            {
                case "+":
                    break;
                case "-":
                    break;
                case "*":
                    break;
                case "/":
                    break;
                default:
                    return false;
            }

            return true;
        }

        private static double Calc(List<double> input, string method)
        {
            double Answer = 0;

            switch (method)
            {
                case "+":
                    Answer = input[0] + input[1];
                    break;
                case "-":
                    Answer = input[0] - input[1];
                    break;
                case "*":
                    Answer = input[0] * input[1];
                    break;
                case "/":
                    Answer = input[0] / input[1];
                    break;
            }


            return Answer;
        }

        private static double ConvStr(string input)
        {

            return Convert.ToDouble(input);
        }
    }
}
robsiemb
  • 6,157
  • 7
  • 32
  • 46
Spree
  • 39
  • 1
  • 5
    Please, never use the `goto` command, it's horrid! – DavidG Nov 14 '19 at 15:23
  • 5
    The Convert.ToDouble method is sensitive to the culture-setting of the environment it runs in. For sweden,it only expects a decimal colon(',') and not a decimal point. before converting you could always replace all occurrences of '.' in the strings to ','... – Johan Donne Nov 14 '19 at 15:25
  • 1
    Look into `System.Globalization.NumberStyles.AllowDecimalPoint` and https://stackoverflow.com/q/2583362/1462295 – BurnsBA Nov 14 '19 at 15:27
  • `I want the calculator to accept 3.2 and 3,2` - in many locales that would be different numbers. `1.000` is 1000 in en-us and 1 in fr-fr. Your calculator would need to read minds to interpret the input correctly. If you don't care about that, then Possible duplicate of [Parse strings to double with comma and point](https://stackoverflow.com/q/11560465/11683) – GSerg Nov 14 '19 at 15:27
  • 1
    Alternatively, update `ConvStr` with something like `input = input.Replace(".", ",")` – BurnsBA Nov 14 '19 at 15:29
  • As an aside - replacing characters for the sole purpose of making ToDouble with current culture work seems as an a bit of an overkill to me; use invariant culture instead. And yes - never use the `goto` operator at least not before you fully realize what issues it causes and how exactly it works. – Fabjan Nov 14 '19 at 15:45
  • @GSerg is spot on. You might ask an initial question like "Which do you prefer? 1,000.00 or 1.000,00" and then parse that into a culture setting. But without specifying one or the other, there's just too much ambiguity. – Jesse Williams Nov 14 '19 at 15:53

3 Answers3

1

If you really want to accept both ',' and '.' for your decimal point and you don't want to bother with CultureInfo, use:

 Numbers.Add(ConvStr(TakeUserInput("First Number:").Replace('.',',')));

on a sidenote: as mentioned, the use of 'goto' is certainly bad practice. You could replace

loop:
            try
            {
                // Ta user input på först nummret, lägger till i "Numbers" listan
                Numbers.Add(ConvStr(TakeUserInput("First Number:")));
            }
            catch
            {
                Console.Clear();
                Console.WriteLine("Felinmatning");
                Console.ReadLine();
                goto loop;
            }

with:

bool correctNumber = false;
do
{
    try
    {
        // Ta user input på först nummret, lägger till i "Numbers" listan
        Numbers.Add(ConvStr(TakeUserInput("First Number:").Replace('.', ',')));
        correctNumber = true;
    }
    catch
    {
        Console.Clear();
        Console.WriteLine("Felinmatning");
        Console.ReadLine();                       
    }                   
 }
 while (!correctNumber);
Johan Donne
  • 3,104
  • 14
  • 21
  • It's good practice to then explicitly specify a culture (in the conversion) which accepts the comma as a decimal point; because otherwise your code is going to fail when deployed on a machine with a culture that uses a period as a decimal point _even when the user inputs a period as the decimal point_ (since it gets converted to a comma and then fails conversion). – Flater Nov 14 '19 at 15:34
  • Also keep in mind that you can't then use thousand separators in the same value (well, you can, but it requires more handling than you currently do). That being said, the core answer of string replacing the period to a comma (or vice versa) is correct, hence +1 – Flater Nov 14 '19 at 15:35
  • @Flater: I absolutely agree, but since this is a schoolassignment, I don't think the intention was to produce code using localization, suitable for deployment in an international context :). – Johan Donne Nov 14 '19 at 15:38
  • 1
    Fair enough for OP's case, but the posts on SO are also read by others who look for an answer to the same question. It is a relevant sidenote for posterity's sake. – Flater Nov 14 '19 at 15:38
  • @JohanDonne why not? Sounds like extra credit to me! :) – Jesse Williams Nov 14 '19 at 15:54
0

the thread culture-specific number separator value is determined by the culture. try to change the culture to the "sv-SE".

System.Threading.Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("sv-SE");

You can change only the decimal separator as well, take a look at How to change symbol for decimal point in double.ToString()?

  • This doesn't answer how to **both** accept the comma and the period as a valid decimal point. Whichever culture you pick (or even when you set your own custom culture info, as per the link), it'll only accept _one_ of the two possibilities. – Flater Nov 14 '19 at 15:37
  • my bad.... well in that case I would just parse the input value, in order to replace athe "." for "," ...or the thread number separator char. – ze.espogeira Nov 14 '19 at 15:41
0

I fixed it by editing this line from:

return Convert.ToDouble(input);

To:

return Convert.ToDouble(input = input.Replace(".", ","));

Might not be the best of fixes but hey it works. Thanks BurnsBA for the idea.

LarsTech
  • 80,625
  • 14
  • 153
  • 225
Spree
  • 39
  • 1
  • @LarsTech: My comment was written in response to the pre-edit version of this answer. You are correct that it no longer applies. – Flater Nov 14 '19 at 15:43