【问题标题】:alternative to global variable for running total用于运行总计的全局变量的替代方案
【发布时间】:2017-07-24 04:44:55
【问题描述】:

我是 C# 的新手,但是为了上课,我必须编写一个程序来保持食品销售的总和。

我们被教导要使用全局变量,但它不仅感觉不是最简单的方法,而且我读到的所有地方都说不要使用它们。

例如,如果不使用全局变量,我还没有找到一种方法来保持两种不同巧克力棒的成本。它可以得到 1 条的总成本 - 无论数量如何,但是当我添加另一个时,之前的任何选择都会从总成本中消失。

简而言之:我有什么工作,但我觉得我需要学习更好的做法。

这是我的代码示例(请注意,这里有多个方法我没有复制到其中):

class Program
{
    static double total = 0;

    static void Main(string[] args)
    {
        string choice = "y";

        while (choice == "y")
        {
            Console.WriteLine("Main Menu:\nChocolate\nSandwiches");

            int menu = int.Parse(Console.ReadLine());

            switch (menu)
            {
                case 1:
                    chocolate();
                    break;
                case 2:
                    sandwich();
                    break;
            }
        }
    }

    static void chocolate()
    {
        int menu = 0;

        //double cost = quant * price;
        Console.WriteLine("Chocolate bar menu:\nMars bar\nSnickers\nTwix\nMilky Bar\nTurkish Delight");

        int chocBar = int.Parse(Console.ReadLine());

        Console.Clear();
        Console.WriteLine("Quantity");

        double quant = double.Parse(Console.ReadLine());

        Console.Clear();

        if (chocBar == 1)
        {
            Console.Clear();

            double costMars = quant * 0.5;
            total = total + costMars;

            Console.WriteLine("current total: £" + total.ToString("0.00"));
            Console.WriteLine("Press 1 for main menu");
            menu = int.Parse(Console.ReadLine());
            if (menu == 1)
            {
                chocolate();
            }
            else
            {
            }
        }

        if (chocBar == 2)
        {
            double costSnick = quant * 0.8;
            total = total + costSnick;

            Console.WriteLine("current total: £" + total.ToString("0.00"));
            Console.WriteLine("Press 1 for main menu");
            menu = int.Parse(Console.ReadLine());
            if (menu == 1)
            {
                chocolate();
            }
            else
            {
            }
        }

        Console.ReadKey();

【问题讨论】:

    标签: c# global-variables cumulative-sum


    【解决方案1】:

    恭喜您选择了 C# 作为学习的编程语言。它确实是一门很棒的编程语言。

    你读的是正确的,全局变量有很多含义。这通常是最后的手段。由于您是初学者,我将推荐另一种简单的技术。我为您找到了一个很棒的链接,它将介绍按值和引用传递变量的概念。看看吧

    https://msdn.microsoft.com/en-us/library/0f66670z.aspx

    祝你好运。

    【讨论】:

    • 很难理解,但至少它是有道理的。谢谢。
    【解决方案2】:

    感谢您在教育早期就积极主动地学习良好的编码实践!我认为您的讲师可能会告诉您现在使用全局变量,以免一次用太多概念使您超载,但是是的,作为一般经验法则,您应该尝试在代码周围传递变量作为方法参数.原因是,如果您在一个包含数万行代码的大型应用程序中拥有一个全局变量,并且该全局变量以某种方式最终得到了一个不正确的值,那么找出其中的哪一部分可能是一场真正的噩梦代码将错误的值写入变量。

    【讨论】:

      【解决方案3】:

      在调用方法时,有多种方法可以让数据流入和流出方法。最糟糕的方法是使用“全局”变量。

      除此之外:C# 在技术上本身没有“全局”变量,因为该术语描述了可以从任何上下文完全访问的变量,无需限定。所有 C# 变量都必须限定为类型或方法。但是,同样的一般警告确实适用于这些类型的变量。在 C# 中,区分变量是否按照最佳实践声明的是用法,而不是声明本身。

      在您的代码中,最明显的解决方法是让每个方法返回要添加到总数中的值。

      此外,出于某种原因,您已将循环实现为递归调用。我不清楚您为什么这样做,但除非这是您课堂作业中的特定要求,否则我建议您不要这样做。在这种情况下,您不太可能遇到任何特定问题,但它非常不规则,使代码难以理解,并且至少在理论上给出了堆栈溢出的可能性(实际上,您不太可能找到用户耐心足以导致这种情况发生,但代码中并不能保证递归最终会终止)。

      我通常不愿重写家庭作业,但在这种情况下,我认为您已经提供了足够的代码,如果提供更多代码,建议会更清晰。你还有一些工作要做,要实现sandwich() 方法和其他糖果条,我只解决了眼前的问题,而不是代码中的其他缺陷。所以我不觉得我只是在为你做你的学业。 :)

      以下是我认为代码应该的大致思路:

      class Program
      {
      
          static void Main(string[] args)
          {
              double total = 0;
              string choice = "y";
      
              while (choice == "y")
              {
                  Console.WriteLine("Main Menu:\nChocolate\nSandwiches");
      
                  int menu = int.Parse(Console.ReadLine());
      
                  switch (menu)
                  {
                      case 1:
                          total += chocolate();
                          break;
                      case 2:
                          total += sandwich();
                          break;
                  }
      
                  Console.WriteLine("current total: £" + total.ToString("0.00"));
                  Console.WriteLine("Press 1 for main menu");
                  menu = int.Parse(Console.ReadLine());
              }
          }
      
          static double chocolate()
          {
              int menu = 0;
      
              Console.WriteLine("Chocolate bar menu:\nMars bar\nSnickers\nTwix\nMilky Bar\nTurkish Delight");
      
              int chocBar = int.Parse(Console.ReadLine());
      
              Console.Clear();
              Console.WriteLine("Quantity");
      
              double quant = double.Parse(Console.ReadLine());
      
              Console.Clear();
      
              double cost;
      
              switch (chocBar)
              {
              case 1: // Mars
                  cost = 0.5;
                  break;
              case 2: // Snickers
                  cost = 0.8;
                  break;
              default:
                  throw new Exception("Invalid user input");
              }
      
              Console.Clear();
      
              return quant * cost;
          }
      }
      

      注意事项:

      • 我不清楚 "Press 1 for main menu" 的提示意义何在。那时用户可以做什么除了返回到主菜单?无论您的意图是什么,无论用户选择了 "Chocolate" 还是 "Sandwiches" 选项,您似乎都会做同样的事情,所以我移动了那个提示到 main 方法。
      • 在处理货币时,decimal 类型是比double 更好的选择,因为人类不喜欢在double 类型中使用base-2 算术出现的舍入误差。使用 decimal 类型可确保以十进制形式输入的值仍然以十进制形式精确表示,从而消除了舍入误差的来源。
      • 我不清楚您是否真的打算让用户能够购买一小部分糖果。您解析输入的类型是double,这将允许用户购买,例如1.25 块糖果。如果那是你的意图,那很好。但如果不是,请考虑将用户输入的数量类型更改为int
      • 您的原始代码没有跳出顶级菜单的机制,即将choice 设置为"y" 以外的其他值。我根本没有做任何事情来解决这个问题。同样的问题在此处的代码中仍然存在。
      • “Turkish Delight” 可以描述各种各样的糖果,但我从未见过我会形容为巧克力棒的糖果。如果您要出售它们,您可能需要重新考虑顶级菜单项描述。 :)

      【讨论】:

      • 在英国的土耳其软糖是一个非常棒的酒吧:)。我运行了您的代码,它解决了除一个问题之外的所有问题;添加各种项目时,如何在每种方法中显示运行总计?假设我添加了一个酒吧,那就是 80 便士,然后是 1.90 英镑的三明治。我希望不断显示总数 - 不仅在我返回主菜单时。当我尝试调用“总”变量时,它说它“在当前上下文中不存在”。一旦我解决了这个问题 - 我们就可以开始了。至于返回主菜单- 已解决。代码远未提前完成。
      • @Matt:不幸的是,规范尚不清楚,您问题中的代码几乎没有说明。我的示例中的代码在输入单个项目后总是返回到主循环,因此总和总是显示在每个项目之后。但是用户必须为购买的每件商品指定类别和单个商品。如果要在chocolate()sandwich() 方法中添加循环,则需要将total 传递给每个方法,在其中使用它,然后从要分配回@ 的方法中返回它987654335@主循环中的局部变量。
      • @Matt:如果没有清晰、完整的规范,就无法确定您需要什么。事实上,在这样一个简单的家庭作业式问题中,只有 static 字段并在您想要的每种方法中使用它并不是那么糟糕。这与将所有逻辑封装在可实例化对象中并没有太大区别,使用非static 字段可以保持运行总计,在更复杂的场景中这将被认为是可以接受的。
      • 是的,这就是我要问的。如何将“总”变量传递给每个方法?我在这里学到了很多东西。目前,该应用程序可以按我的意愿运行,只是我希望始终显示运行总计。
      • @Matt: “如何将 'total' 变量传递给每个方法?” -- 抱歉,我不明白你的意思。你是说你真的不知道参数是如何工作的吗?如果是这样,我建议您阅读语言文档:msdn.microsoft.com/en-us/library/0f66670z.aspx。如果您需要其他类型的帮助,恐怕您需要更具体一些。
      猜你喜欢
      • 1970-01-01
      • 2021-09-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-13
      • 2018-01-07
      • 1970-01-01
      • 2023-03-30
      相关资源
      最近更新 更多