【问题标题】:Program exiting when using String.ToUpper(); on a string that has spaces in it使用 String.ToUpper() 时程序退出;在包含空格的字符串上
【发布时间】:2020-02-27 17:59:08
【问题描述】:

首先让我说我是 C# 新手。

我目前正在制作我的第一个命令行应用程序,它在当前状态下可以做两件事。其中一个是计算器,我需要更多的学习才能真正让它工作,另一个是字符串大写字母。

我有一个string nameCapInput = Console.Readline() 接受用户输入,然后对其进行分析以确保不允许使用数字:

using System;
using System.Linq;

namespace First_Console_Project
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("My first ever console application - 2020/2/26\n\n\n");
        programSel:
            Console.WriteLine("What do you want to do?\n");
            Console.WriteLine("1. Calculate Numbers \n2. Capitalize Letters/Strings");
            Console.WriteLine("Input your desired action:");
            var inputVar = Console.ReadLine();
            switch (inputVar)
            {
                case "1":
                    //Calculator code goes here
                    Console.WriteLine("Number 1 succeeded, opening calculator... Stand by");
                    Console.WriteLine("Calulator Loaded.");
                    Console.WriteLine("Doesn't work right now. Type \"exit\" to get back to the \"what do you want to do\" page.");
                    //Code goes here when I have learned the proper methods
                calcInput:
                    var calcInput = Console.ReadLine();
                    if (calcInput == "exit")
                    {
                        goto programSel;
                    } else
                    {
                        Console.WriteLine("Unknown command. Type \"exit\" to get back to the \"what do you want to do\" page.");
                        goto calcInput;
                    }
                case "2":
                    Console.WriteLine("Loading string capitalizer...");
                    Console.WriteLine("Type any string made of letters only without spaces, because if you use spaces, the program will exit. The output will make them all uppercase. Type \"exit\" to get back to the \"what do you want to do\" page.");
                inputCap:
                    string nameCapInput = Console.ReadLine();
                    bool containsInt = nameCapInput.Any(char.IsDigit);
                    bool isMadeOfLettersOnly = nameCapInput.All(char.IsLetter);
                    if (nameCapInput == "exit")
                    {
                        goto programSel;
                    }
                    else if (containsInt)
                    {
                        Console.WriteLine("You can't capitalize numbers. Use letters only. Try again.");
                        goto inputCap;
                    }
                    else if (isMadeOfLettersOnly)
                    {
                        string upper = nameCapInput.ToUpper();
                        Console.WriteLine($"The uppercase version of your entered text is: {upper}");
                        goto inputCap;
                    }
                    break;
                    }
            }
        }
}

现在,一切正常,它将我放入其中的所有内容都大写除了字符串,其中包含空格。当我输入一个带有空格的字符串时,程序会以代码 0 退出。我还不太擅长 C#,所以我真的不知道从这里往哪里走。任何帮助表示赞赏。

每次我在 C# 中学习新东西时,我都会尝试将其实施到我的项目中,这样我就可以真正学习如何实施它,以了解何时以及如何使用我所学的内容。这是一个例子。

编辑:添加了其余代码。 非常感谢大家。我在这里学到了两件事:

  1. goto 是个坏习惯
  2. 绝对需要开始学习调试我自己的代码。

【问题讨论】:

  • 首先,完全停止使用goto。这不是 1980 年代。
  • 使用goto是你需要马上改掉的习惯。
  • 当你有一个空间时 isMadeOfLettersOnly 将是假的。您没有显示完整的程序,所以我们不知道如果执行超出显示的末尾会发生什么。
  • 重复一遍,去掉goto
  • 哇,你们很多人都说goto 不好。那我应该用什么?

标签: c# command-line .net-core-3.1


【解决方案1】:

问题的症结在于您检查输入是否包含字母(而不是空格)。一个简单的解决方法是稍微更改您的 LINQ。

bool isMadeOfLettersOnly = nameCapInput.All(c => char.IsLetter(c) || char.IsWhiteSpace(c));

所以现在输入带有字母的空格将被认为是有效的。

此外,您使用goto 是一个非常糟糕的主意。一般来说,永远不应该有任何理由使用goto

要解决此问题,请使用 while 循环和方法:

public static void Main()
{
    bool exit = false;
    do {
        exit = ProcessInput();
    }
    while(!exit);
}

private static bool ProcessInput()
{
    string nameCapInput = Console.ReadLine();

    bool containsInt = nameCapInput.Any(char.IsDigit);
    bool isMadeOfLettersOnly = nameCapInput.All(c => char.IsLetter(c) || char.IsWhiteSpace(c));

    if (nameCapInput.Equals("exit", StringComparison.CurrentCultureIgnoreCase))
    {
        return true; //exiting so return true
    }
    else if (containsInt)
    {
        Console.WriteLine("You can't capitalize numbers. Use letters only. Try again.");
    }
    else if (isMadeOfLettersOnly)
    {
        string upper = nameCapInput.ToUpper();
        Console.WriteLine("The uppercase version of your entered text is: {0}", upper);
    }   
    return false; //no exit, so return false
}

这只是一个快速的重构,你可以做得更好。

小提琴here

【讨论】:

  • 谢谢。我唯一没有得到的是while(!exit);。我还没有看到将while 用作一种方法。这是做什么的?看起来它只有在 exit 不正确时才会做某事!exit
  • @TimmSkiller 那是一个do/while 循环,读进去。本质上意味着do 块将在检查条件(while())之前执行至少一次。所以在你的情况下,它会要求用户输入,如果输入是"exit",它将返回一个真值。由于我们将ProcessInput() 的返回值分配给变量exit,它将触发循环结束,因为该变量将不再为假。
  • 这是有道理的。再次感谢。
【解决方案2】:

查看文档:https://docs.microsoft.com/en-us/dotnet/api/system.char.isletter?view=netframework-4.8

根据IsLetter函数的文档,空格不包含在return true case中。

我建议您为此使用正则表达式或将您的最后一个案例更改为

else if (!containsInt)
{
    var upper = nameCapInput.ToUpper();
    Console.WriteLine($"The uppercase version of your entered text is: {upper}");
    goto inputCap;
}

同时查看 goto 的文档:https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/goto

goto 语句将程序控制直接传递给带标签的语句。

goto 的一个常见用途是将控制转移到特定的 switch-case 标签或 switch 语句中的默认标签。

goto 语句对于跳出深度嵌套的循环也很有用。

你不是这种情况,所以你不应该使用它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-05-24
    • 1970-01-01
    • 2017-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-01
    相关资源
    最近更新 更多