运行 总计的全局变量替代方案
alternative to global variable for running total
我是 C# 的新手,但为了 class,我必须编写一个程序来保持 运行 的食品销售总额。
我们被教导使用全局变量,但它不仅感觉不是最简单的方法,我读到的所有地方都说不要使用它们。
例如,在不使用全局变量的情况下,我还没有找到保持两种不同巧克力块成本的方法。它可以计算出 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# 作为要学习的编程语言。它确实是一种很棒的编程语言。
你读的是正确的,全局变量有很多含义。这通常是最后的手段。由于您是初学者,我将推荐另一种简单的技术。我为您找到了一个很棒的 link,它将介绍按值和引用传递变量的概念。看看
https://msdn.microsoft.com/en-us/library/0f66670z.aspx
祝你好运。
很高兴你在教育的早期就积极主动地学习良好的编码实践!我认为您的讲师可能会告诉您现在使用全局变量,以免一次让您负担太多概念,但是,是的,作为一般经验法则,您应该尝试将代码周围的变量作为方法参数传递.原因是因为如果你在一个有数万行代码的大型应用程序中有一个全局变量,而这个全局变量以某种方式以不正确的值结束,那么找出哪一部分是真正的噩梦代码将不正确的值写入变量。
有多种方法可以让数据在调用方法时流入和流出方法。最糟糕的方法是使用 "global" 变量。
旁白:从技术上讲,C# 本身没有 "global" 变量,因为该术语描述的是可以从任何上下文完全访问的变量,无需限定。所有 C# 变量的范围都必须限定为类型或方法。但是,同样的一般警告也适用于这些类型的变量。在 C# 中,区分变量是否按照最佳实践声明的是用法,而不是声明本身。
在您的代码中,最明显的方法是让每个方法 return 将值添加到总数中。
此外,出于某种原因,您将循环实现为递归调用。我不清楚你为什么这样做,但除非这是你课堂作业中的具体要求,否则我建议不要这样做。您不太可能 运行 解决此上下文中的任何特定问题,但它非常不规则,使代码难以理解,并且至少在理论上给出了堆栈溢出的可能性(实际上,您不太可能找到足够耐心的用户来导致这种情况发生,但代码中并没有实际保证递归最终会终止。
我通常对重写家庭作业犹豫不决,但在这种情况下,我认为您提供了足够的代码,如果提供更多代码,建议会更清楚。您还有一些工作要做,以实现 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" 的提示意义何在。用户在 除了 return 到主菜单时可以做什么?无论您的意图如何,无论用户选择的是 "Chocolate" 还是 "Sandwiches"[=,您似乎都会做同样的事情47=] 选项,所以我将该提示移到了主要方法中。
- 在处理货币时,
decimal
类型是比 double
更好的选择,因为人类不喜欢 [=13] 中 base-2 算法出现的舍入误差=] 类型。使用 decimal
类型可确保以十进制形式输入的值保持完全以十进制形式表示,从而消除舍入误差源。
- 我不清楚您是否真的想让用户能够购买一小部分糖果。您解析输入的类型是
double
,这将允许用户购买,例如1.25 块糖块。如果那是你想要的,那很好。但如果不是,请考虑将用户输入的数量类型更改为 int
.
- 您的原始代码没有跳出顶级菜单的机制,即将
choice
设置为 "y"
以外的其他内容。我根本没有采取任何措施来解决这个问题。同样的问题在此处的代码中仍然存在。
- "Turkish Delight" 可能描述了各种各样的糖果,但我从未见过我认为是巧克力棒的糖果。如果您要出售这些菜单项,您可能需要重新考虑顶级菜单项的描述。 :)
我是 C# 的新手,但为了 class,我必须编写一个程序来保持 运行 的食品销售总额。
我们被教导使用全局变量,但它不仅感觉不是最简单的方法,我读到的所有地方都说不要使用它们。
例如,在不使用全局变量的情况下,我还没有找到保持两种不同巧克力块成本的方法。它可以计算出 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# 作为要学习的编程语言。它确实是一种很棒的编程语言。
你读的是正确的,全局变量有很多含义。这通常是最后的手段。由于您是初学者,我将推荐另一种简单的技术。我为您找到了一个很棒的 link,它将介绍按值和引用传递变量的概念。看看
https://msdn.microsoft.com/en-us/library/0f66670z.aspx
祝你好运。
很高兴你在教育的早期就积极主动地学习良好的编码实践!我认为您的讲师可能会告诉您现在使用全局变量,以免一次让您负担太多概念,但是,是的,作为一般经验法则,您应该尝试将代码周围的变量作为方法参数传递.原因是因为如果你在一个有数万行代码的大型应用程序中有一个全局变量,而这个全局变量以某种方式以不正确的值结束,那么找出哪一部分是真正的噩梦代码将不正确的值写入变量。
有多种方法可以让数据在调用方法时流入和流出方法。最糟糕的方法是使用 "global" 变量。
旁白:从技术上讲,C# 本身没有 "global" 变量,因为该术语描述的是可以从任何上下文完全访问的变量,无需限定。所有 C# 变量的范围都必须限定为类型或方法。但是,同样的一般警告也适用于这些类型的变量。在 C# 中,区分变量是否按照最佳实践声明的是用法,而不是声明本身。
在您的代码中,最明显的方法是让每个方法 return 将值添加到总数中。
此外,出于某种原因,您将循环实现为递归调用。我不清楚你为什么这样做,但除非这是你课堂作业中的具体要求,否则我建议不要这样做。您不太可能 运行 解决此上下文中的任何特定问题,但它非常不规则,使代码难以理解,并且至少在理论上给出了堆栈溢出的可能性(实际上,您不太可能找到足够耐心的用户来导致这种情况发生,但代码中并没有实际保证递归最终会终止。
我通常对重写家庭作业犹豫不决,但在这种情况下,我认为您提供了足够的代码,如果提供更多代码,建议会更清楚。您还有一些工作要做,以实现 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" 的提示意义何在。用户在 除了 return 到主菜单时可以做什么?无论您的意图如何,无论用户选择的是 "Chocolate" 还是 "Sandwiches"[=,您似乎都会做同样的事情47=] 选项,所以我将该提示移到了主要方法中。
- 在处理货币时,
decimal
类型是比double
更好的选择,因为人类不喜欢 [=13] 中 base-2 算法出现的舍入误差=] 类型。使用decimal
类型可确保以十进制形式输入的值保持完全以十进制形式表示,从而消除舍入误差源。 - 我不清楚您是否真的想让用户能够购买一小部分糖果。您解析输入的类型是
double
,这将允许用户购买,例如1.25 块糖块。如果那是你想要的,那很好。但如果不是,请考虑将用户输入的数量类型更改为int
. - 您的原始代码没有跳出顶级菜单的机制,即将
choice
设置为"y"
以外的其他内容。我根本没有采取任何措施来解决这个问题。同样的问题在此处的代码中仍然存在。 - "Turkish Delight" 可能描述了各种各样的糖果,但我从未见过我认为是巧克力棒的糖果。如果您要出售这些菜单项,您可能需要重新考虑顶级菜单项的描述。 :)