2013-01-15 39 views
3

嗨,你们在执行循环中的Y/N或y/n时会遇到一些麻烦。我设计的方式是用户可以使用Y和N的大写字母和小写字母作为循环中的答案。顺便说一下,这里是我的代码,但似乎无法使其工作:Y/N或y/n在循环中

do 
     { 
      Console.WriteLine("\nSelect additional topping/s\n"); 

      Console.WriteLine("1 - Extra meat: 200"); 
      Console.WriteLine("2 - Extra cheese: 100"); 
      Console.WriteLine("3 - Extra veggies: 80\n"); 

      int selectedTopping = Convert.ToInt32(Console.ReadLine()); 

      switch (selectedTopping) 
      { 
       case 1: 
        pizza = new MeatToppings(pizza); 
        break; 

       case 2: 
        pizza = new CheeseToppings(pizza); 
        break; 

       case 3: 
        pizza = new VeggieToppings(pizza); 
        break; 

       default: 
        break; 
      } 

      Console.WriteLine("\nAdd more toppings? Y/N"); 


     } 

     while ((Console.ReadLine() == "Y") || (Console.ReadLine() == "y")); 
+2

应该不是你的'Pizza'类有一个'addToppings()'方法或浇头的可公开访问的列表?也许我今天没有足够的咖啡,但是你的代码对我来说似乎没有意义。 – dreamlax

+0

它不起作用? – DWright

+2

请记住,每次调用Console.ReadLine()时,程序都会等待用户写入内容并按Enter键。你有两次,所以为了继续,用户必须先输入Y并按下回车键,然后输入y并按下回车键。提拉克的答案提供了一个简单的方法来做到这一点(你也可以投到更低的水平)。 – MasterMastic

回答

6
while ((Console.ReadLine() == "Y") || (Console.ReadLine() == "y")); 

这是要读2条不同的线路,因为你打电话ReadLine()两次。您需要调用一次并保存值。

+0

这确实是O.P.代码的一个关键问题,但是根据这些方面,Tilak的回答是一个可靠的解决方法。也就是说,将用户输入保存到变量中几乎总是首选的方式。 – Devin

+1

@Devin事实上,蒂拉克的方式很好。我的个人风格是尽量避免这种事情,所以将输入保存在变量中对我来说更具可读性,并使代码几乎可以自行记录。 –

+0

同意,良好的代码应该是自我记录(或至少我订阅了这一理念)。 – Devin

6

您可以使用ToUpper

while ((Console.ReadLine().ToUpper() == "Y")); 
+5

使用ToUpper/ToLower的字符串比较应该不鼓励。 [土耳其语问题和为什么你应该关心](http://haacked.com/archive/2012/07/05/turkish-i-problem-and-why-you-should-care.aspx) – Habib

+2

是的一般,但它不适用于这个问题。 'Y'没有问题。这个问题带有字符'i'。另外一个工具(FxCop或StyleCop)抱怨使用'ToLowerInvariant'来支持'ToUpperInvariant' – Tilak

6

尝试使用String.EqualsStringComparison

String.Equals(Console.ReadLine(), "y", StringComparison.CurrentCultureIgnoreCase); 

从MSDN:

CurrentCultureIgnoreCase:使用文化敏感的排序规则比较字符串,当前的文化,并忽略被比较的字符串的情况。

OrdinalIgnoreCase:使用序号排序规则并忽略字符串的情况下,比较字符串进行比较。

5

要检查Yy忽略的情况下,你应该使用string.Equals(string,StringComparison)超载。

while (Console.ReadLine().Equals("Y", StringComparison.InvariantCultureIgnoreCase)); 

请参阅The Turkish İ Problem and Why You Should Care使用ToUpperToLower与忽略大小写字符串比较之前。

您当前的代码正在从控制台读取两行代码,这就是为什么您的代码保持第二个值的原因。

+0

这对于检查一个甚至不受土耳其语框架影响的单个字符来说是矫枉过正的。了解土耳其套管等事情很重要,但知道其相关时机同样重要。而这不是。 – dreamlax

+0

@dreamlax,它是如何过度杀伤?使用ToLower/ToUpper会创建一个新的字符串,我相信这是一个矫枉过正的问题。是的,土耳其语的套餐在这里不是问题,但是对于忽略大小写的字符串比较,'string.Equals'是一个好得多的方法 – Habib

+1

这太过分了,因为它解决了一个不存在的问题,您已经过度地设计了需求。如果创建一个新的单字符字符串是应用程序性能的瓶颈,那么我想你有一个问题。 – dreamlax

1

正如Austin刚刚指出的,您在while循环语句中使用了两次ReadLine。

有一点值得一提的是试图遵循模块化的规则,这将有助于加快实施和调试我们的代码。

自从我做了任何C#编程,所以sudo编码这种Java风格已经有一段时间了。

由于它是命令行编程,您可能必须多次验证用户输入。我要做的一件事是让工具类包含常见的用户输入任务。

public class TerminalUtil { 
    private TerminalUtil() {} 

    public static boolean isYes(String msg){ return (msg.ToUpper() == "Y" || msg.ToUpper() == "YES"); } 
    public static boolean isNo(String msg){ return (msg.ToUpper() == "N" || msg.ToUpper() == "NO"); } 
    // You also might want basic conditionals to check if string is numeric or contains letters. 

    // I like using recursion for command line utilities so having a method that can re-print messages is handy 
    public static void display(String[] messages){ 
     for(String msg : messages){ 
      Console.WriteLine(msg); 
     } 
    } 

    public static boolean enterYesOrNo(String[] messages, String[] errorMessages){ 
     display(messages) 
     String input = Console.ReadLine(); 
     if(isYes(input)){ 
      return true; 
     } else if(isNo(input)){ 
      return false; 
     } else { 
      display(errorMessages); // Maybe something like, you didn't enter a yes or no value. 
      enterYesOrNo(messages, errorMessages); // Recursive loop to try again. 
     } 

    } 
} 

下面是代码来订购比萨饼可能是什么样子

public class OrderPizza{ 
    public static int selectToppings(){ 
     String[] message = new String[4]; 
     message[0] = ("\nSelect additional topping/s\n"); 
     message[1] = ("1 - Extra meat: 200"); 
     message[2] = ("2 - Extra cheese: 100"); 
     message[3] = ("3 - Extra veggies: 80\n"); 

     int option = TerminalUtils.entryNumeric(message, {"You entered an non-numeric character, try again"}); 
     if(option > 0 && option <= 3){ 
      return option; 
     } else { 
      Console.WriteLine("Number must be between 1 - 3, try again."); 
      return selectToppings(); 
     } 
    } 

    public static Pizza order(){ 
     Pizza pizza = new Pizza(); 

     while(true){ 
      int toppingCode = selectTopping(); 
      pizza.addTopping(toppingCode); 
      if(!TerminalUtil.enterYesOrNo({"\nAdd more toppings? Y/N"}, {"Please enter a 'Y'es or 'N'o"})){ 
       break; 
      } 
     } 
    } 
} 

这样做的主要好处是,while循环的业务逻辑已经减少,那么你可以在重用代码TerminalUtils。这并不意味着一个优雅的解决方案,我很懒,这是凌晨3点的IRL,但它应该足以让球滚动。

你应该重新考虑做的一件事是使用整数代码来表示浇头。使用枚举可能会使事情更容易实现。

我还注意到,您添加了三种不同类型的比萨,我假设三个不同的对象。

由于您正在循环添加配料到披萨,因此需要制作一个抽象类的披萨。通过这种方式,您可以扩展通用的预制比萨饼,如意大利辣香肠或奶酪,如果您想要客户定制他们的订单,则可以使用抽象比萨类。

0

我没有发现比更好的办法:

while (str!="N") 
{ 
    str = Console.ReadLine(); 
    str = str.ToUpper(); 
    if (str == "Y"); 
     break; 
};