在 C# 中解析和循环用户是/否控制台输入

Jon*_*han 3 c#

我正在编写一个将在另一个代码中使用的方法,所以我首先单独编写它。

代码根据输入的第一个字符返回一个布尔值(是,是,y,是,否,...)。但是当输入不同于 Y 或 N 时,它开始起作用。在 eg3 中,它一直在循环中,直到 Console.Read 遇到 Y 或 N 或没有剩余字符。在最后一种情况下,它会再次要求输入。

我使用的是 Console.Read 错误还是我的代码中存在另一个错误?提前致谢

编辑:最终的解决方案是有效的吗?

例如1:

Yes or No?
YeahIthinkso   <--my input
True
Run Code Online (Sandbox Code Playgroud)

例2:

Yes or No?
Negative       <--my input
False
Run Code Online (Sandbox Code Playgroud)

例3:

Yes or No?
Idontknow      <--my input
You can only answer with Yes or No
Yes or No?
You can only answer with Yes or No
Yes or No?
You can only answer with Yes or No
Yes or No?
False
Run Code Online (Sandbox Code Playgroud)

编码:

static void Main(string[] args)
        {
            char YN = 'x';
            bool ans = false;

            while (YN == 'x')
            {
                Console.WriteLine("Yes or No?");
                YN = char.ToUpper(Convert.ToChar(Console.Read()));


                switch (YN)
                {
                    case 'Y':
                        ans = true;
                        break;

                    case 'N':
                        ans = false;
                        break;

                    default:
                        Console.WriteLine("You can only answer with Yes or No");
                        YN = 'x';
                        break;
                }
            }
            Console.WriteLine(ans);
Run Code Online (Sandbox Code Playgroud)

基于@StuartLC 答案的替代解决方案:

bool ans = true, loop = true;
do
{
    switch (Console.ReadLine().ToUpper().FirstOrDefault())
    {
        case 'Y':
            ans = true;
            loop = false;
            break;

        case 'N':
            ans = false;
            loop = false;
            break;

        default:
            Console.WriteLine("You can only answer with Yes or No");
            break;
    }
} while (loop==true);

Console.WriteLine(ans);
Run Code Online (Sandbox Code Playgroud)

Stu*_*tLC 5

根据@Lasse 的评论 - 如果用户输入多个字符,您将循环用户输入的字符串中的每个字符,从而为用户输入的每个字符打印一个新的输出行。相反,使用 ofReadLine会将输入解析为单个字符串,然后 Linq 扩展FirstOrDefault()将安全地获取char字符串中的第一个:

YN = char.ToUpper(Console.ReadLine().FirstOrDefault()); 
Run Code Online (Sandbox Code Playgroud)

顺便说while一句false,C#不是使用强制条件启动循环,而是支持do-while 循环语法,它更符合您的要求,即至少在循环中进行一次迭代,并在循环结束时进行检查:

do
{
    Console.WriteLine("Yes or No?");
    YN = char.ToUpper(Console.ReadLine().FirstOrDefault());

    switch (YN)
    {
        case 'Y':
            ans = true;
            break;

        case 'N':
            ans = false;
            break;

        default:
            Console.WriteLine("You can only answer with Yes or No");
            YN = 'x';
            break;
    }
}
while (YN == 'x');
Run Code Online (Sandbox Code Playgroud)

Re OP 的后续问题

我现在可以完全删除“YN”并(Console.ReadLine().FirstOrDefault().ToUpper())在开头和(ans == true || ans ==false)最后放置一个开关吗?

不完全 - 因为ans是一个布尔值,它只能有两个状态(真或假),并且您需要对至少 3 个状态(真、假和无效)进行建模。尽管您可以使用可为空的布尔值 ( bool?) 对 3 个状态(其中 null = 无效)进行建模,但我个人不喜欢使用它null来表示未知的事物,因为这总是导致NullReferenceException深渊,而 C#(尚未)选择对于“选项”类型/ Monad(如 Java 的Optional)。

如果您对 C#8 模式匹配和元组没问题,您可以通过拆分“输入有效”和“有效输入值是什么”的问题,使代码更加简洁和重构如下?. 您还可以将 switch 表达式重构为它自己的方法,以从解析逻辑中分离出“UI”的关注点,这始终是一个好主意。

static void Main(string[] args)
{
    bool ans;
    bool isValid;
    do
    {
        Console.WriteLine("Yes or No?");
        (ans, isValid) = ParseInput(Console.ReadLine());
        if (!isValid)
        {
            Console.WriteLine("You can only answer with Yes or No");
        }
    }
    while (!isValid);
    Console.WriteLine(ans);

    (bool ans, bool isValid) ParseInput(string input) => 
        char.ToUpper(input.FirstOrDefault()) switch
        {
            'Y' => (true, true),
            'N' => (false, true),
            _ => (default, false)
        };
}
Run Code Online (Sandbox Code Playgroud)