我试图在 C# 控制台中制作一个计算器

ı was trying to make a calculator in c# console

我希望用户将数学方程作为字符串输入,而不是将它们拆分为字符,然后将它们转换为双精度,以便我可以使用它们,但我无法将字符转换为双精度

public  void Cal()
        {
            Console.WriteLine("Enter the transaction without spaces");
            string transaction = Console.ReadLine();
            char[] characters = transaction.ToArray();

            for(int i = 0; i < characters.Length; i++)
            {
                Console.Write(characters[i] + " ");
                if (i % 2 == 1)
                {
                    Convert.ToDouble(characters[i]);
                }
            }
            
        }
static void Main(string[] args)
        {
            Calculate calc = new Calculate();
            bool quit = false;
            
            while (quit == false)
            {
                calc.Cal();
                Console.ReadLine();
                Console.WriteLine("to clear pres C to quit the app pres Q");
                Console.Write(" : ");
                string b = Console.ReadLine().ToUpper();
                if (b == "C")
                {
                    Console.Clear();
                }else 
                {

                    quit = true;
                    Console.ReadLine();

                }
            }
        }

如果你想要一个非常简单的数学计算器,你应该先通过 char[] 来识别运算符。然后,您可以通过将运算符之间或单个运算符外部的 char[] 段转换为数字类型,并将它们作为每个运算符的操作数传递,并显示结果来评估表达式。如果您支持括号括起来,情况会更复杂。 (见下文)

要在运算符之间转换 char[] 段,因为您使用的是 C#,您可以:

  • 使用您的字符串“transaction”并调用 .Substring(startidx, endidx) 将其限制在运算符之前或之间,然后调用 .Trim() 删除空格和 return你一个字符串。例如:“string expression = transaction.Substring(0, opidx-1).Trim()” 该字符串(数字)可以发送到 double.Parse() 函数到 return 你可以使用运算符和其他以这种方式解析和转换的值来评估双精度值。例如:“double val = double.Parse(expression)”.

  • 或者你可以调用一个函数来步进操作符范围内的每个字符索引,使用 char.IsNumber() 找到非空白范围的开始和结束,那么不妨使用事务字符串和带有这些索引的 .Substring 来输出包含要解析的数字的字符串,如上所示,使用 double.Parse()。否则,您可以将数字字符附加到字符串中。

如果您想要一个功能更强大的公式和表达式解析器,则需要更复杂地处理它。

我曾经写过一个 C# 代码解析器,包括一个完整的数学 expression/formula 解析器。解析潜在复杂的数学表达式是数学评估软件程序的重要步骤。括号会影响求值顺序。

基本上,除了识别注释和文字区域(特定于代码解析器)之外,我采取的步骤是:

  • 从您的表达式中创建一组左括号和匹配的右括号索引。递归函数是最有效的。调用一个 FindCloseParan 函数,给它一个开参数索引,如果它在一个闭参数之前找到一个开参数,它会再次调用 FindCloseParan,否则它可以 return 闭参数字符,允许你存储每个在数组中打开 paran 的匹配相同级别的 close paran。然后您可以稍后调用 GetCloseParan 函数以获取开放索引以检索其匹配级别关闭索引,而不必重复使用当时可能效率低下(重叠工作重复)的递归 FindCloseParan 函数,并且您可以使用匹配打开和关闭 paran 索引 运行 每个区域中的解析表达式函数。 (如果你想要一个没有括号支持的简单数学计算器,你可以省略这个)

  • 运行一个解析逻辑表达式的函数。它应该识别运算符(或 AND 或 OR)的下一个索引,并查看它是否在下一个开放参数之前。如果下一个运算符索引在一个开放参数之后,它应该在与开放参数相同的参数级别上搜索关闭参数之后的下一个运算符。如果它发现任何在parans之外,它应该调用parse logic expression函数来解析每个运算符每一侧的表达式。如果没有运算符,它可以解析块将其存储为表达式 class 类型。如果在同一个parans enclosure level有多个运算符,它可以将每个运算符类型的索引存储在一个运算符数组中,以及一个与运算符交错的表达式类型数组中。 (表达式、运算符、表达式、运算符、表达式等)

识别可能是运算符第一个字符的字符会导致检查可能的双字符运算符。来自我的代码:

CSharpTypeWalker.firstcharoperatorsarrray = new char[] { '+', '-', '~', '*', '/', '%', '^', '!', '& '、'|'、'<'、'>'、'='、'?' };

CSharpTypeWalker.alloperatorsarray = new string[] { "+", "-", "~", "*", "/", "%", "^", "!", "& ", "|", "<", ">", "<<", ">>", "&&", "||", "==", "!=", "<=", "= >", ">=", "=<", "?:", "+=", "-=", "++", "--" };